okstra 0.159.0 → 0.161.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 +1 -1
- package/docs/architecture/storage-model.md +2 -0
- package/docs/architecture.md +2 -1
- package/docs/cli.md +8 -3
- package/docs/for-ai/README.md +2 -2
- package/docs/for-ai/skills/okstra-inspect.md +3 -0
- package/docs/for-ai/skills/okstra-run.md +2 -1
- package/docs/for-ai/skills/okstra-user-response.md +5 -5
- package/docs/project-structure-overview.md +5 -1
- package/docs/task-process/implementation.md +28 -0
- package/package.json +1 -1
- package/runtime/BUILD.json +2 -2
- package/runtime/bin/okstra-claude-exec.sh +4 -1
- package/runtime/prompts/host-orchestration/README.md +18 -0
- package/runtime/prompts/host-orchestration/implementation.md +57 -0
- package/runtime/prompts/launch.template.md +10 -1
- package/runtime/prompts/lead/adapters/claude-code.md +1 -1
- package/runtime/prompts/lead/adapters/cmux.md +67 -0
- package/runtime/prompts/lead/context-loader.md +5 -2
- package/runtime/prompts/lead/convergence.md +3 -1
- package/runtime/prompts/lead/plan-body-verification.md +21 -2
- package/runtime/prompts/lead/team-contract.md +2 -1
- package/runtime/prompts/profiles/_clarification-recommendation.md +11 -1
- package/runtime/prompts/profiles/_common-contract.md +3 -1
- package/runtime/prompts/profiles/implementation-planning.md +2 -0
- package/runtime/prompts/profiles/requirements-discovery.md +1 -1
- package/runtime/prompts/wizard/prompts.ko.json +3 -0
- package/runtime/python/okstra_ctl/clarification_items.py +9 -0
- package/runtime/python/okstra_ctl/cmux.py +531 -0
- package/runtime/python/okstra_ctl/codex_dispatch.py +6 -6
- package/runtime/python/okstra_ctl/convergence.py +168 -11
- package/runtime/python/okstra_ctl/dispatch_core.py +76 -7
- package/runtime/python/okstra_ctl/dispatch_state.py +16 -0
- package/runtime/python/okstra_ctl/error_issue.py +640 -0
- package/runtime/python/okstra_ctl/error_report.py +56 -0
- package/runtime/python/okstra_ctl/error_zip.py +23 -10
- package/runtime/python/okstra_ctl/incremental_scope.py +159 -19
- package/runtime/python/okstra_ctl/initial_prompt_materialization.py +18 -5
- package/runtime/python/okstra_ctl/issue_signals.py +186 -0
- package/runtime/python/okstra_ctl/lead_runtime.py +30 -2
- package/runtime/python/okstra_ctl/paths.py +38 -0
- package/runtime/python/okstra_ctl/plan_items_cli.py +167 -3
- package/runtime/python/okstra_ctl/profile_show.py +134 -0
- package/runtime/python/okstra_ctl/recap.py +63 -0
- package/runtime/python/okstra_ctl/render.py +7 -2
- package/runtime/python/okstra_ctl/render_final_report.py +7 -22
- package/runtime/python/okstra_ctl/report_translation.py +4 -0
- package/runtime/python/okstra_ctl/report_views.py +7 -3
- package/runtime/python/okstra_ctl/run.py +54 -3
- package/runtime/python/okstra_ctl/run_audit.py +477 -0
- package/runtime/python/okstra_ctl/team.py +50 -11
- package/runtime/python/okstra_ctl/user_response.py +25 -10
- package/runtime/python/okstra_ctl/verdict_blocks.py +183 -0
- package/runtime/python/okstra_ctl/wizard.py +64 -10
- package/runtime/python/okstra_ctl/worker_audit_check.py +44 -0
- package/runtime/python/okstra_ctl/worker_audit_ledger.py +207 -0
- package/runtime/python/okstra_ctl/worker_heartbeat.py +9 -3
- package/runtime/python/okstra_ctl/worker_liveness.py +81 -9
- package/runtime/schemas/final-report-v1.0.schema.json +14 -0
- package/runtime/schemas/final-report-v2.0.schema.json +51 -1
- package/runtime/skills/okstra-inspect/SKILL.md +3 -1
- package/runtime/skills/okstra-inspect/facets/error-issue.md +77 -0
- package/runtime/skills/okstra-inspect/facets/run-audit.md +34 -0
- package/runtime/skills/okstra-run/SKILL.md +28 -10
- package/runtime/skills/okstra-user-response/SKILL.md +18 -18
- package/runtime/templates/reports/final-report.template.md +4 -0
- package/runtime/templates/reports/html/i18n/en.json +5 -1
- package/runtime/templates/reports/html/i18n/ko.json +5 -1
- package/runtime/templates/reports/html/macros/forms.html +15 -0
- package/runtime/templates/reports/html/tasks/implementation-planning.template.html +1 -0
- package/runtime/templates/reports/i18n/en.json +2 -0
- package/runtime/validators/validate-run.py +267 -208
- package/runtime/validators/validate-workflow.sh +6 -0
- package/runtime/validators/validate_session_conformance.py +135 -31
- package/src/cli-registry.mjs +34 -0
- package/src/commands/execute/incremental-scope.mjs +10 -0
- package/src/commands/execute/worker-audit-check.mjs +35 -0
- package/src/commands/inspect/error-issue.mjs +27 -0
- package/src/commands/inspect/profile-show.mjs +29 -0
- package/src/commands/inspect/run-audit.mjs +26 -0
|
@@ -174,7 +174,9 @@ When `next.kind == "done"`, fetch the public wizard outcome:
|
|
|
174
174
|
okstra wizard outcome --state-file /var/folders/.../okstra-wizard.AbCd.json
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
Output: `{ok: true, outcome: {renderArgs: {...}, persistActions: [...], confirmationText: "..."}}`.
|
|
177
|
+
Output: `{ok: true, outcome: {renderArgs: {...}, orchestration: {chainStages: "..."}, persistActions: [...], confirmationText: "..."}}`.
|
|
178
|
+
|
|
179
|
+
`renderArgs` holds only flags `okstra render-bundle` accepts, which is what makes the pass-everything rule below safe. `orchestration` holds signals this skill acts on itself — never pass its entries to `render-bundle`.
|
|
178
180
|
|
|
179
181
|
Run every `outcome.persistActions[]` entry BEFORE `render-bundle`. The only supported action is:
|
|
180
182
|
|
|
@@ -216,6 +218,19 @@ The python function underneath is mutex-protected (`~/.okstra/.locks/<task-key>.
|
|
|
216
218
|
|
|
217
219
|
You can delete the literal state-file path after this point — its job is done. Invoke `rm` with the literal path (e.g. `rm /var/folders/.../okstra-wizard.AbCd.json`), not a shell variable.
|
|
218
220
|
|
|
221
|
+
<!-- BEGIN FRAGMENT: host-orchestration-implementation -->
|
|
222
|
+
## Host orchestration rules — implementation
|
|
223
|
+
|
|
224
|
+
These are the rules the **host orchestrator** follows around an `implementation`
|
|
225
|
+
run: when to offer a conformance waiver, what a concurrent-run marker means, how
|
|
226
|
+
to recover a stale stage SHA, and what the chaining queue does when the next
|
|
227
|
+
stage is not ready. They are not lead phase rules — the lead's rules live in
|
|
228
|
+
`prompts/profiles/`.
|
|
229
|
+
|
|
230
|
+
This file is the single source. Two surfaces are generated from it: the
|
|
231
|
+
`okstra-run` skill body (marker block, synced by `tools/sync-skill-fragments.mjs`)
|
|
232
|
+
and each run's `instruction-set/host-orchestration-rules.md`. Edit here.
|
|
233
|
+
|
|
219
234
|
### Step 5.1 (implementation only): blocking local conformance waiver offer
|
|
220
235
|
|
|
221
236
|
`render-bundle` accepts an optional `--qa-waiver "<stageKey>:<reason>"` flag (implementation only). It records a **user-acknowledged** waiver into the task-level conformance manifest entry (`entry.waiver`), letting the run proceed when an `io`-only Tier 3 conformance script genuinely cannot run. The waiver records the user's reason **verbatim**.
|
|
@@ -256,6 +271,13 @@ If `render-bundle` fails with a `PrepareError` containing `Recorded stage SHAs n
|
|
|
256
271
|
|
|
257
272
|
If the anchor (`implementation_base_commit`) is reported unresolvable, run the same command's `--reset-anchor <ref>` after user confirmation. Correcting a confirm item without the picker is forbidden — the runtime also rejects a confirm correction without `--use-ref`.
|
|
258
273
|
|
|
274
|
+
### Next stage not yet ready — normal termination (not an exception gate)
|
|
275
|
+
Because of the dependency closure, the chain queue **may include a stage that another implementation run has occupied as started/reserved.** That stage's `render-bundle` is rejected with `--stage N already in progress or reserved by another run` (StageTargetError). This is **not** an exception gate needing human judgment but a "next stage not yet ready" situation. On this rejection, **terminate the chain normally** and report the remaining queue to the user (e.g. `remaining queue: stage 4, 5 — resume with okstra-run after occupancy is released`). This is a different branch from the exception gate below (data corruption·concurrent-occupancy conflict confirmation).
|
|
276
|
+
|
|
277
|
+
### Exception gate during chaining
|
|
278
|
+
If `render-bundle` raises Step 5's concurrent-run conflict detection (concurrent-run branch) or git stale-SHA reconciliation (git-reconcile branch), **stop the chain at that stage** and present the gate to the user exactly as Step 5 prescribes. Once the user resolves the gate, resume the chain in place (continue with the remaining queue). Data corruption·concurrent-occupancy conflicts are confirmed by a human — this is the safety boundary of unattended chaining. (Unlike the "not ready" rejection above, these two branches do not discard the queue; they wait for user resolution.)
|
|
279
|
+
<!-- END FRAGMENT: host-orchestration-implementation -->
|
|
280
|
+
|
|
259
281
|
## Step 6: Take over as Okstra lead
|
|
260
282
|
|
|
261
283
|
Read `<INSTRUCTION_SET_PATH>/lead-execution-prompt.md` verbatim and take over as `Okstra lead` in the current host-native session. The prompt selects exactly one runtime adapter and points to compact intake artifacts first (`active-run-context`, `analysis-profile.md`, and `analysis-packet.md`); full source files such as `analysis-material.md`, `reference-expectations.md`, and `final-report-template.md` are lazy/fallback inputs. Follow the rendered prompt order, do not preempt it.
|
|
@@ -265,11 +287,11 @@ Then proceed through the phases exactly as the lead prompt directs (Phase 1 cont
|
|
|
265
287
|
Inform the user with one short line:
|
|
266
288
|
> Took over as Okstra lead (`<host-runtime>`) for `<taskKey>` (`<task-type>`). Run dir: `<RUN_DIR_RELATIVE_PATH>`. Beginning Phase 1 (context loading).
|
|
267
289
|
|
|
268
|
-
## Step 7: implementation unattended chaining (
|
|
290
|
+
## Step 7: implementation unattended chaining (orchestration.chainStages)
|
|
269
291
|
|
|
270
|
-
When `task-type == implementation` and Step 5
|
|
292
|
+
When `task-type == implementation` and Step 5 outcome's `orchestration.chainStages` CSV has 2+ elements, the current session acts as the orchestrator and runs the stages in dependency order as an unattended chain (a single element behaves like the existing single run, so skip this section — the end of Step 6 is the end of the run).
|
|
271
293
|
|
|
272
|
-
Queue = the topologically-sorted stage list from splitting `
|
|
294
|
+
Queue = the topologically-sorted stage list from splitting `orchestration.chainStages` on `,` (the order Task 5 emitted by topologically sorting the dependency closure). For each stage `N` in the queue, in order:
|
|
273
295
|
|
|
274
296
|
1. Call Step 5's `render-bundle` with the same arguments but `--stage N` (the base commit is auto-computed by prepare from the predecessor's done `head_commit`, so do not pass it by hand). Step 5's blocking local conformance waiver offer·concurrent-run detection·git-reconcile gates apply identically to each stage's `render-bundle`.
|
|
275
297
|
2. As in Step 6, become the host-native Okstra lead and run that stage's Phase 1–7 inline. Phase 6's lead post-stage persistence appends that stage's `status:"done"` row to `runs/<plan-task-key>/consumers.jsonl` (per the implementation profile directive).
|
|
@@ -278,11 +300,7 @@ Queue = the topologically-sorted stage list from splitting `chain-stages` on `,`
|
|
|
278
300
|
|
|
279
301
|
Once the whole queue is consumed, end the chain and report completion to the user.
|
|
280
302
|
|
|
281
|
-
|
|
282
|
-
Because of the dependency closure, the chain queue **may include a stage that another implementation run has occupied as started/reserved.** That stage's `render-bundle` is rejected with `--stage N already in progress or reserved by another run` (StageTargetError). This is **not** an exception gate needing human judgment but a "next stage not yet ready" situation. On this rejection, **terminate the chain normally** and report the remaining queue to the user (e.g. `remaining queue: stage 4, 5 — resume with okstra-run after occupancy is released`). This is a different branch from the exception gate below (data corruption·concurrent-occupancy conflict confirmation).
|
|
283
|
-
|
|
284
|
-
### Exception gate during chaining
|
|
285
|
-
If `render-bundle` raises Step 5's concurrent-run conflict detection (concurrent-run branch) or git stale-SHA reconciliation (git-reconcile branch), **stop the chain at that stage** and present the gate to the user exactly as Step 5 prescribes. Once the user resolves the gate, resume the chain in place (continue with the remaining queue). Data corruption·concurrent-occupancy conflicts are confirmed by a human — this is the safety boundary of unattended chaining. (Unlike the "not ready" rejection above, these two branches do not discard the queue; they wait for user resolution.)
|
|
303
|
+
The two branches that end or pause the queue — "Next stage not yet ready" and "Exception gate during chaining" — are in the host orchestration rules block above.
|
|
286
304
|
|
|
287
305
|
## Persisting the PR template scope (release-handoff)
|
|
288
306
|
|
|
@@ -308,4 +326,4 @@ Do not read the wizard state file directly. `okstra wizard outcome` exposes any
|
|
|
308
326
|
|
|
309
327
|
- Echo each captured answer (`result.echo`) on one short line so the user sees what was registered.
|
|
310
328
|
- Never invent identity; if a `text` prompt returns an empty answer where the wizard rejects it, the user must retry.
|
|
311
|
-
- After Step 6, begin the lead workflow without re-summarizing the skill itself. For a single run, the end of Step 6 is the end of the run — but in an unattended chain where `
|
|
329
|
+
- After Step 6, begin the lead workflow without re-summarizing the skill itself. For a single run, the end of Step 6 is the end of the run — but in an unattended chain where `orchestration.chainStages` has 2+ elements, repeat Step 6 per stage until Step 7's queue is empty (or it stops at a "not ready" / exception gate), then finish.
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: okstra-user-response
|
|
3
3
|
description: >-
|
|
4
|
-
Use this to answer an okstra task's open clarification questions in-session, without hand-editing any file. The tell is a request to respond to an okstra run's clarification items or its approval gate — "answer okstra", "I'll answer the questions", "clarification response", "user response", "approve and move on". This skill lists tasks whose latest report still has open clarification blockers, then walks the open C-ids one at a time — each rewritten as a self-contained question with background,
|
|
4
|
+
Use this to answer an okstra task's open clarification questions in-session, without hand-editing any file. The tell is a request to respond to an okstra run's clarification items or its approval gate — "answer okstra", "I'll answer the questions", "clarification response", "user response", "approve and move on". This skill lists tasks whose latest report still has open clarification blockers, then walks the open C-ids one at a time — each rewritten as a self-contained question with background, its options with their impact plus "Enter directly" — echoes the collected answers back for an explicit "confirmed" acknowledgement, optionally records approval, and writes the `user-responses/` sidecar via `okstra user-response write`. NOT for starting a run (okstra-run), inspecting a finished task (okstra-inspect), or generating a brief (okstra-brief-gen). The skill never picks an answer — it builds the option board and transcribes what the user decides.
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# OKSTRA User Response
|
|
8
8
|
|
|
9
9
|
Single entry point for answering the clarification questions an okstra run left behind (the open `C-*` rows under the final report's `## 1. Clarification Items`) **in-session**, and recording those answers as a `runs/<type>/user-responses/` sidecar. The next `/okstra-run` auto-attaches this sidecar via `--clarification-response`.
|
|
10
10
|
|
|
11
|
-
**Core principle — the skill never picks an answer for the user.** It builds the option board — background, a self-contained question,
|
|
11
|
+
**Core principle — the skill never picks an answer for the user.** It builds the option board — background, a self-contained question, the report's options with their impact, `Enter directly` — and the user alone picks from it; every `value` is what the user chose or typed. It never calls `write` until the user has explicitly confirmed.
|
|
12
12
|
|
|
13
13
|
**Second principle — one question at a time.** Never batch two clarification items into one question, and never dump the whole open list at the user. Ask item 1, transcribe the answer, then ask item 2.
|
|
14
14
|
|
|
15
15
|
| Sub-command | What it does |
|
|
16
16
|
|---|---|
|
|
17
17
|
| `list` | List tasks that still have approval-open clarification, newest report first. |
|
|
18
|
-
| `show` | Expand one report's open `C-*` rows (statement +
|
|
18
|
+
| `show` | Expand one report's open `C-*` rows (statement + options + contextRefs). |
|
|
19
19
|
| `write` | Record the collected answers (+ optional approval) as a `user-responses/` sidecar. |
|
|
20
20
|
|
|
21
21
|
## Step 0: Preflight (shared)
|
|
@@ -71,7 +71,11 @@ Carry the chosen entry's `reportPath` and `taskKey` forward.
|
|
|
71
71
|
okstra user-response show --report <reportPath>
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
Returns `{reportPath, rows: [{id, kind, blocks, status, statement,
|
|
74
|
+
Returns `{reportPath, rows: [{id, kind, blocks, status, statement, expectedForm, options, contextRefs, resolvedRefs}]}`.
|
|
75
|
+
|
|
76
|
+
Each entry of `options[]` is `{role, answer, rationale, scopeImpact, addedWork, directionChange}`. `role` is `recommended` for exactly one entry and `alternative` for the rest; `scopeImpact` is a token list drawn from `in-repo` / `cross-repo` / `new-schema` / `deferrable`; `addedWork` and `directionChange` are one sentence each. A schema-v1 report has nowhere to record impact, so those three arrive empty — the CLI reconstructs only the answers from the report's `Expected form` cell.
|
|
77
|
+
|
|
78
|
+
`resolvedRefs` is `[{ref, definition}]` — the CLI has already looked up what each internal token (`RB-002`, `FU-001`, `§4.7`, …) means in the report body; `definition` is `null` only when the report text alone could not resolve it (e.g. a `path:line` pointer).
|
|
75
79
|
|
|
76
80
|
This call is a **data fetch, not a presentation step**. Do not print `rows` at the user, and do not paste a raw `statement` as a question — a `statement` like `Rewrite RB-002 rollback (see §4.7)` is meaningless on its own, which is the whole reason this skill exists. Announce only the count and the plan:
|
|
77
81
|
|
|
@@ -103,23 +107,19 @@ Close the background with the raw source on one line, so the mapping back to the
|
|
|
103
107
|
|
|
104
108
|
> Source: `C-014` — "<raw statement>"
|
|
105
109
|
|
|
106
|
-
### 3b. The picker —
|
|
110
|
+
### 3b. The picker — the report's options plus `Enter directly`
|
|
107
111
|
|
|
108
|
-
One `AskUserQuestion` (single-select)
|
|
112
|
+
One `AskUserQuestion` (single-select). Fill the slots from `options[]` in array order — the `role: recommended` entry first with its label suffixed `(Recommended)`, then the `alternative` entries — and always close with `Enter directly` as the last option. Never mark anything but the `recommended` entry as recommended.
|
|
109
113
|
|
|
110
|
-
|
|
111
|
-
2. **Alternative** — `alternatives[0]`.
|
|
112
|
-
3. **Alternative** — `alternatives[1]`.
|
|
113
|
-
4. **`Enter directly`** — always last, always present.
|
|
114
|
+
Each `label` is that option's `answer`, kept to the answer itself (1–5 words). Each `description` carries the rationale followed by the three impact axes, in this fixed order:
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
> `<rationale>` — Scope: `<scopeImpact, comma-joined>` · Added work: `<addedWork>` · Direction: `<directionChange>`
|
|
116
117
|
|
|
117
|
-
|
|
118
|
-
- **`Reframe this question`** — the item is held rather than answered, and the next run re-asks it.
|
|
118
|
+
The three axes answer three different questions: how far the choice reaches, what new work it creates, and what it overturns. Never fold them into one phrase — whichever is easiest to write ends up standing in for the other two, and the user weighs a scope change as though it were free. That is the failure this board exists to prevent.
|
|
119
119
|
|
|
120
|
-
|
|
120
|
+
When an axis is empty — a schema-v1 report has nowhere to record impact — write `not stated in the report` for that axis. Do not infer it, and do not read the code to reconstruct it. A guessed side effect is worse than a stated gap, because the user cannot tell the two apart.
|
|
121
121
|
|
|
122
|
-
|
|
122
|
+
When `options[]` carries more than three entries, keep the recommended one plus the two alternatives whose `scopeImpact` differs most from it, and say in the background text how many you left out. When it carries exactly two, the picker has three options in total — do not pad it with an invented third.
|
|
123
123
|
|
|
124
124
|
### 3c. Transcribe the decision, then move on
|
|
125
125
|
|
|
@@ -127,13 +127,13 @@ Record one entry — `{id, kind, value, rationale?, disposition}`, `kind` copied
|
|
|
127
127
|
|
|
128
128
|
| The user picks | `value` | `disposition` |
|
|
129
129
|
|---|---|---|
|
|
130
|
-
|
|
|
130
|
+
| One of the `options[]` entries | that option's `answer` text, not its short label | `answer` |
|
|
131
131
|
| `Enter directly` → their own answer | the user's utterance verbatim (rationale into `rationale`) | `answer` |
|
|
132
|
-
|
|
|
132
|
+
| Free text asking for the item to be re-asked | what the user wants re-asked, verbatim (empty → the raw statement) | `reframe` |
|
|
133
133
|
|
|
134
134
|
A reframe is not an answer, so it does not satisfy the approval gate.
|
|
135
135
|
|
|
136
|
-
If the user replies with a question instead of an answer ("what does this mean?"), record nothing: **Read** the `§`/`path:line` from `contextRefs[]`, explain it in plain language, and re-ask the same item with the same
|
|
136
|
+
If the user replies with a question instead of an answer ("what does this mean?"), record nothing: **Read** the `§`/`path:line` from `contextRefs[]`, explain it in plain language, and re-ask the same item with the same options. Explain only — **do not resolve it for them**; the decision goes back to the user.
|
|
137
137
|
|
|
138
138
|
Echo one line per finished item (`[2/5] C-014 → answer: 60s`), then ask the next one. Do not summarize the whole set until Step 4.
|
|
139
139
|
|
|
@@ -406,6 +406,10 @@ Carried-forward plan items retain their prior verdicts verbatim; each such item
|
|
|
406
406
|
{% endif %}
|
|
407
407
|
{% if implementationPlanning.planBodyVerification.gateBlockedBy %}- **Blocked by**: {% for cause in implementationPlanning.planBodyVerification.gateBlockedBy %}`{{ cause }}`{% if not loop.last %}, {% endif %}{% endfor %}
|
|
408
408
|
{% endif %}
|
|
409
|
+
{% if implementationPlanning.planBodyVerification.uniformVerifiers %}- **{{ t("implementationPlanning.planBodyUniformVerifierLabel") }}**: {% for u in implementationPlanning.planBodyVerification.uniformVerifiers %}`{{ u.worker }}` → `{{ u.verdict }}` ({{ u.itemCount }}){% if not loop.last %}, {% endif %}{% endfor %}
|
|
410
|
+
|
|
411
|
+
> {{ t("implementationPlanning.planBodyUniformVerifierLegend") }}
|
|
412
|
+
{% endif %}
|
|
409
413
|
> {{ t("implementationPlanning.planBodyGateLegend") }}
|
|
410
414
|
>
|
|
411
415
|
> {{ t("implementationPlanning.planBodyBlockedByLegend") }}
|
|
@@ -132,7 +132,11 @@
|
|
|
132
132
|
"answer-as": "Answer as",
|
|
133
133
|
"questions-waiting-on-you": "Questions waiting on you",
|
|
134
134
|
"count-questions-waiting-on-you": "{count} questions waiting on you",
|
|
135
|
-
"your-answer-to-id": "Your answer to {id}"
|
|
135
|
+
"your-answer-to-id": "Your answer to {id}",
|
|
136
|
+
"recommended": "Recommended",
|
|
137
|
+
"scope-impact": "Scope",
|
|
138
|
+
"added-work": "Added work",
|
|
139
|
+
"direction-change": "Direction change"
|
|
136
140
|
},
|
|
137
141
|
"visualizations": {
|
|
138
142
|
"component": "Component",
|
|
@@ -132,7 +132,11 @@
|
|
|
132
132
|
"answer-as": "답변 형식",
|
|
133
133
|
"questions-waiting-on-you": "답변을 기다리는 질문",
|
|
134
134
|
"count-questions-waiting-on-you": "답변을 기다리는 질문 {count}건",
|
|
135
|
-
"your-answer-to-id": "{id}에 대한 답변"
|
|
135
|
+
"your-answer-to-id": "{id}에 대한 답변",
|
|
136
|
+
"recommended": "권장",
|
|
137
|
+
"scope-impact": "범위",
|
|
138
|
+
"added-work": "추가 작업",
|
|
139
|
+
"direction-change": "방향 전환"
|
|
136
140
|
},
|
|
137
141
|
"visualizations": {
|
|
138
142
|
"component": "구성 요소",
|
|
@@ -40,6 +40,21 @@
|
|
|
40
40
|
<p class="eyebrow">{{ row.id }} · {{ row.kind }}</p>
|
|
41
41
|
{{ row.statement | paragraphs }}
|
|
42
42
|
<dl class="clarification-expected"><dt>{{ t('macros.forms.answer-as') }}</dt><dd>{{ row.expectedForm | inline_code }}</dd></dl>
|
|
43
|
+
{% if row.options %}
|
|
44
|
+
<ol class="clarification-options">
|
|
45
|
+
{% for option in row.options %}
|
|
46
|
+
<li class="clarification-option{% if option.role == 'recommended' %} is-recommended{% endif %}">
|
|
47
|
+
<p class="clarification-option-answer">{{ option.answer }}{% if option.role == 'recommended' %} <span class="badge">{{ t('macros.forms.recommended') }}</span>{% endif %}</p>
|
|
48
|
+
<p class="clarification-option-rationale">{{ option.rationale }}</p>
|
|
49
|
+
<dl class="clarification-option-impact">
|
|
50
|
+
<dt>{{ t('macros.forms.scope-impact') }}</dt><dd>{{ option.scopeImpact | join(', ') }}</dd>
|
|
51
|
+
<dt>{{ t('macros.forms.added-work') }}</dt><dd>{{ option.addedWork }}</dd>
|
|
52
|
+
<dt>{{ t('macros.forms.direction-change') }}</dt><dd>{{ option.directionChange }}</dd>
|
|
53
|
+
</dl>
|
|
54
|
+
</li>
|
|
55
|
+
{% endfor %}
|
|
56
|
+
</ol>
|
|
57
|
+
{% endif %}
|
|
43
58
|
<label for="response-{{ row.id }}">{{ t('macros.forms.your-answer-to-id') | replace('{id}', row.id) }}</label>
|
|
44
59
|
<textarea id="response-{{ row.id }}" data-response-id="{{ row.id }}" rows="4">{{ row.userInput | default('') }}</textarea>
|
|
45
60
|
</article>
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
<h2>{{ t('tasks.implementation-planning.plan-body-verification') }}</h2>
|
|
70
70
|
<p><strong>{{ t('tasks.implementation-planning.verdict') }}</strong> — {{ planning.planBodyVerification.gateResult | inline_code }} ({{ planning.planBodyVerification.roundCount }} rounds{% if planning.planBodyVerification.get("selfFixRoundsApplied") is not none %}, {{ planning.planBodyVerification.selfFixRoundsApplied }} self-fix rounds{% if planning.planBodyVerification.get("selfFixStopReason") %} · {{ planning.planBodyVerification.selfFixStopReason | inline_code }}{% endif %}{% endif %})</p>
|
|
71
71
|
{% if planning.planBodyVerification.get("gateBlockedBy") %}<p><strong>{{ t('tasks.implementation-planning.what-it-blocked') }}</strong> — {{ planning.planBodyVerification.gateBlockedBy | join(", ") | inline_code }}</p>{% endif %}
|
|
72
|
+
{% if planning.planBodyVerification.get("uniformVerifiers") %}<p><strong>{{ t('implementationPlanning.planBodyUniformVerifierLabel') }}</strong> — {% for u in planning.planBodyVerification.uniformVerifiers %}{{ u.worker | inline_code }} → {{ u.verdict | inline_code }} ({{ u.itemCount }}){% if not loop.last %}, {% endif %}{% endfor %}<br><small>{{ t('implementationPlanning.planBodyUniformVerifierLegend') }}</small></p>{% endif %}
|
|
72
73
|
<table><thead><tr><th>{{ t('tasks.implementation-planning.plan-item') }}</th><th>{{ t('tasks.implementation-planning.subject') }}</th></tr></thead><tbody>{% for row in planning.planBodyVerification.planItems %}<tr id="id-{{ row.id }}">{{ row_key(pairs=[("ID", row.id), ("Source section", row.sourceSection)]) }}<td>{{ row.subject | inline_code }}</td></tr>{% endfor %}</tbody></table>
|
|
73
74
|
{% if planning.planBodyVerification.get("dissentLog") %}<h3>{{ t('tasks.implementation-planning.dissent-left-standing') }}</h3>
|
|
74
75
|
<table><thead><tr><th>{{ t('tasks.implementation-planning.subject') }}</th><th>{{ t('tasks.implementation-planning.body') }}</th></tr></thead><tbody>{% for row in planning.planBodyVerification.dissentLog %}<tr>{{ row_key(pairs=[("Subject", row.planItem), ("Worker", row.workerRole)]) }}<td>{{ row.body | inline_code }}</td></tr>{% endfor %}</tbody></table>{% endif %}
|
|
@@ -137,6 +137,8 @@
|
|
|
137
137
|
"implementationPlanning": {
|
|
138
138
|
"planBodyGateLegend": "Gate values — `passed`: agreed, no dissent · `passed-with-dissent`: a minority dissent remains but the gate passes (a majority dissent would block approval) · `blocked-by-disagreement`: majority dissent blocks approval · `aborted-non-result`: verification itself produced no result.",
|
|
139
139
|
"planBodyBlockedByLegend": "Which input blocked the gate — `majority-disagree`: a worker majority dissent · `coverage-gap`: a Requirement Coverage gap / blocked row, independent of worker votes · `non-result`: verification produced no result. Absent means nothing blocked.",
|
|
140
|
+
"planBodyUniformVerifierLabel": "Uniform verifier",
|
|
141
|
+
"planBodyUniformVerifierLegend": "This verifier answered the same verdict to every item it voted on, so this round's refutation signal came from its peers alone — the gate above reads as a wider cross-check than it was. A unanimous round is a legitimate outcome; confirm from the worker's `-audit-` sidecar that it actually opened the cited evidence.",
|
|
140
142
|
"planBodyVerdictLegend": "Verdict — **AGREE**: executable as written and internally consistent with other items · **SUPPLEMENT**: item is sound but a dependency / edge case / precondition is missing · **DISAGREE**: has a defect (see Breakage kind) · **verification-error**: the worker produced no result.",
|
|
141
143
|
"planBodyBreakageLegend": "Breakage kind — a: cited file path/symbol mismatches another step or option · b: command is not executable or is ambiguous · c: validation signal is not observable · d: rollback violates commit/dependency order (advisory — a rollback is human-run, so this never blocks the gate) · e: contradicts the trade-off matrix · f: requirement-coverage row does not map to an option/stage/step that actually satisfies the requirement. (`--` = not applicable) Fixability: planner-fixable = correctable from code + plan + brief; needs-user-input = requires an external decision.",
|
|
142
144
|
"planBodySourceLabel": "source §",
|