# Scaffold Project Spec

> Partial Skill: invoke by name only — lay out an SDD project-spec

- Skill: `cyberuni/scaffold-project-spec` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add cyberuni/scaffold-project-spec`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cyberuni/scaffold-project-spec/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: cyberuni (https://skillmd.com/u/cyberuni)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cyberuni/scaffold-project-spec

---


# scaffold-project-spec — lay out a project's spec

The procedure the **conductor** follows, **once at bootstrap**, when `start-mission` explore finds a project
with **no spec yet**. It chooses *how the spec is organized*, scaffolds that skeleton, and
**declares the choice**, so the per-unit explore that follows (`spec-producer-governance`) slots work into known
homes. It is **internal** — reached through `start-mission`, never a user entry — and leaves the tree at
`status: draft`; it authors no node's `## Use Cases`/`.feature`, renders no gate verdict, and freezes nothing.

**Load `sdd:spec-structure-governance`** for the layout law it applies: the node taxonomy (three
spec-types, the concept axis), the two-level depth cap, screaming architecture and the
non-capability folders, root-files-not-folders, and the colocate-or-hoist test. This skill does not
restate that law — it **runs** it, and owns only what is genuinely its own: the **strategy menu**,
the **shared envelope**, and the seven-step procedure below.

Run the seven steps in order, surfacing each choice to the user (recommended-first), never assuming
silently.

## 0 — Pick the evidence mode

**Detected, not chosen.** Ask one question of the tree, not of the user: **does this project have source to
read?** Scope it to the **project**, never the repo — a new package inside an existing monorepo is a
greenfield *project* in a populated *repo*.

- **detection mode** — the project's source exists. Steps 1-3 read it.
- **intent mode** — the project's source does not exist yet. Steps 1-3 have nothing to read for it, so they
  run off what the user states the project *will* be.

**The repo around an intent-mode project is still readable**, and reading it is not a mode switch: an
existing monorepo's shape, conventions, and sibling packages inform the recommendation even when the
project itself is empty. Intent mode means *this project* has no source — not that the disk is blank.

Steps 4-6 are identical under both modes. Never run detection's signal-reading against an empty project and
never let intent mode fall through to a silent default.

## 1 — Establish the project shape

**Detection mode** — read signals, do not guess: an **agentic plugin** (`.plugin/` + `skills/` + `agents/`);
a **monorepo** (`apps/`+`packages/`, or multiple package anchors each with their own manifest); whether
`src/` is **feature-** or **layer-organized**; framework markers; owners (`CODEOWNERS`); size.

**Intent mode** — the project has no signals of its own. Establish by asking (reading the surrounding repo
where it helps) the three things detection would otherwise have read:

1. **What kind of project** — a repo harness, an agent plugin, an npm package, a website, an app
   (`project-unit.md`). This is what the plugin/monorepo/plain classification stood for.
2. **Where it will live** — the repo-relative dir its source will occupy. This is the **`project-path`** step
   5 must write, and in a greenfield project that directory does not exist yet, so it can only be asked.
   Confirm it rather than inventing a path.
3. **What it will do** — the intended capabilities, which step 3 recommends a strategy from.

(2) gives the `project-path`; (1) decides the **location**, per step 2 — nesting does not.

## 2 — Choose the spec location

Recommend, let the user override, never assume:

**Colocate by default.** Hoist only when the spec **cannot be kept out of what ships** — nesting alone is
never the reason.

- **`<project>/.agents/spec/`** (colocated).
  An npm package colocates fine: `files` / `.npmignore` excludes `.agents/` from the tarball.
- **`<repo>/.agents/specs/<name>/`** (hoisted — named by the package). Only when the project dir is
  distributed **wholesale**, with no include/exclude mechanism to leave the spec behind. The one identified
  case is an **agentic plugin**: plugin install distributes the whole plugin directory, so a colocated spec
  would ship to every consumer. If a new packaging format has the same all-or-nothing distribution, it joins
  this case; otherwise colocate.
- **monorepo** — offer to lay out **every package** (each hoisted to `<repo>/.agents/specs/<name>/`) plus the
  outer project (`<repo>/.agents/spec/`). Run steps 1–6 **per selected project**, producing several draft
  trees (the evidence mode is picked once, in step 0, for the whole run).

In **intent mode** apply the same test to the **kind of project** established in step 1: an agentic plugin
hoists, everything else colocates at the `project-path` given. Confirm with the user; never re-ask location
as an independent choice, and never hoist merely because the path is nested.

## 3 — Recommend + choose the strategy

Present **one recommendation + its rationale + the alternative**; the user chooses. Shipped menu:

- **capability-first** *(default)* — top-level folders by what the project *does*. Recommend when a capability
  decomposition is discernible. For a fixed-layout plugin this is a spec-side abstraction over fixed source —
  accepted for legibility; name the spec↔source divergence as a known cost.
- **mirror-source** — spec nodes track the source tree. Offer whenever the team **navigates by code**;
  a **feature-first** `src/` is the best case, not a precondition. Over a **layered** source, still
  offer it — but name the cost: the folder partition is coarse, so the scheduler sees more collisions
  and the schedule is slower (never wrong — an unresolved collision serializes, `sdd:spec-structure-governance`).
  Say what recovers it (the collision ladder resolves most shared-node pairs at the file or symbol
  rung) and what the exit looks like (concept tags accumulate; hoist a capability when the
  false-conflict rate earns it). Mirror is **boundary-aligned** (step 4). **Detection mode only** —
  there is no source tree to mirror in intent mode.

