---
name: apt:setup
description: "Configure Aperant preferences — verification, pipeline, docs policy, parallelization"
apt-skill-version: {{APT_VERSION}}
stage: setup
intent: configure
when_to_use: "The user wants to change framework preferences — verification style, cross-verification, pipeline behavior, docs policy, or parallelization settings."
user_invocable: true
internal: false
spawns_agent: false
agent_name: null
task_context: none
default_execution_mode: step
execution_modes:
  - auto
  - step
allowed-tools: "Bash, Read, Write, Edit, Grep, Glob"
argument-hint: "apt:setup [--batch <n> | --reset]"
gates: []
config_keys:
  - "*"
---
<objective>
Interactive configuration of the Aperant Framework. Presents human-friendly questions
with sensible defaults so the user never needs to remember flag names.

Settings are saved to `.aperant/config.json` in the project root. Commands like
/apt:verify-proof, /apt:run, and /apt:plan read this config automatically —
no flags needed.

For runtime install selection (which CLIs/IDEs to install skills into) the framework
ships a separate prompt as part of `apt-tools init`. Run with no flags in a TTY and
you'll see a menu listing all 14 supported runtimes (Claude / Codex / Cursor / Gemini /
OpenCode / Kilo / Copilot / Antigravity / Windsurf / Augment / Trae / Qwen / Cline /
CodeBuddy) with auto-detected suggestions marked with `*` (those whose runtime root
or marker file already exists in the project). Press ENTER to install the suggested
set, type `all` to install everywhere, or comma-separate specific ids.
</objective>

<process>

## 0. Detect Prompt Mode

Before running any questions, detect whether the host supports structured prompts:

```bash
node packages/framework/bin/apt-tools.mjs host-detect
```

Read `host.capabilities.structured_prompts` from the result.

- **If `true`** (Claude Code, Gemini CLI, OpenCode): use the host's native structured question tool for every `AskUserQuestion([...])` block below:
  - Claude Code → `AskUserQuestion` tool
  - Gemini CLI → `ask_user` tool (same shape: `questions[]` with `header`, `question`, `multiSelect`, options)
  - OpenCode → `question` tool
- **If `false`** (Codex CLI, Pi, unknown): no native dialog. Fall back to numbered text prompts — print each question with its options as a numbered list and ask the user to reply with the number(s). Example:
  ```
  [1/3] Verify Mode — How should verification work?
    1. Screenshots + Report (Recommended)
    2. Scores Only
    3. Full Evidence
  Reply with a number:
  ```
  Read the reply, map it back to the option key, and continue.

Treat every `AskUserQuestion([...])` block in the rest of this skill as an abstract "ask" — the actual tool call depends on the prompt mode you detected here.

## 1. Load Existing Config

```bash
mkdir -p .aperant
```

If `.aperant/config.json` exists, read it. Otherwise start from the template defaults:

```json
{
  "verification": {
    "open_report": true,
    "report_formats": ["html", "md"],
    "evidence_capture": true,
    "max_iterations": 3,
    "strict": false
  },
  "multi_model": {
    "cross_verification": {
      "enabled": false,
      "tools": []
    },
    "video_review": {
      "enabled": false,
      "model": "default",
      "api_key_env": "GEMINI_API_KEY"
    }
  },
  "pipeline": {
    "skip_review": false,
    "auto_branch": true,
    "branch_prefix": "apt"
  },
  "parallelization": {
    "enabled": false,
    "max_agents": 3,
    "use_worktrees": true
  },
  "orchestration": {
    "phase_delegation": "auto",
    "review_mode": "auto",
    "debate_mode": "auto"
  },
  "tdd": {
    "iron_law": false
  }
}
```

If `--reset` flag is passed, ignore existing config and start from defaults.

Also check for global defaults at `~/.aperant/defaults.json` — if they exist and no project config exists, use globals as the starting point.

## 1b. Review Mode (existing config detected)

**Canonical signal.** The `onboarding.completed` marker inside `.aperant/config.json` is the canonical signal that a user has walked through the full /apt:setup batch sequence. Structural completeness of the JSON config does NOT imply onboarding completeness — `packages/framework/templates/config.json` ships with all keys populated to sensible defaults by design, so the JSON alone cannot disambiguate "fresh seed" from "fully tuned." Future template additions must not assume otherwise.

**Dispatch.** Read `.aperant/config.json` and inspect the `onboarding` block. Branch on the four marker states:

| Marker state                                                | `/apt:setup` behaviour                                                |
|-------------------------------------------------------------|-----------------------------------------------------------------------|
| No `onboarding` block (legacy pre-fix config)               | enter **review mode** (preserve current behaviour; do NOT re-onboard) |
| `onboarding.seeded_from_template: true` AND `onboarding.completed: false` | enter **full Batch 1-8 flow** (treat as fresh setup)      |
| `onboarding.completed: true`                                | enter **review mode**                                                 |
| `--reset` flag passed                                       | enter **full Batch 1-8 flow** always (overrides marker)               |

`init` writes the `seeded_from_template: true` / `completed: false` marker on fresh seed only (see `packages/framework/src/cli/commands/init.mjs::applyInterviewAnswers`). The upgrade path never writes the marker — that is why a legacy unmarked config routes to review mode.

If the dispatch lands you in review mode, continue below. If it lands you in the full flow, jump to **Step 2**.

First, run host detection to show resolved orchestration:

```bash
node packages/framework/bin/apt-tools.mjs reconcile .
```

Display the current settings summary:

```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 APT ► CURRENT SETTINGS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

| Setting              | Value                        |
|----------------------|------------------------------|
| Verification         | {current value}              |
| Cross-Verification   | {current value}              |
| Video Review         | {current value}              |
| Open Report          | {current value}              |
| Strictness           | {current value}              |
| Auto Branch          | {current value}              |
| Code Review          | {current value}              |
| TDD Iron Law         | {current value}              |
| Date Format          | {current value}              |
| Time Format          | {current value}              |
| Task Index           | {current value}              |
| Diagram Mode         | {current value}              |
| Phase Delegation     | {config value} → {resolved}  |
| Review Mode          | {config value} → {resolved}  |
| Debate Mode          | {config value} → {resolved}  |
| Visibility           | {solo / team / oss}          |
| Host Detected        | {cli name}                   |
| Agent Teams          | {enabled/disabled}           |

Config: .aperant/config.json
```

For orchestration rows, show both the config preference and what it resolves to on this host (from reconcile output). Example: `auto → sub-agents` or `agent-team → agent-team`.

Then ask:

```
AskUserQuestion([
  {
    question: "What would you like to change?",
    header: "Settings",
    multiSelect: false,
    options: [
      { label: "Verification", description: "Verify mode, cross-verification, video review, strictness" },
      { label: "Pipeline", description: "Auto branch, code review, TDD Iron Law, date/time format, task index, diagram mode (file vs mcp)" },
      { label: "Orchestration", description: "Phase delegation, review mode, debate mode, agent teams" },
      { label: "Team Collaboration", description: "Enable/disable team mode — shared task board, roadmap, members" },
      { label: "Visibility", description: "Artifact-sharing policy — what leaves your machine (roadmap, team.json, decisions, digests, tasks)" },
      { label: "Task Tracking", description: "Tracker backend (local-only / github-issues / app-inbox), publish to tracker, TDD default, prototype discipline" },
      { label: "Changelog & Release Notes", description: "Internal dev changelog + opt-in user-facing release notes (audience, persona filter)" },
      { label: "Everything", description: "Re-run full setup from scratch" },
      { label: "Done", description: "Keep current settings" }
    ]
  }
])
```

