Repository navigation
scaffold-aip reads vendored specs (#1207) - #1622
Conversation
…ing checkout and the drift-check temp tree
There was a problem hiding this comment.
Summary
Refactors scaffold-aip.mjs to read exclusively from the vendored specs/resources tree (no sibling ../agentproto checkout, no .mdx frontmatter), makes missing drafts and broken external $refs fail closed, and deletes the now-dead temp-tree staging path from check-spec-drift.mjs. New tests cover isolation from a poisoned sibling checkout, flag validation, and fail-closed ref handling.
Changeset
| package | bump | reason |
|---|---|---|
| (none) | — | Root-level scripts/ only; no workspace package changed (confirmed via scripts/list-changed-packages.mjs) |
Findings
Correctness
- ✅ Fail-closed on broken external refs (scripts/scaffold-aip.mjs:1091) is the right call vs. the old warn-and-stub
{}— silent any-typing could mask real spec drift. - ✅ Strict flag parsing (
unknown flag/requires a value, exit 2) prevents silently swallowing typos like--slugs. - ✅
checkSpecDriftno longer needs thenormalizeSchemaSrcstripper; direct stdout comparison is valid since the scaffolder now emits deterministically from the vendored draft.
Test coverage
- Good:
scripts/scaffold-aip.test.mjsexercises the real scaffolder as a subprocess in a non-git fixture tree, including the sibling-checkout isolation proof (#1207). All 10 tests pass locally (afternpm install; the fixture symlinksnode_modules, so they fail with ERR_MODULE_NOT_FOUND in a bare checkout — worth noting for CI ordering, but CI installs deps first).
Nitpicks (non-blocking)
- scripts/scaffold-aip.mjs:129 —
let definitionInterface/let zodSchemaExprcan beconstnow that both are unconditionally assigned. - scripts/check-spec-drift.mjs:100 and both test files are missing a trailing newline (the old files had one); avoids noise in future diffs.
Verdict
LGTM ✅ — Tightens provenance (vendored specs only), replaces two silent-failure modes (sibling-checkout reads, broken-ref stubbing) with hard errors, and ships solid subprocess-level tests. CI/scripts-only change; no package bumps or changeset required.
🤖 @agentproto-bot — review · legacy fallback (api-key) · run 36629141880 · sha eb72d19a5ffee31c90fd6657f31d0b5b37d53f94
Closes #1207. Supersedes #1537 — credit @charan-rathore for the original approach (reading the vendored tree instead of the sibling checkout); this lands the same idea rebased on the post-#1554 world.
Why
scripts/scaffold-aip.mjswas the only ts consumer still reaching for a sibling../agentprotocheckout (SPEC_DIR = resolve(TS_ROOT, "../agentproto/specs")) — which doesn't exist in checkouts/CI.scripts/check-spec-drift.mjsstaged an entire temp tree (copy of the scaffolder + symlinked specs + a stub mdx) purely to work around that sibling path.What
specs/resourcestree (RESOURCES_DIR, override with--resources-dir). gray-matter + theaip-<N>.mdxfrontmatter read are gone —title/descriptioncome from the JSON draft'stitle/descriptionfields (generated templates keep their own gray-matter import; untouched). Strict arg parsing: unknown flags, missing flag values, and missing required flags all exit 2. A missing JSON draft is a hard error (thehasSchemaTODO-stub fallbacks are deleted).walkExternalnow throws on a broken external$ref(message includes the ref and the mapped file path) instead of warn-and-replace-with-{}.cwd: ROOTand diffsstdoutagainst the checked-inschema.ts—stageTempTree,specDirCandidates,KNOWN_CODEGEN_MISSING,normalizeSchemaSrcand their imports are deleted. Coverage stays sandbox-only (widening to the other 27 packages is a separate later PR).Tests
New
scripts/scaffold-aip.test.mjs(8 cases, node --test): schema-only emission from the vendored draft, full scaffold in a fixture tree with a poisoned sibling../agentproto/specs/aip-99.mdx(WRONG SIBLINGnever appears in stdout — the sibling is never read),--resources-dirnonexistent → exit 2, explicit--resources-dir→ same result as default, unknown flag → 2, valueless flag → 2, missing required flags → 2, broken external ref → non-zero exit with no "replacing with empty schema".Note on the brief's title assertion:
--schema-onlyoutput renders the draft's rootdescription(.describe(...)) but not thetitle, so theTest Doctitle is asserted on the full-scaffold path'sspec:status line instead (asserted in the isolation test, which doubles as the sibling-proof). Changing the schema-only header would have regressed sandboxschema.tsbyte-drift, which this PR must not touch.scripts/check-spec-drift.test.mjsrewritten: passes on the real sandbox draft, fails with/not found/for a doctype with no vendored draft.How verified
node --test scripts/scaffold-aip.test.mjs→ exit 0 (8/8)node --test scripts/check-spec-drift.test.mjs→ exit 0 (2/2)node --test scripts/sync-specs.test.mjs→ exit 0pnpm check:spec-drift→ exit 0 ("spec↔codegen in sync for @agentproto/sandbox"); regen of the sandbox schema.ts is byte-identical to the checked-in filepnpm test→ exit 0,pnpm check-types→ exit 0 (fresh worktree, no../agentprotosibling present)No changeset: the diff touches
scripts/**only (not a publishable package);pnpm changeset:aiconfirmed "No @agentproto/* packages changed".🤖 @agentproto-bot — PR · session
sess_dbebb183· pi · modelopenrouter/z-ai/glm-5.3-flash· hostmac.home· cwdagentproto/f1207-wt