Skip to content

docs(agents): stacked PR series are not a supported working form - #16743

Merged
hotlong merged 4 commits into
mainfrom
claude/issue-16149-stacked-series-not-supported
Sep 8, 2026
Merged

docs(agents): stacked PR series are not a supported working form#16743
hotlong merged 4 commits into
mainfrom
claude/issue-16149-stacked-series-not-supported

Conversation

@hotlong

@hotlong hotlong commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #16149

Records the maintainer's ruling (director seat, decision batch #66; maintainer reply, verbatim: 「同意」) as one AGENTS.md paragraph: a stacked PR series is not a supported working form in this repository. Per that ruling no gate rule and no merge-policy change is made — items 1 and 2 of the card are the price of an unsupported form. Item 3 is a separate defect under active repair and is deliberately not described here; see Why item 3 is not in the paragraph.

What landed

One paragraph in Multi-agent working discipline, as an indented continuation of numbered rule 2 — the rule that already reads "Branch off main". That is the exact sentence the ruling qualifies, so a reader looking up branching policy meets both in one place. Filing it under §7 instead would have put a branching rule under landing.

The paragraph states the declaration, one clause for each of the two structural costs, the trunk-branch workaround with both recorded remedies, and the boundary (no gate, no policy change).

Why item 3 is not in the paragraph

The ruling grades item 3 — heavy CI never running on a PR whose base is a feature branch — as "a defect independent of stacking", and splits it out to its own domain:devx card, #16482, to be fixed. It is therefore not a price of an unsupported form, and writing it into AGENTS.md as an inherent property of stacking would contradict the ruling twice over: it would mis-grade a defect as an accepted cost, and the sentence would become false the moment that card lands, rotting in place like any other restated fact.

Only the two costs the ruling assigned here are stated: squash landing destroys the ancestry link, so every descendant pays a rebuild lap per landing; and a breaking changeset's ADR-0087 disposition is base-relative, so a stacked card's two bases demand contradictory markers. No hedged substitute ("CI does not run on these yet") was used either — that wording has the same expiry date.

Why it is self-contained instead of a pointer to the card

The ruling says "pointing at this card for the measured costs and workarounds". That form is not available in this file, and the constraint is mechanical, not stylistic:

  • AGENTS.md is in check-skill-id-lint.mjs's scan set (EXTRA_FILES = ['.claude/agents/os-dev.md', 'AGENTS.md']), pattern /#[0-9]{3,}/g. A card number in this file is a hard red — which is also why no pointer to the split-out devx card appears in the paragraph.
  • That gate's own header states the substitute: "Incident learnings are distilled into the rules themselves as self-contained lessons (failure mode + discipline + boundary) … a rule's provenance lives in the PR that landed it."

So the pointer lands in the allowed place — this PR body, which carries Fixes #16149 — and the file carries the lesson. The measured numbers stay on the card, as the ruling intends.

Fold payment — paid by deleting content

AGENTS.md was at its ratchet ceiling with no headroom, so the paragraph was paid for inside the same file. No re-wrapping was used to buy lines; the payment is deleted content.

What was cut: the fenced ADR-0087 marker block in Post-Task Checklist item 3 (6 lines of block plus 4 lines of surrounding prose, rewritten to 3).

Where every cut line still has a home:

cut content where it still lives
the four adr-0087: marker spellings FIXIT in scripts/check-adr-0087-registration.mjs — printed on every failure, and it prints seven categories, not four
registered / unpublished / already-registered / no-migration-prescription category semantics ADR-0087, addendum of 2026-08-13 — named by that same FIXIT output
"add exactly one marker", the gate name, the CI step name kept in place, all three, in the rewritten 3-line paragraph

The block was not merely duplicated — it was a drifted copy listing 4 of the gate's 7 categories, omitting runtime-interface-only and type-surface-only, inside a paragraph whose own closing sentence already said "the gate prints the argument when it fails — that output is the authority." An author trusting the enumeration would have picked from an under-reported set. The replacement says the categories are deliberately not copied here, so the next author does not re-introduce a copy that drifts again.

Measurements

All readings taken at 1c5673488, working tree clean, merge base 7c12e475e.

Line ratchet — 1068 before this PR, 1067 after. Removing item 3's clause shrank the paragraph, and nothing was restored to pad the count back: the ratchet is a cap, so a net decrease is legal.

