# okstra-rollup AI Manual

## Source

- Skill source: [`skills/okstra-rollup/SKILL.md`](../../../skills/okstra-rollup/SKILL.md)
- aggregation core (CLI): [`scripts/okstra_ctl/rollup.py`](../../../scripts/okstra_ctl/rollup.py)
- Node wrapper: [`src/commands/inspect/rollup.mjs`](../../../src/commands/inspect/rollup.mjs)
- reused single-task aggregators: [`scripts/okstra_ctl/time_report.py`](../../../scripts/okstra_ctl/time_report.py), [`scripts/okstra_ctl/error_log_core.py`](../../../scripts/okstra_ctl/error_log_core.py)
- catalog enumeration helper: [`scripts/okstra_project/state.py`](../../../scripts/okstra_project/state.py) (`list_project_tasks`)
- unit tests: [`tests/inspect/test_okstra_rollup.py`](../../../tests/inspect/test_okstra_rollup.py)

## Purpose

`okstra-rollup` **collects and summarizes the run results of multiple tasks at once**. It is a cross-task read-side layer, in contrast to `okstra-inspect` which looks at a single task.

- Input scope: one task-group, or the whole-project catalog when `--task-group` is omitted.
- Deterministic aggregation (counts, time sums, error sums, status/category/phase distributions) is handled entirely by the `okstra rollup` CLI. The skill renders that table and reads each task's report body to write a **cross-task synthesis (digest)**.
- Design principle: hand-computed aggregation is error-prone for an LLM, so it is pushed to the CLI (SSOT), and only the natural-language synthesis is left to the LLM. This is the same division of labor as `okstra-inspect time`, which insists on "never re-sum the time by hand".

This skill is read-only. It does not mutate task artifacts.

## When to use

Use it when:

- The user asks for "rollup", "task-group summary", "group-level report", "collect multiple task results", "whole-project task status summary", "run results all at once".
- You want to look across **multiple tasks** rather than a single one.

Do not use it when:

- A single task's report/time/errors/recap → `okstra-inspect` (report / time / errors / recap facet).
- A forward-looking work plan (a client-facing schedule of non-done tasks) → `okstra-schedule-gen`. rollup is **retrospective**, collecting past run results; schedule is **forward-looking**, planning future work.
- Actual phase execution → `okstra-run`.

## Preflight

A single Bash call starting with the literal `okstra` token (not wrapped in `if`/`eval`/`$(...)`/`VAR=`/`||`/`&&`/`npx` fallback):

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

On `Okstra preflight: ready`, carry `Project root` as a literal string. On
`Okstra preflight: failed`, show `Reason` and `Recovery`, then stop.

## scope resolution

- The user named a task-group ("summarize the alpha group") → `--task-group <group>`.
- "all tasks" / "the whole project" / no scope named → omit `--task-group` (whole catalog).
- If genuinely ambiguous, ask once: one task-group or the whole project? Do not silently guess a specific group.

## CLI call

```bash
okstra rollup --task-group <group> --project-root <projectRoot> --text
```

For the whole project, drop `--task-group`. The output is fixed, ordered label/value rows, and **all times are raw milliseconds**.

## Interpreting the output

Fixed fields:

- `Task group` and `Task count` identify the scope.
- Numbered `Tasks` rows carry task identity, status, phase, next phase, report path, run count, CPU, wall-clock, and error count.
- `Totals runs`, `Totals CPU sum ms`, `Totals wall clock ms`, and `Totals errors` are the aggregate values.
- Numbered `Work status`, `Work category`, `Current phase`, and `Task type` rows carry the aggregate distributions.

Numeric meanings (must observe):

- `Run count` is the **total number of runs** in the timeline. CPU and wall-clock rows reflect only runs that reached Phase 7 usage, so they can be `0` even when run count is positive.
- `CPU sum ms` is the **CPU sum** of the overlapping lead + workers, not wall-clock.
- `Report path` is project-relative and may be `-` for a task with no report yet.
- If `Task count` is `0`, say there are no okstra tasks in that scope and stop.

## Render

Convert every `*Ms` to `HH:MM:SS` (zero-pad; never expose raw ms — the same rule as `okstra-inspect time`). Sort tasks by `updatedAt` descending.

```markdown
## okstra Rollup — <task-group or "whole project"> (<taskCount> tasks)

| Task | Category | workStatus | Phase | Runs | CPU | Errors | Report |
|------|----------|------------|-------|------|-----|--------|--------|
| DEV-1 | bugfix | done | final-verification | 2 | 00:25:00 | 2 | ✓ |
| DEV-2 | feature | in-progress | implementation | 1 | 00:00:00 | 0 | — |

**Totals:** 3 runs · CPU 00:25:00 · 2 errors
**workStatus:** done 1 · in-progress 1   **category:** bugfix 1 · feature 1
```

- `Report` column: `✓` when `reportPath` is present, `—` when not.
- Build the status/category/phase lines from the `totals` tally maps **verbatim**. Do not count the `tasks[]` array yourself (the CLI is the SSOT for aggregation).

## Writing the digest (the summary — the skill's core value)

When the user asks to "summarize"/"organize"/"summarize"/"digest" (the common case):

1. For each task with a non-empty `reportPath` whose `<projectRoot>/<reportPath>` file actually exists, read the report and summarize in 1–2 lines **what it accomplished and its recommended next step**.
2. Above the per-task lines, write a 2–4 sentence group-level synthesis: what was delivered across the group, where the open work sits (using `byWorkStatus`/`byCurrentPhase`), and whether there are error hot-spots (tasks with high `errorCount`).
3. Cite each per-task claim with the report path (`<reportPath>`) so the reader can open it directly.

For a task with no report, do not invent a summary; state the current phase/workStatus instead. Do not read non-report artifacts to fill the gap (artifact-home rule). If a report is empty or missing, say so.

If a deep single-task drill-down (full report, per-worker time, error breakdown, run-to-run recap) is needed, point the user to `/okstra-inspect`.

## Forbidden patterns

- Re-counting aggregate numbers (totals, distributions) by hand from `tasks[]`. `totals` is the SSOT.
- Exposing raw ms. Always `HH:MM:SS`.
- Labeling `cpuSumMs` as if it were wall-clock.
- Inventing a summary for a task with no report. Substitute the current phase/workStatus.
- Reading files outside okstra artifacts (non-`.okstra`) to fill the summary.
- Handling single-task detail in rollup. Send it to `okstra-inspect`.
