* test(#2684): failing-first guard for unbound model= dispatch placeholders Extends the #2517 omit-on-inherit bucket with a behavioral binding guard: every model="{X}" in a workflow must name a field that workflow actually binds — an init-payload key (queried for real), a shell assignment, or a declared parse field. scan.md ({resolved_model}) and ship.md ({balanced_model}) substitute names nothing emits, so the orchestrator invents the value (ADR-1411). Also pins the shipped reference that seeded the placeholder and instructs the #2517-forbidden model="inherit". RED expected on scan.md, ship.md, and references/model-profile-resolution.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso * fix(#2684): bind scan.md and ship.md model dispatch to fields their workflows resolve scan.md:85 passed model="{resolved_model}" and ship.md:486 passed model="{balanced_model}" — names neither workflow's init payload emits. init.map-codebase emits mapper_model; init.phase-op emits no model field at all. With no source for the substitution the orchestrator invents a value, so model_overrides/model_policy are silently inert at both sites — the invisible partial application ADR-1411 prohibits. - scan.md: declare the init fields in a Parse JSON line and substitute {mapper_model}, matching its sibling map-codebase.md. - ship.md: ref.agent is only known at runtime, so resolve it per hook via query resolve-model and dispatch with {HOOK_AGENT_MODEL}, following the same NAME=$(...) → model="{NAME}" convention every other shell-resolved dispatch in the corpus uses (code-review.md, secure-phase.md, ui-phase.md). - Both sites now carry the #2517 rule: omit model= entirely when the resolved value is "inherit" or empty. A bare rename would have traded a dangling placeholder for model="", which 404s on non-Claude runtimes — an agent type absent from the profile table resolves to the empty string, which is exactly ship.md's case. - references/model-profile-resolution.md was the seam: it shipped the copy-pasteable {resolved_model} snippet scan.md inherited, used the stale Task( spelling, and instructed passing model="inherit" outright. Rewritten to teach the real binding convention and the omit rule. Two defects surfaced while fixing this and fixed inline rather than deferred: 1. ref.agent originates in a capability manifest, which may be third-party. Resolving it at runtime made this the first place that value reaches a shell command, so ship.md now validates its shape before interpolating and skips the hook when it fails — matching code-review.md's existing defense-in-depth pattern. Covered by a test that runs the shipped regex against real agent names and injection payloads. 2. The reference doc's omit example first placed a literal model= inside an Agent(...) comment, which tripped the #2284 fail-closed Hermes projection guard (bin/install.js:3704) and refused the install outright. Moved out of the call span; gen:golden is green across all 19 runtimes. Guard tests extend the existing #2517 bucket: every model="{X}" in a workflow must name a field that workflow binds — an init-payload key queried for real, a shell assignment, or a declared parse field. Behavior change (Hyrum's Law): the scan mapper now runs on the catalog-resolved model rather than the session model. The omit path is unchanged. Disclosed in the changeset body. Fixes #2684 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso * fix(#2684): validate capability-supplied ref.agent in-context, not in the shell The first cut of the ref.agent guard was placed after the injection point it was meant to close. It instructed the orchestrator to substitute the untrusted manifest value into a shell assignment and test it there: HOOK_AGENT="<the ref.agent value>" if [[ "$HOOK_AGENT" =~ ^[A-Za-z0-9][A-Za-z0-9._-]*$ ]]; then … Substitution happens before bash parses anything, so a manifest supplying `x"; touch /tmp/pwned; echo "` yields three statements and runs the middle one unconditionally — the regex fires afterwards and protects nothing. ship.md now requires the check to run in-context, the same way the workflow already reads activeHooks ("do NOT pipe it through a shell parser"), and to skip the hook outright on a mismatch. Only a value that has already matched ^[A-Za-z0-9][A-Za-z0-9._-]*$ ever reaches a command line. The guard test asserts the ordering — the in-context requirement and the absence of any raw shell assignment — not just that the pattern rejects metacharacters, since a pattern alone was exactly what gave false assurance here. Also corrects the empty-string explanation in references/model-profile- resolution.md. model_profile:"inherit" resolves to the literal "inherit", not "" (model-resolver.cts:395), and an unknown agent takes the empty-string path via resolve_model_ids:"omit" rather than by absence alone — the doc claimed all three produced "". The workflow instructions were already correct (omit on "inherit" OR empty); only the rationale in the citable reference was wrong. Both found by the isolated adversarial review pass for #2684. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso * chore(#2684): backfill changeset PR number Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
94 lines
2.4 KiB
JSON
94 lines
2.4 KiB
JSON
{
|
|
"add-backlog.md": 7176,
|
|
"add-phase.md": 7578,
|
|
"add-tests.md": 17247,
|
|
"add-todo.md": 11020,
|
|
"ai-integration-phase.md": 15356,
|
|
"analyze-dependencies.md": 3887,
|
|
"audit-fix.md": 12329,
|
|
"audit-milestone.md": 19034,
|
|
"audit-uat.md": 7469,
|
|
"autonomous.md": 42468,
|
|
"check-todos.md": 9771,
|
|
"cleanup.md": 10319,
|
|
"code-review-fix.md": 24906,
|
|
"code-review.md": 33110,
|
|
"complete-milestone.md": 31436,
|
|
"debug.md": 20175,
|
|
"diagnose-issues.md": 13444,
|
|
"discovery-phase.md": 13543,
|
|
"discuss-phase-assumptions.md": 28253,
|
|
"discuss-phase-power.md": 11273,
|
|
"discuss-phase.md": 31986,
|
|
"do.md": 10731,
|
|
"docs-update.md": 56494,
|
|
"edit-phase.md": 12927,
|
|
"eval-review.md": 10316,
|
|
"execute-phase.md": 90143,
|
|
"execute-plan.md": 35143,
|
|
"explore.md": 11127,
|
|
"extract-learnings.md": 13762,
|
|
"fast.md": 7613,
|
|
"forensics.md": 12531,
|
|
"graduation.md": 11987,
|
|
"health.md": 12246,
|
|
"help.md": 1722,
|
|
"import.md": 15599,
|
|
"inbox.md": 19299,
|
|
"ingest-docs.md": 19821,
|
|
"insert-phase.md": 8987,
|
|
"list-phase-assumptions.md": 4305,
|
|
"list-seeds.md": 6987,
|
|
"list-workspaces.md": 5699,
|
|
"manager.md": 27751,
|
|
"map-codebase.md": 21888,
|
|
"milestone-summary.md": 11842,
|
|
"mvp-phase.md": 13991,
|
|
"new-milestone.md": 38667,
|
|
"new-project.md": 67055,
|
|
"new-workspace.md": 11584,
|
|
"next.md": 20171,
|
|
"node-repair.md": 4173,
|
|
"note.md": 6563,
|
|
"onboard.md": 8877,
|
|
"pause-work.md": 14441,
|
|
"plan-milestone-gaps.md": 11809,
|
|
"plan-phase.md": 94427,
|
|
"plan-review-convergence.md": 26363,
|
|
"plant-seed.md": 12150,
|
|
"pr-branch.md": 15963,
|
|
"profile-user.md": 21624,
|
|
"progress.md": 32632,
|
|
"quick.md": 52280,
|
|
"reapply-patches.md": 20312,
|
|
"remove-phase.md": 8513,
|
|
"remove-workspace.md": 7916,
|
|
"resume-project.md": 17270,
|
|
"review.md": 59213,
|
|
"scan.md": 8880,
|
|
"secure-phase.md": 14627,
|
|
"session-report.md": 4044,
|
|
"settings-advanced.md": 40019,
|
|
"settings-integrations.md": 16257,
|
|
"settings.md": 33832,
|
|
"ship.md": 31658,
|
|
"sketch-wrap-up.md": 14267,
|
|
"sketch.md": 20369,
|
|
"smart-entry.md": 11489,
|
|
"spec-phase.md": 31987,
|
|
"spike-wrap-up.md": 15136,
|
|
"spike.md": 24939,
|
|
"stats.md": 6762,
|
|
"sync-skills.md": 6125,
|
|
"thread.md": 12508,
|
|
"transition.md": 22070,
|
|
"ui-phase.md": 26925,
|
|
"ui-review.md": 12166,
|
|
"ultraplan-phase.md": 10512,
|
|
"undo.md": 15323,
|
|
"update.md": 26024,
|
|
"validate-phase.md": 11856,
|
|
"verify-phase.md": 40949,
|
|
"verify-work.md": 41318
|
|
}
|