okstra 0.168.0 → 0.169.1

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 (101) hide show
  1. package/README.md +5 -4
  2. package/docs/architecture/storage-model.md +57 -1
  3. package/docs/architecture.md +70 -2
  4. package/docs/cli.md +8 -4
  5. package/docs/for-ai/skills/okstra-code-review.md +3 -2
  6. package/docs/for-ai/skills/okstra-schedule-gen.md +3 -1
  7. package/docs/project-structure-overview.md +14 -11
  8. package/package.json +1 -1
  9. package/runtime/BUILD.json +2 -2
  10. package/runtime/agents/workers/claude-worker.md +6 -5
  11. package/runtime/agents/workers/report-writer-worker.md +9 -4
  12. package/runtime/agents/workers/translator-worker.md +6 -4
  13. package/runtime/bin/okstra-error-log.py +38 -282
  14. package/runtime/prompts/duties/acceptance-critic.md +24 -0
  15. package/runtime/prompts/duties/acceptance-verifier.md +24 -0
  16. package/runtime/prompts/duties/analysis-worker.md +24 -0
  17. package/runtime/prompts/duties/code-reviewer.md +24 -0
  18. package/runtime/prompts/duties/common.md +35 -0
  19. package/runtime/prompts/duties/implementation-executor.md +24 -0
  20. package/runtime/prompts/duties/implementation-verifier.md +24 -0
  21. package/runtime/prompts/duties/lead.md +24 -0
  22. package/runtime/prompts/duties/report-writer.md +24 -0
  23. package/runtime/prompts/duties/reverification-worker.md +24 -0
  24. package/runtime/prompts/duties/schedule-verifier.md +24 -0
  25. package/runtime/prompts/duties/scope-critic.md +24 -0
  26. package/runtime/prompts/duties/translator.md +24 -0
  27. package/runtime/prompts/lead/convergence.md +104 -14
  28. package/runtime/prompts/lead/okstra-lead-contract.md +11 -21
  29. package/runtime/prompts/lead/plan-body-verification.md +16 -1
  30. package/runtime/prompts/lead/report-writer.md +20 -5
  31. package/runtime/prompts/lead/team-contract.md +13 -13
  32. package/runtime/prompts/profiles/_coding-conventions-preflight.md +1 -1
  33. package/runtime/prompts/profiles/_implementation-diff-review.md +1 -1
  34. package/runtime/prompts/profiles/_implementation-executor.md +1 -1
  35. package/runtime/prompts/profiles/implementation.md +4 -2
  36. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/adapter.py +6 -0
  37. package/runtime/python/okstra_ctl/adapters/hosts/antigravity/relay.md +3 -2
  38. package/runtime/python/okstra_ctl/adapters/hosts/capability_adapter.py +8 -0
  39. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/adapter.py +33 -0
  40. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +13 -12
  41. package/runtime/python/okstra_ctl/adapters/hosts/codex/adapter.py +6 -0
  42. package/runtime/python/okstra_ctl/adapters/hosts/codex/relay.md +3 -2
  43. package/runtime/python/okstra_ctl/adapters/hosts/external/adapter.py +2 -0
  44. package/runtime/python/okstra_ctl/adapters/hosts/external/relay.md +3 -3
  45. package/runtime/python/okstra_ctl/adapters/hosts/grok/adapter.py +6 -0
  46. package/runtime/python/okstra_ctl/adapters/hosts/grok/relay.md +2 -1
  47. package/runtime/python/okstra_ctl/adapters/hosts/kimi/adapter.py +6 -0
  48. package/runtime/python/okstra_ctl/adapters/hosts/kimi/relay.md +2 -1
  49. package/runtime/python/okstra_ctl/agent_invocation.py +1582 -0
  50. package/runtime/python/okstra_ctl/agent_prompt_cli.py +796 -0
  51. package/runtime/python/okstra_ctl/codex_dispatch.py +2 -107
  52. package/runtime/python/okstra_ctl/context_cost.py +46 -5
  53. package/runtime/python/okstra_ctl/dispatch_core.py +538 -43
  54. package/runtime/python/okstra_ctl/dispatch_state.py +461 -36
  55. package/runtime/python/okstra_ctl/doctor.py +90 -16
  56. package/runtime/python/okstra_ctl/entrypoints/hosts.py +87 -9
  57. package/runtime/python/okstra_ctl/error_log_write.py +308 -0
  58. package/runtime/python/okstra_ctl/initial_prompt_materialization.py +214 -23
  59. package/runtime/python/okstra_ctl/path_hints.py +26 -0
  60. package/runtime/python/okstra_ctl/paths.py +20 -0
  61. package/runtime/python/okstra_ctl/ports/__init__.py +8 -0
  62. package/runtime/python/okstra_ctl/ports/host.py +3 -0
  63. package/runtime/python/okstra_ctl/ports/host_model.py +60 -0
  64. package/runtime/python/okstra_ctl/registry/host_registry.py +5 -0
  65. package/runtime/python/okstra_ctl/render.py +217 -12
  66. package/runtime/python/okstra_ctl/report_finalize.py +44 -0
  67. package/runtime/python/okstra_ctl/run.py +368 -51
  68. package/runtime/python/okstra_ctl/session.py +16 -12
  69. package/runtime/python/okstra_ctl/team.py +11 -11
  70. package/runtime/python/okstra_ctl/worker_audit_check.py +26 -4
  71. package/runtime/python/okstra_ctl/worker_audit_ledger.py +59 -9
  72. package/runtime/python/okstra_ctl/worker_dispatch.py +104 -0
  73. package/runtime/python/okstra_ctl/worker_prompt_body.py +5 -38
  74. package/runtime/python/okstra_ctl/worker_prompt_contract.py +56 -3
  75. package/runtime/python/okstra_ctl/worker_prompt_headers.py +2 -2
  76. package/runtime/python/okstra_ctl/worker_prompt_policy.py +38 -1
  77. package/runtime/skills/okstra-code-review/SKILL.md +22 -3
  78. package/runtime/skills/okstra-run/SKILL.md +16 -1
  79. package/runtime/skills/okstra-schedule-gen/SKILL.md +15 -1
  80. package/runtime/templates/implementation-worker-preamble.md +0 -10
  81. package/runtime/templates/report-writer-prompt-preamble.md +0 -9
  82. package/runtime/templates/reports/settings.template.json +0 -11
  83. package/runtime/templates/worker-prompt-preamble.md +0 -10
  84. package/runtime/validators/lib/fixtures.sh +93 -0
  85. package/runtime/validators/lib/validate-assets.sh +0 -8
  86. package/runtime/validators/validate-run.py +182 -0
  87. package/src/cli-registry.mjs +14 -0
  88. package/src/commands/execute/agent-prompt.mjs +25 -0
  89. package/src/commands/execute/codex-dispatch.mjs +6 -63
  90. package/src/commands/execute/worker-dispatch.mjs +76 -0
  91. package/src/commands/lifecycle/doctor.mjs +18 -3
  92. package/src/commands/lifecycle/install.mjs +33 -15
  93. package/src/commands/lifecycle/uninstall.mjs +4 -3
  94. package/src/lib/install-assets.mjs +9 -0
  95. package/runtime/agents/workers/antigravity-worker.md +0 -259
  96. package/runtime/agents/workers/codex-worker.md +0 -259
  97. package/runtime/agents/workers/grok-worker.md +0 -259
  98. package/runtime/agents/workers/kimi-worker.md +0 -259
  99. package/runtime/prompts/coding-preflight/scripts/preedit-check.sh +0 -79
  100. package/runtime/templates/operating-standard.md +0 -22
  101. package/src/lib/worker-agent-render.mjs +0 -50
