okstra 0.122.0 → 0.123.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.
Files changed (53) hide show
  1. package/README.md +4 -2
  2. package/docs/architecture/storage-model.md +14 -0
  3. package/docs/architecture.md +34 -6
  4. package/docs/cli.md +45 -5
  5. package/docs/for-ai/README.md +2 -2
  6. package/docs/for-ai/skills/okstra-rollup.md +1 -1
  7. package/docs/for-ai/skills/{okstra-schedule.md → okstra-schedule-gen.md} +3 -3
  8. package/docs/project-structure-overview.md +3 -2
  9. package/docs/task-process/implementation-planning.md +33 -9
  10. package/docs/task-process/implementation.md +21 -2
  11. package/package.json +1 -1
  12. package/runtime/BUILD.json +2 -2
  13. package/runtime/bin/lib/okstra/usage.sh +3 -3
  14. package/runtime/prompts/launch.template.md +5 -2
  15. package/runtime/prompts/lead/convergence.md +1 -1
  16. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  17. package/runtime/prompts/lead/plan-body-verification.md +29 -0
  18. package/runtime/prompts/lead/report-writer.md +9 -3
  19. package/runtime/prompts/profiles/_common-contract.md +1 -1
  20. package/runtime/prompts/profiles/_implementation-deliverable.md +3 -1
  21. package/runtime/prompts/profiles/_implementation-executor.md +5 -0
  22. package/runtime/prompts/profiles/_implementation-verifier.md +1 -1
  23. package/runtime/prompts/profiles/final-verification.md +2 -0
  24. package/runtime/prompts/profiles/implementation-planning.md +11 -1
  25. package/runtime/prompts/wizard/prompts.ko.json +44 -0
  26. package/runtime/python/okstra_ctl/codex_dispatch.py +23 -1
  27. package/runtime/python/okstra_ctl/design_prep.py +1462 -0
  28. package/runtime/python/okstra_ctl/design_surfaces.py +243 -0
  29. package/runtime/python/okstra_ctl/final_report_schema.py +33 -1
  30. package/runtime/python/okstra_ctl/implementation_stage.py +35 -0
  31. package/runtime/python/okstra_ctl/incremental_carry.py +294 -21
  32. package/runtime/python/okstra_ctl/incremental_scope.py +51 -5
  33. package/runtime/python/okstra_ctl/material.py +1 -1
  34. package/runtime/python/okstra_ctl/model_discovery.py +98 -0
  35. package/runtime/python/okstra_ctl/models.py +8 -3
  36. package/runtime/python/okstra_ctl/render.py +5 -0
  37. package/runtime/python/okstra_ctl/run.py +53 -5
  38. package/runtime/python/okstra_ctl/user_response.py +67 -2
  39. package/runtime/python/okstra_ctl/wizard.py +283 -3
  40. package/runtime/python/okstra_token_usage/report.py +11 -0
  41. package/runtime/schemas/final-report-v1.0.schema.json +336 -0
  42. package/runtime/skills/okstra-inspect/SKILL.md +2 -2
  43. package/runtime/skills/okstra-rollup/SKILL.md +1 -1
  44. package/runtime/skills/{okstra-schedule → okstra-schedule-gen}/SKILL.md +2 -2
  45. package/runtime/skills/okstra-user-response/SKILL.md +8 -6
  46. package/runtime/templates/reports/final-report.template.md +67 -0
  47. package/runtime/templates/reports/i18n/en.json +31 -0
  48. package/runtime/templates/reports/i18n/ko.json +31 -0
  49. package/runtime/validators/validate-run.py +426 -5
  50. package/runtime/validators/validate-schedule.py +4 -4
  51. package/src/cli-registry.mjs +7 -0
  52. package/src/commands/inspect/design-prep.mjs +23 -0
  53. package/src/lib/skill-catalog.mjs +2 -1
@@ -408,6 +408,7 @@
408
408
  "minItems": 1,
409
409
  "items": { "$ref": "#/$defs/ImplementationPlanStage" }
410
410
  },
411
+ "designPreparation": { "$ref": "#/$defs/DesignPreparation" },
411
412
  "stepwiseExecution": {
412
413
  "description": "Legacy flat summary kept for compatibility only. New reports use stageMap/stages.",
413
414
  "type": "array",
@@ -1296,6 +1297,337 @@
1296
1297
  }
1297
1298
  },
1298
1299
 