**Routing:**
- "Verification" → jump to **Step 2** (Batch 1 + Batch 2 only), then skip to **Step 4** (mapping) and **Step 5** (write)
- "Pipeline" → jump to **Step 3** (Batch 2: auto-branch, code review, TDD, PR Review Auto-Suggest, **Sparring Auto-Fire**) AND **Step 3b** (Batch 3 only, including Diagram Mode), then skip to **Step 4** and **Step 5**
- "Orchestration" → jump to **Step 3c** (Batch 4 only), then skip to **Step 4** and **Step 5**
- "Team Collaboration" → jump to **Step 3d** (Batch 5 only), then skip to **Step 4** and **Step 5**
- "Visibility" → jump to **Step 3e** (Batch 6 only), then skip to **Step 4** and **Step 5**
- "Task Tracking" → jump to **Step 3g** (Batch 8 only), then skip to **Step 4** and **Step 5**
- "Changelog & Release Notes" → jump to **Step 3h** (Batch 9 only), then skip to **Step 4** and **Step 5**
- "Everything" → proceed to **Step 2** and run all batches (same as fresh setup). **Legacy-completes-Everything marker write:** if the starting config has no `onboarding` block (legacy unmarked config) and the user completes the full flow, write a full `onboarding` block at Step 5 as `{ completed: true, seeded_from_template: false, seeded_at: <ISO-8601 now> }` to record the explicit onboarding pass.
- "Done" → display "Settings unchanged." and exit

For selective edits, **pre-fill the existing values** as the default selection in each question. The user can confirm or change. Unchanged values are preserved — do not overwrite the entire config, only merge the changed section.

After any selective edit, show the confirmation table from **Step 8** with only the changed values highlighted, then exit.

---

## 2. Present Settings (Batch 1: Verification)

```
AskUserQuestion([
  {
    question: "How should verification work when you run /apt:verify-proof?",
    header: "Verify Mode",
    multiSelect: false,
    options: [
      { label: "Screenshots + Report (Recommended)", description: "Capture screenshots via MCP, terminal output, generate HTML proof report and open it in browser" },
      { label: "Scores Only", description: "Run tests/typecheck/lint, score 4 dimensions, write qa_signoff.json — no visual evidence" },
      { label: "Full Evidence", description: "Screenshots + terminal output + video review + report in all formats (html, md, archive)" }
    ]
  },
  {
    question: "Enable cross-verification? Other AI CLIs independently verify your implementation alongside Claude Code.",
    header: "Cross-Verification",
    multiSelect: false,
    options: [
      { label: "Claude Code only (Recommended)", description: "Fastest — Claude Code handles all verification. No extra tools needed." },
      { label: "Choose verification tools", description: "Select which AI CLIs to use for independent cross-verification (text + screenshot based, no API keys needed)." }
    ]
  }
])
```

### If "Choose verification tools" selected:

```
AskUserQuestion([
  {
    question: "Which AI CLIs should cross-verify? (Claude Code is always included as the primary verifier)",
    header: "Verification Tools",
    multiSelect: true,
    options: [
      { label: "Gemini CLI", description: "Google's gemini command — text + screenshot verification. Free, no API key needed for CLI." },
      { label: "Codex CLI", description: "OpenAI's codex command — text-based code verification." },
      { label: "Open Code", description: "opencode command — open-source AI coding CLI." }
    ]
  }
])
```

### Video review question (separate from cross-verification):

```
AskUserQuestion([
  {
    question: "Enable Gemini video review for UI verification? (Uses Gemini API, not the CLI — requires GEMINI_API_KEY)",
    header: "Video Review",
    multiSelect: false,
    options: [
      { label: "No (Recommended)", description: "Skip video analysis — screenshots + text verification are usually sufficient" },
      { label: "Yes", description: "Record screen interactions and send video to Gemini API for visual analysis. Catches hover states, animations, transitions." }
    ]
  }
])
```

### If video review enabled:

```
AskUserQuestion([
  {
    question: "Which Gemini model for video analysis?",
    header: "Gemini Model",
    multiSelect: false,
    options: [
      { label: "Balanced (Recommended)", description: "gemini-2.5-flash — best detail-to-speed ratio, reads exact text and star counts" },
      { label: "Thorough", description: "gemini-3.1-pro-preview — catches hover states and dropdown bugs, ~26s per video" },
      { label: "Fast", description: "gemini-3.1-flash-lite-preview — ~6s per video, good for CI pass/fail" }
    ]
  }
])
```

### Remaining verification settings:

```
AskUserQuestion([
  {
    question: "Open the proof report in browser automatically after verification?",
    header: "Auto-Open",
    multiSelect: false,
    options: [
      { label: "Yes (Recommended)", description: "Opens report.html in your default browser when verification completes" },
      { label: "No", description: "Just write the files — you open them manually" }
    ]
  }
])
```

## 3. Present Settings (Batch 2: Pipeline)

```
AskUserQuestion([
  {
    question: "How strict should verification be?",
    header: "Strictness",
    multiSelect: false,
    options: [
      { label: "Fix and retry (Recommended)", description: "If issues found, attempt to fix them and re-verify (up to 3 iterations)" },
      { label: "Strict — fail immediately", description: "Report issues but don't attempt fixes. Good for CI or audit mode." }
    ]
  },
  {
    question: "Create feature branches automatically when running /apt:run?",
    header: "Branching",
    multiSelect: false,
    options: [
      { label: "Yes (Recommended)", description: "Creates apt/{task-name} branch for each pipeline run" },
      { label: "No", description: "Commit directly to current branch" }
    ]
  },
  {
    question: "Include code review as the final pipeline step?",
    header: "Auto Review",
    multiSelect: false,
    options: [
      { label: "Yes (Recommended)", description: "Multi-pass code review after verification — catches logic, security, quality, architecture issues" },
      { label: "No", description: "Skip review step in /apt:run — just plan, execute, verify" }
    ]
  },
  {
    question: "Enforce TDD Iron Law? (Every subtask must land a failing test commit before the implementation commit.)",
    header: "TDD Iron Law",
    multiSelect: false,
    options: [
      { label: "No (Recommended)", description: "Leave TDD as a soft convention. Executors choose when to write tests first." },
      { label: "Yes", description: "Opt in to structural red-green-refactor enforcement. Audit gate runs during /apt:verify." }
    ]
  },
  {
    question: "After /apt:ship creates a PR, auto-suggest running /apt:pr-review for deep multi-agent review?",
    header: "PR Review Auto-Suggest",
    multiSelect: false,
    options: [
      { label: "Always (Recommended)", description: "One-line tip after shipping. Noop on npm-publish-only flows." },
      { label: "Ask me", description: "Prompt [Y/n] each time — choose per-PR." },
      { label: "Never", description: "Silent. Run /apt:pr-review manually if needed." }
    ]
  }
])
```

### Sparring Auto-Fire (FRAMEWORK-RFC-001)

Per-device opt-in for pipeline-integrated `/apt:spar`. Three phases — top-level Yes/No, then a conditional partner picker (if Yes) or hint sub-picker (if No). All three resolved fields land in `.aperant/config.local.json` per AUDIT-001 (NOT the shared `config.json`).

**Phase 1 — Top-level Yes/No:**

```
AskUserQuestion([
  {
    question: "Enable /apt:spar to auto-fire after planning (and execution on DEEP tasks)? Spawns a second LLM provider to challenge the plan before you commit code.",
    header: "Sparring Auto-Fire",
    multiSelect: false,
    options: [
      { label: "No (Recommended for now)", description: "Keep /apt:spar manual-only. You invoke it yourself when you want a second opinion." },
      { label: "Yes", description: "After every /apt:run plan stage (STANDARD) or plan+execute stages (DEEP), spawn a partner LLM to spar with the current host. QUICK tasks are hard-exempt." }
    ]
  }
])
```

