Skip to content

docs(agents): drop the retired "gen:schema wipes gen:openapi" trap from three agent-facing surfaces - #11744

Merged
hotlong merged 1 commit into
mainfrom
claude/issue-11597-genschema-openapi-trap-docs
Aug 24, 2026
Merged

hotlong merged 1 commit into
mainfrom
claude/issue-11597-genschema-openapi-trap-docs

Conversation

@claude

@claude claude Bot commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Fixes #11597

Three agent-facing surfaces still taught the pre-#5371 trap "gen:schema's cleanup wipes gen:openapi's output" and prescribed a gen:openapi rerun to recover from it. The trap is gone; the docs are not. This deletes the stale clauses.

Current behavior, from the source

build-schemas.ts no longer removes the output directory itself. Its clean routes through clearOwnedOutputs(), which skips every entry declared in FOREIGN_JSON_SCHEMA_ARTIFACTS — and openapi.json is the one entry there.

  • packages/spec/scripts/lib/json-schema-out-dir.ts:70-72 — FOREIGN_JSON_SCHEMA_ARTIFACTS maps openapi.json to 'gen:openapi (packages/spec/scripts/build-openapi.ts)'.
  • packages/spec/scripts/lib/json-schema-out-dir.ts:121-125 — the clean loop: an entry present in that map goes to preserved and is skipped, never removed.
  • packages/spec/scripts/build-schemas.ts:297-323 — the clean calls clearOwnedOutputs(OUT_DIR, …) instead of the old fs.rmSync(OUT_DIR, { recursive: true }), and line 318 prints ↳ kept openapi.json — owned by gen:openapi (…) (#5371) for each spared entry.
  • The fix commit is 83f86077cd — "fix(spec): gen:schema clears only its own outputs, sparing gen:openapi's openapi.json". (The card cites this as gen:schema rmSync 整个 json-schema/ 会顺手抹掉 gen:openapi 的产物,rest 的 openapi 路由测试随后 503 假红——check:generated 原地跑 build-schemas 也触发 #5371; the commit subject carries (#6200). Both refer to the same landed change; 83f86077cd is an ancestor of this branch's base dd4113ec.)

Pinned in two layers, both already in the tree:

No destructive generation command was run to establish this — the evidence above is read from the current source, per the dispatch constraint.

The file list is the grep's, not the card's

The card names two files. A repo-wide grep for the claim (wipes / 抹掉 / 清场 / expected 503 to be 200, intersected with openapi / gen:schema) returns three surfaces, four occurrences:

Surface Occurrence
.claude/agents/os-dev.md :190-192 — the dispatch prompt itself
.claude/skills/pm-dispatch/references/landing-operations.md :20-21
scripts/pm/os-regen-merge.sh :28-30 header comment and :105-106

The third is not named in the card, and its second occurrence is the worst of the four: it is inside the step-4 heredoc the script prints to the operator at run time, so an agent reads the retired trap as live instruction on every merge of a generated-artifact branch.

Two remaining hits in packages/spec/CHANGELOG.md are deliberately left alone: they state a different and still-true fact (gen:docs dropping a reference page when a schema stops being emitted), and a changelog is a historical record rather than an agent-facing instruction.

Deleted rather than restated

The guarantee and its full reasoning already live at the source, in the json-schema-out-dir.ts docblock, pinned by the two tests above. Restating it in three agent prompts would spend budget on a non-trap; the prompts' job is to warn about live ones. AGENTS.md was already corrected and is untouched here.

The MERGE-state anchor trap sitting beside each deleted clause is unaffected and still true — it is kept verbatim in all three files. One knock-on: landing-operations.md introduced the pair as 顺序防两个陷阱 ("the order prevents two traps"), which becomes 顺序防的陷阱. Only one of the two was ever an ordering trap; leaving the count would have been a second false statement.

Line deltas (all reductions, nothing rewritten):

File Before After Δ
.claude/agents/os-dev.md 405 403 −2
.claude/skills/pm-dispatch/references/landing-operations.md 82 80 −2
scripts/pm/os-regen-merge.sh 112 108 −4

.claude/skills/ package total: 2595 → 2593 (−2). This is internal agent tooling under .claude/, not the customer-published skills/ directory, so the published-skills budget ruling does not apply; the numbers are reported anyway because the surface is skill-adjacent.

Governed surface — draft, human merge

Two of the three files are under .claude/** (one of them the dispatch prompt itself), so Prime Directive #14 applies: this PR stays draft, is never queued, never auto-merged, and is not flipped out of draft by an agent. The PM decides the landing path.

Verification

Gate families derived mechanically with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no path arguments — the script reads its own change set). 14 families matched; all run green, plus the 3 artifact-roster families the residue flags as "not evidence in EITHER direction" for paths under scripts/ and scripts/pm/, which were run rather than reasoned about.

Union re-run at final commit 5c49c442, exit codes captured before any pipe. Each gate's own verdict line:

✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
✓ check-agent-test-spelling: 0 violations — 351 file(s) · 3319 bare `--` token(s) · …
OK: 16 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.   [check:cross-package-test-inputs + the ci.yml node invocation]
✓ doc authoring guard: 389 files clean — no bare metadata literals.
✓ check:doc-formula-expressions (field-level `*When`, #11407): 14 predicate(s) … judged clean; 6 skipped as undeterminable.
✓ check:entry-guard: 143 scripts/ file(s) — every entry guard goes through invoked-as.mjs
✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
✓ check:parse-guard: 142 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
✓ check-governed-merges --self-test: 129 assertions …
✓ check-skill-id-lint: 21 file(s) clean (pattern /#[0-9]{3,}/g).
✓ check-skill-line-ratchet: AGENTS.md is 961 lines (ceiling 961; headroom 0).
✓ check:pnpm-filter-targets: 134/167 `--filter` occurrence(s) across 26 file(s) resolve …
✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files
✓ dispatch-gates self-test: 579 cases pass.
✓ check:pm-label-desc-cap: 21 label descriptions in scripts/pm/ensure-pm-labels.sh, all ≤100 characters
✓ where-matcher conformance holds: 295 matcher(s) discovered …

check:doc-formula-expressions first came back exit=1 on a missing @objectstack/formula/dist and then on packages/lint/dist — the unbuilt-closure trap in a fresh worktree, not a finding. It is green above only after pnpm --filter '@objectstack/lint^...' build and pnpm --filter @objectstack/lint build.

bash -n scripts/pm/os-regen-merge.sh exits 0 (the edit touches a heredoc, so the parse is load-bearing). A control-byte self-scan over the three edited files (grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]') returns no match.

Changeset: none, deliberately. Nothing published moves — .claude/** and scripts/pm/** are repo-level agent tooling, in no package's published files. skip-changeset applied.


Generated by Claude Code

…om three agent-facing surfaces

`build-schemas.ts` stopped removing the output directory itself: its clean now
routes through `clearOwnedOutputs()`, which skips every entry declared in
`FOREIGN_JSON_SCHEMA_ARTIFACTS` — and `openapi.json` is the one entry there. So
`gen:schema` has not deleted `gen:openapi`'s artifact for some time, and the run
prints `↳ kept openapi.json — owned by gen:openapi (...)` when it spares it.

Three agent-facing surfaces still taught the pre-fix trap and prescribed a
`gen:openapi` rerun that is now a no-op:

- .claude/agents/os-dev.md — the dispatch prompt itself
- .claude/skills/pm-dispatch/references/landing-operations.md
- scripts/pm/os-regen-merge.sh — both the header comment and the step-4 text
  the script PRINTS to the operator at run time

The last of these is not named in the card; a repo-wide grep for the claim is
what turned it up, and it is the copy an agent reads live.

A doc naming a fixed trap does not fail loudly — it converts every reader into a
false-positive reporter. The measured cost so far is one full card, filed and
closed premise-false on the strength of this claim.

The clauses are deleted rather than restated: the guarantee and its reasoning
already live at the source, in packages/spec/scripts/lib/json-schema-out-dir.ts,
pinned by scripts/json-schema-out-dir.test.ts and
scripts/build-schemas-check-mode.test.ts. The MERGE-state anchor trap sitting
beside each deleted clause is untouched and still true — in
landing-operations.md the surrounding "顺序防两个陷阱" became "顺序防的陷阱",
since only one of the two was ever an ordering trap.

Co-authored-by: Claude <noreply@anthropic.com>
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 24, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Aug 24, 2026
@hotlong
hotlong marked this pull request as ready for review August 24, 2026 15:10
@hotlong
hotlong added this pull request to the merge queue Aug 24, 2026
Merged via the queue into main with commit f6e182d Aug 24, 2026
32 checks passed
@hotlong
hotlong deleted the claude/issue-11597-genschema-openapi-trap-docs branch August 24, 2026 15:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Two agent-facing docs still teach the gen:schema wipes gen:openapi trap that #5371 fixed — it has already cost one filed issue

2 participants