---
name: apt:bootstrap
description: "Generate or refresh PROJECT.md (product-context source of truth)"
apt-skill-version: {{APT_VERSION}}
stage: setup
intent: configure
when_to_use: "Run when PROJECT.md is missing or stale and downstream skills need product context to operate."
user_invocable: true
internal: false
spawns_agent: false
agent_name: null
task_context: none
default_execution_mode: auto
execution_modes:
  - auto
  - step
allowed-tools: "Bash, Read, Glob, Grep, Write, AskUserQuestion"
argument-hint: "apt:bootstrap [--force-greenfield | --force-brownfield | --mode ask|infer|hybrid | --skip-bootstrap | --force]"
gates: []
---

<objective>
Close the product-context gap between "user ran apt-tools init" and "downstream
skills have enough context to work". PROJECT.md is the single source of truth
(D-01); `.aperant/product-context.json` is a DERIVED sidecar regenerated on every
write. Humans edit PROJECT.md freely; structured consumers read the JSON.

Two postures, chosen by compound heuristic (D-03):

- **Brownfield** — recon the repo (D-02 fixed allowlist: README.md, CLAUDE.md,
  AGENTS.md, package.json selected fields, top-level folder names, git remote,
  first commit message) and infer the 7-section PROJECT.md with per-section
  confidence markers. Only ask follow-up questions on medium or lower confidence
  (D-07); high-confidence sections pass silently.

- **Greenfield** — ask the full 7-section interview. Use structured prompts
  (AskUserQuestion) when the host supports them; fall back to numbered-text
  pickers with "99) type your own" as the inline escape (D-08).

Never invent sections that aren't in the D-06 canonical list. Never edit a
section the user just edited manually without showing a diff first (D-05).
</objective>

<your_environment>
- **Working directory:** The project root (where you were invoked)
- **apt-tools path:** `node packages/framework/bin/apt-tools.mjs` or the locally installed `apt-tools` binary
- **Constitution:** Read `AGENTS.md` in the project root if it exists
- **Canonical source:** `PROJECT.md` at the project root (7 fixed sections per D-06)
- **Derived sidecar:** `.aperant/product-context.json` (never hand-edited — always regenerated from PROJECT.md)
</your_environment>

<state_files>
## State Files

**Reads:**
- `README.md`, `CLAUDE.md`, `AGENTS.md` — first 8KB of each (D-02 allowlist)
- `package.json` — only `name`, `description`, `keywords`, `repository` (D-02)
- Top-level folder names, one level deep (D-02)
- Git `origin` remote URL + oldest commit message (D-02)
- Existing `PROJECT.md` (if present — for diff-and-confirm re-run flow, D-05)

**Writes:**
- `PROJECT.md` (project root) — human-facing prose, 7 D-06 sections with inline
  confidence HTML comments (D-09)
- `.aperant/product-context.json` — derived sidecar (D-01)
</state_files>

<process>

## 0. Hard-Gate + Autonomy Check