**Phase 2 — Partner picker (only if Phase 1 = Yes):**

Before showing the picker, run `apt-tools host-detect` and parse `host.partner_transports.{codex,claude,gemini}` plus `host.cli`. Build the partner availability map:

```bash
node packages/framework/bin/apt-tools.mjs host-detect
```

For each of `codex`, `claude`, `gemini`, check whether ANY rung (MCP, plugin, raw CLI) under `host.partner_transports.<id>` is `detected: true` (or `"runtime-host-only"` for the MCP rung). Also exclude the current host (`host.cli`) — `/apt:spar` rejects same-host sparring by construction (Open Q1 — e.g. on `claude-code` host, the `claude` option is hidden because sparring against the same CLI is sycophancy).

If zero partners remain after filtering, print this graceful skip line and write `spar.enabled: true, spar.partner: null` so the user can opt back in later by installing a partner CLI and re-running `/apt:setup` → Pipeline:

```
[apt:setup] Sparring auto-fire enabled but no partner CLIs detected. Install codex / claude / gemini and re-run /apt:setup → Pipeline → Sparring Auto-Fire to pick a partner.
```

Otherwise, show the partner picker including only detected, non-same-host partners. Example (on a Claude Code host where codex MCP is loaded and gemini CLI is installed):

```
AskUserQuestion([
  {
    question: "Which partner LLM should /apt:spar use by default? You can override per-invocation with --with <id>.",
    header: "Sparring Partner",
    multiSelect: false,
    options: [
      // Include only detected, non-same-host partners. Example shape:
      { label: "Codex (gpt-5)", description: "OpenAI Codex CLI / MCP — sharp on type and edge-case reasoning." },
      { label: "Gemini", description: "Google Gemini — sharp on broad search and doc citations." }
      // "Claude (sonnet)" omitted on a claude-code host (same-host rejection).
    ]
  }
])
```

**Phase 3 — Hint sub-picker (only if Phase 1 = No):**

```
AskUserQuestion([
  {
    question: "Print a one-line reminder at the end of each pipeline stage that /apt:spar is available?",
    header: "Sparring Hint",
    multiSelect: false,
    options: [
      { label: "No (Recommended)", description: "Silent. You remember to run /apt:spar yourself when needed." },
      { label: "Yes", description: "Print `[apt] {stage} complete. /apt:spar available before next stage. (skill, not auto-fire)` at each stage hand-off." }
    ]
  }
])
```

### Task-level worktree isolation (only if host supports worktrees)

First check `host.capabilities.worktrees` from the host-detect output. If `false` (Codex, Gemini, OpenCode), skip this question and leave `task_isolation.worktree_per_task` at its default (`false`).

If `true` (Claude Code), ask:

```
AskUserQuestion([
  {
    question: "Create an isolated git worktree + branch for each new task? Recommended when running multiple agents in parallel on the same repo.",
    header: "Task Worktree",
    multiSelect: false,
    options: [
      { label: "No (Recommended for solo work)", description: "Edit in-place on the current branch. Fine when you're the only agent touching this repo." },
      { label: "Yes", description: "Every new task forks its own branch and worktree under .aperant/worktrees/{scope}/{task-id}/. Multiple /apt runs can execute in parallel without stepping on each other." }
    ]
  }
])
```

Map the answer:
- "Yes" → `task_isolation.worktree_per_task: true`
- "No" → `task_isolation.worktree_per_task: false`

Other `task_isolation` keys (`branch_prefix`, `from_branch`, `push_on_create`, `cleanup_on_close`) keep their template defaults unless the user edits the config file directly.

## 3b. Present Settings (Batch 3: Preferences)

```
AskUserQuestion([
  {
    question: "How should dates be displayed in task folders and reports?",
    header: "Date Format",
    multiSelect: false,
    options: [
      { label: "DD-MM-YY (e.g. 13-04-26)", description: "Day first — common in Europe, UK, and most of the world" },
      { label: "MM-DD-YY (e.g. 04-13-26)", description: "Month first — common in the US" },
      { label: "YY-MM-DD (e.g. 26-04-13) (Recommended)", description: "Year first — ISO-style, sorts chronologically in file explorers" }
    ]
  },
  {
    question: "How should times be displayed?",
    header: "Time Format",
    multiSelect: false,
    options: [
      { label: "24-hour (e.g. 14:30) (Recommended)", description: "No AM/PM — common in most of the world" },
      { label: "12-hour (e.g. 2:30 PM)", description: "With AM/PM — common in the US" }
    ]
  },
  {
    question: "Auto-generate a task index file? (lightweight project management view)",
    header: "Task Index",
    multiSelect: false,
    options: [
      { label: "Yes (Recommended)", description: "Generates .aperant/tasks/INDEX.md with date, status, and title for every task — updated automatically" },
      { label: "No", description: "Skip index generation" }
    ]
  },
  {
    question: "How should /apt:diagram render diagrams by default? (You can override per-call with --mode=file or --mode=mcp.)",
    header: "Diagram Mode",
    multiSelect: false,
    options: [
      { label: "File (default)", description: "Writes a local docs/diagrams/<slug>.excalidraw file — works offline, no external services" },
      { label: "MCP (live canvas)", description: "Renders into a live Excalidraw MCP canvas — requires the Excalidraw MCP server to be connected. Asks for one-time consent on first use." }
    ]
  }
])
```

## 3b-design. Present Settings (Batch 3b: Design Taste) (C26)

Optional step. Offers the user a starting aesthetic for the `apt:design`
pipeline. When picked, copies a reference taste profile from
`packages/framework/templates/design-taste/<direction>.yaml` into
`.aperant/design/taste.yaml`. `apt:design` reads that file on every run
and injects it as a TASTE_BLOCK so generated UI reflects project
identity instead of defaulting to generic-SaaS-Tailwind.

If `.aperant/design/taste.yaml` already exists, confirm overwrite before
copying. Default is "Skip" so this step is zero-friction for users who
don't care about aesthetics yet.

```
AskUserQuestion([
  {
    question: "Pick a starting design taste for apt:design, or skip. You can edit or re-pick later by copying a file from packages/framework/templates/design-taste/ into .aperant/design/taste.yaml.",
    header: "Design Taste",
    multiSelect: false,
    options: [
      { label: "Skip (Recommended for now)", description: "No taste declared. apt:design falls back to generic-SaaS-Tailwind with a note pointing here." },
      { label: "Brutalist", description: "Raw, utilitarian, unafraid of ugly. Dense info, loud contrast, square corners. Think Craigslist, early Basecamp, Are.na." },
      { label: "Editorial", description: "Magazine-like, reading-first, generous rhythm. Serif body type, warm neutrals, slow motion. Think long-form readers, docs sites." },
      { label: "Enterprise-Clean", description: "Trustworthy, quiet, dense-when-it-counts. B2B dashboards, admin consoles. Think Stripe Dashboard, Linear enterprise." },
      { label: "Playful", description: "Saturated, bouncy, high-personality. Consumer + creative tools. Rounded geometry, spring motion. Think Duolingo, Arc Browser." }
    ]
  }
])
```

### Map answer → copy template

- "Skip" → no-op. Leave `.aperant/design/taste.yaml` untouched.
- "Brutalist" → copy `packages/framework/templates/design-taste/brutalist.yaml`
- "Editorial" → copy `packages/framework/templates/design-taste/editorial.yaml`
- "Enterprise-Clean" → copy `packages/framework/templates/design-taste/enterprise-clean.yaml`
- "Playful" → copy `packages/framework/templates/design-taste/playful.yaml`

For any non-Skip choice:

```bash
mkdir -p .aperant/design
```

