@open-agent-toolkit/cli 0.2.54 → 0.2.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/bundle-metadata.json +1 -1
- package/assets/docs/cli-utilities/configuration.md +12 -2
- package/assets/docs/docs-tooling/commands.md +36 -5
- package/assets/docs/reference/oat-directory-structure.md +56 -4
- package/assets/docs/workflows/skills/recon.md +28 -12
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-dispatch-subagents/SKILL.md +4 -105
- package/assets/skills/oat-dispatch-subagents/references/record-schema.md +0 -226
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +2 -2
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +2 -2
- package/assets/skills/recon/SKILL.md +76 -38
- package/assets/skills/recon/references/packet-contract.md +138 -105
- package/assets/skills/recon/scripts/lib/contracts.mjs +181 -674
- package/assets/skills/recon/scripts/lib/validated-run.mjs +10 -16
- package/assets/skills/recon/scripts/render-packet.mjs +7 -20
- package/assets/skills/recon/scripts/validate-packet.mjs +177 -344
- package/dist/commands/config/index.d.ts +1 -0
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +51 -4
- package/dist/commands/docs/index-generate/generator.d.ts +43 -1
- package/dist/commands/docs/index-generate/generator.d.ts.map +1 -1
- package/dist/commands/docs/index-generate/generator.js +169 -3
- package/dist/commands/docs/index-generate/index.d.ts +8 -3
- package/dist/commands/docs/index-generate/index.d.ts.map +1 -1
- package/dist/commands/docs/index-generate/index.js +340 -24
- package/dist/commands/docs/init/scaffold.d.ts +11 -1
- package/dist/commands/docs/init/scaffold.d.ts.map +1 -1
- package/dist/commands/docs/init/scaffold.js +11 -2
- package/dist/config/oat-config.d.ts +14 -0
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +61 -0
- package/dist/fs/assets.d.ts +33 -4
- package/dist/fs/assets.d.ts.map +1 -1
- package/dist/fs/assets.js +127 -12
- package/package.json +2 -2
|
@@ -90,6 +90,7 @@ Common keys in `.oat/config.json`:
|
|
|
90
90
|
- `worktrees.root` — where OAT-managed worktrees live
|
|
91
91
|
- `git.defaultBranch` — base branch fallback for PR workflows
|
|
92
92
|
- `documentation.root`, `documentation.tooling`, `documentation.config` — docs-surface ownership
|
|
93
|
+
- `documentation.excludes` — a JSON array of globs, relative to the docs directory, that `oat docs generate-index` leaves out of the generated index. `oat config set` takes the list as one comma-separated value (`"a/**,b.md"`) and stores it as an array; repeated `--exclude` flags extend it, and an empty value clears the key
|
|
93
94
|
- `documentation.requireForProjectCompletion` — whether docs sync is a completion gate
|
|
94
95
|
- `archive.s3Uri` — base S3 archive prefix
|
|
95
96
|
- `archive.s3SyncOnComplete` — upload archived projects to S3 during completion
|
|
@@ -242,8 +243,17 @@ packaged `assets/` directory next to the installed CLI. Setting a non-empty
|
|
|
242
243
|
directory.
|
|
243
244
|
- The override is validated exactly like the packaged root and fails closed:
|
|
244
245
|
the path must be a directory containing bundle metadata whose version matches
|
|
245
|
-
the running CLI (`OAT_VERSION`)
|
|
246
|
-
|
|
246
|
+
the running CLI (`OAT_VERSION`) **and** the seven top-level directories the
|
|
247
|
+
bundle producer creates (`skills`, `agents`, `templates`, `scripts`, `docs`,
|
|
248
|
+
`migration`, `config`), each of which must be a directory. A missing,
|
|
249
|
+
malformed, version-mismatched, or structurally incomplete override is an
|
|
250
|
+
error with exit code 2 that names the first offending path — the CLI never
|
|
251
|
+
silently falls back to packaged assets, and a metadata-only directory is no
|
|
252
|
+
longer accepted as an empty installation.
|
|
253
|
+
- Remedies are source-aware: an `OAT_ASSETS_DIR` failure tells you to fix or
|
|
254
|
+
unset the override, never to rebuild or reinstall the CLI; a packaged-bundle
|
|
255
|
+
failure keeps the rebuild/reinstall guidance. A directory that exists but
|
|
256
|
+
cannot be read reports the underlying error code.
|
|
247
257
|
- Produce a matching bundle with `bash packages/cli/scripts/bundle-assets.sh`
|
|
248
258
|
while `OAT_ASSETS_DIR` points at the target directory (the script already
|
|
249
259
|
honors the variable as its destination).
|
|
@@ -128,23 +128,54 @@ Key behavior:
|
|
|
128
128
|
- recursively walks the docs directory
|
|
129
129
|
- extracts page titles from frontmatter (falls back to first `# heading`, then filename title-case)
|
|
130
130
|
- includes descriptions from frontmatter when present
|
|
131
|
-
-
|
|
132
|
-
-
|
|
131
|
+
- resolves omitted paths from `.oat/config.json` rather than the current directory: `--docs-dir` defaults to `<documentation.root>/docs` when that directory exists and to `<documentation.root>` otherwise, and `--output` defaults to the app-root manifest `<documentation.root>/index.md`
|
|
132
|
+
- treats explicitly supplied `--docs-dir` / `--output` paths as overrides resolved from the current directory
|
|
133
|
+
- fails with exit code `2` before generating or writing anything when an omitted path has no non-empty `documentation.root` to resolve against, or when the configured root is not a directory
|
|
134
|
+
- refuses unsafe output targets with exit code `1` before generation, for derived and explicit paths alike, comparing symlink-resolved paths: inside the docs directory it indexes, equal to `documentation.config`, or ending in `.yml` / `.yaml` in any case. A derived output whose existing file lacks the `AUTOGENERATED` header is refused too; naming that path with `--output` overwrites it explicitly. A refused target is an actionable flag error (`1`); unusable path configuration is a separate condition and exits `2`, so scripts can branch on the two
|
|
135
|
+
- writes configuration only for the Fumadocs manifest transition — recording the manifest it just wrote inside `documentation.root` in `documentation.index`, when `documentation.tooling` is `fumadocs` or the config declares neither `tooling` nor `config`. MkDocs configurations are never written, and `documentation.root` and `documentation.config` are never modified
|
|
133
136
|
- prepends an `AUTOGENERATED` warning comment to the output and rewrites the file on every run; do not hand-edit the generated `index.md`
|
|
134
137
|
- should be freshness-checked against authored `docs/**/index.md` `## Contents` maps before treating it as navigation evidence
|
|
135
138
|
- sorting: `index.md` first, then directories before files, then lexical
|
|
139
|
+
- reports the derived docs directory in human output and as `docsDir` / `docsDirSource` under `--json`
|
|
140
|
+
- omits pages matching the exclusion list. Nothing is excluded by default; once listed, non-page Markdown such as `CLAUDE.md` or `AGENTS.md` stops reaching the manifest. Patterns come from `documentation.excludes` in `.oat/config.json` and from repeated `--exclude` flags, and the flags **extend** the configured list rather than replacing it. A directory left empty by exclusion emits no heading, and an empty list produces byte-identical output to no exclusions at all
|
|
136
141
|
|
|
137
142
|
Supported flags:
|
|
138
143
|
|
|
139
|
-
- `--docs-dir <path>` (default:
|
|
140
|
-
- `--output <path>` (default:
|
|
144
|
+
- `--docs-dir <path>` (default: `<documentation.root>/docs`, falling back to `<documentation.root>`)
|
|
145
|
+
- `--output <path>` (default: `<documentation.root>/index.md`)
|
|
146
|
+
- `--exclude <glob>` (repeatable; additive to `documentation.excludes`)
|
|
147
|
+
|
|
148
|
+
### Exclusion patterns
|
|
149
|
+
|
|
150
|
+
Patterns match the path of each candidate **relative to the docs directory being indexed** — `api/auth.md`, `api/nested` — never an absolute or current-directory-relative path, and never the repository-relative path.
|
|
151
|
+
|
|
152
|
+
| Pattern | Matches |
|
|
153
|
+
| -------------- | -------------------------------------------------------- |
|
|
154
|
+
| `CLAUDE.md` | only the root-level `CLAUDE.md`; patterns are anchored |
|
|
155
|
+
| `**/CLAUDE.md` | `CLAUDE.md` at any depth, including the docs root |
|
|
156
|
+
| `*.md` | root-level Markdown only; `*` never crosses `/` |
|
|
157
|
+
| `drafts/` | the `drafts` directory and everything beneath it |
|
|
158
|
+
| `drafts` | the same directory; the trailing `/` only forbids a file |
|
|
159
|
+
| `api/**/*.md` | Markdown at any depth under `api/`, including `api/x.md` |
|
|
160
|
+
|
|
161
|
+
A trailing `/` restricts a pattern to directories and never matches a file; without it, a pattern that matches a directory path still prunes that directory. `**` spans `/` only as a whole path segment — inside a segment (`a**b`) it is an ordinary single-segment wildcard. Matching is case-sensitive, `/` is the separator on every platform, and only `*` and `**` are metacharacters — every other character, `.` included, is literal. A leading `./` or `/` is stripped, so both spellings anchor at the docs root.
|
|
141
162
|
|
|
142
163
|
Example:
|
|
143
164
|
|
|
144
165
|
```bash
|
|
145
|
-
|
|
166
|
+
# Resolve both paths from .oat/config.json
|
|
167
|
+
oat docs generate-index
|
|
168
|
+
|
|
169
|
+
# Portable explicit form, resolved from the current directory
|
|
170
|
+
oat docs generate-index --docs-dir apps/oat-docs/docs --output apps/oat-docs/index.md
|
|
171
|
+
|
|
172
|
+
# Persist the repository's own exclusions, then add a one-off
|
|
173
|
+
oat config set documentation.excludes "**/CLAUDE.md,**/AGENTS.md"
|
|
174
|
+
oat docs generate-index --exclude 'drafts/'
|
|
146
175
|
```
|
|
147
176
|
|
|
177
|
+
See [Documentation path resolution](../reference/oat-directory-structure.md#documentation-path-resolution) for the app-root meaning of `documentation.root` and the legacy source-root compatibility rule.
|
|
178
|
+
|
|
148
179
|
The Fumadocs scaffold runs this automatically via `predev`/`prebuild` npm
|
|
149
180
|
script hooks.
|
|
150
181
|
|
|
@@ -117,10 +117,11 @@ Current schema keys:
|
|
|
117
117
|
| `projects.root` | `string` | `".oat/projects/shared"` | Default root directory for OAT projects |
|
|
118
118
|
| `projects.defaultScope` | `string` | `"synced"` | Scope used by project creation when `--scope` is omitted: `shared`, `local`, or `synced`. Environment override: `OAT_PROJECTS_DEFAULT_SCOPE`. |
|
|
119
119
|
| `localPaths` | `string[]` | - | Gitignored directories to sync between main repo and worktrees. Supports glob patterns. Managed via `oat local add/remove`. |
|
|
120
|
-
| `documentation.root` | `string` | - |
|
|
120
|
+
| `documentation.root` | `string` | - | Docs **app root** — the directory `oat docs init` scaffolds (e.g., `apps/docs`). Authored pages live under `<root>/docs`. See [Documentation path resolution](#documentation-path-resolution). |
|
|
121
121
|
| `documentation.tooling` | `string` | - | Documentation framework identifier (`mkdocs` or `fumadocs`) |
|
|
122
122
|
| `documentation.config` | `string` | - | Path to the documentation framework config file (e.g., `mkdocs.yml`, `next.config.js`) |
|
|
123
|
-
| `documentation.index` | `string` | - | Path to the docs surface entry point
|
|
123
|
+
| `documentation.index` | `string` | - | Path to the docs surface entry point: the generated app-root manifest `<root>/index.md` for Fumadocs, `mkdocs.yml` for MkDocs. Set by `oat docs init`. `oat docs generate-index` writes it only for the Fumadocs manifest transition and never for MkDocs. |
|
|
124
|
+
| `documentation.excludes` | `string[]` | - | Globs, relative to the docs directory, that `oat docs generate-index` leaves out of the generated index. See [Excluding pages from the generated index](#excluding-pages-from-the-generated-index). |
|
|
124
125
|
| `documentation.requireForProjectCompletion` | `boolean` | `false` | When `true`, OAT project completion gates require documentation to be updated |
|
|
125
126
|
| `git.defaultBranch` | `string` | `"main"` | Default branch for PR creation. Auto-detected during `oat init` via `gh repo view` or `origin/HEAD`. Used by `oat-project-pr-final` and `oat-project-pr-progress`. |
|
|
126
127
|
| `workflow.autoReviewAtHillCheckpoints` | `boolean` | unset | When `true`, completing a HiLL checkpoint automatically runs the extra lifecycle review. Does not control Tier 1 per-phase `oat-reviewer` gates. Can be overridden per-project via `oat_auto_review_at_hill_checkpoints` in `plan.md` frontmatter. Legacy `autoReviewAtCheckpoints` remains a fallback. |
|
|
@@ -157,14 +158,65 @@ Example:
|
|
|
157
158
|
"root": ".worktrees"
|
|
158
159
|
},
|
|
159
160
|
"documentation": {
|
|
160
|
-
"root": "apps/docs
|
|
161
|
+
"root": "apps/docs",
|
|
161
162
|
"tooling": "mkdocs",
|
|
162
|
-
"config": "mkdocs.yml",
|
|
163
|
+
"config": "apps/docs/mkdocs.yml",
|
|
164
|
+
"index": "apps/docs/mkdocs.yml",
|
|
163
165
|
"requireForProjectCompletion": false
|
|
164
166
|
}
|
|
165
167
|
}
|
|
166
168
|
```
|
|
167
169
|
|
|
170
|
+
### Documentation path resolution
|
|
171
|
+
|
|
172
|
+
`documentation.root` canonically names the docs **app root** — exactly the directory `oat docs init` scaffolds. Authored Markdown lives under `<root>/docs`, and the generated Fumadocs manifest is written to `<root>/index.md`, outside the tree it indexes.
|
|
173
|
+
|
|
174
|
+
`oat docs generate-index` resolves omitted options from this configuration:
|
|
175
|
+
|
|
176
|
+
| Option | Omitted | Supplied |
|
|
177
|
+
| ------------ | ---------------------------------------------------------------------------------------- | ----------------------------------- |
|
|
178
|
+
| `--docs-dir` | `<documentation.root>/docs` when that directory exists, otherwise `<documentation.root>` | Resolved from the current directory |
|
|
179
|
+
| `--output` | `<documentation.root>/index.md` | Resolved from the current directory |
|
|
180
|
+
|
|
181
|
+
If an omitted option has no non-empty `documentation.root` to resolve against, or the configured root is not a directory, the command fails with exit code `2` before generating or writing anything.
|
|
182
|
+
|
|
183
|
+
**Compatibility behavior.** Preferring `<root>/docs` exists for legacy configs whose `root` names a docs _source_ directory rather than an app root; it is not a second meaning of the key. Because the rule is a plain directory-existence test, a source root that happens to contain its own `docs` subdirectory is narrowed to it. The command prints the directory it derived in both human and JSON output (`docsDir`, `docsDirSource`), and `--docs-dir` is the escape hatch when the derivation is wrong.
|
|
184
|
+
|
|
185
|
+
A legacy source root with no `docs` child resolves `--docs-dir` and `--output` to the same tree, so a bare run is refused rather than allowed to overwrite an authored page. Pass an explicit `--output` outside the source tree, or repoint `documentation.root` at the app root.
|
|
186
|
+
|
|
187
|
+
**Refused output targets.** Checked before generation for derived and explicit paths alike, the command refuses to write an output that is inside the docs directory it indexes, equals `documentation.config`, or ends in `.yml` / `.yaml`. A derived output whose existing file lacks the `AUTOGENERATED by oat docs generate-index` header is also refused; naming that same path with `--output` overwrites it explicitly.
|
|
188
|
+
|
|
189
|
+
**Configuration writes.** The only configuration write generation performs is the Fumadocs manifest transition: when the written manifest lies inside `documentation.root` and `documentation.tooling` is `fumadocs`, the repo-relative output path is recorded in `documentation.index`. A config that declares neither `documentation.tooling` nor `documentation.config` is treated as the same Fumadocs-shaped case. Any other declared tooling — `mkdocs` included — is never written, and neither are `documentation.root` and `documentation.config`. The value is always repo-relative: when `documentation.root` points outside the repository, the manifest is still generated but the key is left untouched rather than recording a machine-specific path.
|
|
190
|
+
|
|
191
|
+
### Excluding pages from the generated index
|
|
192
|
+
|
|
193
|
+
`documentation.excludes` and the repeatable `--exclude <glob>` flag feed one matcher. Flags **extend** the configured list rather than replacing it, so a one-off exclusion cannot silently republish pages the repository deliberately excluded. A directory left empty by exclusion emits no heading, and an empty list produces byte-identical output to no exclusions at all.
|
|
194
|
+
|
|
195
|
+
Patterns are matched against each candidate's path **relative to the docs directory being indexed** — the directory `--docs-dir` resolved to, not `documentation.root` and not the repository root.
|
|
196
|
+
|
|
197
|
+
| Pattern | Matches |
|
|
198
|
+
| -------------- | -------------------------------------------------------- |
|
|
199
|
+
| `CLAUDE.md` | only the root-level `CLAUDE.md`; patterns are anchored |
|
|
200
|
+
| `**/CLAUDE.md` | `CLAUDE.md` at any depth, including the docs root |
|
|
201
|
+
| `*.md` | root-level Markdown only; `*` never crosses `/` |
|
|
202
|
+
| `drafts/` | the `drafts` directory and everything beneath it |
|
|
203
|
+
| `api/**/*.md` | Markdown at any depth under `api/`, including `api/x.md` |
|
|
204
|
+
|
|
205
|
+
A trailing `/` restricts a pattern to directories and never matches a file; without it, a pattern that matches a directory path still prunes that directory. `**` spans `/` only as a whole path segment — inside a segment (`a**b`) it is an ordinary single-segment wildcard. Matching is case-sensitive, `/` is the separator on every platform, and only `*` and `**` are metacharacters — every other character, `.` included, is literal. A leading `./` or `/` is stripped, so both spellings anchor at the docs root. Entries are trimmed and de-duplicated; a malformed `documentation.excludes` (a non-array, or an empty or non-string entry) is rejected rather than silently ignored. `oat docs generate-index` reports it with exit code `2`; `oat config` surfaces the same error as an ordinary exit-`1` user error. `oat config set documentation.excludes` can still replace or clear a malformed value, so the repair the error names always works.
|
|
206
|
+
|
|
207
|
+
Set the list with the comma-separated grammar, and clear it with an empty value:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
oat config set documentation.excludes "**/CLAUDE.md,**/AGENTS.md"
|
|
211
|
+
oat config set documentation.excludes ""
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
This repository pins the invocation explicitly, which is the portable fallback anywhere the configured defaults are not what you want:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
oat docs generate-index --docs-dir apps/oat-docs/docs --output apps/oat-docs/index.md
|
|
218
|
+
```
|
|
219
|
+
|
|
168
220
|
### Worktree root precedence
|
|
169
221
|
|
|
170
222
|
When resolving the worktree root directory, `oat-worktree-bootstrap` uses this strict precedence (stops at the first match):
|
|
@@ -70,10 +70,17 @@ maximum concurrency; they do not silently choose a different model tier.
|
|
|
70
70
|
| `thorough` | Expensive failure or correlated blind spots | Standard work plus redundant gathering and verification and contradiction resolution | `verified` |
|
|
71
71
|
|
|
72
72
|
The approval manifest shows the exact adaptive lane count, concurrency, pass
|
|
73
|
-
topology,
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
73
|
+
topology, deadlines, retries, and source/write authority. Declining approval
|
|
74
|
+
launches nothing. A change to a provider, model, effort, route, role, service
|
|
75
|
+
tier, or execution cap requires renewed approval; there is no silent
|
|
76
|
+
substitution after approval.
|
|
77
|
+
|
|
78
|
+
Before any worker launches, recon confirms that the live launch surface can run
|
|
79
|
+
the approved role, model, effort, and authority level. If it cannot, the run
|
|
80
|
+
stays at `awaiting-approval` with a provider/dispatch diagnostic and nothing is
|
|
81
|
+
launched. Deadlines are approved execution limits chosen for the task class,
|
|
82
|
+
not short watchdogs; an accepted lane is never interrupted by hand because a
|
|
83
|
+
displayed deadline elapsed.
|
|
77
84
|
|
|
78
85
|
## Destination Precedence
|
|
79
86
|
|
|
@@ -105,12 +112,12 @@ non-publishable candidate generation withdraws any existing `packet.md`:
|
|
|
105
112
|
|
|
106
113
|
- `packet.md` is the compact consumer view and is published last.
|
|
107
114
|
- `claims.json` is the canonical claim ledger.
|
|
108
|
-
- `manifest.json` records request, source,
|
|
109
|
-
provenance.
|
|
110
|
-
- `reviews/` contains compact
|
|
115
|
+
- `manifest.json` records request, source, approved execution envelope, and
|
|
116
|
+
gap provenance.
|
|
117
|
+
- `reviews/` contains compact semantic, adversarial, coverage, and
|
|
111
118
|
reconciliation evidence.
|
|
112
|
-
- `raw/` contains worker dossiers,
|
|
113
|
-
|
|
119
|
+
- `raw/` contains worker dossiers, candidate artifacts, and safe failure
|
|
120
|
+
diagnostics. It is not normal consumer input.
|
|
114
121
|
|
|
115
122
|
The ledger compiler and packet validator enforce categorical referential
|
|
116
123
|
integrity on `synthesis.keyClaimIds` and `synthesis.unresolvedQuestionIds`. Any
|
|
@@ -137,7 +144,8 @@ percentages:
|
|
|
137
144
|
- `unsupported`: valid supporting evidence is absent or verification failed.
|
|
138
145
|
|
|
139
146
|
A quick packet never promotes a claim to `verified`. Stronger profiles can do
|
|
140
|
-
so only when their required review artifacts and
|
|
147
|
+
so only when their required review artifacts validate and were written by
|
|
148
|
+
approved lanes.
|
|
141
149
|
|
|
142
150
|
When an independent semantic review rejects a proposed claim, the reconciler
|
|
143
151
|
transitions it to `unsupported` rather than deleting it. This preserves the
|
|
@@ -179,7 +187,15 @@ A structurally valid run can publish an honest `partial` packet. The manifest
|
|
|
179
187
|
and `packet.md` then identify the requested and achieved profiles, failed or
|
|
180
188
|
omitted passes, material gaps, affected claims, and required assurance
|
|
181
189
|
downgrades. A run may be partial even when it achieved the requested profile if
|
|
182
|
-
a material evidence gap remains.
|
|
190
|
+
a material evidence gap remains. The achieved profile is derived from the
|
|
191
|
+
complete typed artifacts in the packet; each required pass without a complete
|
|
192
|
+
result needs a material `PASS_FAILED` or `PASS_OMITTED` gap naming it.
|
|
193
|
+
|
|
194
|
+
Status updates and the final handoff label each failure as `worker`,
|
|
195
|
+
`provider/dispatch`, `contract validation`, or `source availability`, and
|
|
196
|
+
say whether every accepted lane reached a terminal result. Workers that
|
|
197
|
+
completed are never reported as failed because the controller could not
|
|
198
|
+
publish.
|
|
183
199
|
|
|
184
200
|
Before assurance or publication, candidate runs are normalized into a deeply
|
|
185
201
|
immutable `ValidatedRun`. To prevent premature or invalid promotion,
|
|
@@ -189,6 +205,6 @@ runs (`failed`, `running`, `preparing`, `awaiting-approval`) withdraw any
|
|
|
189
205
|
existing `packet.md` under the unchanged-root guard, leave no `ValidatedRun`,
|
|
190
206
|
and cause the exported renderer to fail closed with `PACKET_NOT_PUBLISHABLE`.
|
|
191
207
|
|
|
192
|
-
If the manifest, ledger,
|
|
208
|
+
If the manifest, ledger, approval envelope, source identities, or publication
|
|
193
209
|
boundary cannot be validated, the run is `failed`. It may retain safe raw
|
|
194
210
|
diagnostics, but it does not publish a misleading `packet.md`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: oat-dispatch-subagents
|
|
3
|
-
version: 1.2.
|
|
3
|
+
version: 1.2.6
|
|
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,11 +129,6 @@ 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
|
-
The optional `operation` is `prepare`, `execute`, or `dispatch`. `prepare` and
|
|
133
|
-
`execute` form the approval-bound two-step path below. When `operation` is
|
|
134
|
-
omitted, treat it as `operation: dispatch` and preserve the existing one-step
|
|
135
|
-
selection-and-launch path for backwards compatibility.
|
|
136
|
-
|
|
137
132
|
## Native Dispatch Lineage
|
|
138
133
|
|
|
139
134
|
For a project-aware dispatch, the calling workflow records native dispatch
|
|
@@ -375,99 +370,9 @@ Before explicit selection:
|
|
|
375
370
|
Do not launch a diagnostic child solely to obtain a catalog the provider
|
|
376
371
|
cannot expose before selection. Record the visibility timing instead.
|
|
377
372
|
|
|
378
|
-
## Approval-Bound Preparation and Execution
|
|
379
|
-
|
|
380
|
-
Use this path when a caller must show the exact selection and execution
|
|
381
|
-
envelope for approval before any child starts. The caller still owns the user
|
|
382
|
-
interaction; this skill produces and validates the approval evidence.
|
|
383
|
-
|
|
384
|
-
### `operation: prepare`
|
|
385
|
-
|
|
386
|
-
Preparation is selection-only. It must observe the live catalog in the exact
|
|
387
|
-
dispatch context and return a complete prepared dispatch record without
|
|
388
|
-
launching, reserving capacity, or obtaining a child handle.
|
|
389
|
-
|
|
390
|
-
Before selecting a target:
|
|
391
|
-
|
|
392
|
-
1. Classify all planned and conditional waves before selection. Record every
|
|
393
|
-
wave's `task_class` and `model_class_floor`.
|
|
394
|
-
2. Compute the run-wide maximum model-class floor using the durable task-class
|
|
395
|
-
order. Conditional waves count even when the caller may later skip them.
|
|
396
|
-
3. Select one exact target at or above that maximum floor and pin it across all
|
|
397
|
-
prepared waves. The pin includes provider, dispatch context, route, role,
|
|
398
|
-
model and selector granularity, effort, reasoning mode, and service tier.
|
|
399
|
-
Do not weaken a wave floor, split the target, or silently substitute a
|
|
400
|
-
cheaper target. If one target cannot satisfy every wave, return a blocked
|
|
401
|
-
preparation.
|
|
402
|
-
4. Materialize each wave's exact authority, deadline, retry limit,
|
|
403
|
-
concurrency, lane cap, scopes, lane IDs, context controls, fallback, and
|
|
404
|
-
canonical redacted payload digest. Record the catalog observation identity
|
|
405
|
-
and the fingerprint of the relevant selectable facts.
|
|
406
|
-
5. Construct the canonical approval projection defined in
|
|
407
|
-
`references/record-schema.md`, return `dispatch_state: prepared`, and stop.
|
|
408
|
-
|
|
409
|
-
The calling workflow may combine prepared wave records into a run manifest,
|
|
410
|
-
but it must preserve the run ID, maximum floor, pinned target, per-wave axes,
|
|
411
|
-
canonical approval fingerprint, and prepared timestamp byte-for-byte.
|
|
412
|
-
|
|
413
|
-
### Approval
|
|
414
|
-
|
|
415
|
-
The caller presents the complete approval projection and records explicit
|
|
416
|
-
approval by changing only `dispatch_state`, `approved_at`, and the approval
|
|
417
|
-
evidence fields allowed by the schema. Approval is valid only for the exact
|
|
418
|
-
canonical fingerprint. Editing any bound axis creates a new preparation; it
|
|
419
|
-
does not update an already approved record in place.
|
|
420
|
-
|
|
421
|
-
### `operation: execute`
|
|
422
|
-
|
|
423
|
-
Execution accepts one approved prepared record. Before invoking the launcher:
|
|
424
|
-
|
|
425
|
-
1. Validate the prepared-record version, legal state, approval timestamp, and
|
|
426
|
-
approval fingerprint against the unchanged canonical projection.
|
|
427
|
-
2. Re-observe the live catalog in the same dispatch context and compare the
|
|
428
|
-
current relevant selectable facts with the prepared observation. A new
|
|
429
|
-
unrelated candidate alone is not relevant drift; removal, renaming,
|
|
430
|
-
semantic change, or loss of selectability for an approved control is.
|
|
431
|
-
3. Re-resolve the actual launch controls without choosing alternatives and
|
|
432
|
-
compare every approval-bound axis exactly. Provider-native opaque values
|
|
433
|
-
stay byte-for-byte exact.
|
|
434
|
-
4. Refuse launch and mark the record `stale` when any comparison differs. The
|
|
435
|
-
caller must run `prepare` again and obtain reapproval.
|
|
436
|
-
5. Launch the approved payload once. Record `accepted` only from positive
|
|
437
|
-
launcher acceptance; otherwise record `not-accepted`.
|
|
438
|
-
|
|
439
|
-
A model change is model drift. An effort change is effort drift. A provider
|
|
440
|
-
change is provider drift. A route change is route drift. A role change is role
|
|
441
|
-
drift. A service tier change is service tier drift. An authority change is
|
|
442
|
-
authority drift. A deadline change is deadline drift. A concurrency change is
|
|
443
|
-
concurrency drift. A lane cap change is lane cap drift. A relevant catalog
|
|
444
|
-
change is catalog drift. The same fail-closed rule covers reasoning mode,
|
|
445
|
-
selector granularity, retry limit, writable roots, context controls, fallback,
|
|
446
|
-
wave topology, scope, lane identity, payload digest, floor, or pinned-target
|
|
447
|
-
drift. Never adjust one of these controls to make execution fit the current
|
|
448
|
-
surface.
|
|
449
|
-
|
|
450
|
-
Launch acceptance remains terminal for replacement eligibility. After a
|
|
451
|
-
prepared launch is accepted, no alternate route, replacement, or target
|
|
452
|
-
substitution is allowed. Only continuation through the already accepted handle
|
|
453
|
-
is permitted. A linked fresh same-target launch is forbidden, regardless of
|
|
454
|
-
the generic caller lifecycle recovery exception. If that accepted handle is
|
|
455
|
-
lost or cannot resume, record the terminal outcome and stop; the approval-bound
|
|
456
|
-
record never authorizes a second child.
|
|
457
|
-
|
|
458
|
-
### One-Step Backwards Compatibility
|
|
459
|
-
|
|
460
|
-
Existing callers may omit `operation` or provide `operation: dispatch`. This
|
|
461
|
-
retains exactly the current one-step selection-and-launch flow in
|
|
462
|
-
Full-Information Selection: observe, select, record, and launch once in the
|
|
463
|
-
same operation. Do not require those callers to invent a prepared record,
|
|
464
|
-
approval timestamp, or approval fingerprint. New approval-bound callers must
|
|
465
|
-
use `prepare` and `execute`; they may not collapse that path into `dispatch`.
|
|
466
|
-
|
|
467
373
|
## Full-Information Selection
|
|
468
374
|
|
|
469
|
-
For every
|
|
470
|
-
`operation: prepare`:
|
|
375
|
+
For every dispatch:
|
|
471
376
|
|
|
472
377
|
1. Validate the caller request and capability state.
|
|
473
378
|
2. Resolve provider, context, role class, optional task class and model-class
|
|
@@ -482,14 +387,8 @@ For every legacy one-step dispatch and for the selection portion of
|
|
|
482
387
|
7. Record route, selection source, selection reason, candidates, catalog
|
|
483
388
|
source, model, effort, reasoning mode, service tier, guidance version,
|
|
484
389
|
authority, and deadline.
|
|
485
|
-
8.
|
|
486
|
-
|
|
487
|
-
9. For a legacy one-step dispatch only, launch once.
|
|
488
|
-
10. Record launch acceptance separately from child outcome and runtime identity.
|
|
489
|
-
|
|
490
|
-
The following diagram is the legacy one-step flow. Approval-bound preparation
|
|
491
|
-
stops after selection and record construction; its later `execute` operation
|
|
492
|
-
performs the separately approved launch.
|
|
390
|
+
8. Launch once.
|
|
391
|
+
9. Record launch acceptance separately from child outcome and runtime identity.
|
|
493
392
|
|
|
494
393
|
```mermaid
|
|
495
394
|
flowchart TD
|
|
@@ -69,232 +69,6 @@ retain the original role-based selection and fallback behavior. The legacy
|
|
|
69
69
|
`explicit-downgrade` example above is valid only for an unconstrained request
|
|
70
70
|
without task-class metadata or a declared class floor.
|
|
71
71
|
|
|
72
|
-
## Approval-Bound Prepared Record
|
|
73
|
-
|
|
74
|
-
Approval-bound records use `prepared_record_version: 1`. They extend the
|
|
75
|
-
complete Record below: every baseline request, selection, route, payload,
|
|
76
|
-
fallback, diagnostic, and invocation-evidence field remains required when it
|
|
77
|
-
applies. Preparation fills all launch controls but performs no launch.
|
|
78
|
-
|
|
79
|
-
```yaml
|
|
80
|
-
prepared_record_version: 1
|
|
81
|
-
operation: prepare
|
|
82
|
-
dispatch_state: prepared
|
|
83
|
-
approval_projection: <exact Canonical Approval Projection v1 object below>
|
|
84
|
-
approval_canonical_json: <RFC-8785-JSON-text>
|
|
85
|
-
approval_fingerprint: sha256:<64-lowercase-hex>
|
|
86
|
-
approved_at: null
|
|
87
|
-
approval_evidence: null
|
|
88
|
-
launch_acceptance: null
|
|
89
|
-
terminal_outcome: null
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
### Canonical Approval Projection v1
|
|
93
|
-
|
|
94
|
-
`approval_projection` is exactly the object shape below. Its object keys and
|
|
95
|
-
nested structure are immutable for `prepared_record_version: 1`; missing or
|
|
96
|
-
extra keys are invalid. The complete ordered `execution.waves` array and every
|
|
97
|
-
ordered wave-local `lanes` array are values in the projection, not paths to be
|
|
98
|
-
looked up elsewhere. Any future field or aggregation change requires a new
|
|
99
|
-
prepared-record version. Scalar values and example array lengths below are
|
|
100
|
-
illustrative; field names, nesting, value types, and each wave and lane element
|
|
101
|
-
shape are normative. Wave and lane arrays may vary in length only within their
|
|
102
|
-
approved caps.
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"schema": "oat-dispatch-approval/v1",
|
|
107
|
-
"prepared_record_version": 1,
|
|
108
|
-
"run_id": "recon-run-2026-07-12-001",
|
|
109
|
-
"prepared_at": "2026-07-12T00:00:00Z",
|
|
110
|
-
"request": {
|
|
111
|
-
"request_id": "dispatch-recon-001",
|
|
112
|
-
"caller": "recon",
|
|
113
|
-
"objective": "Gather bounded evidence",
|
|
114
|
-
"action": "analysis",
|
|
115
|
-
"expected_output": "versioned-dossiers",
|
|
116
|
-
"verification_evidence": "artifact-digests",
|
|
117
|
-
"escalate_when": ["approved scope is insufficient"]
|
|
118
|
-
},
|
|
119
|
-
"selection": {
|
|
120
|
-
"provider": "codex",
|
|
121
|
-
"dispatch_context": "nested-native",
|
|
122
|
-
"dispatch_policy": "economy",
|
|
123
|
-
"dispatch_ceiling": "high",
|
|
124
|
-
"selected_route": "native",
|
|
125
|
-
"selection_source": "native-default",
|
|
126
|
-
"candidates_considered": ["exact-provider-model"],
|
|
127
|
-
"selection_reason": "native-catalog",
|
|
128
|
-
"role_name": "recon-worker",
|
|
129
|
-
"role_class": "recon",
|
|
130
|
-
"role_selector": "recon-worker",
|
|
131
|
-
"model_selector": "exact-provider-model",
|
|
132
|
-
"model_selector_granularity": "exact-native-model-choice",
|
|
133
|
-
"effort_selector": "high",
|
|
134
|
-
"reasoning_mode_selector": null,
|
|
135
|
-
"service_tier_selector": "standard",
|
|
136
|
-
"guidance_reference": "subagent-orchestration/references/provider-codex.md",
|
|
137
|
-
"guidance_version": "2026-07-21",
|
|
138
|
-
"guidance_verified_at": "2026-07-21",
|
|
139
|
-
"guidance_status": "fresh"
|
|
140
|
-
},
|
|
141
|
-
"execution": {
|
|
142
|
-
"waves": [
|
|
143
|
-
{
|
|
144
|
-
"wave_id": "gathering",
|
|
145
|
-
"conditional": false,
|
|
146
|
-
"task_class": "intelligent-recon",
|
|
147
|
-
"model_class_floor": "intelligent-recon",
|
|
148
|
-
"scope": "repo:packages/cli",
|
|
149
|
-
"lanes": [
|
|
150
|
-
{
|
|
151
|
-
"lane_id": "commands",
|
|
152
|
-
"scope": "packages/cli/src/commands"
|
|
153
|
-
},
|
|
154
|
-
{
|
|
155
|
-
"lane_id": "engine",
|
|
156
|
-
"scope": "packages/cli/src/engine"
|
|
157
|
-
}
|
|
158
|
-
],
|
|
159
|
-
"authority": "read-only",
|
|
160
|
-
"authorization_scope": "this-recon-run",
|
|
161
|
-
"writable_roots": ["packet/raw/dossiers/gathering"],
|
|
162
|
-
"deadline_seconds": 300,
|
|
163
|
-
"retry_limit": 1,
|
|
164
|
-
"fallback": { "mode": "block" },
|
|
165
|
-
"dispatch_mode": "background",
|
|
166
|
-
"context_fork_controls": { "fork_turns": "all" },
|
|
167
|
-
"concurrency": 2,
|
|
168
|
-
"lane_cap": 4,
|
|
169
|
-
"payload_digest": "sha256:0000000000000000000000000000000000000000000000000000000000000000"
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
"wave_id": "contradiction-resolution",
|
|
173
|
-
"conditional": true,
|
|
174
|
-
"task_class": "hard-reasoning",
|
|
175
|
-
"model_class_floor": "hard-reasoning",
|
|
176
|
-
"scope": "packet:claims",
|
|
177
|
-
"lanes": [
|
|
178
|
-
{
|
|
179
|
-
"lane_id": "reconcile",
|
|
180
|
-
"scope": "packet/reviews"
|
|
181
|
-
}
|
|
182
|
-
],
|
|
183
|
-
"authority": "read-only",
|
|
184
|
-
"authorization_scope": "this-recon-run",
|
|
185
|
-
"writable_roots": ["packet/reviews/reconciliation"],
|
|
186
|
-
"deadline_seconds": 300,
|
|
187
|
-
"retry_limit": 0,
|
|
188
|
-
"fallback": { "mode": "block" },
|
|
189
|
-
"dispatch_mode": "background",
|
|
190
|
-
"context_fork_controls": { "fork_turns": "all" },
|
|
191
|
-
"concurrency": 1,
|
|
192
|
-
"lane_cap": 1,
|
|
193
|
-
"payload_digest": "sha256:1111111111111111111111111111111111111111111111111111111111111111"
|
|
194
|
-
}
|
|
195
|
-
],
|
|
196
|
-
"run_maximum_floor": "hard-reasoning",
|
|
197
|
-
"pinned_target": {
|
|
198
|
-
"provider": "codex",
|
|
199
|
-
"dispatch_context": "nested-native",
|
|
200
|
-
"selected_route": "native",
|
|
201
|
-
"role_selector": "recon-worker",
|
|
202
|
-
"model_selector": "exact-provider-model",
|
|
203
|
-
"model_selector_granularity": "exact-native-model-choice",
|
|
204
|
-
"effort_selector": "high",
|
|
205
|
-
"reasoning_mode_selector": null,
|
|
206
|
-
"service_tier_selector": "standard"
|
|
207
|
-
}
|
|
208
|
-
},
|
|
209
|
-
"catalog_observation": {
|
|
210
|
-
"id": "nested-native-2026-07-12-001",
|
|
211
|
-
"source": "tool-schema",
|
|
212
|
-
"dispatch_context": "nested-native",
|
|
213
|
-
"observed_at": "2026-07-12T00:00:00Z",
|
|
214
|
-
"relevant_catalog_fingerprint": "sha256:2222222222222222222222222222222222222222222222222222222222222222"
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
The values in the complete Record and launch payload must exactly match their
|
|
220
|
-
counterparts in `approval_projection`; a mismatch is invalid rather than an
|
|
221
|
-
implicit override. `execution.waves` lists every planned and conditional wave
|
|
222
|
-
before selection. Each wave records its caller-classified task class, equal
|
|
223
|
-
model-class floor, conditionality, ordered lane identities and scopes, and all
|
|
224
|
-
wave-local execution controls. Compute `run_maximum_floor` using this increasing
|
|
225
|
-
order: `mechanical-recon`, `intelligent-recon`, `default-implementation`,
|
|
226
|
-
`hard-reasoning`, `consequential`. `pinned_target` is one exact target shared by
|
|
227
|
-
every prepared wave and must satisfy the maximum; per-wave selection or floor
|
|
228
|
-
weakening is invalid.
|
|
229
|
-
|
|
230
|
-
Absent optional values in the projection are JSON `null`. Preserve caller order
|
|
231
|
-
for waves and lanes; for sets such as writable roots, require the caller to
|
|
232
|
-
provide a stable sorted array. Do not normalize opaque provider values.
|
|
233
|
-
Canonicalize the whole `approval_projection` as canonical JSON using RFC 8785,
|
|
234
|
-
encode that text as UTF-8, hash it with SHA-256, format lowercase hexadecimal,
|
|
235
|
-
and prefix the value with `sha256:`. `payload_digest` is the same construction
|
|
236
|
-
over that wave's complete redacted launch payload. The approval timestamp is
|
|
237
|
-
`approved_at`; `prepared_at` records when selection evidence was fixed.
|
|
238
|
-
|
|
239
|
-
`catalog_observation` identifies the original source, dispatch context, and
|
|
240
|
-
observation time. Its `relevant_catalog_fingerprint` covers the approved
|
|
241
|
-
target's selectability plus the role, model, effort, reasoning-mode, service-
|
|
242
|
-
tier, route, and launcher controls used to qualify it. Execution preserves the
|
|
243
|
-
original observation and separately records its fresh recheck. A new unrelated
|
|
244
|
-
candidate is not drift, but removal, renaming, changed semantics, or loss of
|
|
245
|
-
selectability for an approved control is relevant catalog drift and makes the
|
|
246
|
-
record stale.
|
|
247
|
-
|
|
248
|
-
### Legal State Transitions
|
|
249
|
-
|
|
250
|
-
- `prepared -> approved`: the caller explicitly approves the exact
|
|
251
|
-
`approval_fingerprint`; set `approved_at` and immutable approval evidence.
|
|
252
|
-
- `prepared -> not-accepted`: the caller declines or cancels before approval.
|
|
253
|
-
- `prepared -> stale`: a bound axis or relevant catalog fact changes before
|
|
254
|
-
approval is recorded.
|
|
255
|
-
- `approved -> accepted`: `operation: execute` verifies the unchanged
|
|
256
|
-
fingerprint and current relevant catalog, invokes the exact payload once,
|
|
257
|
-
and receives positive launcher acceptance.
|
|
258
|
-
- `approved -> not-accepted`: the exact launch is rejected before child start.
|
|
259
|
-
- `approved -> stale`: fingerprint validation, an approval-bound axis, or the
|
|
260
|
-
relevant catalog comparison differs before launch.
|
|
261
|
-
- `accepted -> completed`: record exactly one terminal child outcome, including
|
|
262
|
-
success, failure, timeout, interruption, `BLOCKED`, or contract refusal.
|
|
263
|
-
|
|
264
|
-
`completed`, `not-accepted`, and `stale` are terminal record states. There is
|
|
265
|
-
no transition from them back to `approved` or `accepted`; prepare a new record
|
|
266
|
-
and obtain a new approval. `accepted` is terminal for replacement eligibility
|
|
267
|
-
even before the child outcome changes the record to `completed`. An accepted
|
|
268
|
-
record must not become `not-accepted` or `stale`, and must never authorize a
|
|
269
|
-
replacement, alternate route, model substitution, provider substitution, or
|
|
270
|
-
second child. Only continuation through the already accepted handle is
|
|
271
|
-
permitted. A linked fresh same-target launch is forbidden, regardless of the
|
|
272
|
-
generic lifecycle recovery exception. Handle loss or inability to resume is a
|
|
273
|
-
terminal stop for this approval-bound record; generic recovery remains
|
|
274
|
-
unchanged for non-approval-bound dispatches.
|
|
275
|
-
|
|
276
|
-
### Execute Validation and Drift
|
|
277
|
-
|
|
278
|
-
`operation: execute` accepts only `dispatch_state: approved`. First recompute
|
|
279
|
-
the approval fingerprint from the stored projection to detect mutation. Then
|
|
280
|
-
re-observe the same live catalog and resolve the actual launch controls without
|
|
281
|
-
selecting alternatives. A changed model, effort, provider, route, role,
|
|
282
|
-
service tier, authority, deadline, retry limit, concurrency, lane cap,
|
|
283
|
-
reasoning mode, selector granularity, writable root, context control, fallback,
|
|
284
|
-
wave topology, scope, lane identity, payload digest, floor, pinned target, or
|
|
285
|
-
relevant catalog fact changes the record to `stale`. Refuse the launch and
|
|
286
|
-
return for reapproval through a newly prepared record.
|
|
287
|
-
|
|
288
|
-
### Legacy One-Step Compatibility
|
|
289
|
-
|
|
290
|
-
Legacy callers that omit `operation`, or set `operation: dispatch`, retain the
|
|
291
|
-
existing one-step selection-and-launch flow: selection and launch occur in the
|
|
292
|
-
same operation and produce the existing Legacy Record or Record shapes. A
|
|
293
|
-
legacy caller must not fabricate an `approval_fingerprint`, approval evidence,
|
|
294
|
-
or a prepared record merely to remain compatible. `prepared_record_version`
|
|
295
|
-
is required only for the approval-bound path; version `1` is the only supported
|
|
296
|
-
prepared-record version, and unknown versions fail closed before launch.
|
|
297
|
-
|
|
298
72
|
## Legacy Record
|
|
299
73
|
|
|
300
74
|
This baseline Record remains valid without optional model-guidance evidence:
|