Add link snapshot contract + CI enforcement#98
Open
tuliren wants to merge 15 commits into
Open
Conversation
Mirrors the `npm run script scripts/<file>.ts` convention from app-monorepo-template/apps/web so future repo automation has a uniform entry point. The existing Python script under scripts/ is left as-is. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`link-snapshot.yaml` is an append-only record of every URL the docs site has ever served (nav pages + literal redirect sources + on-disk .mdx/.md files under lfm/, leap/, examples/, deployment/). The companion script derives URLs from `docs.json`, supports `--update` and `--check`, and verifies that each `active` URL still resolves via the current nav, disk pages, or redirect chain. Entries under `deleted:` are intentionally retired and skipped by the check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Regenerates link-snapshot.yaml and re-stages it whenever docs.json or any .mdx/.md file is in the commit. Installed automatically by "npm install" via the husky prepare script. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Runs `npm run snapshot:check` on every PR against main and on pushes to main. The check fails the build if any URL recorded in `link-snapshot.yaml#active` no longer resolves under the current `docs.json` + on-disk pages, prompting the contributor to add a redirect, deprecate the page in place, or move the URL to `deleted:`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Explains the one-time `npm install` to wire the pre-commit hook, the three remediation paths when CI flags a missing URL (redirect / keep as deprecated / move to `deleted:`), and the manual commands to regenerate or verify the snapshot. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
The previous contract-violation message told contributors to "move the URL to deleted with a reason" but did not show the YAML shape, so it was unclear whether reason was a quoted string, required, or how to add a retired_at field. Two changes: 1. Both the contract-violation message and a new "malformed deleted entry" check now print a fenced YAML example. 2. Each deleted entry is now validated to have a non-empty reason field; bare URLs under deleted are rejected at check time with the same example. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
README now carries a one-paragraph orientation pointing readers at CLAUDE.md for the full mechanics. CLAUDE.md gains a new "Link Snapshot Contract" section covering the file format, the resolution algorithm CI uses to decide whether an `active` URL is satisfied, the three remediation paths in priority order, and the common pitfalls (forgetting redirects on path renames, skipping `npm install`, manually editing `active`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The header on link-snapshot.yaml already explained that contributors move URLs from active to deleted; it did not show what either form looks like. Two commented examples now ride along with the file so that someone editing it directly does not need to cross-reference CLAUDE.md or trigger a CI failure to discover the shape. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The runScriptWithEnv.sh wrapper was a single exec call with no env-file handling — invoking tsx straight from package.json is one fewer indirection and removes the asymmetry with how scripts are typically run elsewhere. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the examples sat at the top of the file they were easy to skim past — by the time a contributor scrolled down to `deleted:` they had to remember a YAML shape from screens earlier. Splitting the serializer so it emits `active:` first, then the example block, then `deleted:` keeps the examples adjacent to the field they describe. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Compressed from 60+ lines to ~17. Cut the file-shape YAML block (the snapshot file now carries its own example comments), the tooling table (folded into prose), and the common-pitfalls section. Kept the resolution algorithm and the three remediation paths since those are what a contributor needs to act on a CI failure. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous one-paragraph orientation said what the snapshot was but not how the append-only invariant survives the pre-commit hook regenerating the file on every commit. Four bullets now make the mechanism explicit so contributors do not have to follow the link to CLAUDE.md to understand why a missing redirect breaks CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A leading bullet now names `active:` and `deleted:` as the two sections of link-snapshot.yaml so the append-only invariant in the following bullets reads as "the active field stays append-only," not "active is append-only" without antecedent. Also pulled the hand-edit clue into the retire-a-URL bullet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
link-snapshot.yaml, 161 URLs) recording every URL the docs site has ever served — nav pages fromdocs.json, literal redirect sources, and on-disk.mdx/.mdfiles underlfm/,leap/,examples/,deployment/.scripts/generateLinkSnapshot.ts(--update/--check) plus a husky pre-commit hook and a GitHub workflow (check-link-snapshot.yaml) that fails any PR which makes a snapshotted URL stop resolving.package.json,tsconfig.json,scripts/runScriptWithEnv.sh) modeled afterapp-monorepo-template/apps/web. The existingscripts/generate_snippets.pyandcheck-docs.yamlworkflow are untouched.When the check flags a URL, contributors pick one of three remediations: (1) add a
redirectsentry indocs.json, (2) keep the.mdxon disk but drop it from navigation, or (3) move the URL todeleted:inlink-snapshot.yamlwith a reason. Option 3 is described in the README as the last-resort path.Test plan
npm installwires the husky pre-commit hook (run once per clone).npm run snapshot:checkexits 0 on a clean tree (161 URLs verified).docs.jsonnavigation and its.mdxfile without adding a redirect →npm run snapshot:checkfails naming the URL and listing the three remediation paths.redirectsentry for that URL → check passes..mdxon disk but remove from nav → check passes (deprecate-but-keep path).activetodeleted:with a reason, runnpm run snapshot:update, → URL drops fromactiveand check passes..mdxedit andgit commit→ pre-commit hook regenerateslink-snapshot.yamland re-stages it.🤖 Generated with Claude Code
Resolve https://linear.app/liquid-ai/issue/DOC-26/add-ci-to-ensure-old-links-still-work-after-changes-introduced-by-a-pr