1300
+ "DesignPreparation": {
1301
+ "type": "object",
1302
+ "required": ["mode", "reason", "items"],
1303
+ "additionalProperties": false,
1304
+ "properties": {
1305
+ "mode": { "enum": ["assessed", "no-design-inputs"] },
1306
+ "reason": { "type": "string", "minLength": 1 },
1307
+ "items": {
1308
+ "type": "array",
1309
+ "items": { "$ref": "#/$defs/DesignPrepItem" }
1310
+ }
1311
+ },
1312
+ "allOf": [
1313
+ {
1314
+ "if": {
1315
+ "properties": { "mode": { "const": "no-design-inputs" } }
1316
+ },
1317
+ "then": { "properties": { "items": { "maxItems": 0 } } }
1318
+ }
1319
+ ]
1320
+ },
1321
+
1322
+ "DesignPrepKnownFact": {
1323
+ "type": "object",
1324
+ "required": ["statement", "evidence"],
1325
+ "additionalProperties": false,
1326
+ "properties": {
1327
+ "statement": { "type": "string", "minLength": 1 },
1328
+ "evidence": { "type": "string", "minLength": 1 }
1329
+ }
1330
+ },
1331
+
1332
+ "DesignPrepProposal": {
1333
+ "type": "object",
1334
+ "required": ["summary", "details", "assumptions", "evidence", "confidence"],
1335
+ "additionalProperties": false,
1336
+ "properties": {
1337
+ "summary": { "type": "string", "minLength": 1 },
1338
+ "details": {
1339
+ "type": "array",
1340
+ "items": { "type": "string", "minLength": 1 }
1341
+ },
1342
+ "assumptions": {
1343
+ "type": "array",
1344
+ "items": { "type": "string", "minLength": 1 }
1345
+ },
1346
+ "evidence": {
1347
+ "type": "array",
1348
+ "items": { "type": "string", "minLength": 1 }
1349
+ },
1350
+ "confidence": { "enum": ["low", "medium", "high"] }
1351
+ }
1352
+ },
1353
+
1354
+ "DesignPrepHumanConfirmation": {
1355
+ "type": "object",
1356
+ "required": ["required", "reason", "suggestedAction"],
1357
+ "additionalProperties": false,
1358
+ "properties": {
1359
+ "required": { "type": "boolean" },
1360
+ "reason": { "type": "string", "minLength": 1 },
1361
+ "suggestedAction": { "type": "string", "minLength": 1 }
1362
+ }
1363
+ },
1364
+
1365
+ "DesignPrepReviewPoint": {
1366
+ "type": "object",
1367
+ "required": ["phase"],
1368
+ "additionalProperties": false,
1369
+ "properties": {
1370
+ "phase": { "enum": ["implementation", "final-verification"] },
1371
+ "stage": { "type": "integer", "minimum": 1 }
1372
+ },
1373
+ "allOf": [
1374
+ {
1375
+ "if": { "properties": { "phase": { "const": "implementation" } } },
1376
+ "then": { "required": ["stage"] }
1377
+ }
1378
+ ]
1379
+ },
1380
+
1381
+ "DesignPrepItem": {
1382
+ "type": "object",
1383
+ "required": [
1384
+ "id",
1385
+ "kind",
1386
+ "title",
1387
+ "stageRefs",
1388
+ "status",
1389
+ "need",
1390
+ "knownFacts",
1391
+ "openQuestions",
1392
+ "aiProposal",
1393
+ "humanConfirmation"
1394
+ ],
1395
+ "additionalProperties": false,
1396
+ "properties": {
1397
+ "id": { "type": "string", "pattern": "^PREP-[0-9]{3}$" },
1398
+ "kind": {
1399
+ "enum": [
1400
+ "domain-contract",
1401
+ "persistence-schema",
1402
+ "external-interface",
1403
+ "transaction-consistency",
1404
+ "transformation-mapping",
1405
+ "lifecycle-state-machine",
1406
+ "rollout-observability",
1407
+ "manual-user-test",
1408
+ "other"
1409
+ ]
1410
+ },
1411
+ "title": { "type": "string", "minLength": 1 },
1412
+ "stageRefs": {
1413
+ "type": "array",
1414
+ "minItems": 1,
1415
+ "uniqueItems": true,
1416
+ "items": { "type": "integer", "minimum": 1 }
1417
+ },
1418
+ "status": {
1419
+ "enum": ["ready", "provisional", "blocked", "not-applicable"]
1420
+ },
1421
+ "need": { "type": "string", "minLength": 1 },
1422
+ "knownFacts": {
1423
+ "type": "array",
1424
+ "items": { "$ref": "#/$defs/DesignPrepKnownFact" }
1425
+ },
1426
+ "openQuestions": {
1427
+ "type": "array",
1428
+ "items": { "type": "string", "minLength": 1 }
1429
+ },
1430
+ "aiProposal": { "$ref": "#/$defs/DesignPrepProposal" },
1431
+ "humanConfirmation": {
1432
+ "$ref": "#/$defs/DesignPrepHumanConfirmation"
1433
+ },
1434
+ "workingAssumption": { "type": "string", "minLength": 1 },
1435
+ "guardrails": {
1436
+ "type": "array",
1437
+ "minItems": 1,
1438
+ "items": { "type": "string", "minLength": 1 }
1439
+ },
1440
+ "reviewAt": { "$ref": "#/$defs/DesignPrepReviewPoint" },
1441
+ "ifStillOpen": { "enum": ["block", "follow-up"] },
1442
+ "requestPath": {
1443
+ "type": "string",
1444
+ "pattern": "^design-prep-requests/design-prep-request-[0-9]+-PREP-[0-9]{3}\\.md$"
1445
+ },
1446
+ "blockReason": { "type": "string", "minLength": 1 },
1447
+ "requiredDecision": { "type": "string", "minLength": 1 },
1448
+ "notApplicableReason": { "type": "string", "minLength": 1 },
1449
+ "replanTriggerFields": {
1450
+ "type": "array",
1451
+ "uniqueItems": true,
1452
+ "items": {
1453
+ "type": "string",
1454
+ "pattern": "^[^.\\s]+(\\.[^.\\s]+)*$"
1455
+ }
1456
+ }
1457
+ },
1458
+ "oneOf": [
1459
+ {
1460
+ "properties": { "status": { "const": "ready" } },
1461
+ "allOf": [
1462
+ { "not": { "required": ["workingAssumption"] } },
1463
+ { "not": { "required": ["blockReason"] } },
1464
+ { "not": { "required": ["requiredDecision"] } },
1465
+ { "not": { "required": ["notApplicableReason"] } },
1466
+ { "not": { "required": ["requestPath"] } }
1467
+ ]
1468
+ },
1469
+ {
1470
+ "properties": { "status": { "const": "provisional" } },
1471
+ "required": [
1472
+ "workingAssumption",
1473
+ "guardrails",
1474
+ "reviewAt",
1475
+ "ifStillOpen",
1476
+ "requestPath"
1477
+ ],
1478
+ "allOf": [
1479
+ { "not": { "required": ["blockReason"] } },
1480
+ { "not": { "required": ["requiredDecision"] } },
1481
+ { "not": { "required": ["notApplicableReason"] } }
1482
+ ]
1483
+ },
1484
+ {
1485
+ "properties": {
1486
+ "status": { "const": "blocked" },
1487
+ "humanConfirmation": {
1488
+ "properties": { "required": { "const": true } }
1489
+ }
1490
+ },
1491
+ "required": [
1492
+ "blockReason",
1493
+ "requiredDecision",
1494
+ "reviewAt",
1495
+ "ifStillOpen",
1496
+ "requestPath"
1497
+ ],
1498
+ "allOf": [
1499
+ { "not": { "required": ["workingAssumption"] } },
1500
+ { "not": { "required": ["guardrails"] } },
1501
+ { "not": { "required": ["notApplicableReason"] } }
1502
+ ]
1503
+ },
1504
+ {
1505
+ "properties": { "status": { "const": "not-applicable" } },
1506
+ "required": ["notApplicableReason"],
1507
+ "allOf": [
1508
+ { "not": { "required": ["workingAssumption"] } },
1509
+ { "not": { "required": ["guardrails"] } },
1510
+ { "not": { "required": ["reviewAt"] } },
1511
+ { "not": { "required": ["ifStillOpen"] } },
1512
+ { "not": { "required": ["blockReason"] } },
1513
+ { "not": { "required": ["requiredDecision"] } },
1514
+ { "not": { "required": ["requestPath"] } }
1515
+ ]
1516
+ }
1517
+ ]
1518
+ },
1519
+
1520
+ "TriggerEvidence": {
1521
+ "type": "object",
1522
+ "required": ["step", "field", "match"],
1523
+ "additionalProperties": false,
1524
+ "properties": {
1525
+ "step": {
1526
+ "type": ["integer", "null"],
1527
+ "minimum": 1
1528
+ },
1529
+ "field": { "enum": ["files", "action"] },
1530
+ "match": { "type": "string", "minLength": 1 }
1531
+ }
1532
+ },
1533
+
1534
+ "InlineDesignContract": {
1535
+ "type": "object",
1536
+ "required": ["summary", "details", "evidence"],
1537
+ "additionalProperties": false,
1538
+ "properties": {
1539
+ "summary": { "type": "string", "minLength": 1 },
1540
+ "details": {
1541
+ "type": "array",
1542
+ "minItems": 1,
1543
+ "items": { "type": "string", "minLength": 1 }
1544
+ },
1545
+ "evidence": {
1546
+ "type": "array",
1547
+ "minItems": 1,
1548
+ "items": { "type": "string", "minLength": 1 }
1549
+ }
1550
+ }
1551
+ },
1552
+
1553
+ "DesignSurfaceCoverage": {
1554
+ "type": "object",
1555
+ "required": ["kind", "triggerEvidence", "disposition"],
1556
+ "additionalProperties": false,
1557
+ "properties": {
1558
+ "kind": {
1559
+ "enum": [
1560
+ "domain-contract",
1561
+ "persistence-schema",
1562
+ "external-interface",
1563
+ "transaction-consistency",
1564
+ "transformation-mapping",
1565
+ "lifecycle-state-machine",
1566
+ "rollout-observability",
1567
+ "manual-user-test",
1568
+ "other"
1569
+ ]
1570
+ },
1571
+ "triggerEvidence": {
1572
+ "type": "array",
1573
+ "minItems": 1,
1574
+ "items": { "$ref": "#/$defs/TriggerEvidence" }
1575
+ },
1576
+ "disposition": {
1577
+ "enum": ["inline-contract", "prep-item", "not-applicable"]
1578
+ },
1579
+ "inlineContract": { "$ref": "#/$defs/InlineDesignContract" },
1580
+ "prepItemId": {
1581
+ "type": "string",
1582
+ "pattern": "^PREP-[0-9]{3}$"
1583
+ },
1584
+ "prepItemIds": {
1585
+ "type": "array",
1586
+ "minItems": 1,
1587
+ "uniqueItems": true,
1588
+ "items": { "type": "string", "pattern": "^PREP-[0-9]{3}$" }
1589
+ },
1590
+ "rationale": { "type": "string", "minLength": 1 }
1591
+ },
1592
+ "oneOf": [
1593
+ {
1594
+ "properties": { "disposition": { "const": "inline-contract" } },
1595
+ "required": ["inlineContract"],
1596
+ "allOf": [
1597
+ { "not": { "required": ["prepItemId"] } },
1598
+ { "not": { "required": ["prepItemIds"] } },
1599
+ { "not": { "required": ["rationale"] } }
1600
+ ]
1601
+ },
1602
+ {
1603
+ "properties": { "disposition": { "const": "prep-item" } },
1604
+ "allOf": [
1605
+ { "not": { "required": ["inlineContract"] } },
1606
+ { "not": { "required": ["rationale"] } }
1607
+ ],
1608
+ "oneOf": [
1609
+ {
1610
+ "required": ["prepItemId"],
1611
+ "not": { "required": ["prepItemIds"] }
1612
+ },
1613
+ {
1614
+ "required": ["prepItemIds"],
1615
+ "not": { "required": ["prepItemId"] }
1616
+ }
1617
+ ]
1618
+ },
1619
+ {
1620
+ "properties": { "disposition": { "const": "not-applicable" } },
1621
+ "required": ["rationale"],
1622
+ "allOf": [
1623
+ { "not": { "required": ["inlineContract"] } },
1624
+ { "not": { "required": ["prepItemId"] } },
1625
+ { "not": { "required": ["prepItemIds"] } }
1626
+ ]
1627
+ }
1628
+ ]
1629
+ },
1630
+
1299
1631
  "ImplementationPlanStage": {
1300
1632
  "type": "object",
1301
1633
  "required": [
@@ -1364,6 +1696,10 @@
1364
1696
  "maxItems": 6,
1365
1697
  "items": { "$ref": "#/$defs/StageStepRow" }
1366
1698
  },
1699
+ "designSurfaceCoverage": {
1700
+ "type": "array",
1701
+ "items": { "$ref": "#/$defs/DesignSurfaceCoverage" }
1702
+ },
1367
1703
  "exitContract": { "type": "string", "minLength": 1 },
1368
1704
  "stageValidation": { "type": "string", "minLength": 1 }
1369
1705
  }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: okstra-inspect