@@ -23,11 +23,13 @@ from okstra_ctl.domain.wizard.interaction import (
23
23
  WizardPrompt,
24
24
  )
25
25
  from okstra_ctl.ports import (
26
+ HostModelBindingPort,
26
27
  InteractionPort,
27
28
  LeadSessionPort,
28
29
  UsageAccountingPort,
29
30
  WorkerDispatchPort,
30
31
  )
32
+ from okstra_ctl.ports.host_model import FailClosedHostModelBindingPort
31
33
  from okstra_ctl.registry.provider_registry import (
32
34
  ProviderRegistry,
33
35
  default_provider_registry,
@@ -37,6 +39,7 @@ from okstra_ctl.registry.provider_registry import (
37
39
  @dataclass(frozen=True)
38
40
  class HostPorts:
39
41
  interaction: InteractionPort
42
+ host_model: HostModelBindingPort
40
43
  lead_session: LeadSessionPort
41
44
  worker_dispatch: WorkerDispatchPort
42
45
  usage_accounting: UsageAccountingPort
@@ -203,6 +206,7 @@ class CapabilityHostAdapter:
203
206
  readiness_probe: Callable[
204
207
  [HostSessionContext], tuple[Mapping[str, object], ...]
205
208
  ] | None = None,
209
+ host_model_port: HostModelBindingPort | None = None,
206
210
  ) -> None:
207
211
  self.descriptor = descriptor
208
212
  self._executable_finder = executable_finder
@@ -222,6 +226,7 @@ class CapabilityHostAdapter:
222
226
  )
