Repository navigation
Model-tier policy: the contract-review tier is reserved for the skills seat (three protocol files + the published skills/** catalogs), the spec seat's clause-② review, and the maintainer-summoned director; triage and every other seat run the default tier #17285
Description
Activity
- addedpriority:p1High: required for production / M2High: required for production / M2
on Sep 10, 2026 Claim: skills seat, session
session_01MoTv7pn338AZ71owsp19gQ(GitHubos-justin), 2026-09-10T03:07Z — direct dispatch under the maintainer's chat instruction quoted verbatim in the body (直派通道).- Session:
session_01MoTv7pn338AZ71owsp19gQ - Branch:
claude/issue-17285-tier-policy - Worktree:
/home/user/objectstack-issue-17285, cut fromorigin/maind64bcb63(03:01Z) - Domain:
domain:skills— governed surface (.claude/**+scripts/pm/**) - File surface (region-declared):
.claude/skills/pm-dispatch/SKILL.md:75, :310–:311, :332, :398–:399, :507–:526, :767–:770;references/core-rules.md:18, :94, :98, :112, :147;references/contract-review.md:10–:18, :29, :34, :48–:60;references/lanes/director.mdone line;scripts/pm/dispatch-gates.mjsMANDATORY_TIER_GLOBS+ its docblock + self-test cases. Nothing else. - Container & model: L (protocol semantics across five files that all sit at their ratchet ceilings),
mode:subagent, build tier =CONTRACT_REVIEW_TIER(clause ①: the SKILL.md main file is onMANDATORY_TIER_GLOBS; passed explicitly as the dispatch's model parameter), review = skills-seat self-review at the same tier. - Clause-②: no — the card narrows and re-scopes who produces at-tier verdicts; no accept set and no public surface widens.
- Thread-read: card body; 0 comments at claim time (new card).
- Serial constraints: no open PR touches any file on this surface (23 open PRs' file lists read 03:0xZ); docs(skills): cite the platform-tool registry instead of restating it #17259 (this seat's other open PR) is on
skills/objectstack-ai/SKILL.md, disjoint. H17 intersection: dispatch-gates: STAGE-THEN-RUN reaches a program by an edge neither follow traverses — check:objectui-changeset inherits nothing from scripts/bump-objectui.sh #14290 (pm:on-hold, devx) carriesRestart-touch: scripts/pm/dispatch-gates.mjs— its restart precondition ([finding] extractWatchHints masks // but not # comments, so a shell target's inherited population is prose — latent until the first family follows a .sh #16132 closed) is the devx seat's to re-check on that card; ⛔ not folded here; its former riders [finding] dispatch-gates residue: after #12514 the extensionless-target reason is only reachable for a BARE hint, where it names the wrong cause — latent wrong-reason row, zero instances today #12797 / [finding] check-cross-package-test-inputs' docblock states the single-segment hint refusal without its one exception #12808 are closed (delivered on PR fix(devx): an artifact-roster row either judges the diff or says plainly that it cannot #16221). Verify-lock depth 0 at 03:01Z. - Premise checks: action face
git log -6per file read 03:01Z (newest touches: SKILL.mdd03c3c96, dispatch-gates6aa1d090, contract-review02643646, core-rules8efe2753, director7337179d); card-reference face: dispatch-gates: STAGE-THEN-RUN reaches a program by an edge neither follow traverses — check:objectui-changeset inherits nothing from scripts/bump-objectui.sh #14290 open on-hold, [finding] dispatch-gates residue: after #12514 the extensionless-target reason is only reachable for a BARE hint, where it names the wrong cause — latent wrong-reason row, zero instances today #12797/[finding] check-cross-package-test-inputs' docblock states the single-segment hint refusal without its one exception #12808 closed (read 03:0xZ); work-item face: every line the body cites was read ond64bcb63at 03:01Z.
Generated by Claude Code
- Session:
Dispatched — R8, 2026-09-10T03:11Z,
mode:subagent, build tierCONTRACT_REVIEW_TIERpassed explicitly (clause ①). Claim 5612043249 is the dev's identity; branchclaude/issue-17285-tier-policy. Governed terminal: draft + four-piece, skills-seat self-review at the same tier.
Generated by Claude Code
Ruling 5 executed — notices posted 2026-09-10T03:15Z (skills seat). Census method: every open issue and PR in objectstack (636), objectui (484) and hotcrm (75) had its body read, and every open PR or
pm:*-labelled card its full comment thread, forClause-②: yes, contract-review-tier / at-tier / 契约复审档 wording andSize/model suggestion:lines (started 03:00Z, finished 03:07Z). Population = open cards and PRs OUTSIDE the spec and skills lanes carrying such a requirement; spec-lane items keep their tier review and got none; bare (unlabelled) cards are triage's and got none.repo cards PRs knock on seat posts objectstack 35 (engine 8 · services 11 · cli 9 · devx 7) 5 (#16950 #17206 #17223 #17252 #17261 — none touches packages/spec)#6367 #6021 #6024 #6023 #6017 #6015 #12708 objectui 37 (ui 35 · devx 2; four of them quota-holds whose Restart-when:tier half is discharged)13 (cards in domain:ui)#5560 #5748 #5734 hotcrm 0 0 #1353 Two cards carry a caveat because their open PR touches
packages/spec(#16344 → PR #17195, #16549 → PR #17256): the spec seat's tier review still applies to those PRs as they stand. Every notice quotes the ruling verbatim, cites this card, and changes no label, assignee or claim. 90 comments, 0 errors.
Generated by Claude Code
Ruling 6 added 2026-09-10T03:16Z (maintainer, chat, verbatim): 「裁决(决策箱、代裁、一类自裁)是人工召唤,不需要fable,简单的元数据项目opus就可以,这个我人工判断。」 Body amended in place (ruling list, the adjudication table row and paragraph, the :398–:399 / :769 / director.md / contract-review.md / core-rules.md bullets): the director has NO tier hard gate — its tier is the maintainer's per-summon choice, recorded from the harness reading in the session audit line; 置信门 drops gate ⑤ and is four gates; the 降档保险丝 population is the spec seat's clause-② review and the skills seat only. The in-flight dev (claim 5612043249) was messaged the same minute; the branch is expected to carry the amended shape.
Generated by Claude Code
os-dev-report
{ "issue": 17285, "status": "done", "branch": "claude/issue-17285-tier-policy", "pr": "https://github.com/objectstack-ai/objectstack/pull/17294", "premise_still_valid": true, "summary": "Rule text now reserves the contract-review tier for the skills seat (three clause-① files plus the published skills/** catalogs, build and review) and the spec seat’s clause-② review; the triage seat (its emergency-triage subagent included — seat reading recorded in the PR body for veto) and every other execution seat run the default tier and spawn no contract-review-tier subagent; adjudication (decision inbox, 代裁, 一类自裁) is the maintainer-summoned director alone at the tier the maintainer chooses per summon — no hard gate, no 免档整理 state, 置信门 four gates (ruling 6, received 03:16Z as an in-flight amendment and verified on the card, folded in before the first push). dispatch-gates.mjs: MANDATORY_TIER_GLOBS gains skills/** with oneLineExit:false (the ruling’s 必须 closes the one-line exit by path), docblock corrected, tier rendering refuses the one-line exit on a skills/** hit and states the spec-seat-only clause-② review, 15 self-test cases added. Draft PR only (governed .claude/** + scripts/pm/**); no changeset — neither path ships in any package files[], PM applies skip-changeset. Assignee was already set by the PM; identity = claim 5612043249. PR body read back: content byte-identical to what was sent up to and including my session-URL footer (32846 B); the platform appended one more block (blank line, rule line, the same session-URL footer — the measured create-time behaviour), so the stored body carries two footers; per the standing rule it is not re-sent, and durable attribution sits in the body prose (Session: line).", "tests": "All on worktree /home/user/objectstack-issue-17285 at ec15afa1 (base ebf9a489 = origin/main at cut; main later advanced to a256f189 on a disjoint file). --tier acceptance (exit 0 each): skills/objectstack-data/SKILL.md and skills/objectstack-ai/SKILL.md → 「Model tier — MANDATORY: … ⇢ ’skills/**’ … the one-line-class mechanical-edit downgrade is ⛔ NOT available for this surface」; .claude/skills/pm-dispatch/references/core-rules.md → 「no path-derived mandate: the surface hits none of the 4 declared glob(s)」; skills/objectstack-pm-dispatch/SKILL.md → two hits, one tier, no ambiguity refusal. node scripts/pm/dispatch-gates.mjs --self-test (detached, outlived the 600 s cap — assumption E true): 「✓ dispatch-gates self-test: 1639 cases pass.」 exit 0, all 15 new cases found as ✓ by name. pnpm check:pm-dispatch-gates detached per its header, waited with tail --pid (03:47Z→04:00Z): log ends with the same pass line, no wrapper failure print; detached exit code not captured. Gate list derived with dispatch-gates --commands from the merge-base change set (39 commands, identical to the pre-edit five-path derivation) and every family run: check:pm-skill-ratchet 「✓ check-skill-line-ratchet: declared cross-file moves: 1, total ceilings down 9 lines.」; check:skill-frame-sync 「binding sentence present in all 2; 4 count mention(s) agree; 76 markdown files scanned」; check:skill-compatibility 「11 SKILL.md file(s) reconciled against 80 workspace packages」; check:pm-skill-id-lint 「27 file(s) clean」; check:nul-bytes 「OK … no raw ASCII control bytes」; check:pm-governed-prose 「2 instruction surface(s) name all 5 registered governed surfaces」; check:declared-population-live, check:watch-hint-literal, check:entry-guard, check:parse-guard, check:ratchet-remedy-authority, check:comment-mask-corpus 「6466 files, 0 disagree」 and the remaining node/pnpm families all exit 0 (verdict lines quoted in the PR body). check:doc-formula-expressions: first run exit 3 PREREQUISITE NOT MET; after building @objectstack/formula + @objectstack/lint under scripts/pm/os-verify-lock.sh (「VERDICT command-exit 0 · held the lock 191s · waited 0s」) exit 0 「✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 440 files / 1374 TS blocks judged clean」. check-governed-merges.mjs --test over the five files: exit 3 「⛔ GOVERNED — a human merge is the review record for this PR」 (.claude/** ×4). dispatch-gates --ran reconciliation: 「✓ dispatch-gates --ran: 39 derived famil(ies) accounted for — 39 run, 0 NOT-MEASURED.」 exit 0. Not run: repo-wide pnpm lint / pnpm test (CI’s; no package source touched, no build closure or package tests owed). Ablation: none owed — no runtime code path; the self-test’s existing mutation cases cover the tier table (dead-glob and ambiguity refusals) and the new cases pin both rendering directions.", "mcp_calls": "0 — every GitHub read and write went through repo-scoped REST (probe GET comments → 200 at 03:2xZ; POST pulls → 201) and git; no MCP GitHub tool was invoked", "open_questions": [], "out_of_scope_findings": [ "noted, not filed (no defect class; 承接者: the skills seat’s next charter pass on references/lanes/): references/lanes/skills.md:20 「pm-dispatch 根恒契约复审档」 and references/lanes/cli.md:18 stay true but do not mention the skills/** widening — both defer to --tier, which now carries it" ], "gates": { "check:pm-skill-ratchet": "green — ✓ check-skill-line-ratchet: declared cross-file moves: 1, total ceilings down 9 lines.", "check:skill-frame-sync": "green — binding sentence present in all 2; 4 count mention(s) agree; 76 markdown files scanned", "check:skill-compatibility": "green — 11 SKILL.md file(s) reconciled against 80 workspace packages", "check:pm-skill-id-lint": "green — 27 file(s) clean (pattern /#[0-9]{3,}/g)", "check:nul-bytes": "green — no raw ASCII control bytes", "dispatch-gates --self-test": "green — ✓ dispatch-gates self-test: 1639 cases pass. (15 new)", "check:pm-dispatch-gates": "green by log — same pass line, no wrapper failure print; detached exit code not captured", "check-governed-merges --test": "exit 3 GOVERNED (.claude/** ×4)", "check:doc-formula-expressions": "green after prerequisite build — 22 record-scoped formula example(s) … judged clean", "dispatch-gates --ran": "green — 39 derived famil(ies) accounted for — 39 run, 0 NOT-MEASURED", "other derived families (29 pnpm/node commands)": "all exit 0, verdict lines in the PR body", "not run": "repo-wide pnpm lint / pnpm test (CI); 2 CI-measured-only families; Test Core job steps" }, "line_budget": { ".claude/skills/pm-dispatch/SKILL.md": "812/812 → 812/812 (−2: :311, :399 deleted; +2: skills/** no-exemption row after :510, 唯一裁决者 row after :769)", ".claude/skills/pm-dispatch/references/core-rules.md": "151/151 → 151/151 (5 rows in place)", ".claude/skills/pm-dispatch/references/contract-review.md": "60/60 → 60/60 (−1: :19 merged into :20; +1: fuse-population row after :50)", ".claude/skills/pm-dispatch/references/lanes/director.md": "72/72 → 72/72 (5 rows in place)", "ceilings": "none raised, none lowered; every rewritten line ≤120 bytes (max 119 B)", "decision frame :735–:753": "md5 22f2339f0acb64cdb50c7adc9db681c3 unchanged" }, "deviations": [ "ruling-6 amendment (03:16Z, card comment 5612109163) applied over the original dispatch: :398–:399 deleted outright, :769 = maintainer’s per-summon tier with no hard gate, director.md :12–:14 rewritten, fuse population = spec clause-② review + skills seat, core-rules :94/:98 accordingly, 达档者 → 裁决者/总监席 where no tier is spoken of", "lines beyond the card’s declared regions, each forced by the twin rule (SKILL.md :44) or the ruling table: SKILL.md :639 and :642; contract-review.md :19–:20 (merge) and :42; director.md :47 and :72", "dispatch-gates.mjs tierLines edited beyond the exits line: the two clause-② sentences (they restated the superseded review scope in every claim comment); oneLineExit flag added as data on the skills/** entry", "no ruling date in any skill .md (corpus convention: rules carry no dates; the 2026-09-10 date lives in the dispatch-gates docblock/why and the PR body)", "gate spellings in the dispatch corrected: check:skill-line-ratchet → check:pm-skill-ratchet; check:doc-links / check:control-bytes / check:doc-fence-languages do not exist (derived list run instead; control bytes = check:nul-bytes); check-governed-queue-guard.mjs has no --test mode (reads GITHUB_EVENT_PATH, exit 1) — the predicate is check-governed-merges.mjs --test", "self-test count in the first body draft said 20; corrected to the 15 cases actually added before the PR was created" ], "files_changed": [ ".claude/skills/pm-dispatch/SKILL.md", ".claude/skills/pm-dispatch/references/core-rules.md", ".claude/skills/pm-dispatch/references/contract-review.md", ".claude/skills/pm-dispatch/references/lanes/director.md", "scripts/pm/dispatch-gates.mjs" ] }
Generated by Claude Code
ACCEPT — PR #17294 (head
ec15afa1) reviewed in-seat at the contract-review tier (skills seat, sessionsession_01MoTv7pn338AZ71owsp19gQ, 2026-09-10T04:25Z).- Implemented-by: os-dev subagent on branch
claude/issue-17285-tier-policy(claim 5612043249; build tierCONTRACT_REVIEW_TIERpassed explicitly;mode:subagent). - Reviewed-by: the skills seat, this session — independence pair holds (reviewer ≠ implementer); the seat's harness reading is the tier evidence per
references/contract-review.md. - Diff vs card (six rulings, ruling 6 included): every changed line was read in the diff and maps to a ruling — SKILL.md :75, :310 (two rows merged), :332, :397–:398 (置信门四条), :509 + the new :511 (
skills/**in clause ①, no one-line exemption), :513, :523, :638, :641, :767 / :769 / :770; core-rules :18 / :94 / :98 / :112 / :123; contract-review :10 / :12 / :13 / :15 / :19–:20 / :29 / :34 / :42 / :49–:50; director :12–:14 / :47 / :72; dispatch-gates: theskills/**entry withoneLineExit: false, the docblock,deriveTier/tierLines, and 15 self-test cases (each found by name in the log). The six lines beyond the declared regions are forced by the twin rule (SKILL.md :44) — accepted. No 「达档者」, no 「五条」 for 置信门, no model name and no issue number in any skill file. - Verified in the review worktree
/home/user/objectstack-review-17294atec15afa1: line counts 812 / 151 / 60 / 72 (each at its ceiling, headroom 0, none raised); decision-frame block :734–:752 md522f2339f0acb64cdb50c7adc9db681c3unchanged;--tierprints the mandate AND refuses the one-line exit forskills/objectstack-data/SKILL.mdandskills/objectstack-ai/SKILL.md, two hits at one tier forskills/objectstack-pm-dispatch/SKILL.md, no mandate forreferences/core-rules.md, the clause-② line now names the spec seat;pnpm -s check:pm-skill-ratchetexit 0,check:skill-frame-syncexit 0,check:skill-compatibilityexit 0,check:pm-skill-id-lint「27 file(s) clean」;check-governed-merges.mjs --testexit 3 GOVERNED (.claude/**×4).dispatch-gates.mjs --self-testre-run by this seat in a worktree with a realnode_modules: 「✓ dispatch-gates self-test: 1639 cases pass.」 exit 0 (a first attempt in the symlinked-node_modulesreview worktree crashed on an unrelated ignore-rule fixture —git check-ignore … beyond a symbolic link— environment, not this PR). - CI on
ec15afa1at 04:24Z: every check success or skipped; Check Changeset's newest run (04:07Z, afterskip-changesetwas applied by this seat) is skipped. - Terminal: governed (
.claude/**+scripts/pm/**) ⇒ the PR stays draft;needs-user-decisionplaced on the PR, 速读 终稿 posted there, reviews requested from os-zhuang and hotlong; ⛔ not flipped ready, not enqueued, no auto-merge, no approval from this seat. - Tracked outside this PR: A metadata project's cards live in that project's repo — hotcrm's decision cards included; only platform problems are filed on objectstack/objectui: fix the three SKILL.md rows and the core-rules twins that send them to the objectstack inbox #17288 (the inbox-location rows, serial after this merges); deletion of the published
skills/objectstack-pm-dispatch(the maintainer's word pending).
Generated by Claude Code
- Implemented-by: os-dev subagent on branch
Landed — PR #17294 merged by
os-zhuangat 2026-09-10T05:05:11Z (merge commitc47edbb21728, headec15afa1), governed path (.claude/**+scripts/pm/**): draft → approving review by os-zhuang 04:41Z → human merge; this seat's ACCEPT verdict 5613072104 bound to that head. Verified onorigin/main8c9bd8f51fe5at 2026-09-10T05:41Z: SKILL.md :509 namesskills/**in the clause-① surface, :769 carries 「总监席档位由维护者按项目人工定」, anddispatch-gates.mjsMANDATORY_TIER_GLOBScarries theskills/**entry. Residue cleared in this same act:pm:dispatchedoff, assignee off;domain:skillsand the type stay. Unblocked by this landing: #17288 (SKILL.md rows) and the published-skill deletion card (dispatch-gates.mjs), both dispatched now. Skills seat, sessionsession_01MoTv7pn338AZ71owsp19gQ.
Generated by Claude Code
Filed by the
domain:skillsexecution seat (sessionsession_01MoTv7pn338AZ71owsp19gQ, GitHubos-justin) at 2026-09-10T03:1xZ under the maintainer's direct instruction in this seat's chat session — 直派通道: routed and claimed by the instructed PM session, labels set by that seat under the direct-dispatch rule, ⛔ not a triage grading.裁决 — the maintainer's words, verbatim and untranslated (chat, 2026-09-10, 02:0xZ–03:0xZ)
The default model tier is on the manual floor (人工地板: 花费/配额/舰队形态/默认模型档位). These sentences are the maintainer's explicit words for it. ⛔ This card re-adjudicates none of them; the seat's own prose below uses the tier names the skill text already uses (契约复审档 =
CONTRACT_REVIEW_TIER, 默认判断档 =TIER_DEFAULT), and ⛔ no model name enters any skill file (the director charter already forbids it).What the rule text says after this card
skills/**catalogs; default tier forreferences/**and other governed one-liners as todayClause ① (path mandate) =
.claude/skills/pm-dispatch/SKILL.md,.claude/agents/os-dev.md,skills/objectstack-pm-dispatch/SKILL.md(unchanged) plus the publishedskills/**catalogs: objectstackskills/(11 skill trees, 46 files, ~13.6k lines; shipped bynpm create objectstackandnpx skills add objectstack-ai/objectstack/skills --skill '*', perskills/README.md:5–:9) and objectuiskills/objectui/(27 files, 5,189 lines;npx skills add objectstack-ai/objectui, per objectuiREADME.md:521). ⛔ No one-line exemption forskills/**: a closed enumeration beats a per-line "is this mechanical" call, and the maintainer's word is 必须.Clause ② (content rule) is unchanged in substance — the
Clause-②declaration, the widening-tells gate, pin tests, and the manual floor for widenings under 代裁 all stay. What changes is WHO reviews: only the spec seat's clause-② review runs at the contract-review tier. Anything touchingpackages/specalready routes to the spec seat (〈多仓协调〉 rule 5), so no other lane keeps a contract-review-tier dependency.Adjudication: the only adjudicator is the director seat summoned by the maintainer, and its tier is the maintainer's per-summon choice (ruling 6) — the director records the tier it ran at (harness reading) in its session audit line, and ⛔ never refuses or parks its duties for being below the contract-review tier. So: 置信门 drops gate ⑤ (档位硬门) and becomes four gates; the 「档位未达 ⇒ 整体跳过」 consequence and the director's 「不达档只做免档整理并停放四职」 state are deleted, not moved; the 降档保险丝 no longer applies to the director (its population is the spec seat's clause-② review and the skills seat). The triage seat spawns no contract-review-tier subagent — for 代裁 or anything else — and the per-fire 代裁 pass leaves the triage duties; the director's remaining gates (一类自裁门's three criteria, the four-gate 置信门, the manual floor) are where 代裁 lives.
File surface and the exact lines (
origin/maind64bcb63, 2026-09-10T03:01Z).claude/skills/pm-dispatch/SKILL.md— 812 lines, ratchet ceiling 812, headroom 0 ⇒ net-zero or fewer lines; every line added is paid for by a line merged or deleted.model的契约复审档子代理。」 → the second clause goes; the triage seat has no 达档职责.model的契约复审档子代理(逐份过转录核验),或达档总监席。」 → 达档者 = the maintainer-summoned director seat, only.skills/**; :510 (the exemption) saysskills/**is not exempt; :513 scopes the clause-② contract-review-tier review to the spec seat; :523 「契约复审档留给裁决/复审子代理、skills 席与条款②复核。」 → 「契约复审档留给总监席、skills 席与 spec 席的条款②复核」; :522 stays true as written.CONTRACT_REVIEW_TIER,不达档只做免档整理并停放四职。」 → 「总监席档位由维护者按项目人工定,每场记入摘要台账;⛔ 无档位硬门、无免档整理态。」; plus the statement that the director is the only adjudicator..claude/skills/pm-dispatch/references/core-rules.md(151/151): the twins at :18, :94 (代裁 producer = the summoned director, no tier gate, no 「不达档则通道整体跳过」), :98 (four gates, 达档 dropped), :112 and :147 change in the same PR (「一条规则在本文与核心条款一处改动,另一处同 PR 同改」)..claude/skills/pm-dispatch/references/contract-review.md(60/60): :10–:18 keep their shape but name the spec seat as the reviewing seat; :29/:34 the review-subagent language is the spec seat's; :48–:60 the fuse stays for the two seats that still produce at-tier verdicts (the spec seat's clause-② review and the skills seat) and says that other seats' reviews — and the director's adjudications — are not at-tier verdicts and are not gated by it..claude/skills/pm-dispatch/references/lanes/director.md(72 lines): :12–:14 (「档位 =CONTRACT_REVIEW_TIER」, the per-summon fuse reading, 「不达档只做免档整理…⛔ 不裁不清标」) → the tier is the maintainer's per-summon choice, recorded from the harness reading in the session audit line, never a refusal; plus one clause — the director is the only adjudicator and is summoned in whichever repo the maintainer is working in. ⛔ The published-skill director role (summonable inside hotcrm or a customer metadata project) is NOT this card: it is a feature of the published skill, on the manual floor, and waits on the maintainer's inbox-location answer — a separate card.scripts/pm/dispatch-gates.mjs:MANDATORY_TIER_GLOBS(:10603) gains askills/**entry whosewhynames the 2026-09-10 ruling; the docblock at :10512–:10526 is corrected to the new clause-① set; self-test cases so that--tier skills/objectstack-data/SKILL.mdprints the mandate and--tier .claude/skills/pm-dispatch/references/core-rules.mdstill does not. objectui has nodispatch-gates.mjs: itsskills/objectui/**is covered by the rule text and the skills seat's claim/review discipline — ⛔ no objectui PR..claude/agents/os-dev.md(its floor comment at :12 stays true);skills/objectstack-pm-dispatch/SKILL.md(the frame-sync COPIES carry no tier text — measured: zero hits for tier / contract-review / model in the file);references/lanes/triage.md(7 lines, no tier line);references/lanes/spec.md(:25 points at SKILL.md as the single source and stays a pointer).Acceptance
node scripts/pm/dispatch-gates.mjs --tier skills/objectstack-data/SKILL.mdand--tier skills/objectstack-ai/SKILL.mdprint the clause-① mandate;--tier .claude/skills/pm-dispatch/references/core-rules.mdprints none;--self-testis green with the new cases.pnpm -s check:skill-line-ratchet,check:skill-frame-sync,check:pm-skill-id-lint(⛔ no issue numbers in skill files) andcheck:skill-compatibilityare green.Fixes #<this card>;## 维护者速读(草稿)(Chinese, five sections, business angle);## Acceptance notes. Governed (.claude/**+scripts/pm/**) ⇒ draft, ⛔ never ready / enqueued / auto-merged / approved by any seat;skip-changesetapplies (neither path ships in a package).Out of scope — separate acts
skills/objectstack-pm-dispatch, the hotcrm install, and where hotcrm's decision cards live (本仓 vs objectstack): waits on the maintainer's answer; a separate card.Generated by Claude Code