**Offer to measure, rather than argue.** In **detection mode** on a repo with real history, offer to
run `sdd:check-partition-quality` before the choice is made: it reports, from this project's own
commits, how much parallel work each candidate layout would permit. Opt-in — it reads `git log`, so
it is slow on a large repo and says nothing useful on a young one, and it renders no verdict. When it
runs, present its parallelizable shares alongside the recommendation so the user chooses on their own
numbers rather than on doctrine. Skip it silently in intent mode: a greenfield project has no history
to measure.

**Do not require a restructuring before the first spec.** An existing project adopting SDD keeps the
shape it has; capability-first is the destination, reached on evidence, not an entry toll. Recommend
capability-first, accept mirror-source with its cost stated, and let the data drive the migration.

In **intent mode**, recommend from the capabilities the user stated in step 1. If they have not stated any,
**ask for them** — never apply the capability-first default silently. (Detection mode's no-signal fallback
*is* the capability-first default; intent mode has no equivalent, because a greenfield project always has an
intent to state.)

Never offer **layering** or **arc42 sections** as the *top* level — they nest *inside* a capability. **ADR is
not a strategy** — it is the decisions facet (step 4). The deferred strategies (bounded-context, layered,
doc-envelope) are off the shipped menu; surface them only on an explicit "show more options".

## 4 — Scaffold the envelope + skeleton

Write the **shared envelope** every strategy ships:

- root **`spec.md`** (the index + the `project-path` frontmatter + the placement map + the reserved by-concept
  index block — step 5);
- **`design/`** — the rules/model home, **including `design/decisions/`** (the ADR log: append-only,
  descriptive, ungated — the project-scope sibling of a unit's `<unit>.solution.md`; *organize no node as an
  ADR body*);
- **`workflows/`** — the workflows suite home (cross-capability usage flows);
- a **tooling/project** home (build, CI, packaging, deps);
- **`glossary.md`** — a root file beside `spec.md` (never a folder): the project's ubiquitous
  language, every load-bearing term defined once in plain words. Seed it with the terms the scaffold
  already commits to; per-unit explore adds the rest.

Then the chosen strategy's **top-level skeleton** of **stub node READMEs**, each declaring a legal
**`spec-type`** via the classifier:

- a **testable surface** → `behavioral` (`## Use Cases`; its `.feature` is authored later, in explore);
- a **shipped suite-less artifact** (a governance, a config) → `reference` (`## Subject`, no
  `.feature`);
- an **index / rule / structural grouping** → **descriptive** (no marker).

The skeleton obeys the **two-level depth cap** under **every** strategy: a node is
`<capability>/<unit>` and **never three deep** — a sub-grouping inside a capability is a `concept:` tag
recovered by the by-concept index, not a third folder level. Under **mirror-source**, mirror **only to the
unit boundary**: a folder with a testable surface becomes one behavioral leaf that owns its subtree; create
**no node below a behavioral leaf** (nested `src/` there is impl detail). A capability node README carries
**only** its `spec-type` marker — never a lifecycle field; its cross-cutting **`concept:`** tag is assigned
later in per-unit explore (via the `place-node` skill), not at scaffold.

## 5 — Declare the organization (do not leave it to be re-derived)

In the same act that writes root `spec.md`, record both so a later edit reads, never re-scans:

- **`project-path` frontmatter** — the repo-relative source dir this spec governs (the package for a
  hoisted spec; the project root for a colocated one). It is the router's source→spec map; the spec
  **location mode** (`colocated | hoisted | monorepo-member`) is *derived* from it, not stored. There is
  **no `spec-layout` block** (ADR-0017: frontmatter is the router index — the strategy is not something the
  router needs).
- **`name` frontmatter (the project name)** — write it when the project's name is **not reliably
  derivable** from the location (`discover-specs` derives `repo` for a repo-root single-project and the
  folder for a `.agents/specs/<project>`, but only **guesses** a nested project's folder basename). For a
  **hoisted / nested** project, **ask the user for the name and store it** (infer a default from the
  invocation when the user named the project — e.g. `backfill <this-project>`); confirm before writing.
  Skip it when the derived name is already right (a plain colocated repo-root project).
- the **placement map** in the body — the maintained "a concept of kind K lives in home H" taxonomy + the
  nesting rule, **naming the chosen strategy** in its heading/intro, so a newcomer routes a new concept
  without holding the tree in their head and `start-mission` / the Warden read the strategy on demand.
- the **reserved by-concept index block** beside it (generated by the `concept-index` skill) — the
  cross-cutting `concept → its nodes` view. Reserve the block; **leave it for `concept-index` to
  generate** from `concept:` frontmatter — pure derivation, never hand-maintained.

Validate the result with the `spec-gate` skill's `check-spec-state` script (`check-spec-state.mts --root
<specs-dir>`): the root lifecycle tuple must be legal.

## 6 — Hand back

Backfill ends with **stub** behavioral nodes (`## Use Cases` present, no `.feature`), not filled ones —
filling them is the **per-unit explore grill** (`spec-producer-governance`), the interactive live loop. **Do
not auto-continue into it.** Present the count of stub nodes and **ask the user**:

- **Continue now** — proceed into per-unit explore in this session, node by node, to the spec gate.
- **Defer to a mission** — stop at `status: draft`; the stubs stay a worklist any later `start-mission` /
  `resume-mission` picks up (the explore grill may want a different model or session).

Either way, **propose** the node placement for the formation **Warden** to confirm or relocate, and leave
`status: draft`.

## Output boundary

Write the skeleton, the root envelope (`project-path` frontmatter + placement map + the reserved by-concept
index block), the `design/decisions/` home, and `glossary.md` — nothing else. Do **not** author any node's `## Use Cases`/`.feature`, render a gate verdict,
freeze, or write `status` / `approval` / `produced-by` (the conductor's and `spec-gate`'s; see
`ownership-governance`).

