okstra 0.200.0 → 0.201.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 (96) hide show
  1. package/README.md +4 -2
  2. package/dist/cli-registry.mjs +6 -0
  3. package/dist/cli-registry.mjs.map +1 -1
  4. package/docs/cli.md +14 -3
  5. package/package.json +1 -1
  6. package/runtime/BUILD.json +2 -2
  7. package/runtime/agents/workers/report-writer-worker.md +7 -3
  8. package/runtime/bin/okstra-spawn-followups.py +2 -2
  9. package/runtime/prompts/duties/technical-verification-worker.md +44 -0
  10. package/runtime/prompts/launch.template.md +7 -1
  11. package/runtime/prompts/lead/okstra-lead-contract.md +7 -2
  12. package/runtime/prompts/lead/plan-body-verification.md +3 -1
  13. package/runtime/prompts/lead/report-writer.md +11 -5
  14. package/runtime/prompts/lead/team-contract.md +6 -0
  15. package/runtime/prompts/profiles/_implementation-verifier.md +7 -1
  16. package/runtime/prompts/profiles/final-verification.md +5 -0
  17. package/runtime/prompts/profiles/forbidden-actions.json +6 -0
  18. package/runtime/prompts/profiles/implementation-option-selection.md +7 -1
  19. package/runtime/prompts/profiles/implementation-planning.md +1 -0
  20. package/runtime/prompts/profiles/technical-verification.md +53 -0
  21. package/runtime/prompts/wizard/prompts.ko.json +2 -1
  22. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +4 -4
  23. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +2 -0
  24. package/runtime/python/okstra_ctl/adapters/providers/zai/adapter.py +36 -5
  25. package/runtime/python/okstra_ctl/agent/invocation.py +14 -6
  26. package/runtime/python/okstra_ctl/agent/prompt_cli/cli.py +4 -3
  27. package/runtime/python/okstra_ctl/agent/prompt_cli/corrections.py +83 -22
  28. package/runtime/python/okstra_ctl/agent/prompt_cli/materialize.py +44 -2
  29. package/runtime/python/okstra_ctl/conformance.py +2 -20
  30. package/runtime/python/okstra_ctl/dispatch_core.py +25 -5
  31. package/runtime/python/okstra_ctl/dispatch_state.py +2 -0
  32. package/runtime/python/okstra_ctl/domain/provider.py +0 -1
  33. package/runtime/python/okstra_ctl/domain/role.py +1 -0
  34. package/runtime/python/okstra_ctl/execution_mutation_audit.py +6 -1
  35. package/runtime/python/okstra_ctl/implementation_direction.py +64 -7
  36. package/runtime/python/okstra_ctl/implementation_options.py +58 -45
  37. package/runtime/python/okstra_ctl/model_pool.py +2 -5
  38. package/runtime/python/okstra_ctl/next_phase.py +3 -0
  39. package/runtime/python/okstra_ctl/plan_items.py +15 -0
  40. package/runtime/python/okstra_ctl/plan_items_cli.py +9 -3
  41. package/runtime/python/okstra_ctl/qa_commands.py +30 -0
  42. package/runtime/python/okstra_ctl/registry/provider_registry.py +11 -8
  43. package/runtime/python/okstra_ctl/render.py +3 -0
  44. package/runtime/python/okstra_ctl/render_final_report.py +1 -0
  45. package/runtime/python/okstra_ctl/report_assembly.py +8 -2
  46. package/runtime/python/okstra_ctl/report_contract.py +3 -0
  47. package/runtime/python/okstra_ctl/report_corrections.py +209 -93
  48. package/runtime/python/okstra_ctl/report_finalize.py +25 -8
  49. package/runtime/python/okstra_ctl/report_html/router.py +2 -0
  50. package/runtime/python/okstra_ctl/report_html/view_models/technical_verification.py +21 -0
  51. package/runtime/python/okstra_ctl/report_projections.py +4 -3
  52. package/runtime/python/okstra_ctl/report_synthesis_packet.py +181 -47
  53. package/runtime/python/okstra_ctl/run.py +82 -0
  54. package/runtime/python/okstra_ctl/team.py +4 -1
  55. package/runtime/python/okstra_ctl/technical_verification.py +195 -0
  56. package/runtime/python/okstra_ctl/usage_identity.py +54 -0
  57. package/runtime/python/okstra_ctl/usage_report.py +22 -8
  58. package/runtime/python/okstra_ctl/verification_target.py +74 -0
  59. package/runtime/python/okstra_ctl/wizard/__init__.py +1 -1
  60. package/runtime/python/okstra_ctl/wizard/cli.py +2 -1
  61. package/runtime/python/okstra_ctl/wizard/confirmation.py +38 -2
  62. package/runtime/python/okstra_ctl/wizard/engine.py +3 -0
  63. package/runtime/python/okstra_ctl/wizard/ids.py +1 -0
  64. package/runtime/python/okstra_ctl/wizard/outcome.py +63 -0
  65. package/runtime/python/okstra_ctl/wizard/picker_navigation.py +2 -2
  66. package/runtime/python/okstra_ctl/wizard/registry.py +1 -1
  67. package/runtime/python/okstra_ctl/wizard/render.py +8 -55
  68. package/runtime/python/okstra_ctl/wizard/roles.py +11 -7
  69. package/runtime/python/okstra_ctl/wizard/sources.py +28 -2
  70. package/runtime/python/okstra_ctl/wizard/state.py +13 -6
  71. package/runtime/python/okstra_ctl/wizard/steps_plan.py +8 -0
  72. package/runtime/python/okstra_ctl/worker_liveness.py +52 -39
  73. package/runtime/python/okstra_ctl/worker_prompt_policy.py +2 -0
  74. package/runtime/python/okstra_ctl/workflow.py +8 -0
  75. package/runtime/python/okstra_ctl/write_policy.py +23 -0
  76. package/runtime/python/okstra_token_usage/blocks.py +50 -1
  77. package/runtime/python/okstra_token_usage/claude.py +42 -21
  78. package/runtime/python/okstra_token_usage/codex.py +17 -0
  79. package/runtime/python/okstra_token_usage/collect.py +299 -162
  80. package/runtime/python/okstra_token_usage/cursor.py +2 -3
  81. package/runtime/python/okstra_token_usage/report.py +35 -30
  82. package/runtime/python/okstra_token_usage/task_totals.py +3 -12
  83. package/runtime/schemas/final-report-v2.0.schema.json +298 -7
  84. package/runtime/schemas/final-report-v3.0.schema.json +298 -7
  85. package/runtime/schemas/report-narrative-v3.0.schema.json +1 -0
  86. package/runtime/schemas/report-synthesis-packet-v1.0.schema.json +1 -1
  87. package/runtime/schemas/report-writer-corrections-v1.0.schema.json +30 -3
  88. package/runtime/skills/okstra-run/SKILL.md +10 -2
  89. package/runtime/skills/okstra-setup/SKILL.md +42 -7
  90. package/runtime/templates/report-writer-prompt-preamble.md +7 -3
  91. package/runtime/templates/reports/html/i18n/en.json +11 -0
  92. package/runtime/templates/reports/html/i18n/ko.json +11 -0
  93. package/runtime/templates/reports/html/tasks/implementation-option-selection.template.html +7 -3
  94. package/runtime/templates/reports/html/tasks/technical-verification.template.html +35 -0
  95. package/runtime/templates/reports/md/tasks/technical-verification.template.md +5 -0
  96. package/runtime/validators/validate-run.py +9 -4