3
3
  description: >-
4
- Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (결론·통과); its elapsed time (소요 시간) or context/read cost (컨텍스트 비용); its run history, re-run, or resume; to mark it done / in-progress / blocked / todo; or a failed run's error logs gathered into a report (에러 리포트). Also bundles cross-project okstra errors into an anonymized feedback zip (에러 환류). Use it even for a bare "mark it done" or "where's the report." NOT for starting a run (okstra-run), rollups/schedules (okstra-rollup / okstra-schedule), a brief (okstra-brief-gen), setup (okstra-setup), or cross-project management (okstra-manager).
4
+ Use this for everything that happens AFTER a single okstra task has already run — inspecting it or light bookkeeping on it, never launching new work. The tell is usually a named task id (PROD-1623, dev-9184), often dropped without the word "okstra." Reach for it when the user wants one task's: status, current/next phase, blockers, or approval gate; its final report — where it is or whether it passed (결론·통과); its elapsed time (소요 시간) or context/read cost (컨텍스트 비용); its run history, re-run, or resume; to mark it done / in-progress / blocked / todo; or a failed run's error logs gathered into a report (에러 리포트). Also bundles cross-project okstra errors into an anonymized feedback zip (에러 환류). Use it even for a bare "mark it done" or "where's the report." NOT for starting a run (okstra-run), rollups/schedules (okstra-rollup / okstra-schedule-gen), a brief (okstra-brief-gen), setup (okstra-setup), or cross-project management (okstra-manager).
5
5
  ---
