* test(4032): add failing installed-agent grants contract
Cover global and project agent_tools precedence at the real Claude installer seam before adding implementation.
* feat(4032): apply configured agent tool grants during staging
Resolve selector-level global and project config once per staging call, then append validated grants before runtime conversion.
* test(4032): cover host grant and quoted MCP contracts
Exercise installed host artifacts and prove ZCode must treat quoted MCP scalars like plain MCP grants.
* feat(4032): apply configured agent tool grants across runtimes
Move augmentation and scalar identity into the converter seam so every staged artifact preserves host policy.
* fix(4032): register agent tool grants in configuration
Accept documented agent_tools config without unknown-key warnings.\n\nKeep installer fixtures on the shared temporary-directory helper.
* fix(4032): translate configured MCP grants for Kilo
Reuse the converter-owned scalar decoder so quoted canonical grants reach Kilo's native permission keys without altering other host policies.
* fix(4032): decode YAML-escaped tool grants
* fix(4032): emit valid inline agent tool grants
* fix(4032): reject invalid trailing-colon grants
* test(#4032): cover cross-review remediation gaps
* fix(#4032): close cross-runtime grant gaps
* test(#4032): expose Kimi global project context
* fix(#4032): preserve Kimi project config context
* chore(#4032): add release note
* test(#4032): expose fork review regressions
* fix(#4032): address fork review findings
* test(#4032): make byte-stability assertion portable
Compare repeat installs at one root so platform-specific path rendering cannot
masquerade as an agent_tools behavior change.
* chore(#4032): bind changeset to upstream PR 4238
* fix(#4032): address trek-e review findings (2,3,4,5,6,7,8)
Fixes fail-closed decode-failure handling in ZCode's mcp__ stripper,
a comment-only `tools:` header mis-parse that silently dropped
configured grants, and a naive comma-split that could tear a quoted
scalar containing a literal comma. Documents Kilo's inherent
`{server}_{tool}` MCP-permission-key collision (external, fixed
format — not ours to widen) and locks the existing first-seen-wins
resolution in with a regression test.
Opts kimi/kimi-code out of the ADR-1235 pre-converter path-rewrite
step: routing Kimi through that pipeline (needed so project-scoped
agent_tools selectors reach it) was short-circuiting Kimi's own
neutralizeKimiAgentPrompt, which expects the original ~/.claude/gsd-core
text rather than a pre-rewritten Kimi path.
Extends the fast-check token pool and per-runtime install coverage
with the missing comment/comma/broad-runtime cases the prior review
flagged as untested.
* docs(#4032): add CONTEXT.md glossary entries for agent_tools resolver + pre-converter step
Documents readGsdEffectiveAgentTools (Install Model Override Resolver
Module) and the appendAgentTools pre-converter pipeline step (Runtime
Artifact Conversion Module), per contributor-standards.md's
new-seam glossary requirement (finding 1).
* fix(#4032): address agy adversarial review findings
An agy (gemini-3.8-flash-high) adversarial pass over the prior review-fix
commit found the fixes for findings 3, 4, 6 and 8 had unfixed sibling gaps,
plus a genuine new regression and two CONTEXT.md inaccuracies:
- ZCode's comment-only `tools: # note` header matched the inline-value
branch instead of falling through to the block-list scan, so a following
mcp__* item leaked through unstripped — the exact defect finding 4 fixed
in appendAgentTools, unfixed in this sibling function.
- Reverted capabilities/kimi-code/capability.json's noPathRewrite: true.
kimi-code uses the standard 'agents' kind with converter: null (not
kimi-agents — confirmed by reading the descriptor, not its prose
description), so it never went through the pipeline change finding 5
fixed, and disabling its path rewrite broke every ~/.claude/ embed in
its shipped agents instead.
- decodeToolScalar never stripped a trailing ` # comment` from a bare
(unquoted) scalar, so a comment after a block-list item, or after an
appended grant on an inline line, became part of the "tool name" —
fixed at the source (one call site fixes every consumer).
- appendAgentTools's comment-index scan wasn't quote-aware, so a `#`
inside a quoted scalar (`"mcp__server #1"`) was mistaken for a comment
start and corrupted the quote.
- parseFrontmatterTools (Kimi/Qwen's tool-list reader, downstream of
appendAgentTools's own output) had the same naive comma-split and
comment-only-header gaps as findings 4 and 6, unpatched.
- The all-runtime smoke test's presence assertion was built on a guessed
omit-list; empirically only 7 of 17 runtimes keep an arbitrary mcp__
grant recognizable, replaced with a verified allowlist.
- CONTEXT.md claimed a `project:<agent>` selector prefix that does not
exist (project override is a same-key merge across two config files)
and mislabeled stageAgentsForRuntimeWithConverter's module.
* fix(#4032): address full-PR review (Opus critical/ponytail + agy)
A whole-PR pass (critical-code-reviewer + ponytail-review on Opus, plus a
second agy full-source adversarial pass) surfaced defects the earlier
finding-scoped passes couldn't reach:
- appendAgentTools corrupted a `tools:` line whose ENTIRE value is a
leading quoted scalar (`tools: "Read"` -> `tools: "Read", Write`,
invalid YAML) — there is no safe line-surgical rewrite here, so it now
refuses to touch that shape instead of emitting broken frontmatter.
- decodeToolScalar's malformed-trailing-quote check ran BEFORE comment
stripping, so a bare tool name with a quote inside its own trailing
comment (`Bash # note: "internal"`) was wrongly rejected. Reordered.
- findUnquotedCommentIndex (added in the prior remediation commit) was
built on a wrong model of YAML: a `#` after whitespace starts a real
comment in a plain scalar regardless of nearby quote characters —
verified against the actual parser. The one case that DOES need
protection (a leading quoted scalar) is now refused outright above, so
the quote-tracking scan was dead weight solving a problem that no
longer reaches it. Removed; reverted to the plain `[ \t]#` scan.
- Kilo has a SEPARATE agent-frontmatter parser (convertClaudeToKiloFrontmatter,
distinct from the buildKiloAgentPermissionBlock fixed earlier) with the
same comment-only-header and naive-comma-split gaps as findings 4 and 6
— unfixed in both its src/ and bin/install.js copies. Fixed in both,
exporting splitToolScalars for bin/install.js to reuse rather than
reimplementing it.
- Pipeline docstring in stageAgentsForRuntimeWithConverter still listed 5
steps, omitting appendAgentTools (now step 3 of 6).
- docs/CONFIGURATION.md didn't state that a --global install still
discovers agent_tools from the cwd's .planning/config.json (confirmed
intentional and already covered by a dedicated test, not a bug).
- Removed install-engine.cts's deps.cwd injection seam: zero callers or
tests ever populated it.
Two claims from this round were verified and rejected, not fixed:
prototype pollution via a `__proto__` selector key (empirically confirmed
`Object.prototype` is never touched — only reassigns the resolver's own
local object's prototype, with no observable effect), and a `*` grant
value crashing YAML parsing as an alias reference (empirically confirmed
it parses as plain scalar text, no crash). A pre-existing, unrelated
defect (extractFrontmatterField returns null for block-list `tools:` on
Copilot/Antigravity/Cursor/Codex/Qwen, affecting two shipped agents
today) was filed as a follow-up rather than fixed here — it predates
#4032 and isn't caused or worsened by this PR.
* fix(#4032): update stale slug-derivation-drift-guard fixture line
normalizeKimiSkillName's real closing brace moved from line 616 to 635 as a
side effect of this PR's edits to runtime-artifact-conversion.cts; the
MAJOR-1 fixture's hardcoded realEndLine had gone stale.
* fix(#4032): address CodeRabbit findings on projectDir threading and flow-sequence tools
bin/install.js's installAgentsKindStandalone call site omitted the projectDir
argument the function already supports, so a global install through this
legacy branch silently fell back to the runtime config dir instead of
process.cwd() when resolving project-scoped agent_tools grants — inconsistent
with the sibling installOpencodeFamilyArtifacts call site, which already
threads it correctly.
appendAgentTools' leading-quoted-scalar bailout did not cover a YAML flow
sequence (`tools: [Bash, Read]`): splitToolScalars tore it apart on the
in-sequence commas and appended past its closing bracket, producing invalid
frontmatter. Extended the bailout regex to also refuse a value starting with
`[`, matching the same "whole node, nothing may follow" reasoning already
applied to quoted scalars.
---------
Co-authored-by: CI Rebase Check <ci@gsd-redux>
Co-authored-by: Test <test@test.com>
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>