f2c0021941
Archive 21 implemented triplets whose shipped decisions are complete and whose bodies no longer guide future work (one-off UI chrome, generator applications whose scripts are self-explanatory, superseded implementation detail, process history owned by current contracts/skills). Delete 4 rejected triplets whose premises are obsolete: the DeepReadonly proposal (dev-invariants note now carries the alternative inline), the collapse tool-owned presentation proposal (superseded by the shipped render-intent union), retire-mid-turn-steering (steering is now load-bearing across plan-mode/apiproxy/TUI), and single-session-ACP (automation-only ACP resolved the question; multi-session isolation is pinned by tests). Repair every inbound link: retarget intentional historical citations to archived paths, replace decision-current citations with the surviving authority, and fix the stale example-execute-over-tsx pointer in pnpm-workspace.yaml. Re-record pairing sidecars and seal the archive manifest (append-only; existing seals unchanged).
4.9 KiB
4.9 KiB
Agent Note: Consolidate gate scripts on already-present deps and builtins
Status: implemented Archived: 2026-07-27
English | 中文
Problem
The scripts/ gates mostly used the right tools (node:fs globSync in 15+ gates, mdast/micromark in the markdown gates), but a handful of stragglers hand-rolled what a sibling gate already did with an existing dependency or builtin:
- Duplicated fence scanners.
scripts/md-fences.ts(~55 lines, consumed bydoc-typecheck.ts) andextractEquivBlocksinscripts/verify-type-equiv.ts(~39 lines) were two copies of the same regex line-scanner for fenced code blocks, whilescripts/verify-mermaid.tsalready extracted fences by visiting mdastcodenodes — andmarkdownProseLinesinscripts/markdown.tsitself parsed to mdast but then hand-tracked fence state with a second regex. The regex scanners only recognized backtick fences at column 0, so they silently disagreed with the mdast-based gates on tilde and indented fences. - Hand-rolled argv parsing.
parseOptionsinscripts/publint-all.tsand its near-identical copy inscripts/verify-built-package-invariants.mjs(~26 lines) stepped argv indexes manually, while sibling scripts (verify-runtime-closure.ts,build-exe-for-python-sdk.ts,packages/sdk/scripts/src/args.ts) already used thenode:utilparseArgsbuiltin. - Hand-rolled directory walks. Five sites re-derived nested
readdirSyncwalks thatglobSynccovers:verify-runtime-closure.ts(packages + vendor manifests),dev-web.tsdiscoverPluginDirs,verify-package-paths.tsrealPackageNames,verify-client-domain-graph.tslistSources, andpublint-all.tsaddPath(~55–65 lines total).scripts/package-invariants.tsshows the one-lineglobSynctemplate.
No new dependency was needed anywhere; every replacement is an existing devDep or a Node builtin.
Decision
- A shared mdast fence helper,
markdownFencesinscripts/markdown.ts, visitscodenodes for the language, full info string, body, and 1-based opening-fence line;doc-typecheck.tsandverify-type-equiv.tsextract fences through it.md-fences.tsand the duplicatedextractEquivBlocksscanner are deleted, andmarkdownProseLinesderives fenced lines from the parsedcodenodes' positions instead of a second regex. - Both CLIs parse argv via
parseArgs; unknown options and missing values still fail loud, withparseArgs's own error text instead of the bespoke usage strings. - The five straggler walks use
globSync. The walks incheck-workspace-constraints.tsandclean.tsstay: they need dirent-level detail to diagnose malformed trees, which glob-by-pattern cannot report.
Alternatives considered
- A new glob/walking dependency (
tinyglobby,fdir). Rejected: the builtin already won repo-wide; these were stragglers, not a gap. p-mapforpublint-all.ts's ~19-line ordered worker pool. Deliberately left out: one new devDep for one small deletion is at the edge of the dependency policy bar, and the pool's requirements (bounded workers, deterministic order, env override) are documented in the parallel-gates note. Fold it in only ifp-mapearns a second consumer.- Leaving the fence scanners. Rejected: two drifting copies of a parser beside a third correct implementation is exactly the duplication the shared
markdown.tshelper exists to prevent, and the column-0-backtick-only limitation was a latent inconsistency between sibling gates.
Consequences
- One fence parser: every markdown gate now classifies fences through mdast, so tilde, indented, and 4-backtick container fences behave identically everywhere. The docs tree contained no fence shape the regex scanners mishandled, so gate results are unchanged on the tree that landed the swap:
pnpm run doc-syncand each rewritten gate ran before and after with byte-identical output (doc-typecheckblock/opt-out counts,verify-type-equivmatch counts,publint,verify-built-package-invariants,verify-runtime-closure,verify-package-paths,verify-client-domain-graph, and both package-README prose gates). verify-type-equivstill rejects an unterminated type-equivalence fence: mdast silently closes an unterminated block at end-of-file (its comparisons could then pass), so the shared helper reports whether a closing delimiter exists and the gate errors on an unclosed block, preserving the removed scanner's rejection. Thedoc-typecheckscanner never had that error path.parseArgskeeps the last value of a duplicated option instead of erroring — a dev-tool edge case the tests don't pin, accepted in exchange for deleting the two bespoke parsers. (Strict mode still rejects a---prefixed token where a value is expected, matching the replaced parsers.)