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

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

  2. self-assigned this
    on Aug 19, 2026
  3. 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

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

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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions