---
name: ao-task
description: "Create, refine, and manage issues. Use for creating new issues from loose ideas, refining ambiguous issues, bulk operations, or JSON export."
category: core
invokes: [ao-state, ao-interview, ao-usage]
invoked_by: [ao-planning, ao-focus-scan, ao-report]
state_files:
  read: [focus.json, issues/events.jsonl, issues/active.jsonl]
  write: [issues/events.jsonl, issues/active.jsonl]
references: [REFERENCE.md, .ao/reference/confidence.md, .ao/reference/completion-gate.md]
---

# Issue Management

> **Confidence Reference**: This skill uses canonical confidence definitions from [.ao/reference/confidence.md](.ao/reference/confidence.md). When creating issues, always set an appropriate confidence level.
> **Completion Gate**: See [.ao/reference/completion-gate.md](.ao/reference/completion-gate.md) for completion requirements.

**Uses `ao` CLI for all issue operations.** Always include `--yes --format json --progress none` on every invocation. See `ao-usage` skill for full command reference.

## CRITICAL: Issue Management ONLY

**This skill manages issues. It NEVER implements code.**

- ✅ Create, refine, list, search, triage issues
- ✅ Move issues between priority files  
- ❌ **NEVER implement features or fix bugs**
- ❌ **NEVER modify code files**

## <HARD-GATE> Scope Boundary — No Implementation After Issue Creation

**After creating or triaging issues, STOP and offer a handoff.**

Do NOT:
- Start implementing the issue you just created
- Auto-proceed to ao-planning or ao-implementation
- Write any production code or tests for the new issue

Instead, present handoff options and let the user choose the next action. Violation of this gate is a **protocol failure**.

After any issue operation, ALWAYS offer a handoff — never auto-proceed.

**Reference**: See [REFERENCE.md](REFERENCE.md) for templates, CLI commands, JSON export.

---

## Issue ID Format

**Format**: `{TYPE}-{NUMBER}@{HASH}`
**Example**: `BUG-0023@efa54f`, `FEAT-0001@c2d4e6`

Types: `BUG` | `FEAT` | `CHORE` | `ENH` | `SEC` | `PERF` | `DOCS` | `TEST` | `REFAC` | `PLAN`

### ID Validation (MANDATORY)

**Regex pattern**: `^[A-Z]+-\d{4}@[a-f0-9]{6}$`

**All issue IDs MUST be validated against this pattern before creation.**

| Component | Rule | Valid | Invalid |
|-----------|------|-------|---------|
| TYPE | Uppercase letters | `FEAT`, `BUG` | `feat`, `Feature` |
| NUMBER | 4 digits, zero-padded | `0001`, `0042` | `1`, `42` |
| @ | Literal separator | `@` | `-`, `#` |
| HASH | 6 hex chars, lowercase | `a1b2c3`, `efa54f` | `preview`, `abc` |

### ID Generation

IDs are auto-generated by `ao` when creating issues. The format is `{TYPE}-{NNNN}@{hash6}` where the hash is deterministic from the counter value.

**Never manually craft issue IDs** — always use `ao issue add` which returns the assigned ID in `{"issue_id": "..."}` output.

**NEVER use descriptive strings like `@preview`, `@fix`, `@feature` as the hash suffix.**

---

## Minimal Issue Input (IssueCreateInput)

```json
{
  "title": "{title}",
  "type": "feat",
  "priority": "medium",
  "status": "todo",
  "epic": "",
  "owner": "agent",
  "confidence": "normal",
  "requirements": [],
  "acceptance_criteria": [],
  "scope": {"files_to_change": [], "files_must_not_change": []},
  "dependencies": {"depends_on": [], "blocks": []},
  "references": {"spec_file": ""},
  "notes": ""
}
```

Create via:
```bash
printf '%s' '{"title":"...","type":"feat","priority":"medium",...}' | \
  ao issue add --in - --yes --format json --progress none
```

---

## Issue Size Guardrails

- Keep backlog items **minimal**: title, metadata, 1–2 sentence description, acceptance criteria if known.
- If an issue needs more than ~20 lines, **move details to a reference file** in `.agent/ops/issues/references/` and link it in the issue.
- Reference files should contain research, long descriptions, examples, diagrams, or interview notes.
- Never embed large code blocks or research dumps directly in backlog items.

### Reference File Format

- Path: `.agent/ops/issues/references/{ISSUE-ID}.md`
- Include a short header and a link back to the issue.
- Example:

```
# {ISSUE-ID} — {title}

Added YYYY-MM-DD.

## Context
...
```

---

## Issue Data Storage

**Issues are stored in the ao JSONL event store** — no markdown files per priority.

| Path | Purpose |
|------|--------|
| \.agent/ops/issues/events.jsonl\ | Append-only event log (all mutations) |
| \.agent/ops/issues/active.jsonl\ | Current active issues (rebuilt from events) |
| \.agent/ops/issues/references/\ | Detailed spec files linked from issues |

**All issue creation, updates, and closures go through \oi\ CLI.** Never edit \vents.jsonl\ directly.

---
## Operations

### Confidence Field (FIRST-CLASS)

**Confidence is a REQUIRED field for all issues.** When creating or refining issues:

| Confidence | When to Use | Workflow Impact |
|------------|-------------|----------------|
| `low` | Uncertain requirements, complex changes, first-time patterns | 3+ plan iterations, mandatory interview, hard stops |
| `normal` | Standard work, known patterns, moderate complexity | 2 plan iterations, soft approval gates |
| `high` | Simple changes, well-understood, minimal risk | 1 iteration or skip, minimal gates |

**Setting Confidence on Create:**

1. **Infer from context:**
   - User says "quick fix", "trivial", "simple" → `high`
   - User says "not sure", "complex", "risky" → `low`
   - No indicators → `normal`

2. **Ask if ambiguous:**
   ```
   What's your confidence level for this work?
   - [L]ow — uncertain requirements or approach
   - [N]ormal — standard complexity (default)
   - [H]igh — simple, well-understood change
   ```

3. **Default from constitution:**
   - If constitution has `default_confidence:`, use that
   - Otherwise default to `normal`

**Updating Confidence:**

- During planning: may adjust based on research findings
- During implementation: may lower if unforeseen complexity
- Always log confidence changes in issue log

### Create Issue

1. Analyze request for type, title, priority, scope, criteria
2. Use `ao-interview` for missing info
3. **Apply YAGNI check** (see below)
4. Build `IssueCreateInput` JSON with all known fields
5. Create via `ao issue add --in -`:
   ```bash
   printf '%s' '{"title":"...","type":"feat","priority":"medium","confidence":"normal",...}' | \
     ao issue add --in - --yes --format json --progress none
   ```
6. Capture the returned `issue_id` for logging and reference
7. **STOP AND HANDOFF**

### YAGNI Check When Creating Features

When creating FEAT (feature) issues, apply YAGNI before finalizing:

#### YAGNI Questions for New Features

1. **Is this feature needed NOW?**
   - Yes → Continue
   - No → Add to ao with `priority: backlog` instead

2. **What's the MINIMAL viable version?**
   - Describe the simplest implementation
   - Remove nice-to-haves

3. **What happens if we DON'T add this?**
   - If nothing breaks → Consider removing
   - If critical functionality lost → Keep

#### When YAGNI Splits Features

If a feature has multiple components:
- Create one issue for the essential part
- Move non-essential parts to ao backlog as separate ideas (priority: backlog)
- Note dependencies in issue description

**Example:**
```
Original: "Add user authentication with OAuth, JWT, and social login"

YAGNI-applied:
- Issue: "Add username/password login" (essential)
- Backlog idea: "OAuth integration" (deferred)
- Backlog idea: "Social login providers" (deferred)
```

### Mandatory Handoff

```
✅ Issue created: {ISSUE-ID}: {title}

What's next?
1. Start implementing (requires confirmation)
2. Create more issues
3. Do nothing
```

### Refine Issue

Triggers for refinement:
- Generic titles ("Fix bugs")
- Missing acceptance criteria
- Confidence marked `low`

**See: Refinement Procedure (below) for detailed structured questioning process.**

## Refinement Procedure (Structured Questioning)

**Before starting refinement:**
1. Read the current issue from its priority file
2. Identify what's missing or unclear
3. Plan which focus areas need clarification

**Focus Areas to Cover:**

1. **Purpose** - Why are we doing this?
   - What problem does this solve?
   - Who benefits from this change?
   - What's the impact if we don't do it?

2. **Constraints** - What's limiting us?
   - Technical constraints (platforms, languages, APIs)
   - Time constraints (deadlines, milestones)
   - Resource constraints (team size, budget)
   - Compatibility constraints (must work with X, can't break Y)

3. **Success Criteria** - How will we know it's done?
   - Measurable outcomes (metrics, performance targets)
   - Testable behaviors (acceptance criteria)
   - Definition of done (tests pass, docs updated, etc.)

4. **Scope** - What's in and out?
   - Explicitly IN SCOPE (what we will do)
   - Explicitly OUT OF SCOPE (what we won't do)
   - Boundary conditions (where does it stop?)

**Question Flow:**

1. Start with Purpose (understand the "why")
2. Move to Scope (define boundaries)
3. Cover Constraints (identify limitations)
4. End with Success Criteria (define completion)

For each focus area:
- Ask ONE clear question
- Wait for user response
- Record the answer
- Validate understanding before moving on

**Decision Points with Multiple Choice:**

When refining priority, type, or scope - present clear options:

*Priority Example:*
```
Based on your answers, I recommend priority: HIGH (data loss risk)
What priority should this issue have?

1) HIGH - Data loss, security, or production blocker
2) MEDIUM - Important but not blocking
3) LOW - Nice to have, can defer

Your choice (1/2/3 or specify):
```

*Type Example:*
```
What type of issue is this?

1) FEAT - New feature or enhancement
2) BUG - Defect or bug fix
3) CHORE - Maintenance, cleanup, refactoring
4) DOCS - Documentation only

Your choice (1/2/3/4 or specify):
```

**Validation Checkpoint:**

After all questions asked:
1. Summarize the refinements
2. List what changed (priority, type, scope, criteria)
3. Ask: "Is this accurate? (yes/revise)"
4. If yes: Update issue file
5. If revise: Go back to specific area

**Example Refinement Session:**

```
User: /ao-task refine BUG-0012

AO: I'll help refine BUG-0012. Let me ask some clarifying questions.

Question 1/4: Purpose
What is the actual impact of this bug?
1. Data loss or corruption
2. Feature completely broken
3. Workaround exists but annoying
4. Minor UI glitch

User: 1

AO: Noted - data loss or corruption. That's serious.

Question 2/4: Scope
Which areas does this affect?
1. Import functionality only
2. All file operations
3. Multiple features
4. Not sure yet

User: 1

AO: Understood - import functionality only.

[Continue with Constraints and Success Criteria]

Summary of refinements:
- Priority: medium → HIGH (data loss risk)
- Scope: affects only import functionality
- Acceptance criteria: must not break existing imports
- Success criteria: all existing import tests pass

Is this accurate? (yes/revise)

User: yes

AO: Patching BUG-0012 via ao...
Done. Issue refined.
```

### Change Priority

```bash
printf '%s' '{"set":{"priority":"high"},"append":{"log":[{"ts":"YYYY-MM-DD","text":"Priority changed"}]}}' | \
  ao issue patch ISSUE_ID --in - --yes --format json --progress none
```

### Complete Issue

> **Canonical Reference**: See `.ao/reference/completion-gate.md` for the authoritative completion checklist and confidence-aware rules.

**When an issue is done:**

1. **Verify issue is truly complete:**
   - All acceptance criteria checked
   - Tests pass
   - Validation against baseline passes

2. **Close via ao:**
   ```bash
   ao issue close ISSUE_ID --log "Completed: <summary of what changed>" \
     --status done --yes --format json --progress none
   ```

3. **Closed issues** are automatically removed from `active.jsonl` on next rebuild.  
   Their events remain in `events.jsonl` (append-only). No manual archival needed.

**Issue completion is NOT valid without running `ao issue close`.**

### Triage Backlog

```bash
# List backlog items
ao ls priority:backlog --yes --format json --progress none
# Promote to higher priority
printf '%s' '{"set":{"priority":"medium","status":"todo"}}' | \
  ao issue patch ISSUE_ID --in - --yes --format json --progress none
```

Only human can promote from backlog to active priority (not autonomous agents).

---

## Issue Discovery

Other skills invoke discovery when they find potential work:

| Skill | Triggers |
|-------|----------|
| `baseline` | Warnings, failures, missing coverage |
| `planning` | Sub-tasks, prerequisites |
| `critical-review` | Bugs, security, tech debt |

Procedure:
1. Collect findings
2. Categorize by type/priority
3. Present summary to user
4. Create issues on confirmation
5. Offer next actions

---

## Quality Checklist

- [ ] Valid ID format
- [ ] Action-oriented title
- [ ] Testable acceptance criteria
- [ ] Appropriate confidence level
## Issue Description Quality

*Inspired by [writing-clearly-and-concisely patterns](https://skills.sh/softaworks/ao-toolkit/writing-clearly-and-concisely)*

### Title Pattern

**Format**: `[Action verb] + [Object] + [Context (optional)]`

| Good ✅ | Bad ❌ |
|---------|--------|
| "Fix login timeout in mobile app" | "Login bug" |
| "Add dark mode toggle to settings page" | "Dark mode" |
| "Remove deprecated API endpoint /v1/users" | "API cleanup" |
| "Reduce API latency by 50% for search endpoint" | "Performance improvement" |

### Description Principles

1. **Problem statement** (1-2 sentences) — What's wrong or what's needed?
2. **Expected vs actual behavior** (for bugs) — What should happen vs what does happen?
3. **Reproduction steps** (for bugs) — How to see the issue?
4. **Acceptance criteria** (measurable) — How do we know it's done?

### Writing Style

**Prefer**:
- Active voice: "System displays error" not "Error is displayed"
- Specific scope: "Reduce latency by 50ms" not "Improve performance"
- Present context: "When user ID is null" not "Sometimes"

**Avoid**:
- Passive voice without actor
- Vague scope that can't be measured
- Missing context that makes reproduction impossible

### Examples

**Good Issue**:
```
## BUG-0042@c2d4e6 — Fix 500 error when user ID is null in profile endpoint

When a request hits `/api/profile` with a null user ID, the server returns 
HTTP 500 instead of HTTP 400 with a validation message.

**Expected**: HTTP 400 with body `{"error": "user_id is required"}`
**Actual**: HTTP 500 with empty body

**Reproduction**: `curl -X GET /api/profile?user_id=`

### Acceptance Criteria
- [ ] Null user_id returns 400, not 500
- [ ] Response body contains clear error message
```

**Bad Issue**:
```
## BUG-0043@d3e4f5 — Profile bug

The profile doesn't work sometimes. Please fix.
```