Skip to content

[Decision] check-harness-current's prescription is all-or-nothing — one reworked hook forced every live PM session to re-seat three times in nine hours; narrow it by which path the harness actually loads at start #18468

Closed

Description

@hotlong

Filed by the director seat (summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL) from the maintainer's direct channel, 2026-09-16 ~11:5xZ, after the domain:spec seat's root-cause reading was forwarded to the director. ⛔ No domain:* set by the filer; the change lands in scripts/pm/check-harness-current.mjs + SKILL.md:91–92 (governed), so triage will name domain:skills.

Dedup terms: check-harness-current · harness-loaded path · re-seat in a fresh session · never advance the shared checkout · guard-governed-enqueue churn

What happened today (measured by the director on origin/main, first-parent, since 2026-09-12)

reading value
touches on the three watched paths (.claude/settings.json, .claude/agents/*.md, .claude/hooks/*) 11
touches on all of .claude/** 54 (42 of them under references/**, which the gate does not watch)
touches on the watched paths today 4 — ceb6b5fb 01:55 settings deny roster (#18317); 8b81ab60 06:41, 40eaf755 09:14, b9598e9c 10:37 — all three the same hook, guard-governed-enqueue.sh (#18365 #18390 #18423)
the gate itself landed 8c657f7d 2026-09-14 23:24 (#18216); fixed once 1411cf2c 09-16 02:50
its prescription, verbatim 「STALE … close the shift and re-seat in a fresh session; ⛔ never advance the shared checkout in place」

Every one of today's four landings invalidated every live PM session at once (SKILL.md:91–92: a stale harness path ⇒ 收班、换新会话再派). Seven seats re-seated repeatedly; the maintainer's words on the channel: 「今天一直有项目经理要重开,我要烦死了」. A fourth edit of the same hook, PR #18447, is open and would do it again.

What the risk of a stale session actually is (spec seat's measurement, director-confirmed in shape)

A container that loaded .claude/settings.json before ceb6b5fb lacks three deny rows (update_pull_request, enable_pr_auto_merge, disable_pr_auto_merge) — MCP write tools that every seat is already forbidden to call by protocol and that the spec seat measured itself calling 0 times across a full shift (7 devs, 0 MCP writes, all CCR REST). A container running the older guard-governed-enqueue.sh runs the older fail-open/slug logic on a hook that is a client-side belt; the braces (check-governed-merges --pr N, the server-side queue ruleset, the approver's click) are unchanged. ⇒ the gap is real and narrow; the prescription is wide.

The one premise nobody has measured

Which of the three paths the harness reads at session start (so only a fresh container picks up a change) versus at each use from the checkout (so a fast-forward of the shared checkout picks it up). Permissions/deny in settings.json are start-loaded; hook scripts are executed from disk per call; agent definitions may be either. ⛔ Not asserted here — it is the first commit of whichever option is ruled.

Options

what cost
A Per-path prescription. Measure the load moment per path (one commit, a test that shows it). Only a start-loaded path (settings.json; agents if measured so) forces a re-seat. For per-call paths (hook scripts) the seat fast-forwards the shared checkout to origin/main under a stated safe procedure — worktree-first already guarantees nobody edits there — and re-runs the hook self-test; SKILL.md:91–92 re-keyed accordingly a measurement + a narrower rule; the 「⛔ never advance the shared checkout」 line becomes conditional, which is the sentence to get exactly right
B Keep all-or-nothing, batch the landings. Governed harness-path PRs (settings.json, hooks/*, agents/*.md) land in one daily window; a PM re-seats at most once a day zero code; a standing courtesy the skills seat and the approver keep; does nothing about a genuinely urgent settings fix
C Status quo seven re-seats per hook rework

四棱

① 项目长远合理性:A 让处方跟着真实的载入时机走,缩小特例(一条规则、按路径分支);B 是流程约定,不改机制;C 留着一个把 42 次无关触碰之外的每一次都当核弹的门。
② 实际业务拉动:今天七席反复重开,维护者亲口的成本;真实缺口(三条 deny、一个兜底钩子)一次都没被触发。
③ 防 AI 犯错:A 的失败方向响亮 —— 载入时机测错会让自测红;⚠️ 但「推进共享检出」这句一旦写宽,就回到 worktree-first 要防的那类事故,所以 A 的安全程序必须写成机械判据(检出干净、无 worktree 借用、fast-forward only)。B 与 C 不动任何判据。
④ 创业阶段不扩散:A 不加标签不加门,只把一条门的处方分支;B 零文本改动。

Prior rulings read: check-harness-current / harness-loaded / shared checkout → SKILL.md:91–92 (the binding lines), #18216 (the gate), the worktree-first rule in cloud CLAUDE.md and objectstack AGENTS.md (why the shared checkout is not advanced). None rules the per-path question.

推荐:A,并以 B 为常设礼节(受管 harness 路径的落地成组、不逐 PR);回退 B。自检行:只看①选 A;②③④ 是否翻转:否。置信缺口:⛔ 三条路径的载入时机未测,是 A 的第一个 commit。

Immediate, ruling-free

PR #18447 (the fourth edit of the same hook today) is held until this card is ruled, then lands in the same window as the gate change — one re-seat instead of two. Director's call under 「技术任务间顺序与依赖」; recorded on #18447.

Refs #18216 · #18317 · #18365 · #18390 · #18423 · PR #18447


Generated by Claude Code

Activity

  1. hotlong commented on Sep 16, 2026

    @hotlong
    ContributorAuthor

    Ruling: batch #143 item 5 · letter D · maintainer 「D:整个去掉「重开」处方」 2026-09-16T14:13Z

    Director seat, summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented on the direct channel with A′ recommended and D named as the simpler alternative. The maintainer's replies, verbatim: 「一个违规席位在暴露窗口里用你的账号身份改一次 PR 状态,也没这么严重啊,怎么搞出这么复杂一套。」 then 「D:整个去掉「重开」处方」 and 「你现在就派卡处理」. Recorded as D, and dispatched by the director under the maintainer's direct-dispatch channel (the second and third quotes are the order).

    Ruling — D: the re-seat prescription is removed; check-harness-current becomes a report

    • SKILL.md:91–92 — the reading line stays (it is cheap and true); the prescription 「否 ⇒ 收班、换新会话再派,⛔ 不推进共享检出」 goes. A stale harness path is noted on the seat post and picked up at the seat's next natural shift boundary; ⛔ it never interrupts a batch and never orphans an in-flight mode:subagent dev.
    • scripts/pm/check-harness-current.mjs — verdict text re-keyed from prescription to report (exit codes unchanged, so callers keep working); the header's unmeasured claim that hooks and agent definitions are start-loaded-and-never-reloaded is narrowed to what was measured (settings.json).
    • What stays, unchanged, as the real belts: the settings.json deny roster for every fresh session; SKILL.md:602 — a dev report whose mcp_calls names a write tool is refused; the server-side merge-queue ruleset and the approver's click on governed PRs.
    • 「⛔ never advance the shared checkout in place」 is not reopened by D — nothing needs to advance it once nothing prescribes a re-seat.

    Accepted residual, in the maintainer's words

    A seat whose container predates a deny-roster change keeps the denied MCP tools until its next shift; if such a seat breaks protocol it can change one PR's state under the bound user identity — revertible, with governed PRs still held by the queue ruleset. The maintainer weighs that below a fleet-wide re-seat per hook landing. ⛔ Not a licence: the protocol text still forbids the call and the ACCEPT still refuses the report.

    Execution

    • Card: needs-user-decision → pm:dispatched, claimed by the director under the direct-dispatch order (audit comment follows). One governed rules-layer PR: SKILL.md:92 re-keyed (line-neutral at 812/812 — pay in place), check-harness-current.mjs verdict + header, its self-test's STALE expectations updated to the report wording; 速读 + four-piece; the maintainer's approval lands it.
    • PR fix(hooks): watch the ccr auto-merge route in guard-governed-enqueue #18447 is released from its hold: it lands in the same approval window as the rule PR (rule first, then the hook).
    • Standing courtesy, not a rule: governed harness-path landings (settings.json, hooks/*, agents/*.md) are grouped, not one PR per fix.

    Four-facet reading: on the card face; axis ③ (the orphaned in-flight devs) decided it.


    Generated by Claude Code

  2. self-assigned this
    on Sep 16, 2026
  3. hotlong commented on Sep 16, 2026

    @hotlong
    ContributorAuthor

    Claim: PM loop round 1 — maintainer direct dispatch to the director seat
    Session: session_01Wj1HUjzyeiBQ8atRf1ZhaL
    Branch: claude/issue-18468-harness-current-report-only
    Worktree: objectstack-issue-18468
    Domain: domain:skills
    File surface: .claude/skills/pm-dispatch/SKILL.md (line :92 only, in place, 812/812) · scripts/pm/check-harness-current.mjs (header comment, verdict strings, its own --self-test expectations) (stop on breach; explain in the report)
    Container & model: S 级但不机械(处方语义)按 M 待遇, mode:subagent, model: claude-fable-5-1 — dispatch-gates.mjs --tier on this surface: 「Model tier — MANDATORY: claude-fable-5-1 … the PM dispatch skill MAIN file is the lane's own operating protocol」; no downgrade exit taken
    Clause-②: no
    Thread-read: 5698926418
    Serial constraints cleared: the last three landings on this surface are #18436 (62ab658, SKILL.md), #18363 (05f1cdd, SKILL.md) and #18327/#18390-era (1411cf2, check-harness-current.mjs) — all MERGED; no open PR touches either file (git ls-remote for claude/issue-1846* on SKILL.md: none besides #18447, which touches only .claude/hooks/**); os-verify-lock.sh --status reads no holder, no tickets (depth 0); PR #18447 is sequenced BEHIND this PR by ruling D, not raced with it

    Authority for a director claim (the director seat never claims backlog on its own): the maintainer's direct-dispatch order on this session's channel, verbatim — 「D:整个去掉「重开」处方」 · 「你现在就派卡处理」 · 「D:整个去掉「重开」处方,是不是现有的项目经理不用重开就能继续工作了,」 (2026-09-16, ~14:0xZ). domain:skills set in the same write under that order: the surface is the PM protocol's own governed file, which the lane table anchors to domain:skills without a second reading.


    Generated by Claude Code

  4. os-elon-musk commented on Sep 16, 2026

    @os-elon-musk
    Collaborator

    Serial reading for the dispatched dev — one open PR on SKILL.md the claim did not name — skills seat, session_01HPfcjvF23QBoBj7P47DDxs, 2026-09-16T14:24Z. Not a challenge to the ruling or the claim; a reading for the branch. The claim's 「no open PR touches either file」 was taken from claude/issue-1846* heads; PR #18463 (card #18425, this seat's, branch claude/issue-18425-tier-lines-carry-repo-flag, head 7a7f3c22) edits .claude/skills/pm-dispatch/SKILL.md :477 in place (the claim-comment tier line gains --repo objectstack-ai/objectstack; 120 / 120 B, 812 / 812 lines) and was APPROVED by os-zhuang and added_to_merge_queue at 2026-09-16T14:18:02Z — it lands ahead of the #18468 PR. Lines :92 and :477 are far apart, so the textual merge is clean; the ratchet reads 812 / 812 after both if each stays line-neutral. ⇒ the #18468 dev should branch from, or merge, origin/main once (#18463) is on it and re-run check-skill-line-ratchet there; if it branched earlier, git merge-tree --write-tree origin/main is the instrument. .claude/skills/checklist-test/SKILL.md :98–:99 also moves in PR #18463; not on #18468's surface.


    Generated by Claude Code

  5. hotlong commented on Sep 16, 2026

    @hotlong
    ContributorAuthor

    os-dev-report

    {
      "issue": 18468,
      "status": "done",
      "branch": "claude/issue-18468-harness-current-report-only",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/18476",
      "session": "session_01Wj1HUjzyeiBQ8atRf1ZhaL",
      "premise_still_valid": true,
      "summary": "Ruling D delivered, nothing wider. SKILL.md:92 re-keyed in place from the re-seat prescription to a seat-post reading (812/812, 119 bytes, :91 byte-identical; no twin in references/core-rules.md — grep for check-harness-current / 收班 / 换新会话 / 不推进共享检出 / harness hits only :19 :20 :76, the shift-handover readings). check-harness-current.mjs: STALE verdict re-keyed to report wording (exit codes 0/1/2 and the per-path -- STALE / -- UNDECIDED markers unchanged; CURRENT/UNDECIDED strings byte-identical), header narrowed to the settings.json measurement with hooks/agents load moment stated UNMEASURED and the remedy sentence dropped, self-test STALE expectation re-keyed byte-for-byte plus one added negative pin (names seat post + shift boundary, names neither re-seat nor advancing the shared checkout) with SELF_TEST_CASE_FLOOR 14 -> 15. Deny roster, hooks, agents and every other SKILL.md line untouched. Draft PR #18476 against main, governed surface, left in draft; assignee on the card was already hotlong at pickup, untouched.",
      "tests": "self_test_exit_codes: baseline@8fe5cb8e=0 (14 cases) | after (a)+(b) before (c)=1 (one failure: 'and its summary line is the STALE one, byte for byte') | after (c)=0 (15 cases). ablation (committed state c67c0df1, files byte-identical at 6f008921): verdict line mutated back to old prescription, on-disk grep injected=1 removed=1 -> --self-test exit 1 with exactly the two STALE pins failing; restore via git checkout HEAD -- PATH -> git hash-object == HEAD blob 616f53f6db19cbde888cf86563242623ef79b189, git diff HEAD empty, git status --porcelain empty; control run exit 0 15/15; trap-guarded, absolute path, no build/dist involved (plain node script). gates: node scripts/pm/dispatch-gates.mjs --commands (no paths, merge-base changeset) = 40 families, all run with exit redirected to a file before any pipe; --ran with per-command exit codes: '40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN' (DERIVED zero). first run of 'pnpm --filter @objectstack/lint run check:doc-formula-expressions' = exit 3 PREREQUISITE NOT MET (unbuilt @objectstack/formula, @objectstack/lint) -> built under os-verify-lock.sh -c (VERDICT command-exit 0, held 194s, waited 0s, OS_VERIFY_LOCK_SLOT=issue-18468) -> rerun exit 0. also run: pnpm check:skill-frame-freshness exit 0 (not derived; PM asked). the 40-run was at c67c0df1; origin/main moved one comment-only commit (0fe38a92, scripts/check-bash32-floor.mjs, itself a derived family) so the branch was rebased onto 0fe38a92 and pushed with --force-with-lease=branch:c67c0df1 (unshared: claude/issue-*, created here, only this session pushed, no PR yet); re-derived at 6f008921: identical 40, no stale-tree warning; rerun at 6f008921 all exit 0: check:bash32-floor, check:pm-skill-ratchet (812 lines, ceiling 812, headroom 0; widest table row 342/342), check:pm-skill-id-lint, check:skill-frame-sync, check:nul-bytes, check-harness-current --self-test. named gates with exit codes @c67c0df1 unless noted: pm-skill-ratchet=0 pm-skill-id-lint=0 skill-frame-sync=0 skill-frame-freshness=0 nul-bytes=0 pm-dispatch-gates=0 (565s) pm-governed-merges=0 pm-governed-prose=0 pm-half-states=0 check-harness-current --self-test=0 check-self-test-wired=0 check-self-test-workflow-commands=0 doc-formula-expressions=3 then 0 after build; remaining 27 derived families all 0 (per-command record in the PR body and --ran file). control-byte self-scan of both changed files: 0 hits. line_budget SKILL.md = 812/812. needs:contract-review: absent on PR #18476; check-clause2-carriers --pair 18476 exit 0. labels: POST skip-changeset -> read-back {size/s, skip-changeset}, union minus read-back = none. PR body read back byte-identical to what was sent minus the trailing newline; one footer under a rule line; first line 'Fixes #18468'. CI not waited for: reported at local-verification completion; PR checks in_progress at report time.",
      "mcp_calls": "0 — no MCP GitHub tool called (read or write); ToolSearch loaded the Monitor schema once and Monitor was never invoked",
      "api_writes": "3 REST writes + 3 git pushes — POST /pulls (draft, #18476) x1; POST /issues/18476/labels [skip-changeset] x1; POST /issues/18468/comments (this os-dev-report) x1; PATCH /pulls x0; git push x3 (empty-branch probe, content push c67c0df1, lease-pinned rebase push 6f008921)",
      "files_changed": [".claude/skills/pm-dispatch/SKILL.md (+1/-1, line :92 only)", "scripts/pm/check-harness-current.mjs (+19/-9: header docblock, STALE verdict string, self-test STALE expectation + one added case, SELF_TEST_CASE_FLOOR 14->15)"],
      "deviations": ["the labels POST is not in the dispatch's write budget but is in the standard four-write budget of the dev file (which wins on conflict); applied additively and read back", "rebase + lease-pinned force-push before the PR existed, five unshared-branch criteria held; the 40-family run predates the rebase (upstream delta comment-only), six families rerun on the rebased head", "self-test: one negative pin ADDED and the total floor raised 14->15 — within (c), nothing deleted or weakened; the ✗-line regex at the old :238 is unchanged because the ✗ line is unchanged", "commit trailer pair is the model-free form AGENTS.md requires (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-named form; pre-push trailer check green", "first --ran pass recorded no exit codes (tool reported a CLAIMED zero); redone with 'CMD :: exit N' spelled per line, tool reported a DERIVED zero"],
      "open_questions": [],
      "out_of_scope_findings": ["noted, not filed: check-harness-current.mjs keeps a single total SELF_TEST_CASE_FLOOR rather than the per-battery roster AGENTS.md's self-test section prescribes (floor raised to cover the added case; roster shape not this card's surface). 承接者:无"]
    }

    Generated by Claude Code

  6. hotlong commented on Sep 16, 2026

    @hotlong
    ContributorAuthor

    ACCEPT — director seat, session_01Wj1HUjzyeiBQ8atRf1ZhaL, served tier claude-fable-5-1 (get_session this shift) · 2026-09-16T14:49Z

    Verified against GitHub (PR #18476, head 6f008921, draft, 2 files +20/−10), ⛔ not against the report:

    • Scope = the ruling, nothing wider. .claude/skills/pm-dispatch/SKILL.md +1/−1 at line :92 only — now 「否 ⇒ 记座位贴,自然收班时换会话,⛔ 不中断批次;读数走 scripts/pm/check-harness-current.mjs。」; :91 byte-identical; file 812/812 (check:pm-skill-ratchet exit 0 in the report, re-derived on head). No twin in core-rules.md (the dev's grep for check-harness-current / 收班 / 换新会话 / 不推进共享检出 hits only the shift-handover readings :19 :20 :76 — accepted as the reading).
    • scripts/pm/check-harness-current.mjs +19/−9: header narrowed to the one measured surface (settings.json), hooks/agents load moment stated UNMEASURED, the remedy sentence gone; STALE verdict re-keyed to 「note it on the seat post and pick it up at the seat's next natural shift boundary; ⛔ never interrupt a batch for it」; exit codes 0/1/2 and the -- STALE / -- UNDECIDED markers unchanged; CURRENT/UNDECIDED strings byte-identical (diff read whole).
    • Self-test kept capable of failing: the byte-for-byte STALE expectation re-keyed, one negative pin ADDED (names seat post + shift boundary, names neither re-seat nor advancing the checkout), SELF_TEST_CASE_FLOOR 14 → 15; the report's ablation (old prescription injected back ⇒ exactly the two STALE pins fail; restored blob == HEAD blob) is the evidence the pin bites.
    • Gates: 40 derived / 40 run / 0 unrun by --ran (DERIVED zero), all exit 0 after one prerequisite build; --pair 18476 exit 0; mcp_calls 0; api_writes 3 REST + 3 pushes, all read back; skip-changeset read back.
    • CI on 6f008921 at review: 19 success · 11 skipped · 3 in progress · 0 failed.
    • Deviations answered: the labels POST outside the dispatch budget is the dev file's standard budget (it wins) — accepted; the pre-PR rebase on an unshared branch with a lease pin — accepted (five unshared-branch criteria stated); nothing else deviates.

    Landing (governed rules layer, ruling C): four-piece hung on PR #18476 — this record, 维护者速读(终稿), needs-user-decision, review requested from an approver account; the PR stays draft until an authorized APPROVED, then the seat flips ready and arms auto-merge via the ccr routes. Card stays pm:dispatched until MERGED.

    Implemented-by: claude/issue-18468-harness-current-report-only (mode:subagent)
    Reviewed-by: session_01Wj1HUjzyeiBQ8atRf1ZhaL


    Generated by Claude Code

  7. removed their assignment
    on Sep 16, 2026
  8. hotlong commented on Sep 16, 2026

    @hotlong
    ContributorAuthor

    Landed — director seat, session_01Wj1HUjzyeiBQ8atRf1ZhaL · 2026-09-16T15:53Z

    PR #18476 (head 6f008921) merged by the queue as d3c81164d1 at 2026-09-16T15:52:46Z (merged_by os-zhuang, the approver who flipped ready and enqueued); git log origin/main carries (#18476) at the tip. Governed landing by ruling C: APPROVED 5224793115 on that head, in-seat ACCEPT (stamped 2026-09-16T14:49Z), provenance on the PR. Now on origin/main: SKILL.md:92 reads 「否 ⇒ 记座位贴,自然收班时换会话,⛔ 不中断批次」 and check-harness-current reports instead of prescribing — the maintainer's ruling D in text. Same act: pm:dispatched removed and the assignee cleared on this auto-closed card; domain:skills stays.


    Generated by Claude Code

  9. added 3 commits that reference this issue on Sep 17, 2026
    d3c8116
    674872a
    3dfcee2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions