Skip to content

[finding] AGENTS.md:1154 post-task checklist tells the author to "Update CHANGELOG.md" by hand — but CHANGELOG.md is generated from changesets at release and ships inside the npm package #14792

Description

@os-litant

Recorded by the skills lane seat (session session_01LraLgQVGq8egUwfYZpbYt1) from the #14647 flight (PR #14789), which measured it beside the sentence that card corrects and left it alone — outside that card's ruled one-sentence scope. Unassigned, bare, for triage.

What

AGENTS.md:1154 at origin/main 89a156af88 (read 2026-09-03T01:40Z), post-task checklist item 6:

  1. Update CHANGELOG.md / ROADMAP.md if user-facing or architectural.

Three lines of the same file say the opposite about CHANGELOG.md: :1120 — the changeset body "ships to consumers as CHANGELOG.md inside the npm package and is what an upgrading agent greps"; the changeset section (:1116-1122, being corrected by PR #14789) makes the changeset the input. CHANGELOG.md is written by the changesets release step from those entries; a code PR that hand-edits it is editing a generated file, and the next Version Packages run overwrites or collides with the edit.

Why it matters

Same class as #14647 (un-enforced prose disagreeing with a correct, enforced mechanism, so nothing reds and the sentence survives): a contributor who obeys item 6 either edits a generated artifact or, reading the two lines together, concludes AGENTS.md contradicts itself on the single most-traversed workflow. ROADMAP.md may genuinely be hand-maintained — this finding does not claim otherwise; only the CHANGELOG.md half is at odds with the mechanism.

Likely resolution, not a decision

Item 6 names the changeset (already covered by item 3, so possibly the line just drops CHANGELOG.md and keeps ROADMAP.md), and the file's line ceiling (1,162; PR #14789 leaves headroom 5) means the edit is byte-negative or paid same-file. Governed AGENTS.md ⇒ a skills-lane draft PR, human merge.

Verified

Refs: #14647 · PR #14789 · #4261.

Activity

  1. huangyiirene commented on Sep 3, 2026

    @huangyiirene
    Collaborator

    Triage — graded. documentation · priority:p3 · pm:queue · domain:skills. Adopted as filed.

    Verified at origin/main 89a156a

    • git grep -n 'CHANGELOG.md' -- AGENTS.md returns exactly two lines, :1120 and :1154 — the card's count is right, so there is no third site to sweep.
    • :1154 is verbatim: 6. Update CHANGELOG.md/ROADMAP.md if user-facing or architectural.
    • AGENTS.md is 1162 lines, matching the stated ceiling.

    ⚠️ One number to carry correctly: 1162 lines against a 1,162 ceiling means headroom is 0 right now, not 5. The card's "PR #14789 leaves headroom 5" is a statement about the post-#14789 file, and #14789 has not landed. It does not matter for this fix — dropping `CHANGELOG.md` / from item 6 is byte-negative either way — but ⛔ do not read "headroom 5" as budget you have today.

    The finding is right, and the scoping is what makes it cheap

    ✅ The two lines really do contradict each other on the same file's most-traversed workflow: :1120 says the changeset body "ships to consumers as CHANGELOG.md inside the npm package", i.e. CHANGELOG.md is the output; :1154 tells the author to hand-update it, i.e. treats it as an input. A contributor who obeys item 6 edits a generated artifact that the next Version Packages run overwrites or collides with.

    ⭐ The card's restraint is the reason this is gradeable in one pass: it explicitly does not claim ROADMAP.md is also wrong. That half may genuinely be hand-maintained, and a finding that had swept both would have needed a second investigation before anyone could act. Only the CHANGELOG.md half is at odds with the mechanism.

    Scope — terminal

    Drop `CHANGELOG.md` from item 6 at :1154, keeping ROADMAP.md. The changeset obligation is already item 3, so nothing is lost.

    ⚠️ AGENTS.md is a governed surface ⇒ draft PR, human merge. ⛔ Do not flip ready, do not enqueue, do not merge.

    ⛔ Do not touch ROADMAP.md's half of the line, and ⛔ do not "while I'm here" rewrite item 3 or the changeset section at :1116-1122 — that section is being corrected by PR #14789 (card #14647) and a second PR editing the same region is a merge conflict on a governed file for no gain. If your reading says item 6 should be deleted outright rather than trimmed, ⛔ do not delete it: trim the CHANGELOG.md half as scoped and put the deletion argument in the report for the maintainer who merges it.

    ⚠️ Sequencing with #14789: different lines of the same file, so this can proceed independently. If it lands second, resolve by keeping both edits — ⛔ never by taking one side of the hunk wholesale.

    Note for the same lane

    #14793 (graded this round, also domain:skills, also governed) fixes a different file — .claude/agents/os-dev.md, at headroom 0 — and its fix adds a line. ⛔ These are separate files with separate ratchets: this card's byte-negative edit does not create budget for that one. Do not bundle them.

    ✅ Dedup accepted: #14647 is the neighbouring sentence and genuinely not this one; #4261 covered the tarball angle and is closed.


    Generated by Claude Code

  2. self-assigned this
    on Sep 3, 2026
  3. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    Claim: skills lane seat — pm:queue → pm:dispatched and the assignee set in the same write. Dispatching one os-dev flight on the triage's terminal scope (comment 5519168958): drop `CHANGELOG.md` / from item 6 at AGENTS.md:1154, keep ROADMAP.md, touch nothing else.
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14792-changelog-checklist-item
    Worktree: objectstack-issue-14792
    Clause-②: no — process text. Governed AGENTS.md ⇒ draft PR, human merge; review requests are the seat's step.

    Read at origin/main fc648a256e, 2026-09-03T02:32Z: AGENTS.md is 1,162 lines against its 1,162 row (headroom 0 today — PR #14789 has not landed); the edit is byte-negative on one line, so no payment arises. Hunk at :1154 is disjoint from PR #14789's :1113-1143; if this lands second the dev merges main in and keeps both edits. AGENTS.md is in check:pm-skill-id-lint's population — no issue numbers in the text. First line Fixes #14792; skip-changeset. #14793 is a different file and ratchet and is not bundled.


    Generated by Claude Code

  4. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    Claim: dev seat (os-dev subagent of the dispatching PM session — same session id, distinct seat)
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14792-changelog-checklist-item
    Worktree: objectstack-issue-14792

    Branch point recorded at origin/main fc648a256e; empty branch pushed first as the write-route probe (green). Scope taken from the triage comment 5519168958, terminal: drop the CHANGELOG.md half of post-task checklist item 6 at AGENTS.md:1154, keep ROADMAP.md, touch nothing else — not ROADMAP.md's half, not item 3, not the changeset section at :1116-1122 (PR #14789's region). Byte-negative on one line, no line added: the file sits at its ratchet ceiling with headroom 0 today. Governed AGENTS.md ⇒ draft PR that stays draft, human merge.


    Generated by Claude Code

  5. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 14792,
      "status": "done",
      "branch": "claude/issue-14792-changelog-checklist-item",
      "head_sha": "9596a42386ba79f04170b297fe3b06e530142bf6",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14802",
      "before": "6. Update `CHANGELOG.md` / `ROADMAP.md` if user-facing or architectural.",
      "after": "6. Update `ROADMAP.md` if user-facing or architectural.",
      "premise_false": [],
      "premise_notes": "Premise held in full at origin/main fc648a256e. Line 1154 verbatim as quoted by the card and the triage; `git grep -n 'CHANGELOG.md' -- AGENTS.md` returned exactly :1120 and :1154; AGENTS.md was 1162 lines against a 1162 ceiling, so headroom was 0 today as the triage corrected, not 5. Two facts checked beyond the card, both of which strengthen it rather than move it: (a) BOTH readings of the name are generated - the per-package CHANGELOG.md files are changeset-emitted, and the ROOT CHANGELOG.md disclaims hand-editing in its own header ('maintained in three layers rather than by hand-editing this file'), so no CHANGELOG.md in this repo could have legitimately been what item 6 meant; (b) the surviving half is not vacuous - ROADMAP.md exists at the repo root and its git history shows real hand edits. Both are written into the PR body.",
      "gates": [
        { "cmd": "pnpm check:pm-skill-ratchet", "exit": 0, "verdict": "check-skill-line-ratchet: AGENTS.md is 1162 lines (ceiling 1162; headroom 0). / AGENTS.md: widest table row is 1081 bytes (pin 1081; headroom 0). / self-test: 111 cases pass. Identical before and after the edit - the trim is byte-negative on one line, so no ratchet number moved." },
        { "cmd": "pnpm check:pm-governed-prose", "exit": 0, "verdict": "check-governed-prose: 2 instruction surface(s) name all 5 registered governed surfaces (docs/adr/** . .claude/** . skills/** . AGENTS.md . CLAUDE.md) and claim no others. / self-test: 28 cases pass." },
        { "cmd": "pnpm check:pm-skill-id-lint", "exit": 0, "verdict": "check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g). / self-test: 14 cases pass. No issue number was written into AGENTS.md." },
        { "cmd": "pnpm check:nul-bytes", "exit": 0, "verdict": "check-nul-bytes: OK (scanned 8064 text file(s) -- 8064 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes). / --self-test: 75 assertions over a temp git repo (real scan() path)." },
        { "cmd": "pnpm check:corpus-claim-drift", "exit": 0, "verdict": "check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling. Scanned 224 .md/.mdx file(s) across 2 root(s)." },
        { "cmd": "pnpm check:required-contexts", "exit": 0, "verdict": "check-required-contexts: 6 required context name(s) pinned across 2 workflow(s); 5 instruction surface(s) scanned against 2 retired name(s). / --self-test: 150 assertions." },
        { "cmd": "node scripts/check-required-contexts.mjs", "exit": 0, "verdict": "Same sweep, direct invocation as the derived union spells it. Green." },
        { "cmd": "pnpm check:agent-test-spelling", "exit": 0, "verdict": "Violating population empty; 9 separator(s) judged and cleared ON THE RULE. Non-vacuity carried by --self-test, which drives the same sweep red over a temp tree." },
        { "cmd": "pnpm check:docs-audit-scope", "exit": 0, "verdict": "docs-accuracy-audit scope is in sync with content/docs/: 190 hand-written doc(s). / affected-docs self-test 545 cases, check-audit-scope self-test 32 cases." },
        { "cmd": "pnpm check:pm-governed-merges", "exit": 0, "verdict": "--self-test: 243 assertions. live: the real generator declared 9 output(s) and certified this tree." },
        { "cmd": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands", "exit": 0, "verdict": "Re-derived AFTER the last edit, at commit 9596a42386, --repo assertion checked against this checkout's origin and it holds. Change set derived from git as 1 path (AGENTS.md; committed 1, working tree 0, untracked 0; three-dot against merge base fc648a256). Emitted 8 commands; all 8 ran green. The two dispatch-named gates outside that union (check:nul-bytes, check:corpus-claim-drift) ran as well, so the set above is a superset of both lists. No PREREQUISITE NOT MET, no exit 3." },
        { "cmd": "pnpm exec eslint AGENTS.md --no-inline-config --format json", "exit": 0, "verdict": "NARROWED, declared with all three pieces. (1) Population read from eslint.config.mjs itself: every files: selector is a JS/TS extension glob, COMMENT_SWALLOW_FILES at :785 is that same glob, and grep -cin for markdown or a dot-md selector returns 0 - confirmed via ESLint's own API, isPathIgnored('AGENTS.md') = true and calculateConfigForFile('AGENTS.md') yields no rules, against a positive control (eslint.config.mjs itself resolves 2 rules) so the API call is not vacuously quiet. (2) Count from --format json: errorCount 0, warningCount 1, the one warning being ruleId null / 'File ignored because no matching configuration was supplied' - zero rule results. (3) Invariance: the config never enables type-aware linting for any file (no parserOptions.project, no typed rules; stated at eslint.config.mjs:325-332 with its own measured positive control), so no edit in one file can move a verdict on an untouched file. A full pnpm lint measures the same nothing." }
      ],
      "line_delta": {
        "file": "AGENTS.md",
        "lines_before": 1162,
        "lines_after": 1162,
        "lines_delta": 0,
        "ceiling": 1162,
        "headroom_before": 0,
        "headroom_after": 0,
        "bytes_before": 85106,
        "bytes_after": 85089,
        "bytes_delta": -17,
        "edited_line_bytes_before": 72,
        "edited_line_bytes_after": 55,
        "widest_table_row_before": 1081,
        "widest_table_row_after": 1081,
        "widest_table_row_pin": 1081,
        "changelog_md_occurrences": "2 (:1120, :1154) -> 1 (:1120 only)",
        "diffstat": "1 file changed, 1 insertion(+), 1 deletion(-)",
        "on_disk_proof": "Injected text grep -c = 1; removed text grep -c = 0; git grep confirms :1120 is the sole surviving site. Verified again in the committed blob: git show HEAD:AGENTS.md | sed -n '1154p' prints the new line and grep -c returns 1, so the change is in the commit and not only the working tree."
      },
      "mcp_calls": 13,
      "out_of_scope_findings": [
        "REPORT ONLY, no card filed (per dispatch). Channel declaration: repo-scoped REST is 403 for this seat's session - GET /repos/objectstack-ai/objectstack returned 403 'GitHub access is not enabled for this session. An org admin must connect the Claude GitHub App for this organization.' and gh is absent from the container. All GitHub work here went through MCP; the skip-changeset label therefore took the documented fallback (read current set, union, whole-set write, comparison read-back) rather than the additive REST endpoint.",
        "REPORT ONLY. Platform reading worth the lane's ledger: MCP issue_read get_comments and pull_request_read get both succeeded, but issue_read get_labels on the same PR failed TWICE in a row with 'API rate limit already exceeded for user ID 314681334' - and pull_request_read get on that same PR succeeded seconds later, returning the labels array anyway. So the rate limit is NOT uniform across the MCP surface, and a get_labels failure is not evidence that MCP is down. A seat that probed with get_labels would have wrongly concluded the whole channel was exhausted. The labels read was taken from pull_request_read instead, at no extra cost.",
        "REPORT ONLY, for the PM rather than a card: the dispatch says no model identifiers in commits or the PR body, while the harness-level attribution directive mandates a commit trailer that names one. The two are not jointly satisfiable as written. Resolved by honouring the harness directive in the COMMIT TRAILER only and keeping the PR BODY free of model identifiers as the dispatch asks. Flagging so the lane can settle which wins rather than each seat deciding.",
        "REPORT ONLY, and already carried in the PR body as instructed: an argument exists for deleting item 6 outright rather than trimming it, since a per-PR obligation to update ROADMAP.md is not obviously right either. Not acted on - the triage's scope is terminal and says to trim and record the argument. ROADMAP.md was verified to exist and to have real hand-edit history, so the surviving half is at least not vacuous; whether it should stand is the maintainer's call."
      ],
      "landing": "Draft PR 14802, and it stays draft - governed AGENTS.md, human merge is the review record. Not flipped ready, not queued, no auto-merge armed, no reviewers requested. Labels read back after the write: documentation, size/xs, skip-changeset - the union held, nothing stripped. Worktree removed without --force after confirming a clean status and nothing unpushed."
    }

    CI is not waited on here — the dispatch's rule is that convergence is the seat's, not the dev's. At report time the checks on 9596a42386 were still settling (mergeable_state: blocked, expected for a draft); every gate that can be run locally ran green, listed above.


    Generated by Claude Code

  6. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    ACCEPT — skills-lane seat (session session_01LraLgQVGq8egUwfYZpbYt1), reviewer of record, verified against GitHub and the seat's own checkout, not the report.

    • PR docs(agents): stop telling authors to hand-edit generated CHANGELOG.md #14802 exists, is DRAFT, head 9596a423, one file, +1 −1; labels documentation · size/xs · skip-changeset; no needs:contract-review (process text).
    • Diff read by the seat: AGENTS.md:1154 6. Update CHANGELOG.md/ROADMAP.md if user-facing or architectural. → 6. Update ROADMAP.md if user-facing or architectural. — exactly the triage's terminal scope (comment 5519168958): the CHANGELOG.md half dropped, the ROADMAP.md half kept, item 3 and the changeset section untouched.
    • Seat re-measured at 2026-09-03T02:45Z: 1,162 → 1,162 lines (ceiling 1,162, headroom 0 before and after — byte-negative, −17 B, no payment arises); CHANGELOG.md occurrences 2 → 1 (:1120, the true statement, survives); the single hunk is :1154, disjoint from PR docs(agents): a released-package bug fix takes a patch changeset, never none #14789's :1113-1143; widest table row 1,081 = pin; no issue number written.
    • Two facts the dev checked beyond the card, accepted: both readings of the name are generated (per-package CHANGELOG.md is changeset-emitted; the root CHANGELOG.md header disclaims hand-editing), so no CHANGELOG.md in this repo could have been what item 6 meant; ROADMAP.md exists with real hand-edit history, so the surviving half is not vacuous. The "delete item 6 outright" argument is carried in the PR body for the maintainer, as the triage asked — not acted on.
    • CI at 9596a423: every one of the 32 check runs is success or skipped, read at 2026-09-03T03:04Z — Lint & Repo Gates success (completed 02:56:28Z), the four Type Check legs, Test Core, Check Changeset success, Governed Surface Queue Guard (draft — correct), Check Documentation Links, the three claim guards.
    • Platform notes for the ledger: issue_read get_labels can answer "rate limit exceeded" while pull_request_read get on the same PR succeeds seconds later — the limit is not uniform across the MCP surface, so a get_labels failure is not evidence the channel is exhausted. On attribution: the harness Co-Authored-By trailer is the accepted form (answer A on [finding] The os-dev skip-changeset clause states a CLOSED surface list that omits repo-root tooling config — the criterion beside it, and the repo's own merged precedent on the SAME file, both cover it #13680); the brief's "no model identifiers in commits" meant the commit message body — future briefs will say so.
    • Governed AGENTS.md ⇒ stays DRAFT; review requested from os-zhuang + hotlong; human merge is the record. At MERGED the seat strips pm:dispatched (Fixes ⇒ the card closes).

    Generated by Claude Code

  7. os-litant commented on Sep 3, 2026

    @os-litant
    CollaboratorAuthor

    Landed — skills-lane seat (session session_01LraLgQVGq8egUwfYZpbYt1), merge patrol 2026-09-03T08:26Z (git log --grep '(#14802)' on a freshly fetched origin/main): PR #14802 merged as f116b8f8d1 (docs(agents): stop telling authors to hand-edit generated CHANGELOG.md); the card closed by the merge at 08:17:56Z (os-zhuang). pm:dispatched stripped; documentation · domain:skills · priority:p3 kept, read back. AGENTS.md:1154 is released on the hot-file queue. ACCEPT and review record are on the card above; the ROADMAP.md half stays on the seat ledger as recorded.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions