@open-agent-toolkit/cli 0.2.51 → 0.2.52

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 (213) hide show
  1. package/assets/bundle-metadata.json +1 -1
  2. package/assets/docs/cli-utilities/bootstrap.md +6 -2
  3. package/assets/docs/cli-utilities/tool-packs.md +87 -33
  4. package/assets/docs/provider-sync/commands.md +30 -2
  5. package/assets/docs/provider-sync/config.md +19 -0
  6. package/assets/docs/provider-sync/manifest-and-drift.md +37 -0
  7. package/assets/docs/provider-sync/providers.md +69 -2
  8. package/assets/docs/provider-sync/scope-and-surface.md +44 -0
  9. package/assets/docs/reference/cli-reference.md +1 -0
  10. package/assets/docs/reference/oat-directory-structure.md +11 -4
  11. package/assets/docs/workflows/projects/evidence-layers.md +110 -1
  12. package/assets/docs/workflows/projects/implementation-execution.md +13 -0
  13. package/assets/docs/workflows/projects/orchestration-model.md +18 -0
  14. package/assets/public-package-versions.json +4 -4
  15. package/assets/skills/oat-dispatch-subagents/SKILL.md +57 -1
  16. package/assets/skills/oat-dispatch-subagents/references/record-schema.md +77 -1
  17. package/assets/skills/oat-project-autonomous/references/gate-inventory.md +1 -1
  18. package/assets/skills/oat-project-dispatch-subagents/SKILL.md +24 -1
  19. package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +1 -1
  20. package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +11 -0
  21. package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +1 -1
  22. package/assets/skills/oat-project-plan-writing/SKILL.md +12 -1
  23. package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +1 -1
  24. package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +1 -1
  25. package/assets/skills/oat-project-review-provide/SKILL.md +12 -1
  26. package/assets/skills/oat-project-review-provide-remote/SKILL.md +12 -1
  27. package/dist/agents/canonical/index.d.ts +2 -0
  28. package/dist/agents/canonical/index.d.ts.map +1 -1
  29. package/dist/agents/canonical/index.js +1 -0
  30. package/dist/agents/canonical/resolve.d.ts +45 -0
  31. package/dist/agents/canonical/resolve.d.ts.map +1 -0
  32. package/dist/agents/canonical/resolve.js +175 -0
  33. package/dist/commands/decision/agents-guidance.d.ts +2 -2
  34. package/dist/commands/decision/agents-guidance.d.ts.map +1 -1
  35. package/dist/commands/decision/agents-guidance.js +1 -4
  36. package/dist/commands/decision/index.d.ts.map +1 -1
  37. package/dist/commands/decision/index.js +25 -6
  38. package/dist/commands/docs/init/index.d.ts +7 -1
  39. package/dist/commands/docs/init/index.d.ts.map +1 -1
  40. package/dist/commands/docs/init/index.js +53 -20
  41. package/dist/commands/doctor/index.d.ts +8 -2
  42. package/dist/commands/doctor/index.d.ts.map +1 -1
  43. package/dist/commands/doctor/index.js +157 -46
  44. package/dist/commands/init/index.d.ts +8 -3
  45. package/dist/commands/init/index.d.ts.map +1 -1
  46. package/dist/commands/init/index.js +64 -26
  47. package/dist/commands/init/tools/index.d.ts +12 -12
  48. package/dist/commands/init/tools/index.d.ts.map +1 -1
  49. package/dist/commands/init/tools/index.js +430 -99
  50. package/dist/commands/init/tools/install-state.d.ts +2 -0
  51. package/dist/commands/init/tools/install-state.d.ts.map +1 -1
  52. package/dist/commands/init/tools/install-state.js +11 -0
  53. package/dist/commands/init/tools/project-guidance.d.ts +49 -0
  54. package/dist/commands/init/tools/project-guidance.d.ts.map +1 -0
  55. package/dist/commands/init/tools/project-guidance.js +144 -0
  56. package/dist/commands/init/tools/workflows/index.d.ts +7 -0
  57. package/dist/commands/init/tools/workflows/index.d.ts.map +1 -1
  58. package/dist/commands/init/tools/workflows/index.js +160 -7
  59. package/dist/commands/pjm/index.d.ts.map +1 -1
  60. package/dist/commands/pjm/index.js +28 -3
  61. package/dist/commands/pjm/init.d.ts +5 -0
  62. package/dist/commands/pjm/init.d.ts.map +1 -1
  63. package/dist/commands/pjm/init.js +19 -3
  64. package/dist/commands/project/dispatch/index.d.ts +10 -0
  65. package/dist/commands/project/dispatch/index.d.ts.map +1 -0
  66. package/dist/commands/project/dispatch/index.js +137 -0
  67. package/dist/commands/project/dispatch/record.d.ts +91 -0
  68. package/dist/commands/project/dispatch/record.d.ts.map +1 -0
  69. package/dist/commands/project/dispatch/record.js +402 -0
  70. package/dist/commands/project/index.d.ts.map +1 -1
  71. package/dist/commands/project/index.js +2 -0
  72. package/dist/commands/providers/inspect/inspect.d.ts +8 -1
  73. package/dist/commands/providers/inspect/inspect.d.ts.map +1 -1
  74. package/dist/commands/providers/inspect/inspect.js +146 -26
  75. package/dist/commands/providers/list/list.d.ts +8 -1
  76. package/dist/commands/providers/list/list.d.ts.map +1 -1
  77. package/dist/commands/providers/list/list.js +139 -23
  78. package/dist/commands/providers/providers.types.d.ts +25 -1
  79. package/dist/commands/providers/providers.types.d.ts.map +1 -1
  80. package/dist/commands/providers/set/index.d.ts +9 -1
  81. package/dist/commands/providers/set/index.d.ts.map +1 -1
  82. package/dist/commands/providers/set/index.js +43 -33
  83. package/dist/commands/remove/skill/remove-skill.d.ts.map +1 -1
  84. package/dist/commands/remove/skill/remove-skill.js +11 -0
  85. package/dist/commands/shared/agents-md.d.ts +42 -14
  86. package/dist/commands/shared/agents-md.d.ts.map +1 -1
  87. package/dist/commands/shared/agents-md.js +364 -70
  88. package/dist/commands/status/index.d.ts +8 -3
  89. package/dist/commands/status/index.d.ts.map +1 -1
  90. package/dist/commands/status/index.js +147 -32
  91. package/dist/commands/sync/apply.d.ts.map +1 -1
  92. package/dist/commands/sync/apply.js +220 -29
  93. package/dist/commands/sync/dry-run.d.ts.map +1 -1
  94. package/dist/commands/sync/dry-run.js +30 -6
  95. package/dist/commands/sync/index.d.ts +17 -2
  96. package/dist/commands/sync/index.d.ts.map +1 -1
  97. package/dist/commands/sync/index.js +106 -41
  98. package/dist/commands/sync/sync.types.d.ts +39 -2
  99. package/dist/commands/sync/sync.types.d.ts.map +1 -1
  100. package/dist/commands/sync/sync.utils.d.ts +5 -1
  101. package/dist/commands/sync/sync.utils.d.ts.map +1 -1
  102. package/dist/commands/sync/sync.utils.js +73 -0
  103. package/dist/commands/tools/info/info-tool.d.ts +2 -0
  104. package/dist/commands/tools/info/info-tool.d.ts.map +1 -1
  105. package/dist/commands/tools/info/info-tool.js +34 -12
  106. package/dist/commands/tools/install/index.d.ts.map +1 -1
  107. package/dist/commands/tools/install/index.js +19 -3
  108. package/dist/commands/tools/list/list-tools.d.ts +2 -0
  109. package/dist/commands/tools/list/list-tools.d.ts.map +1 -1
  110. package/dist/commands/tools/list/list-tools.js +36 -7
  111. package/dist/commands/tools/remove/index.d.ts.map +1 -1
  112. package/dist/commands/tools/remove/index.js +150 -21
  113. package/dist/commands/tools/remove/remove-tools.d.ts +20 -0
  114. package/dist/commands/tools/remove/remove-tools.d.ts.map +1 -1
  115. package/dist/commands/tools/remove/remove-tools.js +122 -1
  116. package/dist/commands/tools/shared/format-pack-inventory.d.ts +19 -0
  117. package/dist/commands/tools/shared/format-pack-inventory.d.ts.map +1 -1
  118. package/dist/commands/tools/shared/format-pack-inventory.js +109 -0
  119. package/dist/commands/tools/shared/pack-evidence.d.ts +66 -0
  120. package/dist/commands/tools/shared/pack-evidence.d.ts.map +1 -0
  121. package/dist/commands/tools/shared/pack-evidence.js +132 -0
  122. package/dist/commands/tools/shared/pack-inventory.d.ts +1 -0
  123. package/dist/commands/tools/shared/pack-inventory.d.ts.map +1 -1
  124. package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts +44 -0
  125. package/dist/commands/tools/shared/pack-lifecycle-outcome.d.ts.map +1 -0
  126. package/dist/commands/tools/shared/pack-lifecycle-outcome.js +91 -0
  127. package/dist/commands/tools/update/index.d.ts.map +1 -1
  128. package/dist/commands/tools/update/index.js +74 -4
  129. package/dist/commands/tools/update/update-tools.d.ts +5 -0
  130. package/dist/commands/tools/update/update-tools.d.ts.map +1 -1
  131. package/dist/commands/tools/update/update-tools.js +64 -2
  132. package/dist/config/oat-config.d.ts +5 -0
  133. package/dist/config/oat-config.d.ts.map +1 -1
  134. package/dist/config/oat-config.js +17 -5
  135. package/dist/config/user-sync-config.d.ts +1 -0
  136. package/dist/config/user-sync-config.d.ts.map +1 -1
  137. package/dist/config/user-sync-config.js +8 -0
  138. package/dist/drift/detector.d.ts +2 -2
  139. package/dist/drift/detector.d.ts.map +1 -1
  140. package/dist/drift/detector.js +18 -0
  141. package/dist/drift/strays.d.ts.map +1 -1
  142. package/dist/drift/strays.js +5 -0
  143. package/dist/engine/collection-sync.d.ts +14 -0
  144. package/dist/engine/collection-sync.d.ts.map +1 -0
  145. package/dist/engine/collection-sync.js +282 -0
  146. package/dist/engine/compute-plan.d.ts +8 -1
  147. package/dist/engine/compute-plan.d.ts.map +1 -1
  148. package/dist/engine/compute-plan.js +303 -12
  149. package/dist/engine/engine.types.d.ts +61 -0
  150. package/dist/engine/engine.types.d.ts.map +1 -1
  151. package/dist/engine/execute-plan.d.ts +22 -2
  152. package/dist/engine/execute-plan.d.ts.map +1 -1
  153. package/dist/engine/execute-plan.js +459 -27
  154. package/dist/engine/provider-path-safety.d.ts +1 -0
  155. package/dist/engine/provider-path-safety.d.ts.map +1 -1
  156. package/dist/engine/provider-path-safety.js +15 -0
  157. package/dist/engine/scanner.d.ts +2 -2
  158. package/dist/engine/scanner.d.ts.map +1 -1
  159. package/dist/engine/scanner.js +21 -4
  160. package/dist/fs/io.d.ts +67 -0
  161. package/dist/fs/io.d.ts.map +1 -1
  162. package/dist/fs/io.js +536 -3
  163. package/dist/manifest/index.d.ts +2 -2
  164. package/dist/manifest/index.d.ts.map +1 -1
  165. package/dist/manifest/index.js +1 -1
  166. package/dist/manifest/manager.d.ts +2 -2
  167. package/dist/manifest/manager.d.ts.map +1 -1
  168. package/dist/manifest/manager.js +20 -3
  169. package/dist/manifest/manifest.types.d.ts +704 -13
  170. package/dist/manifest/manifest.types.d.ts.map +1 -1
  171. package/dist/manifest/manifest.types.js +131 -15
  172. package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
  173. package/dist/providers/codex/codec/sync-extension.js +41 -10
  174. package/dist/providers/cursor/codec/sync-extension.d.ts.map +1 -1
  175. package/dist/providers/cursor/codec/sync-extension.js +41 -10
  176. package/dist/providers/identity/absolute-paths.d.ts +68 -0
  177. package/dist/providers/identity/absolute-paths.d.ts.map +1 -0
  178. package/dist/providers/identity/absolute-paths.js +144 -0
  179. package/dist/providers/identity/claude-runtime-observation.d.ts +105 -0
  180. package/dist/providers/identity/claude-runtime-observation.d.ts.map +1 -0
  181. package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts +40 -0
  182. package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts.map +1 -0
  183. package/dist/providers/identity/claude-runtime-observation.fixtures.js +146 -0
  184. package/dist/providers/identity/claude-runtime-observation.js +229 -0
  185. package/dist/providers/identity/codex-runtime-observation.d.ts +75 -0
  186. package/dist/providers/identity/codex-runtime-observation.d.ts.map +1 -0
  187. package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts +37 -0
  188. package/dist/providers/identity/codex-runtime-observation.fixtures.d.ts.map +1 -0
  189. package/dist/providers/identity/codex-runtime-observation.fixtures.js +539 -0
  190. package/dist/providers/identity/codex-runtime-observation.js +255 -0
  191. package/dist/providers/identity/generic-dispatch-record.d.ts +313 -0
  192. package/dist/providers/identity/generic-dispatch-record.d.ts.map +1 -0
  193. package/dist/providers/identity/generic-dispatch-record.js +539 -0
  194. package/dist/providers/identity/oat-dispatch-record.d.ts +1964 -0
  195. package/dist/providers/identity/oat-dispatch-record.d.ts.map +1 -0
  196. package/dist/providers/identity/oat-dispatch-record.js +691 -0
  197. package/dist/providers/identity/runtime-observation.d.ts +100 -0
  198. package/dist/providers/identity/runtime-observation.d.ts.map +1 -0
  199. package/dist/providers/identity/runtime-observation.js +169 -0
  200. package/dist/providers/shared/index.d.ts +2 -0
  201. package/dist/providers/shared/index.d.ts.map +1 -1
  202. package/dist/providers/shared/index.js +1 -0
  203. package/dist/providers/shared/materialization-extension.d.ts +12 -0
  204. package/dist/providers/shared/materialization-extension.d.ts.map +1 -1
  205. package/dist/providers/shared/registry.d.ts +69 -0
  206. package/dist/providers/shared/registry.d.ts.map +1 -0
  207. package/dist/providers/shared/registry.js +252 -0
  208. package/dist/providers/shared/restart-adviser.d.ts +26 -0
  209. package/dist/providers/shared/restart-adviser.d.ts.map +1 -0
  210. package/dist/providers/shared/restart-adviser.js +96 -0
  211. package/dist/shared/types.d.ts +4 -0
  212. package/dist/shared/types.d.ts.map +1 -1
  213. package/package.json +2 -2
