Worker uncaught exception handling: Wrapped the fetch handler's handleWebhook call in a top-level try/catch so any unhandled exception returns a 500 response instead of crashing the Worker with a Cloudflare 1101 error. GitHub retries on 500, so no webhook deliveries are permanently lost.
Missing secret guards: Added explicit configuration guards for GITHUB_PRIVATE_KEY (in importPrivateKey) and PAGES_BUILD_HOOK_URL (in maybeTriggerBuild), throwing descriptive errors when either secret is not set rather than a cryptic TypeError.
GitHub App webhook signature verification: Guarded verifySignature against an undefined or empty GITHUB_WEBHOOK_SECRET, which previously caused crypto.subtle.importKey to throw a DataError (empty HMAC key material) and return a 500 instead of processing the webhook. The worker now throws a descriptive error that is caught and logged clearly. Also added a missing draft release check so draft releases are ignored alongside prereleases.
Local summary generation: Added scripts/summarize-local.ts and npm run summarize:local to generate release, weekly, and monthly summaries using a local Ollama model instead of Cloudflare Workers AI. Supports the same --year/--month/--week/--release selectors and --existing/--only modes as the cloud seeding script. An optional --upload flag pushes generated summaries directly to Cloudflare KV. OLLAMA_HOST and OLLAMA_DEFAULT_MODEL env vars configure the Ollama endpoint and default model.
Changelog stats: Added a Stats page with all-time repository and release totals, monthly release activity, and per-repository release counts.
Seeded previews: Added a preview:seed script to seed live KV data, build the site, and start the local preview server in one command.
Selective summary seeding: Added --only flag to npm run data:seed-summaries to control which summary types are regenerated. Accepts a comma-separated list of releases, weekly, and monthly — e.g. --month 2026-04 --only monthly regenerates only the monthly summary without touching release or weekly summaries.
Repository exclusion config: Added src/data/excluded-repos.json to exclude repositories from all changelog views. Entries are full repo names (owner/name). airfleet/airfleet-elements-test is excluded by default. Filtering is applied centrally in the data layer across all pages.
Changed
Changelog page polish: Refined release-card disclosure controls, simplified the project filter, tightened weekly/monthly summary layouts, added month summaries to archive cards, aligned weekly/monthly archive labels and cards, and added previous/next navigation to archive detail pages.
Layout and archive polish: Made the site brand in the header link back to the homepage, refreshed the footer copy to use the product name, surfaced the all-time release count, and aligned archive week pages around the YYYY-Www label plus a clearer week range.
Weekly and monthly summaries: Added a Monthly page, promoted summary-aware weekly cards, introduced separate monthly and summary KV paths, and wired the Worker plus a manual backfill workflow to generate Cloudflare-native release/weekly/monthly summaries for closed periods.
Summary backfill controls and prompts: Expanded the manual summary seeding workflow and CLI to target a full year, one month, one week, or one release; added explicit refresh/skip/overwrite behavior plus model overrides; switched the shared default model to @cf/zai-org/glm-4.7-flash; and upgraded monthly summaries to use a more narrative grouped prompt.
Summary presentation: Tightened release, weekly, and monthly summary prompts to avoid redundant project/version/count phrasing and generic openings; stopped generating unused expanded release summaries; promoted compact summaries on week/month cards; and aligned weekly/monthly landing pages with the archive detail layouts.
Monthly summary prompts: Upgraded monthly compact summaries to avoid opening with the month name, year, or any time-period reference — the summary must start with the work itself. Upgraded monthly expanded summaries to produce a richer structured narrative with 2–4 ##-headed sections by capability theme, starting with a one-sentence overview. Prompt version bumped to monthly-v6 with increased token budget.
Release card repo label: The repository label on release cards is now a link to the repository's release history page (/repo/{owner}/{name}).
Slack digest automation: Added weekly and monthly GitHub Actions workflows plus CLI helpers that post stored summaries to Slack through a Slack app bot, with manual period overrides for reruns.
Docs and workflow guidance: Updated README.md and AGENTS.md for the summaries workflow, release checklist, and changelog expectations.
Fixed
Homepage load-more page count: Capped getRequiredPageCount() by the total matching release count so filtering to a repo with fewer releases than the visible limit no longer requests non-existent pages and triggers 404 errors.
Monthly week overlap filter: Normalized both sides of the week/month overlap comparison to YYYY-MM-DD so full ISO timestamps stored in monthly index items no longer cause boundary weeks to be incorrectly excluded.
Markdown protocol-relative URL sanitization: sanitizeUrl now explicitly rejects protocol-relative URLs (//example.com) instead of normalizing them to http: and passing the allowlist check.
Weekly Slack digest formatting: Applied the same markdown-to-mrkdwn conversion used by the monthly digest so weekly summaries render bold text, headings, and links correctly in Slack instead of showing raw markdown syntax.
KV data download safety: downloadKvData now only deletes public/data after confirming the KV namespace contains keys, preventing an empty build when credentials point at a wrong or temporarily empty namespace.
block-background-image: Add a Background Image block for cover-style section and container backgrounds, with editor image selection and lazy or eager loading.
block-background-image: Allow Background Image blocks inside Media Background containers for responsive art direction alongside video and Lottie layers.
Module Manager: require enabled child modules to be disabled before parent dependencies, confirm before disabling critical modules, and link enabled modules directly to available settings tabs and sections.
Module Manager: remove the module card "More" details popover from the badge row.
Module taxonomy: clarify tier semantics, add the premium tier value to the UI, and update current module metadata for forms, providers, components menu, and Allow Lottie.
Admin pages: document that module settings should generally live in Airfleet → Settings rather than standalone submenus.
Internal: move SVG sanitization into the shared Core\Svg\SvgSanitizer utility for use outside the Allow SVG module.
Fixed
Dev Containers: Allow the WordPress container to open from Git worktrees by using dynamic workspace paths and preserving worktree Git metadata paths inside the container.
Dev Containers: Enable visible and logged PHP errors in the WordPress container with explicit WordPress debug constants and PHP ini settings.
SVG sanitizer: Reject non-fragment url(...) references while avoiding false positives for plain values that merely contain protocol-like substrings.
Adds page-spec v2 vocabulary and a section archetype catalog with auto-discovery, admin endpoints and SPA pages, upgrades the comparison spec, and fixes entrypoint detection for paths with spaces.
Page-spec v2 vocabulary on pageTypeSpecSchema: audience, voice, expectedCta, requiredProofTypes, formFriction, defaultSections, forbidsArchetypes, validationRubric, guidance. All optional or defaulted — v1-shape literals still parse.
Section archetype catalog with auto-discovery: Hero, ValueProps, SocialProof, FeatureDeepDive, Pricing, Faq, FinalCta, plus ComparisonTable, AwardBadgeRow, IconFeatureGrid, InlineLeadForm, IntegrationGrid synthesized from the swipe-file corpus. Filesystem-driven — drop a .ts under archetypes/ and restart.
Best-practice page specs (product, content, service, demo) authored from 89 per-page analyses across 5 categories of a 110-page landing-page swipe file.
Page-spec auto-discovery: drop a spec file under page-specs/specs/ and it's picked up at boot via readdirSync + dynamic import + top-level await.
SpecRepository interface + InMemorySpecRepository as migration insurance for an eventual code → DB swap.
Admin browse endpoints under /admin/api/{page-specs,section-archetypes,block-specs} with cross-reference counts and rendered-prompt previews (Zone 2 for blocks, Zone 3 for specs), gated by requireSession.
Admin SPA catalog pages (Page Specs / Section Archetypes / Block Specs + detail views) with cross-linking, debounced search, and source filters. Sidebar nav extended.
New CSS patterns for detail pages: .card, .kv, .breadcrumb, .prose-block, .block-id-list, .chip, .badge-custom/.badge-native, .empty-state, .id-cell, .num-cell.
Page-type research pipeline tooling under page-type-data/: extract-from-coda.js (DevTools snippet), fetch-images.mjs (parallel image fetcher with native-resolution URL cleanup), analyze-screenshot.md (per-screenshot analysis prompt), synthesize-best-practice.md (per-category synthesis prompt), README documenting the 5-step pipeline.
Prompt-rendering snapshot tests (prompts.snapshot.test.ts) covering all shipped specs.
pnpm dump-prompt CLI: dump the full assembled system prompt for a (spec, stage) pair to stdout, with optional fixture file for Zone 4. Useful for offline iteration without burning API credits.
Inline archetype definitions in Zone 3 of the system prompt for LLM grounding.
Universal page rules + canonical propose_plan example baked into BASE_PROMPT.
purchase and start-trialCtaAction enum values.
Changed
Existing comparison spec upgraded based on best-practice synthesis (13-sample corpus): ComparisonTable added as required default section, Faq moved from required to forbidsArchetypes, Pricing added to forbidsArchetypes, SocialProof split into trust-logo-belt + switcher-testimonial slots, FeatureDeepDive ×1 required + 1 optional added, requiredProofTypes expanded with logos and metric, validation rubric expanded from 5 to 9 testable assertions.
book-demo, comparison, resources specs re-authored with full v2 vocabulary content.
data-index.js renamed to data-index.json to reflect its actual content (pure JSON) and avoid ESLint parsing it as code.
Fixed
Entrypoint detection (isEntrypoint) now uses pathToFileURL so the boot block runs correctly on paths containing spaces (e.g. /Users/.../Local Sites/...); previously the check silently failed off-Railway.
pnpm dump-prompt script imports updated for the post-restructure monorepo layout (../plugins/page-ai/src/... for runtime modules, @airfleet/nexus-ai-server-wp-contracts for types).
Build: Root pnpm run build now runs build:packages before apps/server, compiling platform-sdk, platform, wp-contracts, and page-ai to dist/ and pointing each package exports default entry at ./dist/index.js. Production previously only emitted apps/server/dist; Node still resolved workspace imports to TypeScript sources and failed at runtime (ERR_MODULE_NOT_FOUND for *.js siblings), breaking Railway health checks after the pnpm workspace migration.
Deploy:predb:migrate invokes build:packages so the migration script always resolves @airfleet/nexus-ai-server-platform from emitted dist output; pnpm test does the same so Vitest matches production resolution.
Fixed BlockPreviewDebounce crashing jQuery $.ajax GET requests in wp-admin (including author search and Quick Edit author dropdowns) when the XHR body is null or non-string. The XHR override now coerces non-string bodies before checking whether the request targets an ACF block fetch.
Add the ai-page-generator module (AI Page Generator): a wp-admin AI Page Builder screen with session management and a full-screen editor shell, REST and SSE proxying to the external AI server so the API key never reaches the browser, Airfleet → Settings → Content fields for api_key and optional server_url, and the airfleet/nexus/ai_page_generator/server_url filter for overriding the AI service origin.
Removed
Remove the ai-block-generator module (AI Block Generator): block editor toolbar integration, REST proxy to the external layout service, Airfleet Settings section, related options, and the airfleet/nexus/ai_block_generator/server_url filter.
Internal: Update oh-my-opencode-slim.json to latest recommended models and config
Internal: Replace the parked gh-aw PR review workflows with standard GitHub Actions + Copilot CLI review workflows and refresh the PR review automation guidance
Internal: Add plan-pressure-test and implementation-guardrails skills to reinforce the existing planning and implementation workflow without adding competing commands
Tooling: Reorganize project scripts under scripts/docs/, scripts/docmd/, scripts/playground/, and scripts/webpack/.
Dev Containers: Move both containers to PHP 8.3, update the pinned OpenCode binary to 1.14.28, and let VS Code forward the WordPress service port while keeping WP_DEBUG and SCRIPT_DEBUG enabled.
CI: Add changed-file filters to the WordPress and block e2e test workflows so expensive checks run only for relevant source, dependency, tooling, test, or workflow changes.
CI: Update the docs workflow to actions/upload-pages-artifact@v5.
Add generated API references for Blocks, CPTs, and JavaScript events, plus generated release notes sourced from CHANGELOG.md.
Add documentation guidance for block pages, optional block contributor notes, JS event doc blocks, content type references, generated references, release notes, and hook images.
Add naming guidance for JavaScript events, transient keys, and settings groups/keys.
Add custom docs styling for inline code and release notes layout.
Changed
Upgrade @docmd/core to 0.7.7.
Expand bun run docs:generate to orchestrate PHP API references, JavaScript event references, and release notes.
Rework docs navigation and API Reference labels/order, using Modules, Hooks, CPTs, Taxonomies when present, Blocks, and JS Events without the repeated "Reference" suffix.
Run docs deployment after the plugin release workflow so generated release notes build from the versioned release commit.
Rename the changelog/versioning guide to docs/getting-started/release-process.md.
Update generated references so hook and block headings omit project prefixes while preserving full slugs in metadata, block attributes/supports are collapsible, block rendering details are concise, JS events are grouped in cards, and empty taxonomy references are skipped.
Standardize form and modal DOM events on the afnx- naming convention.
Simplify block documentation pages so they focus on editor usage and link to generated references for attributes, supports, and metadata.
Removed
Remove old airfleet/nexus/form/* and airfleet/nexus/modal/* DOM event names in favor of afnx-form-* and afnx-modal-*.
Deploy: Railway startCommand aligned with the pnpm workspace so production runs apps/server via pnpm start (avoids broken health checks after the composition root moved).
CI: GitHub Actions fixes for pull-request / release validation paths.
Changed
Docs: Deployment and release workflow documentation updates.
Six button block style variations with button- slug prefix to avoid is-style-{slug} collisions across block types: button-primary-dark/-light, button-secondary-dark/-light, button-link-dark/-light
Shared button geometry on styles.elements.button so variations inherit common chrome
Color palette and gradients aligned with the Figma style guide
Overused Grotesk and Area Variable font family registrations (Inter fallback; font files pending license)
SCSS design tokens at src/scss/base/_root.scss (--afs-trs-sm, --afs-trs-timing-function)
SCSS mixins: hover, hover-capable, transition
Per-block stylesheet src/scss/blocks/core-button.scss for variation hover states
Changed
--wp--preset--color--primary now resolves to the new brand purple
Lint: at-rule-empty-line-before granted the same first-nested exception as rule-empty-line-before
Block style variations grouped into per-block subfolders: styles/buttons/, styles/headings/, styles/paragraphs/ (WP scans /styles recursively, so registration is unchanged)
Removed
--wp--preset--color--secondary and the secondary / subtle gradient slugs (no analog in the new palette)
styles/example.json and styles/example-button-large.json placeholder examples (the authored variations are the reference now)
support-button-icon: register an is-style-icon-only block style on core/button for circular, label-hidden icon buttons. The label stays in markup as the button's accessible name; outer/icon sizing exposed as --afnm-button-icon-only-size and --afnm-button-icon-only-icon-size for theme overrides
support-button-icon: add a play icon to the default registry