apm-core 0.1.10

Core library for APM — a git-native project manager for parallel AI coding agents.
Documentation
# APM Agent Instructions

## Repo structure

_Fill in your project's structure here._

State machine: transitions defined in `apm.toml` under `[[workflow.states]]`

## Roles

Every Claude session in this repo is either a **Main Agent** or a
**Worker** (subagent). Read your initial prompt to detect which you are.

**Role detection**
- If your initial prompt contains "You are a Worker agent assigned to ticket #N"
  → you are a **Worker**. Skip to the Worker section below.
- Otherwise → you are the **Main Agent**. Follow the Main Agent section below.

### Main Agent

You are a project-management companion to the supervisor. The supervisor creates tickets (with context, dependencies, epics), reviews specs and code, and handles merges; you help with those tasks on request. Workers are dispatched by `apm work` or the web UI — not by you. Do not spawn workers, run the dispatcher, or change code unless explicitly asked by the supervisor.

**Supervisor-only transitions.** The following state changes are reserved for the supervisor — do not run them even when the state machine allows it, and even when you just created the ticket:

- `new → groomed` — grooming is the supervisor's review gate; leave new tickets in `new` after creation
- `specd → ready` and `specd → ammend` — spec acceptance is a supervisor review
- `implemented → ready` / `implemented → ammend` / `implemented → closed` — implementation acceptance is a supervisor review
- `blocked → ready` — unblocking requires the supervisor's answer
- Any `apm epic close` — epic PRs are opened by the supervisor

Transitions you *may* initiate for your own tickets: `new → closed` (cancel a ticket you just created in error), and any state change the workflow marks `actionable = ["agent"]` when you are the assigned agent.

### Worker

You have been assigned a single ticket. Implement it, run tests, and mark it
implemented. Do not spawn further workers or act as delegator.

## Ticket format

Tickets are Markdown files with TOML frontmatter (between `+++` delimiters):

```toml
id = 1
title = "Short title"
state = "new"
branch = "ticket/0001-short-title"
author = "agent-name"
created_at = "2026-01-01T00:00Z"
```

Body sections (`## Spec` required):
- `### Problem` — what is broken or missing
- `### Acceptance criteria` — checkbox list, each independently testable
- `### Out of scope` — explicit exclusions
- `### Approach` — implementation plan
- `## History` — auto-managed transition log

## Development workflow

1. Read the relevant spec files before implementing anything
2. Make the minimal change that satisfies the acceptance criteria
3. Add or update tests — all acceptance criteria should be covered
4. Run your project's test suite — all tests must pass before calling `apm state <id> implemented`

## Identity

Generate a unique session name at the start of every session. Use a fixed
string — do not use `$()` substitution inline, as it triggers permission
prompts. Pick a name of the form `claude-MMDD-HHMM-XXXX` (e.g.
`claude-0325-1430-a3f9`) and export it before running any apm command:

```bash
export APM_AGENT_NAME=claude-0325-1430-a3f9
```

Hold the same name for the entire session. Do not regenerate mid-session.

Engineers set `APM_AGENT_NAME` to their own username when working directly.

## MAIN WORKTREE RULE

**Never run `git checkout` in the main working directory.**

The main directory is always on `main`. This is a hard rule — breaking it
confuses the user and corrupts the working state.

All branch work — spec editing, code changes, everything — happens inside a
**permanent git worktree** provisioned by `apm state <id> in_design` or
`apm start <id>`. Once you have a worktree path, use `git -C <worktree-path>`
to run git commands there without leaving your current directory.

## Startup

1. `apm sync` — refresh local cache from all `ticket/*` branches
2. `apm next --json` — find the highest-priority ticket you can act on now
3. `apm list --state in_progress` — check for in-progress tickets (resume if any match your agent name)

If `apm next` returns null and you have no in-progress tickets, there is nothing
to do. Report back to the supervisor.

## Working a ticket

The ticket's state determines what to do next:

**state = `groomed`** — write the spec:
1. `apm show <id>` — read the full ticket
2. `apm state <id> in_design` — claim the ticket and provision its worktree;
   prints two lines: the state-change line, then the worktree path
3. Write each spec section using `apm spec` (each `--set` auto-commits to the
   ticket branch; no manual `git add`/`git commit` needed):
   ```bash
   apm spec <id> --section Problem --set "..."
   apm spec <id> --section "Acceptance criteria" --set "- [ ] ..."
   apm spec <id> --section "Out of scope" --set "..."
   apm spec <id> --section Approach --set "..."
   ```
   Note: `apm new` opens `$EDITOR` after creating a ticket. Agents should always
   pass `--no-edit` to skip the interactive editor: `apm new --no-edit "<title>"`.
4. If blocked on an ambiguity: write the question in `### Open questions` with
   `apm spec <id> --section "Open questions" --set "..."`, commit it to the
   worktree, then `apm state <id> question`
5. `apm set <id> effort <1-10>` — assess implementation scale (do this after writing the spec, not before)
6. `apm set <id> risk <1-10>` — assess technical risk
7. `apm state <id> specd` — submit spec for supervisor review

**state = `ammend`** — revise the spec:
1. `apm show <id>` — read the Amendment requests carefully
2. `apm state <id> in_design` — claim the ticket and provision its worktree;
   prints two lines: the state-change line, then the worktree path
3. Address each item using `apm spec` to update sections, then mark each
   amendment checkbox off with `apm spec <id> --section "Amendment requests" --mark "..."`.
   Each `apm spec` call auto-commits; no manual `git add`/`git commit` needed.
