selfware 0.6.7

Your personal AI workshop — software you own, software that lasts
Documentation
{
  "component": "templates",
  "tier": "tooling",
  "loop_stage": "act",
  "summary": "The templates component (templates.rs, TemplateEngine) supplies compile-time embedded project scaffolds for Rust, Python, and Node.js with {{placeholder}} substitution and optional CI workflows. Its stated purpose is to give weaker models a correct starting point so they only fill blanks rather than generating structure from scratch. On the loop it is an 'act' primitive that materializes a Plan into a concrete set of files in one deterministic step, seeded by ScaffoldOptions and InterviewContext. It reshapes the loop by front-loading correctness: instead of many risky generate-verify iterations, one scaffold act produces a known-good baseline that later stages refine.",
  "loop_objects": ["Template", "ScaffoldOptions", "TemplateEngine", "InterviewContext", "Placeholder", "ScaffoldedFile", "Plan", "QaProfile"],
  "context_basis": "Recommendations formed with templates read in the context of the full engine (~600k budget framing), where scaffolding gives 4B-9B models a correct starting point and CI workflows are optionally generated.",
  "examples": [
    {
      "id": "templates-01",
      "title": "Materialize a Plan into a scaffold act",
      "loop_stage": "act",
      "pattern": "plan-to-artifact",
      "intent": "Convert an approved project plan into concrete files in one deterministic step.",
      "how_it_shapes_the_loop": "scaffold_project turns a language + ScaffoldOptions into a file set in a single act, collapsing what would be many generate iterations into one known-good transition.",
      "loop_objects_touched": ["Template", "ScaffoldOptions", "Plan", "ScaffoldedFile"],
      "wiring": {"inputs_from": ["agent Plan", "interview InterviewContext"], "outputs_to": ["filesystem", "verify stage"]},
      "touch_interaction": {"gesture": "drag", "canvas_action": "Dragging the template node onto the canvas root drops a scaffold act that fans out into file nodes.", "visual": "The template node bursts into a cluster of file chips, each labeled with its generated path."},
      "mini_scenario": "The plan calls for a Rust axum API; scaffold_project emits Cargo.toml, src/main.rs, and tests in one act.",
      "pitfall": "Scaffolding writes real files — gate it behind the same act confirmation as any other filesystem mutation."
    },
    {
      "id": "templates-02",
      "title": "Substitute placeholders from ScaffoldOptions",
      "loop_stage": "act",
      "pattern": "parameterized-fill",
      "intent": "Fill {{placeholder}} slots so the scaffold reflects the requested project.",
      "how_it_shapes_the_loop": "The engine replaces {{name}}, {{description}}, {{framework}} in each Template, so the act produces project-specific files instead of a generic stub.",
      "loop_objects_touched": ["Placeholder", "ScaffoldOptions", "Template"],
      "wiring": {"inputs_from": ["ScaffoldOptions"], "outputs_to": ["ScaffoldedFile"]},
      "touch_interaction": {"gesture": "tap", "canvas_action": "Tapping a placeholder slot on the template node opens an inline editor to set its value.", "visual": "Unfilled {{slots}} glow amber; once bound they turn solid and show the substituted value."},
      "mini_scenario": "The user names the project 'my-api'; every {{name}} in Cargo.toml and main.rs resolves to my-api.",
      "pitfall": "Leave no unresolved {{placeholder}} in output — an unbound slot ships broken source."
    },
    {
      "id": "templates-03",
      "title": "Seed scaffold from InterviewContext",
      "loop_stage": "reason",
      "pattern": "elicit-then-scaffold",
      "intent": "Use structured pre-task answers to choose template variant and options.",
      "how_it_shapes_the_loop": "InterviewContext feeds framework/qa choices into ScaffoldOptions before the act, so the reason stage shapes exactly which Template is instantiated.",
      "loop_objects_touched": ["InterviewContext", "ScaffoldOptions", "Template"],
      "wiring": {"inputs_from": ["interview module"], "outputs_to": ["scaffold act"]},
      "touch_interaction": {"gesture": "long-press", "canvas_action": "Long-pressing the template node opens a config wheel populated from the interview answers.", "visual": "The wheel pre-selects framework and QA profile with the interview-derived choices highlighted."},
      "mini_scenario": "The interview establishes 'FastAPI, strict QA'; the scaffold act picks the Python template with strict workflows.",
      "pitfall": "Don't scaffold before the interview resolves ambiguity — a wrong framework choice wastes an act."
    },
    {
      "id": "templates-04",
      "title": "Attach a CI workflow to the scaffold",
      "loop_stage": "verify",
      "pattern": "bake-in-verification",
      "intent": "Ship the project with a working CI gate from the first commit.",
      "how_it_shapes_the_loop": "with_ci pulls the embedded rust/python/nodejs QA workflow into the file set, so the loop's verify stage has a ready gate rather than building one later.",
      "loop_objects_touched": ["Template", "ScaffoldOptions", "QaProfile", "ScaffoldedFile"],
      "wiring": {"inputs_from": ["ScaffoldOptions.with_ci"], "outputs_to": [".github/workflows/", "verify stage"]},
      "touch_interaction": {"gesture": "draw-connection", "canvas_action": "Drawing an edge from the template node to a CI node attaches the matching workflow file.", "visual": "A workflow chip snaps under .github/workflows with a green gate icon."},
      "mini_scenario": "with_ci=true adds rust-qa.yml so the scaffolded repo runs fmt/clippy/test on first push.",
      "pitfall": "Match the workflow to the language — attaching python-qa.yml to a Rust scaffold produces a failing CI."
    },
    {
      "id": "templates-05",
      "title": "Select QA profile intensity",
      "loop_stage": "control",
      "pattern": "tunable-gate",
      "intent": "Set how strict the baked-in verification should be.",
      "how_it_shapes_the_loop": "qa_profile ('standard'|'strict'|'minimal') calibrates the QA schema the scaffold ships with, tuning how hard the loop's later verify stage bites.",
      "loop_objects_touched": ["QaProfile", "ScaffoldOptions", "Template"],
      "wiring": {"inputs_from": ["ScaffoldOptions.qa_profile"], "outputs_to": ["selfware-qa-schema.yaml"]},
      "touch_interaction": {"gesture": "two-finger-rotate", "canvas_action": "Rotating a dial on the template node cycles minimal → standard → strict QA.", "visual": "The dial fills more red as strictness climbs; the QA node shows the active tier."},
      "mini_scenario": "Choosing 'strict' bakes a QA schema that fails the build on any clippy warning.",
      "pitfall": "Strict on a throwaway prototype stalls the loop on nits — match the profile to the task's stakes."
    },
    {
      "id": "templates-06",
      "title": "Scaffold a Rust project baseline",
      "loop_stage": "act",
      "pattern": "language-scaffold",
      "intent": "Produce a compiling Rust starting point.",
      "how_it_shapes_the_loop": "The Rust Cargo.toml.template plus source stubs give the loop a project that builds immediately, so the first verify pass is likely green.",
      "loop_objects_touched": ["Template", "ScaffoldedFile"],
      "wiring": {"inputs_from": ["scaffold_project('rust', ...)"], "outputs_to": ["filesystem"]},
      "touch_interaction": {"gesture": "drag", "canvas_action": "Dragging the Rust template chip onto the canvas expands the standard crate layout.", "visual": "A crab-badged cluster of Cargo.toml, src/, and tests/ nodes appears."},
      "mini_scenario": "scaffold_project('rust','tool') emits a crate that 'cargo build' passes on the first act.",
      "pitfall": "The embedded Cargo.toml pins an edition/MSRV — verify it matches the workspace before adding to it."
    },
    {
      "id": "templates-07",
      "title": "Scaffold a Python project baseline",
      "loop_stage": "act",
      "pattern": "language-scaffold",
      "intent": "Produce a runnable Python project with pyproject.",
      "how_it_shapes_the_loop": "The pyproject.toml template plus package stubs seed a valid Python layout, shortening the loop to editing rather than authoring structure.",
      "loop_objects_touched": ["Template", "ScaffoldedFile"],
      "wiring": {"inputs_from": ["scaffold_project('python', ...)"], "outputs_to": ["filesystem"]},
      "touch_interaction": {"gesture": "drag", "canvas_action": "Dragging the Python template chip lays out pyproject.toml and the package directory.", "visual": "A snake-badged cluster with pyproject.toml and __init__ nodes appears."},
      "mini_scenario": "scaffold_project('python','svc') emits pyproject.toml and a package the agent then fills.",
      "pitfall": "Placeholder substitution must reach pyproject metadata, or the package ships with the template's default name."
    },
    {
      "id": "templates-08",
      "title": "Scaffold a Node/TypeScript baseline",
      "loop_stage": "act",
      "pattern": "language-scaffold",
      "intent": "Produce a TS project with tooling configs.",
      "how_it_shapes_the_loop": "The Node template set (package.json, tsconfig, eslint, prettier, vitest) hands the loop a fully wired TS baseline in one act.",
      "loop_objects_touched": ["Template", "ScaffoldedFile"],
      "wiring": {"inputs_from": ["scaffold_project('nodejs', ...)"], "outputs_to": ["filesystem"]},
      "touch_interaction": {"gesture": "drag", "canvas_action": "Dragging the Node template chip fans out package.json plus the four config nodes.", "visual": "A cluster with tsconfig, eslint, prettier, and vitest chips clicks into place."},
      "mini_scenario": "scaffold_project('nodejs','ui') emits package.json, tsconfig.json, and vitest.config.ts together.",
      "pitfall": "The configs are opinionated — reconcile eslint/prettier with any existing repo conventions."
    },
    {
      "id": "templates-09",
      "title": "Reject an unknown language early",
      "loop_stage": "verify",
      "pattern": "guard-before-act",
      "intent": "Fail fast when asked to scaffold a language with no template.",
      "how_it_shapes_the_loop": "scaffold_project bails on unsupported languages, so the loop doesn't enter an act that would produce nothing usable.",
      "loop_objects_touched": ["Template", "ScaffoldOptions"],
      "wiring": {"inputs_from": ["agent language arg"], "outputs_to": ["error to control"]},
      "touch_interaction": {"gesture": "tap", "canvas_action": "Tapping an unsupported-language request flashes the template node red and refuses to expand.", "visual": "The node shows a red cross and a 'no template' tooltip instead of file chips."},
      "mini_scenario": "A request to scaffold 'cobol' bails immediately, routing the loop back to reason for a supported choice.",
      "pitfall": "Return a clear error, not a partial file set — a half-scaffold pollutes the workspace."
    },
    {
      "id": "templates-10",
      "title": "Opt out of test directories",
      "loop_stage": "control",
      "pattern": "conditional-fanout",
      "intent": "Skip test scaffolding for a minimal spike.",
      "how_it_shapes_the_loop": "with_tests=false drops the test dirs/config from the file set, trimming the act's output for a lean loop.",
      "loop_objects_touched": ["ScaffoldOptions", "Template", "ScaffoldedFile"],
      "wiring": {"inputs_from": ["ScaffoldOptions.with_tests"], "outputs_to": ["filesystem"]},
      "touch_interaction": {"gesture": "tap", "canvas_action": "Tapping the tests toggle on the template node removes the test chip cluster.", "visual": "Test-related chips grey out and detach from the scaffold preview."},
      "mini_scenario": "A quick spike scaffolds with_tests=false, so no tests/ dir is created.",
      "pitfall": "Skipping tests also weakens the verify stage — re-enable before the project matures."
    },
    {
      "id": "templates-11",
      "title": "Wire framework into the scaffold",
      "loop_stage": "reason",
      "pattern": "variant-selection",
      "intent": "Pick the framework flavor of a base template.",
      "how_it_shapes_the_loop": "The optional framework field steers substitution (e.g. axum vs plain), so the reason stage biases the act toward the intended stack.",
      "loop_objects_touched": ["ScaffoldOptions", "Placeholder", "Template"],
      "wiring": {"inputs_from": ["ScaffoldOptions.framework"], "outputs_to": ["ScaffoldedFile"]},
      "touch_interaction": {"gesture": "long-press", "canvas_action": "Long-pressing the template node opens a framework picker wheel.", "visual": "The chosen framework badge (axum/FastAPI) pins to the template node."},
      "mini_scenario": "Setting framework='axum' fills the Rust template's dependency slot with axum.",
      "pitfall": "A framework the base template doesn't wire for leaves dangling imports — verify the pairing exists."
    },
    {
      "id": "templates-12",
      "title": "Preview the scaffold before writing",
      "loop_stage": "verify",
      "pattern": "dry-run",
      "intent": "Let the operator inspect the file set before it hits disk.",
      "how_it_shapes_the_loop": "Rendering the file map without writing lets the loop pause at verify, gating the filesystem act on approval.",
      "loop_objects_touched": ["ScaffoldedFile", "Template"],
      "wiring": {"inputs_from": ["scaffold plan"], "outputs_to": ["operator approval"]},
      "touch_interaction": {"gesture": "spread", "canvas_action": "Spreading the template node expands each generated file into a readable preview panel.", "visual": "File chips show a peek of their filled content; an approve badge waits."},
      "mini_scenario": "The operator spreads the scaffold, reads the rendered Cargo.toml, then approves the write.",
      "pitfall": "Preview must reflect final substitution — showing raw {{placeholders}} misleads the reviewer."
    },
    {
      "id": "templates-13",
      "title": "Refine a scaffold in later iterations",
      "loop_stage": "act",
      "pattern": "baseline-then-refine",
      "intent": "Treat the scaffold as a seed the loop iterates on.",
      "how_it_shapes_the_loop": "After the scaffold act, subsequent edit acts fill blanks; the template's role is to reduce the search space each later iteration explores.",
      "loop_objects_touched": ["ScaffoldedFile", "Template"],
      "wiring": {"inputs_from": ["scaffold output"], "outputs_to": ["agent edit acts"]},
      "touch_interaction": {"gesture": "flick", "canvas_action": "Flicking from a scaffolded file node hands it to the edit-agent node for refinement.", "visual": "File chips gain an 'editable' outline once the scaffold settles."},
      "mini_scenario": "The Rust scaffold lands; the agent then edits src/main.rs to add the requested handler.",
      "pitfall": "Don't re-scaffold to change one file — that clobbers the operator's later edits."
    },
    {
      "id": "templates-14",
      "title": "Attach the QA schema to the repo",
      "loop_stage": "foundation",
      "pattern": "embed-policy",
      "intent": "Ship the selfware QA schema so verification is repo-local.",
      "how_it_shapes_the_loop": "The embedded QA_SCHEMA_YAML is written into the scaffold, giving the loop a durable, versioned verify policy independent of the engine.",
      "loop_objects_touched": ["QaProfile", "Template", "ScaffoldedFile"],
      "wiring": {"inputs_from": ["templates embedded schema"], "outputs_to": ["selfware-qa-schema.yaml"]},
      "touch_interaction": {"gesture": "draw-connection", "canvas_action": "Drawing an edge from the template to the QA node writes the schema file.", "visual": "A policy chip anchors at the repo root with a shield icon."},
      "mini_scenario": "The scaffold writes selfware-qa-schema.yaml so future runs verify against a fixed policy.",
      "pitfall": "The schema tier must match qa_profile — a strict profile with a minimal schema is inconsistent."
    },
    {
      "id": "templates-15",
      "title": "Scaffold at a chosen target path",
      "loop_stage": "act",
      "pattern": "placed-materialization",
      "intent": "Write the file set to an explicit directory.",
      "how_it_shapes_the_loop": "scaffold_project takes a target Path, so the act materializes files exactly where the plan intends, keeping loop state (workspace layout) predictable.",
      "loop_objects_touched": ["ScaffoldedFile", "ScaffoldOptions"],
      "wiring": {"inputs_from": ["agent target path"], "outputs_to": ["filesystem"]},
      "touch_interaction": {"gesture": "drag", "canvas_action": "Dragging the template chip onto a folder node targets that directory for the scaffold.", "visual": "The target folder highlights; file chips nest under it on drop."},
      "mini_scenario": "The agent scaffolds into ./my-api so the new crate lives beside the workspace.",
      "pitfall": "Refuse to scaffold over a non-empty target unless explicitly forced — silent overwrite loses work."
    },
    {
      "id": "templates-16",
      "title": "Give weak models a correct starting point",
      "loop_stage": "reason",
      "pattern": "constrain-the-search",
      "intent": "Reduce structural hallucination for small models.",
      "how_it_shapes_the_loop": "Per the module's purpose, handing 4B-9B models a valid scaffold means the loop's reason stage only fills blanks, cutting failed-generate iterations.",
      "loop_objects_touched": ["Template", "Plan"],
      "wiring": {"inputs_from": ["config model tier"], "outputs_to": ["reason stage"]},
      "touch_interaction": {"gesture": "tap", "canvas_action": "Tapping the template node shows how many boilerplate decisions it removes from the model.", "visual": "A 'search reduced' meter fills, indicating fewer degrees of freedom left to the model."},
      "mini_scenario": "A 7B model that would mis-structure a crate instead edits a correct scaffold, and the build passes.",
      "pitfall": "Templates constrain, not replace, reasoning — the model still must fill the domain logic correctly."
    },
    {
      "id": "templates-17",
      "title": "Keep templates compile-time embedded",
      "loop_stage": "foundation",
      "pattern": "no-external-fetch",
      "intent": "Ensure scaffolding works offline and deterministically.",
      "how_it_shapes_the_loop": "include_str! bakes every template into the binary, so the act never depends on network or disk templates, keeping the loop hermetic.",
      "loop_objects_touched": ["Template", "TemplateEngine"],
      "wiring": {"inputs_from": ["compile-time include_str!"], "outputs_to": ["scaffold act"]},
      "touch_interaction": {"gesture": "long-press", "canvas_action": "Long-pressing the engine node shows the embedded template inventory baked into the binary.", "visual": "A sealed-package icon marks the engine as self-contained; no network glyph appears."},
      "mini_scenario": "Offline on a plane, scaffolding still works because the templates are in the binary.",
      "pitfall": "Editing a template requires a rebuild — a runtime edit to the .template file won't take effect."
    },
    {
      "id": "templates-18",
      "title": "Fan a scaffold into a plan's steps",
      "loop_stage": "control",
      "pattern": "seed-the-plan",
      "intent": "Let the file set define the loop's subsequent work items.",
      "how_it_shapes_the_loop": "Each ScaffoldedFile with a TODO becomes a plan step, so the scaffold act directly seeds the loop's control queue.",
      "loop_objects_touched": ["ScaffoldedFile", "Plan"],
      "wiring": {"inputs_from": ["scaffold output"], "outputs_to": ["agent plan"]},
      "touch_interaction": {"gesture": "flick", "canvas_action": "Flicking the scaffold cluster into the plan lane creates one step per file needing work.", "visual": "TODO-marked file chips spawn matching task nodes in the plan rail."},
      "mini_scenario": "The scaffold's stub handler carries a TODO; the loop enqueues 'implement handler' as its next step.",
      "pitfall": "Don't enqueue steps for files that are already complete — the scaffold's configs need no work."
    },
    {
      "id": "templates-19",
      "title": "Version-align the scaffold with the workspace",
      "loop_stage": "verify",
      "pattern": "consistency-check",
      "intent": "Ensure the scaffold's toolchain matches the surrounding repo.",
      "how_it_shapes_the_loop": "Before accepting the scaffold, the verify stage checks edition/MSRV/deps against the workspace, preventing a build split.",
      "loop_objects_touched": ["Template", "ScaffoldedFile", "QaProfile"],
      "wiring": {"inputs_from": ["scaffold output", "workspace manifest"], "outputs_to": ["verify stage"]},
      "touch_interaction": {"gesture": "spread", "canvas_action": "Spreading the manifest node diffs the scaffold's toolchain against the workspace.", "visual": "Matching versions render green; mismatches flag amber for reconciliation."},
      "mini_scenario": "The scaffold's edition differs from the workspace; verify flags it before the crate is added.",
      "pitfall": "A silent MSRV mismatch surfaces only in CI later — catch it at scaffold verify, not on push."
    },
    {
      "id": "templates-20",
      "title": "Compose a monorepo from multiple scaffolds",
      "loop_stage": "control",
      "pattern": "multi-scaffold-fanout",
      "intent": "Stand up several packages under one plan.",
      "how_it_shapes_the_loop": "Multiple scaffold acts under one control plan build a monorepo; the loop sequences them, each a deterministic sub-act.",
      "loop_objects_touched": ["Template", "ScaffoldOptions", "ScaffoldedFile", "Plan"],
      "wiring": {"inputs_from": ["agent monorepo plan"], "outputs_to": ["filesystem"]},
      "touch_interaction": {"gesture": "draw-connection", "canvas_action": "Drawing edges between multiple template nodes and a shared root composes them into one workspace.", "visual": "Several template clusters nest under a single workspace root node with shared config chips."},
      "mini_scenario": "The plan scaffolds a Rust API and a Node UI under one repo, each via its own scaffold act.",
      "pitfall": "Reconcile shared configs (CI, lint) across packages — duplicated conflicting workflows break CI."
    }
  ]
}