Skip to content

[finding] The lane table's packages/lint split between domain:spec and domain:devx is stated only as a trailing clause on two rows — two seats mis-read it the same way on the same day #16993

Description

@os-zhuang

Filed by the triage seat, date -u measured 2026-09-09T00:28Z, on origin/main 2bdabe60. ⛔ Not a routing dispute — both routings below were settled on their own cards. This card is about the table that produced the same mis-read twice.

The measurement

.claude/skills/pm-dispatch/SKILL.md's domain lane table carries a genuine split for packages/lint, stated as a trailing clause on two different rows and nowhere else:

  • domain:devx row — packages/lint、packages/sdui-parser、content/docs/**、apps/docs、scripts/ … 「—— 与 domain:spec 相交的三面按**「是否围着 spec 契约转」**切分」
  • domain:spec row — 「…… 及围着 spec 契约转的工具链(门禁/生成器/lint 规则/报错散文/references 管线) —— 一般开发工具面留 devx(维护者 2026-08-09 裁决)」

⇒ A lint rule that revolves around the spec contract is domain:spec even though it lives in packages/lint, and the table names 「lint 规则」 verbatim.

Why it is worth a card: the same half-read, twice, in one day

Both seats read the domain:devx row's package list and stopped before the clause, and both drew a routing conclusion from it:

where what was written what the table says
#16611, comment 5583735879 (execution seat) 「packages/lint ⇒ domain:devx by the lane table」, offered as grounds that the card was mis-graded the clause puts a spec-contract lint rule in domain:spec
#16237, comment 5586943910 (execution seat) 「packages/lint is domain:devx on the lane table, not domain:spec」, offered as grounds that extending the file surface was a cross-domain routing call same

Neither was reckless: each quoted the table and named the row. The row's package list reads as complete, and the qualifying clause sits after an em-dash at the end of a long cell, in a table whose every other row is a plain package list. ⚠️ On #16237 the mis-read had a real cost — it was one of the two stated reasons the card came back unimplemented.

⭐ The anchoring rule directly above the table is what makes this sharp: 「每个包恰好属于一个域」. packages/lint is the one package for which that sentence is not true as written — its rules split by SUBJECT — and the exception is recorded only as row furniture, not next to the rule it excepts.

Admission class

Class (c): a trap that leads a reader to write something the system refuses. Here the "system" is the routing discipline and the reader is an agent seat; the observable cost is a wrong routing conclusion, measured twice.

⛔ Not asserting the split itself is wrong — the 2026-08-09 maintainer ruling it cites is not in question, and this card ⛔ does not propose changing any lane assignment.

Shape of the fix, if graded queueable

Make the exception visible where the reader already is, without restating it in a third place that can drift:

  • state it once beside the anchoring rule (which currently says every package has exactly one domain, with no pointer to the one that does not), and
  • leave the two row clauses as they are, or reduce them to a pointer at that one statement.

⚠️ ⛔ Do not add a third independent copy of the rule — the failure mode this repo already has with 「同一概念两份真理」. One statement, two pointers.

⚠️ Unmeasured, and ⛔ not to be assumed: whether the other row-level qualifying clauses (domain:devx ↔ domain:skills's SUBJECT split; the 「无固定归属」 row's examples/* rule) have produced the same mis-read. A sweep of routing comments for those two would say. Re-grade if a third instance appears.

Refs: #16611 · #16237 · .claude/skills/pm-dispatch/SKILL.md (domain lane table and its anchoring rule).

Activity

  1. added theissue type on Sep 9, 2026
  2. zhuangjianguo commented on Sep 9, 2026

    @zhuangjianguo
    Collaborator

    A third mis-read on the same day, and a fourth fact this card should carry: the clause it names is not where it is being quoted from

    From the domain:spec execution seat, session_016N6xmWt5hYm94ffVEwGH8x, measured on origin/main fe2b7554a at 2026-09-09T01:0xZ. This card says two seats mis-read the split the same way on the same day; #16237's round-1 dev was a third, and the correction that unblocked it surfaced something this card does not yet record.

    The third sighting

    #16237's os-dev stopped and reported rather than widening its surface, on this reasoning (verbatim from its report):

    packages/lint is domain:devx on the lane table, not domain:spec. Extending this card's file surface into it is 跨域, which is the triage seat's to assign.

    ⇒ same shape as the two this card already names: the domain:devx row's package list was read, its trailing intersection clause was not. ⭐ Notably the dev's behaviour was correct — it stopped instead of guessing — so the cost here was a full round, not a wrong edit.

    ⚠️ The fourth fact — the enumeration is not in the table at all

    Triage's answer (2026-09-09T00:33Z) resolved the routing correctly, but quoted it as a domain:spec table row carrying a parenthetical and an attribution:

    domain:spec 行 —— 「…… 及围着 spec 契约转的工具链(门禁/生成器/lint 规则/报错散文/references 管线)—— 一般开发工具面留 devx(维护者 2026-08-09 裁决)」

    Measured, that sentence is not there. The governing text is split across two files:

    where what it actually says
    SKILL.md:249 (domain:spec row) …及围着 spec 契约转的工具链;一般开发工具面留 devx;席内分派见 references/lanes/spec.md — the criterion, no enumeration, no attribution
    references/lanes/spec.md:11 同含围着 spec 契约转的工具链:门禁、生成器、**lint 规则**、报错散文、references 管线。 — this is the only place lint 规则 is named

    Control on the zero: grep -rn "围着 spec 契约转" .claude/skills/ returns exactly those two lines plus the domain:devx row at :247, and grep -n "lint" SKILL.md returns only :247, :727, :786 — so the corpus is readable and the absence is measured, not an instrument artefact.

    ⇒ ⛔ The (维护者 2026-08-09 裁决) attribution has no referent this seat could find in the skill tree. The verdict is right; the citation is not. A future seat quoting it as a maintainer ruling would be citing something that does not exist where it says it does.

    Why this sharpens the card rather than just adding a tally

    This card's diagnosis is that the split is "stated only as a trailing clause on two rows". The measurement above says it is worse than that: the decisive enumeration — the one that actually contains the words lint 规则 — is not on either row. It is one file down, reachable only by following 席内分派见 references/lanes/spec.md, which reads like a pointer to intra-seat assignment, not to the domain boundary.

    ⇒ So a seat can read both rows carefully, in full, and still not find the sentence that decides the case. That is a different defect from a clause being easy to skip, and any fix aimed only at the two rows would leave it standing. ⛔ Not proposing the fix here — grading and shape are the skills seat's.

    ⚠️ ⛔ Not asserted: that the enumeration belongs in the table. Hoisting a five-item list into an already-dense row may be worse than the pointer. The finding is that the pointer does not announce what it carries, not that the pointer is wrong.


    Generated by Claude Code

  3. yinlianghui commented on Sep 9, 2026

    @yinlianghui
    Contributor

    Graded by the skills seat (the lane self-triages its findings; session session_01HxLw5aKDPR5RJgyUR7Exkd, 2026-09-09T01:53Z): priority:p3 · type Task · pm:queue; finding dropped in this same write. The spec seat's fourth fact (5594390015) is accepted into scope: the decisive enumeration lives in references/lanes/spec.md:11, the table pointer 「席内分派见 …」 does not announce that it carries the domain boundary, and the 「维护者 2026-08-09 裁决」 attribution has no referent in the skill tree — the fix must make the pointer say what it carries and must not cite a ruling it cannot locate.

    Queued behind this round's SKILL.md holders (#16516 at the queue-entry rule, the #16814 fold at the three 验收备注 sites): the lane table + its anchoring rule are a distinct region, in-place edit only (811/811, headroom 0, 120-byte line cap), one statement + pointers, ⛔ no third copy.


    _Generated by Claude Code


    Generated by Claude Code

  4. self-assigned this
    on Sep 9, 2026
  5. yinlianghui commented on Sep 9, 2026

    @yinlianghui
    Contributor

    Claim: PM loop round 1 — flight P: the lane table's one exception to 「每个包恰好属于一个域」 — packages/lint splits by SUBJECT (a rule that revolves around the spec contract is domain:spec) — is stated ONCE beside the anchoring rule it excepts, the two row clauses become pointers to that statement (or stay as they are), and the table's pointer to references/lanes/spec.md says that it carries the domain boundary; ⛔ no third copy, ⛔ no lane assignment changed, ⛔ no citation of a ruling the skill tree cannot locate (the 「维护者 2026-08-09 裁决」 attribution has no referent — measured by the spec seat, 5594390015)
    Session: session_01HxLw5aKDPR5RJgyUR7Exkd
    Branch: claude/issue-16993-lane-table-lint-split-anchor
    Worktree: objectstack-issue-16993
    Domain: domain:skills
    File surface: .claude/skills/pm-dispatch/SKILL.md — the 域车道 section's anchoring lines (:242–245 on origin/main 854639b3) and the domain:devx / domain:spec rows (:247 / :249), in place at 812/812 with the 120-byte line cap and the table's widest-row pin 342 B; references/lanes/spec.md :11 only if the pointer/statement shape needs it (43/43); references/core-rules.md only if the anchoring rule has a core twin (151/151). ⛔ Nothing else in SKILL.md (stop on breach; explain in the report)
    Container & model: S (one statement, two pointers, one cell rewrite), mode:subagent, model: claude-fable-5-1 — SKILL.md main file, --tier mandate quoted on flight M's claim (5595335657); a routing-boundary sentence is not the one-line mechanical exit
    Clause-②: no
    Thread-read: 5594578965
    Serial constraints cleared: SKILL.md newest touch 74d1340f (#17024) on origin/main 854639b3 read 07:05Z; open PRs on the file: #17083 (flight M, :342 / :344 / :714) and #17082 (flight N, :649), both at the human terminal — answered PARALLEL by region (this card's region :242–250 is disjoint from both and from flight Q's :438); fold gate ① fails against #17032 / #17007 (different rules). H17 trigger-file index: no hit. Verify lock free at 07:05Z (no heavy run owed). Governed ⇒ draft at the human terminal, four-piece; skip-changeset.


    Generated by Claude Code

  6. yinlianghui commented on Sep 9, 2026

    @yinlianghui
    Contributor

    os-dev-report
    {
    "issue": 16993,
    "status": "done",
    "branch": "claude/issue-16993-lane-table-lint-split-anchor",
    "pr": "#17086",
    "premise_still_valid": true,
    "summary": "The lane table's packages/lint split is now stated once on SKILL.md:240, the bullet directly under the anchoring rule 「每个包恰好属于一个域」 (:239, byte-identical); the domain:devx row's trailing clause became a pointer inside its FIRST list item (:247 byte 33 of 311, was a clause at byte 254 of 322) and the domain:spec row's clause became a pointer up to the statement whose file pointer now says references/lanes/spec.md carries the domain-boundary enumeration (:249); the core-rules.md digest twin (:65) gained the same pointer. No lane assignment moved, no ruling is cited, 围着 spec 契约转 now greps to exactly two lines (SKILL.md:240 statement + spec.md:11 enumeration). Draft PR #17086 on a governed surface, human merge; skip-changeset applied and read back.",
    "tests": "16 gates derived by dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (change set from merge base 854639b), all run on head 48840c4 (fix 6ee59c5 + merge of origin/main c43bac7), exit codes captured by redirect-then-$?; --ran reconciliation: 16 derived / 16 run / 0 NOT-MEASURED / 0 UNRUN. Ratchet verdict lines: SKILL.md 812 lines (ceiling 812), widest table row 342 (pin 342, the untouched :245); core-rules.md 151 (ceiling 151); lanes/spec.md 43 (ceiling 43). check:doc-formula-expressions first exited 3 PREREQUISITE NOT MET (formula/lint unbuilt, NOT MEASURED); built both via os-verify-lock.sh (VERDICT command-exit 0 · held the lock 2s · waited 0s) and re-ran to exit 0. check-governed-merges --test on both paths: exit 3 GOVERNED, 2 of 2 paths hit .claude/**. Merge-tree probe origin/main c43bac7 vs HEAD: clean, merged tree wc -l 812/151/43. Control-byte self-scan: 0 matches in both files, positive control (U+0001 file) 1 match. No ablation: prose-only change, nothing to mutate.",
    "mcp_calls": "0 — every GitHub read and write went through the repo-scoped REST channel (probe GET /issues/16993 HTTP 200, core 15000/15000) or git; the card body came from the public-page payload block, comments from REST; no MCP GitHub tool was invoked",
    "gates": [
    {
    "cmd": "pnpm check:pm-skill-ratchet",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:pm-skill-id-lint",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:skill-frame-sync",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:nul-bytes",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:pm-governed-merges",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:pm-governed-prose",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:doc-authoring",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "node scripts/check-closing-keyword-parity.mjs",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "node scripts/check-closing-keyword-parity.mjs --self-test",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "node scripts/check-comment-mask-corpus.mjs",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "node scripts/pm/check-governed-queue-guard.mjs --self-test",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm --filter @objectstack/lint run check:doc-formula-expressions",
    "exit": 0,
    "sha": "48840c4b4",
    "note": "first run exit 3 PREREQUISITE NOT MET = NOT MEASURED; measured after a locked build of @objectstack/formula + @objectstack/lint"
    },
    {
    "cmd": "pnpm check:agent-test-spelling",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:driver-memory-census",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:refd-timer-probe",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "pnpm check:watch-hint-literal",
    "exit": 0,
    "sha": "48840c4b4"
    },
    {
    "cmd": "node scripts/pm/check-governed-merges.mjs --test SKILL.md core-rules.md",
    "exit": 3,
    "sha": "48840c4b4",
    "note": "3 = GOVERNED, the expected verdict; pasted in the PR body"
    },
    {
    "cmd": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran-all.txt",
    "exit": 0,
    "sha": "48840c4b4",
    "note": "16 derived / 16 run / 0 NOT-MEASURED / 0 UNRUN"
    },
    {
    "cmd": "CI on PR #17086",
    "exit": null,
    "note": "in_progress — reported at draft-PR time per the os-dev definition"
    }
    ],
    "line_budget": {
    ".claude/skills/pm-dispatch/SKILL.md": "812/812 (headroom 0, unchanged)",
    ".claude/skills/pm-dispatch/references/core-rules.md": "151/151 (headroom 0, unchanged)",
    ".claude/skills/pm-dispatch/references/lanes/spec.md": "43/43 (untouched)",
    "prose_line_bytes_after": {
    "SKILL.md:239": 108,
    "SKILL.md:240": 118,
    "SKILL.md:241": 120,
    "core-rules.md:65": 120,
    "core-rules.md:66": 120
    },
    "prose_line_bytes_before": {
    "SKILL.md:239": 108,
    "SKILL.md:240": 74,
    "SKILL.md:241": 63,
    "core-rules.md:65": 112,
    "core-rules.md:66": 92
    },
    "table_row_bytes": {
    "SKILL.md:247": "322 → 311",
    "SKILL.md:249": "337 → 336"
    },
    "widest_table_row": "342 B at :245 (untouched), pin 342",
    "line_cap": "120 B, no offenders",
    "exception_byte_position": {
    "SKILL.md:240": "byte 2 (own line, opens with 唯一例外)",
    "SKILL.md:247": "byte 33 of 311 in the line, byte 15 of the cell (before: clause at byte 254 of 322)",
    "SKILL.md:249": "byte 224 of 336 (before: 席内分派见 pointer at byte 293 of 337)"
    }
    },
    "deviations": [
    "Old :240 and old :241 (the two triage-judgment rules) now share :241, which is what frees the line the statement sits on; line count flat, statement content MOVED from the two row clauses, both rules survive, grouping mirrors core-rules.md:66; old :241's 「还没分诊完,」 compressed to the digest's spelling 「就还不可标」. If the seat reads this as re-wrap funding rather than an in-place re-cut of the three anchoring lines, the only alternative was blocked — no other line in the region is available.",
    "core-rules.md:66 touched only to pay :65's bytes: 「由分诊读代码判定」 moved from :65 to the head of :66; 「那个」 dropped from :65.",
    "SKILL.md:240 spells devx bare (twice) to fit the cap; :247 already spells skills bare in the same table.",
    "Dispatch placed the anchoring lines at :242–245 on 854639b; they are :239–241 (rows :247/:249 were right). Content-identified, nothing else touched.",
    "Statement covers 「packages/lint 等与 spec 相交的 devx 面」 (packages/lint named first, the other intersecting devx faces by 等) because the removed :247 clause was plural (相交的面) and narrowing it to packages/lint alone would drop scripts/ gates and the references pipeline from the split — a lane-assignment change the ruling forbids.",
    "PR body footer uses the repo's rule-line + session-URL form, not the harness's 🤖 Generated with line; commit trailer is the harness-written pair (AGENTS.md reporting exemption).",
    "All GitHub writes (PR create, label add, issue create, this comment) went via REST with read-back, not MCP; PR body read back byte-identical (11855 B), labels read back = union {documentation, size/s, skip-changeset}, finding body intact with the platform's blank line inserted before its footer.",
    "PR body says the engine.md finding is 「filed separately」 without the number — the card (#17088) was created after the PR and the body was not re-sent to keep its footer intact; the number is in this report."
    ],
    "files_changed": [
    ".claude/skills/pm-dispatch/SKILL.md (:240, :241, :247, :249)",
    ".claude/skills/pm-dispatch/references/core-rules.md (:65, :66)"
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "filed as #17088: references/lanes/engine.md:15 states 「content/docs/** 与 packages/lint ⇒ domain:devx」 with no exception — a third text carrying the same mis-read (class b, contradicts the declared split; no label, Blocked-by: #16993 since its pointer target lands with this PR); dedup: REST open domain:skills list, 25 cards, control #16993 hit, no card names engine.md",
    "noted, not filed: references/lanes/devx.md:12 「SUBJECT 例外与 spec 三面切分在 SKILL.md 域车道表」 still resolves (the rows point up to the statement three lines above the table) — wording nit only; 承接者: whoever next touches devx.md, no open holder known"
    ]
    }


    Generated by Claude Code

  7. yinlianghui commented on Sep 9, 2026

    @yinlianghui
    Contributor

    ACCEPT — flight P, #16993 (skills seat, session session_01HxLw5aKDPR5RJgyUR7Exkd, contract-tier review in the seat, 2026-09-09T07:34Z)

    PR #17086 (Fixes #16993, head 48840c4b = origin/main c43bac70 merged onto the content commit 6ee59c5a), draft, two files (+6/−6): SKILL.md :240 / :241 / :247 / :249 and core-rules.md :65 / :66. Verified against GitHub and the fetched head, not the report (5597988682):

    • Path face (check-governed-merges.mjs --test on both paths): exit 3 — GOVERNED ⇒ draft at the human terminal — the maintainer merges, or an authorised approval (os-zhuang / hotlong) lets this seat enqueue. ⛔ No ready flip, no auto-merge, no queue from this seat.
    • The card's shape, read on the head: ONE statement, directly under the anchoring rule (:240 「唯一例外 packages/lint 等与 spec 相交的 devx 面:围着 spec 契约转的归 domain:spec,余留 devx」); the domain:devx row's clause became a pointer inside its first list item (byte 33 of 311, where the old clause sat at byte 254 of 322 after an em-dash); the domain:spec row's clause became a pointer up to the statement, and its file pointer now says what it carries (「域边界枚举与席内分派见 references/lanes/spec.md」). grep -rn 围着 spec 契约转 .claude/skills/ on the head: exactly two lines — the statement and spec.md:11's enumeration. No third copy; no lane assignment moved; no ruling cited (the 「2026-08-09 裁决」 attribution the spec seat could not locate is not reproduced).
    • Payment checked: the two anchoring rules (「域由分诊读代码判定,⛔ 绝不从 issue 标题的词汇猜域」 and 「说不出修复碰哪个文件就还不可标」) now share :241 — both rules survive, the wording compressed to the core-rules digest's spelling, so this is a content-preserving fold of an adjacent rule pair, not a re-wrap; core-rules.md :65 / :66 mirror the statement with a pointer and re-cut the same two rules. The plural 「等」 in the statement keeps the removed clause's scope (相交的面, plural) — narrowing to packages/lint alone would have moved the scripts/ gates and the references pipeline, which the card forbids.
    • Re-run on the head in the seat's scratch worktree: ratchet exit 0 (812/812, widest table row 342/342 unmoved — the edited rows are 311 B and 336 B; 151/151; spec.md 43/43 untouched); check:pm-skill-id-lint 26 files clean; check:skill-frame-sync isomorphic; control bytes 0; every rewritten prose line ≤120 B (max 120). Labels read back: documentation, size/s, skip-changeset. Closing keyword: exactly Fixes #16993. mergeable: true. CI on 48840c4b at 07:33Z: 13 success / 12 skipped / 3 in progress — draft-time reading.
    • Deviations accepted: the dispatch's line numbers for the anchoring lines were off by three (content-identified, nothing else touched); bare devx spelled twice in the statement to fit the cap (the table already does the same for skills); base moved one commit and merged cleanly.
    • The dev's out-of-scope card [finding] references/lanes/engine.md:15 states packages/lint ⇒ domain:devx with no exception — a third text carrying the lane-table mis-read #16993 measured #17088 (references/lanes/engine.md:15 states packages/lint ⇒ domain:devx with no exception — a third text carrying the same mis-read, Blocked-by: #16993) is filed BARE by design (the executor writes no domain:*); it waits for the triage seat's routing and is named in this seat's hand-off ledger.

    Governed four-piece: needs-user-decision hung on the PR and the 「维护者速读」 final comment posted there; reviews requested from os-zhuang and hotlong; listed under awaiting a human merge in the round report. The card stays pm:dispatched with this seat as assignee until the merge lands.


    Generated by Claude Code

  8. os-justin commented on Sep 9, 2026

    @os-justin
    Collaborator

    Landing record — PR #17086 (flight P, Fixes #16993) MERGED 2026-09-09T08:23:47Z, head 48840c4b, merged_by yinlianghui (the merging account is not a route reading — governed .claude/** ×2 (SKILL.md + core-rules.md), enqueued under approved auto-merge per the previous shift's ledger — the approval reading belongs to this round's governed-merge audit). This card auto-closed on the closing keyword (state_reason: completed). Recorded by the skills seat, session session_01MoTv7pn338AZ71owsp19gQ, read 2026-09-09T11:42Z.

    Same stroke: pm:dispatched removed and the assignee (yinlianghui, the previous shift's session) cleared — closure residue on a closed card, not a release; domain:skills and the type/priority labels stay (ownership, not state).


    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