---
name: apt:plan
description: "Create an implementation plan from a task description"
apt-skill-version: {{APT_VERSION}}
stage: plan
intent: implement
when_to_use: "The user has a concrete task and needs a spec + subtask plan investigated against the codebase before any coding begins."
user_invocable: true
internal: false
spawns_agent: true
agent_name: "apt-planner"
task_context: create-new
default_track: STANDARD
default_execution_mode: auto
execution_modes:
  - auto
  - step
  - plan-mode
  - plan-only
  - research
allowed-tools: "Read, Grep, Glob, Write, Bash, WebSearch"
argument-hint: "apt:plan [task description] [--spar]"
gates: 
  - constitution-read
  - constitution-coverage
---
<objective>
Analyze a task, assess complexity, investigate the codebase, and produce a structured implementation plan with spec and subtasks.
</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
- **Prompts directory:** Installed alongside this command in the @aperant/framework package
- **Constitution:** Read `AGENTS.md` in the project root if it exists — it defines project principles, tech stack, and conventions that override defaults
- **Task directory:** `{task_dir}` — passed from the router as an absolute main-repo path. All plan artifacts (spec.md, implementation_plan.json) are written here, NOT to project root and NOT to a worktree-local `.aperant/tasks/` directory.
</your_environment>

<state_files>
## State Files

**Reads:**
- `AGENTS.md` — Project constitution (principles, conventions, tech stack)
- `{task_dir}/design.md` — (optional, C24) Pre-coding design artifact emitted by `/apt:design`. When present, treat its Screen Inventory + Component List as fixed inputs and surface it in spec.md.
- Codebase files discovered via Glob/Grep during investigation

**Writes:**
- `{task_dir}/spec.md` — Requirements specification for the task (written to the task directory passed from the router)
- `{task_dir}/implementation_plan.json` — Structured subtask breakdown (written to the task directory passed from the router)
</state_files>

<process>

## 1. Load Constitution

Read `AGENTS.md` if it exists in the project root. Extract:
- Tech stack and language conventions
- Architectural patterns and constraints
- Testing requirements
- Code style preferences

If `AGENTS.md` does not exist, proceed with defaults inferred from the codebase.

**Gates that fire for this skill:** `constitution-coverage` (blocking, C14) —
every AGENTS.md principle must be addressed in `spec.md` or explicitly marked
N/A under a `## Constitution Coverage` section. See the apt-planner agent
definition (`agents/apt-planner.md`, Section 4.1) for the exact bullet form.
On greenfield projects without AGENTS.md, the gate silently skips.

## 2. Initialize State

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

Parse the JSON output to understand current project state (existing specs, plans, progress).

## 3. Assess Complexity

Analyze the task description from `$ARGUMENTS`:

- **SIMPLE** (under 30 words, single-file change, trivial fix): Skip investigation, write a minimal spec directly. Reference `prompts/spec_quick.md` for the quick-spec pattern.
- **STANDARD** (clear feature, 2-10 files, well-defined scope): Investigate affected areas, write spec, create subtask plan.
- **COMPLEX** (multi-service, architectural change, new subsystem): Deep investigation, stakeholder-style requirements gathering, detailed spec with alternatives considered, fine-grained subtask plan.

If `--simple` flag: force SIMPLE path.
If `--complex` flag: force COMPLEX path.

## 4. Investigate Codebase

For STANDARD and COMPLEX tasks:

1. Use Glob to find files matching the task's domain (e.g., `**/*auth*` for auth-related tasks)
2. Use Grep to find existing patterns, interfaces, types, and conventions
3. Read key files to understand current architecture
4. Identify:
   - Files that will be modified
   - Interfaces/types that must be respected
   - Test files that will need updates
   - Configuration that may need changes

### 4.4. React state guidance — sync-store vs render-committed ref (BUG-025-planner)

When a planned event handler fires a flush/persist immediately after mutating a Zustand/Jotai/refs-stored store, the spec MUST recommend reading from `store.getState()` (or the equivalent direct-read primitive) on the synchronous path, NOT from a `useRef`-populated-by-`useEffect`.

Why: refs populated via `useEffect` lag the store by exactly one render cycle. A handler that mutates the store and immediately reads the ref sees the pre-mutation value, silently corrupting persists and order-of-operations contracts. Reference pattern: `apps/desktop/src/renderer/src/App.tsx::runUpsertForIds` (post-fix commit `4c263856`).