6
6
 
7
7
  # OKSTRA Inspect
@@ -186,7 +186,7 @@ Confirm in Korean:
186
186
 
187
187
  Annotate inferred values with `(inferred)` or `(default)`. Do not back-fill on read; only write when the user explicitly issues an update.
188
188
 
189
- **Catalog sync note:** the CLI updates `task-manifest.json` only. `discovery/task-catalog.json` may be stale until the next run regenerates it; downstream consumers (e.g. `okstra-schedule`) re-read each manifest directly.
189
+ **Catalog sync note:** the CLI updates `task-manifest.json` only. `discovery/task-catalog.json` may be stale until the next run regenerates it; downstream consumers (e.g. `okstra-schedule-gen`) re-read each manifest directly.
190
190
 
191
191
  ---
192
192
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: okstra-rollup
3
3
  description: |
4
- Use when the user wants run results from MULTIPLE okstra tasks collected and summarized at once — a task-group digest or a whole-project roll-up, not a single task. Aggregates per-task run count, elapsed time, error count, and latest report path, plus group-level totals and status/category/phase tallies, then synthesizes a cross-task prose summary from the report files. Make sure to use this skill whenever the user mentions "okstra rollup", "롤업", "task-group 요약", "그룹 단위 리포트", "여러 task 결과 모아", "전체 task 현황 요약", "cross-task summary", "그룹 종합 리포트", "모든 task 정리", "run 결과 한꺼번에", even if they don't say "rollup". For a SINGLE task's report/time/errors/recap use okstra-inspect instead; for a forward-looking work plan over non-done tasks use okstra-schedule.
4
+ Use when the user wants run results from MULTIPLE okstra tasks collected and summarized at once — a task-group digest or a whole-project roll-up, not a single task. Aggregates per-task run count, elapsed time, error count, and latest report path, plus group-level totals and status/category/phase tallies, then synthesizes a cross-task prose summary from the report files. Make sure to use this skill whenever the user mentions "okstra rollup", "롤업", "task-group 요약", "그룹 단위 리포트", "여러 task 결과 모아", "전체 task 현황 요약", "cross-task summary", "그룹 종합 리포트", "모든 task 정리", "run 결과 한꺼번에", even if they don't say "rollup". For a SINGLE task's report/time/errors/recap use okstra-inspect instead; for a forward-looking work plan over non-done tasks use okstra-schedule-gen.
5
5
  ---
