@open-agent-toolkit/cli 0.1.46 → 0.1.48
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-phase-implementer.md +202 -191
- package/assets/agents/oat-reviewer.md +11 -1
- package/assets/config/dispatch-matrix-recommendation.json +120 -13
- package/assets/docs/cli-utilities/configuration.md +172 -113
- package/assets/docs/cli-utilities/workflow-gates.md +161 -27
- package/assets/docs/contributing/skills.md +14 -8
- package/assets/docs/provider-sync/providers.md +41 -7
- package/assets/docs/provider-sync/scope-and-surface.md +2 -2
- package/assets/docs/reference/cli-reference.md +3 -1
- package/assets/docs/reference/oat-directory-structure.md +27 -26
- package/assets/docs/workflows/projects/artifacts.md +31 -1
- package/assets/docs/workflows/projects/dispatch-ceiling.md +235 -187
- package/assets/docs/workflows/projects/implementation-execution.md +283 -260
- package/assets/docs/workflows/projects/lifecycle.md +26 -5
- package/assets/docs/workflows/projects/reviews.md +27 -2
- package/assets/migration/pjm-restructure.md +1 -1
- package/assets/public-package-versions.json +4 -4
- package/assets/skills/oat-project-implement/SKILL.md +247 -133
- package/assets/skills/oat-project-import-plan/SKILL.md +173 -16
- package/assets/skills/oat-project-next/SKILL.md +2 -2
- package/assets/skills/oat-project-plan/SKILL.md +122 -92
- package/assets/skills/oat-project-plan-writing/SKILL.md +246 -15
- package/assets/skills/oat-project-quick-start/SKILL.md +157 -107
- package/assets/skills/oat-project-review-provide/SKILL.md +94 -22
- package/dist/commands/config/index.d.ts.map +1 -1
- package/dist/commands/config/index.js +64 -39
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +21 -6
- package/dist/commands/gate/index.d.ts +7 -1
- package/dist/commands/gate/index.d.ts.map +1 -1
- package/dist/commands/gate/index.js +544 -67
- package/dist/commands/gate/review-verdict.d.ts +16 -0
- package/dist/commands/gate/review-verdict.d.ts.map +1 -1
- package/dist/commands/gate/review-verdict.js +72 -9
- package/dist/commands/project/dispatch-ceiling/index.d.ts.map +1 -1
- package/dist/commands/project/dispatch-ceiling/index.js +452 -16
- package/dist/commands/providers/codex/materialize.d.ts.map +1 -1
- package/dist/commands/providers/codex/materialize.js +6 -1
- package/dist/commands/shared/frontmatter.d.ts +4 -0
- package/dist/commands/shared/frontmatter.d.ts.map +1 -1
- package/dist/commands/shared/frontmatter.js +23 -0
- package/dist/commands/status/index.d.ts +1 -0
- package/dist/commands/status/index.d.ts.map +1 -1
- package/dist/commands/status/index.js +10 -4
- package/dist/commands/sync/index.d.ts.map +1 -1
- package/dist/commands/sync/index.js +10 -3
- package/dist/commands/sync/sync.types.d.ts +1 -0
- package/dist/commands/sync/sync.types.d.ts.map +1 -1
- package/dist/config/oat-config.d.ts +19 -2
- package/dist/config/oat-config.d.ts.map +1 -1
- package/dist/config/oat-config.js +139 -24
- package/dist/config/resolve.d.ts +8 -0
- package/dist/config/resolve.d.ts.map +1 -1
- package/dist/config/resolve.js +66 -2
- package/dist/engine/index.d.ts +1 -1
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +1 -1
- package/dist/engine/scanner.d.ts +1 -0
- package/dist/engine/scanner.d.ts.map +1 -1
- package/dist/engine/scanner.js +17 -1
- package/dist/fs/paths.d.ts +4 -0
- package/dist/fs/paths.d.ts.map +1 -1
- package/dist/fs/paths.js +18 -1
- package/dist/providers/ceiling/registry.d.ts +1 -0
- package/dist/providers/ceiling/registry.d.ts.map +1 -1
- package/dist/providers/ceiling/registry.js +12 -5
- package/dist/providers/codex/codec/catalog.d.ts +14 -0
- package/dist/providers/codex/codec/catalog.d.ts.map +1 -0
- package/dist/providers/codex/codec/catalog.js +21 -0
- package/dist/providers/codex/codec/materialize.d.ts.map +1 -1
- package/dist/providers/codex/codec/materialize.js +6 -5
- package/dist/providers/codex/codec/shared.d.ts +19 -0
- package/dist/providers/codex/codec/shared.d.ts.map +1 -1
- package/dist/providers/codex/codec/shared.js +98 -5
- package/dist/providers/codex/codec/sync-extension.d.ts.map +1 -1
- package/dist/providers/codex/codec/sync-extension.js +142 -32
- package/dist/providers/identity/stamp.d.ts.map +1 -1
- package/dist/providers/identity/stamp.js +4 -0
- package/dist/shared/types.d.ts +1 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +4 -0
- package/package.json +2 -2
|
@@ -5,13 +5,13 @@ import { getFrontmatterBlock } from '../../shared/frontmatter.js';
|
|
|
5
5
|
import { readGlobalOptions } from '../../shared/shared.utils.js';
|
|
6
6
|
import { compileDispatchPolicyPreset, } from '../../../config/dispatch-ceiling-preset.js';
|
|
7
7
|
import { getDispatchPolicyChoices, managedDispatchPolicyValueList, renderDispatchPolicyChoicesMarkdown, } from '../../../config/dispatch-policy-options.js';
|
|
8
|
-
import { resolveActiveProject, VALID_CLAUDE_DISPATCH_CEILINGS, VALID_CODEX_DISPATCH_CEILINGS, VALID_DISPATCH_MATRIX_TIERS, VALID_MANAGED_DISPATCH_POLICIES, validateDispatchRouteTarget, } from '../../../config/oat-config.js';
|
|
8
|
+
import { resolveActiveProject, VALID_CLAUDE_DISPATCH_CEILINGS, VALID_CODEX_DISPATCH_CEILINGS, VALID_DISPATCH_MATRIX_TIERS, VALID_MANAGED_DISPATCH_POLICIES, isWorkflowDispatchCandidateLadder, isWorkflowDispatchFallbackRoute, toWorkflowDispatchCandidateLadder, validateDispatchRouteTarget, } from '../../../config/oat-config.js';
|
|
9
9
|
import { resolveEffectiveConfig, } from '../../../config/resolve.js';
|
|
10
10
|
import { resolveProjectRoot } from '../../../fs/paths.js';
|
|
11
11
|
import TOML from '@iarna/toml';
|
|
12
|
-
import { getCeilingAdapter, } from '../../../providers/ceiling/registry.js';
|
|
12
|
+
import { getCeilingAdapter, isDirectDispatchRoleName, CLAUDE_TIER_ORDER, } from '../../../providers/ceiling/registry.js';
|
|
13
13
|
import { classifyModelFamily, } from '../../../providers/identity/family.js';
|
|
14
|
-
import { Command } from 'commander';
|
|
14
|
+
import { Command, Option } from 'commander';
|
|
15
15
|
import YAML from 'yaml';
|
|
16
16
|
const CODEX_VALUES = [
|
|
17
17
|
...VALID_CODEX_DISPATCH_CEILINGS,
|
|
@@ -85,6 +85,8 @@ function sourceLabel(source) {
|
|
|
85
85
|
return 'environment';
|
|
86
86
|
case 'project-state':
|
|
87
87
|
return 'project state';
|
|
88
|
+
case 'invocation':
|
|
89
|
+
return 'explicit invocation';
|
|
88
90
|
default:
|
|
89
91
|
return 'none';
|
|
90
92
|
}
|
|
@@ -151,11 +153,7 @@ function normalizeProjectMatrixRouteTarget(value) {
|
|
|
151
153
|
}
|
|
152
154
|
return Object.keys(target).length > 0 ? target : undefined;
|
|
153
155
|
}
|
|
154
|
-
function
|
|
155
|
-
const bareValue = normalizeProjectMatrixBareValue(provider, value);
|
|
156
|
-
if (bareValue !== undefined) {
|
|
157
|
-
return bareValue;
|
|
158
|
-
}
|
|
156
|
+
function normalizeProjectMatrixRoute(provider, value) {
|
|
159
157
|
if (!Array.isArray(value) || value.length === 0) {
|
|
160
158
|
return undefined;
|
|
161
159
|
}
|
|
@@ -173,6 +171,34 @@ function normalizeProjectMatrixCell(provider, value) {
|
|
|
173
171
|
}
|
|
174
172
|
return route.length > 0 ? route : undefined;
|
|
175
173
|
}
|
|
174
|
+
function normalizeProjectMatrixCandidate(provider, value) {
|
|
175
|
+
const bareValue = normalizeProjectMatrixBareValue(provider, value);
|
|
176
|
+
if (bareValue !== undefined) {
|
|
177
|
+
return bareValue;
|
|
178
|
+
}
|
|
179
|
+
if (isWorkflowDispatchFallbackRoute(value)) {
|
|
180
|
+
const route = normalizeProjectMatrixRoute(provider, value.route);
|
|
181
|
+
return route ? { route } : undefined;
|
|
182
|
+
}
|
|
183
|
+
return normalizeProjectMatrixRouteTarget(value);
|
|
184
|
+
}
|
|
185
|
+
function normalizeProjectMatrixCell(provider, value) {
|
|
186
|
+
const bareValue = normalizeProjectMatrixBareValue(provider, value);
|
|
187
|
+
if (bareValue !== undefined) {
|
|
188
|
+
return bareValue;
|
|
189
|
+
}
|
|
190
|
+
if (isWorkflowDispatchCandidateLadder(value)) {
|
|
191
|
+
const candidates = [];
|
|
192
|
+
for (const candidate of value.candidates) {
|
|
193
|
+
const normalized = normalizeProjectMatrixCandidate(provider, candidate);
|
|
194
|
+
if (normalized !== undefined) {
|
|
195
|
+
candidates.push(normalized);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return candidates.length > 0 ? { candidates } : undefined;
|
|
199
|
+
}
|
|
200
|
+
return normalizeProjectMatrixRoute(provider, value);
|
|
201
|
+
}
|
|
176
202
|
function normalizeProjectMatrixProviderValue(provider, value) {
|
|
177
203
|
const bareValue = normalizeProjectMatrixBareValue(provider, value);
|
|
178
204
|
if (bareValue !== undefined) {
|
|
@@ -343,6 +369,19 @@ function resolveProviderCellFromValue(provider, providerValue, tier, cellSource,
|
|
|
343
369
|
warnings: [],
|
|
344
370
|
};
|
|
345
371
|
}
|
|
372
|
+
if (isWorkflowDispatchCandidateLadder(cell)) {
|
|
373
|
+
const ceiling = cell.candidates.at(-1);
|
|
374
|
+
if (ceiling === undefined) {
|
|
375
|
+
return null;
|
|
376
|
+
}
|
|
377
|
+
if (typeof ceiling === 'string') {
|
|
378
|
+
return resolveRouteMatrixCell(provider, [ceiling], escalationLevel, cellSource);
|
|
379
|
+
}
|
|
380
|
+
const route = isWorkflowDispatchFallbackRoute(ceiling)
|
|
381
|
+
? ceiling.route
|
|
382
|
+
: [ceiling];
|
|
383
|
+
return resolveRouteMatrixCell(provider, route, escalationLevel, cellSource);
|
|
384
|
+
}
|
|
346
385
|
return resolveRouteMatrixCell(provider, cell, escalationLevel, cellSource);
|
|
347
386
|
}
|
|
348
387
|
function resolveProviderMatrixCell(provider, tier, resolvedConfig, projectMatrix, escalationLevel) {
|
|
@@ -370,6 +409,212 @@ function resolveProviderMatrixCell(provider, tier, resolvedConfig, projectMatrix
|
|
|
370
409
|
}
|
|
371
410
|
return selected;
|
|
372
411
|
}
|
|
412
|
+
function resolveProviderMatrixCellDefinition(provider, tier, resolvedConfig, projectMatrix) {
|
|
413
|
+
let selected = null;
|
|
414
|
+
const layers = [
|
|
415
|
+
{
|
|
416
|
+
source: 'user-config',
|
|
417
|
+
providers: resolvedConfig.user.workflow?.dispatchCeiling?.providers,
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
source: 'repo-config',
|
|
421
|
+
providers: resolvedConfig.shared.workflow?.dispatchCeiling?.providers,
|
|
422
|
+
},
|
|
423
|
+
{
|
|
424
|
+
source: 'local-config',
|
|
425
|
+
providers: resolvedConfig.local.workflow?.dispatchCeiling?.providers,
|
|
426
|
+
},
|
|
427
|
+
{ source: 'project-state', providers: projectMatrix },
|
|
428
|
+
];
|
|
429
|
+
for (const layer of layers) {
|
|
430
|
+
const providerValue = layer.providers?.[provider];
|
|
431
|
+
if (typeof providerValue === 'string') {
|
|
432
|
+
selected = null;
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
const cell = providerValue?.[tier];
|
|
436
|
+
if (cell !== undefined) {
|
|
437
|
+
selected = { cell, cellSource: layer.source };
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return selected;
|
|
441
|
+
}
|
|
442
|
+
function candidateRoute(candidate) {
|
|
443
|
+
return isWorkflowDispatchFallbackRoute(candidate)
|
|
444
|
+
? candidate.route
|
|
445
|
+
: [candidate];
|
|
446
|
+
}
|
|
447
|
+
function candidatePrimaryTarget(provider, tier, candidate) {
|
|
448
|
+
const route = candidateRoute(candidate);
|
|
449
|
+
const entry = route[0];
|
|
450
|
+
if (entry === undefined) {
|
|
451
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: fallback routes cannot be empty.`);
|
|
452
|
+
}
|
|
453
|
+
if (typeof entry !== 'string') {
|
|
454
|
+
const validation = validateDispatchRouteTarget(provider, entry);
|
|
455
|
+
if (!validation.valid) {
|
|
456
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: ${validation.reason}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
const target = typeof entry === 'string'
|
|
460
|
+
? routeTargetFromBareValue(provider, entry, 0, route.length)
|
|
461
|
+
: routeTargetFromObject(provider, entry, 0, route.length);
|
|
462
|
+
if (target.model && isDirectDispatchRoleName(target.model)) {
|
|
463
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: direct dispatch role names are not candidate models.`);
|
|
464
|
+
}
|
|
465
|
+
const targetAdapter = getCeilingAdapter(target.harness);
|
|
466
|
+
if (targetAdapter.mechanism === 'pinned-variant' &&
|
|
467
|
+
(!target.model ||
|
|
468
|
+
!target.effort ||
|
|
469
|
+
!CODEX_VALUES.includes(target.effort))) {
|
|
470
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: Codex candidates require a model and supported effort.`);
|
|
471
|
+
}
|
|
472
|
+
if (targetAdapter.mechanism === 'model-arg' && !target.model) {
|
|
473
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: model-argument candidates require a model.`);
|
|
474
|
+
}
|
|
475
|
+
return target;
|
|
476
|
+
}
|
|
477
|
+
function candidateTargetKey(target) {
|
|
478
|
+
return JSON.stringify([
|
|
479
|
+
target.harness,
|
|
480
|
+
target.model ?? null,
|
|
481
|
+
target.effort ?? null,
|
|
482
|
+
]);
|
|
483
|
+
}
|
|
484
|
+
function assertCandidateOrder(provider, tier, ladder) {
|
|
485
|
+
if (ladder.candidates.length === 0) {
|
|
486
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: candidates cannot be empty.`);
|
|
487
|
+
}
|
|
488
|
+
const targets = [];
|
|
489
|
+
const seen = new Set();
|
|
490
|
+
let previousClaudeRank = null;
|
|
491
|
+
const codexRanksByModel = new Map();
|
|
492
|
+
for (const candidate of ladder.candidates) {
|
|
493
|
+
const target = candidatePrimaryTarget(provider, tier, candidate);
|
|
494
|
+
const key = candidateTargetKey(target);
|
|
495
|
+
if (seen.has(key)) {
|
|
496
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: duplicate candidate ${key}.`);
|
|
497
|
+
}
|
|
498
|
+
seen.add(key);
|
|
499
|
+
if (target.harness === 'claude' && target.model) {
|
|
500
|
+
const rank = CLAUDE_TIER_ORDER.indexOf(target.model);
|
|
501
|
+
if (rank < 0) {
|
|
502
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: unsupported Claude model ${JSON.stringify(target.model)}.`);
|
|
503
|
+
}
|
|
504
|
+
if (previousClaudeRank !== null && rank < previousClaudeRank) {
|
|
505
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: Claude candidates must be nondecreasing.`);
|
|
506
|
+
}
|
|
507
|
+
previousClaudeRank = rank;
|
|
508
|
+
}
|
|
509
|
+
if (target.harness === 'codex' && target.model && target.effort) {
|
|
510
|
+
const rank = CODEX_VALUES.indexOf(target.effort);
|
|
511
|
+
const previousRank = codexRanksByModel.get(target.model);
|
|
512
|
+
if (previousRank !== undefined && rank < previousRank) {
|
|
513
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: Codex efforts for ${target.model} must be nondecreasing.`);
|
|
514
|
+
}
|
|
515
|
+
codexRanksByModel.set(target.model, rank);
|
|
516
|
+
}
|
|
517
|
+
targets.push(target);
|
|
518
|
+
}
|
|
519
|
+
return targets;
|
|
520
|
+
}
|
|
521
|
+
function assertTierCeilingsNondecreasing(provider, previous, current, tier) {
|
|
522
|
+
if (!previous || previous.harness !== current.harness) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
if (current.harness === 'claude' &&
|
|
526
|
+
previous.model &&
|
|
527
|
+
current.model &&
|
|
528
|
+
CLAUDE_TIER_ORDER.indexOf(current.model) <
|
|
529
|
+
CLAUDE_TIER_ORDER.indexOf(previous.model)) {
|
|
530
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: named tier ceilings must be nondecreasing.`);
|
|
531
|
+
}
|
|
532
|
+
if (current.harness === 'codex' &&
|
|
533
|
+
previous.model === current.model &&
|
|
534
|
+
previous.effort &&
|
|
535
|
+
current.effort &&
|
|
536
|
+
CODEX_VALUES.indexOf(current.effort) <
|
|
537
|
+
CODEX_VALUES.indexOf(previous.effort)) {
|
|
538
|
+
throw new Error(`Malformed ${provider} candidate ordering in ${tier}: named tier ceilings must be nondecreasing.`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
function requestedCandidateMatches(provider, requested, target) {
|
|
542
|
+
if (target.harness !== provider || target.model !== requested.model) {
|
|
543
|
+
return false;
|
|
544
|
+
}
|
|
545
|
+
return provider !== 'codex' || target.effort === requested.effort;
|
|
546
|
+
}
|
|
547
|
+
function formatRequestedCandidate(provider, requested) {
|
|
548
|
+
return provider === 'codex'
|
|
549
|
+
? `${requested.model}/${requested.effort}`
|
|
550
|
+
: requested.model;
|
|
551
|
+
}
|
|
552
|
+
function resolveRequestedMatrixCandidate(provider, requested, ceilingTier, resolvedConfig, projectMatrix, escalationLevel) {
|
|
553
|
+
const ceilingIndex = ceilingTier === null
|
|
554
|
+
? VALID_DISPATCH_MATRIX_TIERS.length - 1
|
|
555
|
+
: VALID_DISPATCH_MATRIX_TIERS.indexOf(ceilingTier);
|
|
556
|
+
let ceilingCellFound = ceilingTier === null;
|
|
557
|
+
let previousCeiling = null;
|
|
558
|
+
let allowedMatch;
|
|
559
|
+
let foundAboveCeiling = false;
|
|
560
|
+
for (const [tierIndex, tier] of VALID_DISPATCH_MATRIX_TIERS.entries()) {
|
|
561
|
+
const definition = resolveProviderMatrixCellDefinition(provider, tier, resolvedConfig, projectMatrix);
|
|
562
|
+
if (!definition) {
|
|
563
|
+
continue;
|
|
564
|
+
}
|
|
565
|
+
if (tier === ceilingTier) {
|
|
566
|
+
ceilingCellFound = true;
|
|
567
|
+
}
|
|
568
|
+
const ladder = toWorkflowDispatchCandidateLadder(definition.cell);
|
|
569
|
+
const targets = assertCandidateOrder(provider, tier, ladder);
|
|
570
|
+
const currentCeiling = targets.at(-1);
|
|
571
|
+
assertTierCeilingsNondecreasing(provider, previousCeiling, currentCeiling, tier);
|
|
572
|
+
previousCeiling = currentCeiling;
|
|
573
|
+
for (const [candidateIndex, target] of targets.entries()) {
|
|
574
|
+
if (!requestedCandidateMatches(provider, requested, target)) {
|
|
575
|
+
continue;
|
|
576
|
+
}
|
|
577
|
+
const candidate = ladder.candidates[candidateIndex];
|
|
578
|
+
const routeSignature = JSON.stringify(candidateRoute(candidate));
|
|
579
|
+
if (tierIndex > ceilingIndex) {
|
|
580
|
+
foundAboveCeiling = true;
|
|
581
|
+
continue;
|
|
582
|
+
}
|
|
583
|
+
if (allowedMatch && allowedMatch.routeSignature !== routeSignature) {
|
|
584
|
+
throw new Error(`Ambiguous ${provider} candidate ${formatRequestedCandidate(provider, requested)} is configured with multiple routes at or below the ${ceilingTier ?? 'uncapped'} ceiling.`);
|
|
585
|
+
}
|
|
586
|
+
allowedMatch ??= {
|
|
587
|
+
tier,
|
|
588
|
+
candidate,
|
|
589
|
+
cellSource: definition.cellSource,
|
|
590
|
+
routeSignature,
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
if (!ceilingCellFound) {
|
|
595
|
+
throw new Error(`Exact candidate selection requires a configured ${ceilingTier} candidate ladder for ${provider}.`);
|
|
596
|
+
}
|
|
597
|
+
if (!allowedMatch) {
|
|
598
|
+
const label = formatRequestedCandidate(provider, requested);
|
|
599
|
+
if (foundAboveCeiling) {
|
|
600
|
+
throw new Error(`${provider} candidate ${label} is above the configured ${ceilingTier} ceiling.`);
|
|
601
|
+
}
|
|
602
|
+
throw new Error(`${provider} candidate ${label} is not present in the configured ${provider} candidate ladders.`);
|
|
603
|
+
}
|
|
604
|
+
const resolution = resolveRouteMatrixCell(provider, candidateRoute(allowedMatch.candidate), escalationLevel, allowedMatch.cellSource);
|
|
605
|
+
if (!resolution || resolution.value === null) {
|
|
606
|
+
throw new Error(`Configured ${provider} candidate ${formatRequestedCandidate(provider, requested)} cannot compile to an exact dispatch target.`);
|
|
607
|
+
}
|
|
608
|
+
return {
|
|
609
|
+
resolution: {
|
|
610
|
+
...resolution,
|
|
611
|
+
selectionBranch: resolution.selectionBranch === 'escalation-target'
|
|
612
|
+
? 'escalation-target'
|
|
613
|
+
: 'candidate-requested',
|
|
614
|
+
},
|
|
615
|
+
candidateTier: allowedMatch.tier,
|
|
616
|
+
};
|
|
617
|
+
}
|
|
373
618
|
function readProjectDispatchPolicy(provider, content) {
|
|
374
619
|
const frontmatter = getFrontmatterBlock(content);
|
|
375
620
|
if (!frontmatter) {
|
|
@@ -645,7 +890,13 @@ function readResolvedConfigCeiling(provider, resolvedConfig) {
|
|
|
645
890
|
return stripConfigCandidateSource(winner);
|
|
646
891
|
}
|
|
647
892
|
function normalizeRole(value) {
|
|
648
|
-
|
|
893
|
+
if (value === undefined) {
|
|
894
|
+
return 'implementer';
|
|
895
|
+
}
|
|
896
|
+
if (value === 'implementer' || value === 'reviewer') {
|
|
897
|
+
return value;
|
|
898
|
+
}
|
|
899
|
+
throw new Error(`Invalid dispatch role ${JSON.stringify(value)}. Expected implementer or reviewer.`);
|
|
649
900
|
}
|
|
650
901
|
function providerValueOrder(provider) {
|
|
651
902
|
if (provider === 'codex') {
|
|
@@ -674,6 +925,55 @@ function normalizePreferredValue(provider, value) {
|
|
|
674
925
|
}
|
|
675
926
|
return normalized;
|
|
676
927
|
}
|
|
928
|
+
function normalizeCeilingTier(value, role) {
|
|
929
|
+
if (value === undefined) {
|
|
930
|
+
return null;
|
|
931
|
+
}
|
|
932
|
+
const normalized = value.trim();
|
|
933
|
+
if (!VALID_DISPATCH_MATRIX_TIERS.includes(normalized)) {
|
|
934
|
+
throw new Error(`Invalid invocation ceiling tier "${normalized}". Valid tiers: ${VALID_DISPATCH_MATRIX_TIERS.join(', ')}.`);
|
|
935
|
+
}
|
|
936
|
+
if (role === 'reviewer') {
|
|
937
|
+
throw new Error('Invocation ceiling tiers are only supported for implementer/fix task dispatch; reviewers use the configured review ceiling.');
|
|
938
|
+
}
|
|
939
|
+
return normalized;
|
|
940
|
+
}
|
|
941
|
+
function normalizeRequestedCandidate(provider, role, options) {
|
|
942
|
+
const model = options.candidateModel?.trim() ?? '';
|
|
943
|
+
const effort = options.candidateEffort?.trim() ?? '';
|
|
944
|
+
if (!model && !effort) {
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
if (options.preferred?.trim()) {
|
|
948
|
+
throw new Error('Exact candidate flags cannot be combined with --preferred; use one selection path.');
|
|
949
|
+
}
|
|
950
|
+
if (role === 'reviewer') {
|
|
951
|
+
throw new Error('Reviewer candidate requests are not supported; reviewers use the configured review ceiling.');
|
|
952
|
+
}
|
|
953
|
+
if (!model) {
|
|
954
|
+
throw new Error('--candidate-model is required for an exact candidate.');
|
|
955
|
+
}
|
|
956
|
+
if (isDirectDispatchRoleName(model)) {
|
|
957
|
+
throw new Error('Direct dispatch role names are not candidate models; request the configured provider model and effort instead.');
|
|
958
|
+
}
|
|
959
|
+
if (provider === 'codex') {
|
|
960
|
+
if (!effort) {
|
|
961
|
+
throw new Error('--candidate-effort is required for an exact Codex candidate.');
|
|
962
|
+
}
|
|
963
|
+
if (!CODEX_VALUES.includes(effort)) {
|
|
964
|
+
throw new Error(`Invalid Codex candidate effort "${effort}". Valid values: ${CODEX_VALUES.join(', ')}.`);
|
|
965
|
+
}
|
|
966
|
+
return { model, effort };
|
|
967
|
+
}
|
|
968
|
+
if (effort) {
|
|
969
|
+
throw new Error(`--candidate-effort is only valid for Codex; ${provider} candidates use --candidate-model only.`);
|
|
970
|
+
}
|
|
971
|
+
if (provider === 'claude' &&
|
|
972
|
+
!CLAUDE_VALUES.includes(model)) {
|
|
973
|
+
throw new Error(`Invalid Claude candidate model "${model}". Valid values: ${CLAUDE_VALUES.join(', ')}.`);
|
|
974
|
+
}
|
|
975
|
+
return { model };
|
|
976
|
+
}
|
|
677
977
|
function normalizeEscalationLevel(value) {
|
|
678
978
|
if (value === undefined) {
|
|
679
979
|
return 0;
|
|
@@ -696,6 +996,10 @@ function selectDispatchValue(provider, role, policy, preferredValue) {
|
|
|
696
996
|
policy: policy.policy,
|
|
697
997
|
cellSource: policy.cellSource,
|
|
698
998
|
target: policy.target,
|
|
999
|
+
requestedCandidate: policy.requestedCandidate ?? null,
|
|
1000
|
+
candidateTier: policy.candidateTier ?? null,
|
|
1001
|
+
ceilingTier: policy.ceilingTier ?? policyTier(policy.policy),
|
|
1002
|
+
ceilingTarget: policy.ceilingTarget ?? policy.target,
|
|
699
1003
|
};
|
|
700
1004
|
if (policy.mode === 'inherit') {
|
|
701
1005
|
return {
|
|
@@ -709,6 +1013,21 @@ function selectDispatchValue(provider, role, policy, preferredValue) {
|
|
|
709
1013
|
target: null,
|
|
710
1014
|
};
|
|
711
1015
|
}
|
|
1016
|
+
if (policy.requestedCandidate) {
|
|
1017
|
+
const selectedValue = policy.target
|
|
1018
|
+
? dispatchValueFromRouteTarget(policy.target)
|
|
1019
|
+
: null;
|
|
1020
|
+
return {
|
|
1021
|
+
...baseSelection,
|
|
1022
|
+
preferredValue: null,
|
|
1023
|
+
selectedValue,
|
|
1024
|
+
capped: false,
|
|
1025
|
+
selectionMode: selectedValue ? 'candidate' : 'unresolved',
|
|
1026
|
+
selectionBranch: policy.selectionBranch,
|
|
1027
|
+
family: selectionFamily(provider, selectedValue, policy.target),
|
|
1028
|
+
target: policy.target,
|
|
1029
|
+
};
|
|
1030
|
+
}
|
|
712
1031
|
if (policy.policy === 'uncapped') {
|
|
713
1032
|
const targetValue = policy.target
|
|
714
1033
|
? dispatchValueFromRouteTarget(policy.target)
|
|
@@ -769,6 +1088,10 @@ function selectDispatchValue(provider, role, policy, preferredValue) {
|
|
|
769
1088
|
}
|
|
770
1089
|
const selectedIndex = Math.min(preferredIndex, ceilingIndex);
|
|
771
1090
|
const selectedValue = order[selectedIndex];
|
|
1091
|
+
const targetValue = policy.target
|
|
1092
|
+
? dispatchValueFromRouteTarget(policy.target)
|
|
1093
|
+
: null;
|
|
1094
|
+
const selectedTarget = targetValue === selectedValue ? policy.target : null;
|
|
772
1095
|
return {
|
|
773
1096
|
...baseSelection,
|
|
774
1097
|
preferredValue,
|
|
@@ -776,8 +1099,8 @@ function selectDispatchValue(provider, role, policy, preferredValue) {
|
|
|
776
1099
|
capped: preferredIndex > ceilingIndex,
|
|
777
1100
|
selectionMode: 'capped',
|
|
778
1101
|
selectionBranch: policy.selectionBranch,
|
|
779
|
-
family: selectionFamily(provider, selectedValue,
|
|
780
|
-
target:
|
|
1102
|
+
family: selectionFamily(provider, selectedValue, selectedTarget),
|
|
1103
|
+
target: selectedTarget,
|
|
781
1104
|
};
|
|
782
1105
|
}
|
|
783
1106
|
function hasCodexVariantDispatchArgs(dispatchArgs) {
|
|
@@ -835,6 +1158,10 @@ function buildProviderResolution(provider, policy, role, orchestratorTier, prefe
|
|
|
835
1158
|
selection: {
|
|
836
1159
|
role,
|
|
837
1160
|
preferredValue,
|
|
1161
|
+
requestedCandidate: null,
|
|
1162
|
+
candidateTier: null,
|
|
1163
|
+
ceilingTier: null,
|
|
1164
|
+
ceilingTarget: null,
|
|
838
1165
|
selectedValue: null,
|
|
839
1166
|
capped: false,
|
|
840
1167
|
selectionMode: 'unresolved',
|
|
@@ -933,9 +1260,11 @@ async function resolveDispatchCeiling(context, dependencies, options) {
|
|
|
933
1260
|
const providerDefaultEffort = provider === 'codex'
|
|
934
1261
|
? await resolveCodexProviderDefaultEffort(repoRoot, context, dependencies)
|
|
935
1262
|
: 'not-applicable';
|
|
1263
|
+
const requestedCandidate = normalizeRequestedCandidate(provider, role, options);
|
|
936
1264
|
const preferredValue = normalizePreferredValue(provider, options.preferred);
|
|
1265
|
+
const ceilingTier = normalizeCeilingTier(options.ceilingTier, role);
|
|
937
1266
|
const escalationLevel = normalizeEscalationLevel(options.escalationLevel);
|
|
938
|
-
const resolvedValue = await resolveCeilingValue(provider, resolvedConfig, projectPath, dependencies, escalationLevel, role, preferredValue);
|
|
1267
|
+
const resolvedValue = await resolveCeilingValue(provider, resolvedConfig, projectPath, dependencies, escalationLevel, role, preferredValue, requestedCandidate, ceilingTier);
|
|
939
1268
|
for (const warning of resolvedValue?.warnings ?? []) {
|
|
940
1269
|
context.logger.warn(warning);
|
|
941
1270
|
}
|
|
@@ -944,6 +1273,32 @@ async function resolveDispatchCeiling(context, dependencies, options) {
|
|
|
944
1273
|
[provider]: providerResolution,
|
|
945
1274
|
};
|
|
946
1275
|
if (resolvedValue) {
|
|
1276
|
+
const incompleteManagedPreflight = options.preflight === true &&
|
|
1277
|
+
resolvedValue.mode === 'managed' &&
|
|
1278
|
+
providerResolution.mode === 'advisory' &&
|
|
1279
|
+
providerResolution.selection.target?.crossHarness !== true &&
|
|
1280
|
+
providerResolution.selection.selectionMode !== 'no-review-target';
|
|
1281
|
+
if (incompleteManagedPreflight) {
|
|
1282
|
+
const shouldBlock = options.nonInteractive === true ||
|
|
1283
|
+
isNonInteractiveEnv(dependencies.processEnv) ||
|
|
1284
|
+
(!context.interactive && !context.json);
|
|
1285
|
+
const message = shouldBlock ? blockMessage(provider) : undefined;
|
|
1286
|
+
return {
|
|
1287
|
+
status: shouldBlock ? 'blocked' : 'unresolved',
|
|
1288
|
+
provider,
|
|
1289
|
+
value: resolvedValue.value,
|
|
1290
|
+
policyMode: resolvedValue.mode,
|
|
1291
|
+
policy: resolvedValue.policy,
|
|
1292
|
+
source: resolvedValue.source,
|
|
1293
|
+
preset: resolvedValue.preset,
|
|
1294
|
+
unresolved: true,
|
|
1295
|
+
projectPath,
|
|
1296
|
+
providerDefaultEffort,
|
|
1297
|
+
matrix: resolvedValue.matrix,
|
|
1298
|
+
providers,
|
|
1299
|
+
message,
|
|
1300
|
+
};
|
|
1301
|
+
}
|
|
947
1302
|
return {
|
|
948
1303
|
status: 'resolved',
|
|
949
1304
|
provider,
|
|
@@ -985,16 +1340,61 @@ async function resolveDispatchCeiling(context, dependencies, options) {
|
|
|
985
1340
|
* Never reads the preset label for dispatch — the preset is surfaced as
|
|
986
1341
|
* provenance only.
|
|
987
1342
|
*/
|
|
988
|
-
async function resolveCeilingValue(provider, resolvedConfig, projectPath, dependencies, escalationLevel, role, preferredValue) {
|
|
1343
|
+
async function resolveCeilingValue(provider, resolvedConfig, projectPath, dependencies, escalationLevel, role, preferredValue, requestedCandidate, invocationCeilingTier) {
|
|
989
1344
|
const configCeiling = readResolvedConfigCeiling(provider, resolvedConfig);
|
|
990
1345
|
const projectCeiling = await resolveProjectStateCeiling(provider, projectPath, dependencies);
|
|
991
|
-
|
|
1346
|
+
let baseCeiling = configCeiling ?? projectCeiling;
|
|
992
1347
|
if (!baseCeiling) {
|
|
993
1348
|
return null;
|
|
994
1349
|
}
|
|
1350
|
+
if (invocationCeilingTier) {
|
|
1351
|
+
baseCeiling = {
|
|
1352
|
+
...baseCeiling,
|
|
1353
|
+
mode: 'managed',
|
|
1354
|
+
policy: invocationCeilingTier,
|
|
1355
|
+
value: compiledPolicyValueForProvider(provider, compileDispatchPolicyPreset(invocationCeilingTier)),
|
|
1356
|
+
source: 'invocation',
|
|
1357
|
+
preset: invocationCeilingTier,
|
|
1358
|
+
matrix: projectCeiling?.matrix ?? baseCeiling.matrix,
|
|
1359
|
+
cellSource: null,
|
|
1360
|
+
target: null,
|
|
1361
|
+
selectionBranch: 'prompt-persisted',
|
|
1362
|
+
ceilingTier: invocationCeilingTier,
|
|
1363
|
+
ceilingTarget: null,
|
|
1364
|
+
};
|
|
1365
|
+
}
|
|
995
1366
|
if (baseCeiling.mode === 'inherit') {
|
|
1367
|
+
if (requestedCandidate) {
|
|
1368
|
+
throw new Error('Exact candidate selection requires a managed dispatch policy and configured candidate ladder.');
|
|
1369
|
+
}
|
|
996
1370
|
return baseCeiling;
|
|
997
1371
|
}
|
|
1372
|
+
if (requestedCandidate) {
|
|
1373
|
+
if (baseCeiling.policy === 'legacy-ceiling') {
|
|
1374
|
+
throw new Error('Exact candidate selection requires a configured candidate ladder; legacy scalar dispatch ceilings support --preferred only during migration.');
|
|
1375
|
+
}
|
|
1376
|
+
const ceilingTier = policyTier(baseCeiling.policy);
|
|
1377
|
+
const selected = resolveRequestedMatrixCandidate(provider, requestedCandidate, ceilingTier, resolvedConfig, projectCeiling?.matrix ?? null, escalationLevel);
|
|
1378
|
+
const ceilingCell = ceilingTier
|
|
1379
|
+
? resolveProviderMatrixCell(provider, ceilingTier, resolvedConfig, projectCeiling?.matrix ?? null, escalationLevel)
|
|
1380
|
+
: null;
|
|
1381
|
+
return {
|
|
1382
|
+
...baseCeiling,
|
|
1383
|
+
value: ceilingCell?.value ?? baseCeiling.value,
|
|
1384
|
+
cellSource: selected.resolution.cellSource,
|
|
1385
|
+
target: selected.resolution.target,
|
|
1386
|
+
selectionBranch: selected.resolution.selectionBranch,
|
|
1387
|
+
warnings: [
|
|
1388
|
+
...baseCeiling.warnings,
|
|
1389
|
+
...(ceilingCell?.warnings ?? []),
|
|
1390
|
+
...selected.resolution.warnings,
|
|
1391
|
+
],
|
|
1392
|
+
requestedCandidate,
|
|
1393
|
+
candidateTier: selected.candidateTier,
|
|
1394
|
+
ceilingTarget: ceilingCell?.target ?? null,
|
|
1395
|
+
...(ceilingTier ? { ceilingTier } : {}),
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
998
1398
|
if (baseCeiling.policy === 'uncapped') {
|
|
999
1399
|
const preferredTier = uncappedPreferredTier(provider, role, preferredValue);
|
|
1000
1400
|
if (preferredTier) {
|
|
@@ -1014,6 +1414,30 @@ async function resolveCeilingValue(provider, resolvedConfig, projectPath, depend
|
|
|
1014
1414
|
const tier = policyTier(baseCeiling.policy);
|
|
1015
1415
|
const matrixCell = resolveProviderMatrixCell(provider, tier, resolvedConfig, projectCeiling?.matrix ?? null, escalationLevel);
|
|
1016
1416
|
if (matrixCell) {
|
|
1417
|
+
if (provider === 'codex' &&
|
|
1418
|
+
role === 'implementer' &&
|
|
1419
|
+
preferredValue !== null &&
|
|
1420
|
+
matrixCell.value !== null) {
|
|
1421
|
+
const order = providerValueOrder(provider);
|
|
1422
|
+
const preferredIndex = order?.indexOf(preferredValue) ?? -1;
|
|
1423
|
+
const ceilingIndex = order?.indexOf(matrixCell.value) ?? -1;
|
|
1424
|
+
if (order && preferredIndex >= 0 && ceilingIndex >= 0) {
|
|
1425
|
+
const selectedValue = order[Math.min(preferredIndex, ceilingIndex)];
|
|
1426
|
+
if (selectedValue !== matrixCell.value) {
|
|
1427
|
+
const selectedTarget = matrixCell.target?.harness === 'codex'
|
|
1428
|
+
? { ...matrixCell.target, effort: selectedValue }
|
|
1429
|
+
: matrixCell.target;
|
|
1430
|
+
return {
|
|
1431
|
+
...baseCeiling,
|
|
1432
|
+
value: matrixCell.value,
|
|
1433
|
+
cellSource: matrixCell.cellSource,
|
|
1434
|
+
target: selectedTarget,
|
|
1435
|
+
selectionBranch: matrixCell.selectionBranch,
|
|
1436
|
+
warnings: [...baseCeiling.warnings, ...matrixCell.warnings],
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1017
1441
|
return {
|
|
1018
1442
|
...baseCeiling,
|
|
1019
1443
|
value: matrixCell.value,
|
|
@@ -1049,6 +1473,15 @@ function writeHumanResolution(context, resolution) {
|
|
|
1049
1473
|
if (providerResolution) {
|
|
1050
1474
|
context.logger.info(`Mode: ${providerResolution.mode} (${providerResolution.mechanism})`);
|
|
1051
1475
|
context.logger.info(`Selection: ${providerResolution.selection.selectionMode}`);
|
|
1476
|
+
if (providerResolution.selection.requestedCandidate) {
|
|
1477
|
+
const requested = providerResolution.selection.requestedCandidate;
|
|
1478
|
+
context.logger.info(`Requested candidate: model=${requested.model}${requested.effort ? ` effort=${requested.effort}` : ''}`);
|
|
1479
|
+
context.logger.info(`Candidate tier: ${providerResolution.selection.candidateTier ?? 'none'}; ceiling tier: ${providerResolution.selection.ceilingTier ?? 'uncapped'}`);
|
|
1480
|
+
const ceilingTarget = providerResolution.selection.ceilingTarget;
|
|
1481
|
+
if (ceilingTarget) {
|
|
1482
|
+
context.logger.info(`Effective ceiling target: model=${ceilingTarget.model ?? 'none'}${ceilingTarget.effort ? ` effort=${ceilingTarget.effort}` : ''}`);
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1052
1485
|
if (providerResolution.target) {
|
|
1053
1486
|
const details = [
|
|
1054
1487
|
`harness=${providerResolution.target.harness}`,
|
|
@@ -1159,9 +1592,12 @@ export function createProjectDispatchCeilingCommand(overrides = {}) {
|
|
|
1159
1592
|
command.addCommand(new Command('resolve')
|
|
1160
1593
|
.description('Resolve dispatch policy for a provider')
|
|
1161
1594
|
.requiredOption('--provider <provider>', 'Provider name: codex, claude, or cursor are enforced; unregistered providers resolve as unsupported advisory')
|
|
1162
|
-
.
|
|
1595
|
+
.addOption(new Option('--role <role>', 'Dispatch role for variant compilation: implementer (default) or reviewer').choices(['implementer', 'reviewer']))
|
|
1163
1596
|
.option('--orchestrator-tier <tier>', 'Orchestrator tier, used to flag verify-on-upgrade for above-orchestrator requests')
|
|
1164
|
-
.option('--preferred <value>', '
|
|
1597
|
+
.option('--preferred <value>', 'Legacy preferred implementer/fix value before applying the resolved policy')
|
|
1598
|
+
.addOption(new Option('--ceiling-tier <tier>', 'Invocation-only named maximum tier; never persists configuration or project state').choices([...VALID_DISPATCH_MATRIX_TIERS]))
|
|
1599
|
+
.option('--candidate-model <model>', 'Exact configured implementer candidate model beneath the named ceiling')
|
|
1600
|
+
.option('--candidate-effort <effort>', 'Exact configured Codex candidate effort paired with --candidate-model')
|
|
1165
1601
|
.option('--escalation-level <level>', 'Ordered route entry to select; 0 is the floor and higher values advance through escalation targets')
|
|
1166
1602
|
.option('--project-path <path>', 'Read project-state policy from an explicit project path')
|
|
1167
1603
|
.option('--preflight', 'Treat unresolved non-interactive resolution as an implementation block')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"materialize.d.ts","sourceRoot":"","sources":["../../../../src/commands/providers/codex/materialize.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,sBAAsB,EACtB,qCAAqC,EACtC,MAAM,qCAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"materialize.d.ts","sourceRoot":"","sources":["../../../../src/commands/providers/codex/materialize.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,sBAAsB,EACtB,qCAAqC,EACtC,MAAM,qCAAqC,CAAC;AAU7C,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAsD5C,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,sBAAsB,GAC7B,MAAM,CAaR;AA+GD,wBAAgB,6BAA6B,CAC3C,SAAS,GAAE,OAAO,CAAC,qCAAqC,CAAM,GAC7D,OAAO,CAoCT"}
|
|
@@ -8,6 +8,7 @@ import { ensureDir, fileExists } from '../../../fs/io.js';
|
|
|
8
8
|
import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
|
|
9
9
|
import { mergeCodexConfigForRole } from '../../../providers/codex/codec/config-merge.js';
|
|
10
10
|
import { materializeCodexRole } from '../../../providers/codex/codec/materialize.js';
|
|
11
|
+
import { withOatManagedCodexRoleOwner } from '../../../providers/codex/codec/shared.js';
|
|
11
12
|
import { Command, Option } from 'commander';
|
|
12
13
|
function createDependencies() {
|
|
13
14
|
return {
|
|
@@ -59,12 +60,16 @@ async function buildCodexMaterializePlan(agentName, options, context, dependenci
|
|
|
59
60
|
const scopeRoot = await dependencies.resolveScopeRoot(scope, context);
|
|
60
61
|
const agentPath = resolveAgentPath(agentName, options, scopeRoot);
|
|
61
62
|
const agent = await dependencies.parseCanonicalAgentFile(agentPath);
|
|
62
|
-
const
|
|
63
|
+
const materializedRole = dependencies.materializeCodexRole({
|
|
63
64
|
agent,
|
|
64
65
|
model,
|
|
65
66
|
effort,
|
|
66
67
|
roleName: options.roleName,
|
|
67
68
|
});
|
|
69
|
+
const role = {
|
|
70
|
+
...materializedRole,
|
|
71
|
+
content: withOatManagedCodexRoleOwner(materializedRole.content, scope === 'user' ? 'user-config' : 'project-config'),
|
|
72
|
+
};
|
|
68
73
|
const rolePath = join(scopeRoot, '.codex', role.configFile);
|
|
69
74
|
const configPath = join(scopeRoot, '.codex', 'config.toml');
|
|
70
75
|
return {
|
|
@@ -9,6 +9,10 @@ export declare function isProjectStatePhase(value: string): value is ProjectStat
|
|
|
9
9
|
export declare function isProjectStateFrontmatterField(value: string): value is ProjectStateFrontmatterField;
|
|
10
10
|
export declare function getFrontmatterBlock(content: string): string | null;
|
|
11
11
|
export declare function getFrontmatterField(frontmatter: string, field: string): string | null;
|
|
12
|
+
export declare function parseFrontmatterScalarFields(frontmatter: string, fields: readonly string[]): {
|
|
13
|
+
valid: boolean;
|
|
14
|
+
values: Record<string, string>;
|
|
15
|
+
};
|
|
12
16
|
/**
|
|
13
17
|
* Parse an `oat_generated_at` value into a comparable epoch millisecond time.
|
|
14
18
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/frontmatter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/frontmatter.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,6CAA8C,CAAC;AAE/E,eAAO,MAAM,oBAAoB,gFAOvB,CAAC;AAEX,eAAO,MAAM,gCAAgC,sgBA2BnC,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AACpE,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC;AACtE,MAAM,MAAM,4BAA4B,GACtC,CAAC,OAAO,gCAAgC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,gBAAgB,CAE3E;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,iBAAiB,CAE7E;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,MAAM,GACZ,KAAK,IAAI,4BAA4B,CAIvC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGlE;AAED,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAKf;AAED,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,SAAS,MAAM,EAAE,GACxB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CA4BpD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIxD;AAED,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,MAAM,CAAC,CASjB;AAED,wBAAsB,eAAe,CACnC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQxB;AAED,wBAAsB,eAAe,CACnC,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAGxB"}
|