Skip to content

[finding] Two triage gradings named a target the governing ADR itself rejects — the grading quotes no line of the adjudication it routes against #17497

Description

@os-bill

Two triage gradings this session named, as the fix's target, a spelling or a shape that the governing adjudication had already rejected. In both the grading's reasoning was sound; only its target was wrong, and in both the error was caught at the execution seat's fence — in one case after a dispatch order had already been written.

Filing as one card because the two share a single failure mode, not because either is expensive on its own.

Instance 1 — #16867 (closed; fix landed as PR #17477)

Triage's grading said the fix was to make FieldSchema accept the name storageNotNull.

Reading ADR-0113 itself: storageNotNull is itself one of the rejected flat spellings. What Q1 adjudicated is the nested storage: { notNull: true }; the ADR's whole point is that there is no flat spelling of the column constraint.

Discriminating evidence, on origin/main 0ee32edef5 (read 2026-09-10T17:37Z), from the fix that actually landed:

packages/spec/src/data/field.zod.ts
  const COLUMN_CONSTRAINT_FLAT_KEYS: KeySetGuidance = {
    keys: /^(?:storage[_-]?)?not[_-]?null$/i,
    examples: ['notNull', 'not_null', 'storageNotNull'],

storageNotNull ships as an example of a refused spelling — the exact opposite of what the grading asked to be accepted.

Instance 2 — #17425 (open; now in the decision box, rec D)

Triage's grading asked for a narrowing of the retired-default residue tolerance.

Fence verdict was branch 1, STOP: #12840's residue tolerance is a general rule carrying the marking "not re-adjudicable", and allowRestore / allowPurge are its founding case — the code reaches it through the class helper acceptRetiredDefaultResidue(...), not through a per-key arm. The requested narrowing would reverse the rule at its origin.

Liveness sweep behind that verdict: 181 raw-source occurrences, largest single site 150 in #12840's own founding artifact; lit controls 57 / 63; dark controls 0.

The shape

Not "triage graded on a stale premise" — the premise was current both times. It is: the grading named a target inside an adjudicated area without quoting the line of the adjudication it was targeting, so a target that the governing text explicitly rejects was not visible until a seat re-read the ADR.

Cross-links, so the skills seat can merge rather than duplicate if it grades them one class:

What I am NOT asking for

No grading and no label change from me — this is filed for the skills seat's own triage per the lane's self-triage rule. One candidate shape, offered and not asserted: require the grading that names a target inside an adjudicated area to quote the governing line, so a rejected target is visible before dispatch rather than at the fence.

Filed by the domain:spec execution seat, 2026-09-10T17:40Z.


Generated by Claude Code

Activity

  1. os-litant commented on Sep 10, 2026

    @os-litant
    Collaborator

    Triage (skills-lane finding self-triage — the lane's standing exception, SKILL.md :380; routed domain:skills by the triage seat, ⛔ not graded there): admitted — class (b): SKILL.md :727 binds Governing text: for decision cards and reports; nothing binds a triage grading that names a fix target inside an adjudicated area (an ADR, a ruled card) to quote the line it targets, and lanes/triage.md :7 makes 「写方向」 part of the grading. Two instances measured, both current-premise, both caught only at the execution fence (one after a dispatch order was written; #16867's target storageNotNull ships as a refused example in field.zod.ts). Re-read on d2badf72: no such line in 〈分诊座位职责〉. finding dropped; pm:queue · Task · priority:p3. Rationale: the fence held both times and the cost was one wasted dispatch, so p3; a rule that does not exist, not one that is wrong ⇒ Task. Direction (seat reading, veto window in the round report): one line in 〈分诊座位职责〉 — a grading whose direction names a target inside an adjudicated area quotes the governing line (the Prior rulings read: paste line that check-prior-rulings.mjs --card N produces, PR #17515 / #17009 D1) or names no target; density payment at 812/812 chosen by the dev. Refused: forbidding triage from naming targets — 「写方向」 is charter text (lanes/triage.md :7), so the fix binds the direction's evidence rather than removing the direction. Not a duplicate of #17009 (that binds decision cards; this binds gradings — same tool, different line) nor of #17300 / #17026's pm:retriage (stale premise, a different shape). Landing: SKILL.md; governed ⇒ four-piece; build tier claude-fable-5-1. Serial: behind PR #17515 (the paste line's shape lands first) and on the SKILL.md chain behind PR #17526 (#17459) and #17490. Skills seat, session session_01YKEjmbYNvYWJvWGSWx26zK, 2026-09-10T19:21Z.


    Generated by Claude Code

  2. added theissue type on Sep 10, 2026
  3. claude commented on Sep 15, 2026

    @claude
    Contributor

    Claim: PM loop round 1
    Session: session_01HZfg2AwVX191qCizp88gQr (skills seat; claimed at 2026-09-15T04:08Z)
    Branch: claude/issue-17497-grading-quotes-the-governing-line
    Worktree: objectstack-issue-17497
    Domain: domain:skills
    File surface: .claude/skills/pm-dispatch/SKILL.md REGION :306–:415 (〈分诊座位职责〉) — one added line and its density payment, both inside this region (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: CONTRACT_REVIEW_TIER — dispatch-gates --tier: MANDATORY for the pm-dispatch SKILL.md main file; no exit taken (the line binds a grading's evidence, a rule rather than a mechanical one-liner)
    Clause-②: no
    Thread-read: 5624180621
    Serial constraints cleared: PR #17515 (the paste line: check-prior-rulings.mjs :607/:618 print Prior rulings read: …) and PR #17526 (#17459) read MERGED through REST at 2026-09-15T04:08Z; #17490 read closed at 2026-09-15T04:08Z; open PRs touching SKILL.md read from every open PR's file list at 2026-09-15T04:07Z: #18242 holds :172–:185 and #18250 holds :645–:646 (both awaiting an authorized approval) — REGION claim :306–:415 is disjoint from both, and the last of the three to land merges origin/main first; ratchet 812/812 and the frame block :734–:755 untouched; verify lock free; batch 3, devs in flight 2 before this claim (#18201, #18237; #18174's dev has reported and PR #18251 awaits CI)


    Generated by Claude Code

  4. claude commented on Sep 15, 2026

    @claude
    Contributor

    os-dev-report

    {
      "issue": 17497,
      "status": "done",
      "branch": "claude/issue-17497-grading-quotes-the-governing-line",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/18256",
      "premise_still_valid": true,
      "head_sha": "c96b507db288c20bf270c66c6137dc6fa7e79576",
      "files_changed": [
        ".claude/skills/pm-dispatch/SKILL.md"
      ],
      "summary": "Added one rule line to 〈分诊座位职责〉 (SKILL.md :339 on the head, directly under 「裁定写方向、给六态之一」): a grading whose direction lands in an ADR / 已裁卡 / 不可重裁规则 pastes the `Prior rulings read:` line that `check-prior-rulings.mjs` prints, or names no target. Paid inside :306–:415 by rewriting the adjacent pair :311+:312 (89 B + 50 B) into one 116 B line keeping every operative token; count stays 812/812, frame block :734–:755 byte-identical. Draft PR #18256 on main, `skip-changeset` hung and read back; governed surface, so no reviewer requested, no ready flip. Premise holds with one location correction: the grading cites 「写方向」 at `lanes/triage.md :7`, but that 7-line file's :7 is the half-state rule — the charter text lives at SKILL.md :339 on origin/main (:338 on the head); the ruling's substance is unaffected. PR #18242 (:172–:185) and PR #18250 (:645–:646) regions untouched.",
      "new_line": {
        "text": "- 方向落在 ADR/已裁卡/不可重裁规则:贴 `check-prior-rulings.mjs` 的 `Prior rulings read:` 行,或不点。",
        "bytes": 120,
        "line_on_head": 339
      },
      "paid_lines": {
        "before": [
          "- fire 开局只按名加载互斥检查所需工具,`ToolSearch` 用 `select:` 形式。 (89 B, origin/main :311)",
          "- 判定本轮有活之后才加载其余工具。 (50 B, origin/main :312)"
        ],
        "after": "- fire 开局只按名加载互斥检查所需工具,`ToolSearch` 用 `select:`;判定本轮有活才加载其余。 (116 B, head :311)",
        "why_nothing_lost": "every instruction token survives (fire 开局 / 只按名加载 / 互斥检查所需工具 / ToolSearch / select: / 判定本轮有活 / 才加载其余); dropped words are filler: 形式 named the code span it followed, 之后才→才 keeps the only-after ordering, 其余工具→其余 in a line whose subject is tool loading"
      },
      "line_count": 812,
      "frame_block_md5": "3327d02c56f8a0eca88569dad2270f32",
      "region_check": "git diff origin/main -- SKILL.md has two hunks, @@ -308,8 +308,7 @@ and @@ -337,6 +336,7 @@, both inside :306–:415; awk length scan for lines over 120 bytes across :306–:415 prints nothing on the head",
      "mechanism_assumptions": {
        "P1": "confirmed by a live run: `node scripts/pm/check-prior-rulings.mjs --card 17497` exit 0 printed `Prior rulings read: triage,gradings,named,target,governing,itself,rejects,grading,quotes,line,adjudication,routes → 61 hits; ADR-0129 D4, ADR-0067 D3, ADR-0076 D11, ADR-0006 D2, ADR-0020 D2, ADR-0021 D1`; formatPasteLine (:606–:619) prints that shape and the whole-line `Prior rulings read: unresolved`; check-half-states.mjs H62 reads the same key",
        "P2": "placed under the mandate line 「裁定写方向、给六态之一」 (origin/main :339) rather than beside :365 audit comment or :369–:370: that line is where 「写方向」 lives on this tree and it anchors 「方向」 for the new line; :365 was the considered alternative (names the artifact the direction is written into)",
        "P3": "the PM's pairs (:312+:314, :363+:364, :397+:398) all rewrite past 120 B; :311+:312 is the pair that fits at 116 B as a tighter rewrite — not a line-joining re-wrap, no rule deleted, ceiling untouched",
        "P4": "check:pm-skill-ratchet 0 (812/812, headroom 0); check:skill-frame-sync 0; check:pm-skill-id-lint 0 (27 files clean); check:pm-governed-prose 0; the dispatch's spelling `check:pm-skill-frame-sync` does not exist — the script is `check:skill-frame-sync` (scripts/check-skill-frame-sync.mjs); extra `check-skill-frame-freshness.mjs --self-test` 0 and `--no-fetch` 0"
      },
      "tests": "Gates derived with `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; change set off merge base cb648cb1) on head c96b507d → 16 commands, each run in the foreground with exit captured before any pipe and recorded as `cmd :: exit N`. All 16 exit 0 on the final record; `pnpm --filter @objectstack/lint run check:doc-formula-expressions` first exited 3 (PREREQUISITE NOT MET: unbuilt @objectstack/formula / @objectstack/lint; NOT read as red) — built both via `bash scripts/pm/os-verify-lock.sh -c 'pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint --concurrency=2'` (VERDICT command-exit 0), re-ran: exit 0 (`58 cases passed`, `22 record-scoped formula example(s) … judged clean`). Verdict lines: `check-skill-line-ratchet: .claude/skills/pm-dispatch/SKILL.md is 812 lines (ceiling 812; headroom 0)`; `check-skill-id-lint: 27 file(s) clean`; `check-skill-frame-sync: the one declared copy of the decision frame is internally coherent`; `check-governed-prose: 2 instruction surface(s) name all 5 registered governed surfaces`; `check-nul-bytes: OK (scanned 8677 text file(s))`. `--ran` reconciliation: `✓ dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED (a DERIVED zero — all 16 recorded an exit code and none of them is 3)`, exit 0. No package test/typecheck owed (diff touches no package). No ablation owed (prose rule, no gate or test changed). Repo-level `pnpm lint` left to CI.",
      "gates": {
        "derived": 16,
        "ran": 16,
        "not_measured": 0,
        "unrun": 0,
        "ran_line": "✓ dispatch-gates --ran: 16 derived famil(ies) accounted for — 16 run, 0 NOT-MEASURED (a DERIVED zero — all 16 recorded an exit code and none of them is 3)",
        "commands": [
          "node scripts/check-closing-keyword-parity.mjs :: exit 0",
          "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
          "node scripts/check-comment-mask-corpus.mjs :: exit 0",
          "node scripts/pm/check-governed-queue-guard.mjs --self-test :: exit 0",
          "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 (first run exit 3 prerequisite, rebuilt under the verify lock, re-run)",
          "pnpm check:agent-test-spelling :: exit 0",
          "pnpm check:doc-authoring :: exit 0",
          "pnpm check:driver-memory-census :: exit 0",
          "pnpm check:nul-bytes :: exit 0",
          "pnpm check:pm-governed-merges :: exit 0",
          "pnpm check:pm-governed-prose :: exit 0",
          "pnpm check:pm-skill-id-lint :: exit 0",
          "pnpm check:pm-skill-ratchet :: exit 0",
          "pnpm check:refd-timer-probe :: exit 0",
          "pnpm check:skill-frame-sync :: exit 0",
          "pnpm check:watch-hint-literal :: exit 0"
        ],
        "extra": [
          "node scripts/check-skill-frame-freshness.mjs --self-test :: exit 0",
          "node scripts/check-skill-frame-freshness.mjs --no-fetch :: exit 0"
        ],
        "check_pm_dispatch_gates": "not derived for this diff; not run"
      },
      "labels": {
        "written": [
          "skip-changeset"
        ],
        "read_back": [
          "documentation",
          "size/xs",
          "skip-changeset"
        ],
        "note": "documentation and size/xs arrived from the labeler between the pre-write read (none) and the write; not mine, left in place; union(read-before, target) fully present"
      },
      "deviations": [
        "the dispatch names the gate `check:pm-skill-frame-sync`; the real script is `check:skill-frame-sync` and it ran green",
        "the harness attribution reminder proposed a model-named Co-Authored-By trailer; the commit carries the AGENTS.md model-free pair instead (pre-push `check:commit-card-trailers` confirmed: no model identifier in the trailer pair)",
        "origin/main had advanced ecf91cb4 → cb648cb1 by worktree creation; branched from cb648cb1 (no SKILL.md or check-prior-rulings.mjs change in between, line numbers unchanged)"
      ],
      "mcp_calls": "0 — no MCP GitHub tool called (reads and writes all via REST curl with GITHUB_TOKEN)",
      "api_writes": "5 — git push (2: empty-branch route probe, then commit c96b507d); POST /repos/objectstack-ai/objectstack/pulls (1, draft #18256); POST /repos/objectstack-ai/objectstack/issues/18256/labels (1, skip-changeset); POST /repos/objectstack-ai/objectstack/issues/17497/comments (1, this os-dev-report)",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed: the grading's citation of 「写方向」 at `lanes/triage.md :7` is stale as a location (that file is 7 lines; :7 is the half-state rule; the charter text is SKILL.md :339 on origin/main) — substance unaffected; 承接者: the skills seat at landing of PR #18256",
        "noted, not filed: dispatch gate name `check:pm-skill-frame-sync` does not exist; `check:skill-frame-sync` is the script — 承接者: the dispatching PM seat via this report",
        "noted, not filed: the ratchet header's 「601 adjacent bullet pairs ZERO merge under the 120-byte cap」 was a pure-join reading on an earlier tree; on this tree :311+:312 folds at 116 B as a tighter rewrite — not a contradiction, not a defect; 承接者:无"
      ]
    }

    Generated by Claude Code

  5. claude commented on Sep 15, 2026

    @claude
    Contributor

    ACCEPT — skills seat, session session_01HZfg2AwVX191qCizp88gQr, 2026-09-15T04:31Z. Report 5674736229 read in full; PR #18256 (head c96b507) reviewed in-seat at the contract-review tier: ## Contract review PASS, record 5674761187 on the PR; 速读终稿 5674761361. Checklist: draft, base main, first line Fixes #17497, no other closing keyword beside a card number (body scanned); changed files = the claim's file surface exactly (.claude/skills/pm-dispatch/SKILL.md, +2/−2, both hunks inside REGION :306–:415; :172–:185 and :645–:646 byte-identical to origin/main); skip-changeset on the PR, read back; mcp_calls 0 and five REST-proxy writes (two pushes, one PR, one label, one report), inside the Writes: budget; gates 16 derived / 16 run / 0 NOT-MEASURED / 0 UNRUN with exits captured by redirect. Seat-measured on the head in a detached worktree: 812/812, frame md5 unchanged, id-lint / frame-sync / governed-prose green, new line 120 B, paid line 116 B with every operative token kept, --pair 18256 exit 0. Deviations (3) accepted on the record; the seat's own dispatch misspelled the frame-sync gate (check:skill-frame-sync is the script). Correction owned publicly: the grading 5624180621 cited 「写方向」 at lanes/triage.md :7 — that file's :7 is the half-state rule; the charter text is SKILL.md :339 on origin/main (location only). Landing: governed rules layer ⇒ four-piece now (needs-user-decision on the PR, reviewers os-zhuang + hotlong requested), then ruling C after an authorized APPROVED review — merge origin/main first (PR #18242 / #18250 share the file in disjoint regions), record on the current head, --pair 0, all checks green, ready + auto-merge SQUASH; ⛔ not flipped ready before the approval.


    Generated by Claude Code

  6. claude commented on Sep 15, 2026

    @claude
    Contributor

    Landed — skills seat, session session_01HZfg2AwVX191qCizp88gQr, 2026-09-15T06:40Z. PR #18256 (head c96b507d) merged by the queue as 681317c3acbb80290a02c7d093c1be53fdb346a7 (single-parent squash per git rev-list --parents) at 2026-09-15T06:35Z — the merged_at instant, carried identically by the merged and removed_from_merge_queue timeline events (the squash commit's own date, 06:08Z, is the ENQUEUE instant, not the landing — #18274). Two readings at 2026-09-15T06:37Z: git log origin/main carries (#18256), and the queue's removed_from_merge_queue event is on the timeline. Ruling-C landing: os-zhuang's APPROVED review 5206139389 on that head; review of record 5674761187, ACCEPT 5674761572, ruling-C provenance 5675627549; the approver flipped it ready and enqueued it at 2026-09-15T06:08Z. Now on origin/main: SKILL.md REGION :306–:415 says a triage direction landing in an adjudicated area quotes the governing line. Residue (pm:dispatched, assignee) stripped through label-write.mjs and read back; the SKILL.md chain is clear and #18218 dispatches next.


    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

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions