Repository navigation
feat(verify): enforce source headers and a dependency allowlist - #884
Conversation
Two contracts the repo stated but nothing enforced now fail the gate. - `scripts/source-headers.ts` — every shipped source file carries a 1–4 line header comment stating its single responsibility. Existing violations are held by a per-file pin table that may only fall. - `scripts/dependency-allowlist.ts` — every `dependencies` / `devDependencies` entry is either an `@ultimat3/*` workspace edge or a name in the checked-in allowlist. A new dependency is a new row, and a new row is a review. Both reach `x verify` through their own `scripts/<name>.test.ts`, the way `node-imports` and `fix-prose` do. Dz-Task-Id: tsk_35060e816384db46d4d2d836b97ee6c2
🟡 Reviewed2 actionable comment(s) · 3 suppressed (anti-noise) · grounded on your code ⏱ 2m 34s wall clock · 🤖 developerz.ai — automated review, running on your model and your box. |
There was a problem hiding this comment.
Review summary — 13 file(s), 4 finding(s).
Critical 0 · Major 1 · Minor 3 · Nit 0
[bot] completed: Reviewed the source-header and dependency guards, gate tests, and documentation. Found header parsing errors, stale-pin retention, an overly broad dependency exemption, and a vacuous fix-contract test. [bot] completed: Reviewed the source-header and dependency-allowlist guards.
| File | Findings |
|---|---|
scripts/dependency-allowlist.ts |
1 minor |
scripts/source-headers.test.ts |
1 minor |
scripts/source-headers.ts |
1 major, 1 minor |
3 non-blocking findings (3 minor; not posted inline)
scripts/dependency-allowlist.ts:128bug [bot] A dependency namedleft-padbypasses the allowlist whenever any scanned workspace is namedleft-pad, although the acceptance contract exempts only real@ultimat3/*workspace edges. Require the@ultimat3/prefix as well as workspace membership before skipping allowlist validation.scripts/source-headers.test.ts:51test [bot] The runnable-fix test iterates the same repository findings that the preceding test requires to be empty, so it passes even if every generated fix becomes empty. Use violating fixture files and a stale pin to produce findings, assert their presence, then check their fixes.scripts/source-headers.ts:142bug [bot] Deleting a pinned source file silently preserves its allowance because nonexistent paths are skipped, so recreating that path without a header passes later. Report absent pinned paths as X_SOURCE_HEADER_PIN_STALE for the repository root and isolate fixture pin tables explicitly.
🤖 developerz.ai review — automated, running on your model and your box. What is this? · Reviewed by router/gpt-6.1-sol on box hv-dedicated-dev-marshall — 506.8k in / 2.36k out over 9 calls; cost unknown: no price on record for router/gpt-6.1-sol.
|
A fix round is resolving this pull request's merge conflict with
Status for head 🤖 Posted by developerz.ai — an automated agent, not a human. |
|
Resolve merge conflict on #884
Work landed on #884 — watching it toward merge. 27m · 28 tool calls · 18 messages Sessions: coding run · review 1 🤖 developerz.ai, an automated agent, not a human — hv-dedicated-6 (developerz-ai[bot]) · model |
…moved) Follow-up intent: Address review findings on #884 Dz-Task-Id: tsk_32ed0877c196813b4df8aff4b86abd26
…ce-source-headers-and-dependency--35060e81 # Conflicts: # framework.manifest.json
There was a problem hiding this comment.
Review summary — 4 file(s), 2 finding(s).
Critical 0 · Major 0 · Minor 2 · Nit 0
[bot] completed: Reviewed the source-header guard, per-file pins and tests. Deleted files leave reusable stale pins, and the fix-contract test passes without exercising a finding. [bot] completed: Reviewed the source-header guard and regressions.
2 non-blocking finding(s) below major (no thread on a re-review — only blocking findings open threads)
scripts/source-headers.test.ts:105minor · test [bot] The fix-contract test iterates findings from the same clean tree asserted above, so it passes even if every finding factory returns an empty fix. Use fixture files that produce findings, assert the findings are nonempty, and check their fixes.scripts/source-headers.ts:159minor · bug [bot] Deleting a pinned file skips stale-pin detection, so its row survives and silently exempts a headerless file later recreated at that path. Report absent pinned files as stale in repository scans, and isolate fixture pins through an explicit parameter instead.
🤖 developerz.ai review — automated, running on your model and your box. What is this? · Reviewed by router/gpt-6.1-sol on box hv-dedicated-4 — 302.5k in / 1.37k out over 7 calls; cost unknown: no price on record for router/gpt-6.1-sol.
What
Two contracts the repo stated but nothing enforced now fail the gate.
scripts/source-headers.ts— every shipped source file carries a1–4 line header comment stating its single responsibility. Existing
violations are held by a per-file pin table that may only fall.
scripts/dependency-allowlist.ts— everydependencies/devDependenciesentry is either an@ultimat3/*workspace edge or aname in the checked-in allowlist. A new dependency is a new row, and
a new row is a review.
Both reach
x verifythrough their ownscripts/<name>.test.ts, theway
node-importsandfix-prosedo.Acceptance
bun run scripts/source-headers.ts --jsonreports a shipped source file whose leading header comment is missing or whose first paragraph is not 1–4 lines of prose, and exits non-zero — proved bybun test scripts/source-headers.test.ts.bun run scripts/dependency-allowlist.ts --jsonreports adependencies/devDependenciesentry in any workspace manifest that is absent from the checked-in allowlist, and exits non-zero — proved bybun test scripts/dependency-allowlist.test.ts.scripts/<name>.test.tsthat asserts the repo-wide findings are empty, and the gate'sunitstep runs everyscripts/**/*.test.ts, so a violation failsbun run verifywith no extra wiring (thescripts/node-imports.test.tspattern)./* */block header produce no finding; a 5-line first paragraph, a missing header and an empty header each produce a finding; an allowlisted dependency passes while an unallowlisted `dependen [trimmed]scripts/lib/source-header-pins.ts), each row counted per file so a fix cannot be swapped for a new violation; the pin count may only fall, and a stale row is a finding (X_SOURCE_HEADER_PIN_STALE). No [trimmed]X_*code is declared underscripts/, listed in the never-ships parenthesis ofwiki/Error-Codes.mdand given a table row there, sobun run scripts/gate-codes.ts --jsonreports noX_GATE_CODE_UNDOCUMENTED.docs/architecture/guards.mdcarries the two new guard rows, sobun run scripts/guards-doc.ts --checkreports noX_GUARDS_DOC_DRIFT.bun test scripts/corpus-unscanned.test.tspasses: the header guard answersX_CORPUS_UNSCANNEDon an unreadable tree, as every other whole-tree guard does.bun run verifyis green: the new guards add no finding to this tree,scripts/verify.test.ts's assertion that the host checks stay exactly['boundaries','errors','manifest','roadmap']is untouched, andscripts/guards-doc.test.ts's assertion that the committed guards page matches the [trimmed]Changes
scripts/source-headers.ts(create) — New guard: scan the shipped-source corpus (scripts/lib/corpus.ts scope 'shipped') and fail any file whose leading header comment is missing, whose first paragraph is not 1-4 lines, or whose header carries no prose. Ratchets against scripts/lib/source-header-pins.ts per FILE (a count per package would let a fix be swapped for a new violation). Exports sourceHeaderFindings(root) so the .test.ts is the build error. Emits X_SOURCE_HEADER_MISSING, X_SOURCE_HEADER_OUT_OF_CONTRACT, X_SOURCE_HEADER_PIN_STALE, X_SOURCE_HEADER_UNSCANNED.scripts/lib/source-header-pins.ts(create) — Per-FILE pin table for the header guard: key is the repo-relative path, value { count, reason }. Data only, with SOURCE_HEADER_PINS_FILE exported so the stale finding can name the file to edit. Every existing violation is listed explicitly with the sentence saying why it stands; the count may fall and may never rise.scripts/source-headers.test.ts(create) — Regression coverage and the build error: a 1-line and a 4-line header pass, a 5-line first paragraph fails, a missing header fails, an empty header fails, a /* */ block header passes; the repo tree is at or under its pin; each finding carries a runnable fix:. Declares setDefaultTimeout(REPO_SCAN_TIMEOUT_MS) because it calls repoRoot() (scripts/repo-scan-timeout.test.ts).scripts/dependency-allowlist.ts(create) — New guard: read every workspace manifest (root package.json, packages//package.json, and the two tracked apps) through scripts/lib/workspaces.ts and fail any dependencies/devDependencies entry absent from the checked-in allowlist. An @ultimat3/ name must name a real workspace; every other name must be an allowlist row. Ratchets per (manifest, dependency). Exports dependencyAllowlistFindings(root). Emits X_DEPENDENCY_NOT_ALLOWLISTED, X_DEPENDENCY_ALLOWLIST_STALE, X_DEPENDENCY_UNSCANNED.scripts/lib/dependency-allowlist-data.ts(create) — The checked-in allowlist of external dependency names, keyed '#' with a { reason } saying why the dependency is here. Data only, with DEPENDENCY_ALLOWLIST_FILE exported for the stale finding. Every currently-declared external dependency (@babel/core, babel-preset-solid, nats, sass, @electric-sql/pglite, @biomejs/biome, @types/bun, lefthook, solid-js, typescript) is an explicit row.scripts/dependency-allowlist.test.ts(create) — Regression coverage and the build error: an allowlisted dependency passes; an unallowlisted dependencies entry fails; an unallowlisted devDependencies entry fails; an allowlist row for a dependency that no longer exists is stale; a broken manifest is refused as a finding, never thrown; the repo tree is clean.package.json(edit) — Add the two script aliases ('source-headers' and 'dependency-allowlist') so scripts/guards-doc.ts prints 'bun run ' for the new guards and the generated guards page lists them.wiki/Error-Codes.md(edit) — Add the new codes to the never-ships parenthesis on line 27 (scripts/gate-codes.ts refuses a code declared under scripts/ that the parenthesis omits) and give each a table row in the 'CLI and verify' section, where the other gate-script codes live.docs/architecture/guards.md(edit) — Regenerate the two new guard rows (bun run scripts/guards-doc.ts --write). The page is generated from each guard's own header and --check refuses drift, so it cannot be hand-edited.scripts/corpus-unscanned.test.ts(edit) — Add the header guard to the GUARDS list: it reads the tree through scripts/lib/corpus.ts and must therefore answer X_CORPUS_UNSCANNED on an unreadable tree, exactly as every other whole-tree guard in that list does.framework.manifest.json(edit) — [docs] GENERATED FILE — regenerate withbun run manifest, never hand-edit (X_MANIFEST_DRIFT). The four X_SOURCE_HEADER_* rows at lines 4033-4051 must match the codes scripts/source-headers.ts declares after the fix; if X_SOURCE_HEADER_UNSCANNED is removed there, its row goes too and the buildId changes. The three X_DEPENDENCY_* rows at lines 1208-1221 are unaffected by this change and must keep the orderbun run manifestproduces (errorCodes are sorted by code via localeCompare, packages/cli/src/error-contract.ts:264) — do not re-sort them by hand.Verification
bun run verifypassed (exit 0) in 16m 50s.Notes
Premises of the request the team disproved:
package-shapestep. It cannot:packages/cli/src/verify-checks.ts:144-148shows that step calls onlycheckPackageShapeandcheckWorkspaceDependenciesand takes NO host findings, andpackages/cli/src/verify-step.ts:61-66states a host adds findings to a step but can never add, remove or reorder a step. Wideningpackage-shape[trimmed]scripts/verify.test.ts:84assertsObject.keys(HOST_CHECKS)).toEqual(['boundaries', 'errors', 'manifest', 'roadmap']), so adding a step name would red the existing gate. Both guards reachx verifythe wayscripts/node-imports.tsdoes (scripts/node-imports.test.ts:1-3): ascripts/<name>.test.tsthat the ga [trimmed]dependencies/devDependenciesgains an entry absent from a checked-in allowlist. A name-only allowlist covering@ultimat3/*as well would have to duplicate the tier table and the workspace registry (scripts/lib/tiers.ts,scripts/lib/workspaces.ts) and would go stale against them. The guard therefore checks@ultimat3/*names against the real workspace se [trimmed]🤖 Opened by developerz.ai for task
tsk_35060e816384db46d4d2d836b97ee6c2on developerz-ai/ultimate.Raised automatically by the
raw_task_triagelane.