docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs - #14995

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule
Sep 3, 2026
Merged

docs(pm): narrow the model-identifier rule to content artifacts, with both carve-outs#14995
os-zhuang merged 1 commit into
mainfrom
claude/issue-14663-model-identifier-rule

Conversation

@claude

@claudeclaudeBot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Fixes#14663

Every dispatched dev received two binding instructions that read as a conflict. The harness attribution directive mandates a Co-Authored-By trailer naming the serving model, plus a session link, on every commit. The rule the dispatch brief carries forbids model identifiers in artifacts pushed to a repository. A commit trailer is a pushed artifact, so a dev could satisfy one or the other, never both — and, as triage measured, no gate reads commit messages for this, so nothing enforced either reading. Two devs hit it independently in one round, both resolved it the same way, and both filed it as a deviation a reviewer then had to read. That per-round tax is what this PR removes.

The ruling this PR executes

Maintainer ruling, director seat record 5528579332 (2026-09-03, decision batch 23, verbatim 「同意」 adopting option A):

  • The Co-Authored-By trailer naming the serving model, plus the session link, is written on every commit exactly as the harness attribution instruction requires. It is not a violation of the repo-side rule.
  • The repo-side rule means content artifacts: PR titles and bodies, code comments, docs, changesets, issue and PR comments. Model identifiers stay out of those.
  • Two carve-outs are recorded as part of the rule: the commit trailer (above), and .claude/agents/* frontmatter, where check:agent-model-declared requires a model: field.
  • ⛔ No gate over commit messages is added.

What landed

One bullet — three wrapped lines, one file — in the 派发词构造细则 clause list of .claude/skills/pm-dispatch/references/dispatch-runbook.md, placed beside the other verbatim clauses a dispatch brief carries (the 文件面两句原文 clause above it, the Same-day churn clause below it). It states the rule as narrowed, enumerates the content artifacts, names both carve-outs with the gate that requires the second one, dates the ruling, and closes with the operative consequence: devs stop declaring the deviation.

Register matches the section it joins — Chinese prose, English and backticked machine criteria, the file's ASCII punctuation (measured before writing: 112 ASCII ( against 12 full-width, 99 ASCII ; against 2), and every line at or under the file's existing 120-byte maximum.

Per the ruling's quote policy for this card, the bullet carries the ruling's date and substance rather than a verbatim quotation — the quotation is not the operative criterion here — and it carries no issue number, which check:pm-skill-id-lint requires of this corpus.

Premise verification, before the first edit

At origin/main5bc2f272, in the task worktree:

  • git grep -n '模型标识\|model identifier\|Co-Authored-By' -- .claude/skills/pm-dispatch → exit 1, zero hits.
  • Positive control git grep -n '派发词构造细则' -- .claude/skills/pm-dispatchdispatch-runbook.md:214.
  • Widened to every *.md in the repo, model identifier / 模型标识 → still zero hits. So no checked-in text carries the absolute reading that would now contradict the narrowed one — in particular neither .claude/agents/os-dev.md nor the published skills/objectstack-pm-dispatch/rules/dev-template.md has a sentence to report.

Premise valid: the ruled action had not been done.

Reverse check, after the edit

  • git grep -n '模型标识只禁内容工件' over .claude, skills, AGENTS.md, CLAUDE.md → exactly one hit, dispatch-runbook.md:246.
  • git grep -n '模型标识' repo-wide → exactly one hit, the same line. The rule now has a single site.

What is deliberately NOT here

  • No gate over commit messages, per the ruling.
  • The session / dispatch prompt sentence is not in this repository. Triage measured zero hits for it, and this PR's own premise check reproduces that. Narrowing it on that side is the maintainer's to do; until then the template sentence added here is the one agents cite.
  • The published skills/objectstack-pm-dispatch/rules/dev-template.md is untouched. The ruling scopes execution to .claude/skills/pm-dispatch/**, and that published template is a separate governed surface with its own line budget; it carries no model-identifier sentence today, so nothing there contradicts this one.

Verification

Gate family re-derived after the final commit with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths — the script takes the change set from the merge base itself): 12 families, identical to the list the dispatch brief carried. All 12 run at e5fe1325, each exit code captured by redirect before any pipe, each verdict line the gate's own:

gateexitverdict line
node scripts/check-closing-keyword-parity.mjs0check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8160 tracked file(s), all registered).
node scripts/check-comment-mask-corpus.mjs0✓ comment-mask corpus sweep: 5824 files, 0 disagree, 0 unparseable
pnpm --filter @objectstack/lint run check:doc-formula-expressions0✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 426 files / 1365 TS blocks judged clean
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 432 file(s) · 5851 bare -- token(s) · 1389 launcher-rooted run(s) · 9 separator(s) JUDGED
pnpm check:doc-authoring0✓ doc authoring guard: 46 published skill files clean — no internal issue-id references.
pnpm check:nul-bytes0check-nul-bytes: OK (scanned 8153 text file(s) -- 8153 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes).
pnpm check:pm-governed-merges0✓ check-governed-merges --self-test: 243 assertions
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).
pnpm check:pm-skill-ratchet0✓ check-skill-line-ratchet: .claude/skills/pm-dispatch/references/dispatch-runbook.md is 276 lines (ceiling 280; headroom 4).
pnpm check:refd-timer-probe0OK check-refd-timer-probe: 5819 source file(s) swept
pnpm check:skill-frame-sync0✓ check-skill-frame-sync: 2 copies of the decision frame are structurally isomorphic across 2 files
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 48 declaration(s) across 4 rostered name(s)

Ratchet, before and after, from the gate's own verdict lines: ... dispatch-runbook.md is 273 lines (ceiling 280; headroom 7)... dispatch-runbook.md is 276 lines (ceiling 280; headroom 4). Net +3 lines, inside the existing ceiling; no ceiling raised, no cross-file move declared.

check:doc-formula-expressions was NOT MEASURED on its first run — exit 3, PREREQUISITE NOT MET, twice in succession (@objectstack/formula, then @objectstack/lint unbuilt in a fresh worktree). Both builds ran through the shared verification lock (os-verify-lock: VERDICT command-exit 0), after which the gate ran green. The exit-3 runs are recorded as not-measured, not as failures.

Repo-wide ESLint (pnpm lint) was narrowed, and the narrowing is a measurement. Three readings: (1) the population comes from ESLint's own flat config — every files: block in eslint.config.mjs names only ts,tsx,mts,cts,js,jsx,mjs,cjs, and .md appears in none (grep -c "\.md'" eslint.config.mjs → 0); (2) the file count comes from --format json — this diff is exactly one file, and ESLint's own verdict on it is errorCount: 0 with the single message File ignored because no matching configuration was supplied.; (3) invariance for untouched files — a Markdown-only diff changes no lint configuration and no type-aware program, so no untouched file's verdict can move. CI runs the full sweep regardless.

Head of the verification run: e5fe1325.

Governed posture

.claude/** is a governed surface: this PR stays draft, reviewers are requested by the PM (os-zhuang, hotlong), and the maintainer merges by hand. skip-changeset applies — the diff publishes nothing from any released package.

Generated by Claude Code


Generated by Claude Code

… both carve-outs
Two binding instructions read as a conflict for every dispatched dev: the
harness attribution directive mandates a `Co-Authored-By` trailer naming the
serving model on every commit, while the rule the dispatch brief carries
forbids model identifiers in pushed artifacts. Nothing enforced either reading,
so each dev spent a round's deliberation on it and filed the same deviation.
The maintainer ruled it on 2026-09-03: the rule means CONTENT artifacts — PR
titles and bodies, code comments, docs, changesets, issue and PR comments — and
two carve-outs are part of the rule rather than exceptions to it: the
harness-written commit trailer (with its session link), and `.claude/agents/*`
frontmatter `model:`, which `check:agent-model-declared` requires. Devs stop
declaring the deviation.
States it as one bullet in the dispatch-brief construction clauses, beside the
other verbatim clauses a brief carries. No gate over commit messages is added,
per the same ruling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
@os-zhuang
os-zhuang marked this pull request as ready for review September 3, 2026 16:59
@os-zhuang
os-zhuang added this pull request to the merge queueSep 3, 2026
Merged via the queue into main with commit ba4587aSep 3, 2026
31 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-14663-model-identifier-rule branch September 3, 2026 17:52
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-zhuang@claude