6
6
 
7
7
  # OKSTRA Rollup
@@ -1,10 +1,10 @@
1
1
  ---
2
- name: okstra-schedule
2
+ name: okstra-schedule-gen
3
3
  description: Use when the user asks for a task-group work schedule, a consolidated implementation plan across multiple tasks in a task-group, or wants to generate a "schedule" / "일정" / "작업 계획표" for non-done tasks. Trigger words include "okstra schedule", "<task-group> 일정 만들어", "<task-group> schedule 생성", "task-group 작업 계획".
4
4
  model: opus
5
5
  ---
6
6
 
7
- # OKSTRA Schedule
7
+ # OKSTRA Schedule Gen
8
8
 
9
9
  Generate a consolidated work schedule for the selected `implementation-planning` stages of every non-done task in a given `task-group` (or a single `task-id`). For each task the skill reads its `implementation-planning` final-report **Stage Map** as the authoritative forward-looking decomposition, asks the user which stages to include, drafts a single Markdown plan, and only writes the final file after an **independent verifier subagent** confirms the draft covers exactly the selected stages. It runs as a **lead + verifier** flow; the frontmatter `model: opus` switches supporting harnesses to Opus-class for the turn — stage-level cross-task synthesis needs that reasoning depth.
10
10
 
@@ -57,19 +57,21 @@ Carry the chosen entry's `reportPath` and `taskKey` forward.
57
57
  okstra user-response show --report <reportPath>