Investigation checklist when the task touches a Zustand/Jotai store or any handler that does flush-after-mutate:

- Grep for `useRef(` references that cache store state (e.g. `const fooRef = useRef(foo)` populated by `useEffect(() => { fooRef.current = foo }, [foo])`).
- If the spec or planned subtasks read from such a ref on a synchronous path that ALSO mutates the store, recommend `store.getState()` (or `useFooStore.getState()`) as the read primitive.
- Note the caveat explicitly in the spec's Implementation Decisions section so the executor doesn't silently revert it.

### 4.5. Consume design.md (C24)

If `{task_dir}/design.md` exists (emitted by a prior `/apt:design` run), load it before decomposing subtasks:

- Treat its **Screen Inventory** and **Component List** as fixed inputs — do NOT re-derive UI decomposition, and do NOT rename components already locked in the design.
- The design's **Data Bindings** section constrains which stores/queries each component reads; honor those when scoping subtasks.
- Critique Log entries flagged as "known gap for the planner to fill" become mandatory inputs — turn each into a subtask or an explicit Out-of-Scope bullet.
- When design.md does NOT exist, planner behavior is unchanged — this step is a no-op.

## 5. Write Specification

Create `spec.md` in the task directory (`{task_dir}` passed from the router, e.g. `/abs/main/repo/.aperant/tasks/{task-id}/spec.md`). Do not use a relative `.aperant/tasks/{task-id}/spec.md` path when the agent is running in a worktree.

**Content format branches on track (Fast Path Guarantee — ID-05):**

### 5.A. QUICK track — legacy 4-section format (hard-exempt from PRD upgrade)

When `track === "QUICK"` (the `apt:classify` rubric routed this as a one-shot
task) OR the complexity is `SIMPLE`, write the existing minimal 4-section
spec. Do NOT promote to PRD shape. The QUICK path is a constraint, not a
toggle — the user opted into one-shot speed; PRD ceremony would violate
that contract.

```markdown
# Task: {task description}

## Requirements
{Extracted from task description + codebase investigation}

## Affected Files
{List of files to modify/create}

## Technical Approach
{How to implement — informed by existing patterns}

## Acceptance Criteria
{Verifiable conditions — grep-checkable, test-runnable}

## Out of Scope
{What this task explicitly does NOT cover}
```

### 5.B. STANDARD / DEEP / COMPLEX tracks — PRD-shaped spec.md

When `track ∈ {"STANDARD", "DEEP"}` OR complexity is `STANDARD` or
`COMPLEX`, write a PRD-shaped spec.md so the artifact survives the task
and is committable as a second-consumer document. Section ordering is
**load-bearing** — downstream tooling (`apt-tools coverage-check`,
`apt-tools consistency check`) reads sections by header.

**Three orthogonal user-facing sections — keep them distinct.** User
Stories carry product motivation, User Outcomes carry the
verify-proof input contract, and Acceptance Criteria carry code-level
invariants. The three do NOT subsume each other; a STANDARD/DEEP spec
carries all three. See the `## User Outcomes` block below for the
verify-proof unit shape (Epic line + atomic outcomes + surface tags
+ empty-with-note escape).

