# okstra-inspect facet — status

Loaded lazily by the dispatch table in `SKILL.md` (core). Shared rules — Step 0 preflight, the standard task-key resolution rule (0/1/N), the no-task fallback, and Output Rules — live in the core file and still apply here.

## status

Trigger phrases: "okstra status", "task status", "current phase", "next phase", "what is pending", "resume point", "okstra status set", "okstra mark", "<task-id> done", "<task-id> in-progress", "<task-id> in progress", "<task-id> complete".

### status.1 — Overall project status

Run `okstra model-io status-input --project-root <projectRoot>`. Use the fixed
text task blocks as the overview source.

| Field | Description |
|------|------|
| `taskKey` | `<project-id>:<task-group>:<task-id>` |
| `taskType` | latest task type |
| `workCategory` | bugfix / feature / improvement / refactor / ops / unknown. Display `unknown` as-is, but flag with `(unset)` annotation so the reader knows the requirements-discovery classification was skipped or no `--work-category` flag was passed. |
| `currentStatus` | task-level status |
| `currentPhase` | lifecycle current phase |
| `currentPhaseState` | lifecycle phase state |
| `nextRecommendedPhase` | next-phase pointer — an **object** `{phase, status, rationale}`, never a string. `status` is `ready` / `pending` / `blocked` / `terminal`. The lead writes `phase` only under `ready`, but that is an authoring rule, not a constraint the struct enforces — `prepare` lowers a `ready` pointer to `pending` and keeps its `phase`, so a non-`ready` pointer that still names a phase is a normal state to read. Decide launchability from `status` alone. Render `phase` (or `--` when it is empty) — never the object itself. |
| `awaitingApproval` | whether awaiting approval |
| `latestRunStatus` | latest run status |
| `latestReportRecordPath` | latest report path |
| `latestResumeCommandPath` | latest resume command |
| `workStatus` | user-managed work status (todo / in-progress / blocked / done; default in-progress) |
| `updatedAt` | last update time |

Sort by `updatedAt` desc, then `taskKey`.

