Context
Vega's Approve+Follow-Up review on PR #15613 (merged as the #15612 leaf) named two non-blocking items that need a durable home now that Resolves #15612 closed the leaf ticket (post-review-followup-surfacing rule). One of them is a real latent defect his review isolated precisely: the emitted [[permission.rules]] pattern uses underscores (mcp__neo_mjs_memory_core__*), but Kimi's actual MCP tool ids keep the server names verbatim with hyphens (mcp__neo-mjs-memory-core__list_messages) — proven by the Iris seat's living-reference config.toml (Phoebe-provisioned, daily-driven since 2026-07-19) and by the live tool namespace every kimi session loads. The emitted rules would be dead on arrival; only default_permission_mode = "auto" would be load-bearing. The shipped spec asserted the same wrong transform as the generator, so the tautology passed CI — exactly the "false coverage confidence on the single unverified runtime contract" the review flagged (EXECUTION_QUALITY −12).
The Problem
- Generator defect (latent):
generateKimiSeatConfig.mjs renderConfigToml() emits mcp__${server.name.replaceAll('-', '_')}__* — a transform borrowed from MCP hosts that canonicalize dashes, which Kimi does NOT do. Zero generated seats exist yet (no consumer; prepareManagedAgentWorkspace fails closed for kimi-code), so the blast radius is bounded to the emission + spec.
- Spec tautology:
generateKimiSeatConfig.spec.mjs computes the expected pattern with the same replaceAll, so the test proves the code equals itself, not that the pattern matches the harness's real tool ids.
- L3 boot homeless: the #15612 post-merge AC (generate a throwaway seat, boot it through a wake fire/no-fire cycle) lost its tracker when the leaf closed; per the follow-up rule it must live on Epic #15586 — and per the review it must be sharpened to exercise the permission-rule pattern (a wake-fired MCP call with no approval freeze) and to state whether
default_permission_mode = "auto" or the rules are load-bearing.
The Architectural Reality
ai/services/fleet/generateKimiSeatConfig.mjs — renderConfigToml() (~L131): the replaceAll('-', '_') transform to remove; Kimi matches permission patterns against the literal mcp__<server-name>__<tool> ids.
- Living reference: the Iris seat's hand-built
~/.kimi-code/config.toml L4-22 (pattern = "mcp__neo-mjs-memory-core__*" — hyphens, daily-proven through hundreds of MCP calls at default_permission_mode = "auto" + rules).
test/playwright/unit/ai/services/fleet/generateKimiSeatConfig.spec.mjs — the golden-shape permission case to re-anchor on the harness fact (assert the verbatim-hyphen form with a comment naming the living-reference evidence, so the tautology cannot regrow).
The Fix
- Generator: emit
mcp__${server.name}__* (verbatim server name, hyphens preserved).
- Spec: assert the exact hyphenated patterns for all four canonical servers, with a comment citing the living-reference config.toml as the authority (asserting a harness FACT, not a transform).
- Run the fleet family; PR with the review linkage.
- Post-merge (the L3 boot, operator-gated): generate one throwaway kimi seat from the emission, boot it, and drive a wake-fired MCP call through the emitted rules — record whether auto mode or the rules were load-bearing, then re-run the fire/no-fire cycle (the #15596 contract) as the boot's closing proof.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
[[permission.rules]] pattern |
Kimi live tool ids (mcp__neo-mjs-*__* verbatim) |
Hyphenated verbatim pattern |
default_permission_mode = "auto" covers if rules mismatch (but then rules are dead weight) |
living-reference config.toml |
unit: hyphen-form assertion; L3: wake-fired MCP call (post-merge) |
| Spec golden-shape case |
generateKimiSeatConfig.spec.mjs |
Asserts the harness fact, not the transform |
n/a |
spec comment |
this ticket |
Decision Record impact: none — defect fix inside the shipped leaf; no ADR conflict. Parent: Epic #15586.
Acceptance Criteria
Out of Scope
- The cockpit UI leaf (Epic #15586 sibling — unfiled, declared in the steward note).
- Presence-hook emission (#15580/PR #15587 owns the contract).
Avoided Traps
- Transform conventions from other MCP hosts — Kimi is its own naming authority; assert against the living reference, not host folklore.
- Deleting the rules instead of fixing them — auto mode alone would work, but the rules are the defense-in-depth layer the seat design wants; fix the pattern, keep the layer.
Related
- PR #15613 + Vega's review (pullrequestreview-4737802255) · #15612 (shipped leaf) · Epic #15586 (parent) · #15596 (wake coordinate contract the boot re-proves) · #15580/PR #15587 (presence contract)
Origin Session ID: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code session, Iris seat)
Handoff Retrieval Hints: query_raw_memories("kimi permission rule hyphen underscore pattern review follow-up"); living reference = the Iris seat's ~/.kimi-code/config.toml L4-22.
Context
Vega's Approve+Follow-Up review on PR #15613 (merged as the #15612 leaf) named two non-blocking items that need a durable home now that
Resolves #15612closed the leaf ticket (post-review-followup-surfacing rule). One of them is a real latent defect his review isolated precisely: the emitted[[permission.rules]]pattern uses underscores (mcp__neo_mjs_memory_core__*), but Kimi's actual MCP tool ids keep the server names verbatim with hyphens (mcp__neo-mjs-memory-core__list_messages) — proven by the Iris seat's living-referenceconfig.toml(Phoebe-provisioned, daily-driven since 2026-07-19) and by the live tool namespace every kimi session loads. The emitted rules would be dead on arrival; onlydefault_permission_mode = "auto"would be load-bearing. The shipped spec asserted the same wrong transform as the generator, so the tautology passed CI — exactly the "false coverage confidence on the single unverified runtime contract" the review flagged (EXECUTION_QUALITY −12).The Problem
generateKimiSeatConfig.mjsrenderConfigToml()emitsmcp__${server.name.replaceAll('-', '_')}__*— a transform borrowed from MCP hosts that canonicalize dashes, which Kimi does NOT do. Zero generated seats exist yet (no consumer;prepareManagedAgentWorkspacefails closed forkimi-code), so the blast radius is bounded to the emission + spec.generateKimiSeatConfig.spec.mjscomputes the expected pattern with the samereplaceAll, so the test proves the code equals itself, not that the pattern matches the harness's real tool ids.default_permission_mode = "auto"or the rules are load-bearing.The Architectural Reality
ai/services/fleet/generateKimiSeatConfig.mjs—renderConfigToml()(~L131): thereplaceAll('-', '_')transform to remove; Kimi matches permission patterns against the literalmcp__<server-name>__<tool>ids.~/.kimi-code/config.tomlL4-22 (pattern = "mcp__neo-mjs-memory-core__*"— hyphens, daily-proven through hundreds of MCP calls atdefault_permission_mode = "auto"+ rules).test/playwright/unit/ai/services/fleet/generateKimiSeatConfig.spec.mjs— the golden-shape permission case to re-anchor on the harness fact (assert the verbatim-hyphen form with a comment naming the living-reference evidence, so the tautology cannot regrow).The Fix
mcp__${server.name}__*(verbatim server name, hyphens preserved).Contract Ledger Matrix
[[permission.rules]]patternmcp__neo-mjs-*__*verbatim)default_permission_mode = "auto"covers if rules mismatch (but then rules are dead weight)generateKimiSeatConfig.spec.mjsDecision Record impact:
none— defect fix inside the shipped leaf; no ADR conflict. Parent: Epic #15586.Acceptance Criteria
Out of Scope
Avoided Traps
Related
Origin Session ID: session_e86fa9f0-866e-45e8-a6df-d7bb6dd4d8b5 (kimi-code session, Iris seat)
Handoff Retrieval Hints:
query_raw_memories("kimi permission rule hyphen underscore pattern review follow-up"); living reference = the Iris seat's~/.kimi-code/config.tomlL4-22.