feat(docs): require every published doc slug to be recorded in the Fern lock - #515
Conversation
…rn lock `documentation/guides/migrating-optimization-sdk-packages-from-v1-to-v2.md` merged in #514 without a `documentation/fern-slugs.lock.json` entry, which was allowed: the exporter reconciles an unrecorded document in memory, so the page publishes either way. What it silently lost was slug protection. The existing check can only compare a slug against one the lock already names, and the sync workflow runs `pnpm docs:fern` without `--update-lock`, so an entry an author never commits never appears. That page's first slug reword would have moved a live URL with no redirect — the exact failure the lock exists to prevent. It was the first new page since the lock landed in #442, so the gap had never been reachable before. `pnpm fern:check` now reports an unrecorded slug the same way it reports a changed one, naming the command that fixes it, and records the missing v1-to-v2 entry so the check passes on `main`. The slug-change path is unchanged. Because a check only catches what reaches CI, the contract is also written down where an author meets it: a new `docs-site-publishing` skill owns the four artifacts that decide whether a page ships (group README `children:`, the `fern:` block, the slug lock, MDX safety), the group-global sidebar ordering rule, and the release-gated sync. `optimization-guide-authoring` now routes to it from a publication step in its workflow, and the self-review checklist gains a mechanical section G. `documentation/AGENTS.md` documented only how to change a slug, never how to record one, and never that `children:` is what publishes a document at all; both are now stated. Validation: `pnpm fern:check`, `pnpm guides:check`, `pnpm knowledge:check`, `pnpm lint`, `pnpm typecheck`, ESLint on both changed scripts, targeted Prettier on every changed file, `git diff --check`. Verified by hand that the new check fires on an unrecorded page and that a changed slug is still reported. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Code Review Agent Run #8ec28cActionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
Impact Analysis by BitoCross-Repository Impact Analysis
Code Paths AnalyzedImpact: Flow: Direct Changes (Diff Files): Repository Impact: Cross-Repository Dependencies: Database/Caching Impact: API Contract Violations: Infrastructure Dependencies: Additional Insights: Testing RecommendationsFrontend Impact: Service Integration: Data Serialization: Privacy Compliance: Backward Compatibility: OAuth Functionality: Cross-Service Communication: Reliability Testing: Additional Insights: Analysis based on known dependency patterns and edges. Actual impact may vary. |
✅ Review Settings OverriddenStatus: Guidelines:
Note: Extra guidelines beyond 3 general purpose guidelines and 1 language specific guideline per language are not processed. Guidelines are fetched from the source branch. |
…en down The first draft restated ADR 0002 and the `documentation/AGENTS.md` publishing section at length. Both already own this material, so the skill was mostly a third copy that could drift from them. It now points at those two as sources of truth and keeps only what neither records: that a document absent from its group README `children:` is silently not published, that `children:` order is global across the group so an index decides position *within* a section, and that a new slug has to be recorded and committed with the page. Same cut in the self-review checklist. `pnpm fern:check` mechanically enforces the `fern:` block shape, slug format, link and anchor resolution, MDX safety, and slug recording, so restating those as human checkboxes added nothing. Section G now asks only what a check cannot judge: intent — whether the `children:` index is the intended position, whether a slug change is deliberate, and whether the lock diff shipped with the guide. Descriptions are matched, not read, so the skill's own description is now a short purpose plus its trigger conditions rather than a summary of its contents. Wire `fern:check` into the documentation-integrity Stop hook, which ran `knowledge:check` and `guides:check` but not the check that decides whether an edit reaches the public site at all. This is the part that actually fires unprompted: the publishing contract breaks silently, so it needs a trigger that does not depend on anyone thinking to look. Watched paths gain `documentation/concepts`, the slug lock, and the fern scripts. Validation: `pnpm fern:check`, `pnpm guides:check`, `pnpm knowledge:check`, `bash -n` on the hook, targeted Prettier, `git diff --check`. Exercised the hook both ways — silent and exit 0 on a clean tree, and reporting the unrecorded-slug problem with its fix command after removing the lock entry. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
7058dac
There was a problem hiding this comment.
Code Review Agent Run #876303
Actionable Suggestions - 1
-
skills/docs-site-publishing/SKILL.md - 1
- Missing migration-knowledge-authoring in scope list · Line 62-64
Additional Suggestions - 1
-
skills/docs-site-publishing/SKILL.md - 1
-
Incorrect hook claim · Line 46-48The claim that `fern:check` "runs from the `Stop` hook" is incorrect: no `Stop` hook exists in `.husky/` (only `commit-msg`, `pre-commit`, `pre-push`, `prepare-commit-msg`), and `pre-commit` runs only lint-staged (prettier on md). `fern:check` actually runs in CI (`main-pipeline.yaml:255`, `sync-fern-docs.yaml:113`). Reword so an agent doesn't skip a local run expecting a hook.
-
Review Details
-
Files reviewed - 4 · Commit Range:
443a302..7058dac- scripts/documentation-integrity-hook.sh
- skills/docs-site-publishing/SKILL.md
- skills/optimization-guide-authoring/SKILL.md
- skills/optimization-guide-authoring/references/authoring-checklist.md
-
Files skipped - 0
-
Tools
- Whispers (Secret Scanner) - ✔︎ Successful
- Detect-secrets (Secret Scanner) - ✔︎ Successful
Bito Usage Guide
Commands
Type the following command in the pull request comment and save the comment.
-
/review- Manually triggers an incremental AI Review. -
/review full- Manually triggers a full AI Review. -
/pause- Pauses automatic reviews on this pull request. -
/resume- Resumes automatic reviews. -
/resolve- Marks all Bito-posted review comments as resolved. -
/abort- Cancels all in-progress reviews.
Refer to the documentation for additional commands.
Configuration
This repository uses Default Agent You can customize the agent settings here or contact your Bito workspace admin at jared.jolton@contentful.com.
Documentation & Help
| Guide prose and structure (`optimization-guide-authoring`), migration routing | ||
| (`migration-guide-authoring`), fact derivation (`sdk-knowledge-authoring`), and the | ||
| `contentful-docs` repository's own conventions. |
There was a problem hiding this comment.
The Not in scope section now lists only sdk-knowledge-authoring for fact derivation, but the previous version also referenced migration-knowledge-authoring for migration fact derivation. If that skill still exists, readers with migration fact questions may be directed to the wrong skill.
Code suggestion
Check the AI-generated fix before applying
| Guide prose and structure (`optimization-guide-authoring`), migration routing | |
| (`migration-guide-authoring`), fact derivation (`sdk-knowledge-authoring`), and the | |
| `contentful-docs` repository's own conventions. | |
| Guide prose and structure (`optimization-guide-authoring`), migration routing | |
| (`migration-guide-authoring`), SDK or migration fact derivation (`sdk-knowledge-authoring`, | |
| `migration-knowledge-authoring`), and the | |
| `contentful-docs` repository's own conventions. |
Suggested based on your custom review guideline "Repo Truth And Boundaries"
Code Review Run #876303
Should Bito avoid suggestions like this for future reviews? (Manage Rules)
- Yes, avoid them
Summary
The v1-to-v2 migration guide merged in #514 without an entry in
documentation/fern-slugs.lock.json. That was allowed by design —reconcileLocksupplies an entry in memory, so the page publishes either way — but it silently shipped without slug protection:pnpm docs:fernwithout--update-lock, so an entry an author never commits never appearsThat page's first slug reword would have moved a live URL with no redirect — the exact failure the lock exists to prevent. It was the first new page since the lock landed in #442, so the gap had never been reachable before. The release sync has since run, so
migrate-optimization-sdk-v1-to-v2is a live URL and the recorded entry matches what actually shipped.Enforcement
pnpm fern:checknow reports an unrecorded slug the same way it reports a changed one, naming the fix:The missing entry is recorded here, so the check passes on
main. The slug-change path is unchanged, and--update-lockstill records new pages and redirects as before.fern:checkis also wired into the documentation-integrityStophook, which ranknowledge:checkandguides:checkbut not the one check that decides whether an edit reaches the public site. The publishing contract breaks silently, so it needs a trigger that does not depend on someone thinking to look. Watched paths gaindocumentation/concepts, the slug lock, andscripts/fern.Documentation
ADR 0002 and the
documentation/AGENTS.mdpublishing section already own most of this contract, so the newdocs-site-publishingskill points at both rather than becoming a third copy. It keeps only what neither records:children:is silently not published — the exporter reads that list and never scans the filesystemchildren:order is global across the group, so a page's index in the oneguides/list decides its position within itsfern.sectiondocumentation/AGENTS.mdgains those first and third points.optimization-guide-authoringgains a publication step routing to the skill, and checklist section G asks only what a check cannot judge — intent: whether thechildren:index is the intended position, whether a slug change is deliberate, and whether the lock diff shipped with the guide.Validation
pnpm fern:check,pnpm guides:check,pnpm knowledge:check— all passpnpm lint,pnpm typecheck— pass (typecheckneeded apnpm installfirst; unrelated stale deps after chore(repo): release packages for main #503)pnpm lintcovers onlylib packages, notscripts/bash -non the hook; targeted Prettier;git diff --checkclean🤖 Generated with Claude Code