```markdown
# Spec: {task title}

**Task ID:** {task-id}
**Track:** {STANDARD | DEEP}
**Scope:** {framework | desktop | web | core | ui | backend | docs}

## Problem Statement

{What pain are we solving? Cite empirical evidence, prior decisions, or
codebase artifacts where possible. State what's broken or missing today.}

## Solution

{One paragraph: the chosen approach. Then a bulleted net delta of what
ships: new files, modified files, new flags, new config, new skills.}

## User Stories

{One story per user value slice. Format: "**US-NN (persona).** As a
{persona}, when I {trigger}, I want {behavior} so I can {outcome}."
Stories map 1:1 onto subtasks in implementation_plan.json.}

## User Outcomes

{The verify-proof input contract. One bolded `**Epic:**` headline + N
atomic outcomes tagged by surface. Authors write the LITERAL string
`**ON**` — IDs are POSITIONAL and synthesized by the parser (the first
outcome row becomes `O1`, the second `O2`, etc.). Closed surface set:
`electron | web | cli | api | electron+web`. Optional cross-references
via `*(requires ON N)*` where `N` is the digit of a prior outcome's
position. For pure-refactor specs with no user-observable changes, the
body MAY be exactly `_No user-observable changes — pure refactor._`
(italic underscores required, exact em dash, period mandatory).
Coverage-check parses this section into a `user_outcomes` payload —
see the gate table below.}

**Epic:** {one-sentence user-facing capability headline}

- **ON** [surface]: {user does X; system shows/does Y}
- **ON** [surface]: {user does X; system shows/does Y} *(requires ON 1)*
- **ON** [electron+web]: {cross-surface outcome — runs twice, once per surface}

(Refactor-only escape:)
_No user-observable changes — pure refactor._

## Implementation Decisions

{Load-bearing principles carried forward into every subtask. Format:
"### ID-NN: {decision title}" + rationale + practical consequence. Each
ID-NN is referenced from subtask descriptions where relevant.}

## Testing Decisions

{One block per test family: "### TD-NN: {test family name}" + what's
covered + which subtask owns the test file. Critical: Fast Path Guarantee
regression tests (QUICK-exempt assertions) MUST be enumerated here.}

## Out of Scope

{Explicit non-goals. Each bullet names what is deferred + where it
belongs (parallel track, v2 follow-up, separate task).}

## Further Notes

{Sequencing rationale, risk surface, dependencies on other parts of the
codebase, files-affected preview, and any other context the executor
needs but that doesn't fit the seven primary sections.}

### Acceptance Criteria

{Cross-cutting AC1..ACN list — each acceptance criterion gets a stable
ID. Subtasks reference these IDs via their per-subtask
`acceptance_criteria` field (see Section 6). This list IS the
plan-coverage-check input.}
```

**`## User Outcomes` is the verify-proof input contract (STANDARD/DEEP
only — QUICK is hard-exempt per ID-05 / Fast Path Guarantee).** The
section sits between `## User Stories` (product motivation prose) and
`## Implementation Decisions` (load-bearing engineering principles).
Coverage-check (`apt-tools coverage-check validate .`) parses the
section into a `user_outcomes` payload with this gate behavior:

| Header present? | Body shape | Gate result (v0.8.x) | v0.9.0 hard cutover |
|---|---|---|---|
| no | — | `warn` (migration deadline emitted) | `block` |
| yes | `outcomes` (≥1 `**ON**` row) | `pass` | `pass` |
| yes | exactly `_No user-observable changes — pure refactor._` | `pass` | `pass` |
| yes | empty (header but nothing under it) | `block` | `block` |

Closed surface set: `electron | web | cli | api | electron+web`. The
`electron+web` tag means the outcome runs on both surfaces during
verify-proof (split screenshot trees, two test entries in
`verification.json`).