If `.aperant/design/taste.yaml` already exists, ask:

```
AskUserQuestion([
  {
    question: "`.aperant/design/taste.yaml` already exists. Overwrite with the {direction} starter profile?",
    header: "Overwrite?",
    multiSelect: false,
    options: [
      { label: "No (keep existing)", description: "Leave your current taste.yaml untouched." },
      { label: "Yes, overwrite", description: "Replace with the selected starter profile. You can re-edit it afterwards." }
    ]
  }
])
```

If "Yes, overwrite" or the file does not yet exist:

```bash
cp packages/framework/templates/design-taste/<direction>.yaml .aperant/design/taste.yaml
```

Then tell the user:
```
Design taste set to <direction>.
Edit .aperant/design/taste.yaml anytime — palette, type, motion, density,
and anti_patterns are all free-form YAML. apt:design reads this file on
every run.

See packages/framework/docs/design-taste.md for field-by-field guidance.
```

After this batch, add a row to the Step 8 confirmation table:

```
| Design Taste         | {Skip / Brutalist / Editorial / Enterprise-Clean / Playful} |
```

---

## 3c. Present Settings (Batch 4: Orchestration)

First, detect the host environment:

```bash
node packages/framework/bin/apt-tools.mjs host-detect
```

**If the host is `claude-code` and `capabilities.agent_teams` is `false`:**

Agent teams unlock the best orchestration modes (cross-examining reviewers, natural debates). Offer to enable them:

```
AskUserQuestion([
  {
    question: "Agent teams are not enabled for this project. Enable them? (Recommended — unlocks best review and debate modes)",
    header: "Agent Teams",
    multiSelect: false,
    options: [
      { label: "Yes (Recommended)", description: "Enables agent teams for this project. Reviewers can cross-examine findings, debaters communicate directly." },
      { label: "No", description: "Use sub-agents only. Still parallel, but no inter-agent communication." }
    ]
  }
])
```

If "Yes": write the env var to `.claude/settings.local.json` (gitignored — per-developer, not forced on collaborators):

```bash
# Read existing settings.local.json or start fresh
if [ -f .claude/settings.local.json ]; then
  # Merge env into existing file
fi
```

Write/merge into `.claude/settings.local.json`:
```json
{
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  }
}
```

If the file already exists with other settings, merge the `env` key — do not overwrite existing settings. Use Read + JSON merge + Write.

After writing, note to the user: `"Agent teams enabled. Takes effect on next Claude Code session in this project."`

**If the host is not `claude-code`, or agent teams are already enabled:** skip this question and proceed directly to orchestration mode selection.

---

```
AskUserQuestion([
  {
    question: "How should multi-agent workflows be orchestrated?",
    header: "Orchestration",
    multiSelect: false,
    options: [
      { label: "Auto (Recommended)", description: "Automatically picks the best strategy based on which AI CLI you're using. Works everywhere." },
      { label: "Choose manually", description: "Set explicit preferences for phase delegation, code review, and debates." }
    ]
  }
])
```

If "Choose manually":

```
AskUserQuestion([
  {
    question: "How should pipeline phases be delegated?",
    header: "Phase Delegation",
    multiSelect: false,
    options: [
      { label: "Auto", description: "Best available for your CLI" },
      { label: "Agent Team", description: "Uses Claude Code agent teams (requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)" },
      { label: "Sub-Agents", description: "Spawns separate sub-agents for each phase (available on Claude Code and Codex)" },
      { label: "Sequential", description: "Runs everything inline — works on any CLI" }
    ]
  },
  {
    question: "How should multi-reviewer code reviews run?",
    header: "Review Mode",
    multiSelect: false,
    options: [
      { label: "Auto", description: "Best available for your CLI" },
      { label: "Agent Team", description: "Uses Claude Code agent teams (requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)" },
      { label: "Sub-Agents", description: "Spawns 6 parallel sub-agents for review (available on Claude Code and Codex)" },
      { label: "Sequential", description: "Runs 6 review passes inline, one at a time — works on any CLI" }
    ]
  },
  {
    question: "How should roundtable debates run?",
    header: "Debate Mode",
    multiSelect: false,
    options: [
      { label: "Auto", description: "Best available for your CLI" },
      { label: "Agent Team", description: "Uses Claude Code agent teams (requires CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)" },
      { label: "Sub-Agents", description: "Spawns 10 parallel debater agents (available on Claude Code and Codex)" },
      { label: "Sequential", description: "Runs 10 perspectives inline, one at a time — works on any CLI" }
    ]
  }
])
```

## 3d. Present Settings (Batch 5: Team Collaboration)

Ask whether the user wants team collaboration features:

```
AskUserQuestion([
  {
    question: "Are you working on this repo with other people (co-founders, contributors, an open-source community)?",
    header: "Team Mode",
    multiSelect: false,
    options: [
      { label: "Yes — enable team collaboration", description: "Shares task board, roadmap, and who's working on what via git. Gitignored personal state stays local." },
      { label: "No — solo project", description: "Skip team features. All framework state stays local." }
    ]
  }
])
```

### If "Yes — enable team collaboration" selected:

Give the user a brief overview before running setup:

```
Team Mode enables shared files so collaborators can see each other's work:

  .aperant/team.json         — members (auto-detected from git config)
  .aperant/team-status/      — per-agent "who's working on what" (gitignored,
                               ephemeral, TTL-expired; the canonical cross-
                               agent signal)
  .aperant/tasks/INDEX.md    — task history (date, status, owner)
  .aperant/roadmap/          — milestones, phases, ownership

These files are committed to git. Personal state (state.json, locks,
events, team-status/, proof, paused sessions) stays gitignored.

Updates happen automatically when you use /apt commands — no manual
syncing required. Your git identity (name + email) identifies you
to other collaborators.
```

Then initialize team mode:

```bash
node packages/framework/bin/apt-tools.mjs team init .
```

This:
- Creates `.aperant/team.json` with `enabled: true`
- Auto-registers the current user via `git config user.name` / `user.email`
- Per-agent coordination is written to `.aperant/team-status/{agent-id}.json`
  automatically on lifecycle transitions (gitignored, ephemeral)
- From now on, every task create/update/close auto-updates the shared board
  (events also append to `.aperant/events/{YYYY-MM-DD}.jsonl`)

**If the user has no git identity configured**, the `team init` call will still succeed but won't register a member. Warn them:
```
Git identity not found. Run these before using team features:
  git config user.name "Your Name"
  git config user.email "you@example.com"

Your identity will be auto-registered on your next /apt command.
```

### Roadmap initialization (optional)

After team init, offer to bootstrap a roadmap:

```
AskUserQuestion([
  {
    question: "Initialize a project roadmap? (You can add milestones and phases later)",
    header: "Roadmap",
    multiSelect: false,
    options: [
      { label: "Yes", description: "Creates .aperant/roadmap/ with an empty milestones.json and ROADMAP.md" },
      { label: "Skip", description: "You can run `apt-tools roadmap init` later" }
    ]
  }
])
```

If "Yes":
```bash
node packages/framework/bin/apt-tools.mjs roadmap init .
```

Then tell the user:
```
Roadmap initialized at .aperant/roadmap/project/ROADMAP.md

To add milestones and phases, use:
  apt-tools roadmap add-milestone . --id m1 --title "MVP" --goal "Ship paid version"
  apt-tools roadmap add-phase . --milestone m1 --id p1 --title "Setup" --owner "Andre"
  apt-tools roadmap set-phase-status . --milestone m1 --phase p1 --status in-progress
```

### If "No — solo project" selected:

Skip team setup. Proceed directly to **Step 4**.

