# okstra-inspect AI Manual

## Source

- Skill source: [`skills/okstra-inspect/SKILL.md`](../../../skills/okstra-inspect/SKILL.md)
- Facet bodies: `skills/okstra-inspect/facets/<sub-command>.md` — the skill is a thin core (preflight + dispatch + shared rules); each sub-command's full procedure is a lazily loaded facet file, guarded by `tests/contract/test_okstra_inspect_facets.py`
- CLI registry: [`src/cli-registry.mjs`](../../../src/cli-registry.mjs)
- context-cost CLI: `src/commands/inspect/context-cost.mjs`
- time-report CLI: `src/commands/inspect/time-report.mjs`
- log-report CLI: `src/commands/inspect/log-report.mjs`
- error-report CLI: `src/commands/inspect/error-report.mjs`
- container is a separate skill: [`okstra-container-build.md`](okstra-container-build.md)

## Purpose

`okstra-inspect` is the single entry point for okstra read-side work. Most of it is read-only, with two exceptions.

- `status.4`: writes the user-requested `workStatus` into `task-manifest.json`.
- `errors`, `error-zip`, `recap record`: produce report/zip/log artifacts from the information read.

No sub-command writes outside this machine.

## sub-command list

| Sub-command | Role | Writes? |
|---|---|---|
| `status` | check task/phase/workflow status, change workStatus | manifest edit in `status.4` |
| `history` | list past runs, assemble rerun/resume command | read by default |
| `report` | resolve final-report path and optionally read | read |
| `time` | aggregate elapsed time per task type/worker | read |
| `logs` | inventory wrapper `.log` sidecars and suggest cleanup commands | read |
| `cost` | estimate task bundle context/read cost | read |
| `errors` | aggregate task error logs into a timestamped markdown report | generates report |
| `error-zip` | build an anonymized zip of cross-project error logs | generates zip |
| `run-audit` | check every run's artifacts against progress invariants — catches a run that ended wrong without ever logging a failure | read |
| `recap` | summarize a task's before/after runs and record Q&A | appends `recap-log.jsonl` |

## Preflight

Run once before any sub-command.

```bash
okstra preflight --runtime claude-code
```

The project check only sees the cwd of the Bash call. For a project that is not the cwd (a sibling repo, a monorepo subdir, or a project named in the request), `Okstra preflight: failed` can be a false negative rather than missing setup. Retry with `okstra preflight --runtime claude-code --cwd <that-dir>` (`--cwd` is the sanctioned way to target a project without a leading `cd`). Only when that also reports `Okstra preflight: failed` do you show `Reason` and `Recovery`, then stop. On `Okstra preflight: ready`, carry `Project root` as a literal value and pass it to the sub-command CLIs that accept it (`recap`, `context-cost`, etc.) via `--cwd`/`--project-root <projectRoot>`.

## intent routing

Classify the user request into one or more facets. If ambiguous, show the entire sub-command table and let the user pick by number/name. Do not hide a facet because of AskUserQuestion's option limit.

If several facets appear in one message, execute them sequentially. Step 0 runs only once.

## task-key resolution — shared rule

Many facets accept the following target forms.

1. full task-key: `<project-id>:<task-group>:<task-id>`
2. bare task-id
3. task root path

A bare task-id uses the shared resolver.

```bash
okstra model-io task-selection-input --project-root <projectRoot> --task-ref <task-id>
```

Handling the fixed text projection's `Match count` and repeated task lines:

- 0: say it cannot be found; do not guess.
- 1: use that `taskKey`.
- N: show the candidate `taskKey`s and `updatedAt`, and take a disambiguation.

## status

### Project overview

Run `okstra model-io status-input --project-root <projectRoot>`. Its fixed text task blocks are the projected source.

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

Keep the table narrow.

- Task Key
- Category
- Phase
- workStatus
- Next

`nextRecommendedPhase` is an object `{phase, status, rationale}`. The Next cell is its `phase`, or `--` when that is empty. If `awaitingApproval`, or `nextRecommendedPhase.status` is anything but `ready`, add a marker to the Next cell and explain it. When `awaitingApproval` is true, the next human action is to approve the plan (`okstra-run` → `implementation`, or `--approve`); do not re-run `implementation-planning`. When the pointer is `blocked` after planning, send the user to `okstra-user-response` on the named `C-NNN` ids first.

### Specific task

For a single task's detail, run `okstra model-io status-input --project-root <projectRoot> --task-ref <task-key>` and use its named lines.

Information to show:

- work category
- current phase/state
- last completed phase
- next-phase pointer: `phase` (or `--`), its `status`, its `rationale`
- awaiting approval
- task status, latest run status
- latest report, resume command
- workStatus, note
- phase states
- safe resume checkpoint

### workStatus update

Write only when the user explicitly requests a status change.

Allowed values:

- `todo`
- `in-progress`
- `blocked`
- `done`

Procedure: update via a single `okstra set-work-status <token> <status> [--note <text>] --project-root <projectRoot> --text` call — do not edit the manifest by hand. On `Stage: ambiguous`, re-ask with the listed `Match` values; on `Stage: not-found`, answer that it cannot be found.

When `workStatus` is absent in a read display, infer it from the lifecycle state, but do not back-fill on read alone.

## history

First branch: distinguish re-run from resume.

- Re-run: create a new run from previous run parameters. A new run-seq is created.
- Resume: continue an interrupted existing run. No new run-seq is created.