58
58
  ```
59
59
 
60
- Returns `{reportPath, rows: [{id, kind, blocks, status, statement, recommended, alternatives, contextRefs}]}`. For each open `C-*` row, present to the user:
60
+ Returns `{reportPath, rows: [{id, kind, blocks, status, statement, recommended, alternatives, contextRefs, resolvedRefs}]}`. `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).
61
61
 
62
- - **`id`** and its **`statement`** (the original question).
63
- - **`recommended`** — the answer okstra proposed (+ rationale). It is only a recommendation.
64
- - **`alternatives[]`**list them if present.
65
- - **`contextRefs[]`** — the report `§`/`C-id`/`path:line` references this question points at.
62
+ **Do NOT paste the raw `statement` as the question.** A `statement` like `Rewrite RB-002 rollback (see §4.7)` is meaningless to the user on its own — that is the whole reason this skill exists. For each open `C-*` row, you MUST present:
63
+
64
+ - **A rewritten, self-contained question** (lead with this): rewrite `statement` in plain language with **every internal token expanded inline** from its `resolvedRefs` `definition` the user must never have to know what `RB-002` is to answer. If a token's `definition` is `null`, resolve it yourself **using Read** on the report `§`/`path:line` before asking; only if it is genuinely unresolvable do you say so plainly.
65
+ - **`recommended`** — the answer okstra proposed (+ rationale), also stated in plain language. It is only a recommendation.
66
+ - **`alternatives[]`** — list them if present, each in plain language.
67
+ - **Raw source** (secondary, for traceability): the raw `id` + `statement` so the mapping back to the report stays visible.
66
68
 
67
69
  ## Step 3: Per-item — collect the user's decision (4 branches)
68
70
 
69
71
  For each open item, the user picks one of four dispositions. You relay and transcribe; you never choose:
70
72
 
71
73
  1. **Answer** — the user accepts the recommendation or gives their own answer. `disposition: "answer"`, `value` = the user's utterance verbatim.
72
- 2. **Ask-to-explain** — if the user asks "what does this mean?", open the report `§`/`path:line` that this item's `contextRefs[]` points at **using Read** and explain it in plain language. Only explain — **do not pick the answer for the user**; after explaining, hand the decision back to the user.
74
+ 2. **Ask-to-explain (fallback)** — Step 2 already expanded every internal token, so the question should already be self-contained. If the user still asks "what does this mean?" or a `resolvedRefs` `definition` was `null`, open the report `§`/`path:line` that this item's `contextRefs[]` points at **using Read** and explain it in plain language. Only explain — **do not pick the answer for the user**; after explaining, hand the decision back to the user.
73
75
  3. **Free-form** — the user gives a narrative answer that matches neither a recommendation nor an alternative. `value` = that narrative verbatim, with the rationale in `rationale` if needed. `disposition: "answer"`.
74
76
  4. **Hold + reframe** — if the user asks to "re-frame this question itself", record it as `disposition: "reframe"`. Put what the user wants re-asked into `value` verbatim. A reframe is not an answer, so it does not satisfy the approval gate — the next run re-frames that question.
75
77
 
@@ -387,6 +387,73 @@ Carried-forward plan items retain their prior verdicts verbatim; each such item
387
387
  {% endfor %}
388
388
  {%- endif %}