@@ -25,6 +25,7 @@
25
25
  ],
26
26
  "additionalProperties": false,
27
27
  "properties": {
28
+ "technicalVerification": {"$ref": "#/$defs/TechnicalVerification"},
28
29
  "schemaVersion": {
29
30
  "const": "3.0",
30
31
  "description": "Schema version. Renderer refuses to process unknown versions."
@@ -1664,6 +1665,86 @@
1664
1665
  }
1665
1666
  },
1666
1667
  "allOf": [
1668
+ {
1669
+ "if": {
1670
+ "properties": {
1671
+ "header": {
1672
+ "properties": {
1673
+ "taskType": {
1674
+ "const": "technical-verification"
1675
+ }
1676
+ }
1677
+ }
1678
+ },
1679
+ "required": [
1680
+ "header"
1681
+ ]
1682
+ },
1683
+ "then": {
1684
+ "required": [
1685
+ "technicalVerification"
1686
+ ],
1687
+ "properties": {
1688
+ "frontmatter": {
1689
+ "properties": {
1690
+ "approved": {
1691
+ "const": false
1692
+ }
1693
+ }
1694
+ },
1695
+ "implementationOptionSelection": false,
1696
+ "implementationPlanning": false,
1697
+ "implementation": false,
1698
+ "finalVerification": false,
1699
+ "releaseHandoff": false,
1700
+ "errorAnalysis": false,
1701
+ "requirementsDiscovery": false,
1702
+ "improvementDiscovery": false,
1703
+ "analysisCommon": false,
1704
+ "projectAnalysis": false,
1705
+ "featureAnalysis": false,
1706
+ "changeImpactAnalysis": false,
1707
+ "followUpTasks": {
1708
+ "contains": {
1709
+ "properties": {
1710
+ "origin": {
1711
+ "const": "phase-continuation"
1712
+ }
1713
+ },
1714
+ "required": [
1715
+ "origin"
1716
+ ]
1717
+ },
1718
+ "minContains": 1,
1719
+ "maxContains": 1,
1720
+ "items": {
1721
+ "if": {
1722
+ "properties": {
1723
+ "origin": {
1724
+ "const": "phase-continuation"
1725
+ }
1726
+ },
1727
+ "required": [
1728
+ "origin"
1729
+ ]
1730
+ },
1731
+ "then": {
1732
+ "properties": {
1733
+ "suggestedTaskType": {
1734
+ "const": "implementation-option-selection"
1735
+ }
1736
+ }
1737
+ }
1738
+ }
1739
+ }
1740
+ }
1741
+ },
1742
+ "else": {
1743
+ "properties": {
1744
+ "technicalVerification": false
1745
+ }
1746
+ }
1747
+ },
1667
1748
  {
1668
1749
  "description": "Frontmatter approval input matches the implementation-planning contract.",
1669
1750
  "if": {
@@ -2013,6 +2094,7 @@
2013
2094
  "properties": {
2014
2095
  "taskType": {
2015
2096
  "enum": [
2097
+ "technical-verification",
2016
2098
  "requirements-discovery",
2017
2099
  "project-analysis",
2018
2100
  "feature-analysis",
@@ -2192,6 +2274,7 @@
2192
2274
  }
2193
2275
  ],
2194
2276
  "oneOf": [
2277
+ {"required": ["technicalVerification"]},
2195
2278
  {
2196
2279
  "required": [
2197
2280
  "requirementsDiscovery"
@@ -3079,7 +3162,8 @@
3079
3162
  "enum": [
3080
3163
  "pending-direction-selection",
3081
3164
  "implementation-planning",
3082
- "blocked"
3165
+ "blocked",
3166
+ "technical-verification"
3083
3167
  ]
3084
3168
  },
3085
3169
  "userNarrative": {
@@ -3745,6 +3829,17 @@
3745
3829
  ],
3746
3830
  "additionalProperties": false,
3747
3831
  "properties": {
3832
+ "resolutionKind": {
3833
+ "type": "string",
3834
+ "enum": ["user-decision", "technical-verification"],
3835
+ "description": "Optional for historical reads; blocked report publication requires explicit classification."
3836
+ },
3837
+ "clarificationRefs": {
3838
+ "type": "array",
3839
+ "uniqueItems": true,
3840
+ "items": {"type": "string", "pattern": "^C-[0-9]{3}$"},
3841
+ "description": "User decisions require nonempty references to actual clarification records, including answered records."
3842
+ },
3748
3843
  "fact": {
3749
3844
  "type": "string",
3750
3845
  "minLength": 1
@@ -4060,7 +4155,7 @@
4060
4155
  },
4061
4156
  "stageRefs": {
4062
4157
  "type": "array",
4063
- "minItems": 1,
4158
+ "minItems": 0,
4064
4159
  "uniqueItems": true,
4065
4160
  "items": {
4066
4161
  "type": "integer",
@@ -4069,7 +4164,7 @@
4069
4164
  },
4070
4165
  "stepRefs": {
4071
4166
  "type": "array",
4072
- "minItems": 1,
4167
+ "minItems": 0,
4073
4168
  "uniqueItems": true,
4074
4169
  "items": {
4075
4170
  "type": "string",
@@ -4078,7 +4173,7 @@
4078
4173
  },
4079
4174
  "validationRefs": {
4080
4175
  "type": "array",
4081
- "minItems": 1,
4176
+ "minItems": 0,
4082
4177
  "uniqueItems": true,
4083
4178
  "items": {
4084
4179
  "type": "string",
@@ -4087,7 +4182,7 @@
4087
4182
  },
4088
4183
  "fileRefs": {
4089
4184
  "type": "array",
4090
- "minItems": 1,
4185
+ "minItems": 0,
4091
4186
  "uniqueItems": true,
4092
4187
  "items": {
4093
4188
  "type": "string",
@@ -4097,10 +4192,59 @@
4097
4192
  "status": {
4098
4193
  "enum": [
4099
4194
  "covered",
4100
- "not-covered"
4195
+ "not-covered",
4196
+ "externally-tracked"
4101
4197
  ]
4198
+ },
4199
+ "crossProjectDependencyRefs": {
4200
+ "type": "array",
4201
+ "uniqueItems": true,
4202
+ "items": {
4203
+ "type": "string",
4204
+ "pattern": "^XP-[0-9]{3,}$"
4205
+ }
4102
4206
  }
4103
- }
4207
+ },
4208
+ "oneOf": [
4209
+ {
4210
+ "properties": {
4211
+ "status": {
4212
+ "enum": [
4213
+ "covered",
4214
+ "not-covered"
4215
+ ]
4216
+ },
4217
+ "stageRefs": {
4218
+ "minItems": 1
4219
+ },
4220
+ "stepRefs": {
4221
+ "minItems": 1
4222
+ },
4223
+ "validationRefs": {
4224
+ "minItems": 1
4225
+ },
4226
+ "fileRefs": {
4227
+ "minItems": 1
4228
+ },
4229
+ "crossProjectDependencyRefs": {
4230
+ "maxItems": 0
4231
+ }
4232
+ }
4233
+ },
4234
+ {
4235
+ "required": [
4236
+ "crossProjectDependencyRefs"
4237
+ ],
4238
+ "properties": {
4239
+ "status": {
4240
+ "const": "externally-tracked"
4241
+ },
4242
+ "crossProjectDependencyRefs": {
4243
+ "minItems": 1
4244
+ }
4245
+ }
4246
+ }
4247
+ ]
4104
4248
  },
4105
4249
  "SelectedDirectionCoverageSummary": {
4106
4250
  "type": "object",
@@ -4166,8 +4310,155 @@
4166
4310
  }
4167
4311
  }
4168
4312
  },
4313
+ "TechnicalVerification": {
4314
+ "type": "object",
4315
+ "additionalProperties": false,
4316
+ "required": [
4317
+ "sourceReport",
4318
+ "sourceDataSha256",
4319
+ "scope",
4320
+ "checks",
4321
+ "routing"
4322
+ ],
4323
+ "properties": {
4324
+ "sourceReport": {
4325
+ "type": "string",
4326
+ "minLength": 1
4327
+ },
4328
+ "sourceDataSha256": {
4329
+ "type": "string",
4330
+ "pattern": "^[0-9a-f]{64}$"
4331
+ },
4332
+ "scope": {
4333
+ "const": "technical-evidence-only"
4334
+ },
4335
+ "checks": {
4336
+ "type": "array",
4337
+ "minItems": 1,
4338
+ "items": {
4339
+ "type": "object",
4340
+ "additionalProperties": false,
4341
+ "required": [
4342
+ "id",
4343
+ "candidateId",
4344
+ "factIndex",
4345
+ "fact",
4346
+ "hypothesis",
4347
+ "procedure",
4348
+ "confirmingSignal",
4349
+ "rejectingSignal",
4350
+ "status",
4351
+ "commands",
4352
+ "observation",
4353
+ "limitations"
4354
+ ],
4355
+ "properties": {
4356
+ "id": {
4357
+ "type": "string",
4358
+ "pattern": "^TV-[0-9]{3}$"
4359
+ },
4360
+ "candidateId": {
4361
+ "type": "string",
4362
+ "pattern": "^IO-[0-9]{3}$"
4363
+ },
4364
+ "factIndex": {
4365
+ "type": "integer",
4366
+ "minimum": 0
4367
+ },
4368
+ "fact": {
4369
+ "type": "string",
4370
+ "minLength": 1
4371
+ },
4372
+ "hypothesis": {
4373
+ "type": "string",
4374
+ "minLength": 1
4375
+ },
4376
+ "procedure": {
4377
+ "type": "string",
4378
+ "minLength": 1
4379
+ },
4380
+ "confirmingSignal": {
4381
+ "type": "string",
4382
+ "minLength": 1
4383
+ },
4384
+ "rejectingSignal": {
4385
+ "type": "string",
4386
+ "minLength": 1
4387
+ },
4388
+ "status": {
4389
+ "enum": [
4390
+ "supported",
4391
+ "refuted",
4392
+ "inconclusive",
4393
+ "not-run"
4394
+ ]
4395
+ },
4396
+ "commands": {
4397
+ "type": "array",
4398
+ "items": {
4399
+ "type": "object",
4400
+ "additionalProperties": false,
4401
+ "required": [
4402
+ "command",
4403
+ "cwd",
4404
+ "exitCode",
4405
+ "logPath"
4406
+ ],
4407
+ "properties": {
4408
+ "command": {
4409
+ "type": "string",
4410
+ "minLength": 1
4411
+ },
4412
+ "cwd": {
4413
+ "type": "string",
4414
+ "minLength": 1
4415
+ },
4416
+ "exitCode": {
4417
+ "type": "integer"
4418
+ },
4419
+ "logPath": {
4420
+ "type": "string",
4421
+ "minLength": 1
4422
+ }
4423
+ }
4424
+ }
4425
+ },
4426
+ "observation": {
4427
+ "type": "string",
4428
+ "minLength": 1
4429
+ },
4430
+ "limitations": {
4431
+ "type": "array",
4432
+ "items": {
4433
+ "type": "string",
4434
+ "minLength": 1
4435
+ }
4436
+ }
4437
+ }
4438
+ }
4439
+ },
4440
+ "routing": {
4441
+ "type": "object",
4442
+ "additionalProperties": false,
4443
+ "required": [
4444
+ "nextTaskType",
4445
+ "rationale"
4446
+ ],
4447
+ "properties": {
4448
+ "nextTaskType": {
4449
+ "const": "implementation-option-selection"
4450
+ },
4451
+ "rationale": {
4452
+ "type": "string",
4453
+ "minLength": 1
4454
+ }
4455
+ }
4456
+ }
4457
+ }
4458
+ },
4169
4459
  "TaskType": {
4170
4460
  "enum": [
4461
+ "technical-verification",
4171
4462
  "requirements-discovery",
4172
4463
  "improvement-discovery",
4173
4464
  "error-analysis",
@@ -15,6 +15,7 @@
15
15
  "requirementsDiscovery": {"type": "object"},
16
16
  "improvementDiscovery": {"type": "object"},
17
17
  "errorAnalysis": {"type": "object"},
18
+ "technicalVerification": {"type": "object"},
18
19
  "analysisCommon": {"type": "object"},
19
20
  "projectAnalysis": {"type": "object"},
20
21
  "featureAnalysis": {"type": "object"},
@@ -111,7 +111,7 @@
111
111
  "minItems": 1,
112
112
  "items": {
113
113
  "type": "object",
114
- "required": ["label", "owner", "path", "digest", "content"],
114
+ "required": ["label", "owner", "path", "content"],
115
115
  "additionalProperties": false,
116
116
  "properties": {
117
117
  "label": {
@@ -13,13 +13,14 @@
13
13
  "minLength": 1,
14
14
  "description": "Project-relative path of the narrative attempt the corrections apply to."
15
15
  },
16
+ "baseNarrativeSha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
16
17
  "context": {
17
18
  "type": "string",
18
19
  "description": "Free text for the writer to read. Not normative; not validated."
19
20
  },
20
21
  "corrections": {
21
22
  "type": "array",
22
- "minItems": 1,
23
+ "minItems": 0,
23
24
  "items": { "$ref": "#/$defs/Correction" }
24
25
  }
25
26
  },
@@ -30,8 +31,10 @@
30
31
  "required": ["id", "kind", "path", "reason"],
31
32
  "properties": {
32
33
  "id": { "type": "string", "pattern": "^RC-[0-9]{3}$" },
33
- "kind": { "enum": ["replace", "remove", "rewrite"] },
34
+ "kind": { "enum": ["replace", "remove", "add", "move", "rewrite"] },
34
35
  "path": { "type": "string", "minLength": 1 },
36
+ "fromPath": { "type": "string", "minLength": 1 },
37
+ "evidenceRefs": { "type": "array", "items": { "type": "string", "minLength": 1 } },
35
38
  "current": {},
36
39
  "replacement": {},
37
40
  "rule": { "type": "string", "minLength": 1 },
@@ -39,14 +42,38 @@
39
42
  },
40
43
  "allOf": [
41
44
  {
42
- "if": { "properties": { "kind": { "const": "replace" } } },
45
+ "if": { "properties": { "kind": { "enum": ["replace", "add"] } } },
43
46
  "then": { "required": ["replacement"] }
44
47
  },
48
+ {
49
+ "if": { "properties": { "kind": { "const": "move" } } },
50
+ "then": { "required": ["fromPath"] }
51
+ },
45
52
  {
46
53
  "if": { "properties": { "kind": { "const": "rewrite" } } },
47
54
  "then": { "required": ["rule"] }
48
55
  }
49
56
  ]
57
+ },
58
+ "RewriteResults": {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "required": ["baseNarrativeSha256", "replacements"],
62
+ "properties": {
63
+ "baseNarrativeSha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
64
+ "replacements": {
65
+ "type": "array",
66
+ "items": {
67
+ "type": "object",
68
+ "additionalProperties": false,
69
+ "required": ["id", "replacement"],
70
+ "properties": {
71
+ "id": { "type": "string", "pattern": "^RC-[0-9]{3}$" },
72
+ "replacement": {}
73
+ }
74
+ }
75
+ }
76
+ }
50
77
  }
51
78
  }
52
79
  }
@@ -242,6 +242,8 @@ Output: `{ok: true, outcome: {renderArgv: ["--lead-runtime", "...", ...], render
242
242
 
243
243
  `renderArgv` is the canonical ordered `okstra render-bundle` argument list. Pass its tokens verbatim and in order. Repeated `--role-count` and `--role-model` flags are intentional. `renderArgs` is a compatibility and inspection view only; do not reconstruct an invocation from it. `orchestration` holds signals this skill acts on itself — never pass its entries to `render-bundle`.
244
244
 
245
+ `userAuthorization`, when present, preserves the confirmation prompt actually emitted by this wizard and the relayed `proceed` response. Its `--user-authorization-json` token carries that record into the run manifest; preserve it unchanged. Do not synthesize a receipt for older confirmed states. Include the translator's disclosed provider/model and report material when citing this record in host execution requests, including `report-finalize`. The record documents task scope; it does not grant host execution privileges.
246
+
245
247
  Run every `outcome.persistActions[]` entry BEFORE `render-bundle`. The only supported action is:
246
248
 
247
249
  ```json
@@ -441,7 +443,7 @@ Inform the user with one short line:
441
443
 
442
444
  ## Step 7: implementation unattended chaining (orchestration.chainStages)
443
445
 
444
- 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).
446
+ 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 ends this queue after same-run recovery is complete; a separately authorized continuous task follows the continuation rule below).
445
447
 
446
448
  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:
447
449
 
@@ -464,6 +466,12 @@ Do not read the wizard state file directly. `okstra wizard outcome` exposes any
464
466
  - Each wizard run owns its own state file (one per `okstra wizard new-state-file`); two parallel skill invocations do not collide.
465
467
  - The skill must NOT call `okstra.sh` (or any other bash entrypoint) that would re-implement the orchestration. The wizard + `render-bundle` is the single authority.
466
468
 
469
+ ## Authorized continuation
470
+
471
+ At a boundary, distinguish artifact recovery, the next item in the confirmed stage queue, and a new task scope. Continue `recovery.mode: same-run` with its supplied resume command. Continue a confirmed stage queue without asking for another invocation; the wizard receipt's `stageScope` records the displayed selection and prepare rejects stages outside it. For a broader continuous task, cite the user's actual instruction before moving to the recorded ready phase; do not expand a wizard receipt whose task type or inputs no longer match. Preserve approval gates, provider/material scope, and host execution permissions. If these changed or a required user decision remains unresolved, report that specific boundary.
472
+
473
+ A failed report assembly is not an implementation rejection. Read each skipped step's `blockedBy` value and repair its owning input; do not dispatch workers for derivative missing-file errors. Use the existing retry budget and stop with the first unresolved cause and resume location when an unchanged input produces the same failure without progress. At successful completion inside an authorized continuous scope, report progress and continue; offer `nextCommand` as a user action only when that scope has ended or a concrete boundary prevents continuation.
474
+
467
475
  ## Boundary updates
468
476
 
469
477
  Follow the rendered launch prompt's "Progress, remaining work, and recommendation" guidance at each phase or implementation-stage boundary, at task completion, and before a controlled session pause or handoff. Include results, remaining work, and the recommended action with its reason. During an authorized continuous run, report the boundary and continue the queue; when the lead returns, relay its closeout without repeating an already delivered update.
@@ -483,4 +491,4 @@ Follow the rendered launch prompt's "Progress, remaining work, and recommendatio
483
491
  - Echo each captured answer (`result.echo`) on one short line so the user sees what was registered.
484
492
  - Name every file you show the user as a markdown link — `[<what it is>](<path>)`, with the path inside the parentheses. That is the only form the host renders as clickable; a path in backticks is text the user has to copy out. The `report-finalize` result's `reportPaths.markdown` carries the run's report, report record, and team state already in that form. Commands stay in backticks — a link is for a file, not for something to run.
485
493
  - Never invent identity; if a `text` prompt returns an empty answer where the wizard rejects it, the user must retry.
486
- - 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. When `report-finalize` returns `recovery.mode: same-run`, continue the authorized corrections in this run and execute `recovery.resumeCommand` before closeout; preserve approvals and model choices without reopening the wizard. The command and owner issues are supplied by `report_finalize._finalize_recovery`. When the lead (or this skill, after the lead returns) reports a successfully finalized run over, close with the user's next action — one command they can run now. A prohibition is not a next action. Take the pointer from the `report-finalize` result's top-level `nextRecommendedPhase` (`phase`, `status`, `rationale`; also on stderr as `next phase status:` / `next phase:` / `next phase rationale:`) — do not re-derive it from the report, and treat a `nextRecommendedPhaseError` as "pointer unreadable", said in one line before the `validate-run` branch. The same result also carries `nextCommand` — `{command, note}`, the table below already applied to this run. When `command` is non-empty it is the close; when it is empty the `note` says what to do with the `rationale` instead. After `implementation-planning`, open `blocks: approval` rows → `/okstra-user-response`. A recorded `accept-risk` / `select` / `answer` is not an open blocker. No open approval blocker → `/okstra-run` → `implementation` or `--approve` (do not start another planning run; do not say `/okstra-inspect`). For every other task type, quote the pointer's `rationale` in every branch — that sentence is the report's own reason and it is what the user asked to be analysed. Pointer `status: ready` → `/okstra-run` for that phase; `status: terminal` → say the task is finished, name any follow-up tasks this run registered, and do not say `/okstra-inspect`; `status: blocked` → issue the command the `rationale` calls for (`/okstra-user-response` for the `C-NNN` ids, `/okstra-run` for the phase it names); `validate-run` failed with `recovery.mode: phase-reentry` → name the cause and use `nextCommand` for the recorded earlier phase; otherwise `/okstra-inspect status`.
494
+ - After Step 6, begin the lead workflow without re-summarizing the skill itself. For a single run, finish after Step 6 and any same-run recovery, unless the user has already authorized continuing the task through further phases. 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. When `report-finalize` returns `recovery.mode: same-run`, continue the authorized corrections in this run and execute `recovery.resumeCommand` before closeout; preserve approvals and model choices without reopening the wizard. The command and owner issues are supplied by `report_finalize._finalize_recovery`. When the lead (or this skill, after the lead returns) reports a successfully finalized run over, close with the user's next action — one command they can run now. A prohibition is not a next action. Take the pointer from the `report-finalize` result's top-level `nextRecommendedPhase` (`phase`, `status`, `rationale`; also on stderr as `next phase status:` / `next phase:` / `next phase rationale:`) — do not re-derive it from the report, and treat a `nextRecommendedPhaseError` as "pointer unreadable", said in one line before the `validate-run` branch. The same result also carries `nextCommand` — `{command, note}`, the table below already applied to this run. When `command` is non-empty it is the close; when it is empty the `note` says what to do with the `rationale` instead. After `implementation-planning`, open `blocks: approval` rows → `/okstra-user-response`. A recorded `accept-risk` / `select` / `answer` is not an open blocker. No open approval blocker → `/okstra-run` → `implementation` or `--approve` (do not start another planning run; do not say `/okstra-inspect`). For every other task type, quote the pointer's `rationale` in every branch — that sentence is the report's own reason and it is what the user asked to be analysed. Pointer `status: ready` → `/okstra-run` for that phase; `status: terminal` → say the task is finished, name any follow-up tasks this run registered, and do not say `/okstra-inspect`; `status: blocked` → issue the command the `rationale` calls for (`/okstra-user-response` for the `C-NNN` ids, `/okstra-run` for the phase it names); `validate-run` failed with `recovery.mode: phase-reentry` → name the cause and use `nextCommand` for the recorded earlier phase; otherwise `/okstra-inspect status`.
@@ -33,15 +33,36 @@ Inform the user up-front and confirm before continuing:
33
33
 
34
34
  ## Step 1: Install okstra
35
35
 
36
+ Resolve `<host-runtime>` from the launcher's `OKSTRA_RUNTIME_HOST` when present;
37
+ otherwise use the registered host ID declared by the current harness. Use the
38
+ existing host registry and its aliases rather than maintaining a provider-to-host
39
+ lookup in this skill. Claude Code, Codex, Grok, Antigravity, and Kimi are examples,
40
+ not a closed list; additional registered hosts follow the same rule.
41
+
42
+ Do not infer the host from model names, worker providers, installed executables,
43
+ or `PATH`. A GLM model running inside another harness uses that harness's host
44
+ identity; a separately registered GLM harness uses its own registered identity.
45
+ If neither the launcher nor the harness identifies the host, use `auto` to let
46
+ the existing registry resolve session evidence. Report an unresolved or rejected
47
+ identity without substituting Claude Code or claiming host setup is verified.
48
+ When `auto` resolves successfully, carry the reported resolved host ID forward
49
+ as the literal `<host-runtime>` value instead of detecting again at each step.
50
+
51
+ Replace `<host-runtime>` with the resolved literal value before executing each
52
+ command. Keep the same resolved host for installation, preflight, diagnostics,
53
+ and retries, including retries against another project or npm cache directory.
54
+ The runtime registry validates host IDs; the skill command contract is checked
55
+ by `tests/contract/test_docs_runtime_contract.py::test_skills_declare_their_host_runtime_explicitly`.
56
+
36
57
  ```bash
37
- npx -y okstra@latest install --runtime claude-code
58
+ npx -y okstra@latest install --runtime <host-runtime>
38
59
  ```
39
60
 
40
61
  This single command populates everything the user needs:
41
62
 
42
63
  - `~/.okstra/{lib/python, bin, version}` — python + bash runtime
43
- - `~/.claude/skills/<name>/SKILL.md` — all okstra skills (canonical count
44
- in `~/.okstra/installed-skills.json`)
64
+ - Host skill targets selected by the installer, including the shared Agent skill
65
+ home — installed targets are recorded in `~/.okstra/installed-skills.json`
45
66
  - `~/.okstra/installed-skills.json` — manifest for safe uninstall
46
67
 
47
68
  The skill should run this even if `~/.okstra/version` already exists —
@@ -53,12 +74,26 @@ Show the final summary line back to the user (`version stamp: x.y.z`).
53
74
  If install fails, surface the stderr verbatim. Do NOT try to "fix" it by
54
75
  running the legacy `okstra-install.sh` — that path is dev-only.
55
76
 
77
+ For npm `EPERM` / `EACCES` errors under its cache directory, distinguish package
78
+ preparation from okstra installation. npm's root-owned-files message is not
79
+ evidence of root ownership. Inspect ownership and the session's write restrictions
80
+ before proposing a permission change. Retry with a temporary cache directory
81
+ writable by the current session, substituting its literal absolute path:
82
+
83
+ ```bash
84
+ npx --cache <writable-cache-directory> -y okstra@latest install --runtime <host-runtime>
85
+ ```
86
+
87
+ Do not run recursive `sudo chown` based only on npm's generic message. A cache
88
+ override does not grant network access or permission to write the installation
89
+ targets; follow the host's permission mechanism if either remains blocked.
90
+
56
91
  **Bash invocation rule (permission-friendly)**: after Step 1, every Bash command in this skill MUST begin with the literal token `okstra` and pass literal argument values. Do not introduce shell variables (`$PROJECT_ROOT`, `$PROJECT_ID`, ...), `$(...)` command substitution, leading `VAR=...` assignments, or wrap commands in `if`/`eval`/`||`/`&&` — any of those make the leading token non-literal, defeat the `Bash(okstra:*)` permission match, and force a confirmation prompt on every call. When a prior tool call emitted a path or value, paste the literal string into the next command. Every `okstra <subcmd>` call self-bootstraps its Python path — never run `okstra paths --shell` / `export PYTHONPATH=...`.
57
92
 
58
93
  ## Step 2: Resolve PROJECT_ROOT
59
94
 
60
95
  ```bash
61
- okstra preflight
96
+ okstra preflight --runtime <host-runtime>
62
97
  ```
63
98
 
64
99
  Read the fixed `Okstra preflight`, `Project root`, `Project JSON`, `Project ID`,
@@ -68,11 +103,11 @@ Read the fixed `Okstra preflight`, `Project root`, `Project JSON`, `Project ID`,
68
103
  - `Ok: false`, `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:
69
104
 
70
105
  ```bash
71
- okstra preflight --cwd /abs/path/from/user
106
+ okstra preflight --runtime <host-runtime> --cwd /abs/path/from/user
72
107
  ```
73
108
 
74
109
  - `Ok: false`, `Stage: project_json_missing` → proceed to Step 3 (this is the normal create path).
75
- - `Ok: false`, any other `Stage` (`python`, `parse`, `project_json_invalid`) → show the fixed `Reason` line to the user verbatim and follow the `Recovery` line (typically `okstra doctor` to diagnose, then `okstra ensure-installed` or re-running the Step 1 install). `Reason` is the SSOT — do not hand-enumerate stage causes.
110
+ - `Ok: false`, any other `Stage` (`python`, `parse`, `project_json_invalid`) → 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.
76
111
 
77
112
  ## Step 3: Project metadata setup
78
113
 
@@ -132,7 +167,7 @@ matching section:
132
167
  ## Step 4: Verify
133
168
 
134
169
  ```bash
135
- okstra doctor --runtime claude-code
170
+ okstra doctor --runtime <host-runtime>
136
171
  ```
137
172
 
138
173
  If all checks return `OK`, the setup is complete. If any check fails, surface
@@ -6,6 +6,8 @@ This file is the audience-specific contract for `report-writer`. Read it and the
6
6
 
7
7
  Write only the report narrative Markdown at `**Result Path:**`, the pointer record at `**Worker Result Path:**`, and the reading audit at `**Audit sidecar path:**`.
8
8
 
9
+ A correction-only prompt may additionally name a replacements JSON output. In that mode, the supplied `apply-corrections` command owns the narrative update.
10
+
9
11
  The report narrative Markdown contains the task judgment, plan, summaries, and user explanation. It must not write or patch `final-report-*.data.json`, the approval decision ledger, activity ledger, team state, convergence state, or design-preparation input.
10
12
 
11
13
  The following fields belong to other owners and must not appear in the narrative: `designPreparation`, `designSurfaceCoverage`, `executionStatus`, `executionRoles`, `tokenUsage`, `crossVerification`, `approvalContext`, `clarificationItems`, `agentActivity`, and `planBodyVerification`.
@@ -14,7 +16,7 @@ Do not pre-fill a future round, future gate, usage value, activity identifier, o
14
16
 
15
17
  ## Required reading
16
18
 
17
- Read every path listed under `## Inputs` end-to-end. Full context is available for synthesis, but read access does not transfer write ownership. Preserve supplied technical meaning and do not invent missing evidence.
19
+ For initial synthesis, read every range in the synthesis packet's Read Index once, in order. Each range gives a zero-based UTF-8 byte offset and byte count for a bounded read. Continue at the next unread range instead of rereading the beginning. Resolve shared-text references through the definitions in the same source section; every vote, condition, dissent, and unknown field remains available. The sibling JSON stores each original frozen source for targeted checks. Read access does not transfer write ownership. Preserve supplied technical meaning and do not invent missing evidence.
18
20
 
19
21
  Write the audit sidecar before synthesis with one `- PROGRESS: <stage> <ISO-8601-UTC>` line and the required reading confirmation. Valid stages are `started`, `required-reading-complete`, `synthesis-start`, `narrative-write-start`, and `write-result-start`.
20
22
 
@@ -34,7 +36,7 @@ Follow the task-specific schema order and write the prose in English.
34
36
 
35
37
  These are the only names allowed at the top level:
36
38
 
37
- `Analysis Common`, `Change Impact Analysis`, `End State Coverage`, `Error Analysis`, `Feature Analysis`, `Final Verdict`, `Final Verification`, `Follow Up Tasks`, `Human Summary`, `Implementation`, `Implementation Option Selection`, `Implementation Planning`, `Improvement Discovery`, `Project Analysis`, `Rationale`, `Recommended Next Steps`, `Release Handoff`, `Requirements Discovery`, `Summary`, `Ticket Coverage`, `Verdict Card`
39
+ `Analysis Common`, `Change Impact Analysis`, `End State Coverage`, `Error Analysis`, `Feature Analysis`, `Final Verdict`, `Final Verification`, `Follow Up Tasks`, `Human Summary`, `Implementation`, `Implementation Option Selection`, `Implementation Planning`, `Improvement Discovery`, `Project Analysis`, `Rationale`, `Recommended Next Steps`, `Release Handoff`, `Requirements Discovery`, `Summary`, `Technical Verification`, `Ticket Coverage`, `Verdict Card`
38
40
 
39
41
  The synthesis packet's Authoring Contract names which of these are **required** for this run and the exact `Verdict Token` value; those lines are read from the frozen report schema, so follow them over memory. `Verdict Token` under `Final Verdict` is pinned by task type: `not-applicable` for `requirements-discovery`, `error-analysis`, `implementation-option-selection`, `implementation-planning`, `implementation`, `release-handoff` and `quick`; one of `accepted`, `conditional-accept`, `blocked` for `final-verification`; one of `analysis-complete`, `analysis-partial`, `blocked` for `project-analysis`, `feature-analysis` and `change-impact-analysis`. `Human Summary`, `Verdict Card`, `Rationale`, `Summary`, `Final Verdict`, `Recommended Next Steps` and `Follow Up Tasks` are required at the top level of every narrative.
40
42
 
@@ -46,7 +48,9 @@ The pointer record names the project-relative narrative path and audit sidecar p
46
48
 
47
49
  ## Corrections
48
50
 
49
- A prompt whose body carries a `## Corrections` section is a corrective round. okstra has already applied that ledger to your previous attempt and validated the result against the schema and the task's semantic checks, so apply each entry exactly as written and change nothing else.
51
+ A prompt whose body carries a `## Corrections` section is a corrective round. Its correction-only contract supplies the current values, constraints, evidence, and base narrative hash. Read those inputs; the initial-synthesis reading requirement above does not apply. Do not reopen the full synthesis packet or rewrite the complete narrative. If requested, write the specified replacements JSON file and execute the supplied `apply-corrections` command. The runtime checks the base hash, permitted replacement ids, schema, and semantic rules before updating the narrative. Write the pointer and audit sidecar under their existing contracts.
52
+
53
+ Apply only the supplied correction ids and change nothing else.
50
54
 
51
55
  When the `Context` subsection or any free-form instruction in the body conflicts with the synthesis packet's Authoring Contract, the contract wins: write the contract's value and report the conflict through the Worker Error Contract's typed error log instead of following the instruction.
52
56