---
name: apt:quick
description: "Fast task execution — skip planning, go straight to implementation"
apt-skill-version: {{APT_VERSION}}
stage: quick
intent: implement
when_to_use: "The user has a small task (typo, copy change, rounding fix, single-file edit) that is obvious from the description and does not need planning."
user_invocable: true
internal: false
spawns_agent: false
agent_name: null
task_context: create-new
default_track: QUICK
default_execution_mode: auto
execution_modes:
  - auto
  - step
allowed-tools: "Read, Write, Edit, Bash, Grep, Glob"
argument-hint: "apt:quick [task description]"
gates: []
---
<objective>
Execute a small task quickly without full pipeline overhead. For small fixes, doc updates, config changes, and ad-hoc tasks. Skip planning — go straight to implementation with atomic commits and lightweight state tracking.

**QUICK is sequential single-agent by contract.** Per roundtable 2026-05-14 (R1), QUICK = one agent doing intent → implementation in one context window. There are no phase sub-agents. This is a contract, not an optimization — the QUICK track exists precisely because phase isolation buys nothing on tasks small enough that the planner's mental model and the implementer's mental model would be identical.
</objective>

<your_environment>
- **Working directory:** The project root (where you were invoked) UNLESS an active task has a task-level worktree (see below).
- **Constitution:** Read `AGENTS.md` in the project root if it exists
- **State directory:** `.aperant/quick/{task-id}/`
- **Task-level worktree isolation:** If `.aperant/state.json` has an active task with a `worktree_path`, run all editing Bash commands with `cd {worktree_path} &&` prefix. `apt-tools` calls still take the project root as `<project-dir>` so they coordinate through the main repo's shared `.aperant/`. The quick task's `.aperant/quick/{task-id}/` directory lives in the main repo, not the worktree.
</your_environment>

<state_files>
## State Files

**Reads:**
- `AGENTS.md` — Project constitution (conventions, tech stack)
- Codebase files relevant to the task

**Writes:**
- `.aperant/quick/{task-id}/TASK.md` — Human-readable task record
- `.aperant/quick/{task-id}/task.json` — Machine-readable task record (aggregatable)
- `.aperant/quick/{task-id}/evidence/` — Screenshots from visual verification
- `.aperant/quick/INDEX.md` — Running index of all quick tasks
</state_files>

<process>

## 1. Parse Task

Extract the task description from `$ARGUMENTS`.

### 1a. Resolve canonical task id (idempotent)

QUICK now produces a canonical state.active_tasks record so `/apt:ship` can find the task via the lite ship profile. The body owns idempotency because `apt-tools task create` does NOT guard against existing ids (see spec §3 R8).

Two invocation paths converge here:

- **Router path** (`/apt` → `/apt:quick`): the router has already called `task create` and injected `task_id` into your skill context.
- **Direct path** (`/apt:quick foo`): no `task_id` in context — you create one now.

Sequence:

1. **If `task_id` is present in skill context** (router path):
   ```bash
   apt-tools task get . --id {task_id}
   ```
   - If exit 0 AND the returned record has `track === "QUICK"` → reuse, skip the create call.
   - Else (record missing OR wrong track) → call:
     ```bash
     apt-tools task create . --description "$ARGUMENTS" --track QUICK --id {task_id}
     ```
     Parse `task_id` from the returned envelope (it will match the id you passed).

2. **If no `task_id` in skill context** (direct path):
   ```bash
   apt-tools task create . --description "$ARGUMENTS" --track QUICK
   ```
   Parse the generated `task_id` from the envelope — it will be the canonical `{slug}_YY-MM-DD` shape.

The task id is now canonical (no more `quick-YYYYMMDD-*` invention). `QuickTaskSchema` accepts both the canonical `{slug}_YY-MM-DD` form and the legacy `quick-YYYYMMDD-{slug}` form for back-compat with already-shipped task records on disk.

### 1b. Create QUICK working directory

```bash
mkdir -p .aperant/quick/{task-id}
```

**Source finding (best-effort — do not block if nothing found):**
- If the user mentions a priority ID like "P1-1", "P2-3", etc., note it as `source_finding.priority_id`
- If there is a recent verify-proof run directory under `.aperant/proof/` that covers the affected area, note its path as `source_finding.proof_run`
- If the user references a specific test ID from a proof run, note it as `source_finding.test_id`

## 2. Assess Scope

Quickly verify this is appropriate for `/apt:quick`:
- **Good fit:** Single-file fix, typo, config change, small refactor, doc update, dependency bump, adding a missing import, tweaking styles
- **Too big:** Multi-file feature, architectural change, new subsystem, anything requiring tests

