The Context Firewall


Four phases of kodr that landed together because they’re one idea wearing four hats. The problem was specific and brutal for small local models: the --subagent-stages implementer looped over every file in one accumulating context, so by file 4 the window was clogged with files 1 through 3. On a 35B Qwen, that distillation is fatal - responses go vague or miss half the contracts. The fix is a context firewall, and getting there took a skills bundle, a structured plan, isolated authors, and personas.

90: builtin skills bundle

First, a packaging problem. Persona SKILL.md files (planner, implementer, reviewer, file-author) live in src/builtin-skills/roles/, but discoverSkills scans the working directory - so after install-local, running kodr anywhere else finds zero skills. The fix: a build-skills.mjs script parses the role Markdown into a committed src/builtin-skills.json, and npm run check includes a --check drift guard. Bundled as JSON, the roles are always present wherever the shim points. getBuiltinSkill(name) returns a structuredClone so callers can’t accidentally mutate the shared bundle.

91: a plan you can parse

The planner’s output was free-form prose scraped by a fragile regex. Now the planner emits a JSON manifest:

{
  "summary": "...",
  "files": [
    { "path": "...", "responsibility": "...", "exports": [...], "imports": [...] }
  ]
}

parsePlanManifest pulls it from the response, and - because resilience for weak models is non-negotiable - the old regex extractor stays as a fallback when a model returns prose. There’s a strict plannerResponseFormat() for providers that support JSON schemas, stripped for local+tools requests (the same local tool-call incompatibility from earlier), so the prompt-text instruction is the primary path for LM Studio.

92: isolated file authors (the firewall)

Here’s the actual fix. When a plan manifest is present, the implementer routes to runIsolatedFileAuthors instead of the shared-context loop. Each file gets its own author call with a fresh registry, and its context is deliberately tiny:

  • the plan summary (one paragraph, not the whole plan),
  • its own contract: path, responsibility, exports to provide, imports from siblings,
  • sibling export signatures from the manifest - never sibling file bodies.

That’s the firewall. File A’s author never sees file B’s code, only B’s interface. As long as the planner’s contracts are accurate, the authors stay coherent without polluting each other’s context - which is exactly the window-clog that killed the old loop. And it degrades safely: if parsePlanManifest returns null, it falls back to the shared-context loop, so the old free-form tests pass unchanged.

93: persona from skill

Finally, buildAgentSystemPrompt looks up getBuiltinSkill('role:' + agentName) first, falling back to the prompts/orchestration-*.md files. Role bodies are trusted harness content, injected straight into the system prompt - not run through the untrusted-workspace warning path, because they’re mine, not the repo’s. file-author joins the agent roster so --agent-model file-author=lmstudio/my-model works and file-author: directives are recognised.

The only snag in the whole batch was deliciously mundane: biome format reformatted the build script after the JSON was generated, so build-skills --check failed on the first npm run check. Fix: always run build-skills after format. Four interdependent phases, one context firewall, and a formatting gotcha. That’s the job.

Links: