Skip to content

fix(pm): C5 reports a widening tell instead of refusing on it #19490

Description

@os-steve

scripts/pm/check-clause2-carriers.mjs's C5 limb turns a widening tell into a hard refusal: a card declaring Clause-②: no whose diff carries tells makes --pair N exit 4, and PD #14 makes --pair at 0 a conjunct of the landing predicate.

Per the maintainer ruling at #18917 (comment), C5 should be demoted to report-only: the row still prints, with its file:line evidence and its remedy text, but it no longer contributes to a non-zero exit.

The operative distinction from that ruling record:

A limb that judges "is this diff widening a contract" — which check-widening-tells itself says it cannot prove (its header: "a tell, never a proof", "cannot tell an array element from a call argument") — does not hold a hard gate. A limb that asks "does a review of record exist" does.

C6 (an at-tier review of record on this head) stays a hard refusal. C2, C3, C8, C9 and the UNJUDGED exit-2 path keep their current behaviour.


Generated by Claude Code

Activity

  1. os-steve commented on Sep 21, 2026

    @os-steve
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 19490,
      "status": "done",
      "branch": "claude/issue-19490-c5-report-only",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19495",
      "session": "session_01AmH9bKvGoLjiY86Q4Z3og2",
      "premise_still_valid": true,
      "summary": "C5 in scripts/pm/check-clause2-carriers.mjs is demoted from hard refusal to report-only on the maintainer ruling of 2026-09-21 (comment 5755007166). The row is now built by the new pairReportRows() instead of being pushed into `rows`, whose emptiness is the exit-0 condition, so it prints in full -- file:line evidence, REFUSAL_SENTENCE's remedy verbatim, plus a new C5_REPORT_ONLY_DISPOSITION saying it is report-only, that the at-tier review rules on it, and that report-only is neither a clearance nor a verdict that the tell is false -- while moving no exit code. renderPair was split into the pure pairRendering (every line, its stream and the exit, computed before printing) and a printer, so the self-test can pin what a run PRINTS beside what it EXITS; greenPairLine gained a wideningReported branch so an exit-0 line carrying tells never reads as narrow. C6, C2, C3, C8, C9 and the UNJUDGED exit-2 path are untouched. No card existed, so this session created #19490 itself -- the brief predicted issue creation would be refused and it was not.",
      "tests": "ALL exit codes captured BEFORE any pipe (cmd > log 2>&1; EXIT=$?). LIVE PAIRS -- `--pair 19314`: BEFORE exit 4, sole adverse row `x C5`, 7 tells; AFTER exit 0, row now `flag C5`, same 7 tells. grep -c 'T2 packages/spec/src/stack.zod.ts' reads 7 on the before log and 7 on the after log (stack.zod.ts:3412 through :3418, each with its T2 explanation and its + source line) -- 19314 reaches 0 because C5 no longer refuses, not because a tell disappeared. `--pair 19438`: exit 4 BEFORE and exit 4 AFTER, row `x C6`, untouched. `--pair 19495` (this PR itself): exit 4 on C2, because card #19490 carries no Claim: comment; the branch shape is fine, so it is NOT the exit-2 UNJUDGED the brief predicted. SELF-TEST: 1075 -> 1099 cases, exit 0; new battery `the 2026-09-21 ruling: C5 REPORTS its tell, C6 still REFUSES`, 24 cases, declared in SELF_TEST_BATTERIES at its measured floor of 24. ABLATIONS (6, each via scripts/ablation-replace.mjs so the on-disk landing is the tool's own verdict -- anchor 1 -> 0 plus blob-hash before/after -- and each restore proved by blob == HEAD and an empty `git diff HEAD`): (1) put C5 back into `rows` -> 6 red, incl. 'a C5 tell and NOTHING else reaches EXIT 0'; (2) delete the printReports body -> 9 red, incl. row printed / file:line / evidence list / remedy / disposition / marker; (3) delete greenPairLine's wideningReported branch -> exactly 1 red; (4) delete the C6 row push in pairRows -> 14 red, incl. C6-refuses and MIXED; (5) make pairReportRows return [] -> 8 red, incl. the structural case; (6) make wideningUnjudged return null -> 4 red, incl. 'the UNJUDGED exit-2 path is untouched'. GATES, all exit 0: --self-test; node --check; pnpm exec eslint on the changed file; check-self-test-wired; check-scripts-symbol-anchors; check-governed-merges --test scripts/pm/check-clause2-carriers.mjs (NOT governed, ordinary queue landing; size 292 lines, under 5000); and all 35 commands derived by `node scripts/pm/dispatch-gates.mjs --commands` (three-dot from merge base d00692f5d, 1 changed path) -- every one exit 0, none red. NOT MEASURED: CI convergence on PR #19495 (reported before CI, per contract); dispatch-gates also names 54 artifact-roster families, 11 wide-population families, 7 pending-changeset families and 1 path-scheduled CI job as outside the 35 -- those are CI's runs, not this local scope.",
      "mcp_calls": "0 -- no MCP GitHub tool was called; every GitHub read and write went through the REST proxy with curl",
      "api_writes": "5 -- POST /repos/objectstack-ai/objectstack/issues (created card #19490); POST /repos/objectstack-ai/objectstack/pulls (draft PR #19495); POST /repos/objectstack-ai/objectstack/issues/19490/comments (this report); plus 2 git pushes (the empty-branch routing probe, then the single commit f7b1d5baa2). ZERO label writes and zero PATCH, per the brief.",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: the demotion broke NO existing self-test case -- the full 1075-case suite was green on the edited file before a single new case was added, so the old 'C5 refuses' behaviour was pinned nowhere at the rendering level. That is a fact about this file's coverage, not a defect with a repro, so it is not one of the three filing classes. Successor: this PR, which adds the rendering-level pins.",
        "noted, not filed: REFUSAL_SENTENCE in check-widening-tells.mjs still reads as a refusal's remedy ('An explanation in the claim moves no exit code') while C5 no longer refuses. Every clause in it stays TRUE and actionable, so this is wording that could be tightened, not a defect; and that file is explicitly off-limits for this change. Successor: whoever next edits check-widening-tells.mjs."
      ]
    }

    Generated by Claude Code

  2. self-assigned this
    on Sep 21, 2026
  3. os-steve commented on Sep 21, 2026

    @os-steve
    CollaboratorAuthor

    Claim: PM loop round 15
    Session: session_01AmH9bKvGoLjiY86Q4Z3og2
    Branch: claude/issue-19490-c5-report-only
    Worktree: os-19490
    Domain: domain:spec
    Seat: domain:spec#4
    File surface: scripts/pm/check-clause2-carriers.mjs — one file, held
    Container & model: M, mode:subagent, model: opus
    Clause-②: no
    Thread-read: 5755272783
    Serial constraints cleared: none — no other open PR touches scripts/pm/check-clause2-carriers.mjs, read off the 17 open PRs' file lists at this claim, ⛔ not recalled.


    Written after the work, and the reason is on the record rather than smoothed over. This card was created by the dispatched executor at 2026-09-21T03:31Z, and the branch it pushed already carries the contract shape. The executor correctly declined to write this claim — a claim is the owning seat's act — so the card sat claim-less until now, which is exactly what CI caught: the check 「The card this PR closes must claim this branch」 failed on PR #19495 for that reason and for no other. ⛔ This is a seat lateness, not a defect in the delivery.

    ⚠️ priority:* is deliberately NOT written here — grading is triage's. domain:spec and the pm:* state are this seat's to set and are set.

    What this seat verified first-hand before claiming, at 2026-09-21T04:14Z

    ⛔ None of this is adopted from the executor's report. Every exit code captured before any pipe; the after-side run was made in a detached worktree at the PR head f7b1d5baa259dbd733bb62678ac77eb7576d8b06, the before-side in a checkout at origin/main d00692f5d4.

    reading main (before) PR head (after)
    --pair 19314 exit 4 0
    --pair 19438 exit 4 4 — C6 untouched
    T2 packages/spec/src/stack.zod.ts lines printed on the 19314 run 7 7
    ⭐ control, same grep, a string that is in neither log 0 0
    the C5 row's marker ✗ ⚑
    check-governed-merges.mjs --test scripts/pm/check-clause2-carriers.mjs exit 0 — ⛔ NOT governed same
    PR file list, read from the platform 1 file, +260 / −32

    ⇒ #19314 reaches 0 because C5 stopped refusing, ⛔ not because a tell disappeared. The seven tells at stack.zod.ts:3412-3418 print identically on both sides, with their evidence and the remedy verbatim, and the after-side row says in its own words that report-only is neither a clearance nor a verdict that the tell is false. That was the whole risk in this change — a demotion that goes silent — and it is measured closed.

    The two red checks, both this seat's to clear

    check cause act
    The card this PR closes must claim this branch no Claim: on this card this comment
    Check Changeset none written skip-changeset added to PR #19495 — the gate's own text names the label as 「the author's explicit opt-out … this PR declares no release of its own」, and this diff touches one file under scripts/pm/, no publishable package, so no release is owed

    ⛔ Neither was a rerun-and-hope: both were read to their cause before anything was written.


    Generated by Claude Code

  4. added a commit that references this issue on Sep 28, 2026
    d114d4c
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