--- name: scaffold-project-spec description: "Partial Skill: invoke by name only — lay out an SDD project-spec" user-invocable: false --- # 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 on capability nodes, 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. - **`/.agents/spec/`** (colocated). An npm package colocates fine: `files` / `.npmignore` excludes `.agents/` from the tarball. - **`/.agents/specs//`** (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 `/.agents/specs//`) plus the outer project (`/.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 `.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 capability node is `/` 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/`, 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 `); 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.mjs --root `): 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`).