389
389
 
390
+ ### 5.5.10 Implementation Design Preparation{% if t("implementationPlanning.designPreparation.heading") != "Implementation Design Preparation" %} ({{ t("implementationPlanning.designPreparation.heading") }}){% endif %}
391
+
392
+ - **{{ t("implementationPlanning.designPreparation.mode") }}:** `{{ implementationPlanning.designPreparation.mode }}`
393
+ - **{{ t("implementationPlanning.designPreparation.reason") }}:** {{ implementationPlanning.designPreparation.reason }}
394
+
395
+ {% if implementationPlanning.designPreparation["items"] | length == 0 -%}
396
+ {{ t("implementationPlanning.designPreparation.empty") }}
397
+ {%- else %}
398
+ {% for item in implementationPlanning.designPreparation["items"] %}
399
+ #### {{ item.id }} — {{ item.title }}
400
+
401
+ - **{{ t("implementationPlanning.designPreparation.kind") }}:** `{{ item.kind }}`
402
+ - **{{ t("implementationPlanning.designPreparation.status") }}:** `{{ item.status }}`
403
+ - **{{ t("implementationPlanning.designPreparation.stages") }}:** {{ item.stageRefs | join(", ") }}
404
+ - **{{ t("implementationPlanning.designPreparation.need") }}:** {{ item.need }}
405
+ {% if item.knownFacts %}
406
+ - **{{ t("implementationPlanning.designPreparation.knownFacts") }}:**
407
+ {% for fact in item.knownFacts %}
408
+ - {{ fact.statement }} — {{ fact.evidence }}
409
+ {% endfor %}
410
+ {% endif %}
411
+ {% if item.openQuestions %}
412
+ - **{{ t("implementationPlanning.designPreparation.openQuestions") }}:** {{ item.openQuestions | join("; ") }}
413
+ {% endif %}
414
+ - **{{ t("implementationPlanning.designPreparation.aiProposal") }}:** {{ item.aiProposal.summary }}
415
+ - **{{ t("implementationPlanning.designPreparation.proposalDetails") }}:** {{ item.aiProposal.details | join("; ") or t("implementationPlanning.designPreparation.none") }}
416
+ - **{{ t("implementationPlanning.designPreparation.proposalAssumptions") }}:** {{ item.aiProposal.assumptions | join("; ") or t("implementationPlanning.designPreparation.none") }}
417
+ - **{{ t("implementationPlanning.designPreparation.proposalEvidence") }}:** {{ item.aiProposal.evidence | join("; ") or t("implementationPlanning.designPreparation.none") }}
418
+ - **{{ t("implementationPlanning.designPreparation.proposalConfidence") }}:** `{{ item.aiProposal.confidence }}`
419
+ - **{{ t("implementationPlanning.designPreparation.humanConfirmation") }}:**
420
+ - **{{ t("implementationPlanning.designPreparation.confirmationRequired") }}:** `{% if item.humanConfirmation.required %}yes{% else %}no{% endif %}`
421
+ - **{{ t("implementationPlanning.designPreparation.confirmationReason") }}:** {{ item.humanConfirmation.reason }}
422
+ - **{{ t("implementationPlanning.designPreparation.suggestedAction") }}:** {{ item.humanConfirmation.suggestedAction }}
423
+ {% if item.replanTriggerFields %}
424
+ - **{{ t("implementationPlanning.designPreparation.replanTriggerFields") }}:** `{{ item.replanTriggerFields | join("`, `") }}`
425
+ {% endif %}
426
+ {% if item.workingAssumption %}
427
+ - **{{ t("implementationPlanning.designPreparation.workingAssumption") }}:** {{ item.workingAssumption }}
428
+ {% endif %}
429
+ {% if item.guardrails %}
430
+ - **{{ t("implementationPlanning.designPreparation.guardrails") }}:** {{ item.guardrails | join("; ") }}
431
+ {% endif %}
432
+ {% if item.reviewAt %}
433
+ {% if item.reviewAt.stage %}
434
+ - **{{ t("implementationPlanning.designPreparation.reviewAt") }}:** {{ item.reviewAt.phase }} — stage {{ item.reviewAt.stage }}
435
+ {% else %}
436
+ - **{{ t("implementationPlanning.designPreparation.reviewAt") }}:** {{ item.reviewAt.phase }}
437
+ {% endif %}
438
+ {% endif %}
439
+ {% if item.ifStillOpen %}
440
+ - **{{ t("implementationPlanning.designPreparation.ifStillOpen") }}:** `{{ item.ifStillOpen }}`
441
+ {% endif %}
442
+ {% if item.requestPath %}
443
+ - **{{ t("implementationPlanning.designPreparation.requestPath") }}:** `{{ item.requestPath }}`
444
+ {% endif %}
445
+ {% if item.blockReason %}
446
+ - **{{ t("implementationPlanning.designPreparation.blockReason") }}:** {{ item.blockReason }}
447
+ {% endif %}
448
+ {% if item.requiredDecision %}
449
+ - **{{ t("implementationPlanning.designPreparation.requiredDecision") }}:** {{ item.requiredDecision }}
450
+ {% endif %}
451
+ {% if item.notApplicableReason %}
452
+ - **{{ t("implementationPlanning.designPreparation.notApplicableReason") }}:** {{ item.notApplicableReason }}
453
+ {% endif %}
454
+ {% endfor %}
455
+ {%- endif %}
456
+
390
457
  {% endif %}