If team mode is being *disabled* (user previously had it enabled):
```bash
node packages/framework/bin/apt-tools.mjs team disable .
```

---

## 3e. Present Settings (Batch 6: Visibility policy)

The visibility policy (C35) controls what leaves the user's machine: which
`.aperant/` files get committed to git. Default is `solo` — nothing trackable
except the durable framework scaffolding (config.json, templates, prompts,
etc.). Users opt into sharing deliberately via this step.

### 3e.1 Collect signals first

Before asking any questions, gather deterministic signals so questions can
be skipped when the answer is already on disk:

```bash
node packages/framework/bin/apt-tools.mjs audit visibility-signals .
```

This returns JSON with:
- `publicRemote.{isPublic, url, host}` — true only for github.com / gitlab.com / bitbucket.org
- `existingGitignore.{exists, hasAperantEntries, allowsAny, bypassedByShare}` — list of `!` rules currently in `.aperant/.gitignore` and which of them the current policy does NOT authorize (indicates a hand-edited gitignore drifting from config)
- `teamEnabled` — `team.json.enabled === true`
- `digestsEnabled` — `config.digests.enabled === true`
- `currentPolicy.{visibility, share}` — what's in config right now

### 3e.2 Pick 1–3 questions based on signals

Choose at most 3 questions from the candidate list below. Skip any question
the signals already answer. **Always include the preset pick as the final
question.**

Candidate questions:

1. **(always asked, final)** Pick a visibility preset:
   - **Solo** — nothing shared. Safe default for solo work or private repos.
   - **Team** — roadmap + team.json + decisions + digests shared; per-task specs stay local.
   - **OSS Public** — same toggles as Team, but the framework will emit loud warnings when origin is a public host.

   If `publicRemote.isPublic === true`, append a consequence line to the preset pick: "This repo has a public remote ({host}). Files you opt in to will be world-readable."

2. **(conditional: publicRemote.isPublic && currentPolicy.visibility !== 'solo')** "This repo has a public remote ({host}). Committing `.aperant/` files will make them world-readable. Proceed?"

3. **(conditional: teamEnabled === true && currentPolicy.share.team.roster !== true)** "Team mode is on but `.aperant/team.json` is gitignored. Share the roster so collaborators see each other?"

4. **(conditional: existingGitignore.hasAperantEntries && currentPolicy.visibility === 'solo')** "Your current `.gitignore` already shares some `.aperant/` files. Keep that layout (Team preset) or tighten to Solo?"

5. **(conditional: share.tasks not covered by preset already)** "Share per-task specs and plans? Useful for review + async collaboration; adds noise to git history. Default No."

6. **(conditional: digestsEnabled && currentPolicy.share.digests === null)** "Digests are on for this project. Share the narrative digests (weekly summaries) with the team? Inherited default: Yes."

### 3e.3 Apply + audit

After the preset + toggle overrides are resolved:

1. Write the merged `share` block into `.aperant/config.json` via the existing config-writer path (caller id `setup`). Do NOT remove unrelated keys — only merge the `share` block.
2. Rewrite `.aperant/.gitignore` via:
   ```bash
   node packages/framework/bin/apt-tools.mjs config upgrade-gitignore .
   ```
   The upgrade helper reads the updated config automatically.
3. Run the privacy audit:
   ```bash
   node packages/framework/bin/apt-tools.mjs audit privacy .
   ```
4. Display the audit result inline:
   - If `status === "ok"` (no violations): "Your working tree already matches the new policy."
   - If `status === "violations-found"`: print the violation list + the suggested `untrackCommand`, and tell the user to run it themselves. **Do not auto-run.**
5. Only if the user explicitly asks about purging history, mention `audit privacy . --scrub` — it prints `git filter-repo` commands + a 6-step checklist and never executes them.

### 3e.4 Confirmation row

Add a row to the Step 8 table:
```
| Visibility | {solo/team/oss} (overrides: share.tasks=true, …) |
```

If no custom overrides, drop the parenthetical.

---

## 3f. Present Settings (Batch 7: Docs Policy)

The **docs-coherence policy** (C33) controls what the framework does when a
task's diff touches a documented surface. There are three policy kinds:

