Skip to content

docs(pm): a spec narrowing may declare Clause-2 yes — the conservative direction is never an error - #18135

Merged
claude[bot] merged 1 commit into
mainfrom
claude/issue-17963-narrowing-declares-yes-line
Sep 14, 2026
Merged

docs(pm): a spec narrowing may declare Clause-2 yes — the conservative direction is never an error#18135
claude[bot] merged 1 commit into
mainfrom
claude/issue-17963-narrowing-declares-yes-line

Conversation

@claude

@claude claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #17963

Why

references/lanes/spec.md answered one question — what trips clause ② — and was silent on the other: whether declaring Clause-②: yes on a narrowing anyway is allowed. With the rulebook silent, a PR body became the authority. The measured cause, verbatim from PR #17498's body:

This is a spec narrowing, and the objectui#8285 precedent says a spec narrowing declares yes.

That is a per-card director ruling, not rulebook text, and nothing in that body says so. Both statements are true at once — the rulebook says what trips clause ② mechanically, the ruling said what one card should declare — but nothing said so in one place, so the next author either argues about which text wins or quietly stops declaring on narrowings because the rulebook says they do not trip.

The conservative direction was already sanctioned in this same skill, just never joined to the narrowing rule. references/contract-review.md (unchanged by this PR) carries both:

Clause-②: yes | no 按设计临时:只定是否必过席内契约复核的保守方向,⛔ 非终审。

claim 拿不准 ⇒ 按 yes 挂标走席内契约复核;⛔ 不建全量分类学与 claim 时决策程序。

The edit

One rule line, inserted directly under the rule it reconciles (:19 → new :20):

- 收窄不触发条款②,但按 `yes` 申报恒不是错误;⛔ 个案裁决不改本行。

93 bytes. It carries all three ruled halves: a narrowing does not TRIP clause ②, declaring yes on one is never an error, and a per-card ruling does not change this line. No issue number in operational text, so the provenance above lives in this PR rather than in the rule.

Line budget — net 0, ceiling untouched

lanes/spec.md is pinned at 43 lines (scripts/pm/check-skill-line-ratchet.mjs), zero headroom, every line ≤ 120 bytes.

  • Extending :19 in place was measured first and does not fit. :19 is 108 bytes; the budget leaves 12 bytes — four CJK characters — and the shortest wording carrying the new substance needs 30 or more.
  • The line is therefore paid for by deleting content, not by re-wrapping. - 生成物门禁重生成提交,⛔ 手改。 leaves the same section. Its rule survives elsewhere, in files that outrank this one:
    • AGENTS.md → the Documentation Guardrails table (AUTO-GEN ❌ Never hand-edit. Regenerated by …), § Touched packages/spec? Regenerate its artifacts BEFORE pushing (match the change to the gate and regenerate up front; no check: script regenerates anything), and Multi-agent discipline §11 (pre-commit refuses a commit that still owes a regeneration).
    • this skill → references/core-rules.md 「入队资格是每一个检查全绿 ⛔ 不是必查子集;碰生成物的 PR 入队前先同步再重生成。」 and references/landing-operations.md §A.
  • Arithmetic: 43 → 43 lines, +1 / −1. LC_ALL=C awk 'length($0)>120' over the file prints nothing, before and after.

Acceptance greps (both directions)

assertion reading
new clause present git grep -n '恒不是错误' -- .claude/skills/pm-dispatch/references/lanes/spec.md → 0 hits on origin/main, 1 hit (:20) here
lit control (the grep is not vacuous) git grep -n '收窄' -- …/lanes/spec.md:19 still hits, plus the new :20
file surface git diff --stat origin/main1 file changed, 1 insertion(+), 1 deletion(-)
neighbours untouched git diff --stat a90a9f267 -- …/contract-review.md …/core-rules.md …/SKILL.md → empty for each
line count 43 → 43
byte width every edited line ≤ 120 bytes (LC_ALL=C awk)

Gates

Derived with node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths — the tool takes its own change set), all run in the foreground with $? captured before any pipe, then reconciled with --ran:

✓ dispatch-gates --ran: 15 derived famil(ies) accounted for — 15 run, 0 NOT-MEASURED (a DERIVED zero — all 15 recorded an exit code and none of them is 3).

All 15 exit 0, plus pnpm check:pm-governed-prose (exit 0, outside the derivation, named by the dispatch). The named ones: check:pm-skill-ratchet, check:pm-skill-id-lint, check:pm-governed-prose, check:nul-bytes — the ratchet's own verdict line reads ✓ check-skill-line-ratchet: declared cross-file moves: 1, total ceilings down 9 lines. with no ceiling raised.