391
458
  {% if header.taskType == 'release-handoff' %}
392
459
  ## 5.6 Release Handoff Deliverables
@@ -129,6 +129,37 @@
129
129
  "decision": "Decision",
130
130
  "consequences": "Consequences",
131
131
  "alternativesConsidered": "Alternatives Considered"
132
+ },
133
+ "designPreparation": {
134
+ "heading": "Implementation Design Preparation",
135
+ "mode": "Mode",
136
+ "reason": "Reason",
137
+ "kind": "Kind",
138
+ "status": "Status",
139
+ "stages": "Stages",
140
+ "need": "Need",
141
+ "knownFacts": "Known facts",
142
+ "openQuestions": "Open questions",
143
+ "aiProposal": "AI proposal",
144
+ "proposalDetails": "Details",
145
+ "proposalAssumptions": "Assumptions",
146
+ "proposalEvidence": "Evidence",
147
+ "proposalConfidence": "Confidence",
148
+ "humanConfirmation": "Human confirmation",
149
+ "confirmationRequired": "Required",
150
+ "confirmationReason": "Confirmation reason",
151
+ "suggestedAction": "Suggested action",
152
+ "replanTriggerFields": "Replan trigger fields",
153
+ "workingAssumption": "Working assumption",
154
+ "guardrails": "Guardrails",
155
+ "reviewAt": "Review at",
156
+ "ifStillOpen": "If still open",
157
+ "requestPath": "Request path",
158
+ "blockReason": "Block reason",
159
+ "requiredDecision": "Required decision",
160
+ "notApplicableReason": "Not applicable reason",
161
+ "none": "(none)",
162
+ "empty": "No implementation design preparation items."
132
163
  }
133
164
  },
134
165
  "releaseHandoff": {
@@ -129,6 +129,37 @@
129
129
  "decision": "결정",
130
130
  "consequences": "결과",
131
131
  "alternativesConsidered": "검토한 대안"
132
+ },
133
+ "designPreparation": {
134
+ "heading": "구현 설계 준비",
135
+ "mode": "모드",
136
+ "reason": "이유",
137
+ "kind": "종류",
138
+ "status": "상태",
139
+ "stages": "스테이지",
140
+ "need": "필요성",
141
+ "knownFacts": "확인된 사실",
142
+ "openQuestions": "열린 질문",
143
+ "aiProposal": "AI 제안",
144
+ "proposalDetails": "세부 내용",
145
+ "proposalAssumptions": "가정",
146
+ "proposalEvidence": "근거",
147
+ "proposalConfidence": "신뢰도",
148
+ "humanConfirmation": "사람 확인",
149
+ "confirmationRequired": "필수 여부",
150
+ "confirmationReason": "확인 이유",
151
+ "suggestedAction": "권장 조치",
152
+ "replanTriggerFields": "재계획 트리거 필드",
153
+ "workingAssumption": "작업 가정",
154
+ "guardrails": "가드레일",
155
+ "reviewAt": "검토 시점",
156
+ "ifStillOpen": "미해결 시",
157
+ "requestPath": "요청 경로",
158
+ "blockReason": "차단 이유",
159
+ "requiredDecision": "필요한 결정",
160
+ "notApplicableReason": "해당 없음 이유",
161
+ "none": "(없음)",
162
+ "empty": "구현 설계 준비 항목이 없습니다."
132
163
  }
133
164
  },
134
165
  "releaseHandoff": {