You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
scripts/adr-index.mjs reads header fields only from an ADR's first 40 lines, so a longer status note silently empties the Supersedes cell while check:adr-index still passes #30916
Filing gate: (a) a measured defect in an internal tool, found by the objectstack#30881 dev and confirmed by contract review 6682453235 on PR #30899 (should-fix: "file a follow-up card").
scripts/adr-index.mjs: HEADER_WINDOW = 40. It reads **Key**: header fields only within the first 40 lines.
ADR-0146 after the amendment: Supersedes at line 38, Amends at 39, Builds on at 40. Two lines of headroom remain.
An earlier draft of the amendment, with a 7-line status note, pushed Supersedes in part to line 42. The regenerated index then emptied ADR-0146's Supersedes cell (ADR-0126, 0131, 0005, 0048, 0141 and 0070 became an em dash), and the run still exited 0. CI's check:adr-index runs in --report mode and always exits 0.
Expected
Header parsing reads the whole header block (up to the first heading or the first blank-line-delimited body), not a fixed line window. Or it fails loudly when a known key appears after the window.
The CI check fails when a regenerated index would drop a field that the previous index carried.
Acceptance
A self-test with an ADR whose status note pushes Supersedes past line 40: the index keeps the cell, or the tool exits non-zero.
Suggested-grade: p3 · an internal tool; no user door.
Claim: PM loop round 1
Session: session_01FEkQ5njkh3xbcDN6EtSfw7
Account: os-project-manager
Branch: claude/project-thread-timx6f (a project card thread, session_01FEkQ5of5Rharw5eu6Hvhes; the thread can push only its harness branch, a measured platform exception to claude/issue-<n>-<slug>)
Worktree: objectstack-issue-30916
Domain: domain:devx
Seat: domain:devx#3
File surface: scripts/adr-index.mjs and its self-test, the root package.jsoncheck:adr-index line only if its invocation must change, and the generated ADR index only if regeneration changes it (it should not). ⛔ No root ci.yml edit.
Container & model: S, mode:thread, model: default — dispatch-gates --tier: no path-derived mandate, effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: n/a — internal tooling defect, no user door
Thread-read: 6685367873
Premise: holds. On main 5b22ee759, scripts/adr-index.mjs still declares a fixed header window (line 103: HEADER_WINDOW = 40), and check:adr-index runs --report.
Serial constraints cleared: none in flight on scripts/adr-index.mjs; #30763 (in flight) touches scripts/pm/dispatch-gates* only.
Ruling-ref: 「p1 p2 处理完了,就可以处理 p3」 (maintainer, 2026-10-26T10:29Z) — the lane's unclaimed p1 cards are a decision card on the root CI workflow (#30461) and #31159, serialized behind PR #31204.
Order: pm-orders/devx/order-30916.md (project files), handed to the card thread in its opening message.
os-dev-report
{
"issue": 30916,
"status": "done",
"branch": "claude/project-thread-timx6f",
"pr": "#31252",
"session": "session_01FEkQ5of5Rharw5eu6Hvhes",
"premise_still_valid": true,
"summary": "scripts/adr-index.mjs (+180/-22, one file): header fields are read from the whole header block (every line before the first heading after the title), not the first 40 lines; a supersession blockquote counts only when 'superseded' sits in a bold span, because the plain whole-block rule misreads ADR-0126 line 44 (prose about a draft of ADR-0131) into a Superseded-by cell, and ending the block at '---' instead loses ADR-0065 from ADR-0080/0081. All 160 records measured; regenerated docs/adr/README.md on 5b22ee7 is byte-identical. A Date/Supersedes/Superseded-by cell the committed index carried that the regeneration empties is a dropped field: --report exits 1 with an ::error annotation (every other finding stays a warning, exit 0), --check exits 1, the write mode writes and exits 1. The CI half needs no workflow edit: the lint ADR step is continue-on-error and Lane verdict reads its outcome, so a drop reds Lint & Repo Gates. Ablations done although os-dev.md lists scripts among the not-ablated kinds; the order's 'a new negative pin is ablated' line was followed as the per-card ask (one-time proof, nothing left in the tree). No claim of my own; card assignee not touched.",
"tests": "node scripts/adr-index.mjs --self-test on d8acb85: '✓ adr-index --self-test: 60 assertions' (was 46; new batteries header block 6, dropped fields 7; drift battery report pin rewritten; floor 7 -> 9). Ablations via scripts/ablation-replace.mjs, each anchor x1 -> x0 and blob moved, restored with git diff HEAD empty: window (headerBlock -> lines.slice(0, 40)) exit 1, 6 failures; notice (old blockquote regex) exit 1, a-plain-prose-mention-is-not-a-notice; report exit (return 0) exit 1, verdict-carries-the-drop-and-report-exits-1; no drop (if (false)) exit 1, 3 failures. Incident replay on copies of the real registry with 7 lines added to ADR-0146's status note (Supersedes in part line 39 -> 46): base script write exit 0 with ADR-0146 Supersedes cell an em dash; this branch keeps 'ADR-0126, ADR-0131, ADR-0005, ADR-0048, ADR-0141, ADR-0070', index unchanged. Drop path on the real tree (ADR-0123 Supersedes cell hand-set to ADR-0099): --report exit 1, --check exit 1, write exit 1, rerun exit 0 and README restored.",
"gates": "Derived by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on d8acb85: 31 commands, each run with exit captured before any pipe, all 31 exit 0; --ran: '31 derived famil(ies) accounted for — 31 run, 0 NOT-MEASURED'. Slowest: pnpm check:pm-dispatch-gates 449 s, check-comment-mask-corpus.mjs 205 s. pnpm check:adr-index: self-test 60 green, --report OK. Scoped lint: no package touched; pnpm exec eslint --no-inline-config scripts/adr-index.mjs exit 0. Not run locally (CI-only per dispatch-gates): Plan Test Core shards step, type-check lanes (no TypeScript in the diff). CI check-runs on #31252 not yet concluded at report time. Gate record: pm-orders/devx/30916-gates-ran.txt (project files).",
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "4 — mcp__github__issue_read x3 (get, get_comments x2 on #30916), mcp__github__pull_request_read x1 (get #31252 read-back); no write tools",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create: #31252, draft, labels skip-changeset, read back identical 9394/9394 bytes, assignees none); POST /repos/objectstack-ai/objectstack/dispatches (relay comment: this os-dev-report on #30916 via post-stamped.mjs). Plus one git push (not REST).",
"open_questions": [
{
"question": "lint.yml lines 688-696 (the comment above the 'ADR index is current' step, id adr-index-current-report-only) say 'So the only red this step can show is a broken generator, never a record'. After #31252 a dropped field also reds the step. The file is outside this claim's surface, so it was not edited. Who corrects the comment?",
"options": [
"A — the seat amends the claim to add lint.yml (comment lines only) and the fix rides #31252 as a second commit",
"B — leave #31252 as is and carry the one-comment correction as a follow-up docs-only change",
"C — no change: the script header, which the comment points at, is the authority and states the new behaviour"
],
"recommendation": "A, because the stale sentence is created by this PR and a comment-only edit adds no surface (startup axis), keeps the one statement of the step's behaviour true (long-term axis), and an AI reading the step comment would otherwise conclude a record can never red it (AI-error axis); real need: the step exists and its readers are agents. Not a new gate either way. This is a seat call, not a maintainer decision."
}
],
"security_findings": "withheld",
"out_of_scope_findings": []
}
State change: pm:dispatched removed (card closed). Out of scope: #31261 filed (the lint.yml ADR index step's comment and name still say it never reds on a record; that file is governed rules text).
Activity
objectstack-fleet commentedon Nov 6, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: audit · p3 ·
domain:devx· 2026-11-06T12:58Z⛔ Not a claim.
scripts/adr-index.mjsreads**Key**:header fields only from an ADR's first 40 lines (HEADER_WINDOW = 40). A longer status note silently empties the Supersedes cell, andcheck:adr-indexstill passes in--reportmode. Found on PR docs(adr): ADR-0146 amended in place — an upgrade plan may report a .custom override that hides a vendor change, as advice only #30899's contract review.domain:devxandpm:queuekept.Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:devx#3 · os-project-manager · session_01FEkQ5njkh3xbcDN6EtSfw7
Claim: PM loop round 1
Session:
session_01FEkQ5njkh3xbcDN6EtSfw7Account:
os-project-managerBranch:
claude/project-thread-timx6f(a project card thread,session_01FEkQ5of5Rharw5eu6Hvhes; the thread can push only its harness branch, a measured platform exception toclaude/issue-<n>-<slug>)Worktree:
objectstack-issue-30916Domain:
domain:devxSeat:
domain:devx#3File surface:
scripts/adr-index.mjsand its self-test, the rootpackage.jsoncheck:adr-indexline only if its invocation must change, and the generated ADR index only if regeneration changes it (it should not). ⛔ No rootci.ymledit.Container & model:
S,mode:thread,model: default — dispatch-gates --tier: no path-derived mandate,effort: mediumClause-②: no
Metadata-protocol: none
Responsibility: n/a — internal tooling defect, no user door
Thread-read: 6685367873
Premise: holds. On main
5b22ee759,scripts/adr-index.mjsstill declares a fixed header window (line 103:HEADER_WINDOW = 40), andcheck:adr-indexruns--report.Serial constraints cleared: none in flight on
scripts/adr-index.mjs; #30763 (in flight) touchesscripts/pm/dispatch-gates*only.Ruling-ref: 「p1 p2 处理完了,就可以处理 p3」 (maintainer, 2026-10-26T10:29Z) — the lane's unclaimed p1 cards are a decision card on the root CI workflow (#30461) and #31159, serialized behind PR #31204.
Order:
pm-orders/devx/order-30916.md(project files), handed to the card thread in its opening message.Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:devx#3 · os-project-manager · session_01FEkQ5of5Rharw5eu6Hvhes
os-dev-report
{
"issue": 30916,
"status": "done",
"branch": "claude/project-thread-timx6f",
"pr": "#31252",
"session": "session_01FEkQ5of5Rharw5eu6Hvhes",
"premise_still_valid": true,
"summary": "scripts/adr-index.mjs (+180/-22, one file): header fields are read from the whole header block (every line before the first heading after the title), not the first 40 lines; a supersession blockquote counts only when 'superseded' sits in a bold span, because the plain whole-block rule misreads ADR-0126 line 44 (prose about a draft of ADR-0131) into a Superseded-by cell, and ending the block at '---' instead loses ADR-0065 from ADR-0080/0081. All 160 records measured; regenerated docs/adr/README.md on 5b22ee7 is byte-identical. A Date/Supersedes/Superseded-by cell the committed index carried that the regeneration empties is a dropped field: --report exits 1 with an ::error annotation (every other finding stays a warning, exit 0), --check exits 1, the write mode writes and exits 1. The CI half needs no workflow edit: the lint ADR step is continue-on-error and Lane verdict reads its outcome, so a drop reds Lint & Repo Gates. Ablations done although os-dev.md lists scripts among the not-ablated kinds; the order's 'a new negative pin is ablated' line was followed as the per-card ask (one-time proof, nothing left in the tree). No claim of my own; card assignee not touched.",
"tests": "node scripts/adr-index.mjs --self-test on d8acb85: '✓ adr-index --self-test: 60 assertions' (was 46; new batteries header block 6, dropped fields 7; drift battery report pin rewritten; floor 7 -> 9). Ablations via scripts/ablation-replace.mjs, each anchor x1 -> x0 and blob moved, restored with git diff HEAD empty: window (headerBlock -> lines.slice(0, 40)) exit 1, 6 failures; notice (old blockquote regex) exit 1, a-plain-prose-mention-is-not-a-notice; report exit (return 0) exit 1, verdict-carries-the-drop-and-report-exits-1; no drop (if (false)) exit 1, 3 failures. Incident replay on copies of the real registry with 7 lines added to ADR-0146's status note (Supersedes in part line 39 -> 46): base script write exit 0 with ADR-0146 Supersedes cell an em dash; this branch keeps 'ADR-0126, ADR-0131, ADR-0005, ADR-0048, ADR-0141, ADR-0070', index unchanged. Drop path on the real tree (ADR-0123 Supersedes cell hand-set to ADR-0099): --report exit 1, --check exit 1, write exit 1, rerun exit 0 and README restored.",
"gates": "Derived by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack on d8acb85: 31 commands, each run with exit captured before any pipe, all 31 exit 0; --ran: '31 derived famil(ies) accounted for — 31 run, 0 NOT-MEASURED'. Slowest: pnpm check:pm-dispatch-gates 449 s, check-comment-mask-corpus.mjs 205 s. pnpm check:adr-index: self-test 60 green, --report OK. Scoped lint: no package touched; pnpm exec eslint --no-inline-config scripts/adr-index.mjs exit 0. Not run locally (CI-only per dispatch-gates): Plan Test Core shards step, type-check lanes (no TypeScript in the diff). CI check-runs on #31252 not yet concluded at report time. Gate record: pm-orders/devx/30916-gates-ran.txt (project files).",
"dogfood_battery": "n/a — no
!in the PR title and no (narrowing) arm","mcp_calls": "4 — mcp__github__issue_read x3 (get, get_comments x2 on #30916), mcp__github__pull_request_read x1 (get #31252 read-back); no write tools",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create: #31252, draft, labels skip-changeset, read back identical 9394/9394 bytes, assignees none); POST /repos/objectstack-ai/objectstack/dispatches (relay comment: this os-dev-report on #30916 via post-stamped.mjs). Plus one git push (not REST).",
"open_questions": [
{
"question": "lint.yml lines 688-696 (the comment above the 'ADR index is current' step, id adr-index-current-report-only) say 'So the only red this step can show is a broken generator, never a record'. After #31252 a dropped field also reds the step. The file is outside this claim's surface, so it was not edited. Who corrects the comment?",
"options": [
"A — the seat amends the claim to add lint.yml (comment lines only) and the fix rides #31252 as a second commit",
"B — leave #31252 as is and carry the one-comment correction as a follow-up docs-only change",
"C — no change: the script header, which the comment points at, is the authority and states the new behaviour"
],
"recommendation": "A, because the stale sentence is created by this PR and a comment-only edit adds no surface (startup axis), keeps the one statement of the step's behaviour true (long-term axis), and an AI reading the step comment would otherwise conclude a record can never red it (AI-error axis); real need: the step exists and its readers are agents. Not a new gate either way. This is a seat call, not a maintainer decision."
}
],
"security_findings": "withheld",
"out_of_scope_findings": []
}
Generated by Claude Code
objectstack-fleet commentedon Nov 7, 2026
domain:devx#3 · os-project-manager · session_01FEkQ5njkh3xbcDN6EtSfw7
Landed 2026-11-07T20:28Z · PR #31252 merged through the merge queue at 2026-11-07T20:26Z, as
bdefd49f30ed69bad7d9356a9ba66f8ad2ec9591.merged: true, merge commitbdefd49f30, head reviewedd8acb85f71(ACCEPT on the PR)completedbyFixes #30916State change:
pm:dispatchedremoved (card closed). Out of scope: #31261 filed (thelint.ymlADR index step's comment and name still say it never reds on a record; that file is governed rules text).