UNPKG

akm-cli

Version:

akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cur

73 lines (63 loc) • 3.84 kB
# 0001 — No interpolation: data reaches units as attached structured context ## Context The pre-unification engine spliced data into a unit's prompt by string substitution (`${{ item }}`-style interpolation). That created an injection class: a producer's output could itself contain `${{ ... }}`-shaped text, and a re-scan of the already-substituted prose would interpret it as more grammar (the "P1 `{{item}}` re-scan injection" the essay below names). The workflow-format-unification work (spec §2.3) closed that class structurally rather than by escaping or sanitizing. ## Decision The essay, moved verbatim from `src/workflows/exec/native-executor.ts`'s module header: > Data flow (workflow-format-unification, spec §2.3): there is NO > interpolation language. A unit's instructions are the step's body prose > BYTE-EXACT — prose is never scanned for reference syntax, so a literal > `${{` in a body is content, not grammar. Data reaches the unit as ATTACHED > STRUCTURED CONTEXT rather than string splices: `buildUnitPrompt` > (`exec/step-work.ts`) wraps the verbatim instructions with JSON blocks for > the run params, a map unit's item + index, and the artifacts named by the > step's `inputs:`. Because nothing is ever substituted INTO the prose, the > P1 `{{item}}` re-scan injection class is structurally impossible. > > References survive only in the three whole-value FRONTMATTER positions the > closed two-root grammar occupies (`program/expressions.ts`): `map.over`, > `route.input`, and each `inputs[]` entry. They resolve ONCE per step > against `{ params, stepOutputs }`. There is NO ambient key search: a > `steps.<id>.output.<path>` reference addresses INTO that step's recorded > output explicitly. > > Step outputs (`steps.<id>.output…`): every engine-executed step journals a > promoted ARTIFACT under `evidence.output` — the solo unit's result/text, > the collect reducer's per-item array, or the vote reducer's winner — and > that artifact is what the reference scope exposes > (`projectStepOutput`). The documented addressing > (`steps.discover.output.files`) therefore resolves against real step > results, never the raw evidence envelope (peer review R1). Steps completed > manually (no `output` key in their evidence) expose their recorded > evidence object as-is. ## Consequences - A workflow author can never accidentally (or deliberately) inject reference grammar through step output content — the prose a unit receives is always byte-exact, and the only place reference syntax is EVER parsed is the three closed frontmatter positions, resolved once, before dispatch. - `steps.<id>.output` addressing is stable and explicit: it always resolves against the PROMOTED artifact a step recorded, never against an internal evidence shape that could change without the reference contract changing with it. - Peer review R1 flagged an earlier draft where the documented addressing risked resolving against the raw evidence envelope instead of the promoted artifact; the fix (route addressing through `projectStepOutput`) is what the essay above describes as settled behavior, not a proposal. - Because references resolve ONCE per step (not per unit, not lazily), resuming a run against the same frozen plan recomputes the identical resolution — this is part of what makes `computeStepWorkList` (`step-work.ts`, ADR 0002) a pure function of (plan, params, journaled results). ## Provenance - Source: `src/workflows/exec/native-executor.ts`, module header (the "Data flow" / "References" / "Step outputs" paragraphs). - Spec: workflow-format-unification, spec §2.3. - Review round: peer review R1 (addressing must resolve against the promoted artifact, not the raw evidence envelope). - Extracted: P4 (`docs/plans/specs/p4-deletions-closeout.md` §4.2), 2026-08-27.