The overview table is intentionally narrow so it renders cleanly in a terminal. Only six columns are shown; for any task that needs a closer look (phase state, the pointer's status and rationale, approval gate, last run status, resume path, etc.) tell the user to run `/okstra-inspect status <task-key>` for the detail view in `status.2`.

The `Next` cell is `nextRecommendedPhase.phase`, or `--` when that string is empty. If `awaitingApproval` is true OR `nextRecommendedPhase.status` is anything other than `ready`, append a `*` to the cell and explain the marker once below the table — an unset or non-`ready` pointer means no next run is launchable yet.

```markdown
## okstra Status — <project-id>

| # | Task Key | Category | Phase | workStatus | Next |
|---|----------|----------|-------|------------|------|
| 1 | proj:group:id | bugfix | error-analysis | in-progress | implementation-planning |
| 2 | proj:group:id2 | feature | requirements-discovery | done | --* |

`*` = awaiting user approval, or the next-phase pointer is not `ready`. Run `/okstra-inspect status <task-key>` for details.
```

### status.2 — Specific task status

Given a specific `task-key` or `task-group + task-id`:

1. Run `okstra model-io status-input --project-root <projectRoot> --task-ref <task-key>`.
2. Use only the named lines in that fixed text projection.

Required fields: `taskKey`, `taskType`, `workCategory`, `currentStatus`, `latestRunStatus`, `workflow.{currentPhase, currentPhaseState, phaseStates, lastCompletedPhase, nextRecommendedPhase, awaitingApproval, lastSafeCheckpoint}`, `workStatus`, `workStatusUpdatedAt`, `workStatusNote`, `latestReportRecordPath`, `latestResumeCommandPath`, `historyTimelinePath`.

The projection renders next phase, status, and rationale as separate lines.
It has already promoted legacy values.

```markdown
## okstra Task Status — <task-key>

- Work category: `<category>`
- Current phase: `<phase>`
- Current phase state: `<phase-state>`
- Last completed phase: `<phase-or-->`
- Next phase pointer: `<phase-or-->` (`<status>`) — `<rationale-or-->`
- Awaiting approval: `<yes|no>`
- Task status: `<task-status>`
- Latest run status: `<run-status>`
- Latest report: `<relative-path-or-->`
- Resume command: `<relative-path-or-->`
- workStatus: `<todo|in-progress|blocked|done>` (updated `<workStatusUpdatedAt-or-->`)
- workStatus note: `<workStatusNote-or-->`

### Phase States

- `requirements-discovery`: `<state>`
- `error-analysis`: `<state>`
- `implementation-planning`: `<state>`
- `implementation`: `<state>`
- `final-verification`: `<state>`
- `release-handoff`: `<state>`

### Safe Resume Checkpoint

- Label: `<checkpoint-label>`
- Run manifest: `<relative-path-or-->`
- Team state: `<relative-path-or-->`
- Report: `<relative-path-or-->`
- Resume command: `<relative-path-or-->`
```

### status.3 — Resume / next-step guidance

The status response always includes one of:

1. **Resume current run** — if `latestResumeCommandPath` exists, display that path.
2. **Ask the user to approve** — if `workflow.awaitingApproval` is true. Tell the user to approve the plan (`okstra-run` with `--task-type implementation`, which asks `approve_plan_confirm`, or `--approve`). Quote `nextRecommendedPhase.rationale`. A `ready` pointer to `implementation` here means implementation is next after approval, not that it may launch as if already approved. Do not re-run `implementation-planning`.
3. **Restart current phase** — only when `awaitingApproval` is false and the pointer is not `ready`. The task can be re-run with the same `task-key` and current `taskType`.
Branches 4–6 are decided by `workflow.nextRecommendedPhase.status` when `awaitingApproval` is false — one status, one branch:

4. **Start next phase** — `status` is `ready` and `awaitingApproval` is false. Propose `nextRecommendedPhase.phase` as the next run's `--task-type` and quote its `rationale` as the reason. This is the only status under which a named phase may be launched without a prior approval ask, so it is the only branch that proposes a run. A `ready` pointer to `release-handoff` already implies an `accepted` final-verification verdict (the report validator refuses that routing target otherwise), so do not re-gate it here.
5. **Need more information** — `status` is `pending` (the last run did not settle where this task goes next) or `blocked` (it did settle, and the answer is that something outside the run has to change first). Neither proposes a run, and a leftover `phase` name does not change that — `prepare` keeps the name when it lowers a pointer to `pending`, so read `status`, not the emptiness of `phase`. Show the `rationale`, and for `blocked` state what it names as the obstacle. After `implementation-planning`, the first action is `okstra-user-response` on the named `C-NNN` ids; do not re-run planning until those answers exist, and do not start implementation.
6. **Task complete (terminal)** — `status` is `terminal`: the task lifecycle ends here. This is **not** a "next phase" — do not propose a new okstra run. Surface the latest report and ask the user whether any follow-up task should be opened separately.

### status.4 — Update workStatus (write)

Recognize requests to change a task's `workStatus` and update the corresponding `task-manifest.json`.

**Trigger patterns** (recognize both):

Natural language: "change DEV-6827 to done", "mark PROD-1623 as blocked", "set DEV-9047 in progress", "Mark DEV-6827 as done".

Explicit phrasing (recognized user utterances — normalize each to a `okstra set-work-status` call below):
- `okstra status set <task-id> <status>`
- `okstra status set <task-group> <task-id> <status>` (disambiguation)
- `okstra mark <task-id> <status>`
- `okstra status set <task-id> <status> --note "<note>"`

Accepted `<status>` values: `todo`, `in-progress`, `blocked`, `done`.

**Procedure:** run the update through the CLI (one Bash call, literal `okstra` token) — never edit `task-manifest.json` by hand:

```bash
okstra set-work-status <token> <status> --project-root <projectRoot> --text
```

- `<token>` is a full task-key or a bare task-id. Add `--task-group <group>` to scope a duplicated id, `--note "<note>"` to set `workStatusNote` (flag omitted → any existing note is left untouched).
- Branch on the fixed text labels: `OK: True` → confirm below. `Stage: ambiguous` → list each `Match` via a 3-option picker and retry with the chosen full task-key. `Stage: not-found` → `<TASK-ID> cannot be found.` An invalid `<status>` makes the CLI exit 2 with the allowed-values list — surface it verbatim; nothing was modified.

Confirm in Korean (the block below shows the message shape only — render the actual confirmation text in Korean):
```
✓ <TASK-ID> workStatus: <previousWorkStatus> → <workStatus>
✓ task-manifest.json updated
```
`<previousWorkStatus>` = `(none)` when the JSON's `previousWorkStatus` is empty.

**Default value convention:** if `workStatus` is missing or empty, infer the display value from lifecycle state (DO NOT default to a static `in-progress`):

| Manifest state | Inferred display |
|---|---|
| `currentStatus == "completed"` AND `workflow.nextRecommendedPhase.status == "terminal"` | `done` (inferred) |
| `currentStatus == "completed"` AND `workflow.currentPhaseState == "completed"` | `phase-done` (inferred) |
| `currentStatus == "contract-violated"` OR `workflow.currentPhaseState == "blocked"` | `blocked` (inferred) |
| anything else | `in-progress` (default) |

Annotate inferred values with `(inferred)` or `(default)`. Do not back-fill on read; only write when the user explicitly issues an update.

The projection commands own catalog/manifest reconciliation; do not repair their storage while inspecting status.