This skill has no hard gates (`gates: []`) — it is safe on any project state.
The autonomy inherited from the invoking context (init passes it through per
D-04; standalone use reads `.aperant/config.json`'s `autonomy.default`) controls
how aggressively to ask vs infer:

| Autonomy | Greenfield (ask) | Brownfield (infer) |
|---|---|---|
| 0 supervised | Ask every section | Ask every section even when high confidence |
| 1 guided | Ask every section | Ask medium or lower (D-07) |
| 2 autonomous | Ask only personas + scope | Ask medium or lower |
| 3 yolo | Ask only if all recon is empty | Infer everything, mark low-confidence sections for review |

Parse any CLI flags from the invocation:
- `--skip-bootstrap` — exit immediately with `status: "skipped"`. Used by `init`
  in CI-scripted paths. If this flag is set, do not run any steps below.
- `--force-greenfield` / `--force-brownfield` — override the D-03 heuristic.
- `--mode ask` / `--mode infer` / `--mode hybrid` — override the
  autonomy-derived ask-vs-infer defaults for this run only.
- `--force` — overwrite an existing PROJECT.md without the diff-and-confirm
  prompt (D-05).

## 1. Run Recon + Mode Detect (deterministic)

```bash
node packages/framework/bin/apt-tools.mjs bootstrap detect . \
  [--force-greenfield | --force-brownfield]
```

The CLI returns:

```json
{
  "status": "ok",
  "command": "bootstrap-detect",
  "mode": "greenfield" | "brownfield",
  "detected_mode": "greenfield" | "brownfield",
  "override": null | "user-forced greenfield" | "user-forced brownfield",
  "signals": { "sourceFileCount": n, "hasReadme": bool, "hasGit": bool, "commitCount": n },
  "rationale": ["source_file_count=3 < 10 (greenfield gate)", ...],
  "recon": {
    "readme": { "present": true, "body": "...", "truncated": false },
    "claudeMd": { ... },
    "agentsMd": { ... },
    "packageJson": { "present": true, "data": { "name": "...", "description": "...", "keywords": [...], "repository": "..." } },
    "topLevelFolders": ["apps", "packages", ...],
    "gitRemoteUrl": "...",
    "firstCommitMessage": "..."
  }
}
```

If an existing `PROJECT.md` is present, also read it now — you will need it
for D-05 diff-and-confirm.

## 2. Branch on Mode

### 2a. Greenfield → Ask

Run the 7-section interview. Each question targets ONE canonical section
(D-06). The template lives at `packages/framework/templates/project-md.md`;
use it as the shape, not the copy.

Questions to ask (in order):

1. **What This Is** — one-liner: product name + what it does.
2. **Core Value** — why this exists (not what it does — why it matters).
3. **Scope** — two sub-questions in one step: (a) top 3–7 things this product
   does (In), and (b) top 3–5 things this product explicitly does NOT do (Out).
4. **Context** — who built it, why now, team size / constraints.
5. **Personas** — stub only ("See .aperant/personas.json") — C48 populates
   the real roster. Ask only "roughly who's the target user?" and write it
   as a one-sentence placeholder.
6. **Constraints** — tech stack, timelines, hard rules (bullets).
7. **Key Decisions** — already-made architectural choices worth pinning
   (bullets, optional on day one).

Prefer `AskUserQuestion` with multiSelect=false + `99) type your own`
inline as the escape (D-08). When `host_capabilities.structured_prompts`
is false (Codex), fall back to numbered-text prompts with the same
"99) type your own" row as the last option.

Every answered section gets a `<!-- confidence: high | evidence: user-input -->`
marker (the user directly stated it — confidence is always high for a
greenfield ask).

### 2b. Brownfield → Infer

Synthesize each D-06 section from the recon envelope. For each section,
assign a confidence level:

- **high** — the section is directly stated in recon (README.md has a
  "What This Is" paragraph, AGENTS.md enumerates constraints, package.json
  description lines up with the Core Value).
- **medium** — the section can be inferred from adjacent signal (folder
  names suggest scope, git remote URL suggests audience) but the inference
  required a synthesis step.
- **low** — the section has no direct signal; the LLM is drafting a
  placeholder.

Per D-07, ask a follow-up question ONLY for medium-or-lower sections
(autonomy 1 and 2). High sections pass silently. Autonomy 0 asks every
section regardless. Autonomy 3 infers all and marks low sections in the
final report so the user knows to review.

Each section ends with a `<!-- confidence: {level} | evidence: {source} -->`
marker (D-09). `{source}` cites the recon field that informed the inference
(e.g., `README.md:1-20`, `package.json:description`, `AGENTS.md:## Constraints`).

### 2c. Re-run (PROJECT.md already exists)

If PROJECT.md was present at step 1:

1. Compute a fresh draft using the current mode (ask or infer).
2. Diff section-by-section against the on-disk PROJECT.md. For each section
   that changed, ask the user:

   ```
   AskUserQuestion([{
     question: "{section} — accept the new draft or keep the existing text?",
     header: "{section}",
     multiSelect: false,
     options: [
       { label: "Accept new draft", description: "{first 80 chars of new text}" },
       { label: "Keep existing", description: "{first 80 chars of existing text}" },
       { label: "Merge — edit the merged version", description: "Opens in default editor" }
     ]
   }])
   ```

3. Build the final PROJECT.md from the user's per-section choices.

If `--force` was passed, skip the diff-and-confirm and overwrite with the
fresh draft.

## 3. Write PROJECT.md

Write the prose directly (this skill's `allowed-tools` includes Write). Use
the 7-section D-06 template — do NOT invent sections. Inline the confidence
HTML comments at the END of each section body (D-09).

## 4. Derive the Sidecar

```bash
node packages/framework/bin/apt-tools.mjs bootstrap derive-sidecar .
```

This regenerates `.aperant/product-context.json` from the PROJECT.md you
just wrote. The CLI emits a JSON envelope summarizing what landed:

```json
{
  "status": "ok",
  "command": "bootstrap-derive-sidecar",
  "projectMd": ".../PROJECT.md",
  "sidecarPath": ".../.aperant/product-context.json",
  "sidecar": { "productName": "...", ... }
}
```

## 5. Report

Emit a summary the user can read at a glance:

```
PROJECT.md bootstrapped

Mode: {greenfield | brownfield}
Sections written:
  ✓ What This Is              [confidence: high]
  ✓ Core Value                [confidence: high]
  ✓ Scope                     [confidence: medium]    ← follow-up asked
  ✓ Context                   [confidence: high]
  ✓ Personas                  [stub — populate via /apt:personas (C48)]
  ✓ Constraints               [confidence: medium]    ← follow-up asked
  ✓ Key Decisions             [confidence: low]       ← review recommended

Sidecar derived: .aperant/product-context.json

Next:
  Review PROJECT.md and tweak any sections flagged low confidence
  Run /apt:personas to populate the persona roster (C48)
  Run /apt "describe what to build" once the context is set
```

</process>

## Re-invocation

This skill is safe to re-run. The diff-and-confirm re-run path (D-05) ensures
manual edits are never silently wiped. Common triggers to re-run:

- After major product pivots (Scope / Core Value drifted).
- After the personas roster lands (the Personas section's stub can be
  refreshed against the populated `.aperant/personas.json`).
- When downstream skills complain about stale product context (`.aperant/
  product-context.json` out of sync with the live repo).

The `--force` flag is reserved for scripted regeneration (CI paths that
don't want interactive confirmation).

## Integration with Other Skills

| Skill | How it uses PROJECT.md / product-context.json |
|-------|-----------------------------------------------|
| `/apt:plan` | Injects product-context into the planner's spec prompt so the LLM knows what this product is before it drafts a plan |
| `/apt:design` | Injects product-context into the design-synthesize prompt (C44) |
| `/apt:personas` (C48) | Reads PROJECT.md's Personas stub to seed `.aperant/personas.json` |
| `/apt:create-docs` (C49) | Uses the 7 canonical sections as the skeleton for README / ABOUT / etc. |
| `/apt:verify` | Cross-checks implementation against the Scope section (out-of-scope creep detection) |