Seven of the sixteen first exited 3 (PREREQUISITE NOT MET) in the fresh worktree — not a verdict. Six cleared after pnpm install; check:doc-formula-expressions also needed pnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lint, run under scripts/pm/os-verify-lock.sh (VERDICT command-exit 0 · held the lock 172s · waited 0s), and then exited 0.

Local verification scope

The diff touches no package, so there is no dependency-closure build and no package test or typecheck to owe. The repo-wide lint is CI's run, and the narrowing here is an empty intersection measured by eslint itself, not asserted: pnpm exec eslint --no-inline-config --format json on the edited path reports one file, 0 errors, and the warning File ignored because no matching configuration was supplied — every files: selector in eslint.config.mjs names only .ts/.tsx/.mts/.cts/.js/.jsx/.mjs/.cjs, so a Markdown file is outside the linted population and cannot move any untouched file's verdict.

Changeset

skip-changeset label, applied through the additive labels endpoint and read back. .claude/** ships in no package's files[] — it publishes nothing.

Acceptance notes (out of scope, not filed)

  • The card's own citations have drifted by line number: it cites contract-review.md:9 for 「拿不准 ⇒ 按 yes」, which on a90a9f267 is :14 (:9 is the 保守方向 line), and core-rules.md:113 for the review rule, which on a90a9f267 is :112 (:113 is the dispatch-word rule). Nothing in the tree is wrong; this is why the new line cites by content and not by number. Successor: whoever reads this card next — no repo change owed.
  • lanes/spec.md:25 points at 「SKILL.md 模型分档」, which is not a heading in SKILL.md; the rules it means are under ### 派发 and the keyword does occur there (:501), so the pointer resolves by grep, not by section. Polish, not a defect. Successor: the next edit to either file.

维护者速读(草稿)

改了什么 —— PM 技能包 spec 车道说明加一行规则:收窄不触发条款②,但按 yes 申报恒不是错误,个案裁决不改这条。行数配额是零余量,这行由同一节里删掉「生成物门禁重生成提交,⛔ 手改」买单 —— 那条规则在 AGENTS.md 与本技能包的 core-rules / landing-operations 里都还在,不是丢掉。

为什么改 —— 规则只写了「什么触发条款②」,没写「不触发的能不能照样申报」。空白处被一份 PR 正文顶上去当了权威:它引一张个案裁决说收窄要申报 yes。两句话其实都对(一个讲机制,一个讲那张卡),但没有一处把它们放在一起,下一个作者就得在两份文本之间二选一,或者干脆不再申报。一行话把口子合上,保守方向照旧许可,成本是零 —— 语义面卡本来就按契约复审档施工。

风险与代价(含回滚) —— 代价是删掉的那条生成物提醒不再出现在 spec 车道页,读者要去 AGENTS.md 看(那份文件本来就要求全文读,且冲突时它为准)。风险低:纯说明文字,无代码、无发布面、无生成物。回滚 = revert 这一个 commit,文件回到 43 行原样。

席位意见 ——

你要做的 —— 受管面(.claude/**),按 Prime Directive #14 由维护者人工合并:本 PR 保持 draft,未挂 ready、未入队、未开 auto-merge。确认那一行读起来就是你要的裁决,以及「删这条买那条」的取舍你接受,然后人工合并。

Generated by Claude Code


Generated by Claude Code

…e direction is never an error

The spec lane's rule says a narrowing does not TRIP clause 2, and nothing said
whether declaring it anyway is allowed, so an author reading a per-card ruling in
a PR body inferred the opposite rule. One line states both halves and clamps the
per-card ruling out of rulebook standing.

Net 0 lines under the pm skill ratchet: the generated-artifact hand-edit clause
is dropped from the same section — that rule survives in AGENTS.md (the
Documentation Guardrails table and the "Touched packages/spec? Regenerate its
artifacts BEFORE pushing" section) and, for the landing half, in this skill's
core-rules and landing-operations.

Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8
Co-authored-by: Claude <noreply@anthropic.com>
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 14, 2026
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 14, 2026
@claude

claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author
  • Served-tier: 2167/2167 CONTRACT_REVIEW_TIER — harness model stamp counted over this seat's own transcript (non-sidechain assistant messages a model served; <synthetic> harness notices excluded) at 2026-09-14T05:44Z and compared to the constant's value outside the repository; get_session external_metadata.last_served_model read equal to the constant at 2026-09-14T00:20Z.

Contract review

Head: 24947ab0 (PR #18135, card #17963) — reviewed at 2026-09-14T05:45Z by the skills seat at the contract-review tier. GOVERNED references tier (references/lanes/spec.md only; no rules-layer file) ⇒ this in-seat record is the landing record at the tier PR #18036 enforces: the seat readies and arms auto-merge after it; no approval is owed.

① derived judgments (seat-measured on the fetched head 24947ab0 against merge-base a90a9f26, ⛔ not taken from the report):

  1. The one line: lanes/spec.md :20 「- 收窄不触发条款②,但按 yes 申报恒不是错误;⛔ 个案裁决不改本行。」 — 93 bytes, one rule, directly under :19 「…收窄仍是语义面,不触条款②。」, carrying the card's three halves (a narrowing does not trip clause ②; declaring yes on one is never an error; a per-card ruling does not change the line); no issue number in operational text.
  2. Net 0 at 43/43, paid by deleted content: 「- 生成物门禁重生成提交,⛔ 手改。」 (was :22, 46 B) is gone; its rule survives on origin/main in os-dev.md :195 / :198, SKILL.md :648, core-rules.md :124 and landing-operations.md §A (seat grep) — a fold, not a re-wrap. In-place extension of :19 measured and rejected by the dev (108 B, 12 B headroom); every line ≤120 B (LC_ALL=C awk empty on the head); ratchet and frame-sync exit 0 on the head (seat-run in a worktree).
  3. Premise re-read: contract-review.md carries the conservative direction (:9 「只定是否必过席内契约复核的保守方向」) and the conservative grant (「claim 拿不准 ⇒ 按 yes」, at :14 on main — the card's :9 / core-rules :113 line numbers had drifted; the new line cites by content and needs none); lanes/spec.md :24 「拿不准 FLAG 回分诊」 is the triage-flag rule, not a yes grant, so the gap was real. The measured cause — PR fix(spec)!: refuse a padded grouping.fields[].field name at the producer instead of handing three renderers a lookup that always misses #17498's body citing objectui#8285 — is quoted, not edited.
  4. Gates: 15 derived / 15 run / 0 NOT-MEASURED / 0 UNRUN with exit codes recorded, plus check:pm-governed-prose exit 0; seven exit-3 prerequisites built (install + a formula/lint build under the verify lock, 172 s held) and re-run to 0. Checks on the head at 2026-09-14T05:44Z: 15 success / 12 skipped / 2 in progress / 0 red.
  5. Scope held: one file, +1/−1; contract-review.md, core-rules.md, SKILL.md untouched (empty diff-stat each); skip-changeset is the declaration; Clause-②: no holds — no contract path; --pair 18135 on origin/main's reader → exit 0 at 2026-09-14T05:44Z before this record; three REST writes, zero MCP calls per the report.

② semver: unchanged — nothing published.

③ boundary flags: the PR body stores two footers (the create channel appended its own after a footer sent without a leading rule — platform-readings' fourth shape); left as is, a PATCH would add a third. The dev's out-of-scope note that lanes/spec.md :25 points at 「SKILL.md 模型分档」, a keyword rather than a heading — polish for the next edit of either file, no card.

Implemented-by: claude/issue-17963-narrowing-declares-yes-line
Reviewed-by: session_01DAcomhvR9kKizeYgg89Vo8

Verdict: PASS — references tier ⇒ this seat lands: ready through POST …/pulls/18135/ccr/ready_for_review with read-back, then PUT …/ccr/auto_merge; Fixes #17963 closes the card on landing.

维护者速读(终稿)

lanes/spec.md 多一行:收窄不触发条款②,但按 yes 申报永远不算错,个案裁决不改这一行;为守住 43 行上限删了一句「生成物重生成、不手改」,那条规则在 os-dev.md、SKILL.md、core-rules 与 landing-operations 里都还在。references 层,本席自审自落地,不需要你批。


Generated by Claude Code

@claude
claude Bot marked this pull request as ready for review September 14, 2026 05:45
@claude
claude Bot enabled auto-merge September 14, 2026 05:45
@claude
claude Bot added this pull request to the merge queue Sep 14, 2026
Merged via the queue into main with commit 739ab52 Sep 14, 2026
32 checks passed
@claude
claude Bot deleted the claude/issue-17963-narrowing-declares-yes-line branch September 14, 2026 06:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/xs skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pm-dispatch docs: lanes/spec.md says a narrowing does NOT trip clause ②, while a PR body cites objectui#8285 as saying it does

1 participant