| Kind | Meaning | Used for (default) |
|------|---------|--------------------|
| `auto-update` | Reviewer + executor patch the surface inline | INTERNAL files (REGISTRY.md, milestones.json, project_index.json, .aperant/tasks/**) |
| `flag-drift` | Reviewer emits a finding; no auto-edit | EXTERNAL prose (CLAUDE.md, AGENTS.md, READMEs, docs/**) |
| `skip` | Don't audit this surface at all | opt-out |

The defaults match `packages/framework/templates/docs-policy-defaults.json`:
internal state under `auto-update`, external prose under `flag-drift`.
Written to `.aperant/config.json.docs_policy` as a flat
`{ "<glob-or-path>": "auto-update" | "flag-drift" | "skip" }` map.

### 3f.1 Detect structured-prompt support

Re-use the detection from Step 0 (`structured_prompts` capability). If the
host supports `AskUserQuestion(multiSelect: true)`, present the policy
picker as a single multi-select; otherwise use the numbered-input fallback
template shared with Batch 5.

### 3f.2 Present the picker

```
AskUserQuestion([
  {
    question: "Which documented surfaces should /apt:run audit, and how?",
    header: "Docs Policy",
    multiSelect: true,
    options: [
      { label: "CLAUDE.md — flag drift (recommended)",
        description: "External prose; reviewer emits findings, never auto-edits." },
      { label: "AGENTS.md — flag drift (recommended)",
        description: "Constitution / conventions. Findings only." },
      { label: "packages/*/README.md — flag drift (recommended)",
        description: "Per-package READMEs. Findings only." },
      { label: "docs/** — flag drift (recommended)",
        description: "All markdown under docs/. Findings only." },
      { label: ".aperant/roadmap/**/milestones.json — auto-update (recommended)",
        description: "Milestone rollup + phase status. Auto-patched." },
      { label: ".aperant/features/REGISTRY.md — auto-update (recommended)",
        description: "Registry totals refresh on executor post-step." },
      { label: ".aperant/features/*.json — auto-update (recommended)",
        description: "Per-area feature files. Stubs appended on post-step." },
      { label: ".aperant/project_index.json — auto-update (recommended)",
        description: "Workspace deps & package metadata." },
      { label: ".aperant/tasks/** — auto-update (recommended)",
        description: "Task artifacts stay coherent across commit boundaries." }
    ]
  }
])
```

For hosts without structured prompts, present the same options as a
numbered list (Batch 5 style) and read the response as a comma-separated
set of indices to toggle to `skip`. The user is opting OUT of the default
audit, not re-selecting every surface.

### 3f.3 Map answers to `.aperant/config.json.docs_policy`

- Every surface the user LEFT at its default gets its default value
  (auto-update or flag-drift from the recommendations above).
- Every surface the user opted OUT of → `"skip"`.
- The merged map replaces any existing `docs_policy` block in
  `config.json`. Users can hand-edit for finer-grained control; this
  picker is the onboarding happy path.

### 3f.4 Review-Mode routing entry

Extend the existing "1b. Review Mode" routing table (§1b) to include
"Docs Policy" as a selectable edit target — jumping directly back into
this Batch 7 picker.

### 3f.5 Confirmation row

Add a row to the Step 8 table:
```
| Docs Policy | {summary — "defaults" when no surfaces opted out, else "defaults + skip: <list>"} |
```

---

## 3g. Present Settings (Batch 8: Task Tracking + Coding) (AC13)

This batch captures the **task_tracking** backend and the **coding**
defaults block introduced by adoption (ST-10 apt:triage +
ST-3 apt:execute --tdd).

Per ID-01 (Framework full-featured locally; backends are pluggable), the
default is `local-only` — zero GitHub auth required on first run. Users
can switch to `github-issues` (implemented — creates + syncs real issues
via the `gh` CLI) or `app-inbox` (still a stub) later; the framework
abstraction is open for further adapter implementations.

### 3g.1 Present the task-tracking picker

```
AskUserQuestion([
  {
    question: "Where should triage state mirror to?",
    header: "Task Tracking",
    options: [
      { label: "Local files only (recommended for solo / 2-founder)",
        description: "Writes to .aperant/tasks/{id}/triage.json. Zero net dep." },
      { label: "GitHub Issues (creates + syncs real issues via the gh CLI)",
        description: "First mirror creates an issue; transitions update the same issue (label swap), wontfix closes it as not-planned. Requires gh installed + authed + a git remote." },
      { label: "App inbox (post-app-launch — stub)",
        description: "Convex-backed; same state machine, app-rendered. Still a stub." }
    ]
  },
  {
    question: "Publish vertical-slice subtasks to the tracker?",
    header: "Tracker Publishing",
    options: [
      { label: "No (recommended for solo / local)",
        description: "Slices stay in implementation_plan.json only." },
      { label: "Yes (only meaningful with github-issues or app-inbox backend)",
        description: "Each vertical slice becomes an issue via the to-issues template." }
    ]
  }
])
```

For hosts without structured prompts, present each as a numbered list
and read the reply as a single number per question.

### 3g.2 Present the coding-defaults picker

```
AskUserQuestion([
  {
    question: "Activate TDD discipline by default for /apt:execute?",
    header: "TDD Default",
    options: [
      { label: "No (off — opt in per run via --tdd)",
        description: "Single-commit flow; --tdd activates red-green-refactor + G9 audit." },
      { label: "Yes (on — opt out per run via --no-tdd)",
        description: "Vertical-tracer-bullet discipline on every STANDARD/DEEP run." }
    ]
  },
  {
    question: "Enforce the 5-rule prototype discipline on /apt:prototype?",
    header: "Prototype Discipline",
    options: [
      { label: "Yes (recommended — throwaway-marked, single-command-run, etc.)",
        description: "All 5 universal rules apply to every prototype." },
      { label: "No (relaxed — rules are guidance only)",
        description: "Prototypes may grow into production code; not recommended." }
    ]
  }
])
```

### 3g.3 Map answers to `.aperant/config.json`

```jsonc
{
  "task_tracking": {
    "backend": "local-only",            // default; or "github-issues" | "app-inbox"
    "publish_to_tracker": false,        // default
    "tracker_url": null,                // user-supplied when publish_to_tracker = true
    "tracker_label_vocabulary": "default" // or custom name
  },
  "coding": {
    "tdd_default": false,               // default — see ST-3 apt:execute --tdd
    "prototype_discipline": true        // default — see ST-8 apt:prototype
  }
}
```

Migration rule: any existing config WITHOUT a `task_tracking` or
`coding` block gets defaults silently — NEVER error on a missing block.
This is the migration path for projects that adopted Aperant pre-vertical-slice.

### 3g.4 Review-Mode routing entry

Extend the "1b. Review Mode" routing table (§1b) to include "Task
Tracking" as a selectable edit target — jumping back into this Batch 8
picker.

### 3g.5 Confirmation row

Add a row to the Step 8 table:
```
| Task Tracking | {backend} (publish: {true|false}, TDD default: {true|false}) |
```

---

## 3h. Present Settings (Batch 9: Changelog & Release Notes)

This batch captures the **persona-aware changelog + release-notes** preferences introduced by `apt-release-notes/SKILL.md`. Two top-level questions: (1) keep an internal dev `CHANGELOG.md` and (2) publish user-facing release notes. Q2 defaults to **No** on internal/library projects (per spec ID-7: the presence of `personas.json` does NOT auto-enable release-notes — opt-in must be explicit).

If a host supports structured prompts (Claude Code), prefer `AskUserQuestion`. For non-structured hosts (Codex, Gemini-CLI plain mode), present each question as a numbered list and read the reply as a single number per question.

### 3h.1 Present the dev-changelog picker

```
AskUserQuestion([
  {
    question: "Keep an internal dev changelog?",
    header: "Dev Changelog",
    options: [
      { label: "Yes (Recommended)",
        description: "Auto-update CHANGELOG.md from commits on every /apt:ship. Dev-flavored, internal." },
      { label: "No",
        description: "Skip the dev changelog entirely." }
    ]
  }
])
```

### 3h.2 Present the release-notes picker

```
AskUserQuestion([
  {
    question: "Publish user-facing release notes?",
    header: "Release Notes",
    options: [
      { label: "No (Recommended for internal / library projects)",
        description: "Skip the user-facing surface entirely. Most projects pick this." },
      { label: "Yes",
        description: "Enable /apt:release-notes — auto-draft fragments on /apt:ship, compile at tag time." }
    ]
  }
])
```

### 3h.3 If Yes — present the audience + persona-filter sub-pickers

When Q2 = Yes, ask:

```
AskUserQuestion([
  {
    question: "Who is the primary audience for these release notes?",
    header: "Audience",
    options: [
      { label: "End user",        description: "Plain-language, value-focused. Suits consumer apps." },
      { label: "Developer / API", description: "Technical, references API + SDK semantics. Suits libraries." },
      { label: "Internal team",   description: "Lighter polish, faster cadence. Suits company-internal apps." }
    ]
  },
  {
    question: "Which personas should drive the published notes?",
    header: "Persona Filter",
    options: [
      { label: "Primary only",
        description: "Only primary-tier personas surface in published notes." },
      { label: "Primary + Secondary (Recommended)",
        description: "Primary + secondary tiers. Default — balances signal with completeness." },
      { label: "All personas",
        description: "Every tier surfaces. Useful for marketplaces / multi-sided products." }
    ]
  }
])
```

If `.aperant/personas.json` is absent and Q2 = Yes, emit a non-blocking hint:

```
[apt:setup] Note: .aperant/personas.json is missing. Release notes will work but every
            fragment will land in `## Needs Triage` until you run /apt:personas.
