@open-agent-toolkit/cli 0.3.1 → 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 +7 -2
- 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/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,6 +1,7 @@
|
|
|
1
1
|
import { VALID_CLAUDE_DISPATCH_CEILINGS, VALID_CODEX_DISPATCH_CEILINGS, } from '../../config/oat-config.js';
|
|
2
2
|
import { getOwnKey } from '../../config/own-keys.js';
|
|
3
|
-
import {
|
|
3
|
+
import { buildClaudeEffortVariantName, CLAUDE_MODEL_ORDER, validateClaudeDispatchCapability, } from '../claude/targets.js';
|
|
4
|
+
import { buildCodexMaterializedTargetRoleName, SUPPORTED_CODEX_ROLE_TARGETS, } from '../codex/codec/shared.js';
|
|
4
5
|
import { findCursorModelPinMapping } from '../cursor/codec/catalog.js';
|
|
5
6
|
import { buildCursorMaterializedRoleName } from '../cursor/codec/shared.js';
|
|
6
7
|
const DIRECT_DISPATCH_ROLE_PATTERN = /^oat-(?:phase-implementer|reviewer)(?:-|$)/;
|
|
@@ -11,12 +12,7 @@ export function isDirectDispatchRoleName(value) {
|
|
|
11
12
|
const CODEX_IMPLEMENTER_ROLE = 'oat-phase-implementer';
|
|
12
13
|
const CODEX_REVIEWER_ROLE = 'oat-reviewer';
|
|
13
14
|
/** Claude tier order, low → high, for above-orchestrator comparison. */
|
|
14
|
-
export const CLAUDE_TIER_ORDER = [
|
|
15
|
-
'haiku',
|
|
16
|
-
'sonnet',
|
|
17
|
-
'opus',
|
|
18
|
-
'fable',
|
|
19
|
-
];
|
|
15
|
+
export const CLAUDE_TIER_ORDER = [...CLAUDE_MODEL_ORDER];
|
|
20
16
|
const codexAdapter = {
|
|
21
17
|
provider: 'codex',
|
|
22
18
|
supportsCeiling: true,
|
|
@@ -24,7 +20,10 @@ const codexAdapter = {
|
|
|
24
20
|
mechanism: 'pinned-variant',
|
|
25
21
|
selectionAxis: 'model-effort',
|
|
26
22
|
compileToDispatchArgs(value, role, ctx) {
|
|
27
|
-
if (!VALID_CODEX_DISPATCH_CEILINGS.includes(value)
|
|
23
|
+
if (!VALID_CODEX_DISPATCH_CEILINGS.includes(value) &&
|
|
24
|
+
!SUPPORTED_CODEX_ROLE_TARGETS.some((candidate) => candidate.model === ctx.target?.model &&
|
|
25
|
+
candidate.effort === value &&
|
|
26
|
+
ctx.target?.effort === value)) {
|
|
28
27
|
return null;
|
|
29
28
|
}
|
|
30
29
|
const target = ctx.target;
|
|
@@ -65,12 +64,37 @@ const claudeAdapter = {
|
|
|
65
64
|
validValues: [...VALID_CLAUDE_DISPATCH_CEILINGS],
|
|
66
65
|
mechanism: 'model-arg',
|
|
67
66
|
selectionAxis: 'tier',
|
|
68
|
-
compileToDispatchArgs(value) {
|
|
69
|
-
if (isDirectDispatchRoleName(value)
|
|
67
|
+
compileToDispatchArgs(value, role, ctx) {
|
|
68
|
+
if (isDirectDispatchRoleName(value))
|
|
69
|
+
return null;
|
|
70
|
+
const target = ctx.target;
|
|
71
|
+
if (target?.effort) {
|
|
72
|
+
const model = target.model ?? value;
|
|
73
|
+
if (!validateClaudeDispatchCapability({
|
|
74
|
+
model,
|
|
75
|
+
effort: target.effort,
|
|
76
|
+
...(target.capabilityEvidence
|
|
77
|
+
? { capabilityEvidence: target.capabilityEvidence }
|
|
78
|
+
: {}),
|
|
79
|
+
}, ctx.env).valid) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
return {
|
|
83
|
+
variant: buildClaudeEffortVariantName({
|
|
84
|
+
agentName: role === 'reviewer' ? CODEX_REVIEWER_ROLE : CODEX_IMPLEMENTER_ROLE,
|
|
85
|
+
model,
|
|
86
|
+
effort: target.effort,
|
|
87
|
+
}),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
const model = target?.model ?? value;
|
|
91
|
+
if (!target?.model &&
|
|
70
92
|
!VALID_CLAUDE_DISPATCH_CEILINGS.includes(value)) {
|
|
71
93
|
return null;
|
|
72
94
|
}
|
|
73
|
-
|
|
95
|
+
if (!validateClaudeDispatchCapability({ model }).valid)
|
|
96
|
+
return null;
|
|
97
|
+
return { model };
|
|
74
98
|
},
|
|
75
99
|
// Verify only when the request is above the orchestrator tier (upgrade path).
|
|
76
100
|
verifyOnDispatch(value, ctx) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CanonicalAgentDocument } from '../../../agents/canonical/index.js';
|
|
2
|
+
import { type ClaudeCapabilityEvidence } from '../targets.js';
|
|
3
|
+
export type ClaudeRoleOwner = 'user-config' | 'project-config';
|
|
4
|
+
export interface ClaudeMaterializationTarget {
|
|
5
|
+
model: string;
|
|
6
|
+
effort: string;
|
|
7
|
+
capabilityEvidence?: ClaudeCapabilityEvidence;
|
|
8
|
+
owner: ClaudeRoleOwner;
|
|
9
|
+
}
|
|
10
|
+
export interface ClaudeMaterializedAgent {
|
|
11
|
+
roleName: string;
|
|
12
|
+
fileName: string;
|
|
13
|
+
content: string;
|
|
14
|
+
owner: ClaudeRoleOwner;
|
|
15
|
+
target: ClaudeMaterializationTarget;
|
|
16
|
+
}
|
|
17
|
+
export declare function readOatManagedClaudeRole(content: string): {
|
|
18
|
+
roleName: string;
|
|
19
|
+
owner: ClaudeRoleOwner;
|
|
20
|
+
capabilityEvidence?: ClaudeCapabilityEvidence;
|
|
21
|
+
} | null;
|
|
22
|
+
export declare function materializeClaudeAgent(options: {
|
|
23
|
+
agent: CanonicalAgentDocument;
|
|
24
|
+
target: ClaudeMaterializationTarget;
|
|
25
|
+
env?: NodeJS.ProcessEnv;
|
|
26
|
+
}): ClaudeMaterializedAgent;
|
|
27
|
+
export declare function materializeClaudeAgents(options: {
|
|
28
|
+
agents: CanonicalAgentDocument[];
|
|
29
|
+
targets: ClaudeMaterializationTarget[];
|
|
30
|
+
env?: NodeJS.ProcessEnv;
|
|
31
|
+
}): ClaudeMaterializedAgent[];
|
|
32
|
+
export declare function assertNoUnmanagedClaudeAgentCollisions(scopeRoot: string, desiredNames: Iterable<string>): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=materialize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"materialize.d.ts","sourceRoot":"","sources":["../../../../src/providers/claude/codec/materialize.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAIhE,OAAO,EAGL,KAAK,wBAAwB,EAE9B,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG,gBAAgB,CAAC;AAE/D,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;IAC9C,KAAK,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,eAAe,CAAC;IACvB,MAAM,EAAE,2BAA2B,CAAC;CACrC;AAqCD,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,kBAAkB,CAAC,EAAE,wBAAwB,CAAC;CAC/C,GAAG,IAAI,CA8BP;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE;IAC9C,KAAK,EAAE,sBAAsB,CAAC;IAC9B,MAAM,EAAE,2BAA2B,CAAC;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,uBAAuB,CAmC1B;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE;IAC/C,MAAM,EAAE,sBAAsB,EAAE,CAAC;IACjC,OAAO,EAAE,2BAA2B,EAAE,CAAC;IACvC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB,GAAG,uBAAuB,EAAE,CAkB5B;AAWD,wBAAsB,sCAAsC,CAC1D,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,GAC7B,OAAO,CAAC,IAAI,CAAC,CAkDf"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { lstat, readFile, readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { CliError } from '../../../errors/index.js';
|
|
4
|
+
import YAML from 'yaml';
|
|
5
|
+
import { buildClaudeEffortVariantName, normalizeClaudeRoleName, validateClaudeDispatchCapability, } from '../targets.js';
|
|
6
|
+
const DISCOVERY_DIRECTORIES = [
|
|
7
|
+
{ path: '.claude/agents', extension: '.md' },
|
|
8
|
+
{ path: '.cursor/agents', extension: '.md' },
|
|
9
|
+
{ path: '.codex/agents', extension: '.toml' },
|
|
10
|
+
];
|
|
11
|
+
function managedComments(roleName, owner, capabilityEvidence) {
|
|
12
|
+
return [
|
|
13
|
+
'# oat-managed: true',
|
|
14
|
+
`# oat-role: ${roleName}`,
|
|
15
|
+
`# oat-owner: ${owner}`,
|
|
16
|
+
'# oat-provider: claude',
|
|
17
|
+
`# oat-capability-evidence: ${JSON.stringify(capabilityEvidence)}`,
|
|
18
|
+
];
|
|
19
|
+
}
|
|
20
|
+
function frontmatter(content) {
|
|
21
|
+
const match = /^---\n([\s\S]*?)\n---(?:\n|$)/.exec(content);
|
|
22
|
+
if (!match?.[1])
|
|
23
|
+
return null;
|
|
24
|
+
try {
|
|
25
|
+
const value = YAML.parse(match[1]);
|
|
26
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
27
|
+
? { yaml: match[1], value: value }
|
|
28
|
+
: null;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function readOatManagedClaudeRole(content) {
|
|
35
|
+
const parsed = frontmatter(content);
|
|
36
|
+
if (!parsed)
|
|
37
|
+
return null;
|
|
38
|
+
const managed = parsed.yaml.match(/^# oat-managed: true$/gm)?.length === 1;
|
|
39
|
+
const provider = parsed.yaml.match(/^# oat-provider: claude$/gm)?.length === 1;
|
|
40
|
+
const role = /^# oat-role: ([a-z0-9]+(?:-[a-z0-9]+)*)$/m.exec(parsed.yaml)?.[1];
|
|
41
|
+
const owner = /^# oat-owner: (user-config|project-config)$/m.exec(parsed.yaml)?.[1];
|
|
42
|
+
const evidenceJson = /^# oat-capability-evidence: (\{.+\})$/m.exec(parsed.yaml)?.[1];
|
|
43
|
+
let capabilityEvidence;
|
|
44
|
+
if (evidenceJson) {
|
|
45
|
+
try {
|
|
46
|
+
capabilityEvidence = JSON.parse(evidenceJson);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// Malformed evidence makes the role stale but does not hide its ownership.
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return managed && provider && role && owner
|
|
53
|
+
? {
|
|
54
|
+
roleName: role,
|
|
55
|
+
owner,
|
|
56
|
+
...(capabilityEvidence ? { capabilityEvidence } : {}),
|
|
57
|
+
}
|
|
58
|
+
: null;
|
|
59
|
+
}
|
|
60
|
+
export function materializeClaudeAgent(options) {
|
|
61
|
+
const validation = validateClaudeDispatchCapability(options.target, options.env);
|
|
62
|
+
if (!validation.valid)
|
|
63
|
+
throw new CliError(validation.reason ?? 'Invalid Claude target.');
|
|
64
|
+
const capabilityEvidence = validation.capabilityEvidence;
|
|
65
|
+
if (!capabilityEvidence) {
|
|
66
|
+
throw new CliError('Claude effort target has no validated capability evidence.');
|
|
67
|
+
}
|
|
68
|
+
const roleName = buildClaudeEffortVariantName({
|
|
69
|
+
agentName: options.agent.name,
|
|
70
|
+
model: options.target.model,
|
|
71
|
+
effort: options.target.effort,
|
|
72
|
+
});
|
|
73
|
+
const description = `${options.agent.description} Claude-native ${options.target.model}/${options.target.effort} effort variant managed by OAT.`;
|
|
74
|
+
const rendered = YAML.stringify({
|
|
75
|
+
name: roleName,
|
|
76
|
+
description,
|
|
77
|
+
model: options.target.model,
|
|
78
|
+
effort: options.target.effort,
|
|
79
|
+
...(options.agent.tools !== undefined
|
|
80
|
+
? { tools: options.agent.tools }
|
|
81
|
+
: {}),
|
|
82
|
+
}).trimEnd();
|
|
83
|
+
return {
|
|
84
|
+
roleName,
|
|
85
|
+
fileName: `${roleName}.md`,
|
|
86
|
+
content: `---\n${managedComments(roleName, options.target.owner, capabilityEvidence).join('\n')}\n${rendered}\n---\n${options.agent.body}`,
|
|
87
|
+
owner: options.target.owner,
|
|
88
|
+
target: { ...options.target, capabilityEvidence },
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export function materializeClaudeAgents(options) {
|
|
92
|
+
const roles = options.agents.flatMap((agent) => options.targets.map((target) => materializeClaudeAgent({ agent, target, env: options.env })));
|
|
93
|
+
const names = new Set();
|
|
94
|
+
for (const role of roles) {
|
|
95
|
+
if (names.has(role.roleName)) {
|
|
96
|
+
throw new CliError(`Distinct Claude targets produced the same normalized role name ${role.roleName}. Refusing ambiguous role writes.`);
|
|
97
|
+
}
|
|
98
|
+
names.add(role.roleName);
|
|
99
|
+
}
|
|
100
|
+
return roles.sort((left, right) => left.roleName.localeCompare(right.roleName));
|
|
101
|
+
}
|
|
102
|
+
async function pathStats(path) {
|
|
103
|
+
try {
|
|
104
|
+
return await lstat(path);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
if (error.code === 'ENOENT')
|
|
108
|
+
return null;
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export async function assertNoUnmanagedClaudeAgentCollisions(scopeRoot, desiredNames) {
|
|
113
|
+
const desired = new Set(desiredNames);
|
|
114
|
+
for (const { path: directory, extension } of DISCOVERY_DIRECTORIES) {
|
|
115
|
+
const absoluteDirectory = join(scopeRoot, directory);
|
|
116
|
+
const stats = await pathStats(absoluteDirectory);
|
|
117
|
+
if (!stats)
|
|
118
|
+
continue;
|
|
119
|
+
if (!stats.isDirectory() || stats.isSymbolicLink()) {
|
|
120
|
+
throw new CliError(`Claude agent discovery path is unsafe: ${directory}.`);
|
|
121
|
+
}
|
|
122
|
+
for (const fileName of await readdir(absoluteDirectory)) {
|
|
123
|
+
if (!fileName.endsWith(extension))
|
|
124
|
+
continue;
|
|
125
|
+
const path = join(absoluteDirectory, fileName);
|
|
126
|
+
const fileStats = await pathStats(path);
|
|
127
|
+
if (!fileStats?.isFile() || fileStats.isSymbolicLink()) {
|
|
128
|
+
if (desired.has(normalizeClaudeRoleName(fileName.slice(0, -extension.length)))) {
|
|
129
|
+
throw new CliError(`Claude role collision at ${directory}/${fileName}: symbolic links are not writable targets.`);
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
const content = await readFile(path, 'utf8');
|
|
134
|
+
const parsed = extension === '.md' ? frontmatter(content) : null;
|
|
135
|
+
const declared = typeof parsed?.value.name === 'string'
|
|
136
|
+
? normalizeClaudeRoleName(parsed.value.name)
|
|
137
|
+
: null;
|
|
138
|
+
const fileRole = normalizeClaudeRoleName(fileName.slice(0, -extension.length));
|
|
139
|
+
if (!desired.has(fileRole) && (!declared || !desired.has(declared)))
|
|
140
|
+
continue;
|
|
141
|
+
const managed = readOatManagedClaudeRole(content);
|
|
142
|
+
if (directory !== '.claude/agents' ||
|
|
143
|
+
!managed ||
|
|
144
|
+
!desired.has(managed.roleName)) {
|
|
145
|
+
throw new CliError(`Claude role name collision at ${directory}/${fileName}: existing definition is not the matching OAT-managed Claude variant.`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type CanonicalEntry } from '../../../engine/index.js';
|
|
2
|
+
import { type MaterializationApplyResult, type MaterializationContext, type MaterializationExtension, type MaterializationOperation, type MaterializationPlan, type MaterializationWriteOperation } from '../../shared/index.js';
|
|
3
|
+
import { type ClaudeRoleOwner } from './materialize.js';
|
|
4
|
+
export interface ClaudeMaterializationTargetOptions {
|
|
5
|
+
userConfigDir?: string;
|
|
6
|
+
projectPath?: string | null;
|
|
7
|
+
env?: NodeJS.ProcessEnv;
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface ClaudeExtensionPlan extends MaterializationPlan<'claude', 'role', {
|
|
11
|
+
cleanupOwners: ClaudeRoleOwner[];
|
|
12
|
+
isPartialSync: boolean;
|
|
13
|
+
}> {
|
|
14
|
+
operations: (MaterializationWriteOperation<'claude', 'role'> & {
|
|
15
|
+
roleName?: string;
|
|
16
|
+
})[];
|
|
17
|
+
}
|
|
18
|
+
export declare function computeClaudeProjectExtensionPlan(scopeRoot: string, canonicalEntries: CanonicalEntry[], allowedCanonicalPaths?: string[], options?: ClaudeMaterializationTargetOptions): Promise<ClaudeExtensionPlan>;
|
|
19
|
+
export declare function applyClaudeProjectExtensionPlan(scopeRoot: string, plan: ClaudeExtensionPlan): Promise<MaterializationApplyResult>;
|
|
20
|
+
export declare function hasClaudeExtensionChanges(plan: ClaudeExtensionPlan): boolean;
|
|
21
|
+
export declare function summarizeClaudeExtension(plan: ClaudeExtensionPlan): import("../../shared/index.js").MaterializationPlanSummary;
|
|
22
|
+
export declare function toClaudeExtensionOperations(plan: ClaudeExtensionPlan): MaterializationOperation[];
|
|
23
|
+
export declare const claudeMaterializationExtension: MaterializationExtension<ClaudeExtensionPlan, MaterializationContext<ClaudeMaterializationTargetOptions>>;
|
|
24
|
+
//# sourceMappingURL=sync-extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-extension.d.ts","sourceRoot":"","sources":["../../../../src/providers/claude/codec/sync-extension.ts"],"names":[],"mappings":"AAYA,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,eAAe,CAAC;AAIvB,OAAO,EAIL,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,6BAA6B,EACnC,MAAM,mBAAmB,CAAC;AAI3B,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAKvB,MAAM,WAAW,kCAAkC;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAoB,SAAQ,mBAAmB,CAC9D,QAAQ,EACR,MAAM,EACN;IAAE,aAAa,EAAE,eAAe,EAAE,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAC7D;IACC,UAAU,EAAE,CAAC,6BAA6B,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG;QAC7D,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC,EAAE,CAAC;CACN;AAwLD,wBAAsB,iCAAiC,CACrD,SAAS,EAAE,MAAM,EACjB,gBAAgB,EAAE,cAAc,EAAE,EAClC,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAChC,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,mBAAmB,CAAC,CAgH9B;AAyCD,wBAAsB,+BAA+B,CACnD,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,mBAAmB,GACxB,OAAO,CAAC,0BAA0B,CAAC,CA+BrC;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAE5E;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,mBAAmB,0DAEjE;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,mBAAmB,GACxB,wBAAwB,EAAE,CAE5B;AAED,eAAO,MAAM,8BAA8B,EAAE,wBAAwB,CACnE,mBAAmB,EACnB,sBAAsB,CAAC,kCAAkC,CAAC,CAY3D,CAAC"}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { lstat, readFile, readdir, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { basename, dirname, join, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import { parseCanonicalAgentFile } from '../../../agents/canonical/index.js';
|
|
5
|
+
import { normalizeDispatchMatrix, walkDispatchMatrix, } from '../../../config/dispatch-matrix.js';
|
|
6
|
+
import { normalizeProjectPath, resolveActiveProject } from '../../../config/oat-config.js';
|
|
7
|
+
import { resolveEffectiveConfig } from '../../../config/resolve.js';
|
|
8
|
+
import { materializationCanonicalPathAllowed, } from '../../../engine/index.js';
|
|
9
|
+
import { CliError } from '../../../errors/index.js';
|
|
10
|
+
import { ensureDir, fileExists } from '../../../fs/io.js';
|
|
11
|
+
import { validateRealPathWithinScope } from '../../../fs/paths.js';
|
|
12
|
+
import { hasMaterializationChanges, summarizeMaterializationPlan, toMaterializationOperations, } from '../../shared/index.js';
|
|
13
|
+
import YAML from 'yaml';
|
|
14
|
+
import { assertNoUnmanagedClaudeAgentCollisions, materializeClaudeAgents, readOatManagedClaudeRole, } from './materialize.js';
|
|
15
|
+
const SUPPORTED_BASE_ROLES = ['oat-phase-implementer', 'oat-reviewer'];
|
|
16
|
+
function hash(content) {
|
|
17
|
+
return createHash('sha256').update(content).digest('hex');
|
|
18
|
+
}
|
|
19
|
+
function isUserScope(scopeRoot, options) {
|
|
20
|
+
return Boolean(options.userConfigDir &&
|
|
21
|
+
resolve(scopeRoot) === resolve(options.userConfigDir, '..'));
|
|
22
|
+
}
|
|
23
|
+
function collectTargets(value, owner, targets) {
|
|
24
|
+
if (value === undefined || typeof value === 'string')
|
|
25
|
+
return;
|
|
26
|
+
for (const ref of walkDispatchMatrix({ claude: value }, {
|
|
27
|
+
source: owner === 'user-config' ? 'user-config' : 'repo-config',
|
|
28
|
+
pathPrefix: 'workflow.dispatchCeiling.providers',
|
|
29
|
+
})) {
|
|
30
|
+
const target = ref.target;
|
|
31
|
+
if (!target?.model ||
|
|
32
|
+
!target.effort ||
|
|
33
|
+
(target.harness ?? 'claude') !== 'claude') {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
targets.set(`${target.model}\0${target.effort}`, {
|
|
37
|
+
model: target.model,
|
|
38
|
+
effort: target.effort,
|
|
39
|
+
owner,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function frontmatter(content) {
|
|
44
|
+
const match = /^---\n([\s\S]*?)\n---(?:\n|$)/.exec(content);
|
|
45
|
+
if (!match?.[1])
|
|
46
|
+
return null;
|
|
47
|
+
const parsed = YAML.parse(match[1]);
|
|
48
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
49
|
+
? parsed
|
|
50
|
+
: null;
|
|
51
|
+
}
|
|
52
|
+
async function collectProjectStateTargets(scopeRoot, options, targets) {
|
|
53
|
+
const candidate = options.projectPath === undefined
|
|
54
|
+
? (await resolveActiveProject(scopeRoot)).path
|
|
55
|
+
: options.projectPath;
|
|
56
|
+
if (!candidate)
|
|
57
|
+
return;
|
|
58
|
+
const normalized = normalizeProjectPath(scopeRoot, candidate);
|
|
59
|
+
if (!normalized)
|
|
60
|
+
return;
|
|
61
|
+
let projectRoot;
|
|
62
|
+
try {
|
|
63
|
+
projectRoot = (await validateRealPathWithinScope(join(scopeRoot, normalized), scopeRoot)).realPath;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const statePath = join(projectRoot, 'state.md');
|
|
69
|
+
if (!(await fileExists(statePath)))
|
|
70
|
+
return;
|
|
71
|
+
const parsed = frontmatter(await readFile(statePath, 'utf8'));
|
|
72
|
+
const policy = parsed?.['oat_dispatch_policy'];
|
|
73
|
+
if (!policy || typeof policy !== 'object' || Array.isArray(policy))
|
|
74
|
+
return;
|
|
75
|
+
const matrix = normalizeDispatchMatrix(policy['matrix'], {
|
|
76
|
+
pathPrefix: 'oat_dispatch_policy.matrix',
|
|
77
|
+
compatibilityMode: 'project-state',
|
|
78
|
+
});
|
|
79
|
+
collectTargets(matrix.providers.claude, 'project-config', targets);
|
|
80
|
+
}
|
|
81
|
+
async function readTargets(scopeRoot, options) {
|
|
82
|
+
const config = await resolveEffectiveConfig(scopeRoot, options.userConfigDir ?? join(scopeRoot, '.oat', '__no-user-config__'), options.env);
|
|
83
|
+
const targets = new Map();
|
|
84
|
+
if (isUserScope(scopeRoot, options)) {
|
|
85
|
+
collectTargets(config.user.workflow?.dispatchCeiling?.providers?.claude, 'user-config', targets);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
collectTargets(config.shared.workflow?.dispatchCeiling?.providers?.claude, 'project-config', targets);
|
|
89
|
+
collectTargets(config.local.workflow?.dispatchCeiling?.providers?.claude, 'project-config', targets);
|
|
90
|
+
await collectProjectStateTargets(scopeRoot, options, targets);
|
|
91
|
+
}
|
|
92
|
+
return [...targets.values()].sort((left, right) => `${left.model}/${left.effort}`.localeCompare(`${right.model}/${right.effort}`));
|
|
93
|
+
}
|
|
94
|
+
async function optionalFile(path) {
|
|
95
|
+
return (await fileExists(path)) ? readFile(path, 'utf8') : null;
|
|
96
|
+
}
|
|
97
|
+
async function staleRoles(scopeRoot, desired, owners, baseRoles) {
|
|
98
|
+
let files = [];
|
|
99
|
+
try {
|
|
100
|
+
files = await readdir(join(scopeRoot, '.claude', 'agents'));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// The managed directory does not exist before the first materialization.
|
|
104
|
+
}
|
|
105
|
+
const stale = [];
|
|
106
|
+
for (const file of files) {
|
|
107
|
+
if (!file.endsWith('.md'))
|
|
108
|
+
continue;
|
|
109
|
+
const roleName = basename(file, '.md');
|
|
110
|
+
if (desired.has(roleName))
|
|
111
|
+
continue;
|
|
112
|
+
const content = await optionalFile(join(scopeRoot, '.claude', 'agents', file));
|
|
113
|
+
const managed = content ? readOatManagedClaudeRole(content) : null;
|
|
114
|
+
const matchesBaseRole = !baseRoles ||
|
|
115
|
+
[...baseRoles].some((baseRole) => roleName.startsWith(`${baseRole}-claude-`));
|
|
116
|
+
if (matchesBaseRole &&
|
|
117
|
+
managed?.roleName === roleName &&
|
|
118
|
+
owners.includes(managed.owner))
|
|
119
|
+
stale.push(roleName);
|
|
120
|
+
}
|
|
121
|
+
return stale.sort();
|
|
122
|
+
}
|
|
123
|
+
function removedSupportedBaseRoles(entries, allowedCanonicalPaths) {
|
|
124
|
+
if (!allowedCanonicalPaths?.length)
|
|
125
|
+
return new Set();
|
|
126
|
+
const present = new Set(entries
|
|
127
|
+
.filter((entry) => entry.type === 'agent' && entry.isFile)
|
|
128
|
+
.map((entry) => entry.name.replace(/\.md$/, '')));
|
|
129
|
+
return new Set(SUPPORTED_BASE_ROLES.filter((role) => allowedCanonicalPaths.includes(`.agents/agents/${role}.md`) &&
|
|
130
|
+
!present.has(role)));
|
|
131
|
+
}
|
|
132
|
+
export async function computeClaudeProjectExtensionPlan(scopeRoot, canonicalEntries, allowedCanonicalPaths, options = {}) {
|
|
133
|
+
const partial = Boolean(allowedCanonicalPaths?.length);
|
|
134
|
+
const cleanupOwners = isUserScope(scopeRoot, options)
|
|
135
|
+
? ['user-config']
|
|
136
|
+
: ['project-config'];
|
|
137
|
+
const empty = () => ({
|
|
138
|
+
provider: 'claude',
|
|
139
|
+
operations: [],
|
|
140
|
+
managedEntries: [],
|
|
141
|
+
aggregateHash: hash(''),
|
|
142
|
+
metadata: { cleanupOwners, isPartialSync: partial },
|
|
143
|
+
});
|
|
144
|
+
if (options.enabled === false)
|
|
145
|
+
return empty();
|
|
146
|
+
const entries = canonicalEntries.filter((entry) => materializationCanonicalPathAllowed(scopeRoot, entry, allowedCanonicalPaths));
|
|
147
|
+
const removedBaseRoles = removedSupportedBaseRoles(entries, allowedCanonicalPaths);
|
|
148
|
+
if (partial && entries.length === 0 && removedBaseRoles.size === 0)
|
|
149
|
+
return empty();
|
|
150
|
+
const targets = await readTargets(scopeRoot, options);
|
|
151
|
+
const agents = [];
|
|
152
|
+
for (const entry of entries) {
|
|
153
|
+
if (entry.type !== 'agent' || !entry.isFile || !entry.name.endsWith('.md'))
|
|
154
|
+
continue;
|
|
155
|
+
const agent = await parseCanonicalAgentFile(entry.canonicalPath);
|
|
156
|
+
if (SUPPORTED_BASE_ROLES.includes(agent.name))
|
|
157
|
+
agents.push(agent);
|
|
158
|
+
}
|
|
159
|
+
if (!partial && isUserScope(scopeRoot, options) && targets.length > 0) {
|
|
160
|
+
const present = new Set(agents.map(({ name }) => name));
|
|
161
|
+
const missing = SUPPORTED_BASE_ROLES.filter((name) => !present.has(name));
|
|
162
|
+
if (missing.length > 0) {
|
|
163
|
+
throw new CliError(`Bundled managed Claude role definitions are unavailable for user sync: ${missing.join(', ')}. Refusing stale user-role cleanup.`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const roles = materializeClaudeAgents({
|
|
167
|
+
agents,
|
|
168
|
+
targets,
|
|
169
|
+
env: options.env,
|
|
170
|
+
});
|
|
171
|
+
const desired = new Set(roles.map(({ roleName }) => roleName));
|
|
172
|
+
await assertNoUnmanagedClaudeAgentCollisions(scopeRoot, desired);
|
|
173
|
+
const stale = partial
|
|
174
|
+
? await staleRoles(scopeRoot, desired, cleanupOwners, removedBaseRoles)
|
|
175
|
+
: await staleRoles(scopeRoot, desired, cleanupOwners);
|
|
176
|
+
const operations = [];
|
|
177
|
+
for (const role of roles) {
|
|
178
|
+
const relativePath = `.claude/agents/${role.fileName}`;
|
|
179
|
+
const existing = await optionalFile(join(scopeRoot, relativePath));
|
|
180
|
+
if (existing === null) {
|
|
181
|
+
operations.push({
|
|
182
|
+
provider: 'claude',
|
|
183
|
+
action: 'create',
|
|
184
|
+
target: 'role',
|
|
185
|
+
path: relativePath,
|
|
186
|
+
reason: 'managed Claude effort variant missing',
|
|
187
|
+
entryName: role.roleName,
|
|
188
|
+
roleName: role.roleName,
|
|
189
|
+
content: role.content,
|
|
190
|
+
});
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const managed = readOatManagedClaudeRole(existing);
|
|
194
|
+
if (!managed ||
|
|
195
|
+
managed.roleName !== role.roleName ||
|
|
196
|
+
!cleanupOwners.includes(managed.owner)) {
|
|
197
|
+
throw new CliError(`Refusing to update Claude role ${role.roleName}: existing file is unmanaged or has incompatible ownership.`);
|
|
198
|
+
}
|
|
199
|
+
const current = existing.trimEnd() === role.content.trimEnd();
|
|
200
|
+
operations.push({
|
|
201
|
+
provider: 'claude',
|
|
202
|
+
action: current ? 'skip' : 'update',
|
|
203
|
+
target: 'role',
|
|
204
|
+
path: relativePath,
|
|
205
|
+
reason: current
|
|
206
|
+
? 'managed Claude effort variant already in sync'
|
|
207
|
+
: 'managed Claude effort variant differs from desired state',
|
|
208
|
+
entryName: role.roleName,
|
|
209
|
+
roleName: role.roleName,
|
|
210
|
+
...(current ? {} : { content: role.content }),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
for (const roleName of stale) {
|
|
214
|
+
operations.push({
|
|
215
|
+
provider: 'claude',
|
|
216
|
+
action: 'remove',
|
|
217
|
+
target: 'role',
|
|
218
|
+
path: `.claude/agents/${roleName}.md`,
|
|
219
|
+
reason: 'stale managed Claude effort variant removed',
|
|
220
|
+
entryName: roleName,
|
|
221
|
+
roleName,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return {
|
|
225
|
+
provider: 'claude',
|
|
226
|
+
operations,
|
|
227
|
+
managedEntries: [...desired, ...stale],
|
|
228
|
+
aggregateHash: hash(roles.map(({ content }) => content).join('\0')),
|
|
229
|
+
metadata: { cleanupOwners, isPartialSync: partial },
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
async function stats(path) {
|
|
233
|
+
try {
|
|
234
|
+
return await lstat(path);
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
if (error.code === 'ENOENT')
|
|
238
|
+
return null;
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
async function assertSafePath(scopeRoot, path) {
|
|
243
|
+
const root = resolve(scopeRoot);
|
|
244
|
+
const rel = relative(root, path);
|
|
245
|
+
if (rel === '..' ||
|
|
246
|
+
rel.startsWith(`..${sep}`) ||
|
|
247
|
+
resolve(root, rel) !== path) {
|
|
248
|
+
throw new CliError(`Claude materialization path escapes the sync scope: ${path}`);
|
|
249
|
+
}
|
|
250
|
+
let current = root;
|
|
251
|
+
for (const part of rel.replaceAll('\\', '/').split('/').slice(0, -1)) {
|
|
252
|
+
current = join(current, part);
|
|
253
|
+
const value = await stats(current);
|
|
254
|
+
if (!value)
|
|
255
|
+
break;
|
|
256
|
+
if (value.isSymbolicLink() || !value.isDirectory()) {
|
|
257
|
+
throw new CliError(`Claude materialization parent is unsafe: ${relative(root, current)}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
if ((await stats(path))?.isSymbolicLink()) {
|
|
261
|
+
throw new CliError(`Claude materialization target is a symbolic link: ${rel}`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
export async function applyClaudeProjectExtensionPlan(scopeRoot, plan) {
|
|
265
|
+
const operations = [];
|
|
266
|
+
for (const operation of plan.operations) {
|
|
267
|
+
if (operation.action === 'skip') {
|
|
268
|
+
operations.push({ ...operation, status: 'current' });
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
const path = resolve(scopeRoot, operation.path);
|
|
272
|
+
try {
|
|
273
|
+
await assertSafePath(scopeRoot, path);
|
|
274
|
+
if (operation.action === 'remove')
|
|
275
|
+
await rm(path, { force: true });
|
|
276
|
+
else {
|
|
277
|
+
await ensureDir(dirname(path));
|
|
278
|
+
await writeFile(path, operation.content ?? '', 'utf8');
|
|
279
|
+
}
|
|
280
|
+
operations.push({ ...operation, status: 'changed' });
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
operations.push({
|
|
284
|
+
...operation,
|
|
285
|
+
status: 'failed',
|
|
286
|
+
failure: 'Materialization failed; inspect local verbose diagnostics and retry sync.',
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
applied: operations.filter(({ status }) => status === 'changed').length,
|
|
292
|
+
failed: operations.filter(({ status }) => status === 'failed').length,
|
|
293
|
+
skipped: operations.filter(({ status }) => status === 'current').length,
|
|
294
|
+
operations,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
export function hasClaudeExtensionChanges(plan) {
|
|
298
|
+
return hasMaterializationChanges(plan);
|
|
299
|
+
}
|
|
300
|
+
export function summarizeClaudeExtension(plan) {
|
|
301
|
+
return summarizeMaterializationPlan(plan);
|
|
302
|
+
}
|
|
303
|
+
export function toClaudeExtensionOperations(plan) {
|
|
304
|
+
return toMaterializationOperations(plan);
|
|
305
|
+
}
|
|
306
|
+
export const claudeMaterializationExtension = {
|
|
307
|
+
provider: 'claude',
|
|
308
|
+
computePlan(context) {
|
|
309
|
+
return computeClaudeProjectExtensionPlan(context.scopeRoot, context.canonicalEntries, context.allowedCanonicalPaths, context.options);
|
|
310
|
+
},
|
|
311
|
+
applyPlan: applyClaudeProjectExtensionPlan,
|
|
312
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type GenericDispatchRecord } from '../identity/generic-dispatch-record.js';
|
|
2
|
+
import { type ClaudeCapabilityEvidence } from './targets.js';
|
|
3
|
+
export interface AcceptedClaudeLaunchEnvelope {
|
|
4
|
+
schemaVersion: 1;
|
|
5
|
+
provider: 'claude';
|
|
6
|
+
resolverRole: 'implementer' | 'reviewer';
|
|
7
|
+
baseRole: 'oat-phase-implementer' | 'oat-reviewer';
|
|
8
|
+
variant: string;
|
|
9
|
+
model: string;
|
|
10
|
+
capabilityEvidence: ClaudeCapabilityEvidence;
|
|
11
|
+
effort: string;
|
|
12
|
+
policy: string;
|
|
13
|
+
ceiling: string;
|
|
14
|
+
payload: {
|
|
15
|
+
variant: string;
|
|
16
|
+
model?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validate the managed resolver result against the generated provider role and
|
|
21
|
+
* the exact payload that will be launched. This is the production boundary
|
|
22
|
+
* used by the project dispatch-record producer for managed Claude dispatches.
|
|
23
|
+
*/
|
|
24
|
+
export declare function acceptClaudeLaunchEnvelope(input: {
|
|
25
|
+
resolution: unknown;
|
|
26
|
+
definition: string;
|
|
27
|
+
launch: unknown;
|
|
28
|
+
}): AcceptedClaudeLaunchEnvelope;
|
|
29
|
+
/** Build configured invocation evidence only from an accepted launch envelope. */
|
|
30
|
+
export declare function buildClaudeDispatchRecord(input: {
|
|
31
|
+
envelope: AcceptedClaudeLaunchEnvelope;
|
|
32
|
+
recordBase: unknown;
|
|
33
|
+
}): GenericDispatchRecord;
|
|
34
|
+
//# sourceMappingURL=dispatch-envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch-envelope.d.ts","sourceRoot":"","sources":["../../../src/providers/claude/dispatch-envelope.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,6CAA6C,CAAC;AAKrD,OAAO,EAEL,KAAK,wBAAwB,EAE9B,MAAM,WAAW,CAAC;AA4FnB,MAAM,WAAW,4BAA4B;IAC3C,aAAa,EAAE,CAAC,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,YAAY,EAAE,aAAa,GAAG,UAAU,CAAC;IACzC,QAAQ,EAAE,uBAAuB,GAAG,cAAc,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,EAAE,wBAAwB,CAAC;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAsCD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IAChD,UAAU,EAAE,OAAO,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB,GAAG,4BAA4B,CA6F/B;AAmBD,kFAAkF;AAClF,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,QAAQ,EAAE,4BAA4B,CAAC;IACvC,UAAU,EAAE,OAAO,CAAC;CACrB,GAAG,qBAAqB,CAoDxB"}
|