@@ -63,7 +63,7 @@ launched**, and it records:
63
63
  `gate-target` (adapters may add a more specific diagnostic but never replace
64
64
  or rename these);
65
65
  - the ordered `candidates_considered` before launch (never sorted);
66
- - launch acceptance status (`accepted` or `pre-start-rejected`) and mechanism.
66
+ - launch acceptance status (`accepted` or `blocked-before-start`) and mechanism.
67
67
 
68
68
  Because the launcher constructs the invocation payload itself, this layer does
69
69
  not depend on any child cooperation. A launch is judged consistent only when its
@@ -75,6 +75,20 @@ This layer maps to Dispatch Report V1 and its provenance record; see the
75
75
  [Dispatch Report V1 / producer provenance](dispatch-ceiling.md#dispatch-report-v1-and-producer-provenance)
76
76
  section.
77
77
 
78
+ For project-aware work, OAT persists this native dispatch lineage as one
79
+ generic record per request under the project's `dispatch/` directory. The
80
+ generic snake-case fields remain authoritative. A namespaced `oat` block adds
81
+ only canonical-role identity, proven pre-start rejection, fallback linkage,
82
+ and optional runtime observation. `DispatchReportV1` and the parseable
83
+ `Dispatch:` compatibility stamp keep their existing byte shape.
84
+
85
+ The launcher constructs and redacts the complete payload before calling the
86
+ native host, then records the host's accepted or `blocked-before-start` result
87
+ immediately. Only a provider-wrapper attestation proving that no child started
88
+ can authorize one fresh, exact-target fallback record. Timeout, `BLOCKED`,
89
+ refusal after acceptance, runtime mismatch, missing telemetry, and malformed
90
+ output cannot authorize replacement.
91
+
78
92
  ## Layer 3 — Runtime-observed identity (optional corroboration)
79
93
 
80
94
  Layer 3 is the only layer that reflects what a runtime said about itself, and it
@@ -90,6 +104,95 @@ missing or `not-reported` runtime identity **never invalidates** the
90
104
  launcher-owned configured-invocation evidence in Layer 2. Selected model and
91
105
  effort axes stay exact even when runtime producer identity is not reported.
92
106
 
107
+ ### Provider metadata observation
108
+
109
+ `oat project dispatch record` accepts an optional post-launch observation event
110
+ whose `metadata` is a provider envelope — `provider`, `observedAt`, and
111
+ `entries` — and normalizes it against the record's own immutable configured
112
+ invocation. `entries` may be raw, unmodified provider output. The result is stored under the record's `oat.runtimeObservation`.
113
+
114
+ The channel is metadata-only and capability-gated:
115
+
116
+ | Provider | Observed axes | Notes |
117
+ | -------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
118
+ | Codex | child lineage, role, model, effort | Read from `session_meta` and `turn_context` metadata entries. No captured Codex rollout reports a service tier, so that axis never populates today. |
119
+ | Claude | role, model, effort, service tier; lineage is root-or-child | Read from on-disk `assistant` entry metadata (`attributionAgent`, `effort`, `isSidechain`) plus `message.model` and `message.usage.service_tier`. |
120
+ | Cursor | none | Explicitly `not-reported`; requested values are never copied into it. |
121
+
122
+ Parsers classify entries by their `type` discriminator alone, so a conversation
123
+ entry's body is never read, and only bounded provider identifiers are extracted.
124
+ The Claude parser reads `assistant` entry metadata, which is not the same as
125
+ reading a conversation: it reaches inside `message` by exactly two explicit key
126
+ paths and never spreads, enumerates, or filters that object, so
127
+ `message.content` is never touched rather than being dropped afterwards.
128
+
129
+ Claude reports lineage only as a binary: `root` for a main session and
130
+ `depth-unknown` for a subagent turn. No depth, nesting, or ancestry field exists
131
+ on any captured assistant entry and `parentUuid` links messages within one agent
132
+ rather than agents to each other, so a depth number is reported unknown rather
133
+ than derived.
134
+
135
+ The guarantee is the projection, not caller discipline. Provider parsing happens
136
+ entirely inside the provider module, and what comes back is a flat, closed set
137
+ of neutral facts — lineage, role, model, effort, service tier, correlation —
138
+ whose key names are owned by OAT rather than by the provider. That projection,
139
+ never the raw input, is what the sensitive-content boundary inspects and what is
140
+ compared against the configured invocation. `entries` are never persisted in any
141
+ form.
142
+
143
+ Emitting neutral keys rather than mirroring the provider's own entry shape is
144
+ deliberate. Mirroring a source shape means inheriting its field names, and a
145
+ provider is free to name a field anything: an earlier revision passed the
146
+ provider's shape through and carried `sessionId` and `message` into the output,
147
+ both of which classify as sensitive, which made every real Claude transcript
148
+ unrecordable.
149
+
150
+ A caller may therefore hand over an unmodified rollout or session log: every
151
+ field outside the fact set, including instruction text, conversation bodies,
152
+ working directories, and repository identity, is dropped before the record
153
+ boundary and is never read in the first place. Requiring pre-sanitized input
154
+ instead would push the stripper into every caller, which is a larger leak
155
+ surface than the one it removes.
156
+
157
+ Comparison covers only the axes both sides report, and `comparedAxes` records
158
+ exactly which ones. This qualifier is load-bearing: `matching` means "every axis
159
+ in `comparedAxes` agreed", never "the configured invocation was confirmed". An
160
+ observation reporting only a service tier can be `matching` while model, role,
161
+ and effort are all unknown, so read `comparedAxes` — or the `on role+model`
162
+ qualifier in human output — before treating a match as corroboration. With no
163
+ comparable axis the match is `not-comparable`, because silence is not agreement.
164
+
165
+ An axis a provider genuinely does not expose (`not-exposed`) is excluded rather
166
+ than compared as a literal. That value is reserved for a truly absent axis: an
167
+ axis a provider does report is recorded with its observed value, and an axis it
168
+ simply did not mention on a given run is left unreported. An axis the configured invocation names under two equally
169
+ authoritative spellings — a canonical role name and its materialized native
170
+ selector — matches either.
171
+
172
+ `match` and `comparedAxes` are always derived at the durable-write boundary from
173
+ the record's own configured invocation. A caller that submits a finished
174
+ observation cannot assert its own verdict, and an observation naming a provider
175
+ the record does not use is refused.
176
+
177
+ Request correlation is verified only when the provider declares one: a session
178
+ that names a different request is declined, and a session that declares none is
179
+ attributed to the request the caller paired it with. In practice neither
180
+ provider declares an OAT request id today — no captured Codex rollout carries
181
+ `session_meta.request_id`, and Claude's own `requestId` is a per-turn API
182
+ identifier rather than a dispatch request — so correlation is caller-asserted
183
+ for both, and the declared-correlation check is a forward-compatible guard.
184
+
185
+ A parse failure, a declined request correlation, an unsupported provider, or an
186
+ envelope too large to project all produce `not-reported`. A `runtime-observation`
187
+ event carrying neither `metadata` nor `observation` is a malformed event and is
188
+ rejected by the schema rather than degraded. None of them copies a requested
189
+ argument or a materialized pin into observed state, and `mismatching` is
190
+ evidence only: it authorizes no replacement, retry, or fallback, and leaves
191
+ `launch_status`, `child_outcome`, and every configured control untouched. The
192
+ `--json` result reports `runtimeIdentity.configured` and
193
+ `runtimeIdentity.observed` as separate objects that are never merged into one
194
+ "effective" identity.
195
+
93
196
  ## How the smoke runner consumes these layers
94
197
 
95
198
  The smoke runner's evidence pipeline reads all three layers and asserts only on
@@ -108,6 +211,12 @@ collection. The collector then flows the evidence through three stages:
108
211
  artifacts, carrying `reported` / `not-reported` runtime status without
109
212
  letting a missing Layer 3 fail a Layer 2 assertion.
110
213
 
214
+ The collector projects `runtimeObservation` the same way: it reads committed
215
+ records and never launches a provider, so an observation appears in a bundle
216
+ only because a launcher-owned record already carried one. A partially filled
217
+ observation normalizes to `not-reported` rather than being completed from any
218
+ other layer.
219
+
111
220
  For how to run this end to end and when to refresh the fixture, see
112
221
  [Smoke testing](../../contributing/smoke-testing.md).
113
222
 
@@ -32,6 +32,9 @@ and updates project state.
32
32
  third tier.
33
33
  - **Parallelism:** plan-declared phases may run concurrently in separate
34
34
  worktrees. Tasks inside one phase remain serial.
35
+ - **Dispatch evidence:** project-aware launches persist one generic request
36
+ record plus namespaced OAT native dispatch lineage without changing native
37
+ model or provider selection.
35
38
 
36
39
  Tasks execute serially in one worktree for the phase.
37
40
 
@@ -69,6 +72,16 @@ The root:
69
72
  The root does not implement phase tasks while an accepted phase launch owns
70
73
  that scope.
71
74
 
75
+ Before a native launch, the root constructs and redacts the complete generic
76
+ dispatch record and OAT role event. Immediately after the host returns, it runs
77
+ `oat project dispatch record --project <project-path> --event-file - --json`
78
+ with the accepted or `blocked-before-start` result. An accepted launch closes
79
+ replacement. Only an explicit rejection proving no child started permits one
80
+ fresh request that preserves the exact target and controls and is labeled as
81
+ an approximation. Timeout, `BLOCKED`, refusal after acceptance, runtime
82
+ mismatch, missing telemetry, and malformed output are terminal evidence, not
83
+ fallback triggers.
84
+
72
85
  ### Phase implementer
73
86
 
74
87
  The phase implementer receives one `Phase Scope`, reads the relevant artifacts
@@ -76,12 +76,14 @@ sequenceDiagram
76
76
  participant Root as Project root
77
77
  participant Adapter as Project adapter
78
78
  participant Engine as Dispatch engine
79
+ participant Journal as Project dispatch journal
79
80
  participant Phase as Phase implementer
80
81
 
81
82
  Root->>Adapter: Phase + lifecycle authority
82
83
  Adapter->>Engine: Provider-neutral dispatch request
83
84
  Engine-->>Root: Exact route + request ID
84
85
  Root->>Phase: Phase Scope
86
+ Root->>Journal: Accepted or blocked-before-start record
85
87
  Phase-->>Root: Phase report + commits
86
88
  ```
87
89
 
@@ -118,6 +120,22 @@ original `request_id`.
118
120
  This preserves continuity without allowing replacement after an accepted failed
119
121
  launch.
120
122
 
123
+ ## Native Dispatch Lineage
124
+
125
+ The launcher constructs and redacts the complete generic record plus the
126
+ namespaced OAT role event before it calls the native host. Immediately after
127
+ the host returns, the project adapter validates and persists the accepted or
128
+ `blocked-before-start` state with `oat project dispatch record`. The command is
129
+ a recorder only; it never launches a provider or changes selection authority.
130
+
131
+ An accepted handle owns the scope and closes replacement. One fresh fallback
132
+ record is legal only when the native wrapper proves no child started, links the
133
+ trigger and fallback request IDs, preserves the exact provider/model/effort/
134
+ route/authority controls, resolves canonical role identity, and labels the
135
+ fresh child as an approximation. Timeout, `BLOCKED`, refusal after acceptance,
136
+ runtime mismatch, missing telemetry, interruption, and malformed output never
137
+ authorize a fallback.
138
+
121
139
  ## Optional Third Tier
122
140
 
123
141
  Nested work is appropriate when the work itself benefits:
@@ -1,6 +1,6 @@
1
1
  {
2
- "cli": "0.2.51",
3
- "docs-config": "0.2.51",
4
- "docs-theme": "0.2.51",
5
- "docs-transforms": "0.2.51"
2
+ "cli": "0.2.52",
3
+ "docs-config": "0.2.52",
4
+ "docs-theme": "0.2.52",
5
+ "docs-transforms": "0.2.52"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-dispatch-subagents
3
- version: 1.2.3
3
+ version: 1.2.4
4
4
  description: Use when an OAT skill or workflow needs provider-neutral selection, launch, recovery, or evidence for bounded subagent work without project lifecycle policy.
5
5
  disable-model-invocation: true
6
6
  user-invocable: false
@@ -129,6 +129,62 @@ decomposition.
129
129
  The optional policy and ceiling are already-resolved inputs. Do not infer where
130
130
  they came from or resolve project state to obtain them.
131
131
 
132
+ ## Native Dispatch Lineage
133
+
134
+ For a project-aware dispatch, the calling workflow records native dispatch
135
+ lineage through the project adapter; this provider-neutral engine never writes
136
+ project state itself.
137
+
138
+ 1. Construct the complete generic record and namespaced OAT event, redact it,
139
+ and validate sensitive-content exclusion before the native host call or
140
+ launch. Construction is in memory; do not claim a launch result yet.
141
+ 2. Invoke the exact native target once. Immediately after the host returns,
142
+ record either `launch_status: accepted` or
143
+ `launch_status: blocked-before-start` in the generic dispatch record. A
144
+ blocked result also requires the provider-wrapper attestation
145
+ `provesNoChildStarted: true`.
146
+ 3. Preserve the exact target and controls: provider, model, effort, reasoning
147
+ mode, service tier, route, authority, sandbox/tool payload, deadline, and
148
+ retry limit. Namespaced evidence cannot redefine any generic field.
149
+ 4. Only a proven pre-start rejection permits one fresh fallback record; that
150
+ one fallback requires `provesNoChildStarted: true`. It preserves the exact
151
+ target and controls, links both request IDs,
152
+ includes resolved canonical role identity, and says `approximation: true`.
153
+ 5. Timeout, `BLOCKED`, refusal after acceptance, runtime mismatch, missing
154
+ telemetry, malformed output, and interruption never authorize fallback or
155
+ replacement. Continue only through the accepted handle or stop.
156
+
157
+ Pre-start native-selection rejection is a closed event set, disjoint from
158
+ terminal child-outcome codes. Use exactly one of `native-role-unavailable`,
159
+ `native-target-unavailable`, `native-selector-unsupported`,
160
+ `native-catalog-unsatisfying`, `capability-unresolved-or-unsupported`,
161
+ `wrapper-payload-rejected`, or `wrapper-launch-refused`. The recorder rejects
162
+ every other code, and it names the prohibited outcome family when a terminal
163
+ code such as `timeout` is submitted. A fallback additionally requires the
164
+ trigger record to carry resolved canonical role evidence, and the fallback's
165
+ role evidence must equal it exactly.
166
+
167
+ `wrapper-launch-refused` covers only conditions in which the launch surface
168
+ declined the request and no child process was ever created: a rejected or
169
+ unsupported payload, a refused authorization scope, an unavailable or
170
+ unregistered target, or a wrapper precondition failure raised before spawn. Any
171
+ condition in which a child process was created — including spawn success
172
+ followed by immediate exit, a crash, a broken handle, or a lost transport — is a
173
+ terminal outcome, not a pre-start rejection, and must be recorded through
174
+ `child_outcome`. If you cannot prove the child never existed, you cannot set
175
+ `provesNoChildStarted: true`, and no fallback is authorized.
176
+
177
+ Project-aware callers pass the validated record and event on standard input:
178
+
179
+ ```bash
180
+ oat project dispatch record \
181
+ --project "$PROJECT_PATH" \
182
+ --event-file - \
183
+ --json
184
+ ```
185
+
186
+ The command validates and persists evidence only. It never launches a provider.
187
+
132
188
  ## Capability and Authorization
133
189
 
134
190
  Classify delegation before launch:
@@ -191,7 +191,9 @@ current nested dispatcher. It does not imply a stable enum or authorize
191
191
  reconstruction of a materialized lifecycle variant.
192
192
 
193
193
  `role_selector` is the exact provider or harness agent-type selector, when that
194
- surface exists. Preserve opaque selectors byte-for-byte.
194
+ surface exists. Preserve opaque selectors byte-for-byte, within the
195
+ 256-character identifier bound described under
196
+ [Size and Content Bounds](#size-and-content-bounds).
195
197
 
196
198
  Use the stable selection reasons `native-catalog`,
197
199
  `native-catalog-unsatisfying`, `pre-start-rejection`, `inherit`, and
@@ -257,3 +259,77 @@ the interpreted service tier when known.
257
259
  A service tier never changes `model_class_floor` or `floor_satisfaction`.
258
260
  Unknown tier semantics must be recorded as a diagnostic and may block a
259
261
  consequential route.
262
+
263
+ ## Size and Content Bounds
264
+
265
+ A dispatch record is evidence, not a document. Validation enforces these bounds
266
+ and fails closed; know them before authoring a record rather than discovering
267
+ them at a durable write.
268
+
269
+ Caller-authored text, by kind:
270
+
271
+ - 256 characters — identifiers, names, selectors, routes, and statuses.
272
+ - 512 characters — a single explanatory field such as `classification_reason`
273
+ or one `escalate_when` entry.
274
+ - 1024 characters — the longest free-form fields: `objective`,
275
+ `expected_output`, and `verification_evidence`.
276
+
277
+ Six container fields carry short references and identifiers, never narrative
278
+ text: `payload`, `candidates_considered`, `configured_invocation_evidence`,
279
+ `continuation_events`, `diagnostics`, and `escalate_when`. Each is validated as
280
+ a closed JSON projection bounded on four independent axes, so no one axis can
281
+ be traded against another:
282
+
283
+ - nesting depth at most 4 levels;
284
+ - each string at most 512 characters;
285
+ - at most 512 values per field, which closes chunking one body into many short
286
+ strings; and
287
+ - at most 16 KiB serialized per field.
288
+
289
+ The whole record is additionally capped at 64 KiB, measured as the **published**
290
+ bytes — the pretty-printed JSON plus trailing newline that is actually written
291
+ to the journal, not compact `JSON.stringify` output. The two differ by roughly a
292
+ tenth on a nested record, so size against the published form. Per-field
293
+ projection limits above remain compact measurements, because they bound the
294
+ shape of a field rather than the size of a file. A realistically rich record
295
+ measures a few kilobytes, so these limits bind prompt bodies, transcripts, and
296
+ chunked logs rather than legitimate evidence.
297
+
298
+ Keys are classified against credential, token, prompt/message, transcript, and
299
+ role-content families after Unicode folding, and a spelling the normalizer
300
+ cannot fully account for is treated as sensitive rather than classified on a
301
+ partial token. Store references, identifiers, and digests; never role content, message bodies,
302
+ or credentials.
303
+
304
+ Absolute filesystem paths are handled by field class, because the journal is
305
+ committed and a home path in it is permanent:
306
+
307
+ - **Identity and control fields reject them.** `caller`, `scope`, every
308
+ selector, `selected_route`, the `guidance_*` fields, `authority`,
309
+ `authorization_scope`, `catalog_snapshot`, `candidates_considered` and
310
+ `fallback` refuse a record containing an absolute path, including
311
+ colon-prefixed forms such as `cwd:/Users/alice`. A path is never a legitimate
312
+ identifier there, so ambiguity resolves to rejection. Pass a repository-relative
313
+ path or a redacted form like `<user>/agents/<role>.md`.
314
+ - **Prose and nested evidence redact them best-effort.** `objective`,
315
+ `expected_output`, `verification_evidence`, `classification_reason`,
316
+ `escalate_when`, and the bounded container fields replace a detected path with
317
+ `<redacted-path>`. This is deliberately conservative rather than complete: it
318
+ skips candidates inside an `http`/`https` URL and candidates ending in `/`, so
319
+ a URL route (`?next=/dashboard`) and a regex literal (`/foo/bar/`) survive
320
+ intact. Colon-prefixed forms also survive. Corrupting a legitimate value is
321
+ worse than leaving a path in prose, so do not rely on this to sanitize
322
+ caller-authored text — redact before submitting.
323
+
324
+ Optional runtime observation is metadata-only and subject to the same
325
+ identifier bound, which admits letters, digits, `.`, `_`, and `-` only, so no
326
+ observation value can carry a path or a URL. Its `match` and `comparedAxes` are
327
+ always derived from the record's configured invocation rather than supplied by
328
+ the caller, and `matching` covers only the axes listed in `comparedAxes`.
329
+ It records what a provider reported about its own child and never restates the
330
+ request. An axis the provider did not report is simply absent from the
331
+ observation; an absent or unparseable observation is `not-reported` as a whole;
332
+ and `not-exposed` is reserved vocabulary for an axis a provider genuinely has
333
+ no selectable control for, with no producer today. None of the three is ever
334
+ filled in from `model_selector`, `effort_selector`, `service_tier_selector`, or
335
+ `role_selector`.
@@ -256,7 +256,7 @@ remains immutable baseline evidence for the original p01-t01 verification.
256
256
  | `oat-dispatch-subagents/references/provider-claude.md` | `fbe3a21e9533 -> NG` |
257
257
  | `oat-dispatch-subagents/references/provider-codex.md` | `95b0f82018c7 -> NG` |
258
258
  | `oat-dispatch-subagents/references/provider-cursor.md` | `f781555295a9 -> NG`; `55ccfef14fd6 -> NG` |
259
- | `oat-dispatch-subagents/references/record-schema.md` | `78f8069274a8 -> NG`; `1c9a84c4d1e0 -> NG` |
259
+ | `oat-dispatch-subagents/references/record-schema.md` | `78f8069274a8 -> NG`; `1c9a84c4d1e0 -> NG`; `2a63da6e3a96 -> NG`; `30762d53b043 -> NG` |
260
260
  | `oat-project-dispatch-subagents/SKILL.md` | `eca03ad1ca12 -> PDISPATCH-01`; `59fbcdc79cea -> PDISPATCH-01` |
261
261
  | `oat-project-plan/SKILL.md` | `f99e44b39932 -> PLAN-12`; `7e6a9854504b -> NG` |
262
262
  | `oat-project-implement/references/completion-and-closeout.md` | `6909a5a5a1fa -> IMPLEMENT-19`; `a7c02ef670fd -> IMPLEMENT-19`; `9dde56d89a71 -> IMPLEMENT-16`; `13c41b2b2590 -> IMPLEMENT-16` |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: oat-project-dispatch-subagents
3
- version: 1.1.3
3
+ version: 1.1.4
4
4
  description: Use when an OAT project lifecycle skill needs to translate project state, phase or task scope, gates, and write authority into a provider-neutral subagent dispatch.
5
5
  disable-model-invocation: true
6
6
  user-invocable: false
@@ -151,6 +151,29 @@ For every lifecycle dispatch:
151
151
  9. Add lifecycle outcome metadata and let the calling workflow perform state,
152
152
  plan, implementation-log, commit, or review-table writes.
153
153
 
154
+ ### Persist native dispatch lineage
155
+
156
+ For project-aware launches, apply the generic engine's native dispatch lineage
157
+ contract. Construct and redact the complete generic record plus OAT event
158
+ before the native host call. Immediately after the call returns accepted or
159
+ `blocked-before-start`, persist the result with:
160
+
161
+ ```bash
162
+ oat project dispatch record \
163
+ --project "$PROJECT_PATH" \
164
+ --event-file - \
165
+ --json
166
+ ```
167
+
168
+ The accepted record closes replacement. A rejected record must include
169
+ `provesNoChildStarted: true` before one target-preserving canonical-instruction
170
+ fallback may receive its own fresh request ID. Preserve exact provider, model,
171
+ effort, reasoning mode, service tier, route, authority, payload controls,
172
+ deadline, and retry limit. Timeout, `BLOCKED`, refusal after acceptance,
173
+ runtime mismatch, missing telemetry, or malformed output never authorizes
174
+ fallback or replacement. The recorder validates evidence; it never launches a
175
+ provider or mutates lifecycle bookkeeping.
176
+
154
177
  Example adapter input:
155
178
 
156
179
  ```yaml
@@ -256,7 +256,7 @@ remains immutable baseline evidence for the original p01-t01 verification.
256
256
  | `oat-dispatch-subagents/references/provider-claude.md` | `fbe3a21e9533 -> NG` |
257
257
  | `oat-dispatch-subagents/references/provider-codex.md` | `95b0f82018c7 -> NG` |
258
258
  | `oat-dispatch-subagents/references/provider-cursor.md` | `f781555295a9 -> NG`; `55ccfef14fd6 -> NG` |
259
- | `oat-dispatch-subagents/references/record-schema.md` | `78f8069274a8 -> NG`; `1c9a84c4d1e0 -> NG` |
259
+ | `oat-dispatch-subagents/references/record-schema.md` | `78f8069274a8 -> NG`; `1c9a84c4d1e0 -> NG`; `2a63da6e3a96 -> NG`; `30762d53b043 -> NG` |
260
260
  | `oat-project-dispatch-subagents/SKILL.md` | `eca03ad1ca12 -> PDISPATCH-01`; `59fbcdc79cea -> PDISPATCH-01` |
261
261
  | `oat-project-plan/SKILL.md` | `f99e44b39932 -> PLAN-12`; `7e6a9854504b -> NG` |
262
262
  | `oat-project-implement/references/completion-and-closeout.md` | `6909a5a5a1fa -> IMPLEMENT-19`; `a7c02ef670fd -> IMPLEMENT-19`; `9dde56d89a71 -> IMPLEMENT-16`; `13c41b2b2590 -> IMPLEMENT-16` |
@@ -386,6 +386,17 @@ For gate-originated review, keep `dispatchReport.gateInvocation`, existing
386
386
  work-producer `diversity`, and reviewer `runtimeIdentity` as three distinct
387
387
  facts; producer stamps or self-report never overwrite configured invocation.
388
388
 
389
+ All project-aware launch paths preserve native dispatch lineage. Construct and
390
+ redact the complete generic record plus OAT role event before the native host
391
+ call. Immediately after the call returns `accepted` or
392
+ `blocked-before-start`, run `oat project dispatch record --project
393
+ "$PROJECT_PATH" --event-file - --json`. The rejected form must attest
394
+ `provesNoChildStarted: true`; only it permits one exact-target approximation
395
+ with a fresh request ID. Preserve exact model, effort, reasoning, service tier,
396
+ route, authority, and provider controls. Timeout, `BLOCKED`, refusal after
397
+ acceptance, runtime mismatch, missing telemetry, interruption, or malformed
398
+ output never authorizes fallback or replacement.
399
+
389
400
  Axis states:
390
401
 
391
402
  - `selected:<value>` - host exposes the axis and the orchestrator chose a value.
@@ -256,7 +256,7 @@ remains immutable baseline evidence for the original p01-t01 verification.
256
256
  | `oat-dispatch-subagents/references/provider-claude.md` | `fbe3a21e9533 -> NG` |
257
257
  | `oat-dispatch-subagents/references/provider-codex.md` | `95b0f82018c7 -> NG` |
258
258
  | `oat-dispatch-subagents/references/provider-cursor.md` | `f781555295a9 -> NG`; `55ccfef14fd6 -> NG` |
259
- | `oat-dispatch-subagents/references/record-schema.md` | `78f8069274a8 -> NG`; `1c9a84c4d1e0 -> NG` |
259
+ | `oat-dispatch-subagents/references/record-schema.md` | `78f8069274a8 -> NG`; `1c9a84c4d1e0 -> NG`; `2a63da6e3a96 -> NG`; `30762d53b043 -> NG` |
260
260
  | `oat-project-dispatch-subagents/SKILL.md` | `eca03ad1ca12 -> PDISPATCH-01`; `59fbcdc79cea -> PDISPATCH-01` |
261
261
  | `oat-project-plan/SKILL.md` | `f99e44b39932 -> PLAN-12`; `7e6a9854504b -> NG` |
262
262
  | `oat-project-implement/references/completion-and-closeout.md` | `6909a5a5a1fa -> IMPLEMENT-19`; `a7c02ef670fd -> IMPLEMENT-19`; `9dde56d89a71 -> IMPLEMENT-16`; `13c41b2b2590 -> IMPLEMENT-16` |