| name | scaffold-substrate |
| description | Materialize the canon-substrate foundation pack into a target workspace. Reads a diagnose-substrate JSON report + a small config file, copies the recommended template files into the target, substitutes high-frequency placeholders (PROJECT NAME, OWNER NAME, sensitivity tiers), and emits a landing prompt the user pastes into their Claude Code session to finish the customization. Pairs with diagnose-substrate — diagnose first, scaffold second. Step (b) of SPEC §14's productized Diagnostic + Foundation Pack pattern. |
| disable-model-invocation | true |
| allowed-tools | Bash(node *) |
| argument-hint | --report <path-to-diagnose.json> --config <path-to-config.yml> --target <workspace-path> [--dry-run] [--force] |
Liminal Agents — Substrate Scaffold
You are scaffolding the canon-substrate foundation pack into a target workspace based on a prior diagnose-substrate audit. The scaffold is the second step of the §14 productized pattern: diagnose names the gaps, scaffold ships the templates with high-frequency tokens already filled, landing prompt finishes the per-domain customization.
When to invoke
- After running
diagnose-substrate and the user wants to act on the recommendations
- When a new cohort member is onboarding and you have a known configuration shape
- NOT for first contact — always run diagnose first; scaffolding without a fresh diagnose ships into unknown agent state
Flow
1. Validate inputs
User provides three flags:
--report <path> — JSON file produced by diagnose-substrate (the audit output)
--config <path> — YAML or JSON file with answers to high-frequency NEEDS markers (project name, owner name, hard-stop categories, etc.)
--target <path> — workspace root where the foundation pack lands
Optional:
--dry-run — print what would be written, write nothing
--force — overwrite existing files in the target (default is refuse-and-report)
If config is missing, the script will write a template config to <cwd>/scaffold-config.example.yml and exit, asking the user to fill it in.
2. Materialize templates
Invoke:
node ~/liminal/liminal-agents/skills/scaffold-substrate/scaffold.js \
--report <report.json> \
--config <config.yml> \
--target <workspace-path>
The script:
- Reads the diagnose JSON, extracts
recommended_foundation_pack[].template paths
- Reads the config YAML, builds a substitution map for high-frequency NEEDS markers
- For each recommended template:
- Reads the source
.template file from liminal-agents/templates/canon-substrate/
- Substitutes high-frequency placeholders
- Writes to target path (e.g.,
CLAUDE.md.template → <target>/CLAUDE.md)
- Counts remaining NEEDS markers and lists them in the materialization report
- Emits a
LANDING_PROMPT.md at the target root — paste-into-Claude prompt for finishing the customization per SPEC §14 Steps 0-5
3. Present the materialization report
Render:
- Files written — each path + count of remaining NEEDS markers
- Files skipped — any that already existed (suggest
--force if user wants to overwrite)
- Landing prompt location —
<target>/LANDING_PROMPT.md
- Next step — user opens the target workspace in Claude Code, pastes the landing prompt, finishes per-domain customization
Config schema
The config file has this shape (YAML or JSON):
project_name: "Smog King"
project_description: "14-shop California smog inspection network + vertical SaaS"
owner_name: "Sam Nejad"
owner_slug: "sam"
n_agents: 9
hard_stop_categories:
- name: "BAR / STAR compliance"
description: "smog inspector certifications, equipment calibrations, license renewals — wrong answer = state penalty"
canonical_source: "compliance/bar-star/"
- name: "Customer PII"
description: "VIN, license plate, owner contact — quarantined under reference/customers/"
canonical_source: "reference/customers/"
sensitivity_tiers:
- public
- internal
- partner
- absolute_hard_stop
core_entity:
type: "shop"
plural: "shops"
count: 14
example_slug: "carlsbad_main"
quarantine_dirs:
- "compliance/"
- "reference/customers/"
external_systems_loaded:
- "Notion (project tracker)"
- "Linear (engineering)"
The example config is auto-generated by the script with placeholder values + comments explaining each field. The user fills in their values before running with --config.
Output principles
- Idempotent by default. Never overwrite. User must explicitly pass
--force to replace existing files.
- Honest about what's filled vs unfilled. High-frequency tokens get substituted; per-domain content stays as
<<<NEEDS: ...>>> for the landing prompt to address.
- Single emit point. All file writes happen in one phase. If any write fails, no partial state.
- Landing prompt is the bridge. Scaffold doesn't try to fully customize — it produces a substrate the user's own Claude session finishes against their actual canon.
Related canon
- SPEC §14 — architectural rationale + service-shape
skills/diagnose-substrate/ — Step (1), the audit
templates/canon-substrate/ — source templates
- Original live event:
~/liminal/founder-brain/retros/2026-05-19-helping-sam-shape-of-help.md