```

This is a hint only — the user can still complete setup; the triage bucket is the intentional safety net (spec ID-6 never-silent-drop).

### 3h.4 Map answers to `.aperant/config.json`

Mapping rules (extend Section 4 below):

| User picked | Config write |
|---|---|
| Q1: Yes | `changelog.dev.enabled = true` |
| Q1: No | `changelog.dev.enabled = false` |
| Q2: No  | `changelog.release_notes.enabled = false` (DEFAULT — leave audience + persona_filter at template defaults) |
| Q2: Yes | `changelog.release_notes.enabled = true` and apply the audience + persona-filter sub-pickers |
| Audience: End user        | `changelog.release_notes.audience = "end-user"` |
| Audience: Developer / API | `changelog.release_notes.audience = "developer-api"` |
| Audience: Internal team   | `changelog.release_notes.audience = "internal-team"` |
| Persona filter: Primary only            | `changelog.release_notes.persona_filter = "primary"` |
| Persona filter: Primary + Secondary    | `changelog.release_notes.persona_filter = "primary+secondary"` (DEFAULT) |
| Persona filter: All personas           | `changelog.release_notes.persona_filter = "all"` |

The remaining `release_notes` keys (`output_dir`, `require_pr_field`, `draft.*`, `compile.*`, `publish.*`) keep their template defaults from `packages/framework/templates/config.json` v5. Users wanting to override those edit `.aperant/config.json` directly — they are not surfaced through the Q-block to keep the picker short.

Migration rule: any existing config WITHOUT a `changelog` block gets defaults silently from the template migrator (`migrateConfigSchema` in `src/cli/config/schema-migrate.mjs`) — this is the same auto_added path Batch 8 relies on for the `task_tracking` / `coding` blocks.

### 3h.5 Review-Mode routing entry

Extend the "1b. Review Mode" routing table (§1b) to include "Changelog & Release Notes" as a selectable edit target — jumping back into this Batch 9 picker.

### 3h.6 Confirmation row

Add a row to the Step 8 table:
```
| Changelog & Release Notes | dev: {Yes/No}; release-notes: {Yes/No} (audience: {value}, persona-filter: {value}) |
```

The selective-edit pass through Batch 9 MUST respect the §1b dispatch — it does NOT flip `onboarding.completed`. Marker writes are reserved for the full-flow / "Everything" branches.

---

## 4. Map Answers to Config

**AUDIT-001 — file-routing contract for per-device fields (UPDATED 0.8.1 for FRAMEWORK-RFC-001):** the
following PER-DEVICE fields MUST land in `.aperant/config.local.json`
(gitignored), NOT the shared `.aperant/config.json`:
- `verification.open_report` — covered in the "Auto-Open" mapping below.
- `multi_model.cross_verification.tools` — covered in the "Cross-Verification" mapping below.
- `preferences.date_format` — covered in the "Date Format" mapping below.
- `preferences.time_format` — covered in the "Time Format" mapping below.
- `preferences.quick_task_post_verify` — covered in apt-quick SKILL config block.
- `spar.enabled` — covered in the "Sparring Auto-Fire" mapping below (FRAMEWORK-RFC-001).
- `spar.partner` — covered in the "Sparring Auto-Fire" mapping below (FRAMEWORK-RFC-001).
- `spar.hint` — covered in the "Sparring Auto-Fire" mapping below (FRAMEWORK-RFC-001).

All other fields (including `verification.evidence_capture`,
`multi_model.cross_verification.enabled`, `multi_model.video_review.*`,
`preferences.task_index`, every `orchestration.*` value) stay in shared
`.aperant/config.json`.

Implementation: use the framework's `writeLocalConfigField(targetDir, dotPath, value)`
helper from `packages/framework/src/cli/config/load.mjs` (or its shell-out
equivalent via `apt-tools config write . --local --key <dotpath> --value <json>`)
for the per-device fields enumerated above (`verification.open_report`,
`multi_model.cross_verification.tools`, `preferences.date_format`,
`preferences.time_format`, `preferences.quick_task_post_verify`, and the
three `spar.*` fields). NEVER hand-roll `JSON.parse(readFileSync('.aperant/config.json'))`
followed by `writeFileSync('.aperant/config.json', ...)` for these fields — it
will land per-device data in the shared file and re-introduce the
shared-config trap AUDIT-001 was designed to close.

Reads of these fields anywhere in the framework MUST go through
`loadMergedProjectConfig(targetDir)` or `readLocalOrSharedField(targetDir, dotPath)`
so per-device overrides are honored.

---

Map the user's selections to config values:

**Verify Mode:**
- "Screenshots + Report" → `evidence_capture: true`, `report_formats: ["html", "md"]`
- "Scores Only" → `evidence_capture: false`, `report_formats: []`
- "Full Evidence" → `evidence_capture: true`, `report_formats: ["html", "md", "archive"]`

**Cross-Verification:**
- "Claude Code only" → `multi_model.cross_verification.enabled: false`, `multi_model.cross_verification.tools: []`
- "Choose verification tools" → `multi_model.cross_verification.enabled: true`, `multi_model.cross_verification.tools: [selected tools]`
  - Tool identifiers: `"gemini-cli"`, `"codex-cli"`, `"opencode"`
  - Example: `["gemini-cli", "codex-cli"]`

**Video Review:**
- "No" → `multi_model.video_review.enabled: false`
- "Yes" → `multi_model.video_review.enabled: true`

**Gemini Model (video review only):**
- "Balanced" → `multi_model.video_review.model: "default"`
- "Thorough" → `multi_model.video_review.model: "thorough"`
- "Fast" → `multi_model.video_review.model: "fast"`

**Auto-Open:** "Yes" → `open_report: true`, "No" → `open_report: false`

**Strictness:** "Fix and retry" → `strict: false, max_iterations: 3`, "Strict" → `strict: true, max_iterations: 1`

**Branching:** "Yes" → `auto_branch: true`, "No" → `auto_branch: false`

**Auto Review:** "Yes" → `skip_review: false`, "No" → `skip_review: true`

**TDD Iron Law:** "No" → `tdd.iron_law: false`, "Yes" → `tdd.iron_law: true`

**PR Review Auto-Suggest:**
- "Always (Recommended)" → `pr_review.suggest_after_ship: "always"`
- "Ask me" → `pr_review.suggest_after_ship: "ask"`
- "Never" → `pr_review.suggest_after_ship: "never"`

**Sparring Auto-Fire (FRAMEWORK-RFC-001):**
- Phase 1 "No" → `spar.enabled: false`, ask Phase 3 (hint sub-picker)
- Phase 1 "Yes" → `spar.enabled: true`, ask Phase 2 (partner picker)
- Phase 2 "Codex" → `spar.partner: "codex"`
- Phase 2 "Claude" → `spar.partner: "claude"`
- Phase 2 "Gemini" → `spar.partner: "gemini"`
- Phase 2 graceful-skip path (zero partners detected) → `spar.partner: null` (re-prompted inline by `/apt:run` gate handler when consent is on but partner is null)
- Phase 3 "Yes" → `spar.hint: true`
- Phase 3 "No" → `spar.hint: false` (or omit the field)

**AUDIT-001 — all three fields are PER-DEVICE** and MUST land in `.aperant/config.local.json` via `writeLocalConfigField(targetDir, dotPath, value)` (or its shell-out equivalent `apt-tools config write . --local --key <dotpath> --value <json>`). Do NOT touch shared `.aperant/config.json` for any `spar.*` field. The AUDIT-001 routing block above already enumerates `spar.enabled`, `spar.partner`, `spar.hint` as per-device — this addendum is the call-site reference for future contributors.

Note: task ids are slug-first since v0.6.6 — the date-format setting controls the trailing date component only.

**Date Format:**
- "DD-MM-YY" → `preferences.date_format: "DD-MM-YY"`
- "MM-DD-YY" → `preferences.date_format: "MM-DD-YY"`
- "YY-MM-DD" → `preferences.date_format: "YY-MM-DD"`

**Time Format:**
- "24-hour" → `preferences.time_format: "24h"`
- "12-hour" → `preferences.time_format: "12h"`

**Task Index:** "Yes" → `preferences.task_index: true`, "No" → `preferences.task_index: false`

**Diagram Mode:**
- "File (default)" → `diagram.mode: "file"`
- "MCP (live canvas)" → `diagram.mode: "mcp"`

**Diagram MCP consent (per-user, FRAMEWORK-AUDIT-001).** The `diagram.mcpConsent` field is per-user and lives in `.aperant/config.local.json` (gitignored), NOT in the shared `config.json`. If `config.local.json` doesn't exist or has no `diagram.mcpConsent` field, seed `{diagram: {mcpConsent: null}}` in `config.local.json`. The `diagram.mode` field (file vs mcp) stays in `config.json` as team-shared policy and continues to seed there. Existing `mcpConsent` records in `config.local.json` are preserved across mode flips (changing the mode does not invalidate prior consent for the same host).

**Orchestration (Auto mode):** "Auto (Recommended)" → all three fields set to `"auto"`:
- `orchestration.phase_delegation: "auto"`
- `orchestration.review_mode: "auto"`
- `orchestration.debate_mode: "auto"`

**Orchestration (Manual mode):** map each question independently:
- "Auto" → `"auto"`
- "Agent Team" → `"agent-team"`
- "Sub-Agents" → `"sub-agents"`
- "Sequential" → `"sequential"`

## 5. Write Config

Write merged config to two files per AUDIT-001 routing (see Step 4 block):

- Shared `.aperant/config.json` — all project policy values (the bulk of the answers).
- Per-device `.aperant/config.local.json` — the AUDIT-001 per-device fields enumerated in Step 4 (5 original + 3 `spar.*` fields per FRAMEWORK-RFC-001).

```bash
mkdir -p .aperant
```

Write each JSON file with 2-space indentation. Bump shared `config.json`'s `version` to 4 if upgrading from an older config (versions 2/3 load forward-compatibly — the new `tdd` block is optional). `config.local.json` is gitignored by `.aperant/.gitignore` — do not check it in.

## 6. Save as Global Defaults (Optional)

```
AskUserQuestion([
  {
    question: "Save these as default settings for all new projects?",
    header: "Defaults",
    multiSelect: false,
    options: [
      { label: "Yes", description: "New projects start with these settings (saved to ~/.aperant/defaults.json)" },
      { label: "No (Recommended)", description: "Only apply to this project" }
    ]
  }
])
```

If "Yes":
```bash
mkdir -p ~/.aperant
```
Write `~/.aperant/defaults.json` with the same config.

## 7. Check Prerequisites

### If cross-verification tools selected:

For each selected tool, check if the CLI is available:

```bash
which gemini 2>/dev/null && echo "found" || echo "not found"
which codex 2>/dev/null && echo "found" || echo "not found"
which opencode 2>/dev/null && echo "found" || echo "not found"
```

For any tool not found, inform the user:
```
Cross-verification tool not found: {tool}