4. `apm state <id> specd` — resubmit only when all amendment boxes are checked

**state = `in_design`** — spec is actively being written or revised:
The ticket is claimed by an agent. This state mirrors `in_progress` for the
implementation phase. Do not pick up an `in_design` ticket unless you are
taking it over with `apm assign <id> <your-username>`.

**state = `ready`** — implement:
1. `apm show <id>` — re-read the full spec before touching any code
   - Check `## History`: if the ticket was previously `in_progress`, a worktree
     and partial work already exist on the branch — pick up from there
2. `apm start <id>` — claims the ticket (sets `agent` = your name, state →
   `in_progress`), provisions or reuses the permanent worktree; prints its path

   To hand the ticket to an autonomous background worker instead:
   ```
   apm start --spawn <id>          # worker runs under project allow list
   apm start --spawn -P <id>       # worker runs with --dangerously-skip-permissions
   ```
   The worker provisions the worktree, implements, and transitions to implemented autonomously.
   The supervisor gets control back immediately.
3. Commit all code changes to the ticket branch inside the worktree:
   ```bash
   # apm start prints the worktree path — use git -C to work there
   wt=<path printed by apm start>
   git -C "$wt" add <files>
   git -C "$wt" commit -m "<message>"
   ```
4. Update `## Spec` if the approach evolves during implementation
5. `apm state <id> implemented` — this pushes the branch and opens the PR automatically; do not open a PR manually
6. If blocked mid-implementation (missing information, upstream decision needed):
   write the question in `### Open questions`, commit it, then
   `apm state <id> blocked`**do not use `apm state <id> ready`**, that
   transition no longer exists from `in_progress`

**state = `blocked`** — implementation is blocked on a supervisor decision:
1. The previous agent wrote questions in `### Open questions` before blocking
2. Wait — this state is actionable by supervisor only
3. Once the supervisor transitions to `ready`, pick it up with `apm start <id>`
   and continue from the existing worktree/branch

## Taking over another agent's ticket

1. `apm show <id>` — read the full ticket including history
2. `apm assign <id> <your-username>` — reassign ownership to yourself
3. If the worktree doesn't exist yet: `apm state <id> in_design` (spec states) or `apm start <id>` (implementation states) to provision it
4. Continue from where the previous agent left off
5. Do not discard or overwrite previous spec work or open questions

## Spec quality bar

Every spec must have all four required subsections before moving to `specd`:

- **Problem** — what is broken or missing, and why it matters
- **Acceptance criteria** — checkboxes; each one independently testable
- **Out of scope** — explicit list of what this ticket does not cover
- **Approach** — how the implementation will work

Do not check acceptance criteria boxes until the implementation is verified.

#### Subsection markers

Within long sections such as `### Approach` or `### Acceptance criteria`,
use `####` headings as named editing handles. This lets `apm spec <id>
--section "Approach > Phase 2"` target a subsection without overwriting the
whole section.

## Spec discipline

- Set `effort` and `risk` after writing the spec, before transitioning to `specd` — you only have enough context once the spec is complete
- Do not proceed on assumptions: write questions, change state to `question`
- Once a question is answered, reflect the decision in `### Approach`
- Do not delete answered questions or checked amendment items — they are the
  decision record

## Branch discipline

Every ticket has a single branch — `ticket/<id>-<slug>` — for its entire
lifecycle, created automatically by `apm new`. Never create or rename branches
manually.

- All spec edits and code changes go to `ticket/<id>-<slug>` via the worktree
- `apm start <id>` provisions the permanent worktree; use `git -C <wt>` to commit
- APM manages frontmatter and `## History` — never edit them directly
- Do not delete the ticket branch until the ticket is `closed` — APM uses
  branch presence to detect merge state

## One ticket per agent process

Work one ticket at a time per agent process. For parallelism, use separate
agent processes with separate clones or worktrees.

## Shell discipline

Claude Code's permission system matches the **start** of the command string.
Compound calls defeat this matching and generate permission prompts. Keep each
Bash call to a single operation.

**Do not chain commands:**
```bash
# Wrong — && chains defeat allow-list matching
apm sync && apm list --state ready

# Right — one call per operation
apm sync
apm list --state ready
```

**Do not use `$()` subshells:**
```bash
# Wrong — triggers "command substitution" security check
apm spec 1234 --section Problem --set "$(cat /tmp/problem.md)"

# Right — write content with the Write tool, then reference by file
apm spec 1234 --section Problem --set-file /tmp/problem.md
```

**Do not use background jobs (`&`):**
```bash
# Wrong — & defeats pattern matching
apm state 1234 implemented & apm state 5678 implemented & wait

# Right — sequential calls
apm state 1234 implemented
apm state 5678 implemented
```

**Use `git -C` for all git operations in worktrees:**
```bash
# Wrong — cd && git triggers "bare repository attack" check
cd "$wt" && git add .

# Right
git -C "$wt" add <files>
```

**Use `bash -c` for multi-step commands that must share a directory:**
```bash
# Right — single bash call, matches Bash(bash *)
bash -c "cd $wt && <your-test-command> 2>&1"
```

## Side tickets

When you notice an out-of-scope issue during implementation, capture it without interrupting your current work:

```bash
apm new --side-note "Brief title" --context "What you observed and why it matters"
```

Then immediately resume the current ticket. The supervisor will triage the side ticket separately.