okstra 0.124.0 → 0.125.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/architecture/storage-model.md +2 -0
- package/docs/architecture.md +5 -1
- package/docs/cli.md +1 -1
- package/docs/for-ai/skills/okstra-inspect.md +1 -0
- package/docs/for-ai/skills/okstra-pr-gen.md +2 -2
- package/docs/performance-improvement-plan-v2.md +2 -2
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/lib/okstra/usage.sh +1 -1
- package/runtime/prompts/lead/okstra-lead-contract.md +1 -1
- package/runtime/prompts/lead/report-writer.md +16 -13
- package/runtime/prompts/profiles/_implementation-verifier.md +26 -0
- package/runtime/prompts/profiles/implementation-planning.md +4 -4
- package/runtime/prompts/profiles/implementation.md +1 -0
- package/runtime/prompts/profiles/requirements-discovery.md +1 -2
- package/runtime/python/okstra_ctl/models.py +4 -2
- package/runtime/python/okstra_ctl/run.py +8 -2
- package/runtime/python/okstra_ctl/stage_fix_carry.py +112 -0
- package/runtime/schemas/final-report-v1.0.schema.json +6 -6
- package/runtime/skills/okstra-inspect/SKILL.md +23 -737
- package/runtime/skills/okstra-inspect/facets/cost.md +84 -0
- package/runtime/skills/okstra-inspect/facets/error-zip.md +41 -0
- package/runtime/skills/okstra-inspect/facets/errors.md +69 -0
- package/runtime/skills/okstra-inspect/facets/history.md +90 -0
- package/runtime/skills/okstra-inspect/facets/logs.md +89 -0
- package/runtime/skills/okstra-inspect/facets/recap.md +96 -0
- package/runtime/skills/okstra-inspect/facets/report.md +61 -0
- package/runtime/skills/okstra-inspect/facets/status.md +145 -0
- package/runtime/skills/okstra-inspect/facets/time.md +56 -0
- package/runtime/skills/okstra-pr-gen/SKILL.md +3 -3
- package/runtime/templates/project-docs/task-index.template.md +1 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# okstra-inspect facet — status
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## status
|
|
6
|
+
|
|
7
|
+
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".
|
|
8
|
+
|
|
9
|
+
### status.1 — Overall project status
|
|
10
|
+
|
|
11
|
+
Read `.okstra/discovery/task-catalog.json`. The catalog is the authoritative source — every field listed below (including `workStatus`, `workStatusUpdatedAt`, `workStatusNote`) is projected directly from each `task-manifest.json` by `scripts/okstra_ctl/render.py :: render_task_catalog_discovery`. Do NOT re-open individual manifests for the overview.
|
|
12
|
+
|
|
13
|
+
| Field | Description |
|
|
14
|
+
|------|------|
|
|
15
|
+
| `taskKey` | `<project-id>:<task-group>:<task-id>` |
|
|
16
|
+
| `taskType` | latest task type |
|
|
17
|
+
| `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. |
|
|
18
|
+
| `currentStatus` | task-level status |
|
|
19
|
+
| `currentPhase` | lifecycle current phase |
|
|
20
|
+
| `currentPhaseState` | lifecycle phase state |
|
|
21
|
+
| `nextRecommendedPhase` | next recommended phase |
|
|
22
|
+
| `routingStatus` | routing decision status |
|
|
23
|
+
| `awaitingApproval` | whether awaiting approval |
|
|
24
|
+
| `latestRunStatus` | latest run status |
|
|
25
|
+
| `latestReportPath` | latest report path |
|
|
26
|
+
| `latestResumeCommandPath` | latest resume command |
|
|
27
|
+
| `workStatus` | user-managed work status (todo / in-progress / blocked / done; default in-progress) |
|
|
28
|
+
| `updatedAt` | last update time |
|
|
29
|
+
|
|
30
|
+
Sort by `updatedAt` desc, then `taskKey`.
|
|
31
|
+
|
|
32
|
+
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, routing, 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`.
|
|
33
|
+
|
|
34
|
+
If `awaitingApproval` is true OR `routingStatus == "pending"`, append a `*` to the `Next` cell and explain the marker once below the table.
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
## okstra Status — <project-id>
|
|
38
|
+
|
|
39
|
+
| # | Task Key | Category | Phase | workStatus | Next |
|
|
40
|
+
|---|----------|----------|-------|------------|------|
|
|
41
|
+
| 1 | proj:group:id | bugfix | error-analysis | in-progress | implementation-planning |
|
|
42
|
+
| 2 | proj:group:id2 | feature | requirements-discovery | done | pending-routing-decision* |
|
|
43
|
+
|
|
44
|
+
`*` = awaiting user approval or pending routing decision. Run `/okstra-inspect status <task-key>` for details.
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### status.2 — Specific task status
|
|
48
|
+
|
|
49
|
+
Given a specific `task-key` or `task-group + task-id`:
|
|
50
|
+
|
|
51
|
+
1. If possible, quickly look it up in `task-catalog.json`.
|
|
52
|
+
2. If necessary, read `.okstra/tasks/<task-group>/<task-id>/task-manifest.json` directly.
|
|
53
|
+
3. If you need the latest run information, read `history/timeline.json` along with the latest run manifest.
|
|
54
|
+
|
|
55
|
+
Required fields: `taskKey`, `taskType`, `workCategory`, `currentStatus`, `latestRunStatus`, `workflow.{currentPhase, currentPhaseState, phaseStates, lastCompletedPhase, nextRecommendedPhase, awaitingApproval, routingStatus, lastSafeCheckpoint}`, `workStatus`, `workStatusUpdatedAt`, `workStatusNote`, `latestReportPath`, `latestResumeCommandPath`, `historyTimelinePath`.
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
## okstra Task Status — <task-key>
|
|
59
|
+
|
|
60
|
+
- Work category: `<category>`
|
|
61
|
+
- Current phase: `<phase>`
|
|
62
|
+
- Current phase state: `<phase-state>`
|
|
63
|
+
- Last completed phase: `<phase-or-->`
|
|
64
|
+
- Next recommended phase: `<phase>`
|
|
65
|
+
- Awaiting approval: `<yes|no>`
|
|
66
|
+
- Routing status: `<routing-status>`
|
|
67
|
+
- Task status: `<task-status>`
|
|
68
|
+
- Latest run status: `<run-status>`
|
|
69
|
+
- Latest report: `<relative-path-or-->`
|
|
70
|
+
- Resume command: `<relative-path-or-->`
|
|
71
|
+
- workStatus: `<todo|in-progress|blocked|done>` (updated `<workStatusUpdatedAt-or-->`)
|
|
72
|
+
- workStatus note: `<workStatusNote-or-->`
|
|
73
|
+
|
|
74
|
+
### Phase States
|
|
75
|
+
|
|
76
|
+
- `requirements-discovery`: `<state>`
|
|
77
|
+
- `error-analysis`: `<state>`
|
|
78
|
+
- `implementation-planning`: `<state>`
|
|
79
|
+
- `implementation`: `<state>`
|
|
80
|
+
- `final-verification`: `<state>`
|
|
81
|
+
- `release-handoff`: `<state>`
|
|
82
|
+
|
|
83
|
+
### Safe Resume Checkpoint
|
|
84
|
+
|
|
85
|
+
- Label: `<checkpoint-label>`
|
|
86
|
+
- Run manifest: `<relative-path-or-->`
|
|
87
|
+
- Team state: `<relative-path-or-->`
|
|
88
|
+
- Report: `<relative-path-or-->`
|
|
89
|
+
- Resume command: `<relative-path-or-->`
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### status.3 — Resume / next-step guidance
|
|
93
|
+
|
|
94
|
+
The status response always includes one of:
|
|
95
|
+
|
|
96
|
+
1. **Resume current run** — if `latestResumeCommandPath` exists, display that path.
|
|
97
|
+
2. **Restart current phase** — task can be re-run with the same `task-key` and current `taskType`.
|
|
98
|
+
3. **Start next phase** — if `workflow.nextRecommendedPhase` is one of `error-analysis`, `implementation-planning`, `implementation`, `final-verification`, `release-handoff`, that phase is proposed. If `nextRecommendedPhase` is `pending-release-handoff`, surface as verdict-gated and propose `release-handoff` only when the cited verdict is `accepted`.
|
|
99
|
+
4. **Need more information** — if `nextRecommendedPhase` is `pending-routing-decision` or `routingStatus` is `pending`.
|
|
100
|
+
5. **Task complete (terminal)** — if `nextRecommendedPhase` is `done-or-follow-up`, the task lifecycle has reached its terminal signal. 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.
|
|
101
|
+
|
|
102
|
+
### status.4 — Update workStatus (write)
|
|
103
|
+
|
|
104
|
+
Recognize requests to change a task's `workStatus` and update the corresponding `task-manifest.json`.
|
|
105
|
+
|
|
106
|
+
**Trigger patterns** (recognize both):
|
|
107
|
+
|
|
108
|
+
Natural language: "change DEV-6827 to done", "mark PROD-1623 as blocked", "set DEV-9047 in progress", "Mark DEV-6827 as done".
|
|
109
|
+
|
|
110
|
+
Explicit phrasing (recognized user utterances — normalize each to a `okstra set-work-status` call below):
|
|
111
|
+
- `okstra status set <task-id> <status>`
|
|
112
|
+
- `okstra status set <task-group> <task-id> <status>` (disambiguation)
|
|
113
|
+
- `okstra mark <task-id> <status>`
|
|
114
|
+
- `okstra status set <task-id> <status> --note "<note>"`
|
|
115
|
+
|
|
116
|
+
Accepted `<status>` values: `todo`, `in-progress`, `blocked`, `done`.
|
|
117
|
+
|
|
118
|
+
**Procedure:** run the update through the CLI (one Bash call, literal `okstra` token) — never edit `task-manifest.json` by hand:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
okstra set-work-status <token> <status> --project-root <projectRoot> --json
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- `<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).
|
|
125
|
+
- Branch on the stdout JSON: `ok: true` → confirm below. `stage: "ambiguous"` → list `matches[]` (with `_matchedVia`) 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.
|
|
126
|
+
|
|
127
|
+
Confirm in Korean (the block below shows the message shape only — render the actual confirmation text in Korean):
|
|
128
|
+
```
|
|
129
|
+
✓ <TASK-ID> workStatus: <previousWorkStatus> → <workStatus>
|
|
130
|
+
✓ task-manifest.json updated
|
|
131
|
+
```
|
|
132
|
+
`<previousWorkStatus>` = `(none)` when the JSON's `previousWorkStatus` is empty.
|
|
133
|
+
|
|
134
|
+
**Default value convention:** if `workStatus` is missing or empty, infer the display value from lifecycle state (DO NOT default to a static `in-progress`):
|
|
135
|
+
|
|
136
|
+
| Manifest state | Inferred display |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `currentStatus == "completed"` AND `workflow.nextRecommendedPhase == "done-or-follow-up"` | `done` (inferred) |
|
|
139
|
+
| `currentStatus == "completed"` AND `workflow.currentPhaseState == "completed"` | `phase-done` (inferred) |
|
|
140
|
+
| `currentStatus == "contract-violated"` OR `workflow.currentPhaseState == "blocked"` | `blocked` (inferred) |
|
|
141
|
+
| anything else | `in-progress` (default) |
|
|
142
|
+
|
|
143
|
+
Annotate inferred values with `(inferred)` or `(default)`. Do not back-fill on read; only write when the user explicitly issues an update.
|
|
144
|
+
|
|
145
|
+
**Catalog sync note:** the CLI updates `task-manifest.json` only. `discovery/task-catalog.json` may be stale until the next run regenerates it; downstream consumers (e.g. `okstra-schedule-gen`) re-read each manifest directly.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# okstra-inspect facet — time
|
|
2
|
+
|
|
3
|
+
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.
|
|
4
|
+
|
|
5
|
+
## time
|
|
6
|
+
|
|
7
|
+
Trigger phrases: "work time", "elapsed time", "time summary", "duration", "elapsed", "how long did it take", "time analysis".
|
|
8
|
+
|
|
9
|
+
Aggregate elapsed work time for a task, grouped by **task type** and broken down by **worker** (lead + each worker). The `time-report` CLI reads both data sources (`history/timeline.json` runs + each run's `team-state-*.json` usage blocks) and does **all** aggregation — cross-run sums, CPU-sum vs wall-clock, timestamp parsing, unavailable detection. You only resolve the task-key, call it, and render. **Never recompute durations by hand.**
|
|
10
|
+
|
|
11
|
+
### time.1 — Resolve the task-key
|
|
12
|
+
|
|
13
|
+
Apply the standard task-key resolution rule from `SKILL.md` (core): full task-key → use directly; bare token → the resolver CLI and the 0/1/N branch. If no okstra history exists, say `No okstra history found. Run /okstra-run first.`
|
|
14
|
+
|
|
15
|
+
### time.2 — Fetch aggregated data
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
okstra time-report <task-key> --project-root <projectRoot> --json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Returns (all durations are **raw milliseconds**):
|
|
22
|
+
- `byTaskType[]` — `{taskType, runs, leadMs, workersMs, cpuSumMs}`, plus `grandTotal`
|
|
23
|
+
- `perWorker` — `{<taskType>: [{workerId, agents[], runs, totalMs, avgMs}]}`; only workers with a nonzero run appear, and `agents[]` lists agent labels that differ from `workerId`
|
|
24
|
+
- `perRunWallClock[]` — `{runTimestamp, taskType, wallClockMs}` (max `endedAt` − min `startedAt` per run)
|
|
25
|
+
- `phaseTimelines[]` — `{runTimestamp, taskType, phases:[{phase, firstAt, wallMsToNext}]}`
|
|
26
|
+
- `unavailable[]` — `{runTimestamp, taskType, reason}` for runs with no Phase-7 durations (never summed into totals)
|
|
27
|
+
|
|
28
|
+
### time.3 — Render
|
|
29
|
+
|
|
30
|
+
Convert every `*Ms` to `HH:MM:SS` (zero-pad; never show raw ms). Task types in `byTaskType` are already in chronological (first-appearance) order.
|
|
31
|
+
|
|
32
|
+
- **By task type** — `| Task type | Runs | CPU sum | Lead | Workers |` from `byTaskType`, plus a `grandTotal` row. `CPU sum` (= Lead + Workers) overlaps because workers run inside the lead's window — it is *not* wall-clock. Surface wall-clock only when the user explicitly asks, from `perRunWallClock`.
|
|
33
|
+
- **Per worker** (per task type) — `| Worker | Runs | Total | Avg/run |` from `perWorker`. Render the worker as bare `workerId` when `agents` is empty, else `workerId (agent1, agent2)`.
|
|
34
|
+
- **Phase breakdown** — "by stage"/"per stage"/"which stage took longest" in okstra most often means the **lifecycle stage (task-type)** view, which the *By task type* table above already answers — lead with that table, do not treat the request as unanswerable. Render the intra-run phase timeline only when the user clearly means within-a-run phases ("which phase", "Phase 1~7", "phase timeline"): one table per run from `phaseTimelines`: `| Phase | Start | Wall to next |` using `firstAt`/`wallMsToNext` (`null` → `--`). When `phaseTimelines` is empty, do **not** headline "not measurable" — the By-task-type table is the stage answer; mention the missing intra-run markers only as a trailing footnote.
|
|
35
|
+
- If `unavailable[]` is non-empty, append a trailing note listing each run with its reason. Never fold them into totals.
|
|
36
|
+
- Show the resolved `<task-key>` in the heading.
|
|
37
|
+
|
|
38
|
+
```markdown
|
|
39
|
+
## Time summary — <task-key>
|
|
40
|
+
|
|
41
|
+
### By task type
|
|
42
|
+
|
|
43
|
+
| Task type | Runs | CPU sum | Lead | Workers |
|
|
44
|
+
|------------------------|------|-----------|----------|----------|
|
|
45
|
+
| requirements-discovery | 2 | 00:33:12 | 00:12:08 | 00:21:04 |
|
|
46
|
+
| **Grand total** | 6 | **03:03:06** | 01:05:49 | 01:57:17 |
|
|
47
|
+
|
|
48
|
+
### Per worker — requirements-discovery
|
|
49
|
+
|
|
50
|
+
| Worker | Runs | Total | Avg/run |
|
|
51
|
+
|----------------------|------|----------|----------|
|
|
52
|
+
| lead | 2 | 00:12:08 | 00:06:04 |
|
|
53
|
+
| claude (sonnet-eval) | 2 | 00:09:12 | 00:04:36 |
|
|
54
|
+
|
|
55
|
+
> Unavailable: 1 run (implementation / 2026-04-30_03-03-48) — Phase 7 not reached
|
|
56
|
+
```
|
|
@@ -33,7 +33,7 @@ Present a 3-option picker (`AskUserQuestion`):
|
|
|
33
33
|
|
|
34
34
|
1. `Generate PR` — generate a PR body from a branch diff.
|
|
35
35
|
2. `Register template` — save a new PR body template.
|
|
36
|
-
3. `Enter
|
|
36
|
+
3. `Enter directly` — always the last option (okstra picker convention).
|
|
37
37
|
|
|
38
38
|
## Mode A — Generate PR
|
|
39
39
|
|
|
@@ -44,7 +44,7 @@ okstra pr template list --json
|
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
- If `templates` is non-empty, present a picker: 1–2 recommended templates from
|
|
47
|
-
the list, plus `Default template` (the bundled default), plus `Enter
|
|
47
|
+
the list, plus `Default template` (the bundled default), plus `Enter directly`
|
|
48
48
|
last.
|
|
49
49
|
- If empty, tell the user the bundled default template will be used.
|
|
50
50
|
|
|
@@ -56,7 +56,7 @@ Carry the chosen template name as `<template>` (`default` for the bundled one).
|
|
|
56
56
|
okstra pr branches --json
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
-
Present a 3-option base picker from `recommended` (top entries) plus `Enter
|
|
59
|
+
Present a 3-option base picker from `recommended` (top entries) plus `Enter directly`
|
|
60
60
|
last. Carry the choice as `<base>`.
|
|
61
61
|
|
|
62
62
|
### A3. Build the generation bundle and fill the template
|