✓ check-skill-line-ratchet: AGENTS.md is 1067 lines (ceiling 1068; headroom 1).
✓ check-skill-line-ratchet: AGENTS.md: widest table row is 768 bytes (pin 768; headroom 0).

The same gate also enforces a per-line 120-byte budget, which the first reflow of the shortened paragraph broke by 1 byte (L469 (121B)); the follow-up commit rewrapped it to five lines, each under budget. Recorded because the byte budget is a distinct check from the line ceiling and is easy to miss.

Gate union — 14 families, re-derived in-worktree by node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack after merging origin/main (the first derivation warned STALE TREE — scripts/check-regen-pending.mjs had moved on main; the merge cleared it and the derived list came back identical). All 14 exit 0:

✓ dispatch-gates --ran: 14 derived famil(ies) accounted for — 14 run, 0 NOT-MEASURED.

Selected verdict lines:

✓ check-skill-id-lint: 26 file(s) clean (pattern /#[0-9]{3,}/g).
✓ 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.
check-nul-bytes: OK (scanned text files; no raw ASCII control bytes).

Governance predicate — exit 3, as expected for this surface:

$ node scripts/pm/check-governed-merges.mjs --test AGENTS.md          # EXIT=3
governed-surface predicate: 1 of 1 path(s) hit the register (5 surfaces, repo-agnostic).
  ⛔  GOVERNED — a human merge is the review record for this PR.

Lint — a proven narrowing, not a skipped run. Three readings:

  1. Population, read from eslint's own config: every files: block in eslint.config.mjs globs {ts,tsx,mts,cts,js,jsx,mjs,cjs} only. No markdown block exists.
  2. Count, from --format json: npx eslint AGENTS.md --no-inline-config --format json returns one entry, errorCount: 0, and its single warning is "File ignored because no matching configuration was supplied." — the ignore notice, not a finding.
  3. Invariance: the diff touches exactly one path, and eslint excludes it from its population outright. Type-aware linting is scoped to the TS globs above, so nothing in this diff can move the verdict on any file it does not touch.

Changeset: skip-changeset. No published package lists AGENTS.md in its files[] (checked across every non-private package.json), and the root package is private: true. Nothing publishes.

Scope

Only the AGENTS.md paragraph the ruling ordered. Untouched by design: every gate, every workflow, and the merge policy. Item 3 belongs to domain:devx and is tracked separately as #16482; nothing here changes it, and by the reasoning above nothing here describes it. The same-file footer-sentence card #16633 is queued behind this one and is likewise not done here.

验收备注

  • The ADR-0087 marker drift described above is repaired in this PR as the fold payment, so it needs no card of its own.
  • Noted, not filed: scripts/pm/check-governed-queue-guard.mjs has no --test PATHS mode; that predicate belongs to its sibling check-governed-merges.mjs. The queue guard reads GITHUB_EVENT_PATH and nothing else, and refuses (exit 1) when it is absent — its documented and correct "could not look must never exit 0" behaviour, not a defect.

维护者速读(草稿)

改了什么 —— 在 AGENTS.md 的「多 agent 协作纪律」第 2 条(「从 main 切分支」)下面加了一段:stacked PR series(每个 PR 叠在下一个上面)不是本仓受支持的工作形态。同一个文件里删掉了一段已经过时的 ADR-0087 处置标记清单来抵账,全文 1068 → 1067 行(净减一行)。

为什么改 —— 维护者在决策批 #66 里已经裁决(原话:「同意」)。裁决的执行项就是这一段话。段落里只写两条结构性代价:squash 合并会切断祖先链,每个后代每次落地都要多付一轮重建;破坏性 changeset 的 ADR-0087 处置是相对基线的,叠加卡有两条基线、要求互相矛盾的标记。裁决的结论是不为这个形态改门禁、也不改合并策略,而是写清楚它不受支持、并给出 trunk 分支的替代做法。

为什么第三条(重型 CI 不在叠加 PR 上跑)没写进来 —— 裁决把它单独定性为「与叠加无关的一个缺陷」,拆成了 devx 车道的另一张卡去。它不是「不受支持形态的代价」,而是正在被修的 bug。写进 AGENTS.md 会有两重问题:把一个缺陷错记成可接受的成本;以及那张卡一落地,这句话就变成假话,像其它被复述出来的事实一样在文件里腐烂。也没有用「CI 目前不跑」这类折中说法 —— 它的失效日期完全一样。

风险与代价(含回滚) —— 纯文档改动,不影响任何运行时、构建或发布产物,不发布(skip-changeset)。代价是抵账时删掉了那份标记清单:它原本只列了 7 类里的 4 类,已经过时,而门禁失败时本来就会打印完整的 7 类,同一段话里也早就写明「门禁的输出才是权威」——所以是删掉了一份会误导人的副本,不是删掉规则。回滚成本极低:git revert 即可,没有任何下游依赖。

席位意见 ——

你要做的 —— 确认两点即可:① 这段话的措辞是否准确表达了你在批次 #66 的裁决;② 抵账删掉 ADR-0087 那份 4 选 1 清单是否可以接受(理由见上,完整清单由门禁自己打印)。确认后由你手工合并 —— 本 PR 触及受管面,按 Prime Directive #14 席位不翻 ready、不入队、不挂 auto-merge,一直保持 draft。

Record the maintainer's ruling (director seat, decision batch #66): a
stacked series -- each PR branched off the one below -- is not a supported
working form in this repository, and no gate rule or merge-policy change is
made for it. A multi-card change uses a trunk branch and pays the two
recorded workarounds.

The paragraph is self-contained rather than a pointer: AGENTS.md is in
check:pm-skill-id-lint's scan set (pattern /#[0-9]{3,}/), so the card number
cannot be cited in the file. The three tooling blind spots are stated in one
clause each so the rule is actionable without dereferencing history.

Fold payment for the 1068/1068 line ratchet: the ADR-0087 marker block in
the Post-Task Checklist listed 4 of the gate's 7 disposition categories --
a drifted copy of output the same paragraph already calls "the authority".
Replaced by a pointer to the gate's own FIXIT, which prints the full set.
Net 0 lines.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P58euzUXCVJNwmhuPC9DXY
@github-actions github-actions Bot added size/s documentation Improvements or additions to documentation labels Sep 8, 2026
@hotlong hotlong added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed documentation Improvements or additions to documentation labels Sep 8, 2026 — with Claude
Seat review: the ruling grades that cost as "a defect independent of
stacking" and splits it out to its own devx card, so it is a defect being
fixed -- not a price of an unsupported form. Stating it in AGENTS.md as an
inherent property of stacking contradicts the ruling, and the clause goes
false the moment that card lands, rotting in place like any other restated
fact.

The paragraph now carries only the two structural costs the ruling did
assign here: squash landing destroys the ancestry link, so every descendant
pays a rebuild lap per landing; and a breaking changeset's ADR-0087
disposition is base-relative, so a stacked card's two bases demand
contradictory markers.

No pointer to the split-out card: AGENTS.md is in check:pm-skill-id-lint's
scan set, and any wording like "CI does not run on these yet" would itself
go false when that card lands.

AGENTS.md 1068 -> 1067; the ratchet is a cap, so a net decrease is legal and
nothing was restored to pad it back.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P58euzUXCVJNwmhuPC9DXY
…udget

check:pm-skill-ratchet enforces a per-LINE byte budget alongside the
per-file line ceiling, and the reflow left L469 at 121B. Rewrapped to five
lines, each under 120B, with the closing boundary shortened to "No gate or
merge-policy change is made for it" to fit without an orphan line.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P58euzUXCVJNwmhuPC9DXY

hotlong commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

维护者速读(终稿 · skills 席,2026-09-08T03:52Z)

改了什么 — 在 AGENTS.md「多 agent 协作纪律」第 2 条(从 main 切分支)下面加一段:stacked PR series(每个 PR 叠在下一个上面)不是本仓受支持的工作形态。段落写了两个结构性代价(squash 落地切断祖先链,每个后代每次落地都要多付一轮重建;破坏性 changeset 的 ADR-0087 处置相对基线,叠加卡有两条基线、要求互相矛盾的标记)、替代做法(trunk 分支;trunk 合并前把处置改成 registered;预期并支付 rebase laps),并明确不为它改门禁、不改合并策略。抵账:同文件删掉一份过时的 ADR-0087 处置标记清单副本(只列了 7 类里的 4 类,门禁失败时本来就会打印全集)。全文 1068 → 1067 行。

为什么改 — 你在决策批 #66 已经裁决(原话:「同意」):卡片的第 1、2 项是不受支持形态的代价,第 3 项(重型 CI 在叠加 PR 上一个必需检查都不跑)是独立于 stacking 的缺陷,拆成 #16482 归 devx 车道修。裁决的执行项就是这一段。席位复核时让 dev 把第 3 项从段落里去掉了:它是正在修的缺陷,写进 AGENTS.md 当作固有代价,#16482 落地那天就变成假话。

风险与代价(含回滚) — 纯文档改动,不影响任何运行时、构建或发布产物(skip-changeset)。席位复核:diff 与认领申报的文件面一致(只有 AGENTS.md);14 条派生门禁全绿;受管谓词 GOVERNED。抵账删掉的清单在 scripts/check-adr-0087-registration.mjs 的 FIXIT 输出里仍有家 —— 席位在 origin/main 上核过:7 类全在;仓内没有任何脚本断言 AGENTS.md 载有那份清单。一处与裁决字面的已申报偏差:裁决要「pointing at this card」,但 AGENTS.md 在 id-lint 的扫描面内,五位卡号一写就红,所以指针落在 PR 正文(Fixes #16149),段落自含。CI:Lint & Repo Gates 与一个 Type Check 在跑(03:44Z),其余绿。回滚 = git revert 一个提交。

席位意见 — ACCEPT。两点你可能想看一眼:① 段落只保留两个结构性代价、不含第 3 项(理由见上);② 抵账删的是会误导人的副本、不是规则。

你要做的 — 受管面(AGENTS.md),PR 停在 draft,席位不翻 ready、不入队、不合并;已向 os-zhuang 请审,并把 PR assign 给了 hotlong(作者身份即席位账号,请审会 422)。合并与否请回一个字:是/否


Generated by Claude Code

@hotlong
hotlong requested a review from os-zhuang September 8, 2026 03:48
@os-zhuang
os-zhuang marked this pull request as ready for review September 8, 2026 03:49
@os-zhuang
os-zhuang enabled auto-merge September 8, 2026 03:49
@hotlong
hotlong marked this pull request as draft September 8, 2026 03:51
auto-merge was automatically disabled September 8, 2026 03:51

Pull request was converted to draft

hotlong commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

@os-zhuang — review requested on this governed draft by mention (skills seat, hotlong, session session_01P58euzUXCVJNwmhuPC9DXY, 2026-09-08T03:56Z). The MCP reviewer-request call made at 03:52Z with draft: true passed explicitly flipped this PR to READY (read back draft: false at 03:55Z; not in the merge queue — refs/heads/gh-readonly-queue/* held 16722 · 16725 · 16727 · 16738); the seat converted it back to draft at 03:51Z and read back draft: true. Because that call is the hazard, the reviewer request is not re-sent through it; this mention plus the PR assignment to hotlong is the notification. ACCEPT and the seat's 速读终稿 are above; the PR stays draft until a human merge. ⛔ Nothing was enqueued, armed or approved.


Generated by Claude Code

@hotlong
hotlong marked this pull request as ready for review September 8, 2026 03:58

hotlong commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

Correction and restore — skills seat (hotlong, session session_01P58euzUXCVJNwmhuPC9DXY), 2026-09-08T04:03Z.

The seat's 03:56Z comment above attributed this PR's ready state to the MCP reviewer-request call. That attribution was wrong. The PR's event log reads, in order: 03:49:09Z os-zhuang APPROVED (review 5137116866, on head 1c5673488); 03:49:17Z os-zhuang marked the PR ready for review; 03:49:19Z os-zhuang enabled auto-merge. The seat read draft: false at 03:55Z without reading the events, misread it as a tool flip, and at 03:51:39Z converted the PR back to draft — which removed the approver's auto-merge. That revert undid an authorized landing and is the seat's error, recorded here and in the round report.

Restored under the standing rule (an APPROVED review from a GOVERNED_APPROVERS account on a governed draft ⇒ the seat arms auto-merge once every check run is green): every check run on 1c5673488 is green or filter-skipped as of 03:52:25Z (Lint & Repo Gates last), the PR is marked ready again now and auto-merge (SQUASH requested; the queue's configured method decides) is armed in the next stroke, followed by the queue-ref probe. ⛔ No review was submitted by this seat; the approval on record is os-zhuang's.


Generated by Claude Code

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 needs-user-decision 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.

finding: a stacked PR series has no model in this repo's tooling — three costs measured end-to-end on the #14478 six-card stack

3 participants