fix(core,content): stop generated SvelteKit routes dirtying the working tree - #2201
Open
willgriffin wants to merge 3 commits into
Open
fix(core,content): stop generated SvelteKit routes dirtying the working tree#2201willgriffin wants to merge 3 commits into
willgriffin wants to merge 3 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR addresses persistent working-tree churn caused by SMRT’s SvelteKit route generator by (1) making legacy .gitignore migration robust to routesDir changes and (2) ensuring generated route output is treated as build/dev-time output rather than tracked source, aligning content with assets/images.
Changes:
- Core: migrate legacy generated-route
.gitignoreentries by shape (including negations) and continue stripping legacy entries even when a bounded managed block already exists. - Packages: replace legacy broad ignore rules in
assets/imageswith bounded, explicit managed blocks for generator-owned+server.tspaths. - Content: remove previously committed generated route handlers and document the intended “generator output is not tracked” workflow in
AGENTS.md.
Reviewed changes
Copilot reviewed 103 out of 103 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| packages/images/.gitignore | Replaces legacy broad ignore rule with bounded managed block for generated routes. |
| packages/core/src/vite-plugin/sveltekit-generator.ts | Updates .gitignore managed-block logic to migrate legacy entries by shape and strip stale negations reliably. |
| packages/core/README.md | Documents updated migration behavior and clarifies that generated routes should not be committed. |
| packages/content/src/routes/api/v1/contentversions/restoreIntoContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentversions/listForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentversions/getVersion/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentversions/getNextVersionNumber/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentversions/getLatestPublishedForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentversions/getLatestForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentversions/createSnapshot/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentversions/[id]/transparency/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/transparency/preview/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/transparency/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/review-profiles/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/review-profiles/[profileKey]/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/governance/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/fact-audit/repair/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/fact-audit/evidence/status/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/fact-audit/evidence/repair/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/fact-audit/claims/recheck/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contents/[id]/fact-audit/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreviews/listForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreviews/getLatestForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreviews/createFromResult/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/unlink/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/setLinks/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/getForTarget/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/getForSource/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/detach/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/byRight/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/byLeft/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentreferences/attach/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentgovernanceprofiles/getByKey/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentgovernancepolicies/getByKey/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentgovernanceassignments/resolveForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentfeedsources/findByStatus/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentfeedsources/findActive/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcorrections/listForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcorrections/issue/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcorrections/getPublishedForContent/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributors/getByProfileId/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributors/getByEmail/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributors/findOrCreateByEmail/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributiontypes/getByKey/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/submit/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/ingest-email/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/[id]/withdraw/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/[id]/revisions/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/[id]/request-changes/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/[id]/reject/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/[id]/promote/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributions/[id]/approve/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/src/routes/api/v1/contentcontributionattachments/listForRevision/+server.ts | Removes tracked generated route file (now treated as generated output). |
| packages/content/AGENTS.md | Documents the “do not track generated routes” policy and the current typecheck spillover behavior/guard. |
| packages/assets/.gitignore | Replaces legacy broad ignore rule with bounded managed block for generated routes. |
The legacy `.gitignore` migration matched the header only when the line beneath it equalled a pattern derived from the *current* `routesDir`. `@happyvertical/smrt-content` adopted the plugin at `src/routes/api` and later moved to `src/routes/api/v1`, so its pair never matched and survived every regeneration; the bounded block was then appended after the surviving `!src/routes/api/v1/**/+server.ts` negation, leaving contradictory rules. Migrate by shape instead: take the recognized header plus the contiguous run of recursive `+server.ts` wildcards beneath it, negations included, stopping at the first line that is neither (a comment always ends the run). Migration now also runs once the bounded block exists, because a project generated by the first #2185 release kept its unmatched pair, and that stale negation silently re-includes whatever the block stops listing. An application-owned broad rule elsewhere in the file is still preserved. Stop tracking the 96 generated route files in `packages/content`. They were swept into #1863 alongside the handwritten dev-app pages and the negation that exposed them; nothing described them as intentional output. They are not Biome-formatted — regenerating produces 117 `format` errors across 99 files against 6 today — so tracking them means a Lint job gated on output no one edits, and emitting byte-exact formatted code for arbitrary model and field names is not something the generator can promise. `packages/assets` and `packages/images` already track none, `files: ["dist"]` ships none, and `.claude/rules/testing.md` says to test generators, not generated output. `contents-api.test.ts` imports two of them; the `test` script runs `svelte-kit sync` first, which regenerates the tree, so all 302 content tests pass with none committed. The 5 handwritten handlers under `src/routes/api/v1` stay tracked and gain lint coverage: the bounded block lists only generator-owned paths, where the blanket negation covered everything. Regenerate the bounded block for all three packages. Regeneration is now idempotent — a second dev run rewrites nothing. `packages/content/.gitignore` keeps a documented spillover guard: `svelte-check` runs a second generation pass at the default `routesDir`, emitting a duplicate API surface under `src/routes/api/` and deleting the v1 tree. That is pre-existing and tracked separately in #2199; the guard keeps route files out of `git status` under both shapes so this change does not unmask it. Closes #2198 Refs #2199
willgriffin
force-pushed
the
feat/issue-2198-sveltekit-route-drift
branch
from
August 3, 2026 17:03
7b5f49f to
24221a0
Compare
`scripts/check-coverage.mjs` runs `pnpm exec vitest run --coverage` directly, bypassing the package's `test` script and therefore its `svelte-kit sync` step. With the generated routes no longer committed, `contents-api.test.ts` cannot resolve `./routes/api/v1/contents/+server`, the suite fails to load, no coverage summary is written, and the gate reports `content (T2): no coverage produced` instead of a percentage. The gate already runs `pnpm run --if-present generate:test` first for exactly this reason — core uses it to build its test manifest. Point content's at `svelte-kit sync`, which regenerates the whole route tree. Mark the task `cache: false` for this package: the root `generate:test` declares core's manifest paths as its `outputs`, so a turbo cache hit would restore nothing for content and silently skip the sync. Coverage gate now reports content (T2) 72.07% against a 70% floor. Refs #2198
willgriffin
force-pushed
the
feat/issue-2198-sveltekit-route-drift
branch
from
August 3, 2026 17:30
24221a0 to
6a3f3d9
Compare
|
Implementation lease expired. PR is ready for review but blocked pending handoff. |
willgriffin
enabled auto-merge
August 6, 2026 02:35
willgriffin
disabled auto-merge
August 6, 2026 02:35
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.
{"schema":"hv-agent-run:v1","runtime":"claude","session":"8a94e288-0358-403f-a3a6-8e81a80e6c5d","issue":"2198","head_sha":"274fccd02208b3ac4296ce17b26abcbeac2a4498","policy_revision":"1.0.0","status":"complete"}Summary
.gitignoreblock by shape instead of by the currentroutesDir, and keep migrating once the bounded block existspackages/content; regenerate the bounded block forcontent,assets, andimagespackages/content/.gitignorefor fix(content,core): svelte-check runs a second route generation pass at the default routesDir, deleting the v1 tree #2199Root cause
updateGeneratedRouteIgnoreBlock()recognized the legacy pair only when the line under# SMRT auto-generated routes (from Vite plugin)equalled${routesDir}/**/+server.tsfor theroutesDirconfigured today.smrt-contentadopted the plugin atsrc/routes/apiand later moved tosrc/routes/api/v1, so its pair never matched and survived. The generator then appended its bounded block after the surviving!src/routes/api/v1/**/+server.tsnegation, leaving rules that contradict each other.Separately, the 96 generated routes under
src/routes/api/v1were tracked only because that stale negation exposed them. They were swept into #1863 alongside the handwritten dev-app pages; nothing described them as intentional output.pnpm builddoes not reproduce —content/assets/imagesbuild in library mode (SMRT_PACKAGE_BUILD=1), which skips route generation. Generation runs fromconfigResolved, sopnpm dev(orsvelte-kit sync) is what dirties the tree.Why untrack rather than commit the regenerated output
The committed routes are stale against today's generator, and the generator's output is not Biome-formatted:
biome ci --diagnostic-level=erroronpackages/content/src/routes/api/v1They are
formatdiagnostics — emitted import lists, call expressions, andJSON.stringify-derived literals exceedlineWidth: 80or use double quotes. Committing the regenerated output means runningbiome --writeover 99 files, after which the committed text no longer matches generator output and the next dev run re-dirties it. Emitting byte-exact formatted code for arbitrary model and field names would mean reimplementing the formatter in the generator, and would regress the moment a name got longer.Untracking matches
packages/assetsandpackages/images(which track none), the generator's own stated intent,files: ["dist"](the routes ship nowhere), and.claude/rules/testing.md— "Test generators, not generated output." Regression coverage lands inpackages/coreagainst the generator.Lint coverage improves
The 5 handwritten handlers under
src/routes/api/v1(contents/[id]/chat/**,images/**) stay tracked and gain coverage: the bounded block lists only generator-owned paths, where the blanket negation exposed everything indiscriminately.contents-api.test.tsimports two generated routes. Thetestscript runssvelte-kit syncfirst, which regenerates the tree, so all 302 content tests pass with none committed — verified by hiding all 96 files and re-running.Known limitation (#2199, pre-existing)
svelte-check, viapnpm typecheck, runs a second generation pass at the plugin's defaultroutesDir. It deletes the v1 tree and emits a duplicate surface undersrc/routes/api/. That is pre-existing onmain, masked there by the broad glob this PR removes, and unrelated to this fix — a.gitignorecannot influence whichroutesDirthe plugin uses. The documented guard inpackages/content/.gitignorekeeps route files out ofgit statusunder both block shapes; only the.gitignoreitself still churns. Filed as #2199 with the investigation so far; the guard is to be deleted with that fix.Follow-up: Coverage Gate (2nd commit)
scripts/check-coverage.mjsrunspnpm exec vitest run --coveragedirectly, bypassing the package'stestscript and itssvelte-kit sync. With the routes untracked,contents-api.test.tscould not resolve its imports, so the gate reportedcontent (T2): no coverage produced.The gate already runs
pnpm run --if-present generate:testfirst for exactly this case (core builds its test manifest there). Content's now points atsvelte-kit sync, markedcache: falseinpackages/content/turbo.jsonbecause the root task'soutputsdescribe core's manifest — a turbo cache hit would restore nothing and silently skip the sync.Gate now reports content (T2) 72.07% (floor 70%) and core (T1) 86.21% (floor 80%), verified from a true fresh-checkout state with every generated route deleted.
Validation
pnpm test— core 3179 passed / 45 skipped (270 files); content 302 passed / 6 skipped (45 files)npx @biomejs/biome@2.5.2 ci --diagnostic-level=error .— exit 0 (the CI Lint job command)turbo run typecheck— core + content exit 0; assets + images exit 0 and leave a clean tree (theirroutesDiris already the default, so they need no guard)pnpm smrt dev:knowledge-check— 0 errors, 0 warnings;pnpm check:agents-chain— 64 chains under limitnode scripts/check-coverage.mjs— no tiered packages affectedUpdated .gitignoreis not logged) and leaves zero untracked noiseCloses #2198
Refs #2199
Note: an orphaned
Agent Policyrun (workflow id 315669746, since deleted) sat queued on this head and could not be rerun, blocking the required context. It was force-cancelled and this edit re-triggersAgent Policyviapull_request: edited.Lifecycle re-trigger: the org-required
Agent Policyrun and this repo's own share the concurrency groupagent-policy-diagnostic-2201, so overlapping push/edit events wedged the required run inqueued. Cleared and re-fired once.