Repository navigation
pm-dispatch: a declared narrowing is the fourth contract-review face, at CONTRACT_REVIEW_TIER - #23750
Conversation
…eview face Ruling record 6203713500 (letter B): ruling C stands as a face of its own under B-prime. `REVIEW_FACES` gains `narrowing`, mapped to `CONTRACT_REVIEW_TIER` exactly, keyed on the `Clause-②: no (narrowing)` line read by `readClause2Line`. `reviewFace` takes the declaration's carrier texts as an optional third input; a path list that decides no face and carries a changeset nobody read is UNREADABLE, never the cheaper tier, and `--template/--brief-template --paths` refuse it in favour of `--face`. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VqGhCg9wdsBXPz54uAEWg7
… its fourth face Ruling record 6203713500 (letter B): the three contract faces become four. A `Clause-②: no (narrowing)` line at line start in the PR body and the changeset puts the review at `CONTRACT_REVIEW_TIER`, its floor the whole diff outside the prose faces; the face reads the committed file list and the declaration line. Net +1 line (47 to 48, ceiling 60 unchanged). Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VqGhCg9wdsBXPz54uAEWg7
Without the `narrowing` row the template and brief calls refuse; each case now turns that refusal into its own red so an ablation reads the case names. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VqGhCg9wdsBXPz54uAEWg7
席位核对Seat Implemented-by:
Generated by Claude Code |
Contract reviewServed-tier: ① Derived judgmentsEvery accept-set and public-surface change the diff implies, judged in the cited code at this head:
Check-runs on this head, read 2026-10-16T00:16Z: 47 runs, all completed. The five required contexts — ② Semver level
③ Boundary flagsDev deviations (os-dev-report 6204819375):
Open questions, which are also the seat's three accepted design choices (ACCEPT 6204870805):
Out-of-scope findings (carrier: none; acceptance notes):
Reviewer's own flags:
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #23692
Clause-②: no
Implements ruling record 6203713500 (letter B, maintainer 「B (推荐)」): ruling C (6053791774) stands as a face of its own under ruling B′ (6159870311). A card declared
Clause-②: nothat narrows a published accept set owes one isolated review atCONTRACT_REVIEW_TIER, exactly.What changed
scripts/pm/record-recognisers.mjsREVIEW_FACESgainsnarrowing, mapped toCONTRACT_REVIEW_TIER_NAME. The decision order isschema,rules,narrowing,declaration.REVIEW_TIER_NAMESis unchanged: still two names.reviewFace(paths, repo, { declaredOn })takes one optional, named third input: the texts theClause-②:line is written on. Those are each committed changeset's text, plus the PR body where the caller holds it. The texts are read withreadClause2Line, imported fromclause2-line.mjs; there is no second parser.servedTierStandsis unchanged. Because the face now answersCONTRACT_REVIEW_TIER_NAMEon a narrowing PR, it accepts aCONTRACT_REVIEW_TIERrecord there and refusesTIER_DEFAULT(ruling item 1).--templateand--brief-template,--face narrowingis listed from the face table. The narrowing brief sets the scope floor at every path of the diff outside the prose faces, with no lane remainder.--pathsover a list the face cannot be read from is refused: exit 1, with the usage, the reason, and a pointer to--face.letter B: a declared NARROWING is a face of its own …(17 cases, floor 17; the roster floor goes from 11 to 12). The closed-set case now expects four faces..claude/skills/pm-dispatch/references/contract-review.md: net +1 line (47 → 48; the ceiling stays at 60).CONTRACT_REVIEW_TIER, and a scope floor of the whole diff outside the prose faces.execution-duties.mdis not touched (ruling item 2). Neither are the frozendispatch-gates.mjs,dispatch-gates.data.mjsanddispatch-gates.self-test.mjs, orcheck-governed-queue-guard.mjs.Design answer: how the face learns the declaration (dispatch §2 (b))
declaredOn. Results forschemaandrulesare byte-identical to the two-argument call. A case pins this byJSON.stringifyequality with a narrowing line, with a malformed line, and with no line.(narrowing)arm on any carrier gives the narrowing face. Otherwise, amalformedline on any carrier gives UNREADABLE:readClause2Linecollapses near-miss arms such as(narrowed)intomalformedprecisely so they cannot read as no narrowing. Otherwise the result is the declaration face..changesetmarkdown file other than the README), the result is UNREADABLE:face: null,tierName: null, plus areason.servedTierStandsstands nothing on that, so the reading is never the cheaper tier. This is the queue guard's own rule for a pair with no path list, applied one level down. If the list carries no changeset, the declaration face stands, byte-identical to before. A narrowing of a published accept set moves a published package and therefore ships a changeset, so a committed tree with no changeset carries no narrowing declaration.reviewFace(pair.paths, pair.repo)with no declaration. Its self-test pinsrecordVerdictstanding atTIER_DEFAULTon a declaration-only pair whose paths include no changeset (casethe-SAME-reading-STANDS-a-TIER_DEFAULT-record-on-a-declaration-only-pair). The requiredGoverned Surface Queue Guardcheck runs that self-test first. An unconditional UNREADABLE would turn that case red, and fixing it would need an edit tocheck-governed-queue-guard.mjs, which is outside this card's file surface. The changeset rule keeps that pin true and still refuses the narrowing-only shape that met PR fix(metadata-protocol)!: the promote doors ask ADR-0029 D9.9's question the save door asks (#23630) #23683. So the PM reading in §2 (e) holds: no guard edit is owed. The guard self-test passes 322 cases before and after.Three choices for the reviewer to judge:
yes (narrowing)line maps to the narrowing face. The arm decides, the way one hit decides a mixed diff. The ruling's text names only theno (narrowing)spelling.hitsfloor would be empty on this face.Verification at head
4c15f575bDefect reproduced at
3b46855fb:--brief-template --pathsover a list shaped like PR fix(metadata-protocol)!: the promote doors ask ADR-0029 D9.9's question the save door asks (#23630) #23683's (one changeset,packages/metadata-protocol/src/protocol.ts, one runtime test) printed "You review atTIER_DEFAULT". At this head the same command exits 1 and names--face narrowing.pnpm check:pm-record-recognisers(--self-test): 184 cases passed at the base and 201 pass at the head, exit 0.Ablation:
scripts/ablation-replace.mjsdeleted thenarrowingrow ofREVIEW_FACES(anchor ×1 → ×0, blobe0e82d93bad8→23a1eb6ce055). The self-test then exited 1 with 8 of 201 cases red:Clause-②: no (narrowing)on its changeset ⇒ the narrowing face, CONTRACT_REVIEW_TIERyes (narrowing)is the narrowing face — a diff that widens and narrows owes the narrowing review, as a mixed diff owes its hit--face narrowing's record carries CONTRACT_REVIEW_TIER and theScope:line, round-trips through the locator and STANDS on the narrowing face--template --face narrowingprints exactly that template and exits 0--face narrowing, and floors the WHOLE diff — no lane remainderThe restore leg proved blob == HEAD (
e0e82d93bad8) with an emptygit diff HEAD. The restored run passes 201 cases, exit 0.node scripts/pm/check-governed-queue-guard.mjs --self-test: 322 cases pass, exit 0, before and after.check-skill-line-ratchetforcontract-review.md: "is 47 lines (ceiling 60; headroom 13)" before, "is 48 lines (ceiling 60; headroom 12)" after, exit 0.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat4c15f575bderives 37 commands, the same list as the dispatch. All 37 were run locally, each exit code captured before any pipe.--ranreports: "37 derived famil(ies) accounted for — 37 run, 0 NOT-MEASURED (a DERIVED zero — all 37 recorded an exit code and none of them is 3)".check:doc-formula-expressionsfirst exited 3 (PREREQUISITE NOT MET:@objectstack/formulanot built). After a rebuild of@objectstack/formulaand@objectstack/lintunder the verify lock (command-exit 0), it reran with exit 0.pnpm check:pm-dispatch-gatesexited 0: fast tier, 1884 cases, 6 slow sections deferred to CI.No control bytes in either file (scan exit 1 = no match). No changeset: neither
scripts/pm/**nor.claude/**publishes a package, so this PR carriesskip-changeset.Acceptance notes (observations; not edited, because the files are frozen or outside this card's surface)
scripts/pm/dispatch-gates.mjs:12013(comment: "the contract-review reference's three faces") now names three of four faces. The file is frozen.scripts/pm/dispatch-gates.data.mjs:1062("the three contract faces … a published schema, governed rules text, theClause-②: yesdeclaration") likewise. Frozen.scripts/pm/dispatch-gates.self-test.mjs:9961("the three contract faces") likewise. Frozen..claude/skills/pm-dispatch/references/lanes/ui.md:38still says 契约三面. It is outside this card's file surface (carrier: none).dispatch-gates.mjs:11794–11797(the--tierdocblock) and:11866–11873remain true. The--tiernote already says what ruling C says.TIER_DEFAULTon narrowing-only PRs before this lands, such as PR fix(metadata-protocol)!: the promote doors ask ADR-0029 D9.9's question the save door asks (#23630) #23683's, are not re-opened (ruling item 3).维护者速读(草稿)
改了什么:复核记录识别器新增第四个复核面「收窄」。PR 正文与 changeset 行首写
Clause-②: no (narrowing)的卡,其隔离复核档位定为CONTRACT_REVIEW_TIER,且只认这一档。规则文 contract-review.md 同步把「三面」改为「四面」,净增一行。为什么改:裁决 B 认定「收窄已发布接受集的卡欠一次契约复审档复核」是独立的一面。旧识别器没有这一面,收窄类 PR 只能按默认档复核,规则文与工具给出两个答案;本周已有四张收窄类 PR 遇到。
风险与代价(含回滚):风险小,只动 PM 工具与一份内部规则文,不发布任何包。若调用方没有交来申报内容,而 PR 带 changeset,识别器答「不可读」,不再默认给便宜档;命令行
--paths此时会拒绝并提示改用--face。队列守卫的线上行为不变(它只看 governed PR,永远按路径定面)。回滚:revert 本 PR 即可,无数据迁移。席位意见:
你要做的:无需动手。席位拿到达档契约复核 PASS 后按 Tier S 落地;如对上文三处设计取舍有不同意见,在卡上回一句即可。
Generated by Claude Code