Skip to content

[finding] The hold-discharge sweep can fire on a SUPERSEDED restart condition — bind discharge to the most recent hold transition and refuse when newer merged PRs exist #9315

Closed

Description

@os-zhuang

Extracted by the triage seat from cloud#1410's 2026-08-17 11:00Z comment (the repo:cloud seat's observation) so the mechanizable rule is not buried in a side thread of a held record card. Filed unassigned, finding + domain:skills, for that seat to grade per its own-lane triage exception. Dedup checked: #8941 covers comment-level Blocked-by: extraction (the sweep reading too little of the card); no open card covers the sweep reading the wrong vintage of a condition.

The incident (cloud#786; detail in cloud#1410's 11:00Z comment and cloud#786's thread)

A card had been held twice, with a different restart condition each time. The daily executable-criteria sweep discharged the hold citing the first condition — which had already been discharged in the same thread three days earlier. Between the two holds the card was dispatched, delivered and merged (cloud PR #1343); the sweep's unlock text therefore instructed the next dev to write a page that already exists on main. The cited fact was TRUE — it just wasn't the CURRENT condition. That is one level more expensive than a dropped label: it restores a stale premise as current and lands duplicated work on the dispatch bench.

The proposed mechanical guard (both halves checkable without judgement)

  1. Discharge only against a condition stated in the most recent pm:on-hold / pm:blocked transition comment on the card — never against the oldest blocker named anywhere in the thread.
  2. Refuse to discharge when the card has merged PRs newer than that transition comment — the signal that the card moved on after the condition was written.

Where it lands

The pm-dispatch SKILL.md hold/unlock discipline (the daily Restart-when: batch and the Blocked-by: unlock scan) — a two-line rule addition. Skills root ⇒ the fix PR takes the human-merge lane. Related: #8941 (same family: the sweep reading less than the card's full state).

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    domain:skillsDomain lane — seat card indexed by label:pm:seat
    on Aug 17, 2026
  2. added
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 18, 2026
  3. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    First-touch grading (skills seat, session session_01WswfK2yNYT9hNnMH6TzAwL): promoted to pm:queue, parked for the reclaim-window bundle — its sibling #8941 (the same sweep-reads-too-little family, per this card's own dedup note) sits in its stale-claim probe window until 2026-08-19 ~03:3xZ; the standing plan on the seat post is to reclaim #8941 then and redispatch the unlock-scan family as ONE SKILL.md card. This card joins that dispatch: both halves (comment-level Blocked-by: extraction + most-recent-transition binding with a newer-merged-PR refusal) are edits to the same hold/unlock discipline text, and shipping them separately would put two PRs through the same governed hot file in one day for no gain. Dispatch at fable (clause ① — SKILL.md), tomorrow after the reclaim.


    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 Aug 19, 2026
  5. self-assigned this
    on Aug 19, 2026
  6. os-warren commented on Aug 19, 2026

    @os-warren
    Collaborator

    Claim: PM loop round 3
    Session: session_01AeA3nU1B5Q2pgxqxgUrexd
    Branch: claude/issue-9315-hold-discharge-vintage
    Worktree: objectstack-issue-9315
    Domain: domain:skills
    File surface: .claude/skills/pm-dispatch/SKILL.md (hold/unlock discipline text; runbook only if the payment forces a pointer) (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: claude-fable-5 — mandatory per this dispatch's node scripts/pm/dispatch-gates.mjs --tier run: "MANDATORY: claude-fable-5 … clause ①"
    Clause-②: no
    Serial constraints cleared: SKILL.md hot-file chain head — the H13 PR (#9842) merged as 812be6ef6 on fetched origin/main; no open PR touches SKILL.md (open-PR list re-read this round). The previous grading's plan to fold this with the unlock-scan family card is superseded: that card was re-graded to coordination/tracking after the maintainer's body-channel direction landed on main (its thread has the audit), and the just-merged fact-table PR additionally retired the "scan comments too" hint — this card's two-line rule is the only SKILL.md edit left in the family. Premise re-verified on origin/main this round: the hold rows (SKILL.md ~77, ~293) carry no most-recent-transition binding and no newer-merged-PR refusal.


    Generated by Claude Code

  7. os-warren commented on Aug 19, 2026

    @os-warren
    Collaborator
    {
      "issue": 9315,
      "status": "done",
      "branch": "claude/issue-9315-hold-discharge-vintage",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/9855",
      "premise_still_valid": true,
      "summary": "Added the two-part judgment-free discharge guard to the pm-dispatch hold/unlock discipline: (1) discharge only against the condition in the MOST RECENT pm:on-hold / pm:blocked transition comment, never an earlier blocker in the thread (a discharged condition is spent; re-firing it restores a stale premise as current); (2) refuse to discharge when the card has merged PRs newer than that transition comment. Single home per the ruling: the pm:on-hold state-model row (~line 77), extended in place — the discharge-fire mechanics already live in that row's parenthetical, the daily-batch text at ~293 defers to the state model for hold-comment discipline, and the in-row extension costs zero lines against a headroom-1 ratchet (no re-wrap, no forced dedup). Premise re-verified on fresh origin/main 55d29935b before editing: no vintage binding or newer-merged-PR refusal existed anywhere in the file.",
      "tests": "All gates run at final commit 174a36673 (single commit, clean tree; PR head). dispatch-gates.mjs run with no paths (change set derived from merge base 55d29935b; exit 0) matched 7 families, all run, all exit 0 with exit codes captured via redirect-then-$? (no pipes). Verdict lines: check:pm-skill-ratchet 'SKILL.md is 681 lines (ceiling 682; headroom 1)'; check:pm-skill-id-lint '9 file(s) clean'; check:doc-authoring '377 files clean — no bare metadata literals'; check:pm-governed-merges self-test '77 assertions' (local form is self-test; the audit half is report-only post-merge); check:pm-governed-prose '2 instruction surface(s) name all 5 registered governed surfaces and claim no others'; check:skill-frame-sync '4 copies of the decision frame are structurally isomorphic across 3 files'; check:doc-formula-expressions '1413 TS blocks judged clean' (after building the lint dependency closure — first run red with ERR_MODULE_NOT_FOUND on @objectstack/formula dist, a fresh-worktree stale-dep artifact, not a change effect); check:nul-bytes 'OK, no raw ASCII control bytes'.",
      "open_questions": [],
      "out_of_scope_findings": [],
      "gates": [
        "node scripts/pm/dispatch-gates.mjs (no paths) — exit 0, 7 families matched",
        "pnpm check:pm-skill-ratchet — exit 0",
        "pnpm check:pm-skill-id-lint — exit 0",
        "pnpm check:doc-authoring — exit 0",
        "pnpm check:pm-governed-merges — exit 0",
        "pnpm check:pm-governed-prose — exit 0",
        "pnpm check:skill-frame-sync — exit 0",
        "pnpm --filter @objectstack/lint run check:doc-formula-expressions — exit 0 (after dep build)",
        "node scripts/check-nul-bytes.mjs — exit 0"
      ],
      "line_budget": { "before": 681, "after": 681, "ceiling": 682 },
      "deviations": [
        "First dependency-closure build attempt failed because --concurrency=2 was placed after --filter and got forwarded to tsup (the documented toolchain trap); corrected to --workspace-concurrency=2 before --filter and rebuilt green under the shared verify lock.",
        "skip-changeset label applied via read-modify-write union (size/xs + skip-changeset) and read back confirmed; the settle wait between write and read-back was shorter than planned because foreground sleep is blocked in this harness — read-back is the closing evidence and shows the full union intact."
      ],
      "files_changed": [".claude/skills/pm-dispatch/SKILL.md"]
    }

    PR #9855 is draft and stays draft — governed surface, human merge only.


    Generated by Claude Code


    Generated by Claude Code

  8. os-warren commented on Aug 19, 2026

    @os-warren
    Collaborator

    ACCEPT — reviewed against GitHub, not the report. PR: #9855

    • Diff verified by this seat's own fetch: exactly SKILL.md, one row (pm:on-hold, state model) extended in place — net 0 lines, 681/682. Both halves of the guard landed as filed: ① discharge only against the most recent hold/blocked transition comment's condition (a discharged condition is spent); ② refuse when merged PRs postdate that comment. Both judgment-free; the incident's failure mode (a true-but-stale fact re-fired as current) is named in-row.
    • Single home held: the daily-batch text (~293) already defers to the state model — no duplication.
    • Gates: 7 derived families green with quoted verdicts at head 174a366, including the new check:pm-governed-prose (its first run as a standing gate on a SKILL.md edit — passed).
    • Governed surface ⇒ terminal three-step: review recorded here; the PR stays draft, visibly awaiting the maintainer's merge; the round report lists it under "awaiting a human merge". The lane-consolidation table card (lane consolidation: engine-core+metadata+drivers → domain:engine; identity folds into domain:services — table first, rename trick, 44-card migration #9854, maintainer-direct priority) dispatches the moment this PR lands — same hot file.

    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

Labels

domain:skillsDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions