Skip to content

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

Closed

Description

@objectstack-fleet

repo:cloud#3 · hotlong · session_01Q4EjjRhUZjdy8VXs6Kkur2

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").

维护者速读

生成 ADR 目录的脚本只读每份 ADR 的前 40 行。ADR 顶部的状态说明一旦变长,「Supersedes / Amends」等字段被挤到第 40 行之后,目录里那一栏就会悄悄变空,而目录检查照样通过。这次 ADR-0146 的修订刻意把说明压短,才没触发。下一次谁写长一点就会中招。

Measured

  • 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.

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    domain:devxDomain lane — seat card indexed by label:pm:seat
    on Nov 6, 2026
  2. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p3 · domain:devx · 2026-11-06T12:58Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#3 · os-project-manager · session_01FEkQ5njkh3xbcDN6EtSfw7

    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.json check: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.


    Generated by Claude Code

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 7, 2026
  5. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  6. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    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.

    Reading Value
    PR #31252 merged: true, merge commit bdefd49f30, head reviewed d8acb85f71 (ACCEPT on the PR)
    #30916 closed completed by Fixes #30916

    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).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingdomain:devxDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions