feat(nav): expose Skill and Contribute, add footer Source row#106
Merged
Conversation
The /contribute markdown landed in 5e7c94d (feat(content): add /contribute site page and CONTRIBUTING.md) but the route was never registered. `subPages` in src/build/build.mjs never iterated `content/contribute.md`, so neither `dist/contribute.html` nor `dist/contribute.md` was produced. The page silently 404'd on the live worker. Add the missing entry to `subPages` so both HTML and markdown twins build, and add `/contribute` to the sitemap's canonical-path list so it's discoverable by crawlers and the `/llms.txt` index.
…nces Two corrections in `content/contribute.md`. First, the `Add a tool to the registry` bullet was being mangled by the markdown auto-format hook. The link URL plus the bullet text exceeded 120 characters as a single line, so the hook (`textwrap.fill` with `break_long_words=False`) put the bullet marker `-` on its own line and indented the rest, producing an orphan dash. Switch to a reference-style link so the inline portion stays under 120 characters and the bullet renders as a single list item. Second, three `principles/AGENTS.md § Pressure-test protocol` references linked to the top of the upstream file rather than the named section. Add `#pressure-test-protocol` anchors so all three callers land at the section that holds both the protocol prose and the `draft → under-review → active → locked` status-flip rules. Verified against `agentnative-spec/principles/AGENTS.md:96` (`## Pressure-test protocol`).
The header nav gains two items in their natural reading order: `Skill` sits with the consumption-tier links (after `Check your CLI`) and `Contribute` sits last (governance/community tier). The `/skill` page has shipped since the skill-bundle endpoint landed; `/contribute` ships in the companion commit on this branch. Both routes are now discoverable from every page instead of requiring an out-of-band URL. The footer gains a Source-of-truth row between the AI-summary block and the meta line: a quiet GitHub icon kicker followed by `Source: spec · cli · site · skill`, each repo name linking to `github.com/brettdavies/agentnative*`. The icon is the Simple Icons GitHub mark at 1rem in `fg-muted`, with the same hover-lift treatment as the meta links. Reuses the inline-SVG `currentColor` pattern the AI-summary icons already use, so dark mode and theme switches work without additional CSS. `.site-nav` gains `flex-wrap: wrap` plus `white-space: nowrap` on the individual links. Without those, the eight-item nav was breaking inside a single link on narrow viewports (e.g. `Check your CLI` rendering as `Check` / `your` / `CLI` stacked). The bug was pre-existing under the six-item layout but only became visible once two more items pushed the row past common phone widths. Header reads clean (eight plain-text items, theme toggle on the right) on wide; nav wraps to two lines on narrow without breaking mid-link. Footer Source row reads as a kicker, not a primary call-out, so the existing meta line continues to carry the secondary metadata.
brettdavies
added a commit
that referenced
this pull request
May 21, 2026
…emap and prose-check fixes (#107) ## Summary Four-commit refactor branch covering one bug fix, one shared-tooling refactor, one doc update, and the headline SRP split of `src/build/build.mjs` (676 LOC to 267, with pipeline-stage modules numbered in execution order so the directory listing reads as the build narrative). ## Changelog ### Added - `/scorecard-schema` now appears in `dist/sitemap.xml`. The page rendered and was reachable by direct URL, but was missing from `src/build/06-sitemap.mjs`'s hardcoded paths so crawlers could not discover it. Flagged as the "near miss" in the convention doc landed in PR #106 (`docs/solutions/conventions/new-content-page-requires-three-registrations-2026-05-21.md`). ### Changed - `scripts/prose-check.sh` now sources the LanguageTool wrapper from `~/dotfiles/config/shell/languagetool.sh` rather than carrying its own baseline denylist + reachability probe inline. The site script contributes four site-local denylist rules (IN_PRINCIPAL, CONTRACT_CONTACT, TO_DO_HYPHEN, PLURAL_MODIFIER) on top of the baseline 10 in the helper. Drops the script from 281 to 195 lines and keeps universal-rule edits in one place across all four agentnative channel repos. - `src/build/build.mjs` split at the data/render boundary into four new per-stage emit modules. The orchestrator now reads as a 267-line sequential pipeline; each emit module owns one cohesive output surface. ### Fixed - The "Authoring PR bodies" snippet in `RELEASES.md` referenced the older bare `curl + jaq` LanguageTool invocation. Updated to call `lt_check /tmp/body.md` so the documentation matches the actual script after the prose-check refactor. ### Documentation - New pipeline-stage modules `02-homepage.mjs`, `03-subpages.mjs`, `04-scorecards-emit.mjs`, `05-llms-emit.mjs` each carry module-level docstrings explaining what they emit and where downstream consumers pull from. The `03-subpages.mjs` header includes the cross-reference to the three-registrations convention doc so future authors finding that module also find the convention. ## Type of Change - [x] `refactor`: Code refactoring (no functional changes) - [x] `fix`: Bug fix (non-breaking change which fixes an issue) - [x] `docs`: Documentation update - [ ] `BREAKING CHANGE`: Breaking API change (requires major version bump) ## Related Issues/Stories - Story: n/a - Issue: n/a - Architecture: `docs/solutions/best-practices/build-module-srp-dry-refactor-20260421.md` (the refactor pattern this SRP split applies). Reviewed during the `/ce-compound-refresh` pass that paired with this work; doc remained valid without edits. - Related PRs: builds on #106 (which landed the convention doc + the sibling registration gap) ## Testing - [x] Manual testing completed - [x] All tests passing **Test Summary:** - `bun test`: 736 pass, 0 fail. - `bun run lint`: 0 errors (biome + markdownlint). - `bun run build`: produces 370 `dist/` artifacts. - `bash scripts/prose-check.sh`: 0 blocking, 1296 warning (same totals as before the LT refactor, confirming the dotfiles helper produces equivalent coverage). - Byte-identical verification across the SRP split: `find dist/ -type f | sort | xargs sha256sum` produces the same digest set before and after the refactor and again after the numbering pass. The spec-version-gen banner in `src/worker/spec-version.gen.ts` updates to reference the renamed path; esbuild strips comments at bundle time so the worker bundle output is unchanged. - `dist/sitemap.xml` row count: 116 (was 115; the new row is `/scorecard-schema`). - `node scripts/generate-pack-readme.mjs --check`: passes. ## Files Modified **Modified:** - `RELEASES.md`: updated inline LanguageTool example snippet - `scripts/prose-check.sh`: extract LT plumbing to shared `~/dotfiles` helper (281 to 195 lines) - `src/build/build.mjs`: split per-stage emit logic out; now 267 lines (was 676), imports the seven numbered pipeline-stage modules in order - `src/build/06-sitemap.mjs`: add `/scorecard-schema` to canonical paths - `src/worker/spec-version.gen.ts`: regenerated banner reflects renamed source path - `tests/spec-version-gen.test.ts`: updated import path + marker assertion for the renamed source module **Created:** - `src/build/02-homepage.mjs`: homepage HTML + MD twin emit (section 6 of the pipeline) - `src/build/03-subpages.mjs`: content-driven HTML + MD twin loop (section 7) - `src/build/04-scorecards-emit.mjs`: leaderboard + per-tool scorecards + badges + coverage + skill surfaces (section 8) - `src/build/05-llms-emit.mjs`: llms.txt + llms-full.txt assembly (section 9) **Renamed:** - `src/build/spec-version-gen.mjs` to `src/build/00-spec-version-gen.mjs` - `src/build/assets.mjs` to `src/build/01-assets.mjs` - `src/build/sitemap.mjs` to `src/build/06-sitemap.mjs` **Deleted:** - None ## Key Features - Pipeline-stage modules now sort in execution order in `ls src/build/`. Shared helpers (badge, content, coverage, llms, registry-index, render, scorecards, scorecards-render, shell, skill, util) stay unnumbered because they do not represent a single stage. - `build.mjs`'s `build()` function reads as a thirteen-step orchestrator where each emit step is one call into a numbered module. ## Benefits - The four extracted modules each have one reason to change. A future change to scorecard rendering touches `04-scorecards-emit.mjs` only; a future change to homepage layout touches `02-homepage.mjs` only. - The numbering ordering aid is decorative but matches the inline section comments in `build.mjs`. A new contributor reading `src/build/` in the editor's file tree sees the same order as the orchestrator's awaits. - The prose-check + RELEASES doc updates close the gap between the script's implementation and its documentation, and put the rule denylist in one shared place across all four agentnative channel repos. ## Breaking Changes - [x] No breaking changes The `dist/` output is byte-identical to the pre-refactor state. The renamed source files have no public consumers outside the repo. The `tests/spec-version-gen.test.ts` import path updates in lockstep with the rename. ## Deployment Notes - [x] No special deployment steps required A normal `dev` to `staging` worker deploy ships the build. `paths-ignore` does not skip changes to `src/build/`. ## Screenshots/Recordings n/a (no rendered-output changes; `dist/` is byte-identical). ## Checklist - [x] Code follows project conventions and style guidelines - [x] Commit messages follow [Conventional Commits](https://www.conventionalcommits.org/) - [x] Self-review of code completed - [x] Tests added/updated and passing - [x] No new warnings or errors introduced - [x] Changes are backward compatible (or breaking changes documented) ## Additional Context The SRP split applies the pattern documented in `docs/solutions/best-practices/build-module-srp-dry-refactor-20260421.md`. The byte-identical safety net described there (`find dist/ -type f | sort | xargs sha256sum`) was used at every step. Out of scope for this PR: a build-time assertion that every `content/*.md` file has a corresponding entry in the `subPages` list. The convention doc that surfaced the `/scorecard-schema` gap recommends this follow-up; deferred to a future PR.
5 tasks
brettdavies
added a commit
that referenced
this pull request
May 25, 2026
## Summary First production cut of the live-scoring stack. Promotes every dev change since PR #91 (2026-05-15) and a lockstep sandbox image bump to anc-cli v0.4.0. The headline is `/api/score` on anc.dev. Users (and agents) can paste an install command or a GitHub URL into the homepage form, and the Worker resolves it through the registry-fast-path, R2 cache, or a live sandbox run inside a Cloudflare Durable Object + Container. Sandbox runs invoke `anc check` (v0.4.0, baked into the image at build time) against a fresh install of the user's tool and return a typed scorecard with the response triad (`spec_version`, `site_spec_version`, `anc_version`, `checker_url`). Shareable result URLs at `/live-score/<binary>` serve from R2 with a 7-day TTL. Ride-alongs: - Contributor surface: nav exposes Skill + Contribute, footer carries a Source row, an intake template lands for external contributions, and the README is rewritten to reflect the current dev surface. - SEO: JSON-LD `@graph` now emits an Organization + Person author on every page. - Build internals: `build.mjs` SRP-split into numbered pipeline stages; CI smoke for `/api/score` extracted into `scripts/smoke-api-score.sh`. - Reliability: handler now returns a typed 503 `sandbox_unavailable` instead of Cloudflare error 1101 when the `SCORE` DO binding is missing (mid-rollback safety; surfaced by the rehearsal). - Operational: `RELEASES.md` includes the cross-migration rollback rehearsal evidence row and a recipe correction (mandatory `wrangler containers delete <id>` step between v2-drop-sandbox and v3-restore-sandbox). Image lockstep: top-level `containers[0].image` and `env.staging.containers[0].image` both pinned at `:9aed5c3` (anc-cli v0.4.0, digest `sha256:dae72c56afe2f332e8745c0517f1ed5d21993470de663409dfc9b3973cdfe4c1`). The image cleared the staging deploy on dev push run `26384622721`; soak was skipped per the release-cut decision documented in the PR thread that produced #114. ## Changelog ### Added - Live scoring at `/api/score`: paste an install command or GitHub URL, get a typed scorecard back. Homepage form + shareable `/live-score/<binary>` result URLs (R2-backed, 7-day TTL). - Cloudflare Sandbox DO + Container running anc v0.4.0 against a fresh install of the user's tool inside a per-request ephemeral environment. - Cost guardrails: Workers Analytics Engine telemetry, per-session + per-IP rate limits, operator-flippable `scoring_disabled` kill switch in KV. - Contributor surface: Skill + Contribute nav entries, footer Source row pointing at the four `brettdavies/agentnative-*` repos, intake template at `.github/ISSUE_TEMPLATE/`, rewritten README. - Monitoring runbook at `docs/runbooks/live-scoring-analytics.md`. ### Changed - `wrangler.jsonc` `containers[0].image` (production pin) advances from `:30f61f1` to `:9aed5c3` lockstep with `env.staging.containers[0].image`. New image carries anc-cli v0.4.0 (was v0.3.1) plus the PR #100 Dockerfile pip-version-check suppression baked in (previously runtime-bridged). - JSON-LD on every page now emits a `@graph` with Organization + Person author (was bare `TechArticle`). - Build pipeline split into numbered SRP stages under `src/build/`; `build.mjs` becomes the orchestrator. - `staging` env block in `wrangler.jsonc` carries an explicit `routes: []` and `triggers.crons: []` override and the full live-scoring binding surface (Sandbox DO, Container, R2, SCORE_KV, Analytics Engine, two rate-limit namespace IDs). ### Fixed - `/api/score` no longer surfaces Cloudflare error 1101 when the `SCORE` DurableObject binding is missing (mid-rollback Worker state). Returns a typed 503 `sandbox_unavailable` with `spec_version` and `checker_url` so clients can render a useful error. ### Documentation - `RELEASES.md` cross-migration rollback rehearsal section now documents the mandatory `wrangler containers delete <id>` step between v2-drop-sandbox and v3-restore-sandbox (surfaced live during the 2026-05-24 rehearsal). - Rehearsal evidence row populated with every staging deploy ID, container app ID, and DO namespace ID from the v1 → v2-drop-sandbox → v3-restore-sandbox walk. ## Type of Change - [x] `feat`: New feature (non-breaking change which adds functionality) This release is multi-typed (feat headline plus several fix and docs ride-alongs) but `feat` headlines because live scoring is the durable new product surface anc.dev ships with this cut. ## Related Issues/Stories - Story: Closes the live-scoring v3 plan (U1-U10). Production has never run this stack; staging absorbed the full rehearsal (see `RELEASES.md` § Cross-migration rollback rehearsal evidence row dated 2026-05-24) and the lockstep image bump via PR #114. - Issue: n/a - Architecture: `docs/solutions/tooling-decisions/cloudflare-sandbox-python-3.12-base-2026-05-19.md` (dev-only) for the python:3.12 base + version-pin matrix the sandbox image follows. - Related PRs: Every dev-side PR that contributed: #82 (prose-check), #83 (P8 + PRODUCT.md), #93 (`/api/score` U5), #94 (DO stub fetch), #95 (Sandbox DO + two-phase egress U6), #96 (R2 cache + unified scorecard lookup U7), #97 (R2 lifecycle docs), #98 (U7 red-team tests), #99 (python:3.12 + sdist allowlist), #100 (homepage form + share URLs U8), #101 (U9 tests + CI smoke), #102 (extract smoke script), #103 (monitoring runbook), #104 (analytics + cost guardrails U10), #105 (contrib docs + prose pass), #106 (nav + footer source), #107 (build SRP split), #108 (README rewrite), #109 (matrix sync), #110 (docker/score mode injection), #111 (JSON-LD @graph), #112 (rehearsal evidence + recipe fix), #113 (env.SCORE handler guard), #114 (anc v0.4.0 image rebuild). ## Testing - [x] Unit tests added/updated - [x] Integration tests added/updated - [x] Manual testing completed - [x] All tests passing **Test Summary:** - `bun test`: 737 pass / 0 fail across 28 files on the release branch. - `bun x wrangler deploy --dry-run` against both environments: clean. Lists `agentnative-site-sandbox` at `:9aed5c3` (production) and `agentnative-site-staging-sandbox-staging` at `:9aed5c3` (staging). - Cross-migration rollback rehearsal executed live on staging 2026-05-24: v1 baseline confirmed, v2-drop-sandbox applied cleanly, container-app cleanup performed, v3-restore-sandbox applied cleanly, DO-invoking path confirmed running. Evidence in `RELEASES.md`. - Staging deploy on dev push `26384622721` (post PR #114 merge): green. Confirmed `:9aed5c3` deployed and `/api/score` responds with `anc_version: 0.4.0` (cold-start `xplr` request returned typed 504 `timeout` while container provisioned; warm cache hit immediately after returned full scorecard). - Pre-push gate (lint, build, test, wrangler dry-run x2, pack-README, banned-fonts, prose-check): pass. - Triple-diff verification per `RELEASES.md`: A=134 files clean, B=`wrangler.jsonc` only (the prod-pin bump), C=mirror of A, guarded-paths leak=clean. **Post-merge verification plan** (after the production deploy on this PR's merge): - Production deploy log shows `agentnative-site` at `:9aed5c3`. - `curl https://anc.dev/api/score -H 'Content-Type: application/json' -d '{"input":"ripgrep","turnstile_token":"<real>"}' ` returns 200 with the response triad (`spec_version: 0.4.0`, `site_spec_version: 0.4.0`, `anc_version: 0.4.0`, `checker_url`). - Homepage form at anc.dev renders the Turnstile widget (real `sitekey`, not the staging test `sitekey`) and successfully POSTs. - `bun x wrangler containers list` shows `agentnative-site-sandbox` advanced from container app `a0329fb0-...` (image `:30f61f1`, 6 instances) to a new container app instance at `:9aed5c3`. Existing prod instances may take a few minutes to roll over. - DO migration `v1` (which created the `Sandbox` class) applies to production for the first time; the migration is irreversible. Rollback path documented in `RELEASES.md` § Cross-migration rollback rehearsal, including the `wrangler containers delete <id>` step that the rehearsal surfaced. - No production smoke step runs automatically (per `RELEASES.md` § Post-deploy smoke scope, the smoke step is staging-only). Manual verification within ~5 minutes of merge is the gate. ## Files Modified **Modified:** - 95+ files across `src/worker/`, `src/build/`, `content/`, `docker/sandbox/`, `docker/score/`, `tests/`, `scripts/`, `styles/`, `.github/`, `RELEASES.md`, `README.md`, `wrangler.jsonc`. Full list in the diff. - `wrangler.jsonc`: lockstep image pin bump (top-level + env.staging both `:30f61f1` → `:9aed5c3`); full live-scoring binding surface mirrored under env.staging; migration history aligned with applied state (v1 top-level; v1 + v2-drop-sandbox + v3-restore-sandbox under env.staging per the rehearsal). - `RELEASES.md`: rehearsal recipe correction + evidence row. **Created:** - 30+ new source files implementing the live-scoring pipeline: `src/worker/score/handler.ts`, `src/worker/score/do.ts`, `src/worker/score/cache.ts`, `src/worker/score/discover-binary.ts`, `src/worker/score/parse-install.ts`, `src/worker/score/registry-lookup.ts`, `src/worker/score/resolve-spec.ts`, `src/worker/score/response-shape.ts`, `src/worker/score/sandbox-exec.ts`, `src/worker/score/session.ts`, `src/worker/score/sdist-allowlist.ts`, `src/worker/score/telemetry.ts`, `src/worker/score/turnstile.ts`, `src/worker/score/kill-switch.ts`, `src/worker/score/github-accessibility.ts`, plus their test files. Full list in the diff. - `docker/sandbox/Dockerfile` (sandbox image source), `docker/sandbox/README.md`. - `docs/runbooks/live-scoring-analytics.md`. - `scripts/smoke-api-score.sh`, `scripts/staging-cache-smoke.sh`. **Renamed:** - None. **Deleted:** - None.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Exposes the two unreachable pages, fixes a build-registration bug that was silently 404ing
/contribute, adds a four-repo Source row to the footer, and corrects a markdown formatting bug plus three near-dead deep links on the contributor page.Changelog
Added
/skillpage (skill-bundle install) and the/contributepage; the header now carries eight plain-text items in reading order: Leaderboard, Install, Check your CLI, Skill, Methodology, Coverage, About, Contribute.spec,cli,site,skill) under a quiet GitHub icon kicker. Inline SVG matches thecurrentColortreatment of the existing AI-summary icons so theme switches and dark mode work without extra CSS.Fixed
/contributewas building no HTML or markdown twin because the content file shipped without a corresponding entry insrc/build/build.mjssubPages. The route silently 404'd on the live worker. Adding the entry restores the page and adds it todist/sitemap.xml./contributebullet forAdd a tool to the registryrendered with an orphan-and a stray paragraph below it. The link URL is long enough that the auto-format hook (textwrap.fillwithbreak_long_words=False) couldn't keep bullet marker and link on the same 120-character line. Switched to a reference-style link so the inline bullet stays short./contributereferences toprinciples/AGENTS.md § Pressure-test protocollinked to the top of the upstream file rather than the named section. All three now deep-link to#pressure-test-protocolso visitors land on the protocol prose (which also carries thedraft → under-review → active → lockedstatus-flip rules at lines 98 to 117)..site-navwas breaking words inside a single link on narrow viewports (e.g.Check your CLIstacking asCheck/your/CLI). Addingflex-wrap: wrappluswhite-space: nowrapon the links fixes both the immediate eight-item layout and the pre-existing six-item bug.Type of Change
feat: New feature (non-breaking change which adds functionality)fix: Bug fix (non-breaking change which fixes an issue)BREAKING CHANGE: Breaking API change (requires major version bump)Related Issues/Stories
content/contribute.mdandCONTRIBUTING.md)Testing
Test Summary:
bun test: 736 pass, 0 fail (no test changes; existing assertions still hold).bun run lint: 0 errors across biome and markdownlint.node scripts/generate-pack-readme.mjs --check: passes (nostyles/content changed).bunx wrangler dev --env staging --local --port 8787: visually verified header (8 items, light + dark, 480px narrow viewport wraps cleanly without intra-link breaks), footer Source row (GitHub icon kicker plus four repo links rendered between AI-summary block and meta line), and both newly-routed pages (/skilltitleInstall agent-native-cli,/contributetitleContribute).dist/contribute.html,dist/contribute.md, and a<url>/contributeentry indist/sitemap.xmlare all produced where the previous build emitted nothing.Files Modified
Modified:
src/build/build.mjs: added{ name: 'contribute', path: ... }to thesubPagesarray.src/build/sitemap.mjs: added/contributeto the canonical paths list.src/build/shell.mjs: addedSkillandContributenav items, aGITHUB_SVGconstant (Simple Icons mark), aSOURCE_REPOSlist of four canonical repos, and the footer Source row markup.src/styles/site.css: addedflex-wrapandgapto.site-navpluswhite-space: nowrapon.site-nav a; added.site-footer__sourcerules for the new row.content/contribute.md: reference-style link foradd-tool-to-registrytemplate, three deep-link anchors onprinciples/AGENTS.mdreferences.Created:
Renamed:
Deleted:
Key Features
/skilland/contributeno longer require an out-of-band URL.Benefits
/skillwas reachable only via the homepage's "Install agent-native-cli" CTA copy and/contributewas unreachable entirely./contribute.Breaking Changes
No anchor changes, no removed routes.
/contributegoing from 404 to 200 is a Worker-observable change but not a user-facing breakage (404 was the bug; 200 is the fix).Deployment Notes
The
paths-ignorefilter does not skip changes tosrc/build/orsrc/styles/, so a normaldev → stagingworker deploy ships the build.Screenshots/Recordings
n/a in this body. Visual verification covered in Testing above; screenshots reviewed locally under
bunx wrangler dev --env staging --local --port 8787.Checklist
Additional Context
Two
/contributeintake URLs are known to 404 on the live web and were left as-is per direct instruction during review:agentnative-cli/issues/new?template=add-tool-to-registry.yml(template file exists locally in the cli working tree as untracked, never committed, never pushed).agentnative/issues/new?template=grading-finding.yml(template exists onagentnativeorigin/devper PR docs(plans): H6 day-1 addendum — merge mishap retro + tomorrow's batch #30 but not yet onorigin/main; GitHub serves issue templates from the default branch).Both will resolve once their respective upstreams land. No site-side workaround was added.