**Constraint — do NOT interview the user.** The PRD is synthesized from
the task description + codebase investigation + AGENTS.md, not from a
clarifying interview. If a section truly cannot be filled, write
`{TBD — needs user input}` so the gap is visible; do NOT pause for
clarification (that's `apt:discuss`'s job, not the planner's).

**Section ordering is mandatory.** `apt-tools coverage-check validate`
greps `## Acceptance Criteria` for AC IDs; `apt-tools consistency check`
greps `## Solution` and `## User Stories`. Renaming or reordering these
breaks downstream tooling.

### 5.1. Design Reference section (C24 — when design.md exists)

When `{task_dir}/design.md` exists, `spec.md` MUST include a `## Design Reference` section **directly below `## Requirements`**. The section cites the design artifact by relative path and enumerates which screens and components the subtasks cover. Shape:

```markdown
## Design Reference

See [design.md](./design.md) — locked {N} screens and {M} components on {accepted-at}.

- **Screens covered by this plan:** {screen-1}, {screen-2}, …
- **Components covered by this plan:** {ComponentA}, {ComponentB}, …
- **Design gaps deferred to follow-ups:** {gap} — {why deferred}
```

When design.md is absent, omit the section entirely (backwards compatible).

Reference `prompts/spec_writer.md` for spec format patterns.
Reference `prompts/complexity_assessor.md` for tier assessment methodology.

## 5.5. Declare Persona Tier (C50 — when personas.json exists)

When `.aperant/personas.json` exists (produced by `/apt:personas`), the
planner MUST attach three persona-related fields to `implementation_plan.json`:

- `declared_persona_tier` — `"primary" | "secondary" | "tertiary"`, the
  effective tier of the personas this task serves (D-04: minimum tier
  covered for multi-persona tasks).
- `declared_personas: string[]` — persona ids / names that this task
  targets; each must resolve to a persona in `.aperant/personas.json`.
- `tier_confidence` — `"high" | "medium" | "low"`, the planner's
  self-reported confidence in its tier inference.

**Infer first, confirm only when uncertain (D-03).** Follow the C47 D-07
pattern: infer the tier from the task description + personas.json BEFORE
asking the user; ask for confirmation only when `tier_confidence` is
`medium` or lower. See `packages/framework/agents/apt-planner.md` §3.85
for the full rubric.

**When personas.json is absent, skip this step.** The r-persona-alignment
gate auto-skips with a hint pointing back here — no gating until the user
opts in via `/apt:personas`.

### 5.5.1 Handle r-persona-alignment rejection (D-08 — when gate fires at plan → execute handoff)

After plan approval (plan-mode) or when `apt-tools gate check execute` is
called at the start of `/apt:execute`, the `r-persona-alignment` gate may
return `status: fail` or `status: warn` with a structured
`evidence.rejection_options[]` array. When this happens, surface the picker
to the user before proceeding:

```
The persona tier declared in this plan ("{{effective_tier}}") is not in
milestone "{{milestone_id}}" focus_tier [{{focus_tier}}].

How would you like to resolve this?
  [D] Defer — park this task until a milestone with matching focus_tier is active
  [R] Reassign — move the task to a milestone whose focus_tier includes "{{effective_tier}}"
  [P] Promote — add "{{effective_tier}}" to milestone "{{milestone_id}}" focus_tier
  [F] Force — proceed anyway (records an override entry in events/)
```

Read the four options from `gate_result.evidence.rejection_options[]` (each has
`key`, `label`, `description`). The user selects by key letter. Branch:

- **D (Defer):** Call `apt-tools task update . --id {task_id} --status deferred` and
  halt execution. Report: "Task deferred — run `/apt:execute` when a matching milestone is active."
- **R (Reassign):** Prompt the user for the target milestone ID, then call
  `apt-tools task move . --id {task_id} --milestone {target_milestone_id}`. Re-run
  `apt-tools gate check execute .` to confirm the tier now passes.
- **P (Promote):** Guide the user to edit `.aperant/roadmap/{scope}/milestones.json`
  to add `"{{effective_tier}}"` to `focus_tier` on milestone `"{{milestone_id}}"`. Re-run
  the gate check to confirm after the edit.
- **F (Force):** Call `apt-tools gate check execute . --force` to bypass the gate and
  record the override in the event log. Emit a `⚠ persona-tier override` note in the
  plan summary.

When `status: warn` (non-blocking enforcement) and the user is in **auto mode** (autonomy
≥ 2), default to **F** silently and log the override — do not interrupt the pipeline.

## 6. Create Implementation Plan

Create `implementation_plan.json` in the task directory (`{task_dir}/implementation_plan.json`).

**Subtask schema branches on track.**

### 6.A. QUICK track / SIMPLE complexity — legacy flat subtask schema

```json
{
  "task": "{task description}",
  "complexity": "simple",
  "spec": "spec.md",
  "subtasks": [
    {
      "id": "1",
      "title": "{subtask title}",
      "description": "{what to do — concrete, not vague}",
      "files": ["path/to/file1.ts", "path/to/file2.ts"],
      "dependencies": [],
      "status": "pending",
      "verification": "{command or check to verify completion}"
    }
  ]
}
```

QUICK subtasks omit `hitl`, `afk`, `acceptance_criteria`, and `user_value`
fields. The one-shot path doesn't need user-value framing or per-subtask
HITL gates.

### 6.B. STANDARD / DEEP / COMPLEX — vertical-slice subtask schema

```json
{
  "task": "{task description}",
  "complexity": "standard|complex",
  "spec": "spec.md",
  "vertical_slice_schema_version": "1",
  "declared_persona_tier": "primary",
  "declared_personas": ["mobile-dev"],
  "tier_confidence": "high",
  "subtasks": [
    {
      "id": "1",
      "title": "{subtask title — user-value framing, not 'add UI'}",
      "description": "{what to do — concrete, not vague}",
      "files": ["path/to/file1.ts", "path/to/file2.ts"],
      "acceptance_criteria": ["AC1", "AC3"],
      "dependencies": [],
      "status": "pending",
      "hitl": "required | review | none",
      "afk": "safe | unsafe",
      "user_value": "{one-line user-value framing — who benefits, how}",
      "verification": "{command or check to verify completion}"
    }
  ]
}
```

**Mandatory STANDARD/DEEP fields (per subtask):**

- `hitl` — `"required" | "review" | "none"`. `required` means a human MUST
  approve the subtask before proceeding (autonomy 1 always pauses;
  autonomy 2 batches recommendations; autonomy 3 escalates only on
  conflict). `review` means the human reviews the diff after the agent
  ships it (post-hoc, not blocking). `none` means agent-only.
- `afk` — `"safe" | "unsafe"`. `safe` means the agent may proceed
  unattended without supervision. `unsafe` means the agent should pause
  at the start of this subtask if no human is present (autonomy < 3).
- `acceptance_criteria` — `string[]` of id-refs (`"AC1"`, `"AC3"`, …)
  into the spec.md `## Acceptance Criteria` section. Every AC in spec.md
  MUST be referenced by at least one subtask (gate G8 consistency-check
  enforces this on ship).
- `user_value` — one-line framing of WHO benefits and HOW. Prevents
  horizontal slicing ("add UI" / "add backend") — every subtask must be
  a vertical user-shippable slice with a defensible value framing.

**Plan-level fields for STANDARD/DEEP:**

- `vertical_slice_schema_version` — `"1"` (current). Stable across the
  v1 schema window; bumped when the subtask shape changes incompatibly.
  Plans without this field are treated as legacy flat schema.

Reference `prompts/planner.md` for subtask decomposition patterns:
- Each subtask should be completable in one focused session
- Dependencies must form a DAG (no circular deps)
- Verification must be automated (test command, grep check, type check)
- Files list must be exhaustive — every file the subtask touches
- Subtask title MUST frame user value, not file scope (e.g., "Solo
  dogfooder gets PRD-shaped spec on STANDARD", NOT "edit apt-plan SKILL.md")

**Framework-scope doc-sync rule (C33).** When `task.scope === "framework"` AND any subtask's `files` intersect `packages/framework/src/cli/**`, the plan MUST end with a subtask whose title contains `Doc sync` (case-insensitive) and whose `files` list includes at least one of `packages/framework/skills/apt-*/SKILL.md`, `packages/framework/agents/apt-*.md`, `packages/framework/templates/agents-*.md`, or `CLAUDE.md`. The detailed rule and rationale live in `packages/framework/agents/apt-planner.md` §5.1; the planner agent appends this subtask automatically when it would otherwise be missing. Smoke-drain emits a warn-only signal for plans that violate the rule.

## 7. Coverage Check

Before declaring the plan complete, validate requirement-to-verification coverage:

```bash
node packages/framework/bin/apt-tools.mjs coverage-check validate .
```

Parse the JSON result:
- If `status: "ok"` -- plan passes coverage check, proceed to persist state
- If `status: "incomplete"`:
  - Read autonomy from config (`node packages/framework/bin/apt-tools.mjs config .`)
  - At autonomy <= 1: present unmapped criteria to user, ask for verification methods
  - At autonomy 2+: auto-generate test stub files for unmapped criteria, add as subtasks to plan
  - Re-run `node packages/framework/bin/apt-tools.mjs coverage-check validate .` to confirm coverage

**`reason: "no-criteria-found"` (zero criteria detected).** The validator reports this when neither the resolved spec.md nor `plan.acceptance_criteria` nor any subtask's `acceptance_criteria` field yielded a single criterion. This is NOT a pass — it means the plan is effectively unverified. Handle it identically to unmapped criteria:

- At autonomy <= 1: STOP AND ASK. Present the `sources_checked` array from the response (each entry has `path`, `present`, `source`, `criteria_count`) so the user can see exactly what was checked, and request they add acceptance criteria to `spec.md` under `## Acceptance Criteria` or add `plan.acceptance_criteria` to `implementation_plan.json`. Do not proceed to execute.
- At autonomy 2+: best-effort regenerate a `## Acceptance Criteria` section of the spec from the subtask titles + descriptions (one criterion per subtask), write it to the resolved `spec_path` (or the task-dir spec.md if `spec_path` is null), and re-run `coverage-check validate` once. If the second run still reports `no-criteria-found`, escalate to the user regardless of autonomy level.

The coverage check ensures every acceptance criterion has at least one subtask with a verification method that covers it. This prevents shipping untestable requirements.

## 8. Persist State

```bash
node packages/framework/bin/apt-tools.mjs commit "plan: create implementation plan for {task}" --files spec.md implementation_plan.json
```

## 8a. Runtime-context adapters

If `APERANT_TERMINAL_ID` is set (you are running under the Aperant
Conductor — a master-orchestrator agent inside the Aperant app), see
`adapters/conductor.md` for the plan-review handshake convention
(`proceed` / `abort` / `[Conductor realignment]` stdin strings) the
Conductor's drawer uses post-commit. The `artifact.ready{kind:'plan'}`
signal itself is now emitted automatically by the `apt-tools commit`
postcondition — no manual emit step required. Native invocations
(Claude Code, Gemini, OpenCode, Codex with no Conductor context) can
skip the adapter entirely and proceed to Section 9.

## 9. Report

Output a summary:
```
Plan created:
- Complexity: {tier}
- Subtasks: {count}
- Files affected: {count}
- Spec: spec.md
- Plan: implementation_plan.json

Next: /apt:execute
```

### 9b. --spar flag (FRAMEWORK-RFC-001)

If `$ARGUMENTS` contained `--spar`, dispatch `/apt:spar` against the
just-written `spec.md` + `implementation_plan.json` before reporting Next.

Topic frame: the §1 Scope paragraph from `spec.md` (1-2 sentences). Same
`--timeout-ms 120000` pipeline-mode budget and NO `--rounds` flag (per
FRAMEWORK-BUG-038 — pipeline gates always defer to the skill default).
When merged-config `spar.partner` is set, append `--with <partner>`.

```
/apt:spar --timeout-ms 120000 [--with <partner>] <topic-frame-from-spec.md-§Scope>
```

After spar returns, append the termination headline + Layer 2 path
(`.aperant/spar/<slug>-<ts>.md`) into the report output so the user can
review findings before invoking `/apt:execute`.

### 9a. Mode-Aware Compact Suggestion (Human-in-the-Loop Only)

Decide whether to show a compact suggestion by reading the **per-task autonomy** from state — not the global default, because the router asks per-task and stores the answer on the task record.

```bash
node packages/framework/bin/apt-tools.mjs task get . --id {task_id}
```

Parse the JSON result and read `task.autonomy` (numeric, 0–3):
- `0` = supervised
- `1` = guided (step-by-step)
- `2` = autonomous (full-auto)
- `3` = yolo

**Also** check `task.execution_mode` if present (string: `"plan-only"`, `"plan-mode"`, `"step"`, `"auto"`, `"research"`). `execution_mode` is what the router writes when the user chose at prompt-time; `autonomy` is the fallback numeric level.

**Show the suggestion when** any of these is true:
- `task.execution_mode` ∈ `{"plan-only", "plan-mode", "step", "research"}`
- `task.autonomy` ≤ 1 (supervised or guided) AND `execution_mode` is not `"auto"`

For `plan-mode`, end the planner's turn with **"Plan ready for approval — /apt will now prompt"** (the /apt orchestrator handles the three-choice approval handshake and records `plan_approval.json`). Do **not** emit `/apt:execute` as the next action in plan-mode — execution is gated on the approval handshake.

**Do NOT show when**:
- `task.execution_mode === "auto"` (explicit full-auto)
- `task.autonomy` ≥ 2 AND `execution_mode` is unset

If the `task get` call fails (no state, no task record), fall back to `.aperant/config.json` → `autonomy.default`: show only if `≤ 1`.

When the criteria are met, append this block to your report:

```
─────────────────────────────────────────────────────────
  Plan is ready for your review. Before running execution,
  consider running `/compact` (or `/clear`, if you don't
  need conversation history) to free context for the build.
  Everything you need is persisted in {task_dir}/ — after
  compact, run: /apt:execute
─────────────────────────────────────────────────────────
```

**Why this matters:** in full-auto the pipeline flows straight from plan → execute → verify → review in the same session. The executor trusts auto-compact to handle context pressure via the PreCompact hook, which re-injects task state into the compacted summary. Emitting a "now would be a good time to compact" message in full-auto would just pause execution unnecessarily. Compact suggestions are a convenience for the human — if no human is in the loop, don't suggest anything, let the harness auto-compact.

</process>
