okstra 0.36.2 → 0.37.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/README.kr.md +6 -6
- package/README.md +6 -6
- package/bin/okstra +4 -2
- package/docs/kr/architecture.md +29 -29
- package/docs/kr/cli.md +7 -6
- package/docs/pr-template-usage.md +2 -2
- package/docs/project-structure-overview.md +4 -4
- package/docs/superpowers/plans/2026-05-25-okstra-project-root-rename.md +159 -0
- package/docs/superpowers/plans/2026-05-26-wizard-3-option-picker.md +860 -0
- package/docs/task-process/common-flow.md +2 -2
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/SKILL.md +2 -2
- package/runtime/agents/workers/claude-worker.md +1 -1
- package/runtime/prompts/profiles/_common-contract.md +6 -6
- package/runtime/prompts/profiles/_implementation-executor.md +2 -2
- package/runtime/prompts/profiles/_implementation-verifier.md +1 -1
- package/runtime/prompts/profiles/final-verification.md +1 -1
- package/runtime/prompts/profiles/implementation-planning.md +5 -5
- package/runtime/prompts/profiles/release-handoff.md +1 -1
- package/runtime/prompts/profiles/requirements-discovery.md +3 -3
- package/runtime/prompts/wizard/prompts.ko.json +80 -6
- package/runtime/python/lib/okstra/interactive.sh +2 -2
- package/runtime/python/lib/okstra/project-resolver.sh +1 -1
- package/runtime/python/lib/okstra/usage.sh +5 -5
- package/runtime/python/lib/okstra-ctl/cmd-rerun.sh +1 -1
- package/runtime/python/okstra_ctl/backfill.py +5 -3
- package/runtime/python/okstra_ctl/migrate.py +408 -0
- package/runtime/python/okstra_ctl/paths.py +12 -3
- package/runtime/python/okstra_ctl/pr_template.py +4 -2
- package/runtime/python/okstra_ctl/render.py +8 -6
- package/runtime/python/okstra_ctl/run.py +5 -5
- package/runtime/python/okstra_ctl/seeding.py +12 -6
- package/runtime/python/okstra_ctl/sequence.py +3 -1
- package/runtime/python/okstra_ctl/wizard.py +412 -77
- package/runtime/python/okstra_ctl/worktree.py +8 -6
- package/runtime/python/okstra_project/__init__.py +35 -5
- package/runtime/python/okstra_project/dirs.py +67 -0
- package/runtime/python/okstra_project/resolver.py +8 -8
- package/runtime/python/okstra_project/state.py +11 -9
- package/runtime/python/okstra_token_usage/collect.py +3 -1
- package/runtime/skills/okstra-brief/SKILL.md +30 -30
- package/runtime/skills/okstra-context-loader/SKILL.md +7 -7
- package/runtime/skills/okstra-inspect/SKILL.md +25 -25
- package/runtime/skills/okstra-run/templates/pr-body.template.md +1 -1
- package/runtime/skills/okstra-schedule/SKILL.md +7 -7
- package/runtime/skills/okstra-setup/SKILL.md +8 -8
- package/runtime/templates/okstra.CLAUDE.md +4 -4
- package/runtime/templates/reports/brief.template.md +5 -5
- package/runtime/templates/reports/task-brief.template.md +1 -1
- package/runtime/validators/lib/fixtures.sh +2 -2
- package/runtime/validators/lib/paths.sh +9 -3
- package/runtime/validators/validate-brief.py +2 -2
- package/runtime/validators/validate-brief.sh +1 -1
- package/runtime/validators/validate-run.py +3 -1
- package/runtime/validators/validate-workflow.sh +2 -2
- package/src/check-project.mjs +3 -3
- package/src/config.mjs +6 -5
- package/src/install.mjs +5 -5
- package/src/migrate.mjs +163 -0
- package/src/okstra-dirs.mjs +37 -0
- package/src/paths.mjs +17 -0
- package/src/setup.mjs +8 -4
- package/src/uninstall.mjs +3 -3
|
@@ -76,7 +76,7 @@ sequenceDiagram
|
|
|
76
76
|
participant Skill as okstra-run skill
|
|
77
77
|
participant Node as okstra CLI
|
|
78
78
|
participant Py as okstra_ctl.run
|
|
79
|
-
participant FS as .
|
|
79
|
+
participant FS as .okstra
|
|
80
80
|
participant Home as ~/.okstra
|
|
81
81
|
|
|
82
82
|
Skill->>Node: okstra wizard render-args
|
|
@@ -119,7 +119,7 @@ flowchart TD
|
|
|
119
119
|
|
|
120
120
|
```mermaid
|
|
121
121
|
flowchart TD
|
|
122
|
-
Root["<PROJECT_ROOT>/.
|
|
122
|
+
Root["<PROJECT_ROOT>/.okstra/tasks/<group>/<task>/"] --> IS[instruction-set/]
|
|
123
123
|
Root --> Runs[runs/<task-type>/]
|
|
124
124
|
Root --> Hist[history/timeline.json]
|
|
125
125
|
IS --> Profile[analysis-profile.md]
|
package/package.json
CHANGED
package/runtime/BUILD.json
CHANGED
package/runtime/agents/SKILL.md
CHANGED
|
@@ -133,7 +133,7 @@ Executor is chosen at run-prep time via `--executor <claude|codex|gemini>` (or `
|
|
|
133
133
|
- Location: `~/.okstra/worktrees/<project-id>/<task-group-segment>/<task-id-segment>/` (override `OKSTRA_HOME` only for tests). All segments are sanitised — `/`, `:`, and other special chars collapse to `-`.
|
|
134
134
|
- Branch: `<work-category-prefix>-<task-id-segment>` (e.g. `feat-dev-9436`, `fix-dev-7311`). Branched from `HEAD` of the repo's **main** worktree at the first phase's prep time; base SHA is recorded in `EXECUTOR_WORKTREE_BASE_REF`.
|
|
135
135
|
- A global registry at `~/.okstra/worktrees/registry.json` (flock-guarded) maps each task-key to its path + branch and prevents concurrent runs from colliding. Branch names are globally unique across task-keys on this machine.
|
|
136
|
-
- Worktree sync mirrors the configured project-relative directories from the **main worktree** so task checkouts see the same filesystem state. This is filesystem continuity only: okstra-owned context and writes still stay inside `<PROJECT_ROOT>/.
|
|
136
|
+
- Worktree sync mirrors the configured project-relative directories from the **main worktree** so task checkouts see the same filesystem state. This is filesystem continuity only: okstra-owned context and writes still stay inside `<PROJECT_ROOT>/.okstra/**` unless the brief explicitly authorizes a non-okstra path.
|
|
137
137
|
- The path, branch, base ref, and provisioning status (`created` | `reused` | `skipped-in-worktree` | `skipped-not-git`) are exposed through the launch prompt's `## Executor Worktree` section and the implementation profile's worktree block.
|
|
138
138
|
- **Skip conditions** (worktree provisioning is a no-op; task uses `project_root` directly):
|
|
139
139
|
- `project_root` is already inside a non-main worktree (the run reuses the caller's worktree to avoid nesting).
|
|
@@ -145,7 +145,7 @@ Executor is chosen at run-prep time via `--executor <claude|codex|gemini>` (or `
|
|
|
145
145
|
|
|
146
146
|
**REQUIRED SUB-SKILL:** Invoke [okstra-context-loader](./skills/okstra-context-loader/SKILL.md) first to discover task bundle paths.
|
|
147
147
|
|
|
148
|
-
Treat cross verify input as a task bundle, not as a single file. If the user did not specify an explicit task key or task path, use `.
|
|
148
|
+
Treat cross verify input as a task bundle, not as a single file. If the user did not specify an explicit task key or task path, use `.okstra/discovery/latest-task.json` as the current-task convenience pointer. If task browsing, task-id disambiguation, or project-level task inventory is needed, inspect `.okstra/discovery/task-catalog.json` first.
|
|
149
149
|
|
|
150
150
|
After context-loader completes, read **only the five mandatory files below** in a single parallel-Read message at the start of Phase 1. The other instruction-set files are loaded lazily at the phase that actually needs them — see "Lazy reading discipline" below. This split came from observed lead-token bloat: in `fontsninja-classifier-v2:dev-9461:dev-9495` RD-001 the lead burned 71 M tokens (97 % cache_read) largely because every phase entry re-absorbed a 93 KB instruction-set baseline that included files only one downstream phase ever actually used.
|
|
151
151
|
|
|
@@ -48,7 +48,7 @@ Unlike the Codex / Gemini workers, you are an in-process Claude subagent — you
|
|
|
48
48
|
- **Verifier QA-gate exception:** verifier roles MAY use the same `cd <WORKTREE> && <cmd>` shape when executing project-declared `qaCommands` (lint / format / typecheck / test) from `project.json`, since those commands are cwd-sensitive by nature. Outside the QA gate, verifiers still read with absolute paths only — do NOT use `cd` for file inspection.
|
|
49
49
|
- **No extra chaining beyond `cd && cmd`:** the permission matcher only allows the exact two-segment shape `cd <PATH> && <single-command>`. Do NOT append additional pipes, semicolons, redirects, or `&&` chains — e.g. `cd ... && cargo test ... 2>&1 | tail -20; echo "exit:$?"` will trigger a permission prompt every dispatch because the trailing `| tail`, `; echo`, and `2>&1` tokens disqualify the prefix match against `Bash(cargo:*)`. Let Claude Code capture the full stdout/stderr and exit code natively — do not post-process with `tail`, `head`, or `echo "exit:$?"`. If output truncation is genuinely needed, run the command first and read the result in a separate tool call.
|
|
50
50
|
|
|
51
|
-
5. **MCP usage**: The canonical list of MCP servers and tools available for this run lives in the lead prompt's `## Available MCP Servers` section (sourced from `.
|
|
51
|
+
5. **MCP usage**: The canonical list of MCP servers and tools available for this run lives in the lead prompt's `## Available MCP Servers` section (sourced from `.okstra/project.json`'s `mcpServers` array). When the task requires inspection of an external system covered by one of those servers, call the listed tool directly by name (e.g. `mcp__<server>__<tool>`). Do NOT shell out via `claude --mcp-cli call ...` or run the tool name as a Bash command — those are not valid invocation paths. If a server you need is not listed, record `MCP not available for this run` in your worker output rather than guessing a tool name.
|
|
52
52
|
|
|
53
53
|
6. If the task brief includes an `## Available MCP Servers` section in the lead prompt, treat that as the canonical list of MCP tools you may invoke for this run. If a needed server is not listed, record `MCP not available for this run` rather than calling it.
|
|
54
54
|
|
|
@@ -19,9 +19,9 @@ profile document.
|
|
|
19
19
|
- Tooling — read-only MCP availability (shared):
|
|
20
20
|
- MCP is not implicit okstra context. Query an MCP server only when the task brief explicitly lists it as source material for this run. Any MCP-derived finding MUST cite server, table, and the SELECT used. MCP MUST NEVER be used as a write path — schema/data mutations go through repository migration files reviewed by humans.
|
|
21
21
|
- Resource boundary (shared — artifact-home rule):
|
|
22
|
-
- Okstra-owned project artifacts live only under `<PROJECT_ROOT>/.
|
|
23
|
-
- Treat paths outside `<PROJECT_ROOT>/.
|
|
24
|
-
- Create, modify, or delete only inside `<PROJECT_ROOT>/.
|
|
22
|
+
- Okstra-owned project artifacts live only under `<PROJECT_ROOT>/.okstra/**`. Treat `project.json`, task bundles, run artifacts, `glossary.md`, and `decisions/` under that subtree as the canonical okstra memory.
|
|
23
|
+
- Treat paths outside `<PROJECT_ROOT>/.okstra/**` as source material only when the task brief's `Source Material` or `Reporter Confirmations` explicitly cites them; they never become okstra memory.
|
|
24
|
+
- Create, modify, or delete only inside `<PROJECT_ROOT>/.okstra/**` unless the brief verbatim requests a specific non-okstra edit. The phase performing that edit must quote the user instruction in its report. Implementation source edits also require the approved implementation plan.
|
|
25
25
|
- Authority & permissions assumption (applies to every okstra task-type):
|
|
26
26
|
- **Assume the user (and their team) holds full authority and every permission required for the anticipated, in-flight, or follow-up work.** Treat external approvals, third-party access grants, role/IAM permissions, organisational sign-off, legal/compliance review, vendor coordination, and "verify access exists" steps as already satisfied unless the task brief explicitly states otherwise.
|
|
27
27
|
- Do NOT add such items to routing decisions, missing-materials lists, clarification questions, option trade-offs, dependency/migration risk, validation checklists, rollout plans, acceptance blockers, residual risks, release recommendations, the `## 5. Clarification Items` table, or any day/effort estimate. They are not legitimate sources of schedule extension.
|
|
@@ -52,13 +52,13 @@ profile document.
|
|
|
52
52
|
- `Source Material` is reporter-verbatim. Do NOT paraphrase, summarize, reorder, or restructure it. Quote it directly when needed.
|
|
53
53
|
- `Augmentation` entries carry one of four labels — `evidence-link`, `format-conversion`, `terminology-mapping`, `intent-inference`. Treat them as follows:
|
|
54
54
|
- `evidence-link` / `format-conversion` → trust without re-verification.
|
|
55
|
-
- `terminology-mapping` → verify against `<PROJECT_ROOT>/.
|
|
55
|
+
- `terminology-mapping` → verify against `<PROJECT_ROOT>/.okstra/glossary.md` (authoritative); raise a `Clarification Items` row if the mapping is missing or contradicts the glossary.
|
|
56
56
|
- `intent-inference` → treat as an **unverified hypothesis**. Every `intent-inference` augmentation MUST be paired in the brief with an `Open Questions` row prefixed `intent-check:`. Promote that row into the run's `## 5. Clarification Items` table as `Kind=decision, Blocks=next-phase` (or `Blocks=approval` for `implementation-planning`) with the recommended answer set to "보고자에게 직접 확인 후 응답" unless the codebase can be inspected to confirm or refute the inference.
|
|
57
57
|
- `Open Questions` row prefixes are signals — do not strip them when promoting:
|
|
58
58
|
- `intent-check:` → `Kind=decision`, recommended answer = reporter confirmation. NEVER silently resolve an `intent-check:` by inference at this layer.
|
|
59
|
-
- `terminology:` → `Kind=decision`, recommended answer = canonical term from `<PROJECT_ROOT>/.
|
|
59
|
+
- `terminology:` → `Kind=decision`, recommended answer = canonical term from `<PROJECT_ROOT>/.okstra/glossary.md` (or "extend okstra glossary via brief Step 4.5").
|
|
60
60
|
- `conversion-block:` → `Kind=decision`, recommended answer = "보고자에게 직접 확인". The brief is explicitly signalling that translation failed; further inference is forbidden until the reporter clarifies.
|
|
61
|
-
- `adr-candidate:` → handled by `implementation-planning`; carry forward without modification. Approved decision files land only at `<PROJECT_ROOT>/.
|
|
61
|
+
- `adr-candidate:` → handled by `implementation-planning`; carry forward without modification. Approved decision files land only at `<PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md`.
|
|
62
62
|
- `general:` → free-form; classify per the standard `Clarification Items` rules.
|
|
63
63
|
- Any decision in this run that contradicts the brief's `Source Material` must be raised back to the reporter via a `Clarification Items` row; it must NOT be silently overridden. Disagreement with the reporter is allowed only after the row is resolved.
|
|
64
64
|
- This contract is the single authority on brief consumption. Phase-specific addenda may *tighten* these rules but may not relax them.
|
|
@@ -14,7 +14,7 @@ until Phase 5 ends, then drop from active context for Phase 6/7.
|
|
|
14
14
|
- The `Executor` (bound in `implementation.md` thin core) is the **only worker permitted to use Edit / Write / state-mutating Bash commands** on project files. All other workers run read-only. When the executor provider is `codex` or `gemini`, the actual file mutation happens inside the executor CLI's own auto-edit mode (e.g. `codex exec --sandbox workspace-write`, gemini's equivalent) — not through Claude-side Edit/Write tools — but the safety rules in this sidecar still apply identically.
|
|
15
15
|
- Worktree cwd handling — when the thin core's Task worktree block resolves status to `created` or `reused`, the Executor MUST run every Edit / Write / build / test / commit command with the worktree path as cwd. Treat it as `project_root` for the duration of this run. Do NOT mutate the caller's original checkout. Do NOT `cd` out of the worktree to reach files; if a file outside the worktree is needed, the dependency is a planning gap — record it in `Out-of-plan edits` and continue.
|
|
16
16
|
- **How to set cwd per Bash call**: the Claude Bash tool inherits its cwd from the lead session, which is NOT the worktree. To put cwd-sensitive toolchains (`cargo`, `npm`, `pnpm`, `bun`, `pytest`, `make`, `go`) into the worktree, prefix the command with `cd {{EXECUTOR_WORKTREE_PATH}} && ` inside the same Bash invocation — e.g. `cd {{EXECUTOR_WORKTREE_PATH}} && cargo test -p foo`. **Never wrap in `bash -lc "..."` or `bash -c "..."`** — the wrapper hides the leading `cd` token from Claude Code's permission auto-allow layer (causing prompts on every call) without any safety benefit. For tools that accept an explicit working-directory flag (`git -C <path>`, `cargo --manifest-path`, `pytest --rootdir`), prefer that form over the `cd && ` chain. Edit / Write / Read tool calls already use absolute paths and need no cwd handling. The codex / gemini executor CLI wrappers (`okstra-codex-exec.sh -C`, `okstra-gemini-exec.sh --include-directories`) already inject worktree cwd at the CLI layer, so this rule applies primarily to the Claude executor.
|
|
17
|
-
- **Synced okstra state directory.** At provision time `okstra-ctl` may symlink `.project-docs/` from the repo's **main worktree** into the task worktree. This is NOT an independent copy — writes through it land in the main worktree. Inside this run the executor MUST confine okstra artifact writes to its own task scope (i.e. `.
|
|
17
|
+
- **Synced okstra state directory.** At provision time `okstra-ctl` may symlink `.project-docs/` from the repo's **main worktree** into the task worktree. This is NOT an independent copy — writes through it land in the main worktree. Inside this run the executor MUST confine okstra artifact writes to its own task scope (i.e. `.okstra/tasks/<this-task-id>/...`). Other synced directories, if present due to local configuration, are not implicit okstra context; read them only when the brief explicitly cites them as source material.
|
|
18
18
|
|
|
19
19
|
## Pre-implementation context exploration (executor before first edit)
|
|
20
20
|
|
|
@@ -54,7 +54,7 @@ until Phase 5 ends, then drop from active context for Phase 6/7.
|
|
|
54
54
|
- `<scope>` SHOULD be the plan step identifier or the primary module touched (e.g. `feat(report-writer): ...`). Omit the parentheses only when no meaningful scope applies.
|
|
55
55
|
- `<subject>` MUST be ≤72 characters, imperative mood (`add`, `fix`, `remove` — not `added` / `adding`), no trailing period, no emoji, no AI attribution lines (no `Co-Authored-By: Claude ...`, no `Generated with Claude Code`).
|
|
56
56
|
- Body (when present) explains *why*, not *what*; wrap at ~100 chars.
|
|
57
|
-
- Do NOT append okstra artefact paths to the commit message — no `Plan: .
|
|
57
|
+
- Do NOT append okstra artefact paths to the commit message — no `Plan: .okstra/...`, no `Report: ...`, no `Run: ...`, no `Task: ...` footers, and no other reference to files under `.okstra/`. Those paths belong in the final report's `Plan link & approval evidence` section, not in git history; they rot quickly and leak internal layout into the upstream changelog.
|
|
58
58
|
- Allowed footers are limited to standard Conventional Commits trailers (`BREAKING CHANGE: ...`, `Refs: <issue/ticket-id>`, `Closes #<n>`). When citing a ticket, use the ticket id only (e.g. `Refs: DEV-9423`) — never a filesystem path.
|
|
59
59
|
- One commit MUST correspond to one plan step (or one cohesive sub-step). Do NOT bundle unrelated steps into a single commit, and do NOT split a single step across commits unless the plan explicitly sequenced it that way.
|
|
60
60
|
- The exact message used for each commit MUST be reproduced verbatim in the final report's `Commit list` so reviewers can audit it without re-running `git log`.
|
|
@@ -23,7 +23,7 @@ Every verifier acts as a QA gate, not just a diff reviewer. Trusting the executo
|
|
|
23
23
|
Verifier obtains the QA command set from exactly two declared sources, in order — there is **no fallback to guessing tools from manifest files**.
|
|
24
24
|
|
|
25
25
|
1. **Tier 1 — plan validation set (task-specific):** every command listed under the approved plan's `validation` block (pre / mid / post).
|
|
26
|
-
2. **Tier 2 — project baseline (`project.json.qaCommands`):** the project's standing QA baseline declared in `<PROJECT_ROOT>/.
|
|
26
|
+
2. **Tier 2 — project baseline (`project.json.qaCommands`):** the project's standing QA baseline declared in `<PROJECT_ROOT>/.okstra/project.json` under the `qaCommands` key. Schema (each category is an array of `{ "label", "cmd", "language"? }` objects):
|
|
27
27
|
```json
|
|
28
28
|
{
|
|
29
29
|
"qaCommands": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
- **Residual Risk block** (under section 4): risks that are not blockers but should be tracked, each with mitigation owner and a trigger that would escalate them to a blocker.
|
|
32
32
|
- **Validation Evidence**: for every requirement in the originating plan or task brief, cite the artifact (commit SHA, test output, log line, MCP SELECT result) that demonstrates coverage. Paraphrased "verified" claims without an artifact are rejected.
|
|
33
33
|
- **Read-only command log**: any pre-existing test/validation command executed during this run MUST be listed with its exact command line and exit code. No mutating commands may appear here.
|
|
34
|
-
- **Two-tier command lookup (shared with `implementation`):** when this phase performs its own independent re-validation, the command source is exactly the same two tiers `implementation` verifiers use — Tier 1 is the originating task brief / approved plan's `validation` set, Tier 2 is `<PROJECT_ROOT>/.
|
|
34
|
+
- **Two-tier command lookup (shared with `implementation`):** when this phase performs its own independent re-validation, the command source is exactly the same two tiers `implementation` verifiers use — Tier 1 is the originating task brief / approved plan's `validation` set, Tier 2 is `<PROJECT_ROOT>/.okstra/project.json` under `qaCommands`. Auto-detecting tools from manifest files is forbidden; missing tiers are recorded as `qa-command not configured: <category>` and do NOT trigger a guess. The `cmd` deny-list (`--fix`, `--write`, ` -w`, ` -u`, `--snapshot-update`, `INSTA_UPDATE=<not-no>`, `cargo update`, `npm install` without `ci`, etc.) is enforced identically. NOTE: runtime fail-fast validation (`okstra_ctl.qa_commands.validate_qa_commands`) only fires at `--task-type implementation` run-prep, so this phase MUST self-check each `qaCommands` entry against the deny-list before executing it — if a denied token is present, skip the command and record it as a `Read-only command log` line `qa-command rejected (denied token: <token>): <label>`.
|
|
35
35
|
- **Routing recommendation**: brief note on the next safe phase (`done`, `error-analysis`, `implementation-planning`) tied to the verdict and blocker list.
|
|
36
36
|
- Clarification request policy (phase-specific addendum — shared policy is in `_common-contract.md`):
|
|
37
37
|
- populate `## 5. Clarification Items` only when a blocker hinges on information only the user can supply (deployment intent, intended target environment, business-rule interpretation); use `Blocks=next-phase` for items that gate continuing to release-handoff
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
- skim recent commits touching those files (`git log -- <path>`) to surface in-flight work or contested areas
|
|
19
19
|
- **codebase-first ambiguity resolution**: any ambiguity that can be answered by `Read` / `Grep` MUST be resolved that way and recorded with file:line evidence. Only ambiguities that genuinely require a human decision are escalated as `Clarification Items` rows. Writing a clarification row for something the code already answers is a defect of this phase.
|
|
20
20
|
- flag any requirement that is ambiguous, contradictory, or missing success criteria — register each one as a row in the report's `## 5. Clarification Items` table with `Blocks=approval` instead of guessing
|
|
21
|
-
- read `<PROJECT_ROOT>/.
|
|
21
|
+
- read `<PROJECT_ROOT>/.okstra/glossary.md` and `<PROJECT_ROOT>/.okstra/decisions/` titles if present. Absent okstra memory files are the normal state — do not error. Treat the brief's `terminology:*` resolutions from `requirements-discovery` (if any) as authoritative; if missing, resolve any remaining fuzzy term as a `Blocks=approval` clarification row.
|
|
22
22
|
- Primary focus areas:
|
|
23
23
|
- requirement gaps
|
|
24
24
|
- affected components and boundaries
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
- executing builds, migrations, deployments, or any command that mutates project state outside the run's own artifact directories (`reports/`, `prompts/`, `state/`, `manifests/`, `worker-results/`, `status/`, `sessions/`)
|
|
44
44
|
- this run stays in `implementation-planning` regardless of user phrasing — the shared anti-escalation rule applies
|
|
45
45
|
- dispatching parallel sub-agents beyond the required worker roster — okstra owns worker fan-out
|
|
46
|
-
- writing artifacts anywhere except `<PROJECT_ROOT>/.
|
|
46
|
+
- writing artifacts anywhere except `<PROJECT_ROOT>/.okstra/` — the run's `reports/` directory is the canonical location for this phase
|
|
47
47
|
- Clarification request policy (phase-specific addenda — shared policy is in `_common-contract.md`):
|
|
48
48
|
- every clarification row carries a recommended answer + one-line rationale inside the `Expected form` cell; rows that lack a recommendation are rejected as half-formed.
|
|
49
49
|
- **Evidence note required inside `Statement`**: every clarification row includes `Evidence checked: <path:line>` or `Evidence checked: none — <human-only reason>` in the `Statement` cell. `none` is allowed ONLY when the row's nature is "only a human can answer this" (reporter intent, business priority, organisational decision). A row with `none` that *could* have been answered by the codebase is a defect of this phase, restated from the pre-planning rule above.
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
1. **Hard to reverse** — would changing the decision later cost meaningfully more than deciding now?
|
|
78
78
|
2. **Surprising without context** — would a future reader, seeing only the code, wonder "why was it built this way?"?
|
|
79
79
|
3. **Real trade-off** — were there named alternatives, and was one picked for specific reasons?
|
|
80
|
-
If **all three** hold, attach a decision draft as a report appendix section titled `Decision Drafts` (one decision per subsection). Each draft uses the `## Context / ## Decision / ## Consequences / ## Alternatives Considered` shape, names the alternatives that were rejected and why, and starts with `## Status: Proposed`. The next decision number is `(max existing in <PROJECT_ROOT>/.
|
|
81
|
-
The drafts are NOT written by this phase. The approved plan's stepwise execution order MUST include the step `Create <PROJECT_ROOT>/.
|
|
82
|
-
- **Glossary proposals**: if a term or definition should become okstra institutional memory, add the step `Update <PROJECT_ROOT>/.
|
|
80
|
+
If **all three** hold, attach a decision draft as a report appendix section titled `Decision Drafts` (one decision per subsection). Each draft uses the `## Context / ## Decision / ## Consequences / ## Alternatives Considered` shape, names the alternatives that were rejected and why, and starts with `## Status: Proposed`. The next decision number is `(max existing in <PROJECT_ROOT>/.okstra/decisions/ + 1)` zero-padded to 4 digits. If any of the three criteria is missing, do NOT raise a decision draft — instead record `skipped adr-candidate: <topic> — reason: <criterion that failed>` on one line under `Decision Drafts` so the next reader knows the candidate was evaluated and intentionally dropped.
|
|
81
|
+
The drafts are NOT written by this phase. The approved plan's stepwise execution order MUST include the step `Create <PROJECT_ROOT>/.okstra/decisions/<NNNN>-<slug>.md from the decision draft in section X` so the `implementation` run commits the file inside okstra's subtree.
|
|
82
|
+
- **Glossary proposals**: if a term or definition should become okstra institutional memory, add the step `Update <PROJECT_ROOT>/.okstra/glossary.md: <term> = <definition>` to the stepwise execution order. Use no other project-memory path.
|
|
83
83
|
- No-placeholder rule (plan failures — reject any option or step that contains these):
|
|
84
84
|
- "TBD", "TODO", "implement later", "fill in details", "add appropriate error handling", "handle edge cases", "write tests for the above" without actual test code
|
|
85
85
|
- "similar to Option/Task N" without repeating the concrete content (readers may consume sections out of order)
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
- `cancel` — end the run without executing push or PR commands; record the cancellation in the final report.
|
|
44
44
|
- Inline drafting rules (Claude lead):
|
|
45
45
|
- read the run brief, the cited final-verification report, `git log --oneline <base>..HEAD`, and `git diff <base>..HEAD --stat` to ground the drafted text in actual committed changes.
|
|
46
|
-
- **PR body template** — the run context exposes `PR_TEMPLATE_PATH` and `PR_TEMPLATE_SOURCE`. The path MUST be an okstra-owned project artifact under `<PROJECT_ROOT>/.
|
|
46
|
+
- **PR body template** — the run context exposes `PR_TEMPLATE_PATH` and `PR_TEMPLATE_SOURCE`. The path MUST be an okstra-owned project artifact under `<PROJECT_ROOT>/.okstra/**` or a file already materialised into this run's artifact directory by the prepare step. The lead MUST `Read` this file verbatim, strip HTML comments, then fill in the placeholders. Do NOT hard-code a section list — the template is the source of truth for the structure. If the resolved file is missing or outside the okstra resource boundary at draft time, abort the run with a clear error rather than inventing a structure.
|
|
47
47
|
- produce **two artifacts** before showing them to the user:
|
|
48
48
|
1. **PR title** — by default the subject of the most recent implementation commit, or a concise Conventional Commits-style summary of the committed range.
|
|
49
49
|
2. **PR body** — markdown filled from `PR_TEMPLATE_PATH`. The user-confirmation step's diff (Q3 `edit then proceed`) is computed against the filled template, not against the raw template file.
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
- identify missing materials that block reliable routing
|
|
20
20
|
- define task continuity expectations for long-running work under the same task key
|
|
21
21
|
- capture approval or confirmation points before the next phase starts
|
|
22
|
-
- **domain alignment check**: read `<PROJECT_ROOT>/.
|
|
22
|
+
- **domain alignment check**: read `<PROJECT_ROOT>/.okstra/glossary.md` and `<PROJECT_ROOT>/.okstra/decisions/` titles if present. Absent okstra memory files are normal — do not error. Validate that every `terminology:*` entry under the brief's `Open Questions` has a canonical resolution before routing. Fuzzy or overloaded terms in the brief MUST be resolved to a single canonical term in this phase.
|
|
23
23
|
- Decision-tree walk (bounded):
|
|
24
24
|
- When the brief's `Desired Outcome`, classification, or routing target depends on a chain of decisions, walk that chain one branch at a time. Each branch is one `Clarification Items` row, not a free-form interview.
|
|
25
25
|
- For every clarification row, put the single best answer and one-line rationale in `Expected form` as `Recommended: ...`. Put other options and one-sentence consequences in the same cell as `Alternatives: ...`.
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- evidence-backed routing decision
|
|
30
30
|
- uncertainty boundaries and missing inputs
|
|
31
31
|
- next recommended phase and safe resume guidance
|
|
32
|
-
- canonical-term resolution for every `terminology:*` brief item, written as a one-line `<term> = <definition>` line in a new `Domain Alignment` subsection of the final report; alongside each, propose whether `<PROJECT_ROOT>/.
|
|
32
|
+
- canonical-term resolution for every `terminology:*` brief item, written as a one-line `<term> = <definition>` line in a new `Domain Alignment` subsection of the final report; alongside each, propose whether `<PROJECT_ROOT>/.okstra/glossary.md` should be updated (proposal only — actual writes happen via `okstra-brief` Step 4.5 on a subsequent run)
|
|
33
33
|
- Clarification request policy (phase-specific addenda — shared policy is in `_common-contract.md`):
|
|
34
34
|
- if any blocking input is missing at the time of writing the final report, populate `## 5. Clarification Items` in `final-report-template.md` (a single unified table; `Blocks=next-phase` for items the next run cannot start without)
|
|
35
35
|
- prefer concrete questions whose answers map directly to a routing decision (`bugfix` vs `feature`, `error-analysis` vs `implementation-planning`, etc.). State each option in plain language with one sentence describing what choosing it would mean for the next phase.
|
|
@@ -39,4 +39,4 @@
|
|
|
39
39
|
- Non-goals:
|
|
40
40
|
- full implementation design unless it is required to decide the next phase
|
|
41
41
|
- **source code edits, plan authoring, builds, or deployments** — this run only classifies the work and routes it; deeper analysis and planning belong to subsequent phases
|
|
42
|
-
- **writes outside `<PROJECT_ROOT>/.
|
|
42
|
+
- **writes outside `<PROJECT_ROOT>/.okstra/`** — this phase only uses okstra's artifact root. Glossary additions land in `<PROJECT_ROOT>/.okstra/glossary.md` (via `okstra-brief` Step 4.5); decision drafts land in `<PROJECT_ROOT>/.okstra/decisions/` (via `implementation-planning`).
|
|
@@ -23,6 +23,20 @@
|
|
|
23
23
|
"options": {
|
|
24
24
|
"__use_suggested__": "brief 값 사용: {suggestion}",
|
|
25
25
|
"__free_input__": "다른 값 입력"
|
|
26
|
+
},
|
|
27
|
+
"echo_variants": {
|
|
28
|
+
"free_input": "task-group: (직접 입력)"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"task_group_no_suggestion": {
|
|
32
|
+
"label": "Task group? (예: backend-api, INV-1234)",
|
|
33
|
+
"echo_template": "task-group: {value}",
|
|
34
|
+
"options": {
|
|
35
|
+
"__free_input__": "직접 입력"
|
|
36
|
+
},
|
|
37
|
+
"recent_label_prefix": "최근 사용: ",
|
|
38
|
+
"echo_variants": {
|
|
39
|
+
"free_input": "task-group: (직접 입력)"
|
|
26
40
|
}
|
|
27
41
|
},
|
|
28
42
|
"task_group_text": {
|
|
@@ -42,6 +56,20 @@
|
|
|
42
56
|
"options": {
|
|
43
57
|
"__use_suggested__": "brief 값 사용: {suggestion}",
|
|
44
58
|
"__free_input__": "다른 값 입력"
|
|
59
|
+
},
|
|
60
|
+
"echo_variants": {
|
|
61
|
+
"free_input": "task-id: (직접 입력)"
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"task_id_no_suggestion": {
|
|
65
|
+
"label": "Task id? (예: login-error-analysis, dev-9043)",
|
|
66
|
+
"echo_template": "task-id: {value}",
|
|
67
|
+
"options": {
|
|
68
|
+
"__free_input__": "직접 입력"
|
|
69
|
+
},
|
|
70
|
+
"recent_label_prefix": "같은 group 의 기존: ",
|
|
71
|
+
"echo_variants": {
|
|
72
|
+
"free_input": "task-id: (직접 입력)"
|
|
45
73
|
}
|
|
46
74
|
},
|
|
47
75
|
"task_id_text": {
|
|
@@ -66,6 +94,18 @@
|
|
|
66
94
|
"kept": "brief: {brief_path} (유지)"
|
|
67
95
|
}
|
|
68
96
|
},
|
|
97
|
+
"brief_path_pick": {
|
|
98
|
+
"label": "task brief markdown 의 경로를 선택해주세요",
|
|
99
|
+
"echo_template": "brief(pick): {value}",
|
|
100
|
+
"options": {
|
|
101
|
+
"__existing__": "기존 brief 사용: {existing}",
|
|
102
|
+
"__standard__": "표준 경로 사용: {standard}",
|
|
103
|
+
"__free_input__": "직접 입력"
|
|
104
|
+
},
|
|
105
|
+
"errors": {
|
|
106
|
+
"existing_missing": "기존 brief 가 없습니다. 다른 옵션을 선택하세요."
|
|
107
|
+
}
|
|
108
|
+
},
|
|
69
109
|
"brief_path": {
|
|
70
110
|
"label": "task brief markdown 의 경로를 알려주세요 (project root 기준 상대경로 또는 절대경로)",
|
|
71
111
|
"echo_template": "brief: {value}"
|
|
@@ -87,10 +127,16 @@
|
|
|
87
127
|
"echo_template": "approved-plan(pick): {value}",
|
|
88
128
|
"options": {
|
|
89
129
|
"__use_default__": "기본 경로 사용: {default}",
|
|
90
|
-
"__other__": "
|
|
130
|
+
"__other__": "직접 입력"
|
|
131
|
+
},
|
|
132
|
+
"labels": {
|
|
133
|
+
"other_report": "이전 보고서: {path}"
|
|
134
|
+
},
|
|
135
|
+
"echo_suffixes": {
|
|
136
|
+
"other_report": "(이전 보고서)"
|
|
91
137
|
},
|
|
92
138
|
"errors": {
|
|
93
|
-
"default_not_found": "기본 approved-plan 경로를 찾을 수 없습니다. '
|
|
139
|
+
"default_not_found": "기본 approved-plan 경로를 찾을 수 없습니다. '직접 입력'을 선택하세요."
|
|
94
140
|
}
|
|
95
141
|
},
|
|
96
142
|
"approved_plan": {
|
|
@@ -109,7 +155,14 @@
|
|
|
109
155
|
"echo_template": "directive(pick): {value}",
|
|
110
156
|
"options": {
|
|
111
157
|
"__skip__": "없음 (건너뛰기)",
|
|
112
|
-
"
|
|
158
|
+
"__free_input__": "직접 입력"
|
|
159
|
+
},
|
|
160
|
+
"labels": {
|
|
161
|
+
"reuse_last": "이전 run 의 directive 재사용: {snippet}"
|
|
162
|
+
},
|
|
163
|
+
"echo_suffixes": {
|
|
164
|
+
"reuse": "directive: {value} (재사용)",
|
|
165
|
+
"skip": "directive: (none)"
|
|
113
166
|
}
|
|
114
167
|
},
|
|
115
168
|
"related_tasks_pick": {
|
|
@@ -117,7 +170,14 @@
|
|
|
117
170
|
"echo_template": "related-tasks(pick): {value}",
|
|
118
171
|
"options": {
|
|
119
172
|
"__skip__": "없음 (건너뛰기)",
|
|
120
|
-
"
|
|
173
|
+
"__free_input__": "직접 입력"
|
|
174
|
+
},
|
|
175
|
+
"labels": {
|
|
176
|
+
"siblings": "같은 group 의 task-id 사용: {snippet}"
|
|
177
|
+
},
|
|
178
|
+
"echo_suffixes": {
|
|
179
|
+
"skip": "related-tasks: (none)",
|
|
180
|
+
"siblings": "related-tasks: {value} (siblings)"
|
|
121
181
|
}
|
|
122
182
|
},
|
|
123
183
|
"clarification_pick": {
|
|
@@ -125,7 +185,14 @@
|
|
|
125
185
|
"echo_template": "clarification(pick): {value}",
|
|
126
186
|
"options": {
|
|
127
187
|
"__skip__": "없음 (건너뛰기)",
|
|
128
|
-
"
|
|
188
|
+
"__free_input__": "직접 입력"
|
|
189
|
+
},
|
|
190
|
+
"labels": {
|
|
191
|
+
"latest_report": "최근 final-report 사용: {snippet}"
|
|
192
|
+
},
|
|
193
|
+
"echo_suffixes": {
|
|
194
|
+
"skip": "clarification: (none)",
|
|
195
|
+
"latest_report": "clarification: {value} (재사용)"
|
|
129
196
|
}
|
|
130
197
|
},
|
|
131
198
|
"pr_template_pick": {
|
|
@@ -133,7 +200,14 @@
|
|
|
133
200
|
"echo_template": "pr-template(pick): {value}",
|
|
134
201
|
"options": {
|
|
135
202
|
"__skip__": "자동 해석 (project.json → config → 기본)",
|
|
136
|
-
"
|
|
203
|
+
"__free_input__": "직접 입력"
|
|
204
|
+
},
|
|
205
|
+
"labels": {
|
|
206
|
+
"project_default": "project.json 의 prTemplatePath 사용: {snippet}"
|
|
207
|
+
},
|
|
208
|
+
"echo_suffixes": {
|
|
209
|
+
"skip": "pr-template: (auto-resolve)",
|
|
210
|
+
"project_default": "pr-template: {value} (project default)"
|
|
137
211
|
}
|
|
138
212
|
},
|
|
139
213
|
"executor": {
|
|
@@ -78,7 +78,7 @@ def slugify(value: str) -> str:
|
|
|
78
78
|
|
|
79
79
|
candidates = []
|
|
80
80
|
|
|
81
|
-
catalog_path = project_root / ".
|
|
81
|
+
catalog_path = project_root / ".okstra" / "discovery" / "task-catalog.json"
|
|
82
82
|
catalog_keys = []
|
|
83
83
|
if catalog_path.is_file():
|
|
84
84
|
try:
|
|
@@ -111,7 +111,7 @@ if catalog_path.is_file():
|
|
|
111
111
|
sys.exit(0)
|
|
112
112
|
candidates.append(str(abs_path))
|
|
113
113
|
|
|
114
|
-
slug_path = project_root / ".
|
|
114
|
+
slug_path = project_root / ".okstra" / "tasks" / slugify(task_group) / slugify(task_id)
|
|
115
115
|
if slug_path.is_dir():
|
|
116
116
|
print(f"OK\t{slug_path}")
|
|
117
117
|
sys.exit(0)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# shellcheck shell=bash
|
|
2
2
|
|
|
3
3
|
# bash wrappers around scripts/okstra_project resolver. okstra.sh 가 시작 시
|
|
4
|
-
# PROJECT_ROOT 를 확정하고 <PROJECT_ROOT>/.
|
|
4
|
+
# PROJECT_ROOT 를 확정하고 <PROJECT_ROOT>/.okstra/project.json 을
|
|
5
5
|
# upsert 한다. 과거 conf 파일 모델은 폐기되었다.
|
|
6
6
|
|
|
7
7
|
# 절대경로(또는 빈 문자열) 를 stdout 으로 출력한다. 실패 시 stderr 에 메시지를
|
|
@@ -16,7 +16,7 @@ summary:
|
|
|
16
16
|
|
|
17
17
|
required arguments:
|
|
18
18
|
--project-id Globally unique project ID. Example: sample-project-v2-api.
|
|
19
|
-
Each project is registered at <project-root>/.
|
|
19
|
+
Each project is registered at <project-root>/.okstra/project.json
|
|
20
20
|
on first run; subsequent runs verify the projectId there matches.
|
|
21
21
|
--task-group Logical task group. Example: backend-api, bugfix, linear-8858
|
|
22
22
|
--task-id Stable task identifier inside the task group. Example: login-error-analysis
|
|
@@ -25,7 +25,7 @@ required arguments:
|
|
|
25
25
|
|
|
26
26
|
optional arguments:
|
|
27
27
|
--project-root Absolute path to the target project root. Resolution order when omitted:
|
|
28
|
-
(1) ancestor of cwd that contains .
|
|
28
|
+
(1) ancestor of cwd that contains .okstra/project.json,
|
|
29
29
|
(2) `git rev-parse --show-toplevel` from cwd. Errors out if neither resolves.
|
|
30
30
|
--directive Free-form user-supplied directive carried into the run as a "## Directive" section
|
|
31
31
|
inside instruction-set/analysis-material.md. Lead, workers, and skills (e.g. okstra-schedule)
|
|
@@ -107,15 +107,15 @@ model defaults:
|
|
|
107
107
|
|
|
108
108
|
output:
|
|
109
109
|
Stable task bundles are stored under:
|
|
110
|
-
<target-project>/.
|
|
110
|
+
<target-project>/.okstra/tasks/<task-group>/<task-id>/
|
|
111
111
|
Per-run history is stored under:
|
|
112
|
-
<target-project>/.
|
|
112
|
+
<target-project>/.okstra/tasks/<task-group>/<task-id>/runs/
|
|
113
113
|
Inside each run date folder, artifacts are grouped by type under:
|
|
114
114
|
manifests/, state/, prompts/, reports/, status/, sessions/, worker-results/
|
|
115
115
|
|
|
116
116
|
project-level discovery:
|
|
117
117
|
Latest $DISPLAY_TOOL_NAME task pointer:
|
|
118
|
-
<target-project>/.
|
|
118
|
+
<target-project>/.okstra/discovery/latest-task.json
|
|
119
119
|
|
|
120
120
|
interactive behavior:
|
|
121
121
|
If required arguments are missing and stdin is interactive, $DISPLAY_TOOL_NAME prompts for them.
|
|
@@ -216,7 +216,7 @@ for original in targets:
|
|
|
216
216
|
slug_group = slugify_task_segment(row["taskGroup"])
|
|
217
217
|
slug_task = slugify_task_segment(row["taskId"])
|
|
218
218
|
slug_type = slugify_task_segment(row["taskType"])
|
|
219
|
-
base_run = (".
|
|
219
|
+
base_run = (".okstra/tasks/"
|
|
220
220
|
f"{slug_group}/{slug_task}/runs/{slug_type}")
|
|
221
221
|
final_rel = (f"{base_run}/reports/"
|
|
222
222
|
f"final-report-{slug_type}-{next_seq:03d}.md")
|
|
@@ -7,6 +7,8 @@ import re as _re
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from typing import List
|
|
9
9
|
|
|
10
|
+
from okstra_project.dirs import tasks_root
|
|
11
|
+
|
|
10
12
|
from .ids import build_run_id
|
|
11
13
|
from .invocation import invocation_path, save_invocation
|
|
12
14
|
from .jsonl import append_jsonl, read_jsonl, rotate_recent_if_needed
|
|
@@ -19,7 +21,7 @@ def discover_project_roots(home: Path) -> List[tuple]:
|
|
|
19
21
|
project_root) 목록을 반환한다.
|
|
20
22
|
|
|
21
23
|
신규 모델에서는 okstra.sh 가 첫 실행 시 PROJECT_ROOT 를 해석해
|
|
22
|
-
`<PROJECT_ROOT>/.
|
|
24
|
+
`<PROJECT_ROOT>/.okstra/project.json` 에 자기 등록하고,
|
|
23
25
|
record_start 가 그 PROJECT_ROOT 를 meta.json 에 mirror 한다. ctl 입장
|
|
24
26
|
에서는 한 번이라도 record_start 를 거친 프로젝트는 meta.json 에 등재
|
|
25
27
|
되어 있으므로, examples/projects 같은 외부 등록 디렉토리가 필요하지
|
|
@@ -88,11 +90,11 @@ def _apply_backfill_meta(home: Path, project_id: str, project_root: Path, *,
|
|
|
88
90
|
|
|
89
91
|
|
|
90
92
|
def backfill_project(home: Path, project_id: str, project_root: Path) -> int:
|
|
91
|
-
"""타깃 프로젝트의
|
|
93
|
+
"""타깃 프로젝트의 okstra tasks 디렉토리를 스캔해 누락된 run 을 인덱스에 채움.
|
|
92
94
|
실제 okstra 레이아웃: runs/<task_type>/manifests/run-manifest-<task_type>-<seq:03d>.json
|
|
93
95
|
이미 존재하는 runId 는 스킵. 새로 추가된 run 수를 반환.
|
|
94
96
|
"""
|
|
95
|
-
base = project_root
|
|
97
|
+
base = tasks_root(project_root)
|
|
96
98
|
if not base.is_dir():
|
|
97
99
|
return 0
|
|
98
100
|
existing_index = home / "projects" / project_id / "index.jsonl"
|