Run `okstra model-io history-input --project-root <projectRoot>` for project history, or add `--task-ref <task-key>` for one task.

Re-run obtains `projectId`, `taskGroup`, `taskId`, `taskType`, `taskBriefPath`, workers, related tasks, model overrides, and executor provider through `okstra model-io rerun-input --run-manifest <runManifestPath>`. Omit `implementation`'s `--base-ref` to reuse a registration; if launch reports that a base is required, ask the user.

Resume checks `latestResumeCommandPath` or the timeline entry's `resumeCommandPath`, and if the file exists, guides/runs `bash <resume-command-path>`. If the path is empty or the file is missing, declare "no resume" and guide to history.3 (re-run).

## report

Run `okstra model-io report-input --project-root <projectRoot> --task-ref <task-key>` for the latest report. For a specific run, use the `Report` line from `okstra model-io history-input --project-root <projectRoot> --task-ref <task-key>`. Render a full reading copy on demand with `okstra render-final-report <that data.json>`.

Match read depth to the request (a final report is 300+ lines / 50K+ tokens). For summary/conclusion/pass questions ("summary", "just the key points", "conclusion", "did it pass?"), do not read the whole thing — read only the verdict in the `runs/<task-type-segment>/status/final-<task-type-segment>-<NNN>.status` (stage-isolated: `runs/<task-type-segment>/stage-<N>/status/`) sidecar plus the report's leading summary block. Ingest the whole file only for "the whole thing / read it all / full body". If a completion signal exists but the file does not, report it as a missing report; if it is not yet complete, show the current status and workStatus.

## time

The CLI does the time computation. The AI does not recompute duration by hand.

```bash
okstra time-report <task-key> --project-root <projectRoot> --text
```

Convert every `*Ms` to `HH:MM:SS` for display. `CPU sum` is the overlapping cost of lead and workers time combined, not wall-clock. Show wall-clock from `perRunWallClock` only when the user explicitly asks. For `by stage`/`per stage`/`which stage took longest`, the task-type view (the By task type table) is the default answer — do not treat it as 'not measurable'. Render the intra-run `phaseTimelines` only on an explicit request like 'Phase 1–7' / 'which phase', and when it is empty, mention it only as a footnote rather than a headline.

`unavailable[]` is not summed into totals; show it as a separate note.

## cost

For context/read cost, the CLI output is the source of truth.

```bash
okstra context-cost <task-key> --project-root <projectRoot>
```

Interpretation points:

- the token estimate is a heuristic, not a billing figure.
- if `leadPhase1.mode == "active-run-context"`, the compact lead intake is primary.
- if `analysisWorker.mode == "analysis-packet-primary"`, the worker reads the analysis-packet first and opens the full source only when needed.
- if `skillAssets` is large, it is a prompt-diet target.
- if there are many legacy timestamp artifacts, propose current-view/cold-artifact separation rather than a destructive delete.

## logs

wrapper sidecar log inventory:

```bash
okstra log-report --project-root <projectRoot> --text
```

Scans `.okstra/tasks/**/runs/*/prompts/*.log`. Does not delete. The cleanup command merely presents a dry-run and `-delete` pair as fenced bash.

Deleting an active run's log loses the live trace, so recommend checking `status` first.

## errors

Aggregate task error logs into a markdown report.

```bash
okstra error-report <task-key> --project-root <projectRoot> --text
```

Read the fixed `Report path`, total, phase, agent, and parse-skipped labels and summarize. If the report path is `-` and total errors is 0, say there are no recorded error logs. Do not hide a nonzero parse-skipped count.

## error-zip

Bundle the machine's cross-project okstra errors into an anonymized zip.

Run `okstra model-io error-zip-input`. Recommend its `Previous output path` first when present; otherwise propose `~/okstra-error-feedback-<YYYY-MM-DD>.zip`.

Run:

```bash
okstra error-zip --out <path> --text
```

Summary fields:

- `outPath`
- `errorCount`
- `runCount`
- `unreachableRuns`
- `clusterCount`
- `projectCount`

At the end, guide the user to build a brief with the error-feedback variant of `/okstra-brief-gen`, then run `error-analysis` in the okstra repo.

## recap

The default is artifact mode. It builds the before/after summary and answers questions using only `.okstra/` artifacts.

Read the fixed recap projection:

```bash
okstra model-io recap-input --project-root <projectRoot> --task-ref <task-key>
```

Use the emitted `Run count` and repeated `Transition` fields in order. Do not parse recap JSON or open recap state files directly.

record:

```bash
okstra recap record <task-key> --project-root <projectRoot> --kind <summary|qa> --mode <artifact|code> --question "<question>" --answer "<summary>" --citation "<path:line>"
```

Enter code mode only when the user explicitly requests it, such as "including the diff" or "the code changes too". Entering recap alone does not read the code diff.

## Output rules

- Answer in Korean, spelling out task ids, phase names, and status values on first mention.
- Prefer project-relative paths.
- Show disk field values as-is without normalizing.
- Clearly indicate an awaiting-approval state.
- If there is no recent report, show `--`.
- Display dates in `YYYY-MM-DD HH:MM`.

## Forbidden patterns

- Failing immediately because the catalog is absent. There is a manifest fallback.
- Confusing `workStatus` with `currentStatus`.
- Hand-computing time duration without the CLI.
- Running a cleanup command directly.
- Arbitrarily reinterpreting raw files instead of CLI output in `errors`/`cost`/`time`.
- Automatically reading code changes in recap artifact mode.
