okstra 0.201.3 → 0.204.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.md +3 -3
- package/dist/cli-registry.mjs +7 -7
- package/dist/cli-registry.mjs.map +1 -1
- package/dist/commands/lifecycle/install.mjs +50 -124
- package/dist/commands/lifecycle/install.mjs.map +1 -1
- package/dist/commands/lifecycle/setup.mjs +15 -0
- package/dist/commands/lifecycle/setup.mjs.map +1 -1
- package/dist/commands/memory/memory.mjs +41 -8
- package/dist/commands/memory/memory.mjs.map +1 -1
- package/dist/lib/citation-guidance.d.mts +21 -0
- package/dist/lib/citation-guidance.mjs +79 -0
- package/dist/lib/citation-guidance.mjs.map +1 -0
- package/dist/lib/install-assets.mjs +3 -0
- package/dist/lib/install-assets.mjs.map +1 -1
- package/dist/lib/runtime-manifest.mjs +2 -1
- package/dist/lib/runtime-manifest.mjs.map +1 -1
- package/dist/lib/types.d.mts +2 -1
- package/docs/architecture/storage-model.md +17 -10
- package/docs/architecture.md +26 -20
- package/docs/cli.md +16 -13
- package/docs/contributor-change-matrix.md +3 -2
- package/docs/performance-improvement-plan-v2.md +2 -3
- package/docs/project-structure-overview.md +38 -9
- package/docs/task-process/README.md +1 -1
- package/docs/task-process/common-flow.md +1 -1
- package/docs/task-process/final-verification.md +3 -1
- package/docs/task-process/implementation.md +1 -1
- package/docs/task-process/release-handoff.md +36 -39
- package/package.json +1 -2
- package/runtime/BUILD.json +2 -2
- package/runtime/agents/common.json +28 -0
- package/runtime/agents/operations/code-review.json +6 -0
- package/runtime/agents/operations/report-translation.json +6 -0
- package/runtime/agents/operations/schedule-verification.json +6 -0
- package/runtime/agents/roles/analyser.json +18 -0
- package/runtime/agents/roles/critic.json +18 -0
- package/runtime/agents/roles/designer.json +18 -0
- package/runtime/agents/roles/implementer.json +20 -0
- package/runtime/agents/roles/leader.json +20 -0
- package/runtime/agents/roles/planner.json +18 -0
- package/runtime/agents/roles/report-writer.json +19 -0
- package/runtime/agents/roles/translator.json +19 -0
- package/runtime/agents/roles/verifier.json +18 -0
- package/runtime/bin/lib/okstra/usage.sh +5 -5
- package/runtime/prompts/duties/acceptance-critic.json +32 -0
- package/runtime/prompts/duties/acceptance-verifier.json +32 -0
- package/runtime/prompts/duties/analysis-worker.json +32 -0
- package/runtime/prompts/duties/code-reviewer.json +32 -0
- package/runtime/prompts/duties/diagnosis-worker.json +32 -0
- package/runtime/prompts/duties/direction-selection-worker.json +32 -0
- package/runtime/prompts/duties/discovery-worker.json +32 -0
- package/runtime/prompts/duties/implementation-executor.json +32 -0
- package/runtime/prompts/duties/implementation-verifier.json +32 -0
- package/runtime/prompts/duties/lead.json +32 -0
- package/runtime/prompts/duties/planning-worker.json +36 -0
- package/runtime/prompts/duties/report-writer.json +32 -0
- package/runtime/prompts/duties/reverification-worker.json +32 -0
- package/runtime/prompts/duties/schedule-verifier.json +32 -0
- package/runtime/prompts/duties/scope-critic.json +32 -0
- package/runtime/prompts/duties/technical-verification-worker.json +32 -0
- package/runtime/prompts/duties/translator.json +32 -0
- package/runtime/prompts/launch.template.md +3 -2
- package/runtime/prompts/lead/adapters/cmux.md +1 -1
- package/runtime/prompts/lead/convergence.md +4 -4
- package/runtime/prompts/lead/okstra-lead-contract.md +115 -6
- package/runtime/prompts/lead/plan-body-verification.md +6 -6
- package/runtime/prompts/lead/report-writer.md +3 -3
- package/runtime/prompts/profiles/_common-contract.md +2 -2
- package/runtime/prompts/profiles/_implementation-executor.md +4 -1
- package/runtime/prompts/profiles/_implementation-verifier.md +3 -3
- package/runtime/prompts/profiles/change-impact-analysis.json +31 -0
- package/runtime/prompts/profiles/change-impact-analysis.md +0 -20
- package/runtime/prompts/profiles/error-analysis.json +39 -0
- package/runtime/prompts/profiles/error-analysis.md +0 -25
- package/runtime/prompts/profiles/feature-analysis.json +31 -0
- package/runtime/prompts/profiles/feature-analysis.md +0 -20
- package/runtime/prompts/profiles/final-verification.json +30 -0
- package/runtime/prompts/profiles/final-verification.md +3 -22
- package/runtime/prompts/profiles/forbidden-actions.json +4 -3
- package/runtime/prompts/profiles/implementation-option-selection.json +31 -0
- package/runtime/prompts/profiles/implementation-option-selection.md +0 -20
- package/runtime/prompts/profiles/implementation-planning.json +40 -0
- package/runtime/prompts/profiles/implementation-planning.md +6 -29
- package/runtime/prompts/profiles/implementation.json +30 -0
- package/runtime/prompts/profiles/implementation.md +1 -20
- package/runtime/prompts/profiles/improvement-discovery.json +31 -0
- package/runtime/prompts/profiles/improvement-discovery.md +0 -20
- package/runtime/prompts/profiles/project-analysis.json +31 -0
- package/runtime/prompts/profiles/project-analysis.md +0 -20
- package/runtime/prompts/profiles/release-handoff.json +5 -0
- package/runtime/prompts/profiles/release-handoff.md +71 -73
- package/runtime/prompts/profiles/requirements-discovery.json +39 -0
- package/runtime/prompts/profiles/requirements-discovery.md +0 -25
- package/runtime/prompts/profiles/technical-verification.json +39 -0
- package/runtime/prompts/profiles/technical-verification.md +0 -25
- package/runtime/prompts/wizard/prompts.ko.json +12 -17
- package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +1 -0
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +3 -0
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/manifest.json +1 -1
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -3
- package/runtime/python/okstra_ctl/adapters/hosts/claude-code/worker-session.md +108 -0
- package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +1 -0
- package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +2 -0
- package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +2 -0
- package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +8 -1
- package/runtime/python/okstra_ctl/adapters/providers/claude/adapter.py +8 -0
- package/runtime/python/okstra_ctl/adapters/providers/codex/adapter.py +23 -6
- package/runtime/python/okstra_ctl/adapters/providers/grok/adapter.py +6 -2
- package/runtime/python/okstra_ctl/agent/invocation.py +168 -113
- package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +120 -0
- package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +107 -2
- package/runtime/python/okstra_ctl/agent/prompt_cli/run_identity.py +0 -49
- package/runtime/python/okstra_ctl/analysis_packet.py +4 -1
- package/runtime/python/okstra_ctl/application/open_worker.py +6 -1
- package/runtime/python/okstra_ctl/assignment_resolver.py +16 -5
- package/runtime/python/okstra_ctl/cmux.py +69 -20
- package/runtime/python/okstra_ctl/code_review_target.py +16 -8
- package/runtime/python/okstra_ctl/conformance.py +43 -0
- package/runtime/python/okstra_ctl/consumers.py +6 -3
- package/runtime/python/okstra_ctl/container.py +31 -8
- package/runtime/python/okstra_ctl/context_cost.py +11 -15
- package/runtime/python/okstra_ctl/contract_refreeze.py +156 -0
- package/runtime/python/okstra_ctl/convergence_critic_prompt.py +4 -6
- package/runtime/python/okstra_ctl/convergence_provenance.py +81 -18
- package/runtime/python/okstra_ctl/design_prep.py +34 -1
- package/runtime/python/okstra_ctl/dispatch_core.py +53 -27
- package/runtime/python/okstra_ctl/domain/host.py +5 -0
- package/runtime/python/okstra_ctl/domain/worker_runtime.py +10 -0
- package/runtime/python/okstra_ctl/error_report.py +4 -3
- package/runtime/python/okstra_ctl/execution_manifest.py +71 -18
- package/runtime/python/okstra_ctl/execution_mutation_audit.py +21 -21
- package/runtime/python/okstra_ctl/handoff.py +167 -277
- package/runtime/python/okstra_ctl/implementation_stage.py +9 -0
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +113 -0
- package/runtime/python/okstra_ctl/lead_progress.py +1 -1
- package/runtime/python/okstra_ctl/legacy_model_selection.py +2 -2
- package/runtime/python/okstra_ctl/manager_cli.py +175 -14
- package/runtime/python/okstra_ctl/manager_launch.py +41 -19
- package/runtime/python/okstra_ctl/manager_paths.py +22 -3
- package/runtime/python/okstra_ctl/manager_split.py +474 -0
- package/runtime/python/okstra_ctl/manager_store.py +331 -21
- package/runtime/python/okstra_ctl/manager_sync.py +37 -16
- package/runtime/python/okstra_ctl/manager_view.py +217 -0
- package/runtime/python/okstra_ctl/model_discovery.py +30 -0
- package/runtime/python/okstra_ctl/model_io/lines.py +14 -1
- package/runtime/python/okstra_ctl/model_io/renderers.py +4 -3
- package/runtime/python/okstra_ctl/models.py +1 -1
- package/runtime/python/okstra_ctl/next_phase.py +16 -6
- package/runtime/python/okstra_ctl/operation_invocation.py +86 -0
- package/runtime/python/okstra_ctl/option_comparison.py +168 -0
- package/runtime/python/okstra_ctl/path_hints.py +9 -0
- package/runtime/python/okstra_ctl/paths.py +3 -0
- package/runtime/python/okstra_ctl/plan_items_cli.py +6 -1
- package/runtime/python/okstra_ctl/profile_show.py +42 -1
- package/runtime/python/okstra_ctl/qa_commands.py +15 -0
- package/runtime/python/okstra_ctl/registry/host_discovery.py +20 -12
- package/runtime/python/okstra_ctl/registry/host_registry.py +11 -0
- package/runtime/python/okstra_ctl/render.py +50 -0
- package/runtime/python/okstra_ctl/report_contract.py +1 -1
- package/runtime/python/okstra_ctl/report_finalize.py +13 -6
- package/runtime/python/okstra_ctl/report_html/view_models/final_verification.py +2 -21
- package/runtime/python/okstra_ctl/report_html/view_models/release_handoff.py +21 -3
- package/runtime/python/okstra_ctl/report_html/visualizations.py +0 -5
- package/runtime/python/okstra_ctl/report_synthesis_packet.py +177 -17
- package/runtime/python/okstra_ctl/report_translation.py +2 -1
- package/runtime/python/okstra_ctl/report_translation_dispatch.py +69 -9
- package/runtime/python/okstra_ctl/role_requirements.py +142 -129
- package/runtime/python/okstra_ctl/rollup.py +3 -1
- package/runtime/python/okstra_ctl/run.py +76 -29
- package/runtime/python/okstra_ctl/schedule_semantics.py +17 -6
- package/runtime/python/okstra_ctl/stage_fix_carry.py +23 -4
- package/runtime/python/okstra_ctl/stage_integrate.py +178 -18
- package/runtime/python/okstra_ctl/stage_map.py +16 -2
- package/runtime/python/okstra_ctl/stage_targets.py +209 -43
- package/runtime/python/okstra_ctl/team.py +22 -13
- package/runtime/python/okstra_ctl/time_report.py +2 -1
- package/runtime/python/okstra_ctl/usage_report.py +3 -1
- package/runtime/python/okstra_ctl/verification_target.py +13 -2
- package/runtime/python/okstra_ctl/wizard/confirmation.py +3 -9
- package/runtime/python/okstra_ctl/wizard/ids.py +1 -1
- package/runtime/python/okstra_ctl/wizard/registry.py +1 -1
- package/runtime/python/okstra_ctl/wizard/state.py +3 -5
- package/runtime/python/okstra_ctl/wizard/steps_plan.py +3 -23
- package/runtime/python/okstra_ctl/worker_prompt_contract.py +5 -1
- package/runtime/python/okstra_ctl/worker_prompt_headers.py +35 -7
- package/runtime/python/okstra_ctl/worker_prompt_policy.py +66 -48
- package/runtime/python/okstra_ctl/workflow.py +1 -1
- package/runtime/python/okstra_ctl/worktree/__init__.py +3 -1
- package/runtime/python/okstra_ctl/worktree/naming.py +9 -0
- package/runtime/python/okstra_ctl/worktree_registry.py +38 -9
- package/runtime/python/okstra_token_usage/pricing.py +6 -4
- package/runtime/schemas/agent-common-v1.schema.json +34 -0
- package/runtime/schemas/agent-duty-v1.schema.json +38 -0
- package/runtime/schemas/agent-operation-v1.schema.json +11 -0
- package/runtime/schemas/agent-profile-v1.schema.json +46 -0
- package/runtime/schemas/agent-role-v1.schema.json +29 -0
- package/runtime/schemas/final-report-v2.0.schema.json +118 -97
- package/runtime/schemas/final-report-v3.0.schema.json +118 -97
- package/runtime/skills/okstra-brief-gen/SKILL.md +84 -4
- package/runtime/skills/okstra-chat/SKILL.md +2 -2
- package/runtime/skills/okstra-code-review/SKILL.md +23 -9
- package/runtime/skills/okstra-container-build/SKILL.md +10 -10
- package/runtime/skills/okstra-inspect/SKILL.md +1 -1
- package/runtime/skills/okstra-inspect/facets/cost.md +1 -1
- package/runtime/skills/okstra-inspect/facets/error-zip.md +9 -9
- package/runtime/skills/okstra-inspect/facets/errors.md +16 -16
- package/runtime/skills/okstra-inspect/facets/logs.md +7 -7
- package/runtime/skills/okstra-inspect/facets/recap.md +2 -2
- package/runtime/skills/okstra-inspect/facets/report.md +1 -1
- package/runtime/skills/okstra-inspect/facets/status.md +4 -3
- package/runtime/skills/okstra-inspect/facets/time.md +11 -10
- package/runtime/skills/okstra-manager/SKILL.md +70 -5
- package/runtime/skills/okstra-pr-gen/SKILL.md +6 -5
- package/runtime/skills/okstra-rollup/SKILL.md +5 -5
- package/runtime/skills/okstra-run/SKILL.md +32 -13
- package/runtime/skills/okstra-schedule-gen/SKILL.md +19 -14
- package/runtime/skills/okstra-setup/SKILL.md +21 -10
- package/runtime/skills/okstra-setup/references/project-config.md +7 -6
- package/runtime/skills/okstra-usage/SKILL.md +1 -1
- package/runtime/skills/okstra-user-response/SKILL.md +1 -1
- package/runtime/templates/manager/view.template.html +109 -0
- package/runtime/templates/report-writer-prompt-preamble.md +8 -0
- package/runtime/templates/reports/brief.template.md +14 -4
- package/runtime/templates/reports/html/i18n/en.json +7 -4
- package/runtime/templates/reports/html/i18n/ko.json +7 -4
- package/runtime/templates/reports/html/tasks/final-verification.template.html +2 -2
- package/runtime/templates/reports/html/tasks/release-handoff.template.html +8 -5
- package/runtime/templates/reports/i18n/en.json +1 -1
- package/runtime/templates/reports/md/tasks/release-handoff.template.md +1 -1
- package/runtime/templates/reports/release-handoff-input.template.md +6 -4
- package/runtime/templates/translator-prompt-preamble.md +36 -0
- package/runtime/validators/checks/validate-assets-01.py +7 -8
- package/runtime/validators/validate-brief.py +77 -2
- package/runtime/validators/validate-implementation-plan-stages.py +2 -1
- package/runtime/validators/validate-run.py +59 -9
- package/runtime/validators/validate-schedule.py +9 -0
- package/docs/for-ai/README.md +0 -68
- package/docs/for-ai/skills/okstra-brief-gen.md +0 -262
- package/docs/for-ai/skills/okstra-chat.md +0 -34
- package/docs/for-ai/skills/okstra-code-review.md +0 -57
- package/docs/for-ai/skills/okstra-container-build.md +0 -129
- package/docs/for-ai/skills/okstra-inspect.md +0 -262
- package/docs/for-ai/skills/okstra-manager.md +0 -69
- package/docs/for-ai/skills/okstra-memory.md +0 -126
- package/docs/for-ai/skills/okstra-pr-gen.md +0 -49
- package/docs/for-ai/skills/okstra-rollup.md +0 -114
- package/docs/for-ai/skills/okstra-run.md +0 -250
- package/docs/for-ai/skills/okstra-schedule-gen.md +0 -240
- package/docs/for-ai/skills/okstra-setup.md +0 -158
- package/docs/for-ai/skills/okstra-usage.md +0 -29
- package/docs/for-ai/skills/okstra-user-response.md +0 -72
- package/runtime/agents/workers/claude-worker.md +0 -128
- package/runtime/agents/workers/report-writer-worker.md +0 -37
- package/runtime/agents/workers/translator-worker.md +0 -63
- package/runtime/prompts/duties/acceptance-critic.md +0 -44
- package/runtime/prompts/duties/acceptance-verifier.md +0 -44
- package/runtime/prompts/duties/analysis-worker.md +0 -44
- package/runtime/prompts/duties/code-reviewer.md +0 -44
- package/runtime/prompts/duties/common.md +0 -39
- package/runtime/prompts/duties/diagnosis-worker.md +0 -44
- package/runtime/prompts/duties/direction-selection-worker.md +0 -44
- package/runtime/prompts/duties/discovery-worker.md +0 -44
- package/runtime/prompts/duties/implementation-executor.md +0 -44
- package/runtime/prompts/duties/implementation-verifier.md +0 -44
- package/runtime/prompts/duties/lead.md +0 -44
- package/runtime/prompts/duties/planning-worker.md +0 -52
- package/runtime/prompts/duties/report-writer.md +0 -44
- package/runtime/prompts/duties/reverification-worker.md +0 -44
- package/runtime/prompts/duties/schedule-verifier.md +0 -44
- package/runtime/prompts/duties/scope-critic.md +0 -44
- package/runtime/prompts/duties/technical-verification-worker.md +0 -44
- package/runtime/prompts/duties/translator.md +0 -44
- package/runtime/python/okstra_ctl/pane_title.py +0 -154
|
@@ -52,7 +52,7 @@ restated a table that sat directly above or below them.
|
|
|
52
52
|
|
|
53
53
|
## Audience & authority (READ FIRST — drives everything below)
|
|
54
54
|
|
|
55
|
-
**The schedule is shared with people who do not run okstra.** It is the team's work-plan document, not a record of a run. The body names neither the tool nor its vocabulary — `okstra`, `task-group`, `task-key`, `taskType`, a run's phase names
|
|
55
|
+
**The schedule is shared with people who do not run okstra.** It is the team's work-plan document, not a record of a run. The body names neither the tool nor its vocabulary — `okstra`, `task-group`, `task-key`, `taskType`, a run's phase names. The validator refuses prose that names `okstra`, `task-group`, `task-key`, or `taskType` outside inline code; it does not check phase names or backticked tokens. The title is the work's name, the one metadata line is `> 작성일 <YYYY-MM-DD> · 대상 저장소 <repo>`, and At a Glance identifies each task by name rather than by task-id. That extends to paths: a plan often puts its own scaffolding under the run's working tree — `.okstra/…`, or the `qa/…` scratch it holds — and those are places the reader cannot open and does not own. Name the artefact instead ("계약 캡처 도구", "위반 대장") and keep the path out. Real repository paths — `package.json`, `src/**`, `eval/**`, `.github/workflows/**` — are content and stay.
|
|
56
56
|
|
|
57
57
|
**The schedule is a client-facing work plan.** It assumes the team has all permissions and can proceed without further approval. Even when the underlying per-task reports flag blocking items, missing approvals, or "items requiring user confirmation", **the schedule MUST NOT surface them** — those belong in the internal report. Never emit a decision checklist, a `#### Items requiring user confirmation` sub-section, `Done`/`Ready?`/`Blocking Decisions` columns, or checkbox lists; "Status" reflects work phase only.
|
|
58
58
|
|
|
@@ -64,13 +64,13 @@ restated a table that sat directly above or below them.
|
|
|
64
64
|
|
|
65
65
|
**The schedule must be self-contained.** Opaque codes pulled from internal reports (`FC-5`, `UC-12`, `M1`, decision-item letters, …) must not appear unresolved. Choose one per identifier: **Form A** (≤3 codes) — replace the code inline with a 5–20 character one-line description of the item; **Form B** (≥4 recurring codes) — keep the codes and emit a `## Glossary` table as the last section resolving every one. Decision-item letters (`A1`, `B2`, …) are approval items and may not appear at all. TASK-IDs listed in `## At a Glance` need neither.
|
|
66
66
|
|
|
67
|
-
**Enforced:** `validators/validate-schedule.py` `_validate_format` rejects a
|
|
67
|
+
**Enforced:** `validators/validate-schedule.py` `_validate_format` rejects a `## Consolidated User Decision Checklist` heading, a `#### 사용자 확인 필요 항목` heading, and any checkbox item; it does not detect other approval content such as `Done`/`Ready?`/`Blocking Decisions` columns or an approval-request sentence. `_check_self_contained_identifiers` rejects a decision-item code and an unresolved opaque identifier that neither Form A nor a `## Glossary` row resolves.
|
|
68
68
|
|
|
69
69
|
## Contract SSOT — template + validator
|
|
70
70
|
|
|
71
|
-
The installed template `~/.okstra/templates/reports/schedule.template.md` is the **byte-for-byte SSOT** for the output shape: frontmatter, top header block, the mandatory `##` heading list and order, per-task `Item / Detail` field labels and sub-section order, table column shapes, the ASCII Gantt format (relative day axis, plain fence, bar-only rows), the dependency-graph shapes, and the optional `## Glossary` gate. **Read the template before writing the schedule and follow it exactly** — do not re-derive section shapes from memory. Headings and field labels stay English literals regardless of the source-report language; body prose is Korean. When a section has no data, render its heading with `_none_` — never delete or reorder headings. Never emit mermaid or any graph DSL.
|
|
71
|
+
The installed template `~/.okstra/templates/reports/schedule.template.md` is the **byte-for-byte SSOT** for the output shape: frontmatter, top header block, the mandatory `##` heading list and order, per-task `Item / Detail` field labels and sub-section order, table column shapes, the ASCII Gantt format (relative day axis, plain fence, bar-only rows), the dependency-graph shapes, and the optional `## Glossary` gate. **Read the template before writing the schedule and follow it exactly** — do not re-derive section shapes from memory. Headings and field labels stay English literals regardless of the source-report language; body prose is Korean. When a section has no data, render its heading with `_none_` — never delete or reorder headings, except `## Task Dependency Graph`, which is omitted when no task depends on another (Step 5). Never emit mermaid or any graph DSL.
|
|
72
72
|
|
|
73
|
-
`~/.okstra/lib/validators/validate-schedule.py`
|
|
73
|
+
`~/.okstra/lib/validators/validate-schedule.py` enforces most of the above (heading order, field labels, controlled vocabulary — e.g. `Med-High` is the canonical risk form — forbidden translations, checkbox bans, Gantt fence rules, unresolved-code detection). It treats `## Task Dependency Graph` and `## Gantt Chart` as optional, and it does not refuse a risk, cross-task, or next-actions section (Step 4 bans them). The Step 4 ambiguous-classification rationale line is not enforced either — emit it yourself.
|
|
74
74
|
|
|
75
75
|
One computation rule the template scaffold cannot carry inline:
|
|
76
76
|
|
|
@@ -175,7 +175,7 @@ Do not render `sliceValue` — it argues why the plan sliced the work this way,
|
|
|
175
175
|
|
|
176
176
|
When the source is a Stage Map, the Gantt bars are selected stages. A row is labelled `Stage <n>` when exactly one task is scheduled, and `<TASK-ID> Stage <n>` when more than one is. Spell the stage out — `S1` costs the reader a lookup and saves five characters. A row is a label and a bar and nothing else: no `days=` annotation (the Work Breakdown owns those numbers, and the validator compares the bar against that column), and no per-row `! crit` / `est` markers, which distinguish nothing when every row carries them. One line above the fence states the column unit and what `█` and `░` mean — that is the whole legend, because those two glyphs are the only notation left. Split the task effort range proportionally by `step_count`; round every stage except the last to 0.5 day and let the last stage absorb the remainder. Cross-stage dependency annotations follow `depends_on`. Already-done and non-selected stages never get a bar. A task tagged `[NEEDS-PLANNING]` contributes no bars.
|
|
177
177
|
|
|
178
|
-
**Bar geometry is checked, not decorative.** One column is half a day: a bar runs `lower / 0.5` filled cells `█` then `(upper - lower) / 0.5` open cells `░`. A bar drawn to any other width is a validation error, as is an axis whose last tick overshoots the scheduled work by 5 days
|
|
178
|
+
**Bar geometry is checked, not decorative.** One column is half a day: a bar runs `lower / 0.5` filled cells `█` then `(upper - lower) / 0.5` open cells `░`. A bar drawn to any other width is a validation error, as is an axis whose last tick overshoots the scheduled work by more than 5 days.
|
|
179
179
|
|
|
180
180
|
**Every controlled code the schedule prints must be defined on the page.** The template's `### Priority & Risk Scale` resolves `P0`–`P3` and `Very Low`–`High`; the validator requires that subsection and both header literals. Stage labels are spelled out for the same reason — Gantt rows read `Stage 3`, and `Depends On` cells read `None` / `Stage 2` / `Stage 1 (done)` rather than a bare number the reader has to match against the Stage column of the same table. A reader who never saw the source report cannot rank `P0` against `P1`, calibrate `High`, or expand `S3`; those are opaque codes wearing a friendlier shape.
|
|
181
181
|
|
|
@@ -229,13 +229,18 @@ When you do skip, insert in the section's position exactly: `> _Gantt Chart skip
|
|
|
229
229
|
3. **Run the deterministic gate first.** Execute `python3 ~/.okstra/lib/validators/validate-schedule.py <draft> --selection-json <selection>`. Do not dispatch the narrative verifier when this exits non-zero.
|
|
230
230
|
4. **Run the independent LLM verifier second.** Only after the deterministic gate passes, create
|
|
231
231
|
`.okstra/agent-invocations/schedule-verification/<invocation-id>.instructions.md` containing the draft,
|
|
232
|
-
selection JSON, and checks below, but none of the lead's reasoning.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
232
|
+
selection JSON, and checks below, but none of the lead's reasoning. Ask the runtime what this operation
|
|
233
|
+
runs — `okstra agent-prompt resolve-operation --operation schedule-verification` prints the duty, the
|
|
234
|
+
verifier count, and each slot's provider and model; the contract owns them, so do not choose a role or
|
|
235
|
+
provider here. Materialize its sibling `.prompt.md` with
|
|
236
|
+
`okstra agent-prompt materialize`, `--purpose schedule-verification`, `--audience <dutyId>`, the
|
|
237
|
+
current host runtime, and that slot's `--provider` and `--model <modelRef>`. Run
|
|
238
|
+
`okstra agent-prompt verify` against the returned `metadataPath` before dispatch. A native host call receives the verified prompt body and `hostModelValue`; a deterministic
|
|
239
|
+
provider process runs the provider wrapper
|
|
240
|
+
`~/.okstra/bin/okstra-<provider>-exec.sh <projectRoot> <modelExecutionValue> <prompt-path>`
|
|
241
|
+
(`okstra worker-dispatch` dispatches only a run manifest's assignments, not a standalone prompt). The
|
|
242
|
+
wrapper records the provider's output in the prompt path with `.md` replaced by `.log`. These values are
|
|
243
|
+
not interchangeable.
|
|
239
244
|
The verifier returns `pass` plus concrete findings. Give it these checks:
|
|
240
245
|
- **Executable ordering** — stage sequence, `Depends On`, and Gantt bar positions tell the same story; nothing depends on something scheduled after it.
|
|
241
246
|
- **Arithmetic** — the Work Breakdown `Days` column sums to the At a Glance `Days` cell and to the `Effort sum` line.
|
|
@@ -262,7 +267,7 @@ Reached only after both Step 5.5 gates return `pass`. Promote the verified same
|
|
|
262
267
|
.okstra/tasks/<task-group-segment>/schedule/<task-group-segment>-plan-<YYYY-MM-DD_HH-MM-SS>.md
|
|
263
268
|
```
|
|
264
269
|
|
|
265
|
-
`<task-group-segment>`
|
|
270
|
+
`<task-group-segment>` is the parent directory name of the `Task root` that `okstra stage-map` printed in Step 3, used verbatim. Timestamp is current local time. Auto-create the parent directory. Never overwrite an existing file — on a same-second collision append `-2`, `-3`, ….
|
|
266
271
|
|
|
267
272
|
### Step 7: Self-validate before reporting completion
|
|
268
273
|
|
|
@@ -301,7 +306,7 @@ Reached only after both Step 5.5 gates return `pass`. Promote the verified same
|
|
|
301
306
|
| either validation gate still fails after two revisions | Final file not written; report residual findings to the user |
|
|
302
307
|
| `task-group` matches no tasks | "That task-group could not be found." and stop |
|
|
303
308
|
| Catalog and manifest disagree on `workStatus` | Manifest wins (catalog may be stale) |
|
|
304
|
-
| task-group casing / punctuation variants |
|
|
309
|
+
| task-group casing / punctuation variants | `schedule-input` matches them: it lowercases the argument and the group part of each catalog task key and drops every non-alphanumeric character (Unicode letters and digits stay); use the Step 6 segment verbatim for path output |
|
|
305
310
|
|
|
306
311
|
## Output Rules
|
|
307
312
|
|
|
@@ -96,18 +96,19 @@ targets; follow the host's permission mechanism if either remains blocked.
|
|
|
96
96
|
okstra preflight --runtime <host-runtime>
|
|
97
97
|
```
|
|
98
98
|
|
|
99
|
-
Read the fixed `Okstra preflight
|
|
100
|
-
`
|
|
99
|
+
Read the fixed `Okstra preflight` line. On `Okstra preflight: ready` the output
|
|
100
|
+
carries `Project ID` and `Project root`; on `Okstra preflight: failed` it carries
|
|
101
|
+
`Stage`, `Reason`, and `Recovery`, and no `Project root` line.
|
|
101
102
|
|
|
102
|
-
- `
|
|
103
|
-
- `
|
|
103
|
+
- `Okstra preflight: ready` → carry `Project root` as a literal absolute string and paste it into every subsequent command in this skill.
|
|
104
|
+
- `Okstra preflight: failed`, `Stage: resolve` → ask the user (`AskUserQuestion`, free text) for an absolute project root and rerun as a separate Bash tool call with the literal absolute path:
|
|
104
105
|
|
|
105
106
|
```bash
|
|
106
107
|
okstra preflight --runtime <host-runtime> --cwd /abs/path/from/user
|
|
107
108
|
```
|
|
108
109
|
|
|
109
|
-
- `
|
|
110
|
-
- `
|
|
110
|
+
- `Okstra preflight: failed`, `Stage: project_json_missing` → proceed to Step 3 (this is the normal create path). The project root appears only inside the `Reason` path (`<root>/.okstra/project.json not found — ...`); take the root from that path.
|
|
111
|
+
- `Okstra preflight: failed`, any other `Stage` (`install`, `helper_scripts_missing`, `python`, `parse`, `project_json_invalid`, `runtime_readiness`) → show the fixed `Reason` line to the user verbatim and follow the `Recovery` line (typically `okstra doctor --runtime <host-runtime>` to diagnose, then `okstra ensure-installed --runtime <host-runtime>` or re-running the Step 1 install). `Reason` is the SSOT — do not hand-enumerate stage causes.
|
|
111
112
|
|
|
112
113
|
## Step 3: Project metadata setup
|
|
113
114
|
|
|
@@ -129,10 +130,11 @@ If the file does NOT exist, ask via `AskUserQuestion`:
|
|
|
129
130
|
|
|
130
131
|
- **Question**: `"Project id for okstra (e.g. INV-1234, my-app, okstra)"`
|
|
131
132
|
- **Validate**: the answer must be non-empty AND contain at least one
|
|
132
|
-
alphanumeric character. Re-ask on empty input — `okstra setup
|
|
133
|
-
|
|
134
|
-
`
|
|
135
|
-
|
|
133
|
+
alphanumeric character. Re-ask on empty input — `okstra setup` exits 1
|
|
134
|
+
on an empty `--project-id` value or an id with no alphanumeric character,
|
|
135
|
+
and `okstra setup --yes` with no `--project-id` and no existing
|
|
136
|
+
`project.json` exits 1 with
|
|
137
|
+
`error: --project-id is required (no existing project.json, not a TTY)`.
|
|
136
138
|
|
|
137
139
|
Then create the file — paste the literal `projectRoot` from Step 2 and the literal `projectId` from the user's answer (no shell variables):
|
|
138
140
|
|
|
@@ -140,6 +142,15 @@ Then create the file — paste the literal `projectRoot` from Step 2 and the lit
|
|
|
140
142
|
okstra setup --yes --project-root /abs/path/to/projectRoot --project-id my-project-id
|
|
141
143
|
```
|
|
142
144
|
|
|
145
|
+
`okstra setup` also refreshes the okstra-managed citation-guidance block in
|
|
146
|
+
`<PROJECT_ROOT>/CLAUDE.md` and `AGENTS.md` when those files already exist (it never
|
|
147
|
+
creates them). The block tells agents not to carry okstra-internal references — report
|
|
148
|
+
section numbers, `C-NNN` clarification ids, run/stage ids, `.okstra/...` paths — into
|
|
149
|
+
writing that is not an okstra report, where the reader cannot resolve them. The command
|
|
150
|
+
reports the files it touched in its JSON `citationGuidance` array; a failure there is a
|
|
151
|
+
`warning:` line, not a non-zero exit. Tell the user which guidance files were updated so
|
|
152
|
+
they can review the appended block.
|
|
153
|
+
|
|
143
154
|
## Step 3.5 (optional): project customisation
|
|
144
155
|
|
|
145
156
|
The built-in defaults work for most projects — skip straight to Step 4
|
|
@@ -81,8 +81,9 @@ form only. Representative denied tokens: `--fix` / `--write` (formatters),
|
|
|
81
81
|
(`_DENIED_LITERAL_TOKENS` / `_DENIED_SUBSTRINGS` plus the dynamic
|
|
82
82
|
`npm install` and `INSTA_UPDATE=` checks) — do not re-enumerate it here.
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
`
|
|
84
|
+
A declared denied token makes okstra refuse to prepare an `implementation`
|
|
85
|
+
or `final-verification` run, with an error naming the token (other task types
|
|
86
|
+
do not read `qaCommands`); re-declare the command in check-only form to recover
|
|
86
87
|
(e.g. swap `prettier --write` → `prettier --check`).
|
|
87
88
|
|
|
88
89
|
The field is preserved across the runtime's auto-upserts of `project.json`, so
|
|
@@ -134,7 +135,7 @@ and `validators/validate-run.py::_validate_conformance`.
|
|
|
134
135
|
|
|
135
136
|
## C. Project-local Claude settings symlink and workspace trust
|
|
136
137
|
|
|
137
|
-
`okstra setup` (and `okstra run`
|
|
138
|
+
`okstra setup` (and every `okstra run` prepare that is not render-only)
|
|
138
139
|
provisions `<PROJECT_ROOT>/.claude/settings.local.json` as a symlink to
|
|
139
140
|
`~/.okstra/templates/settings.local.json`. The template contains the Bash
|
|
140
141
|
permission rules required for the codex/antigravity worker wrappers:
|
|
@@ -159,9 +160,9 @@ If a non-symlink `.claude/settings.local.json` already exists, setup backs it
|
|
|
159
160
|
up to `.claude/settings.local.json.bak.<timestamp>` before installing the
|
|
160
161
|
symlink — surface that to the user so they can merge project-specific rules
|
|
161
162
|
back (the symlinked template is okstra-owned and refreshed on okstra updates).
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
There is no persistent opt-out: a regular file or foreign symlink put in
|
|
164
|
+
its place is backed up as `.bak.<timestamp>` and replaced with the symlink on
|
|
165
|
+
the next `okstra setup` or run prepare.
|
|
165
166
|
|
|
166
167
|
## D. Project PR body template (release-handoff)
|
|
167
168
|
|
|
@@ -10,7 +10,7 @@ description: >-
|
|
|
10
10
|
|
|
11
11
|
# OKSTRA Usage
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Project usage snapshot. The skill itself writes nothing. `okstra usage-report` resolves every catalog task by task-key, and that lookup self-heals a finished implementation phase. When a task's current phase is `implementation`, that lookup appends a `done` row to `runs/implementation-planning/consumers.jsonl` for each stage whose carry file is complete but has no settled row, and when every stage of the latest plan has a `done` row and a pass-grade carry it marks the phase completed in `task-manifest.json` (`workflow`, `phaseOutcome.implementation`) and refreshes that task's catalog entry. Nothing else is written. The CLI owns every sum; never re-add rows.
|
|
14
14
|
|
|
15
15
|
## Step 0: Preflight
|
|
16
16
|
|
|
@@ -156,7 +156,7 @@ Every value, rationale, and reason body file must be a regular file under `<proj
|
|
|
156
156
|
okstra user-response answer --transaction <transaction> --clarification-id <C-NNN> --kind <kind> --disposition <disposition> --value-file <value.md> [--rationale-file <rationale.md>]
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
-
The two answer forms are mutually exclusive. The command validates that the clarification ID
|
|
159
|
+
The two answer forms are mutually exclusive. The command validates that the clarification ID exists once in the selected report, that its kind matches, and that its status is `open` or `answered` — an item answered in an earlier response can be answered again. Within one transaction, a repeated answer for the same ID replaces the earlier one, so repeating the same command is safe.
|
|
160
160
|
|
|
161
161
|
## Step 6: Record an explicit decision when present
|
|
162
162
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>{{TITLE}}</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #f7f7f5;
|
|
10
|
+
--panel: #ffffff;
|
|
11
|
+
--text: #1f2328;
|
|
12
|
+
--muted: #5f6670;
|
|
13
|
+
--line: #d9dbde;
|
|
14
|
+
--planned: #6e7781;
|
|
15
|
+
--missing: #9a6700;
|
|
16
|
+
--running: #0969da;
|
|
17
|
+
--done: #1a7f37;
|
|
18
|
+
--blocked: #cf222e;
|
|
19
|
+
}
|
|
20
|
+
@media (prefers-color-scheme: dark) {
|
|
21
|
+
:root {
|
|
22
|
+
--bg: #111418;
|
|
23
|
+
--panel: #1a1f25;
|
|
24
|
+
--text: #e6e8eb;
|
|
25
|
+
--muted: #9aa3ad;
|
|
26
|
+
--line: #2f363e;
|
|
27
|
+
--planned: #8b949e;
|
|
28
|
+
--missing: #d29922;
|
|
29
|
+
--running: #58a6ff;
|
|
30
|
+
--done: #3fb950;
|
|
31
|
+
--blocked: #f85149;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
* { box-sizing: border-box; }
|
|
35
|
+
body {
|
|
36
|
+
margin: 0;
|
|
37
|
+
background: var(--bg);
|
|
38
|
+
color: var(--text);
|
|
39
|
+
font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "Apple SD Gothic Neo", "Noto Sans KR", sans-serif;
|
|
40
|
+
}
|
|
41
|
+
main { max-width: 1200px; margin: 0 auto; padding: 24px 16px 48px; }
|
|
42
|
+
header h1 { margin: 0 0 4px; font-size: 22px; }
|
|
43
|
+
.meta { color: var(--muted); font-size: 13px; }
|
|
44
|
+
section { margin-top: 28px; }
|
|
45
|
+
h2 { font-size: 17px; margin: 0 0 10px; }
|
|
46
|
+
h3 { font-size: 15px; margin: 0; }
|
|
47
|
+
.panel {
|
|
48
|
+
background: var(--panel);
|
|
49
|
+
border: 1px solid var(--line);
|
|
50
|
+
border-radius: 8px;
|
|
51
|
+
padding: 16px;
|
|
52
|
+
margin-bottom: 16px;
|
|
53
|
+
}
|
|
54
|
+
.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; }
|
|
55
|
+
.tile { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 10px 12px; }
|
|
56
|
+
.tile .count { font-size: 24px; font-weight: 600; }
|
|
57
|
+
.tile .label { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; }
|
|
58
|
+
.scroll { overflow-x: auto; }
|
|
59
|
+
table { width: 100%; border-collapse: collapse; }
|
|
60
|
+
th, td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--line); vertical-align: top; }
|
|
61
|
+
th { color: var(--muted); font-weight: 600; font-size: 12px; white-space: nowrap; }
|
|
62
|
+
.wrap { display: inline-block; min-width: 220px; }
|
|
63
|
+
code.id { white-space: nowrap; word-break: normal; }
|
|
64
|
+
code { font: 12px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; word-break: break-all; }
|
|
65
|
+
.chip {
|
|
66
|
+
display: inline-block;
|
|
67
|
+
padding: 1px 8px;
|
|
68
|
+
border-radius: 999px;
|
|
69
|
+
border: 1px solid currentColor;
|
|
70
|
+
font-size: 12px;
|
|
71
|
+
white-space: nowrap;
|
|
72
|
+
}
|
|
73
|
+
.chip.planned { color: var(--planned); }
|
|
74
|
+
.chip.missing { color: var(--missing); }
|
|
75
|
+
.chip.running { color: var(--running); }
|
|
76
|
+
.chip.done { color: var(--done); }
|
|
77
|
+
.chip.blocked { color: var(--blocked); }
|
|
78
|
+
.chip.unlinked { color: var(--missing); }
|
|
79
|
+
.task-head { display: flex; flex-wrap: wrap; gap: 8px 16px; align-items: baseline; margin-bottom: 8px; }
|
|
80
|
+
.counts { display: flex; flex-wrap: wrap; gap: 6px; }
|
|
81
|
+
.hint { color: var(--muted); font-size: 12px; margin: 6px 0 12px; }
|
|
82
|
+
details { margin-top: 10px; }
|
|
83
|
+
summary { cursor: pointer; color: var(--muted); }
|
|
84
|
+
ul.plain { margin: 6px 0 0; padding-left: 18px; }
|
|
85
|
+
.empty { color: var(--muted); }
|
|
86
|
+
a { color: var(--running); }
|
|
87
|
+
</style>
|
|
88
|
+
</head>
|
|
89
|
+
<body>
|
|
90
|
+
<main>
|
|
91
|
+
<header>
|
|
92
|
+
<h1>{{TITLE}}</h1>
|
|
93
|
+
<div class="meta">{{META}}</div>
|
|
94
|
+
</header>
|
|
95
|
+
<section>
|
|
96
|
+
<h2>Summary</h2>
|
|
97
|
+
{{SUMMARY}}
|
|
98
|
+
</section>
|
|
99
|
+
<section>
|
|
100
|
+
<h2>Projects</h2>
|
|
101
|
+
{{PROJECTS}}
|
|
102
|
+
</section>
|
|
103
|
+
<section>
|
|
104
|
+
<h2>Manager tasks</h2>
|
|
105
|
+
{{TASKS}}
|
|
106
|
+
</section>
|
|
107
|
+
</main>
|
|
108
|
+
</body>
|
|
109
|
+
</html>
|
|
@@ -42,6 +42,14 @@ The synthesis packet's Authoring Contract names which of these are **required**
|
|
|
42
42
|
|
|
43
43
|
Any other top-level name is rejected however reasonable it reads — a section title copied out of a lead procedure document (`Clarification Response Carried In`, `Stage Map`, `Rollback Strategy`) is a heading in that document, not a top-level field here. Nested names come from the task's block in `schemas/final-report-v3.0.schema.json`; when a name is refused, the parser's message lists the names allowed at that exact position, so correct against that list rather than guessing a second time.
|
|
44
44
|
|
|
45
|
+
**Implementation-planning direction branch.** A selected-direction narrative carries `selectedDirectionRef` and `directionRealization`; the `P-Dir-1` verifier checks that realization against the selected core mechanism, architecture boundaries, planning invariants, and any hidden direction change. A legacy candidate-comparison narrative retains `P-Opt-*` option comparison semantics. These are plan-body judgments, not frontmatter fields owned by the writer. Four `directionRealization` fields — `coreMechanism`, `architectureBoundaries`, `planningInvariants`, `userConstraints` — are verbatim copies of the selected-direction snapshot and report assembly overwrites them from that snapshot at publication: do not paraphrase them; spend the writing on the fields the writer actually owns (`fileStructure` and the other realization fields).
|
|
46
|
+
|
|
47
|
+
**Implementation-option-selection comparison.** Candidate details remain direction-level and must not claim planning precision:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{"candidateDetailBoundary":{"expectedChangeAreas":"direction-level-only","expectedVerification":"direction-level-signals-only","forbidden":["exact-file-lists","stage-lists","test-commands"]}}
|
|
51
|
+
```
|
|
52
|
+
|
|
45
53
|
## Pointer record
|
|
46
54
|
|
|
47
55
|
The pointer record names the project-relative narrative path and audit sidecar path. It does not contain the narrative, worker result corpus, or any machine-owned ledger.
|
|
@@ -34,10 +34,15 @@ candidate-cap: 8 # codebase-scan only: 1..12, de
|
|
|
34
34
|
|
|
35
35
|
<!-- author guidance — strip out at fill-in time:
|
|
36
36
|
Paste each source separately and as-is. No paraphrasing, summarizing, or
|
|
37
|
-
restructuring.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
restructuring. Length is never a reason to excerpt: capture the record in
|
|
38
|
+
full — for a ticket that means title, body, every comment, status, labels,
|
|
39
|
+
assignee and linked/child issue references, not the body alone. Format
|
|
40
|
+
conversion (e.g. Jira ADF -> Markdown) is allowed and must be annotated in
|
|
41
|
+
the header meta. Anything the fetch could not deliver (a truncated body, an
|
|
42
|
+
attachment returned as a link, an opaque embed node) gets a
|
|
43
|
+
`conversion-block:` row in Open Questions naming what is missing. Heading was
|
|
44
|
+
originally "Source Material (verbatim — do not modify)" — the parenthetical
|
|
45
|
+
is a reviewer note, not body text.
|
|
41
46
|
-->
|
|
42
47
|
|
|
43
48
|
### Source 1 — <type: file | linear | jira | github | notion | url | user-input>
|
|
@@ -145,6 +150,11 @@ than downstream. -->
|
|
|
145
150
|
|
|
146
151
|
## Constraints
|
|
147
152
|
|
|
153
|
+
<!-- Author guidance: this section also records what the source asked for and
|
|
154
|
+
this task deliberately leaves out. One bullet per dropped item, written as
|
|
155
|
+
`out of scope: <the source's item> — <why>`. Dropping a source requirement
|
|
156
|
+
without that line is indistinguishable from overlooking it. -->
|
|
157
|
+
|
|
148
158
|
<Deadlines, compatibility, technical/operational limits. Use _(none)_ if
|
|
149
159
|
none.>
|
|
150
160
|
|
|
@@ -57,10 +57,6 @@
|
|
|
57
57
|
"brief": "Brief",
|
|
58
58
|
"clarification": "Your answer"
|
|
59
59
|
},
|
|
60
|
-
"handoffMode": {
|
|
61
|
-
"whole-task": "Whole task",
|
|
62
|
-
"stage-group": "Selected stages"
|
|
63
|
-
},
|
|
64
60
|
"workerStatus": {
|
|
65
61
|
"completed": "Completed",
|
|
66
62
|
"error": "Failed",
|
|
@@ -371,6 +367,8 @@
|
|
|
371
367
|
"final-verification": {
|
|
372
368
|
"verification-verdict": "Verification verdict",
|
|
373
369
|
"result-per-requirement": "Result per requirement",
|
|
370
|
+
"requirement": "Requirement",
|
|
371
|
+
"evidence": "Evidence",
|
|
374
372
|
"what-the-change-added": "What the change added",
|
|
375
373
|
"traced-to": "Serves",
|
|
376
374
|
"callers": "Callers",
|
|
@@ -650,6 +648,11 @@
|
|
|
650
648
|
"handoff-scope": "Handoff scope",
|
|
651
649
|
"the-behaviour-you-chose": "The behaviour you chose",
|
|
652
650
|
"handoff-mode": "Handoff mode",
|
|
651
|
+
"stages-shipped": "Stages shipped:",
|
|
652
|
+
"release-base": "Release base:",
|
|
653
|
+
"stage": "Stage",
|
|
654
|
+
"pr-head": "PR head branch",
|
|
655
|
+
"pr-base": "PR base branch",
|
|
653
656
|
"conflict-check": "Conflict check",
|
|
654
657
|
"pr-body": "PR Body",
|
|
655
658
|
"branch-and-pr": "Branch and PR",
|
|
@@ -57,10 +57,6 @@
|
|
|
57
57
|
"brief": "브리프",
|
|
58
58
|
"clarification": "사용자 답변"
|
|
59
59
|
},
|
|
60
|
-
"handoffMode": {
|
|
61
|
-
"whole-task": "태스크 전체",
|
|
62
|
-
"stage-group": "선택한 stage"
|
|
63
|
-
},
|
|
64
60
|
"workerStatus": {
|
|
65
61
|
"completed": "완료",
|
|
66
62
|
"error": "실패",
|
|
@@ -371,6 +367,8 @@
|
|
|
371
367
|
"final-verification": {
|
|
372
368
|
"verification-verdict": "검증 판정",
|
|
373
369
|
"result-per-requirement": "요구사항별 결과",
|
|
370
|
+
"requirement": "요구사항",
|
|
371
|
+
"evidence": "근거",
|
|
374
372
|
"what-the-change-added": "이 변경이 추가한 것",
|
|
375
373
|
"traced-to": "봉사하는 요구사항",
|
|
376
374
|
"callers": "호출자",
|
|
@@ -650,6 +648,11 @@
|
|
|
650
648
|
"handoff-scope": "인계 범위",
|
|
651
649
|
"the-behaviour-you-chose": "선택한 동작",
|
|
652
650
|
"handoff-mode": "인계 방식",
|
|
651
|
+
"stages-shipped": "내보낸 stage:",
|
|
652
|
+
"release-base": "릴리스 base:",
|
|
653
|
+
"stage": "stage",
|
|
654
|
+
"pr-head": "PR head 브랜치",
|
|
655
|
+
"pr-base": "PR base 브랜치",
|
|
653
656
|
"conflict-check": "충돌 확인",
|
|
654
657
|
"pr-body": "PR 본문",
|
|
655
658
|
"branch-and-pr": "브랜치와 PR",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
{% extends "html/base.template.html" %}
|
|
2
2
|
{% from "html/macros/layout.html" import narrative as render_narrative, row_key %}
|
|
3
|
-
{% from "html/macros/visualizations.html" import figure %}
|
|
4
3
|
|
|
5
4
|
{% block human_content %}
|
|
6
5
|
<section data-report-section="verification-verdict">
|
|
@@ -22,7 +21,8 @@
|
|
|
22
21
|
<section data-report-section="requirement-results" data-report-field="finalVerification.validationEvidence">
|
|
23
22
|
<h2>{{ t('tasks.final-verification.result-per-requirement') }}</h2>
|
|
24
23
|
{{ render_narrative(narrative.coverageExplanation, "finalVerification.userNarrative.coverageExplanation") }}
|
|
25
|
-
{{
|
|
24
|
+
<div class="table-scroll"><table><thead><tr><th>{{ t('macros.layout.id') }}</th><th>{{ t('tasks.final-verification.requirement') }}</th><th>{{ t('macros.layout.status') }}</th><th>{{ t('tasks.final-verification.evidence') }}</th></tr></thead>
|
|
25
|
+
<tbody>{% for row in final.validationEvidence %}<tr id="id-{{ row.id }}"><td>{{ row.id | inline_code }}</td><td>{{ row.requirement | inline_code }}</td><td><span class="status status-{{ row.status }}">{{ row.status }}</span></td><td>{{ row.artifact | inline_code }}</td></tr>{% endfor %}</tbody></table></div>
|
|
26
26
|
</section>
|
|
27
27
|
|
|
28
28
|
<section data-report-section="added-surface" data-report-field="finalVerification.addedSurfaceAudit">
|
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
{% if handoff.get("handoffScope") %}
|
|
13
13
|
<section data-report-section="handoff-scope" data-report-field="releaseHandoff.handoffScope">
|
|
14
14
|
<h2>{{ t('tasks.release-handoff.handoff-scope') }}</h2>
|
|
15
|
-
<p><strong>{{ handoff.
|
|
15
|
+
<p><strong>{{ t('tasks.release-handoff.stages-shipped') }}</strong> {{ handoff.handoffScope.stages | join(", ") }} · {{ t('tasks.release-handoff.release-base') }} <code>{{ handoff.handoffScope.releaseBase }}</code></p>
|
|
16
|
+
{% if handoff.handoffScope.get("stagePlan") %}
|
|
17
|
+
<table><thead><tr><th>{{ t('tasks.release-handoff.stage') }}</th><th>{{ t('tasks.release-handoff.pr-head') }}</th><th>{{ t('tasks.release-handoff.pr-base') }}</th></tr></thead><tbody>{% for row in handoff.handoffScope.stagePlan %}<tr><td>{{ row.stage }}</td><td><code>{{ row.headBranch }}</code></td><td><code>{{ row.baseBranch }}</code> ({{ row.baseKind }})</td></tr>{% endfor %}</tbody></table>
|
|
18
|
+
{% endif %}
|
|
16
19
|
</section>
|
|
17
20
|
{% endif %}
|
|
18
21
|
|
|
@@ -25,22 +28,22 @@
|
|
|
25
28
|
<h2>{{ t('tasks.release-handoff.branch-and-pr') }}</h2>
|
|
26
29
|
{{ render_narrative(narrative.branchAndPrExplanation, "releaseHandoff.userNarrative.branchAndPrExplanation") }}
|
|
27
30
|
<p><strong>{{ t('tasks.release-handoff.branch') }}</strong> {{ handoff.featureBranchState.branchName }}</p>
|
|
28
|
-
<
|
|
31
|
+
<ul data-report-field="releaseHandoff.pullRequestOutcomes">{% for row in prOutcomes %}<li><strong>{{ t('tasks.release-handoff.pr-result') }}</strong> stage {{ row.stage }} — {{ row.kind }}{% if row.get("baseBranch") %} → <code>{{ row.baseBranch }}</code>{% endif %}{% if row.get("url") %} · <a href="{{ row.url }}" rel="noopener noreferrer">{{ t('tasks.release-handoff.pull-request-open') }}</a>{% endif %}{% if row.get("reason") %} · {{ row.reason }}{% endif %}</li>{% endfor %}</ul>
|
|
29
32
|
</section>
|
|
30
33
|
|
|
31
34
|
<section data-report-section="conflicts" data-report-field="releaseHandoff.mergeConflictProbe">
|
|
32
35
|
<h2>{{ t('tasks.release-handoff.conflict-verdict') }}</h2>
|
|
33
36
|
{{ render_narrative(narrative.conflictExplanation, "releaseHandoff.userNarrative.conflictExplanation") }}
|
|
34
37
|
{{ summary_card(handoff.mergeConflictProbe.kind, t('tasks.release-handoff.base-branch') ~ " " ~ (handoff.mergeConflictProbe.baseBranch | default('not-run'))) }}
|
|
38
|
+
{% if handoff.mergeConflictProbe.get("conflictingStages") %}<p>{{ t('tasks.release-handoff.stage') }} {{ handoff.mergeConflictProbe.conflictingStages | join(", ") }}</p>{% endif %}
|
|
35
39
|
{% if handoff.mergeConflictProbe.get("conflictingPaths") %}<ul>{% for path in handoff.mergeConflictProbe.conflictingPaths %}<li>{{ path }}</li>{% endfor %}</ul>{% endif %}
|
|
36
40
|
</section>
|
|
37
41
|
|
|
38
42
|
<section data-report-section="delivered-commits" data-report-field="releaseHandoff.commitList">
|
|
39
43
|
<h2>{{ t('tasks.release-handoff.commits-delivered') }}</h2>
|
|
40
44
|
{% if handoff.commitList is mapping %}<p>{{ t('tasks.release-handoff.there-are-no-commits') }}</p>{% else %}
|
|
41
|
-
<table><thead><tr><th>{{ t('tasks.release-handoff.commit') }}</th><th>{{ t('tasks.release-handoff.subject') }}</th><th>{{ t('tasks.release-handoff.files') }}</th></tr></thead><tbody>{% for row in handoff.commitList %}<tr>{{ row_key(pairs=[(t('macros.layout.sha'), row.shortSha), (t('macros.layout.order'), loop.index)]) }}<td>{{ row.subject | inline_code }}</td><td>{{ file_paths(row.files) }}</td></tr>{% endfor %}</tbody></table>{% endif %}
|
|
42
|
-
|
|
43
|
-
{% else %}<p data-report-field="releaseHandoff.sourceVerificationReport"><strong>{{ t('tasks.release-handoff.the-verification-report-this-rests-on') }}</strong> — <code>{{ handoff.sourceVerificationReport.path }}</code> · {{ handoff.sourceVerificationReport.verdictTokenQuote | inline_code }}</p>{% endif %}
|
|
45
|
+
<table><thead><tr><th>{{ t('tasks.release-handoff.stage') }}</th><th>{{ t('tasks.release-handoff.commit') }}</th><th>{{ t('tasks.release-handoff.subject') }}</th><th>{{ t('tasks.release-handoff.files') }}</th></tr></thead><tbody>{% for row in handoff.commitList %}<tr><td>{{ row.get("stage", "") }}</td>{{ row_key(pairs=[(t('macros.layout.sha'), row.shortSha), (t('macros.layout.order'), loop.index)]) }}<td>{{ row.subject | inline_code }}</td><td>{{ file_paths(row.files) }}</td></tr>{% endfor %}</tbody></table>{% endif %}
|
|
46
|
+
<p data-report-field="releaseHandoff.sourceVerificationReports"><strong>{{ t('tasks.release-handoff.the-verification-report-this-rests-on') }}</strong>{% for row in handoff.sourceVerificationReports %} — stage {{ row.stage }}: <code>{{ row.path }}</code> · {{ row.verdictTokenQuote | inline_code }}{% endfor %}</p>
|
|
44
47
|
</section>
|
|
45
48
|
|
|
46
49
|
<section data-report-section="next-action">
|
|
@@ -239,7 +239,7 @@
|
|
|
239
239
|
"allowedOptions": "Allowed options"
|
|
240
240
|
},
|
|
241
241
|
"h1Body": "Which action should run?",
|
|
242
|
-
"h2Body": "
|
|
242
|
+
"h2Body": "Release base branch (when H1 = `push + PR`)",
|
|
243
243
|
"h3Body": "How should the PR title/body draft be handled?",
|
|
244
244
|
"h2DefaultLabel": "(n/a)",
|
|
245
245
|
"h2OptionsLabel": "staging / preprod / main / user input",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
{{ s.section("releaseHandoff.handoffScope", "Handoff Scope") }}
|
|
7
7
|
{{ s.section("releaseHandoff.userSelections", "User Selections") }}
|
|
8
8
|
{{ s.section("releaseHandoff.featureBranchState", "Feature Branch State") }}
|
|
9
|
-
{{ s.section("releaseHandoff.
|
|
9
|
+
{{ s.section("releaseHandoff.pullRequestOutcomes", "Pull Request Outcomes") }}
|
|
10
10
|
{{ s.section("releaseHandoff.mergeConflictProbe", "Merge Conflict Probe") }}
|
|
11
11
|
{{ s.section("releaseHandoff.executedCommands", "Executed Commands") }}
|
|
12
12
|
{{ s.section("releaseHandoff.routingRecommendation", "Routing Recommendation") }}
|
|
@@ -25,8 +25,7 @@ taskType: "{{FM_TASK_TYPE}}"
|
|
|
25
25
|
|
|
26
26
|
## Source Verification Report
|
|
27
27
|
|
|
28
|
-
-
|
|
29
|
-
- Stages: `{{HANDOFF_STAGES}}`
|
|
28
|
+
- Stages: `{{HANDOFF_STAGES}}` — one PR per stage.
|
|
30
29
|
- Reports (one row per cited `final-verification` final-report; the verdict must be release-ready).
|
|
31
30
|
**Enforced:** `validators/validate-run.py` routes through
|
|
32
31
|
`okstra_ctl.release_gate.release_handoff_allowed`, which passes `accepted` and
|
|
@@ -47,11 +46,14 @@ taskType: "{{FM_TASK_TYPE}}"
|
|
|
47
46
|
- Existing implementation commits (`git log --oneline <base>..HEAD`):
|
|
48
47
|
- Existing PR for this head, if any (`gh pr list --head <branch> --state open --json url --jq '.[0].url'`):
|
|
49
48
|
|
|
50
|
-
## Candidate
|
|
49
|
+
## Candidate Release Base Branches
|
|
50
|
+
|
|
51
|
+
The user picks ONE release base for the whole run. Each stage's own PR base is then derived from its `depends-on` by `okstra handoff pr-plan`: a stage with no live dependency targets the release base, a stage with one targets that stage's branch (a stacked PR), and a stage with several targets a branch merging them.
|
|
51
52
|
|
|
52
53
|
- Default options offered to the user: `staging` | `preprod` | `prod` | `main` | `dev` | custom input
|
|
53
54
|
- Repo-specific preference, if known (e.g. `main` is the integration branch):
|
|
54
55
|
- Branches that are off-limits as a base in this repo (security / freeze rules):
|
|
56
|
+
- Merge order the stack implies (merge a stage's PR only after its base PR):
|
|
55
57
|
|
|
56
58
|
## PR Draft Inputs
|
|
57
59
|
|
|
@@ -69,7 +71,7 @@ taskType: "{{FM_TASK_TYPE}}"
|
|
|
69
71
|
## User-Selection Defaults (advisory only — the user still chooses interactively)
|
|
70
72
|
|
|
71
73
|
- Suggested action (Q1): `local checkout` | `push + PR` | `skip`
|
|
72
|
-
- Suggested base (Q2): one of the candidate base branches above
|
|
74
|
+
- Suggested release base (Q2): one of the candidate base branches above
|
|
73
75
|
- Suggested message handling (Q3): `use as-is` | `edit then proceed`
|
|
74
76
|
|
|
75
77
|
> These suggestions help the lead phrase its `AskUserQuestion` prompts. They are NOT pre-approvals — every mutating command still requires an explicit user pick at run time.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Translator Prompt Preamble (canonical)
|
|
2
|
+
|
|
3
|
+
This file is the audience-specific contract for `translator`. Read it and the shared Worker Error Contract end-to-end. The task instructions in this prompt own this run's commands, paths, and target language; this file owns how you translate and what you may write.
|
|
4
|
+
|
|
5
|
+
## Output ownership
|
|
6
|
+
|
|
7
|
+
Write only the translations file at `**Result Path:**`, the completion pointer at `**Worker Result Path:**`, and the reading audit at `**Audit sidecar path:**`. The publish command named in the task instructions owns the sidecar the renderer overlays; do not write that file yourself.
|
|
8
|
+
|
|
9
|
+
Never edit the report record, the narrative Markdown, the rendered HTML, or any project source file.
|
|
10
|
+
|
|
11
|
+
Never add, remove, or re-order the `T-NNN` items relative to the work list you were given. Never translate a value the work list did not offer you: its absence is deliberate, because the renderer reads those values as machinery and a translated copy breaks the page silently.
|
|
12
|
+
|
|
13
|
+
Never return the translated text inline. The file on disk is the artifact; your return message names the paths and the verification result.
|
|
14
|
+
|
|
15
|
+
## Required reading
|
|
16
|
+
|
|
17
|
+
Read the complete work list before translating any item, continuing in chunks when it is long. A partial read produces a partial sidecar, and the items you never saw render in the source language with no error raised.
|
|
18
|
+
|
|
19
|
+
## How to translate
|
|
20
|
+
|
|
21
|
+
Judge every term on whether the translation or the original carries the meaning faster to a working developer in the target language, and pick that one. The goal is a reader who understands the report sooner, not a document with no English left in it.
|
|
22
|
+
|
|
23
|
+
- **Never touch**: code identifiers, file paths, CLI commands and flags, model names, commit SHAs, URLs, and anything already inside backticks. Reproduce them character for character.
|
|
24
|
+
- **Keep the English word** when that is what developers in the target language actually say. Forcing a native coinage onto `commit`, `worktree`, `merge`, `lint`, `diff`, `stage`, `rollback` or `PR` makes the sentence *slower* to read, not more local.
|
|
25
|
+
- **Translate the explanation.** Connective prose — why something matters, what a reader should do, what a finding means — is where the translation earns its place. Carry the meaning, not the word order.
|
|
26
|
+
- **Do not translate literally.** A word-for-word rendering that is technically correct and unreadable has failed. Say what the sentence means the way a developer would say it.
|
|
27
|
+
- **Gloss on first use, once.** When a technical term does need translating, write it as `<translation>(<English>)` the first time it appears in the document, then use the translation alone. Never gloss the same term twice.
|
|
28
|
+
- **One claim per sentence.** Where the English stacks four clauses behind em-dashes, split it. The reader gains nothing from the original's punctuation.
|
|
29
|
+
- **Match the register.** A verdict line is terse; a rationale paragraph is explanatory. Do not inflate a three-word cell into a sentence, or compress a paragraph into a fragment.
|
|
30
|
+
- **Leave it out when you cannot do it justice.** An omitted item renders in the source language, which is a correct fallback. A confident mistranslation is not.
|
|
31
|
+
|
|
32
|
+
## Failure handling
|
|
33
|
+
|
|
34
|
+
A failing verification check means a pointer resolves nowhere — you altered or invented one. Fix the translation and run the check again; do not return while it fails.
|
|
35
|
+
|
|
36
|
+
Record your own tool failures through the file named by `**Worker Error Contract Path:**`.
|
|
@@ -22,15 +22,14 @@ def check(source_path: Path, target_path: Path) -> None:
|
|
|
22
22
|
errors.append(f"build-output asset does not match source: {target_path}")
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
# 1.
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if not workers_source.is_dir():
|
|
30
|
-
errors.append(f"missing agents/workers source directory: {workers_source}")
|
|
25
|
+
# 1. Agent contracts: agents/common.json + agents/roles/* + agents/operations/*
|
|
26
|
+
# -> runtime/agents/*. 호스트 전역 에이전트 정의는 더 이상 없다(ADR-0017).
|
|
27
|
+
if not agents_source_root.is_dir():
|
|
28
|
+
errors.append(f"missing agents source directory: {agents_source_root}")
|
|
31
29
|
else:
|
|
32
|
-
for source_path in sorted(
|
|
33
|
-
|
|
30
|
+
for source_path in sorted(agents_source_root.rglob("*.json")):
|
|
31
|
+
relative = source_path.relative_to(agents_source_root)
|
|
32
|
+
check(source_path, runtime_root / "agents" / relative)
|
|
34
33
|
|
|
35
34
|
# 2. Lead contract + internal lead resources: prompts/lead/* + prompts/coding-preflight/*
|
|
36
35
|
# -> runtime/prompts/*. These ship as runtime resources (okstra install copies
|