docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@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(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@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(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@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(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@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(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@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(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@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(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@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(scripts): make check-agent-model-declared's header the stated home of the model-resolution order - #14689

Merged
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home
Sep 2, 2026
Merged

docs(scripts): make check-agent-model-declared's header the stated home of the model-resolution order#14689
os-litant merged 1 commit into
mainfrom
claude/issue-14232-model-pin-header-home

Conversation

@os-litant

Copy link
Copy Markdown
Collaborator

Fixes#14232

Comment-only: one sentence in the header of scripts/check-agent-model-declared.mjs. One file, no behaviour change, no code change.

Premise, verified on origin/main

PR #14229 (merged 2026-09-02, commit 909a44171) shrank .claude/agents/os-dev.md's model-pin comment to a two-line pointer. At merge base bd4aa4e49 that comment is lines 12-13. Quoted verbatim and untranslated below; its delimiters are an HTML-comment open/close pair, described in words rather than written literally per this repo's body-sanitizer discipline (fences do not protect that shape):

`model: opus` 是刻意钉死的下限,不是上限 —— PM 的逐单定档优先。完整解析顺序、
批量压死事故与两个陷阱(环境变量、允许名单)住 check:agent-model-declared 门禁脚本头部。

That pointer's destination is this gate's header — while this gate's header still said "see .claude/agents/os-dev.md for the full order and both adjacent traps". The two comments pointed at each other and neither claimed to be the home. Premise holds.

Nothing was ever unreachable. The header already carries all three pieces the deferral promised: the four-step resolution order (lines 5-9), the env var outranking every other step including this gate's own pin (the sentence being fixed), and the org-allowlist fallback landing on the INHERITED model (lines 17-20, unchanged). The defect was only that the sentence described the pre-#14229 file.

The one sentence — before / after

Before, lines 13-15 on origin/main:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — see// `.claude/agents/os-dev.md` for the full order and both adjacent traps.)

After, lines 13-17:

// and it changes with no signal, mid-term, invisibly. (`CLAUDE_CODE_SUBAGENT_MODEL`// outranks every other step, including this gate's own pin — the first of the two// adjacent traps; the allowlist fallback below is the second. This header is the// home of that full order and of both traps, and `.claude/agents/os-dev.md` carries// only the `model: opus` pin plus a pointer back here.)

The header now names both adjacent traps in place — the env-var one in the sentence itself, the allowlist one by pointing at the paragraph directly below that already states it — and claims itself as the home instead of deferring to a file that no longer holds the text.

Line-width convention preserved: the file's existing maximum comment width is 84 characters; the replacement's widest line is also 84 (measured, not estimated).

⛔ No edit to .claude/agents/os-dev.md (governed, and it already points here). ⛔ No other file touched.

skip-changeset

Applied. scripts/ releases nothing: the root manifest is "private": true, and scripts/check-agent-model-declared.mjs appears in no package's files[]. scripts/check-empty-changeset.mjs has nothing to say about a PR that adds no changeset at all — its GREEN 3 case asserts "an untouched .changeset dir must not even be read".

Gates

Every command ran through scripts/pm/os-verify-lock.sh (slot issue-14232), each exit code captured by redirect before any pipe. All measured at c529a40a — the final commit on this branch, and the same tree the union was derived from.

CommandExitThe gate's own verdict line
pnpm check:agent-model-declared (the script's own suite — it has a --self-test flag, already wired into this script name)0✓ check-agent-model-declared self-test: 18 cases pass. + ✓ check-agent-model-declared: 1 agent definition(s) under .claude/agents/ all declare a model
pnpm exec eslint --no-inline-config scripts/check-agent-model-declared.mjs0no output; os-verify-lock: VERDICT command-exit 0
pnpm check:nul-bytes0✓ check-nul-bytes --self-test: 75 assertions over a temp git repo (real scan() path)
pnpm check:entry-guard0✓ check:entry-guard: 199 scripts/ file(s) — every entry guard goes through invoked-as.mjs
pnpm check:parse-guard0✓ check:parse-guard: 198 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.
pnpm check:pm-skill-id-lint0✓ check-skill-id-lint: 23 file(s) clean (pattern /#[0-9]{3,}/g).

Full union, re-derived after the edit

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands — no hand-fed paths; the script took its own change set from the merge base (1 path(s) vs merge base bd4aa4e49, three-dot semantics) and asserted the repo: "--repo 'objectstack-ai/objectstack' checked against this checkout's 'origin' remote — it holds." It derived 16 commands; all 16 were run.

CommandExitVerdict
node scripts/check-ci-filter-parity.mjs0OK: all 130 declared cross-package glob(s) (92 unique) are covered by core or crosspkg…
node scripts/check-cross-package-test-inputs.mjs0OK: 25 package(s) read outside themselves, all declared…
node scripts/check-shard-attestation.mjs0✓ check-shard-attestation: 2 aggregate gate(s) count 3 declared leg(s) across 3 attesting job(s).
node scripts/check-test-completeness.mjs3NOT MEASURED — see below
node scripts/pm/bare-root-worklist.mjs --self-test0OK self-test: 57 live row(s), 49 unreachable as spelled, 49 recorded verdict(s) — none stale…
pnpm check:agent-model-declared0as above
pnpm check:agent-test-spelling0✓ check-agent-test-spelling: 0 violations — 425 file(s) · 5645 bare -- token(s)…
pnpm check:bash32-floor0✓ check-bash32-floor: 26 tracked shell file(s) … name no bash 4+ construct…
pnpm check:cli-command-ids0✓ check-cli-command-ids: 315 command-id literal(s) across 112 file(s) … all resolve
pnpm check:cross-package-test-inputs0OK: 25 package(s) read outside themselves, all declared…
pnpm check:entry-guard0as above
pnpm check:parse-guard0as above
pnpm check:pm-dispatch-gates0✓ dispatch-gates self-test: 1240 cases pass.
pnpm check:pnpm-filter-targets0✓ check:pnpm-filter-targets: 142/181 --filter occurrence(s) across 32 file(s) resolve…
pnpm check:ratchet-remedy-authority0OK check-ratchet-remedy-authority: 184 scripts swept…
pnpm check:watch-hint-literal0✓ check-watch-hint-literal: 45 declaration(s) across 4 rostered name(s)…

check-test-completeness = NOT MEASURED, not a red and not a flake. Exit 3, and the gate says so itself in the text it printed:

check-test-completeness: PREREQUISITE NOT MET — this gate grades a saved 'turbo run test' log, and no log was named.
"Arrived here from the gate family scripts/pm/dispatch-gates.mjs derives? That list names this script with NO argument, which is this branch. There is no local log to hand it, so the local reading for this gate is NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix."

CI tees the log and passes the path on every invocation, so this branch is unreachable there.

The derivation also noted 9 further families that "apply once this card's changeset exists". This PR carries skip-changeset and writes no changeset, so those 9 have no path to match.

premise_false

None. Every premise the dispatch stated held as written:

  • os-dev.md's model-pin comment is the two-line pointer at lines 12-13 — held (quoted above).
  • The gate header's sentence still deferred to os-dev.md — held (it is the before block).
  • The header already documents both adjacent traps and the full order — held; that is why this is a comment reword and not a code change.
  • scripts/check-agent-model-declared.mjs has a --self-test flag, and package.json wires it into check:agent-model-declared — held, so the script's own suite is measured rather than NOT MEASURED.
  • scripts/ is not governed surface and releases nothing — held.

One dispatch detail was off by two lines and is recorded rather than corrected: the sentence is at lines 13-15 on origin/main, not "around line 15" alone — the parenthetical spans three lines. No consequence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1


Generated by Claude Code

…as the home of the model-resolution order
The header's parenthetical still said "see `.claude/agents/os-dev.md` for the
full order and both adjacent traps". That file's model-pin comment is now a
two-line pointer back at this header, so the two comments pointed at each
other and neither claimed to be the home.
The header already documents everything the deferral promised: the full
four-step resolution order above, the env var outranking every other step
including this gate's own pin, and the org-allowlist fallback landing on the
INHERITED model in the next paragraph. So the sentence now names both
adjacent traps in place and states that os-dev.md carries only the
`model: opus` pin plus a pointer here.
Comment-only; no behaviour change.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LraLgQVGq8egUwfYZpbYt1
@os-litantClaude

Copy link
Copy Markdown
CollaboratorAuthor

Landing provenance (skills lane seat, session session_01LraLgQVGq8egUwfYZpbYt1): flipped ready and auto-merge enabled at 19:0xZ under landing-operations B — in-seat ACCEPT on #14232 (comment 5514707108), every check on c529a40a green after the one re-run of the changeset job (it had evaluated before the skip-changeset write; the label is present and the re-run passed at 18:52Z), and scripts/check-agent-model-declared.mjs is outside every governed prefix — CI's Governed Surface Queue Guard agrees. No human merge is owed on this face.


Generated by Claude Code

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/xsskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@os-litant@claude