Data Flow
Purpose #
Show how ProjectContext is built, how manifests are parsed, how {{varName}} interpolation flows through to the staged write.
Diagram #
%%{init: {
"theme": "base",
"themeVariables": {
"fontFamily": "ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif",
"fontSize": "14px",
"primaryColor": "#eff6ff",
"primaryTextColor": "#0f172a",
"primaryBorderColor": "#2563eb",
"lineColor": "#475569",
"secondaryColor": "#f1f5f9",
"tertiaryColor": "#ffffff",
"clusterBkg": "#f8fafc",
"clusterBorder": "#cbd5e1"
}
}}%%
flowchart TD
classDef actor fill:#ede9fe,stroke:#6d28d9,color:#1e1b4b,stroke-width:1.2px;
classDef cli fill:#dbeafe,stroke:#1d4ed8,color:#0c1f4a,stroke-width:1.4px;
classDef adapter fill:#cffafe,stroke:#0e7490,color:#083344;
classDef pack fill:#dcfce7,stroke:#15803d,color:#052e16;
classDef core fill:#fef9c3,stroke:#a16207,color:#422006;
classDef artifact fill:#f1f5f9,stroke:#475569,color:#0f172a;
classDef stop fill:#fee2e2,stroke:#b91c1c,color:#7f1d1d,stroke-dasharray:4 3;
classDef ok fill:#ecfdf5,stroke:#047857,color:#064e3b;
classDef external fill:#fff7ed,stroke:#c2410c,color:#431407;
start(["aidokit init"]):::cli
subgraph detect [Detection]
host["@aidokit/prereq-check
Node / Git / Claude Code / Beads"]:::core
detCtx["@aidokit/stack-detect
createDetectContext({ projectRoot, os })"]:::core
packs["each stack pack: detect(detCtx)"]:::pack
manifests["readManifest('package.json' | 'pyproject.toml' | …)"]:::core
end
pm["packageManagerLockfile detection
(pnpm-lock.yaml, yarn.lock, …)"]:::core
subgraph prompts [Selection]
clack["@clack/prompts
adapter, conformance, packs, MCPs, Beads"]:::cli
end
subgraph build [Build ProjectContext]
base["base ctx fields
projectRoot, projectName, os, arch"]:::artifact
parsed["ProjectContext.parsedManifests
(real package.json scripts — ADR-0014)"]:::artifact
stack["StackInfo (composed from detector results)"]:::artifact
sels["adapter, conformance, selectedStackPacks, selectedMCPs, beadsEnabled"]:::artifact
end
ctx["ProjectContext (immutable)"]:::artifact
subgraph emit [File plan + interpolation]
template["templates from src/files/ (tree-copied to dist/files/)"]:::artifact
interp["interpolate(template, {
projectName,
validationCommands,
kitVersion,
specVersion,
aidoCliVersion,
})"]:::cli
files["EmittedFile[]
{ path, content, mode? }"]:::artifact
end
write["writeFilesStaged(files, projectRoot)
(@aidokit/core)"]:::core
staging[".aido-staging/"]:::artifact
final["project root (atomic move)"]:::artifact
start --> host
start --> detCtx
detCtx --> packs
detCtx --> manifests
manifests --> parsed
detCtx --> pm
host --> base
packs --> stack
prompts --> sels
pm --> base
base --> ctx
parsed --> ctx
stack --> ctx
sels --> ctx
ctx --> emit
template --> interp --> files
files --> write --> staging --> final
What this shows #
DetectContextis the only filesystem surface stack packs may use — no shell, no network (stack-pack-contract §7.1).ProjectContext.parsedManifestsis populated frompackage.jsonper ADR-0014; stack packs (e.g.node-ts.suggestValidationCommands) consume real scripts.- Interpolation is the only template mechanism. Variables are a small fixed set per package. Anything more complex is generated programmatically by the adapter (ADR-0007 prep / CLAUDE.md §8).
- The atomic move at the end is what makes failed
initnon-destructive: staging deleted, project unchanged.
Common pitfalls #
- Adding a new variable to interpolation without documenting it. Variables are a small, documented set per package.
- Making
ProjectContextmutable. It is frozen post-build; deltas flow back via method return values, not via mutation. - Calling
fs.writeFilefrom an adapter. Adapters returnEmittedFile[]; the CLI writes.