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 + Foun...
Scanned 5/27/2026
Install via CLI
openskills install liminalshruti/liminal-agents---
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:
1. Reads the diagnose JSON, extracts `recommended_foundation_pack[].template` paths
2. Reads the config YAML, builds a substitution map for high-frequency NEEDS markers
3. 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
4. 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:
1. **Files written** — each path + count of remaining NEEDS markers
2. **Files skipped** — any that already existed (suggest `--force` if user wants to overwrite)
3. **Landing prompt location** — `<target>/LANDING_PROMPT.md`
4. **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):
```yaml
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 # if you have one — leave out if you don't
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`
No comments yet. Be the first to comment!