If the task is too complex:
```
This task looks too complex for /apt:quick.
Consider using /apt:plan + /apt:execute instead.

Reason: {why it is too complex}
```
Ask the user if they want to proceed anyway or switch to the full pipeline.

## 2.5. Dimension Check (Lightweight)

QUICK tasks skip the full planner, but they still must respect architectural obligations:

1. Read CLAUDE.md — scan for **MUST** obligation language (especially "Deployment Modes (Obligations)")
2. If `.aperant/axes.json` exists, skim the axes list
3. Does this task touch persistence, auth, storage, tokens, or data flow? If YES:
   - This task crosses the deployment-mode axis and likely needs all 3 modes covered
   - A task that needs multi-mode coverage is **too big for QUICK** — escalate:
     ```
     This task crosses deployment-mode obligations (3 modes must be covered).
     Escalating to /apt:plan for proper dimensional coverage.
     ```
   - Ask the user to confirm escalation, or let them override if they're sure it's single-mode only

If the task does NOT cross any obligation axes, proceed normally.

## 3. Load Context

1. Read `AGENTS.md` if it exists — extract relevant conventions
2. Use Glob/Grep to find the files that need changes
3. Read those files to understand current state

## 3.5. Risk Check (mandatory)

Before implementing, check the risk class of files this task will modify. QUICK shares the same Critical/Destructive hard stop as `/apt:execute` step 3b — the speed of QUICK does NOT waive the risk gate. Misclassified QUICK tasks touching `**/auth/**`, `**/schema*`, `**/convex/schema.*`, or other Critical paths must NOT commit without explicit human approval.

```bash
node .aperant/deps/node_modules/@aperant/framework/bin/apt-tools.mjs risk-check . --paths {target files}
```

If the task description contains destructive keywords ("delete", "remove", "drop", "force-push"), pass `--operation delete` so glob matching covers the destructive intent.

Parse the JSON result and apply the gate:

**If `risk_class` is `"Critical"` or `"Destructive"`:**
Stop execution. Show the user:
```
RISK GATE: This QUICK task touches {risk_class} files.
Files: {matched_paths list}
Pattern: {matched_pattern}

Approve this change? (yes/no)
```
Wait for explicit approval. If denied, abort the task and record `verification.risk_gate = "denied"` in `task.json`. The gate is hardcoded at ALL autonomy levels — QUICK does not get to skip it.

**If `risk_class` is `"Elevated"` AND autonomy < 3:**
Show the affected files briefly before proceeding (5-second delay; user can interrupt). At YOLO autonomy, proceed without stopping.

**Why this exists:** roundtable 2026-05-14 R1 surfaced that `apt-quick` previously had no risk-check gate, meaning a misclassified QUICK task touching schema/auth could commit Critical-path changes with zero code-level safeguard. See `.aperant/roundtables/phase-mode-per-track-20260514/REPORT.md` (R1, Risk Assessment §1).

## 4. Implement

Make the changes directly:
- Follow existing code patterns and conventions
- Keep changes minimal — solve the stated problem, nothing more
- If touching code with tests, run the tests to make sure nothing breaks

## 5. Verify (Lightweight)

Run a quick sanity check appropriate to the change:
- **Code change:** Run typecheck and affected tests
  ```bash
  pnpm typecheck 2>&1 | tail -20
  ```
- **Config change:** Validate the config is syntactically correct
- **Doc change:** No verification needed unless `--verify` flag is set
- **Style change:** Run lint on changed files

If visual verification is performed via MCP screenshots:
- Save the screenshot to `.aperant/quick/{task-id}/evidence/` (not /tmp)
- Record the relative path in `task.json` as `verification.evidence_path`

If verification fails:
- Fix the issue
- Re-run verification
- If stuck after 2 attempts, report the failure and let the user decide

## 6. Commit

Create an atomic commit with a descriptive message:

```bash
git add {changed-files}
git commit -m "{type}: {description}"
```

Use appropriate conventional commit type:
- `fix:` for bug fixes
- `docs:` for documentation
- `style:` for formatting/style
- `chore:` for config, dependencies, maintenance
- `refactor:` for code restructuring
- `feat:` for small features (rare for quick tasks)

## 7. Record Task

Write `.aperant/quick/{task-id}/TASK.md`:

```markdown
# Quick Task: {task-id}

## Description
{what was done}

## Files Changed
- {file1}: {brief change description}

## Verification
- {what was checked and result}

## Commit
- {commit hash}: {commit message}

## Timestamp
{ISO date}
```

Write `.aperant/quick/{task-id}/task.json` (conforming to the `QuickTask` schema in `@aperant/framework/schemas`):

