@open-agent-toolkit/cli 0.3.0 → 0.3.2
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/agents/oat-reviewer.md +10 -3
- package/assets/bundle-metadata.json +1 -1
- package/assets/config/dispatch-matrix-recommendation.json +63 -43
- package/assets/docs/cli-utilities/configuration.md +20 -8
- package/assets/docs/cli-utilities/workflow-gates.md +1 -1
- package/assets/docs/contributing/index.md +1 -0
- package/assets/docs/contributing/updating-model-guidance.md +106 -0
- package/assets/docs/contributing/verifying-cursor-pins.md +30 -18
- package/assets/docs/provider-sync/providers.md +5 -2
- package/assets/docs/reference/cli-reference.md +1 -1
- package/assets/docs/reference/oat-directory-structure.md +1 -1
- package/assets/docs/workflows/projects/artifacts.md +1 -1
- package/assets/docs/workflows/projects/dispatch-ceiling.md +67 -50
- package/assets/docs/workflows/projects/evidence-layers.md +6 -2
- package/assets/docs/workflows/projects/implementation-execution.md +9 -4
- package/assets/docs/workflows/projects/lifecycle.md +8 -6
- package/assets/docs/workflows/projects/programmatic-execution.md +4 -3
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-dispatch-subagents/SKILL.md +1 -1
- package/assets/skills/oat-dispatch-subagents/references/provider-claude.md +20 -7
- package/assets/skills/oat-project-autonomous/references/gate-inventory.md +4 -4
- package/assets/skills/oat-project-document/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-implement/SKILL.md +1 -1
- package/assets/skills/oat-project-implement/references/completion-and-closeout.md +2 -0
- package/assets/skills/oat-project-implement/references/dispatch-and-dry-run.md +82 -25
- package/assets/skills/oat-project-implement/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-implement/references/phase-execution.md +16 -8
- package/assets/skills/oat-project-import-plan/SKILL.md +7 -4
- package/assets/skills/oat-project-lite/SKILL.md +5 -3
- package/assets/skills/oat-project-lite/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-plan/SKILL.md +7 -4
- package/assets/skills/oat-project-plan-writing/SKILL.md +28 -16
- package/assets/skills/oat-project-pr-final/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-quick-start/SKILL.md +7 -4
- package/assets/skills/oat-project-quick-start/references/docs/autonomy-contract.md +4 -4
- package/assets/skills/oat-project-review-provide/SKILL.md +7 -4
- package/assets/skills/subagent-orchestration/SKILL.md +1 -1
- package/assets/skills/subagent-orchestration/references/evidence-and-refresh.md +30 -29
- package/assets/skills/subagent-orchestration/references/provider-claude.md +41 -36
- package/assets/skills/subagent-orchestration/references/provider-codex.md +30 -35
- package/assets/skills/subagent-orchestration/references/provider-cursor.md +46 -38
- package/assets/templates/plan.md +5 -5
- package/dist/commands/gate/review-verdict.d.ts.map +1 -1
- package/dist/commands/gate/review-verdict.js +23 -1
- package/dist/commands/project/dispatch/record.d.ts.map +1 -1
- package/dist/commands/project/dispatch/record.js +27 -5
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +112 -35
- package/dist/config/dispatch-matrix.d.ts.map +1 -1
- package/dist/config/dispatch-matrix.js +13 -0
- package/dist/providers/ceiling/registry.d.ts +7 -2
- package/dist/providers/ceiling/registry.d.ts.map +1 -1
- package/dist/providers/ceiling/registry.js +35 -11
- package/dist/providers/claude/codec/materialize.d.ts +33 -0
- package/dist/providers/claude/codec/materialize.d.ts.map +1 -0
- package/dist/providers/claude/codec/materialize.js +149 -0
- package/dist/providers/claude/codec/sync-extension.d.ts +24 -0
- package/dist/providers/claude/codec/sync-extension.d.ts.map +1 -0
- package/dist/providers/claude/codec/sync-extension.js +312 -0
- package/dist/providers/claude/dispatch-envelope.d.ts +34 -0
- package/dist/providers/claude/dispatch-envelope.d.ts.map +1 -0
- package/dist/providers/claude/dispatch-envelope.js +233 -0
- package/dist/providers/claude/targets.d.ts +48 -0
- package/dist/providers/claude/targets.d.ts.map +1 -0
- package/dist/providers/claude/targets.js +228 -0
- package/dist/providers/codex/codec/shared.d.ts +6 -0
- package/dist/providers/codex/codec/shared.d.ts.map +1 -1
- package/dist/providers/codex/codec/shared.js +8 -0
- package/dist/providers/cursor/codec/catalog.d.ts.map +1 -1
- package/dist/providers/cursor/codec/catalog.js +47 -45
- package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts +35 -0
- package/dist/providers/identity/claude-runtime-observation.fixtures.d.ts.map +1 -1
- package/dist/providers/identity/claude-runtime-observation.fixtures.js +225 -12
- package/dist/providers/shared/registry.d.ts.map +1 -1
- package/dist/providers/shared/registry.js +5 -2
- package/package.json +2 -2
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
guidance_version: 2026-
|
|
3
|
-
last_verified: 2026-
|
|
4
|
-
review_after: 2026-
|
|
2
|
+
guidance_version: 2026-09-23
|
|
3
|
+
last_verified: 2026-09-23
|
|
4
|
+
review_after: 2026-12-22
|
|
5
5
|
catalog_basis:
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
subagentStart lifecycle hooks
|
|
6
|
+
Cursor desktop 3.20.14 resolved all five Opus 5.5 effort selectors in native
|
|
7
|
+
subagent hooks; GPT-6 Sol/Luna were absent from the observed Cursor catalog
|
|
9
8
|
---
|
|
10
9
|
|
|
11
10
|
# Cursor Model Selection
|
|
@@ -45,25 +44,40 @@ does not by itself prove lower user-observed elapsed time.
|
|
|
45
44
|
|
|
46
45
|
## Dated Task-Class Matrix
|
|
47
46
|
|
|
48
|
-
Use exact aliases from the
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
47
|
+
Use currently approved exact aliases from the Cursor catalogue. On 2026-09-23,
|
|
48
|
+
Cursor desktop 3.20.14 resolved all five `claude-opus-5-5[effort=...]`
|
|
49
|
+
selectors to corresponding flat IDs in native hooks. See the
|
|
50
|
+
probe record at `packages/cli/src/providers/cursor/codec/__fixtures__/README.md`.
|
|
51
|
+
GPT-6 Sol/Luna were absent from the observed Cursor catalogue, so their Codex
|
|
52
|
+
availability does not authorize Cursor routes.
|
|
53
|
+
|
|
54
|
+
| Task class | Default | Economy | Escalation | Floor notes |
|
|
55
|
+
| ------------------------ | ------------------------------------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `mechanical-recon` | `composer-2.5` | Same with mechanical verification | `gpt-5.6-luna-high` | Fast aliases select service tier, not capability. |
|
|
57
|
+
| `intelligent-recon` | `cursor-grok-4.5-medium` or `gpt-5.6-sol-medium` | `gpt-5.6-terra-high` | `gpt-5.6-sol-high` | Verify silent-miss-prone conclusions. |
|
|
58
|
+
| `default-implementation` | `gpt-5.6-sol-medium` | `composer-2.5` for bounded, testable changes | `gpt-5.6-sol-high` | `cursor-grok-4.5-medium` remains an available judgment-heavy alternative. |
|
|
59
|
+
| `hard-reasoning` | `gpt-5.6-sol-high` | `cursor-grok-4.5-high` with corroborating evidence | `gpt-5.6-sol-xhigh` | Opus 5.5 high/xhigh are verified cross-family alternatives; qualify task performance separately. |
|
|
60
|
+
| `consequential` | An eligible high-effort author with independent cross-family review | No routine economy route | Sol xhigh for a depth bottleneck; max only after evaluation | If independent review cannot be met among approved Cursor mappings, use a separately qualified provider or stop. |
|
|
61
|
+
|
|
62
|
+
## Current Opus 5.5 Pin Evidence
|
|
63
|
+
|
|
64
|
+
Cursor desktop 3.20.14 resolved `claude-opus-5-5[effort=low|medium|high|xhigh|max]`
|
|
65
|
+
to `claude-opus-5-5-low|medium|high|xhigh|max`, respectively, on 2026-09-23.
|
|
66
|
+
Both the `subagentStart.subagent_model` and the subagent Shell `preToolUse.model`
|
|
67
|
+
agreed for every rung. The Sonnet 5 high positive control resolved to
|
|
68
|
+
`claude-sonnet-5-thinking-high`. An unknown family fell back to
|
|
69
|
+
`cursor-grok-4.6-high-fast`; an unknown effort on Opus 5.5 fell back to
|
|
70
|
+
`claude-opus-5-5-medium`. The provenance summary at `packages/cli/src/providers/cursor/codec/__fixtures__/README.md`
|
|
71
|
+
links the adjacent redacted summary and native-event JSONL records containing
|
|
72
|
+
the exact observations. Recheck live availability before launch.
|
|
73
|
+
|
|
74
|
+
## Historical Opus Cursor Probe Evidence (Retired)
|
|
75
|
+
|
|
76
|
+
The following observations document Cursor 3.12.30 behavior on 2026-07-25.
|
|
77
|
+
They no longer qualify those generations for current recommendations or the
|
|
78
|
+
active approved mapping catalogue. A new family needs its own live probe.
|
|
79
|
+
|
|
80
|
+
Five Opus 5 effort rungs plus an Opus 4.8 rung were
|
|
67
81
|
probe-verified on 2026-07-25 against Cursor 3.12.30, using `subagentStart`
|
|
68
82
|
lifecycle hooks to read the resolved model that Cursor itself reports:
|
|
69
83
|
|
|
@@ -80,21 +94,15 @@ Every rung resolves to the thinking variant. This is a verified fact, not an
|
|
|
80
94
|
inference: the catalog carries distinct non-thinking IDs at low, medium, and
|
|
81
95
|
high, and none were selected.
|
|
82
96
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
route; Opus is generally stronger for interpretation-heavy work. Exact
|
|
89
|
-
cross-provider substitutions remain provisional.
|
|
90
|
-
|
|
91
|
-
Opus 4.8 xhigh is catalogued so the cyber-sensitive route is dispatchable, but it
|
|
92
|
-
is deliberately excluded from the bundled recommendation. Select it explicitly
|
|
93
|
-
when the cyber-sensitive refusal profile is required.
|
|
97
|
+
That historical result did not validate an Opus 5.5 selector; the 2026-09-23
|
|
98
|
+
probe above independently qualifies its five selectors. Even where the
|
|
99
|
+
requested effort has the same spelling across generations, preserve the old
|
|
100
|
+
probe only as evidence of past behavior and use the current approved catalogue
|
|
101
|
+
for dispatch.
|
|
94
102
|
|
|
95
103
|
### Unresolvable selectors fall back to a default, silently
|
|
96
104
|
|
|
97
|
-
|
|
105
|
+
The historical probe showed that Cursor did not reject a malformed pin. It substitutes a
|
|
98
106
|
default for whichever component it cannot resolve, with no error or warning:
|
|
99
107
|
|
|
100
108
|
- An unknown family falls back to the default model. `claude-opus-9[effort=high]`
|
|
@@ -102,7 +110,7 @@ default for whichever component it cannot resolve, with no error or warning:
|
|
|
102
110
|
- An unknown effort falls back to the family's default rung.
|
|
103
111
|
`claude-opus-5[effort=ultra]` resolved to `claude-opus-5-thinking-high`.
|
|
104
112
|
|
|
105
|
-
The default rung is family-specific, not a fixed value. In
|
|
113
|
+
The default rung is family-specific, not a fixed value. In that catalog snapshot
|
|
106
114
|
exactly one rung per family carries an unqualified display label, and that marks
|
|
107
115
|
the default: `claude-opus-5-high` shows as `Opus 5 1M` while
|
|
108
116
|
`claude-opus-5-medium` shows as `Opus 5 1M Medium`. The default is not always
|
package/assets/templates/plan.md
CHANGED
|
@@ -55,13 +55,13 @@ Default is `[]` (fully sequential, no worktrees). Only declare parallelism when
|
|
|
55
55
|
|
|
56
56
|
_Optional override surface. Use only for explicit user-authored constraints or preferences. Omit this section when runtime selection should choose the lowest confident tier._
|
|
57
57
|
|
|
58
|
-
Blank or `auto` means there is no explicit constraint
|
|
58
|
+
Blank or `auto` means there is no explicit phase constraint. Do not generate rows by default; a missing phase row uses runtime selection.
|
|
59
59
|
|
|
60
|
-
| Phase |
|
|
61
|
-
| ----- |
|
|
62
|
-
| pNN |
|
|
60
|
+
| Phase | Named ceiling | Rationale |
|
|
61
|
+
| ----- | --------------------------------------- | ----------------------------- |
|
|
62
|
+
| pNN | economy\|balanced\|high\|frontier\|auto | why this constraint is needed |
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
The named ceiling is a maximum candidate tier, not an exact provider, model family, or effort preference. `oat-project-implement` chooses one exact phase-implementer target from the complete configured ladder at runtime.
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-verdict.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/review-verdict.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,4BAA4B,CAAC;IAC9C,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE;QACd,kBAAkB,EAAE,QAAQ,EAAE,CAAC;QAC/B,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAEzD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,6BAA6B;IAC5C,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;CAC/C;
|
|
1
|
+
{"version":3,"file":"review-verdict.d.ts","sourceRoot":"","sources":["../../../src/commands/gate/review-verdict.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAAC;IAC5C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,4BAA4B,CAAC;IAC9C,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,QAAQ,EAAE,OAAO,CAAC;IAClB,aAAa,CAAC,EAAE;QACd,kBAAkB,EAAE,QAAQ,EAAE,CAAC;QAC/B,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;AAEzD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,6BAA6B;IAC5C,qCAAqC,CAAC,EAAE,OAAO,CAAC;IAChD,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;CAC/C;AA8OD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAE9D;AA4fD,wBAAsB,sBAAsB,CAC1C,YAAY,EAAE,MAAM,EACpB,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,iBAAiB,CAAC,CA8F5B"}
|
|
@@ -129,6 +129,17 @@ function sectionContentIsEmpty(content) {
|
|
|
129
129
|
.trim();
|
|
130
130
|
return cleaned.length === 0 || /^none\.?$/i.test(cleaned);
|
|
131
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Count the findings a severity section declares.
|
|
134
|
+
*
|
|
135
|
+
* Only top-level markdown list items count. Prose shapes are deliberately not
|
|
136
|
+
* counted — a bold lead-in paragraph, a wrapped continuation line, and a nested
|
|
137
|
+
* detail bullet are indistinguishable from a finding title without parsing the
|
|
138
|
+
* prose, so counting them would miscount and double-count. The cost of that
|
|
139
|
+
* choice is that a reviewer who writes findings as paragraphs gets a zero
|
|
140
|
+
* tally, so every diagnostic built on this count must name the list-item
|
|
141
|
+
* requirement (see `FINDING_LIST_ITEM_CONTRACT_HINT`).
|
|
142
|
+
*/
|
|
132
143
|
function countFindingsInSection(content) {
|
|
133
144
|
if (sectionContentIsEmpty(content)) {
|
|
134
145
|
return 0;
|
|
@@ -409,6 +420,15 @@ async function normalizeMissingEmptySeveritySections(artifactPath, content, coun
|
|
|
409
420
|
persisted: insertedSeverities.length > 0 && persist,
|
|
410
421
|
};
|
|
411
422
|
}
|
|
423
|
+
/**
|
|
424
|
+
* The one fact a reviewer cannot recover from the raw contradiction report.
|
|
425
|
+
*
|
|
426
|
+
* A section whose findings are written as bold paragraphs tallies zero, so the
|
|
427
|
+
* gate reports a contradiction that looks like a counting mistake. Without this
|
|
428
|
+
* sentence the reviewer has no way to learn that the shape of the finding, not
|
|
429
|
+
* the arithmetic, is what the parser objected to.
|
|
430
|
+
*/
|
|
431
|
+
const FINDING_LIST_ITEM_CONTRACT_HINT = 'Only markdown list items count as findings in a Findings section: a line starting with `- `, `* `, `+ `, or `1. `. A finding written as a bold paragraph, a heading, or any other prose shape counts as zero, which is the usual reason a section tallies lower than the declared counts. Rewrite each finding as a list item, or correct the declared counts to match.';
|
|
412
432
|
function formatCounts(counts) {
|
|
413
433
|
return SEVERITIES.map((severity) => `${counts[severity]} ${severity}`).join(', ');
|
|
414
434
|
}
|
|
@@ -424,7 +444,8 @@ function assertAgreeingCounts(artifactPath, left, right, tiers = SEVERITIES) {
|
|
|
424
444
|
if (differing.length === 0) {
|
|
425
445
|
return;
|
|
426
446
|
}
|
|
427
|
-
|
|
447
|
+
const sectionsInvolved = left.fromSections === true || right.fromSections === true;
|
|
448
|
+
throw new Error(`Review artifact at ${artifactPath} contradicts itself about finding counts (${differing.join(', ')}): declared counts are ${formatCounts(left.counts)} (${left.name}) but ${formatCounts(right.counts)} (${right.name}). Reconcile them before the gate can evaluate the review.${sectionsInvolved ? ` ${FINDING_LIST_ITEM_CONTRACT_HINT}` : ''}`);
|
|
428
449
|
}
|
|
429
450
|
/**
|
|
430
451
|
* Resolve the artifact's counts, cross-checking every source that is present.
|
|
@@ -467,6 +488,7 @@ function resolveCounts(content, frontmatter, artifactPath) {
|
|
|
467
488
|
name: 'the Findings sections',
|
|
468
489
|
counts: bodyCounts,
|
|
469
490
|
tiers: bodyTiers,
|
|
491
|
+
fromSections: true,
|
|
470
492
|
};
|
|
471
493
|
for (const source of explicitSources) {
|
|
472
494
|
const comparableTiers = source.tiers.filter((severity) => bodyTiers.includes(severity));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/record.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch/record.ts"],"names":[],"mappings":"AAkBA,OAAO,EAKL,KAAK,qBAAqB,EAC3B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAOL,KAAK,wBAAwB,EAE7B,KAAK,4BAA4B,EAElC,MAAM,yCAAyC,CAAC;AAWjD;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACzC,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAoCD;;;;;;;;;GASG;AAEH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,KAAK,GAAE;IACL,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjB,GACL,MAAM,CAcR;AAaD,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,qBAAqB,CAAC;IAC9B,KAAK,EAAE,wBAAwB,CAAC;IAChC,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;GAKG;AACH,MAAM,WAAW,6BAA6B;IAC5C,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,CAAC;IACF,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;KAC5B,GAAG,IAAI,CAAC;IACT,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC5D;;;OAGG;IACH,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC;;;;OAIG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,UAAU,GAAG,cAAc,CAAC;CACrC;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,WAAW,GAAG,gBAAgB,CAAC;IACvC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,4BAA4B,CAAC;IACrC,eAAe,EAAE,6BAA6B,CAAC;CAChD,CAAC;AAsEF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CA0G5E;AAgKD;;;;;;GAMG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE;IACjD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,OAAO,CAAC;IACf,YAAY,CAAC,EAAE,0BAA0B,CAAC;CAC3C,GAAG,OAAO,CAAC,2BAA2B,CAAC,CA6HvC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFile, readdir } from 'node:fs/promises';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { publishContainedJsonRevision, redactedFsError, withContainedWriterLock, } from '../../../fs/io.js';
|
|
4
|
+
import { acceptClaudeLaunchEnvelope, buildClaudeDispatchRecord, } from '../../../providers/claude/dispatch-envelope.js';
|
|
4
5
|
import { assertJournalIdentityHasNoAbsolutePath, redactAbsolutePaths, } from '../../../providers/identity/absolute-paths.js';
|
|
5
6
|
import { CLAUDE_OBSERVATION_SOURCE } from '../../../providers/identity/claude-runtime-observation.js';
|
|
6
7
|
import { CODEX_OBSERVATION_SOURCE } from '../../../providers/identity/codex-runtime-observation.js';
|
|
@@ -127,12 +128,34 @@ export function parseDispatchRecordInput(value) {
|
|
|
127
128
|
throw new Error('Dispatch record input must be a JSON object.');
|
|
128
129
|
}
|
|
129
130
|
const keys = Object.keys(value).sort();
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
const isGenericInput = keys.length === 2 && keys[0] === 'event' && keys[1] === 'record';
|
|
132
|
+
const isManagedClaudeInput = keys.length === 3 &&
|
|
133
|
+
keys[0] === 'claudeLaunch' &&
|
|
134
|
+
keys[1] === 'event' &&
|
|
135
|
+
keys[2] === 'recordBase';
|
|
136
|
+
if (!isGenericInput && !isManagedClaudeInput) {
|
|
137
|
+
throw new Error('Dispatch record input accepts record and event, or claudeLaunch, event, and recordBase.');
|
|
132
138
|
}
|
|
133
139
|
if (!isRecord(value.event)) {
|
|
134
140
|
throw new Error('Dispatch record event must be a JSON object.');
|
|
135
141
|
}
|
|
142
|
+
const record = isManagedClaudeInput
|
|
143
|
+
? buildClaudeDispatchRecord({
|
|
144
|
+
envelope: acceptClaudeLaunchEnvelope({
|
|
145
|
+
resolution: isRecord(value.claudeLaunch)
|
|
146
|
+
? value.claudeLaunch.resolution
|
|
147
|
+
: undefined,
|
|
148
|
+
definition: isRecord(value.claudeLaunch)
|
|
149
|
+
? String(value.claudeLaunch.definition ?? '')
|
|
150
|
+
: '',
|
|
151
|
+
launch: isRecord(value.claudeLaunch)
|
|
152
|
+
? value.claudeLaunch.payload
|
|
153
|
+
: undefined,
|
|
154
|
+
}),
|
|
155
|
+
recordBase: value.recordBase,
|
|
156
|
+
})
|
|
157
|
+
: parseGenericDispatchRecord(value.record);
|
|
158
|
+
const boundedInput = { record, event: value.event };
|
|
136
159
|
// Raw provider metadata is the one input a caller may legitimately supply
|
|
137
160
|
// unmodified, so it is projected through the owning parser's allowlist and
|
|
138
161
|
// asserted as the projection. Everything else is asserted exactly as given.
|
|
@@ -143,15 +166,14 @@ export function parseDispatchRecordInput(value) {
|
|
|
143
166
|
? value.event.metadata
|
|
144
167
|
: null;
|
|
145
168
|
assertNoSensitiveDispatchContent(rawMetadata === null
|
|
146
|
-
?
|
|
169
|
+
? boundedInput
|
|
147
170
|
: {
|
|
148
|
-
...
|
|
171
|
+
...boundedInput,
|
|
149
172
|
event: {
|
|
150
173
|
...value.event,
|
|
151
174
|
metadata: { ...rawMetadata, entries: null },
|
|
152
175
|
},
|
|
153
176
|
});
|
|
154
|
-
const record = parseGenericDispatchRecord(value.record);
|
|
155
177
|
if (rawMetadata !== null) {
|
|
156
178
|
if ('observation' in value.event) {
|
|
157
179
|
throw new Error('A runtime observation event carries either observation or metadata, not both.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAkB9B,OAAO,EAUL,KAAK,uBAAuB,EAY7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/commands/project/dispatch-ceiling/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,cAAc,EACnB,KAAK,aAAa,EACnB,MAAM,sBAAsB,CAAC;AAkB9B,OAAO,EAUL,KAAK,uBAAuB,EAY7B,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,iBAAiB,CAAC;AAoCzB,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAiC5C,UAAU,2BAA2B;IACnC,mBAAmB,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,cAAc,CAAC;IAChE,kBAAkB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACrD,sBAAsB,EAAE,CACtB,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,CAAC,UAAU,KACnB,OAAO,CAAC,cAAc,CAAC,CAAC;IAC7B,oBAAoB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,CAAC,CAAC;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5C,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC;CAC/B;AAm4FD,wBAAgB,mCAAmC,CACjD,SAAS,GAAE,OAAO,CAAC,2BAA2B,CAAM,GACnD,OAAO,CA0GT"}
|
|
@@ -12,7 +12,9 @@ import { getOwnKey, setOwnKey } from '../../../config/own-keys.js';
|
|
|
12
12
|
import { resolveEffectiveConfig, } from '../../../config/resolve.js';
|
|
13
13
|
import { resolveProjectRoot } from '../../../fs/paths.js';
|
|
14
14
|
import TOML from '@iarna/toml';
|
|
15
|
-
import { getCeilingAdapter, isDirectDispatchRoleName,
|
|
15
|
+
import { getCeilingAdapter, isDirectDispatchRoleName, } from '../../../providers/ceiling/registry.js';
|
|
16
|
+
import { claudeTargetRank, CLAUDE_EFFORT_ORDER, validateClaudeDispatchCapability, validateClaudeDispatchTarget, } from '../../../providers/claude/targets.js';
|
|
17
|
+
import { SUPPORTED_CODEX_ROLE_TARGETS } from '../../../providers/codex/codec/shared.js';
|
|
16
18
|
import { buildDispatchReport, formatDispatchReport, } from '../../../providers/identity/dispatch-report.js';
|
|
17
19
|
import { classifyModelFamily, } from '../../../providers/identity/family.js';
|
|
18
20
|
import { formatDispatchStamp, } from '../../../providers/identity/stamp.js';
|
|
@@ -21,6 +23,11 @@ import YAML from 'yaml';
|
|
|
21
23
|
const CODEX_VALUES = [
|
|
22
24
|
...VALID_CODEX_DISPATCH_CEILINGS,
|
|
23
25
|
];
|
|
26
|
+
// Catalogue order is low to high within each model; the scalar ceiling
|
|
27
|
+
// remains separately capped by CODEX_VALUES.
|
|
28
|
+
const CODEX_CANDIDATE_EFFORTS = [
|
|
29
|
+
...new Set(SUPPORTED_CODEX_ROLE_TARGETS.map((target) => target.effort)),
|
|
30
|
+
];
|
|
24
31
|
const CLAUDE_VALUES = [
|
|
25
32
|
...VALID_CLAUDE_DISPATCH_CEILINGS,
|
|
26
33
|
];
|
|
@@ -124,6 +131,9 @@ function validManagedPolicyList() {
|
|
|
124
131
|
return managedDispatchPolicyValueList(', ');
|
|
125
132
|
}
|
|
126
133
|
function validProviderValueList(provider) {
|
|
134
|
+
if (provider === 'codex') {
|
|
135
|
+
return CODEX_VALUES.join(', ');
|
|
136
|
+
}
|
|
127
137
|
return providerValueOrder(provider)?.join(', ') ?? 'none';
|
|
128
138
|
}
|
|
129
139
|
function compiledPolicyValueForProvider(provider, compiled) {
|
|
@@ -259,6 +269,39 @@ function routeTargetFromObject(provider, target, routeIndex, routeLength) {
|
|
|
259
269
|
routeLength,
|
|
260
270
|
};
|
|
261
271
|
}
|
|
272
|
+
function resolveClaudeTargetCapability(target, env) {
|
|
273
|
+
if (!target ||
|
|
274
|
+
target.harness !== 'claude' ||
|
|
275
|
+
!target.model ||
|
|
276
|
+
!target.effort) {
|
|
277
|
+
return target;
|
|
278
|
+
}
|
|
279
|
+
const validation = validateClaudeDispatchCapability({
|
|
280
|
+
model: target.model,
|
|
281
|
+
effort: target.effort,
|
|
282
|
+
...(target.capabilityEvidence
|
|
283
|
+
? { capabilityEvidence: target.capabilityEvidence }
|
|
284
|
+
: {}),
|
|
285
|
+
}, env);
|
|
286
|
+
if (!validation.valid || !validation.capabilityEvidence) {
|
|
287
|
+
throw new Error(validation.reason ??
|
|
288
|
+
'Claude effort target has no established model capability.');
|
|
289
|
+
}
|
|
290
|
+
return { ...target, capabilityEvidence: validation.capabilityEvidence };
|
|
291
|
+
}
|
|
292
|
+
function resolveClaudePolicyCapabilities(policy, env) {
|
|
293
|
+
if (!policy)
|
|
294
|
+
return policy;
|
|
295
|
+
return {
|
|
296
|
+
...policy,
|
|
297
|
+
target: resolveClaudeTargetCapability(policy.target, env) ?? null,
|
|
298
|
+
...(policy.ceilingTarget !== undefined
|
|
299
|
+
? {
|
|
300
|
+
ceilingTarget: resolveClaudeTargetCapability(policy.ceilingTarget, env) ?? null,
|
|
301
|
+
}
|
|
302
|
+
: {}),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
262
305
|
function resolveRouteMatrixCell(provider, route, escalationLevel, cellSource) {
|
|
263
306
|
const routeIndex = Math.min(escalationLevel, route.length - 1);
|
|
264
307
|
const entry = route[routeIndex];
|
|
@@ -319,6 +362,8 @@ function resolveProviderCellFromValue(provider, providerValue, tier, cellSource,
|
|
|
319
362
|
};
|
|
320
363
|
}
|
|
321
364
|
if (isWorkflowDispatchCandidateLadder(cell)) {
|
|
365
|
+
if (provider === 'claude')
|
|
366
|
+
assertCandidateOrder(provider, tier, cell);
|
|
322
367
|
const ceiling = cell.candidates.at(-1);
|
|
323
368
|
if (ceiling === undefined) {
|
|
324
369
|
return null;
|
|
@@ -417,7 +462,7 @@ function candidatePrimaryTarget(provider, tier, candidate) {
|
|
|
417
462
|
if (targetAdapter.selectionAxis === 'model-effort' &&
|
|
418
463
|
(!target.model ||
|
|
419
464
|
!target.effort ||
|
|
420
|
-
!
|
|
465
|
+
!CODEX_CANDIDATE_EFFORTS.includes(target.effort))) {
|
|
421
466
|
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: Codex candidates require a model and supported effort.`);
|
|
422
467
|
}
|
|
423
468
|
if ((targetAdapter.selectionAxis === 'model' ||
|
|
@@ -425,6 +470,15 @@ function candidatePrimaryTarget(provider, tier, candidate) {
|
|
|
425
470
|
!target.model) {
|
|
426
471
|
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: model-argument candidates require a model.`);
|
|
427
472
|
}
|
|
473
|
+
if (target.harness === 'claude' && target.model) {
|
|
474
|
+
const validation = validateClaudeDispatchTarget({
|
|
475
|
+
model: target.model,
|
|
476
|
+
...(target.effort ? { effort: target.effort } : {}),
|
|
477
|
+
});
|
|
478
|
+
if (!validation.valid) {
|
|
479
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: ${validation.reason}`);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
428
482
|
return target;
|
|
429
483
|
}
|
|
430
484
|
function candidateTargetKey(target) {
|
|
@@ -450,17 +504,18 @@ function assertCandidateOrder(provider, tier, ladder) {
|
|
|
450
504
|
}
|
|
451
505
|
seen.add(key);
|
|
452
506
|
if (target.harness === 'claude' && target.model) {
|
|
453
|
-
const
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
507
|
+
const [modelRank, effortRank] = claudeTargetRank({
|
|
508
|
+
model: target.model,
|
|
509
|
+
...(target.effort ? { effort: target.effort } : {}),
|
|
510
|
+
});
|
|
511
|
+
const rank = modelRank * CLAUDE_EFFORT_ORDER.length + effortRank;
|
|
457
512
|
if (previousClaudeRank !== null && rank < previousClaudeRank) {
|
|
458
513
|
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: Claude candidates must be nondecreasing.`);
|
|
459
514
|
}
|
|
460
515
|
previousClaudeRank = rank;
|
|
461
516
|
}
|
|
462
517
|
if (target.harness === 'codex' && target.model && target.effort) {
|
|
463
|
-
const rank =
|
|
518
|
+
const rank = CODEX_CANDIDATE_EFFORTS.indexOf(target.effort);
|
|
464
519
|
const previousRank = codexRanksByModel.get(target.model);
|
|
465
520
|
if (previousRank !== undefined && rank < previousRank) {
|
|
466
521
|
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: Codex efforts for ${target.model} must be nondecreasing.`);
|
|
@@ -478,16 +533,26 @@ function assertTierCeilingsNondecreasing(provider, previous, current, tier) {
|
|
|
478
533
|
if (current.harness === 'claude' &&
|
|
479
534
|
previous.model &&
|
|
480
535
|
current.model &&
|
|
481
|
-
|
|
482
|
-
|
|
536
|
+
(() => {
|
|
537
|
+
const [previousModel, previousEffort] = claudeTargetRank({
|
|
538
|
+
model: previous.model,
|
|
539
|
+
...(previous.effort ? { effort: previous.effort } : {}),
|
|
540
|
+
});
|
|
541
|
+
const [currentModel, currentEffort] = claudeTargetRank({
|
|
542
|
+
model: current.model,
|
|
543
|
+
...(current.effort ? { effort: current.effort } : {}),
|
|
544
|
+
});
|
|
545
|
+
return (currentModel < previousModel ||
|
|
546
|
+
(currentModel === previousModel && currentEffort < previousEffort));
|
|
547
|
+
})()) {
|
|
483
548
|
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: named tier ceilings must be nondecreasing.`);
|
|
484
549
|
}
|
|
485
550
|
if (current.harness === 'codex' &&
|
|
486
551
|
previous.model === current.model &&
|
|
487
552
|
previous.effort &&
|
|
488
553
|
current.effort &&
|
|
489
|
-
|
|
490
|
-
|
|
554
|
+
CODEX_CANDIDATE_EFFORTS.indexOf(current.effort) <
|
|
555
|
+
CODEX_CANDIDATE_EFFORTS.indexOf(previous.effort)) {
|
|
491
556
|
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: named tier ceilings must be nondecreasing.`);
|
|
492
557
|
}
|
|
493
558
|
}
|
|
@@ -495,10 +560,11 @@ function requestedCandidateMatches(provider, requested, target) {
|
|
|
495
560
|
if (target.harness !== provider || target.model !== requested.model) {
|
|
496
561
|
return false;
|
|
497
562
|
}
|
|
498
|
-
return provider !== 'codex'
|
|
563
|
+
return ((provider !== 'codex' && provider !== 'claude') ||
|
|
564
|
+
target.effort === requested.effort);
|
|
499
565
|
}
|
|
500
566
|
function formatRequestedCandidate(provider, requested) {
|
|
501
|
-
return provider === 'codex'
|
|
567
|
+
return provider === 'codex' || requested.effort !== undefined
|
|
502
568
|
? `${requested.model}/${requested.effort}`
|
|
503
569
|
: requested.model;
|
|
504
570
|
}
|
|
@@ -867,7 +933,7 @@ function normalizeRole(value) {
|
|
|
867
933
|
}
|
|
868
934
|
function providerValueOrder(provider) {
|
|
869
935
|
if (provider === 'codex') {
|
|
870
|
-
return
|
|
936
|
+
return CODEX_CANDIDATE_EFFORTS;
|
|
871
937
|
}
|
|
872
938
|
if (provider === 'claude') {
|
|
873
939
|
return CLAUDE_VALUES;
|
|
@@ -887,7 +953,7 @@ function normalizePreferredValue(provider, value) {
|
|
|
887
953
|
return null;
|
|
888
954
|
}
|
|
889
955
|
if (!isValidProviderValue(provider, normalized)) {
|
|
890
|
-
const validValues = order.join(', ');
|
|
956
|
+
const validValues = (provider === 'codex' ? CODEX_VALUES : order).join(', ');
|
|
891
957
|
throw new Error(`Invalid preferred dispatch value "${normalized}" for ${provider}. Valid values: ${validValues}.`);
|
|
892
958
|
}
|
|
893
959
|
return normalized;
|
|
@@ -927,17 +993,23 @@ function normalizeRequestedCandidate(provider, role, options) {
|
|
|
927
993
|
if (!effort) {
|
|
928
994
|
throw new Error('--candidate-effort is required for an exact Codex candidate.');
|
|
929
995
|
}
|
|
930
|
-
if (!
|
|
931
|
-
throw new Error(`Invalid Codex candidate effort "${effort}". Valid values: ${
|
|
996
|
+
if (!CODEX_CANDIDATE_EFFORTS.includes(effort)) {
|
|
997
|
+
throw new Error(`Invalid Codex candidate effort "${effort}". Valid values: ${CODEX_CANDIDATE_EFFORTS.join(', ')}.`);
|
|
932
998
|
}
|
|
933
999
|
return { model, effort };
|
|
934
1000
|
}
|
|
935
|
-
if (
|
|
936
|
-
|
|
1001
|
+
if (provider === 'claude') {
|
|
1002
|
+
const validation = validateClaudeDispatchTarget({
|
|
1003
|
+
model,
|
|
1004
|
+
...(effort ? { effort } : {}),
|
|
1005
|
+
});
|
|
1006
|
+
if (!validation.valid) {
|
|
1007
|
+
throw new Error(validation.reason);
|
|
1008
|
+
}
|
|
1009
|
+
return effort ? { model, effort } : { model };
|
|
937
1010
|
}
|
|
938
|
-
if (
|
|
939
|
-
|
|
940
|
-
throw new Error(`Invalid Claude candidate model "${model}". Valid values: ${CLAUDE_VALUES.join(', ')}.`);
|
|
1011
|
+
if (effort) {
|
|
1012
|
+
throw new Error(`--candidate-effort is only valid for Codex or Claude; ${provider} candidates use --candidate-model only.`);
|
|
941
1013
|
}
|
|
942
1014
|
return { model };
|
|
943
1015
|
}
|
|
@@ -965,12 +1037,12 @@ function normalizeClassification(provider, role, options) {
|
|
|
965
1037
|
throw new Error(`Invalid task class "${taskClassValue}". Valid values: ${TASK_CLASSES.join(', ')}.`);
|
|
966
1038
|
}
|
|
967
1039
|
const taskEffort = options.taskEffort?.trim() ?? '';
|
|
968
|
-
if (hasTaskEffort && provider !== 'codex') {
|
|
969
|
-
throw new Error(`--task-effort is only valid for Codex; received ${provider}.`);
|
|
1040
|
+
if (hasTaskEffort && provider !== 'codex' && provider !== 'claude') {
|
|
1041
|
+
throw new Error(`--task-effort is only valid for Codex or Claude; received ${provider}.`);
|
|
970
1042
|
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
throw new Error(`Invalid Codex task effort "${taskEffort}". Valid values: ${
|
|
1043
|
+
const validTaskEfforts = provider === 'claude' ? CLAUDE_EFFORT_ORDER : CODEX_CANDIDATE_EFFORTS;
|
|
1044
|
+
if (hasTaskEffort && !validTaskEfforts.includes(taskEffort)) {
|
|
1045
|
+
throw new Error(`Invalid ${provider === 'claude' ? 'Claude' : 'Codex'} task effort "${taskEffort}". Valid values: ${validTaskEfforts.join(', ')}.`);
|
|
974
1046
|
}
|
|
975
1047
|
return {
|
|
976
1048
|
taskClass: hasTaskClass ? taskClassValue : null,
|
|
@@ -1153,7 +1225,7 @@ function codexEffortAxis(selection, dispatchArgs) {
|
|
|
1153
1225
|
* the enforcement mode, mechanism, dispatch args, and verify-on-upgrade flag.
|
|
1154
1226
|
* Mode is computed here at call time — it is never read from persisted state.
|
|
1155
1227
|
*/
|
|
1156
|
-
function buildProviderResolution(provider, policy, role, orchestratorTier, preferredValue) {
|
|
1228
|
+
function buildProviderResolution(provider, policy, role, orchestratorTier, preferredValue, env) {
|
|
1157
1229
|
const adapter = getCeilingAdapter(provider);
|
|
1158
1230
|
if (policy === null) {
|
|
1159
1231
|
return {
|
|
@@ -1193,6 +1265,7 @@ function buildProviderResolution(provider, policy, role, orchestratorTier, prefe
|
|
|
1193
1265
|
? adapter.compileToDispatchArgs(dispatchValue, role, {
|
|
1194
1266
|
orchestratorTier,
|
|
1195
1267
|
target: selection.target,
|
|
1268
|
+
env,
|
|
1196
1269
|
})
|
|
1197
1270
|
: null;
|
|
1198
1271
|
let mode;
|
|
@@ -1208,12 +1281,16 @@ function buildProviderResolution(provider, policy, role, orchestratorTier, prefe
|
|
|
1208
1281
|
return {
|
|
1209
1282
|
value: policy.value,
|
|
1210
1283
|
mode,
|
|
1211
|
-
mechanism:
|
|
1284
|
+
mechanism: hasVariantDispatchArgs(dispatchArgs)
|
|
1285
|
+
? 'pinned-variant'
|
|
1286
|
+
: adapter.mechanism,
|
|
1212
1287
|
dispatchArgs,
|
|
1213
1288
|
modelAxis: modelAxis(provider, selection, dispatchArgs),
|
|
1214
1289
|
effortAxis: provider === 'codex'
|
|
1215
1290
|
? codexEffortAxis(selection, dispatchArgs)
|
|
1216
|
-
: '
|
|
1291
|
+
: provider === 'claude' && selection.target?.effort
|
|
1292
|
+
? `selected:${selection.target.effort}`
|
|
1293
|
+
: 'not-applicable',
|
|
1217
1294
|
verifyOnDispatch: dispatchValue && !isCrossHarness
|
|
1218
1295
|
? adapter.verifyOnDispatch(dispatchValue, {
|
|
1219
1296
|
orchestratorTier,
|
|
@@ -1385,11 +1462,11 @@ async function resolveDispatchCeiling(context, dependencies, options) {
|
|
|
1385
1462
|
const escalationLevel = normalizeEscalationLevel(options.escalationLevel);
|
|
1386
1463
|
const policyResolution = readResolvedConfigCeiling(provider, resolvedConfig) ??
|
|
1387
1464
|
(await resolveProjectStateCeiling(provider, projectPath, dependencies));
|
|
1388
|
-
const resolvedValue = await resolveCeilingValue(provider, resolvedConfig, projectPath, dependencies, escalationLevel, role, preferredValue, requestedCandidate, ceilingTier);
|
|
1465
|
+
const resolvedValue = resolveClaudePolicyCapabilities(await resolveCeilingValue(provider, resolvedConfig, projectPath, dependencies, escalationLevel, role, preferredValue, requestedCandidate, ceilingTier), dependencies.processEnv);
|
|
1389
1466
|
for (const warning of resolvedValue?.warnings ?? []) {
|
|
1390
1467
|
context.logger.warn(warning);
|
|
1391
1468
|
}
|
|
1392
|
-
const providerResolution = buildProviderResolution(provider, resolvedValue, role, orchestratorTier, preferredValue);
|
|
1469
|
+
const providerResolution = buildProviderResolution(provider, resolvedValue, role, orchestratorTier, preferredValue, dependencies.processEnv);
|
|
1393
1470
|
const providers = {
|
|
1394
1471
|
[provider]: providerResolution,
|
|
1395
1472
|
};
|
|
@@ -1714,7 +1791,7 @@ function writeHumanResolution(context, resolution) {
|
|
|
1714
1791
|
}
|
|
1715
1792
|
}
|
|
1716
1793
|
else {
|
|
1717
|
-
context.logger.info(
|
|
1794
|
+
context.logger.info(`Effort axis: ${providerResolution?.effortAxis ?? 'not-applicable'}`);
|
|
1718
1795
|
if (providerResolution?.selection.selectionMode === 'inherit-default') {
|
|
1719
1796
|
context.logger.info('Note: OAT will not select a Claude model; Task dispatch inherits host/provider behavior.');
|
|
1720
1797
|
}
|
|
@@ -1910,9 +1987,9 @@ export function createProjectDispatchCeilingCommand(overrides = {}) {
|
|
|
1910
1987
|
.option('--preferred <value>', 'Legacy preferred implementer/fix value before applying the resolved policy')
|
|
1911
1988
|
.addOption(new Option('--ceiling-tier <tier>', 'Invocation-only named maximum tier; never persists configuration or project state').choices([...VALID_DISPATCH_MATRIX_TIERS]))
|
|
1912
1989
|
.option('--candidate-model <model>', 'Exact configured implementer candidate model beneath the named ceiling')
|
|
1913
|
-
.option('--candidate-effort <effort>', 'Exact configured Codex candidate effort paired with --candidate-model')
|
|
1990
|
+
.option('--candidate-effort <effort>', 'Exact configured Codex or Claude candidate effort paired with --candidate-model')
|
|
1914
1991
|
.option('--task-class <class>', `Provider-neutral task classification provenance: ${TASK_CLASSES.join(', ')}`)
|
|
1915
|
-
.option('--task-effort <effort>', 'Codex
|
|
1992
|
+
.option('--task-effort <effort>', 'Codex or Claude task effort classification provenance; does not select a candidate')
|
|
1916
1993
|
.option('--escalation-level <level>', 'Ordered route entry to select; 0 is the floor and higher values advance through escalation targets')
|
|
1917
1994
|
.option('--project-path <path>', 'Read project-state policy from an explicit project path')
|
|
1918
1995
|
.option('--preflight', 'Treat unresolved non-interactive resolution as an implementation block')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch-matrix.d.ts","sourceRoot":"","sources":["../../src/config/dispatch-matrix.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dispatch-matrix.d.ts","sourceRoot":"","sources":["../../src/config/dispatch-matrix.ts"],"names":[],"mappings":"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"}
|