223
227
  self._ports = HostPorts(
224
228
  interaction_port,
229
+ host_model_port or FailClosedHostModelBindingPort(descriptor.id),
225
230
  resolved_lead_session,
226
231
  resolved_worker_dispatch,
227
232
  usage_accounting_port,
@@ -256,6 +261,9 @@ class CapabilityHostAdapter:
256
261
  def interaction(self) -> InteractionPort:
257
262
  return self._ports.interaction
258
263
 
264
+ def host_model(self) -> HostModelBindingPort:
265
+ return self._ports.host_model
266
+
259
267
  def lead_session(self) -> LeadSessionPort:
260
268
  return self._ports.lead_session
261
269
 
@@ -15,6 +15,10 @@ from okstra_ctl.adapters.hosts.capability_adapter import (
15
15
  numbered_interaction_port,
16
16
  )
17
17
  from okstra_ctl.domain.host import HostClaim, HostDescriptor, HostResolutionContext
18
+ from okstra_ctl.ports.host_model import (
19
+ HostModelBindingError,
20
+ HostModelBindingRequest,
21
+ )
18
22
  from okstra_ctl.registry.provider_registry import ProviderRegistry
19
23
 
20
24
 
@@ -35,6 +39,33 @@ DESCRIPTOR = HostDescriptor(
35
39
  )
36
40
 
37
41
 
42
+ class ClaudeFamilyHostModelBindingPort:
43
+ _FAMILIES = ("fable", "opus", "sonnet", "haiku")
44
+
45
+ def resolve(self, request: HostModelBindingRequest) -> str | None:
46
+ if request.runner == "cli-wrapper":
47
+ return None
48
+ if (
49
+ request.runner != "native-session"
50
+ or request.host_runtime != DESCRIPTOR.id
51
+ or request.provider != DESCRIPTOR.native_provider_id
52
+ ):
53
+ raise self._unsupported(request)
54
+ segments = request.model_execution_value.lower().split("-")
55
+ matches = [family for family in self._FAMILIES if family in segments]
56
+ if len(matches) != 1:
57
+ raise self._unsupported(request)
58
+ return matches[0]
59
+
60
+ @staticmethod
61
+ def _unsupported(request: HostModelBindingRequest) -> HostModelBindingError:
62
+ return HostModelBindingError(
63
+ "unsupported host model: "
64
+ f"host={request.host_runtime!r}, provider={request.provider!r}, "
65
+ f"model={request.model_execution_value!r}"
66
+ )
67
+
68
+
38
69
  def _detect_claude_skill_handoff(
39
70
  context: HostResolutionContext,
40
71
  ) -> HostClaim | None:
@@ -101,6 +132,7 @@ def create_adapter(
101
132
  worker_dispatch_port=PENDING_HOST_PORT,
102
133
  usage_accounting_port=ClaudeJsonlUsageAccountingPort(),
103
134
  provider_registry: ProviderRegistry | None = None,
135
+ host_model_port=None,
104
136
  ) -> CapabilityHostAdapter:
105
137
  return CapabilityHostAdapter(
106
138
  DESCRIPTOR,
@@ -117,4 +149,5 @@ def create_adapter(
117
149
  detector=_detect_claude_skill_handoff,
118
150
  provider_registry=provider_registry,
119
151
  readiness_probe=_workspace_trust_checks,
152
+ host_model_port=host_model_port or ClaudeFamilyHostModelBindingPort(),
120
153
  )
@@ -136,9 +136,9 @@ For a `host-text` mapping, render each numbered item as its option label followe
136
136
  | `read_artifacts` | Use the host file-read primitive and preserve the core contract's read order. |
137
137
  | `write_artifact` | Use the host file-write primitive only for paths authorized by the active lifecycle phase. |
138
138
  | `prompt_user` | Use the native question tool for approvals and clarifications; do not infer an answer from silence. |
139
- | `dispatch_worker` | Dispatch each assignment through `Agent(name: "<role>", run_in_background: true)` without `team_name`; use an in-process worker for `runner=native-session` and the assigned provider's wrapper worker for `runner=cli-wrapper`. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row — start every worker with `okstra team dispatch`, this host's native path included, so okstra owns the panes and the user can watch the work. |
139
+ | `dispatch_worker` | First verify the materialized invocation metadata. Dispatch `runner=native-session` through `Agent(name: "<role>", run_in_background: true)` without `team_name`, passing the verified final prompt and `hostModelValue`. Dispatch `runner=cli-wrapper` with the deterministic shell command `okstra worker-dispatch --project-root <root> --run-manifest <path> --workers <ids>`; never wrap that process in another `Agent(...)` call. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row. |
140
140
  | `await_workers` | Arm one background shell poll for the pending Result Paths; the spawn acknowledgement is not completion. |
141
- | `redispatch_worker` | Dispatch a fresh `Agent(...)` session with the same prompt plus the core reverify/retry reason. |
141
+ | `redispatch_worker` | Materialize and verify a fresh invocation, then use a fresh native `Agent(...)` session or `okstra worker-dispatch` attempt according to the persisted runner. |
142
142
  | `shutdown_workers` | For each confirmed-complete worker selected for cleanup, send `SendMessage(to: <name>, message: { type: "shutdown_request" })` to idle the roster member **and** call `TaskStop(task_id: "<name>")` to stop its background task. Both are required; neither subsumes the other. |
143
143
  | `record_lead_event` | Emit the required `PROGRESS:` line as assistant text and persist core-required state/artifact updates. |
144
144
  | `collect_usage` | Run `okstra token-usage` against the team-state; it reads the run-scoped `~/.claude/projects` session JSONL evidence. |
@@ -147,27 +147,28 @@ For a `host-text` mapping, render each numbered item as its option label followe
147
147
 
148
148
  - The session owns one implicit team. `TeamCreate` and `TeamDelete` are absent on current Claude Code builds; never probe for them and never pass `team_name`.
149
149
  - Set `name` to the core-assigned functional role label so token attribution can match `agentName`.
150
- - Map a `runner=native-session` Claude assignment to `claude-worker`. Map a `runner=cli-wrapper` assignment to `<provider>-worker`; the registered providers currently resolve to `claude-worker`, `codex-worker`, `antigravity-worker`, `grok-worker`, or `kimi-worker`. The functional `report-writer` worker ID does not override its provider assignment. Never substitute `general-purpose` for a rostered worker.
151
- - For `runner=native-session`, map `modelExecutionValue` to the supported Claude family token and pass it as the `model` argument. CLI-wrapper roles apply their exact model in the provider wrapper and remain `inherit` at the Agent layer.
150
+ - Map a `runner=native-session` Claude assignment to the real host execution definition for its function (`claude-worker`, `report-writer-worker`, or `translator-worker`). A CLI-wrapper assignment has no Claude agent definition; `worker-dispatch` starts its registered provider process directly.
151
+ - For `runner=native-session`, pass the persisted `hostModelValue` as the `model` argument. For `runner=cli-wrapper`, `worker-dispatch` passes the persisted `modelExecutionValue` to the provider process. Never interchange the two fields.
152
+ - Immediately before every native host primitive, run `okstra agent-prompt record-dispatch` with the project root, run manifest, verified metadata path, and `--enforcement-mode host-native-spec-link-gate`. After the Result Path exists, run `okstra agent-prompt link-result` with `--dispatch-id <invocationId>:attempt-1` and that path before accepting or parsing it. CLI-wrapper calls are recorded by `worker-dispatch` itself.
152
153
  - A resumed lead can dispatch a fresh worker; resume is not a valid reason to omit a rostered role.
153
154
 
154
155
  ### Dispatch-time model enforcement
155
156
 
156
- - A native Claude worker definition declares `model: inherit`; the lead MUST override that default by passing the assigned family token (`fable`, `opus`, `sonnet`, or `haiku`) as the `Agent(...)` `model` argument.
157
- - Every CLI-wrapper agent remains `inherit` at the Agent layer because its exact `modelExecutionValue` is applied by `okstra-claude-exec.sh`, `okstra-codex-exec.sh`, `okstra-antigravity-exec.sh`, `okstra-grok-exec.sh`, or `okstra-kimi-exec.sh` according to the assignment provider.
157
+ - A native Claude execution definition declares `model: inherit`; the lead MUST override it with the verified assignment's `hostModelValue`.
158
+ - CLI-wrapper assignments never enter the Agent layer. `okstra worker-dispatch` validates the metadata and passes `modelExecutionValue` to the registered provider script.
158
159
  - Missing or unsupported family-token mapping is a pre-dispatch contract failure. Never inherit the lead model, choose a nearby alias, or switch provider silently.
159
160
  - Every analysis dispatch sets `name: "<workerId>-worker"`; convergence retries append `-reverify-r<N>`, implementation uses the functional `-executor` / `-verifier` suffix, and report writing uses `report-writer`. These values are retained as `agentName` in session JSONL for usage attribution.
160
161
  - Every CLI-worker prompt includes `**Pane role:** <functional-role>` so the entrypoint's optional fifth argument carries the dispatched role. That argument selects the dispatch's idle budget — `executor` and `verifier` run silent build+test suites and get 1500s, every other role 600s — and is recorded in the run's status sidecar. Omitting it defaults to `worker`, i.e. the short budget, which reaps a healthy build mid-suite.
161
- - The Agent SDK may supply transport metadata through the in-process worker definition, but the persisted semantic prompt body and primary analysis-packet input remain identical to the CLI-wrapper workers after permitted identity/path normalization.
162
+ - The host may supply transport metadata for native calls, but acceptance records only the verified invocation specification link. Record `enforcementMode=host-native-spec-link-gate`, `promptPath`, and `metadataPath`; do not claim the host-delivered bytes were observed.
162
163
  - A retry keeps the same Agent `name`. When logging a twice-failed CLI-wrapper attempt, reference both attempts' `bash_ids` and prompt-history paths.
163
164
  - An internally detected contract violation without a specific worker uses `--agent "claude-lead"` in the error-log event.
164
165
 
165
166
  ### Reverify, critic, and report-writer assignments
166
167
 
167
168
  - For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
168
- - Reverify dispatch uses a fresh one-shot `Agent(...)` call named `<workerId>-worker-reverify-r<N>`. Preserve the initial worker's definition and map an in-process Claude assignment's `modelExecutionValue` to its exact family token; CLI-wrapper assignments remain `inherit` at the Agent layer and apply the exact model in their wrapper.
169
+ - Reverify dispatch materializes `reverification-worker`, verifies its metadata, then uses a fresh one-shot native call named `<workerId>-worker-reverify-r<N>` or a fresh deterministic `worker-dispatch` attempt according to the persisted runner.
169
170
  - Critic dispatch uses `name: "<provider>-worker-critic"`, `dispatchKind: "critic"`, and the exact mapped model from `config.critic.modelExecutionValue`. If that value cannot be mapped, record `critic-skipped: model-unresolved` and do not dispatch.
170
- - Report-writer dispatch uses `name: "report-writer"`. A native Claude assignment maps `modelExecutionValue` to the supported family token; a CLI-wrapper assignment remains `inherit` at the Agent layer and applies the exact value in its provider wrapper. The prompt's `**Model:**` header must carry the same execution value.
171
+ - Report-writer dispatch uses `name: "report-writer"` only for a native Claude assignment and passes `hostModelValue`. A CLI assignment goes through `worker-dispatch` with `modelExecutionValue`.
171
172
  - Each variant persists its prompt path, Result Path, worker-results path, error paths, and `dispatchKind` before dispatch. Completion uses the shared background Result Path poll; an Agent acknowledgement never completes the variant.
172
173
 
173
174
  ## Completion, cleanup, and resume
@@ -180,12 +181,12 @@ For a `host-text` mapping, render each numbered item as its option label followe
180
181
  - On approved cleanup, reconcile the current live session roster before sending shutdown requests. Never target the lead session.
181
182
  - Collect usage before teardown. Resume through the recorded Claude session id and keep all run artifacts authoritative.
182
183
 
183
- ### CLI-wrapper polling
184
+ ### CLI process polling
184
185
 
185
- - Start the assignment's registered wrapper (`okstra-claude-exec.sh`, `okstra-codex-exec.sh`, `okstra-antigravity-exec.sh`, `okstra-grok-exec.sh`, or `okstra-kimi-exec.sh`) with `Bash(run_in_background: true)` and poll `BashOutput(bash_id)` back-to-back until terminal completion. Never add a foreground sleep.
186
+ - Start `okstra worker-dispatch` with `Bash(run_in_background: true)` and poll `BashOutput(bash_id)` back-to-back until terminal completion. The deterministic dispatcher starts the registered provider script after metadata verification. Never add a foreground sleep.
186
187
  - Return accumulated stdout on success. On a non-zero `exit_code`, record the real code and observed duration.
187
188
  - At the 1800-second cap, inspect the live log mtime once. Recent output grants one extension to 2100 seconds; otherwise call `KillShell(shell_id)`, record exit code 124, and return the wrapper timeout sentinel.
188
- - Keep the wrapper subagent alive throughout polling so its JSONL timestamp window covers the underlying CLI rollout.
189
+ - Keep the background process handle until the provider process reaches terminal state.
189
190
 
190
191
  ### Session accounting
191
192
 
@@ -14,6 +14,7 @@ from okstra_ctl.adapters.hosts.capability_adapter import (
14
14
  numbered_interaction_port,
15
15
  )
16
16
  from okstra_ctl.domain.host import HostDescriptor
17
+ from okstra_ctl.ports.host_model import NativeExecutionValueHostModelBindingPort
17
18
  from okstra_ctl.registry.provider_registry import ProviderRegistry
18
19
 
19
20
 
@@ -42,6 +43,7 @@ def create_adapter(
42
43
  worker_dispatch_port=PENDING_HOST_PORT,
43
44
  usage_accounting_port=CliArtifactUsageAccountingPort(),
44
45
  provider_registry: ProviderRegistry | None = None,
46
+ host_model_port=None,
45
47
  ) -> CapabilityHostAdapter:
46
48
  return CapabilityHostAdapter(
47
49
  DESCRIPTOR,
@@ -57,4 +59,8 @@ def create_adapter(
57
59
  supported_functions=INTERACTION_FUNCTIONS,
58
60
  detector=no_automatic_claim,
59
61
  provider_registry=provider_registry,
62
+ host_model_port=host_model_port or NativeExecutionValueHostModelBindingPort(
63
+ DESCRIPTOR.id,
64
+ DESCRIPTOR.native_provider_id,
65
+ ),
60
66
  )
@@ -77,9 +77,9 @@ Render every numbered item as its option label followed by its description verba
77
77
  | `read_artifacts` | Read the manifest-provided paths through the current host's file interface. |
78
78
  | `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
79
79
  | `prompt_user` | Ask through the host text/question interface and stop at approval gates until an explicit answer arrives. |
80
- | `dispatch_worker` | Dispatch every `runner=native-session` assignment with the current Codex host's native worker/session primitive. Pass only `runner=cli-wrapper` assignments to `okstra codex-dispatch --project-root <root> --run-manifest <path> --workers <ids>`; use `--dry-run` first when the core requires a dispatch preview. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row — start every worker with `okstra team dispatch`, this host's native path included, so okstra owns the panes and the user can watch the work. |
80
+ | `dispatch_worker` | Verify each materialized invocation first. Dispatch `runner=native-session` with the current Codex host's primitive, the returned `promptPath`, and `hostModelValue`. Pass `runner=cli-wrapper` assignments to `okstra worker-dispatch --project-root <root> --run-manifest <path> --workers <ids>`; use `--dry-run` first when required. **Not in a cmux run:** when `terminalBackend` is `cmux-pane`, the cmux adapter overrides this row. |
81
81
  | `await_workers` | Await native host workers through the host primitive and CLI workers through synchronous dispatch, then verify team-state terminal records and Result Paths for both. |
82
- | `redispatch_worker` | Start a fresh native worker or `okstra codex-dispatch` attempt according to the persisted assignment's `runner`, and record the retry/reverify dispatch kind. |
82
+ | `redispatch_worker` | Materialize and verify a fresh invocation, then start a fresh native worker or `okstra worker-dispatch` attempt according to the persisted runner. |
83
83
  | `shutdown_workers` | Perform process cleanup when a wrapper remains live; otherwise this operation is a no-op recorded in state. |
84
84
  | `record_lead_event` | Append the required structured event to the manifest-provided `leadEventsPath`; emit the matching user-facing `PROGRESS:` line. |
85
85
  | `collect_usage` | Collect artifact/rollout-backed usage through the existing Okstra token-usage path; never read Claude session JSONL as a substitute. |
@@ -91,6 +91,7 @@ Render every numbered item as its option label followed by its description verba
91
91
  - The prepared run manifest and team-state are the dispatch authority. A `runner=native-session` assignment stays in the current Codex host; a `runner=cli-wrapper` assignment uses the registered provider wrapper. Unsupported explicitly requested workers fail; an adapter must not silently change the roster.
92
92
  - The report-writer follows its persisted provider, model, and runner assignment exactly. It has no Codex-only provider override or separate opt-in gate.
93
93
  - Reverify and critic retries invoke a fresh worker attempt and persist the core-supplied `dispatchKind` (`reverify-r<N>` or `critic`) in the dispatch record; never reuse a prior rollout as a new vote.
94
+ - Native calls use only `hostModelValue`. Immediately before the host primitive, run `okstra agent-prompt record-dispatch` with the project root, run manifest, verified metadata path, and `--enforcement-mode host-native-spec-link-gate`; after the Result Path exists, run `okstra agent-prompt link-result` with `--dispatch-id <invocationId>:attempt-1` and that path before accepting it. CLI calls use only `modelExecutionValue` through `worker-dispatch`, which records its own dispatch. The native linkage proves association with a verified specification, not observed prompt delivery.
94
95
  - Report-writer completion requires both the data.json Result Path and the worker-results audit path, even when the synchronous dispatch command exits successfully.
95
96
 
96
97
  ## Completion, cleanup, and resume
@@ -54,6 +54,7 @@ def create_adapter(
54
54
  "transcript or CLI usage artifact contract is registered."
55
55
  ),
56
56
  provider_registry: ProviderRegistry | None = None,
57
+ host_model_port=None,
57
58
  ) -> CapabilityHostAdapter:
58
59
  return CapabilityHostAdapter(
59
60
  DESCRIPTOR,
@@ -69,4 +70,5 @@ def create_adapter(
69
70
  supported_functions=INTERACTION_FUNCTIONS,
70
71
  detector=_detect_tmux,
71
72
  provider_registry=provider_registry,
73
+ host_model_port=host_model_port,
72
74
  )
@@ -77,7 +77,7 @@ Render every numbered item as its option label followed by its description verba
77
77
  | `read_artifacts` | Read the manifest-provided paths through the current host's file or shell interface. |
78
78
  | `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
79
79
  | `prompt_user` | Ask through the host text/question interface and require an explicit approval or clarification response. |
80
- | `dispatch_worker` | Run `okstra team dispatch --project-root <root> --run-manifest <path>`; use `--dry-run` first when the core requires a dispatch preview. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row — start every worker with `okstra team dispatch`, this host's native path included, so okstra owns the panes and the user can watch the work. |
80
+ | `dispatch_worker` | Verify each materialized invocation, then run deterministic `okstra worker-dispatch --project-root <root> --run-manifest <path>` for CLI assignments. Use `okstra team dispatch` only when the selected pane backend owns visible panes. |
81
81
  | `await_workers` | Run `okstra team await --project-root <root> --run-manifest <path>` through the host's asynchronous shell facility. |
82
82
  | `redispatch_worker` | Create the core-specified fresh jobs file and dispatch it with a new `dispatchKind`; never reuse a live worker conversation. |
83
83
  | `shutdown_workers` | Run `okstra team teardown --project-root <root> --run-manifest <path>` only after the user-approved cleanup gate. |
@@ -87,11 +87,11 @@ Render every numbered item as its option label followed by its description verba
87
87
  ## External dispatch details
88
88
 
89
89
  - For convergence reverify, consume the persisted round plan exactly. This adapter may map and transport each returned batch, but it cannot change batch membership and does not classify findings or branch on task type, provider, or model identity.
90
- - Do not invoke Claude Code team tools or `okstra codex-dispatch`.
90
+ - Do not invoke Claude Code team tools or provider-specific LLM transport agents. `okstra codex-dispatch` is a compatibility alias only; use `okstra worker-dispatch`.
91
91
  - Worker completion is valid only from `workerDispatches[]`, terminal status sidecars, and required Result Paths. Pane creation alone is not completion.
92
92
  - Reverify uses a fresh jobs file at `runs/<task-type>/state/reverify-jobs-r<N>-<task-type>-<seq>.json`, sets `dispatchKind: "reverify-r<N>"`, and dispatches with `okstra team dispatch --project-root <root> --run-manifest <path> --dispatch-kind reverify-r<N> --jobs-file <jobs-file>`.
93
93
  - Report-writer uses a fresh one-job jobs file with `dispatchKind: "report-writer"` and the same schema, then dispatches through `okstra team dispatch --project-root <root> --run-manifest <path> --jobs-file <jobs-file>`.
94
- - Every reverify or report-writer jobs file carries `workerId`, `provider`, `role`, `modelExecutionValue`, `promptPath`, `resultPath`, `workerResultPath`, and `completionPaths`. For reverify, set `role` to `worker-reverify-r<N>` — the role selects the dispatch's idle budget and is recorded in the run's status sidecar, so it must name the actual assignment. The report-writer completion paths include both data.json and the worker-results audit file.
94
+ - Every reverify or report-writer jobs file carries `workerId`, `provider`, `role`, `modelExecutionValue`, `promptPath`, `promptMetadataPath`, `invocationId`, `assignmentRef`, `audience`, the five prompt digests, `resultPath`, `workerResultPath`, and `completionPaths`. `worker-dispatch` verifies these fields before launching the provider process. For reverify, set `role` to `worker-reverify-r<N>`. The report-writer completion paths include both data.json and the worker-results audit file.
95
95
  - After either dispatch, run `okstra team await --project-root <root> --run-manifest <path>` before evaluating terminal status or completion paths.
96
96
 
97
97
  ## Completion, cleanup, and resume
@@ -14,6 +14,7 @@ from okstra_ctl.adapters.hosts.capability_adapter import (
14
14
  numbered_interaction_port,
15
15
  )
16
16
  from okstra_ctl.domain.host import HostDescriptor
17
+ from okstra_ctl.ports.host_model import NativeExecutionValueHostModelBindingPort
17
18
  from okstra_ctl.registry.provider_registry import ProviderRegistry
18
19
 
19
20
 
@@ -45,6 +46,7 @@ def create_adapter(
45
46
  "transcript or CLI usage artifact contract is registered."
46
47
  ),
47
48
  provider_registry: ProviderRegistry | None = None,
49
+ host_model_port=None,
48
50
  ) -> CapabilityHostAdapter:
49
51
  return CapabilityHostAdapter(
50
52
  DESCRIPTOR,
@@ -60,4 +62,8 @@ def create_adapter(
60
62
  supported_functions=INTERACTION_FUNCTIONS,
61
63
  detector=no_automatic_claim,
62
64
  provider_registry=provider_registry,
65
+ host_model_port=host_model_port or NativeExecutionValueHostModelBindingPort(
66
+ DESCRIPTOR.id,
67
+ DESCRIPTOR.native_provider_id,
68
+ ),
63
69
  )
@@ -76,7 +76,7 @@ Render every numbered item as its option label followed by its description verba
76
76
  | `read_artifacts` | Read the manifest-provided paths through the current Grok host file interface. |
77
77
  | `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
78
78
  | `prompt_user` | Ask through the current host text interface and wait for an explicit answer. |
79
- | `dispatch_worker` | Follow each persisted assignment's `runner` and use the common host dispatch boundary. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row — start every worker with `okstra team dispatch`, this host's native path included, so okstra owns the panes and the user can watch the work. |
79
+ | `dispatch_worker` | Verify the materialized invocation. Use the host primitive with `promptPath` and `hostModelValue` for `native-session`; use deterministic `okstra worker-dispatch` with `modelExecutionValue` for `cli-wrapper`. **Not in a cmux run:** the cmux adapter overrides this row. |
80
80
  | `await_workers` | Await through the selected common dispatch backend, then verify terminal state and Result Paths. |
81
81
  | `redispatch_worker` | Start a fresh attempt from the persisted assignment and record the supplied dispatch kind. |
82
82
  | `shutdown_workers` | Clean up only host or process resources owned by this run. |
@@ -87,4 +87,5 @@ Render every numbered item as its option label followed by its description verba
87
87
 
88
88
  - Do not infer the current host from an installed `grok` executable. The runtime must come from an explicit request or current-session declaration.
89
89
  - Keep persisted provider, model, runner, and dispatch-kind assignments unchanged.
90
+ - Before a native call, run `okstra agent-prompt record-dispatch` with the project root, run manifest, verified metadata path, and `--enforcement-mode host-native-spec-link-gate`; after the Result Path exists, run `okstra agent-prompt link-result` with `--dispatch-id <invocationId>:attempt-1` and that path before accepting it. This is a verified specification link, not proof of delivered prompt bytes.
90
91
  - Resume with the persisted Grok session ID when one exists; otherwise resume from Okstra run artifacts.
@@ -14,6 +14,7 @@ from okstra_ctl.adapters.hosts.capability_adapter import (
14
14
  numbered_interaction_port,
15
15
  )
16
16
  from okstra_ctl.domain.host import HostDescriptor
17
+ from okstra_ctl.ports.host_model import NativeExecutionValueHostModelBindingPort
17
18
  from okstra_ctl.registry.provider_registry import ProviderRegistry
18
19
 
19
20
 
@@ -45,6 +46,7 @@ def create_adapter(
45
46
  "transcript or CLI usage artifact contract is registered."
46
47
  ),
47
48
  provider_registry: ProviderRegistry | None = None,
49
+ host_model_port=None,
48
50
  ) -> CapabilityHostAdapter:
49
51
  return CapabilityHostAdapter(
50
52
  DESCRIPTOR,
@@ -60,4 +62,8 @@ def create_adapter(
60
62
  supported_functions=INTERACTION_FUNCTIONS,
61
63
  detector=no_automatic_claim,
62
64
  provider_registry=provider_registry,
65
+ host_model_port=host_model_port or NativeExecutionValueHostModelBindingPort(
66
+ DESCRIPTOR.id,
67
+ DESCRIPTOR.native_provider_id,
68
+ ),
63
69
  )
@@ -76,7 +76,7 @@ Render every numbered item as its option label followed by its description verba
76
76
  | `read_artifacts` | Read the manifest-provided paths through the current Kimi host file interface. |
77
77
  | `write_artifact` | Write only core-authorized `.okstra/` artifacts and preserve their schemas. |
78
78
  | `prompt_user` | Ask through the current host text interface and wait for an explicit answer. |
79
- | `dispatch_worker` | Follow each persisted assignment's `runner` and use the common host dispatch boundary. **Not in a cmux run:** when the run manifest's `terminalBackend` is `cmux-pane`, `prompts/lead/adapters/cmux.md` overrides this row — start every worker with `okstra team dispatch`, this host's native path included, so okstra owns the panes and the user can watch the work. |
79
+ | `dispatch_worker` | Verify the materialized invocation. Use the host primitive with `promptPath` and `hostModelValue` for `native-session`; use deterministic `okstra worker-dispatch` with `modelExecutionValue` for `cli-wrapper`. **Not in a cmux run:** the cmux adapter overrides this row. |
80
80
  | `await_workers` | Await through the selected common dispatch backend, then verify terminal state and Result Paths. |
81
81
  | `redispatch_worker` | Start a fresh attempt from the persisted assignment and record the supplied dispatch kind. |
82
82
  | `shutdown_workers` | Clean up only host or process resources owned by this run. |
@@ -87,4 +87,5 @@ Render every numbered item as its option label followed by its description verba
87
87
 
88
88
  - Do not infer the current host from an installed `kimi` executable. The runtime must come from an explicit request or current-session declaration.
89
89
  - Keep persisted provider, model, runner, and dispatch-kind assignments unchanged.
90
+ - Before a native call, run `okstra agent-prompt record-dispatch` with the project root, run manifest, verified metadata path, and `--enforcement-mode host-native-spec-link-gate`; after the Result Path exists, run `okstra agent-prompt link-result` with `--dispatch-id <invocationId>:attempt-1` and that path before accepting it. This is a verified specification link, not proof of delivered prompt bytes.
90
91
  - Resume with the persisted Kimi session ID when one exists; otherwise resume from Okstra run artifacts.