```json
{
  "id": "{task-id}",
  "description": "{what was done}",
  "files_changed": [
    { "path": "{file}", "change": "{brief description}" }
  ],
  "verification": {
    "typecheck": "pass|fail|skip",
    "lint": "pass|fail|skip",
    "visual": "pass|fail|skip",
    "test": "pass|fail|skip",
    "evidence_path": "{relative path to screenshot, if captured}"
  },
  "commit": {
    "hash": "{short commit hash}",
    "message": "{commit message}"
  },
  "source_finding": {
    "proof_run": "{path if found}",
    "test_id": "{id if referenced}",
    "priority_id": "{e.g. P1-1 if mentioned}"
  },
  "timestamp": "{ISO 8601 datetime}",
  "duration_seconds": "{elapsed seconds if tracked}"
}
```

Omit `source_finding` entirely if no linkage was found. Omit `evidence_path` if no screenshot was taken. Omit `duration_seconds` if not tracked.

Update `.aperant/quick/INDEX.md`:
- If the file does not exist, create it with this header:
  ```markdown
  # Quick Task Index

  | Task | Description | Commit |
  |------|-------------|--------|
  ```
- Append one row:
  ```
  | [{task-id}]({task-id}/TASK.md) | {one-line description} | {short commit hash} |
  ```
- Keep the table under 100 rows; if it exceeds 100 rows, trim the oldest entries from the top of the table (preserve the header).

## 8. Report

```
Quick task complete: {task-id}
  Changed: {file list}
  Commit: {commit message}
  Verified: {yes/no/skipped}

State: .aperant/quick/{task-id}/TASK.md
       .aperant/quick/{task-id}/task.json
```

If this fix addresses a verify-proof finding:
  Suggest: "Run /apt:verify-proof {area} to re-verify the fix."
  Do NOT run it automatically — the user decides.

### Post-quick verify prompt

After printing the completion report, decide whether to offer an `apt:verify`
pass. Behaviour is gated by `preferences.quick_task_post_verify` in
`.aperant/config.json` (default `"ask"` when the key is absent — older configs
that predate C32 do not need regeneration).

Resolution table:

| Setting           | TTY?     | Action                                                                                  |
|-------------------|----------|-----------------------------------------------------------------------------------------|
| `"never"`         | any      | Skip silently — print nothing, exit.                                                    |
| any value         | non-TTY  | Skip silently — non-interactive callers (spawned subagents, CI) get no prompt.          |
| `"always"`        | TTY      | Invoke `apt:verify` with `{task-id}` immediately.                                       |
| `"ask"` (default) | TTY      | Print `Run verify now? (y/n)` and read one line via `readline` with a 30-second timeout. `y`/`yes` (any case) → invoke `apt:verify {task-id}`. Anything else, including timeout → print `Skipping verify. Run manually with /apt:verify {task-id}.` and exit. |

The `process.stdin.isTTY` check is non-negotiable: if stdin is not a TTY the
skill MUST exit silently regardless of the config value, so spawned subagents
never block on a prompt that no human will answer.

```bash
# Pseudocode the model executes inline.
# AUDIT-001: `preferences.quick_task_post_verify` is per-device — read from
# the MERGED config (shared `.aperant/config.json` + local
# `.aperant/config.local.json`). Local wins on collision. Reading raw
# `config.json` only would miss per-device overrides.
node -e '
  const fs = require("fs");
  const path = require("path");
  const readJsonOrEmpty = (p) => { try { return JSON.parse(fs.readFileSync(p, "utf-8")) ?? {} } catch { return {} } };
  const shared = readJsonOrEmpty(path.join(process.cwd(), ".aperant/config.json"));
  const local = readJsonOrEmpty(path.join(process.cwd(), ".aperant/config.local.json"));
  function merge(a, b) {
    if (a === null || typeof a !== "object" || Array.isArray(a)) return b;
    if (b === null || typeof b !== "object" || Array.isArray(b)) return b;
    const out = { ...a };
    for (const k of Object.keys(b)) out[k] = (k in a) ? merge(a[k], b[k]) : b[k];
    return out;
  }
  const cfg = merge(shared, local);
  let mode = "ask";
  if (cfg.preferences && cfg.preferences.quick_task_post_verify) {
    mode = cfg.preferences.quick_task_post_verify;
  }
  if (mode === "never" || !process.stdin.isTTY) process.exit(0);
  if (mode === "always") { /* invoke apt:verify {task-id} */ process.exit(0); }
  // mode === "ask": readline prompt with 30s timeout, default = skip.
'
```

This is skill markdown — the model executes the behaviour above; nothing here
ships as runtime code.

</process>