Install it:
  Gemini CLI:  npm install -g @anthropic-ai/gemini-cli  (or see https://github.com/anthropics/gemini-cli)
  Codex CLI:   npm install -g @openai/codex              (or see https://github.com/openai/codex)
  Open Code:   go install github.com/opencode-ai/opencode@latest

Cross-verification will skip unavailable tools at runtime.
```

### If video review enabled:

```bash
echo "${GEMINI_API_KEY:-${GOOGLE_API_KEY:-NOT_SET}}"
```

If not set, inform the user:
```
Gemini video review is enabled but no API key found.

Set your key:
  export GEMINI_API_KEY="your-key"

Get a free key at: https://aistudio.google.com/apikey

Note: This key is ONLY used for video review (sending recorded videos to Gemini API).
Cross-verification uses the Gemini CLI directly — no API key needed for that.
```

## 8. Confirm

Display:
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 APT ► SETTINGS UPDATED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

| Setting              | Value                        |
|----------------------|------------------------------|
| Verification         | {Screenshots/Scores/Full}    |
| Cross-Verification   | {Off / gemini-cli, codex-cli}|
| Video Review         | {Off / On (balanced)}        |
| Open Report          | {Yes/No}                     |
| Strictness           | {Fix & retry/Strict}         |
| Auto Branch          | {Yes/No}                     |
| Code Review          | {Yes/No}                     |
| TDD Iron Law         | {Yes/No}                     |
| Sparring Auto-Fire   | {Off / On (codex), On (claude), On (gemini)} (hint: {Yes/No}) |
| Date Format          | {DD-MM-YY / MM-DD-YY / YY-MM-DD} |
| Time Format          | {24h / 12h}                  |
| Task Index           | {Yes/No}                     |
| Diagram Mode         | {file/mcp}                   |
| Design Taste         | {Skip / Brutalist / Editorial / Enterprise-Clean / Playful} |
| Phase Delegation     | {Auto / Agent Team / Sub-Agents / Sequential} |
| Review Mode          | {Auto / Agent Team / Sub-Agents / Sequential} |
| Debate Mode          | {Auto / Agent Team / Sub-Agents / Sequential} |
| Visibility           | {solo / team / oss} (overrides if any)        |
| Changelog & Release Notes | dev: {Yes/No}; release-notes: {Yes/No} (audience, persona-filter) |
| Saved as Defaults    | {Yes/No}                     |

Config saved to: .aperant/config.json

Commands now use these settings automatically:
  /apt:verify       — uses your verification prefs
  /apt:verify-proof — uses cross-verification + video review prefs
  /apt:run          — uses your pipeline + branching prefs
  /apt:setup        — change settings anytime
```

### 8. (continued) Flip `onboarding.completed` on full-flow success

After a successful **full Batch 1-8 pass** (i.e. the user came in via `--reset`, via the fresh-seed marker-state `seeded_from_template:true / completed:false`, or via the review-mode "Everything" option), patch `.aperant/config.json` to set `onboarding.completed: true`. **Preserve** the existing `seeded_from_template` and `seeded_at` fields untouched — they carry forensic value (debug "did init upgrade overwrite my config?"). Concretely:

- Read the current `.aperant/config.json` you just wrote in **Step 5**.
- Set `onboarding.completed = true`. If the `onboarding` block was already present, preserve the other fields verbatim.
- If the starting config was a **legacy unmarked config** (no `onboarding` block — see §1b "Everything" routing), instead write the full block as `{ completed: true, seeded_from_template: false, seeded_at: <ISO-8601 now> }`.
- Re-write `.aperant/config.json` with 2-space indentation.

Selective edits in review mode (Verification, Pipeline, Orchestration, Team Collaboration, Visibility, Task Tracking) DO NOT flip the marker — only a full Batch 1-8 pass does.

### 8a. PreCompact Hook Status

After confirming settings, check whether the framework's PreCompact hook is
installed in `.claude/settings.local.json` (per-developer, gitignored — each
collaborator opts in by running `apt-tools init` locally). This hook keeps
`/apt:run`, `/apt:execute`, `/apt:review`, and other long-running commands
alive across Claude Code's auto-compact — it injects task resume instructions
into the compacted summary so the post-compact agent continues from
`build-progress.json` instead of asking the human to restart.

```bash
# The hook is installed by `apt-tools init` automatically. Check it:
grep -l 'apt-tools.mjs precompact-hook' .claude/settings.local.json 2>/dev/null && \
  echo "PreCompact hook: installed" || \
  echo "PreCompact hook: NOT installed — run apt-tools init to add it"
```

If missing, re-run `node packages/framework/bin/apt-tools.mjs init .` — it's
idempotent and only touches the hook entry. Users who want to opt out can
remove the entry from `.claude/settings.local.json` manually; the framework
will still work, but long runs will fall back to the `--continue` flow after
compaction (human re-invocation required).

**Host parity note.** The PreCompact hook is a Claude Code feature. As of this
writing:

| Host | Auto-compact? | PreCompact-equivalent hook? | Framework behavior |
|------|---------------|----------------------------|---------------------|
| Claude Code | Yes | Yes (`PreCompact`) | Full resume-across-compact via this hook |
| Codex CLI (`codex`) | Yes (internal) | No public hook API | Bailout removal still helps; after compaction the agent re-reads `build-progress.json` + `implementation_plan.json` from instructions in the skill itself |
| Gemini CLI | Partial (session summary) | No | Same fallback — checkpoint files are the source of truth |
| OpenCode CLI | Varies by adapter | No | Same fallback |

On non-Claude-Code hosts the framework still works because the apt-execute and
apt-executor skills explicitly instruct the agent to treat `build-progress.json`
as the authoritative checkpoint and to re-read it after any context reset. The
PreCompact hook is an *optimization* for Claude Code — it injects the resume
block directly into the compacted summary so the agent doesn't have to
rediscover which task is active. Without it, the agent relies on the standing
skill instructions plus whatever the host's own summarization preserved.

</process>
