Skip to content

feat(pm): make close-out debt mechanical — same-round verdict clause, H8 merged-but-dispatched detector, seat-title liveness patrol (#8683) - #8685

Merged
hotlong merged 2 commits into
mainfrom
claude/issue-8683-closeout-mechanization
Aug 14, 2026
Merged

feat(pm): make close-out debt mechanical — same-round verdict clause, H8 merged-but-dispatched detector, seat-title liveness patrol (#8683)#8685
hotlong merged 2 commits into
mainfrom
claude/issue-8683-closeout-mechanization

Conversation

@hotlong

@hotlonghotlong commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Fixes#8683

Three deliverables, one PR, per the maintainer-pulled card (ruling verbatim, untranslated: 「现在开工派发」, 2026-08-14).

1. Runbook clause — a verdict executes in the round that produces it

.claude/skills/pm-dispatch/references/dispatch-runbook.md gains 「结论当轮执行(维护者 2026-08-14)」, placed directly after the decision-recording section (the close-out/review flow area), in the file's existing style. It states: writing "recommends closing" (or any retest/audit verdict) without performing the paired close/label write in the same round is itself a half-state, on the same footing as the half-states family; record-and-walk-away is prohibited; a verdict table's production round is its execution round (the table is not the deliverable, the executed writes are); an actor lacking authority must name who has it and move the state into their inbox (label flip into their view) in the same round — a comment is nobody's inbox. No issue numbers in operational text (id-lint clean).

2. H8 detector — delivering PR MERGED, card still pm:dispatched

scripts/pm/check-half-states.mjs gains H8, following H7's shape exactly:

  • exported pure predicate h8MergedPrStillDispatched(issue, mergedPrs) — kept exported so downstream gates can reuse it, the way check:partof-closing-keyword imports H7's predicate;
  • the delivering relation is read from merged PR bodies with H7's own code-stripped extractors (Part of #N, or a closing keyword bound to #N), so the measured reference-parser behavior (inline-span/fence stripping, per-number binding) carries over instead of being re-proved;
  • report-only wiring on the module's existing input contract: one bounded listing of recently merged PRs (2 pages, most recently updated), matched against the already-listed open pm:dispatched cards — no per-card fetch, exit-code contract unchanged;
  • boundary stated in the module header and at the window helper: live mode feeds H8 a bounded recent window, so it is a patrol accelerator, never an exhaustive audit — a delivery older than the window is invisible; the finding clears when the paired write lands (label dropped), not when the PR ages out;
  • self-test extended 79 -> 91 cases (positive, negative, strip reuse, per-number binding, closed-unmerged is not a delivery, empty/missing window).

3. Triage-Routine seat-title liveness patrol

Location established first, as the card asked: the triage Routine's platform-side prompt is a one-line skill invocation by design (SKILL.md: 「座位 Routine 的prompt 收敛成一行技能调用,座位行为全部版本化在 git,升级走技能 PR,⛔ 永不靠重建Routine 改行为」) — so the behavior text IS versioned in-repo, and the patch lands in the skill references; no live trigger was touched or needs touching. The runbook gains 「座位贴活性巡查(分诊轮常设项;维护者 2026-08-14)」: each fire, scan pm:seat posts whose title shows 🟢 against the incumbent's OWN recent activity (own comments/claims/body edits — not inbound cross-seat notices); silent beyond the existing 24h recycling threshold ⇒ demote to ⏳ vacant with an evidence comment, title + assignee cleared in the same stroke (the triple-write discipline). seat-post-protocol.md's liveness bullet is amended in the same PR to name both paths (lazy evaluation at takeover conflict + the standing patrol) so the two texts cannot contradict each other.

Compression round (maintainer ruling 2026-08-14, verbatim: 「8685 字太多了」)

The two new runbook sections were cut to roughly half (every normative bullet, ⛔ mark and load-bearing one-liner kept; provenance narratives cut to one line); the H8 module's narrative prose was trimmed (boundary now stated once in the header and once at the helper); test cases and their comments untouched. References net delta after compression: +30 lines (dispatch-runbook +28, seat-post-protocol +6/−4).

Constraints honored

  • ADR-class surface (.claude/skills/pm-dispatch/**): this PR stays draft, human merge, auto-merge never armed.
  • SKILL.md untouched — the ratchet gate confirms 686/686, headroom 0.
  • scripts/pm + skills-reference diff only, nothing published ⇒ skip-changeset (precedent: the PRs that introduced and last touched this module carry it).

Verification (gate union at e75de0a890, the final commit)

Families derived with node scripts/pm/dispatch-gates.mjs over the actual changed paths, re-run in full after the compression commit. One family surfaced beyond the dispatch prompt's named set and was run: check:partof-closing-keyword — it imports H7's predicate from the edited module.

gateresult
pnpm check:pm-half-states (extended self-test)✓ 91 cases pass
pnpm check:pm-skill-id-lint✓ 9 file(s) clean
pnpm check:pm-skill-ratchet✓ SKILL.md 686 lines (ceiling 686)
pnpm check:skill-frame-sync✓ 4 copies structurally isomorphic
pnpm check:nul-bytes✓ 5725 text file(s) clean
pnpm check:doc-authoring✓ 377 files clean
pnpm check:partof-closing-keyword✓ 28 self-test cases pass
pnpm --filter @objectstack/lint run check:doc-formula-expressions (after @objectstack/formula... build closure)✓ 22 + 9 example(s) clean

Generated by Claude Code

… H8 merged-but-dispatched detector, seat-title liveness patrol
Three deliverables per the maintainer-pulled card:
1. dispatch-runbook.md gains a same-round verdict-execution clause: a
verdict executes in the round that produces it; record-and-walk-away
is prohibited; an actor lacking authority names who has it and moves
the state to their inbox in the same round.
2. check-half-states.mjs gains H8 (report-only): a card's delivering PR
is MERGED while the card still carries pm:dispatched. Exported
predicate follows H7's shape and reuses its code-stripped extractors;
live mode reads a bounded window of recently merged PRs; self-test
extended 79 -> 91 cases.
3. dispatch-runbook.md gains the triage-Routine seat-title liveness
patrol (scan green-titled pm:seat posts against the incumbent's own
recent activity; silent beyond 24h => demote to vacant with an
evidence comment, title + assignee in the same stroke), with the
seat-post-protocol liveness bullet amended to name both paths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WuTtyckQa1VcXwgd52JpN
@vercel

vercelBot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 14, 2026 2:41pm

Request Review

@hotlonghotlong added skip-changeset PR has no user-facing published change; bypasses the changeset gate and removed size/m labels Aug 14, 2026 — with Claude
@github-actionsgithub-actionsBot added the documentation Improvements or additions to documentation label Aug 14, 2026
@hotlongClaude

Copy link
Copy Markdown
ContributorAuthor

Review: ACCEPT — PM seat, session session_018WuTtyckQa1VcXwgd52JpN, review at fable tier (mandatory surface). Stays draft for human merge; auto-merge not armed.

Verification performed by the reviewer (scratch worktree at the PR head)

Head check per the checklist clause that landed this morning: quoted union HEAD 3785d616fa == current head.sha3785d616fa… ✓. Re-ran independently at that head: check-half-states self-test 91 cases pass (79→91 as claimed), check-partof-closing-keyword28 cases pass (the downstream import of the edited module survives), SKILL.md counted 686 (untouched), id-lint pattern scan on both changed reference files clean.

Substance

  • Deliverable 3's location finding is the right resolution: the triage Routine's prompt is a one-line skill invocation by design (behavior versioned in git), so the patrol clause lands in the references and no live trigger is touched — exactly the investigate-first shape the card demanded, and it makes the patrol upgradeable by PR forever.
  • The patrol clause encodes today's actual failure modes, not a generic rule: liveness counts only the incumbent's OWN output (inbound cross-seat notices explicitly excluded — the engine-core misread), threshold reuses the existing >24h recycling line rather than minting a second constant, and the demote is the same-stroke triple with an evidence comment. Notably the >24h bar would have prevented this morning's race mis-correction — the clause fixes the corrector's failure mode too.
  • H8 is honest about its window: merged_at-gated (closed-unmerged is an abandoned attempt, not a delivery), per-number bound, extractor reuse carries H7's measured parser behavior instead of re-proving it, and the bounded 2-page window is documented as a patrol accelerator with the aging-out boundary stated in both the header and the helper — plus the right clearing semantics (the label, not the PR's age, clears the finding).
  • The two prose formulations worth the lines: 「表不是交付物,落账才是」 and 「评论不是任何人的收件箱,标签才是」 — both are the measured failure in one sentence each.
  • Reasonableness (three axes): the failure class cost ~13 unexecuted verdicts and seven registry corrections in one day (real need); all three fixes are report-only or text, no new gate blocks anyone (platform fit); and the mechanisms remove reliance on session goodwill entirely (error prevention). Proportionate: +222/−10, no SKILL.md pressure.

Awaiting a human merge (ADR-class).


Generated by Claude Code

…e the two runbook sections, trim H8 module narrative
Normative bullets, ⛔ marks and load-bearing one-liners kept; provenance
narratives cut to one line (detail lives on the card and PR); H8 boundary
now stated once in the header and once at the window helper; test cases
and their comments untouched (self-test stays 91).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WuTtyckQa1VcXwgd52JpN
@hotlongClaude

Copy link
Copy Markdown
ContributorAuthor

Re-review after the compression rework: ACCEPT stands — PM seat, session session_018WuTtyckQa1VcXwgd52JpN, fable tier.

Verified at the new head (quoted union HEAD e75de0a890 == branch head, checked live): both runbook sections read at roughly half their prior length with every normative bullet, ⛔ mark and both load-bearing one-liners intact (「表不是交付物,落账才是」「评论不是任何人的收件箱,标签才是」); provenance narratives are one to two lines; the H8 boundary statement now appears exactly twice (header + window helper). Reviewer re-ran at head: check-half-states self-test 91 pass, check-partof-closing-keyword28 pass, SKILL.md686 untouched. References net delta of the PR after compression: +30 (was ~+40). No semantic change detected against the accepted substance.

Ready for the human merge (ADR-class, draft, auto-merge not armed). Merging this also releases the serial hold on the instruction-surface compression card, which dispatches on this PR's merge event.


Generated by Claude Code

@hotlong
hotlong marked this pull request as ready for review August 14, 2026 14:49
@hotlong
hotlong added this pull request to the merge queueAug 14, 2026
Merged via the queue into main with commit 37827b8Aug 14, 2026
24 checks passed
@hotlong
hotlong deleted the claude/issue-8683-closeout-mechanization branch August 14, 2026 14:57
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@hotlong@claude