@williambeto/ai-workflow 2.8.0 → 2.8.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/CHANGELOG.md +41 -0
- package/bin/ai-workflow.js +193 -49
- package/bin/ai-workflow.js.map +1 -1
- package/{chunk-LI76KI7C.js → chunk-4FI5ODAM.js} +259 -296
- package/{chunk-Y4RLP6ZM.js → chunk-GLYX3HEY.js} +353 -39
- package/{chunk-XW747GIG.js → chunk-H7GIKXFO.js} +339 -14
- package/core/index.d.ts +20 -1
- package/core/index.js +2 -2
- package/dist-assets/agents/atlas.md +25 -6
- package/dist-assets/commands/atlas.md +7 -2
- package/dist-assets/docs/QUICKSTART.md +10 -1
- package/dist-assets/docs/compatibility/provider-usage.md +16 -1
- package/dist-assets/docs/compatibility/runtime-matrix.md +13 -2
- package/dist-assets/docs/policies/06-FINAL_EVIDENCE_CONTRACT.md +11 -1
- package/dist-assets/docs/policies/SKILLS_COMMON_GOVERNANCE.md +16 -0
- package/dist-assets/schemas/README.md +4 -0
- package/dist-assets/schemas/evidence.schema.json +60 -1
- package/package.json +1 -1
- package/{validate-IEHLAVZ6.js → validate-DDKN6ORS.js} +3 -3
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ArtifactFidelityGate,
|
|
3
|
-
DeliveryDecisionEngine
|
|
4
|
-
|
|
3
|
+
DeliveryDecisionEngine,
|
|
4
|
+
RequestRouter
|
|
5
|
+
} from "./chunk-H7GIKXFO.js";
|
|
5
6
|
|
|
6
7
|
// src/core/package-assets.ts
|
|
7
8
|
import { fileURLToPath } from "url";
|
|
@@ -94,21 +95,145 @@ var AGENT_PROMPT_CONTRACTS = {
|
|
|
94
95
|
Sage: "Act as Sage, the independent validation agent. Audit the implementation against requirements, inspect evidence, and report concrete pass/fail findings.",
|
|
95
96
|
Phoenix: "Act as Phoenix, the bounded remediation agent. Remediate only concrete findings, keep attempts bounded, and stop when no progress is made."
|
|
96
97
|
};
|
|
98
|
+
function buildPromptFallback(agent, message, orchestratedChild = false) {
|
|
99
|
+
if (agent === "Astra") {
|
|
100
|
+
return [
|
|
101
|
+
"You are Atlas, the AI Workflow Kit coordinator running under Atlas permissions.",
|
|
102
|
+
"Delegate the implementation exactly once to the configured Astra agent using the task tool. Do not edit workspace files yourself and do not pretend to be Astra.",
|
|
103
|
+
orchestratedChild ? "The parent execute process already owns branch safety, validation, evidence, and finalization. Do not run git branch/status, collect-evidence, handoff, or another execute workflow." : "Keep coordination minimal and let Astra own every requested workspace mutation.",
|
|
104
|
+
"Ask Astra to make the smallest scoped change and run only proportional validation: docs integrity for docs, a focused behavior test for simple code, and tests plus build for normal React work. Screenshots, README changes, Sage, and Phoenix are conditional, not default.",
|
|
105
|
+
"Return Astra's observed result without adding a second implementation or finalization pass.",
|
|
106
|
+
"",
|
|
107
|
+
"User request:",
|
|
108
|
+
message
|
|
109
|
+
].join("\n");
|
|
110
|
+
}
|
|
111
|
+
return `${AGENT_PROMPT_CONTRACTS[agent]}
|
|
112
|
+
|
|
113
|
+
Runtime agent selection note: requested actor '${agent}' could not be applied with --agent because this OpenCode runtime does not support it. Continue under this bounded prompt contract and preserve all AI Workflow Kit safety rules.
|
|
114
|
+
|
|
115
|
+
User request:
|
|
116
|
+
${message}`;
|
|
117
|
+
}
|
|
97
118
|
function extractSdkExecution(data, requestedAgent) {
|
|
98
119
|
const parts = data?.parts || [];
|
|
99
120
|
const output = parts.filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join("");
|
|
100
121
|
const commandsRun = parts.filter((part) => part.type === "tool").map((part) => part.state?.input?.command ?? part.state?.input?.CommandLine).filter((command) => typeof command === "string");
|
|
122
|
+
const commandEvents = commandsRun.map((command) => ({
|
|
123
|
+
command,
|
|
124
|
+
tool: "sdk-tool",
|
|
125
|
+
status: "UNKNOWN",
|
|
126
|
+
exitCode: null,
|
|
127
|
+
source: "sdk"
|
|
128
|
+
}));
|
|
101
129
|
const appliedAgent = typeof data?.info?.agent === "string" ? data.info.agent : null;
|
|
102
130
|
const confirmed = appliedAgent === requestedAgent;
|
|
103
131
|
return {
|
|
104
132
|
success: !data?.info?.error && confirmed,
|
|
105
133
|
commandsRun,
|
|
134
|
+
commandEvents,
|
|
106
135
|
eventCount: parts.length,
|
|
107
136
|
runtimeAgentApplied: appliedAgent,
|
|
108
137
|
runtimeActorConfirmation: confirmed ? "confirmed" : "unavailable",
|
|
109
138
|
output
|
|
110
139
|
};
|
|
111
140
|
}
|
|
141
|
+
function extractCommandEvents(event) {
|
|
142
|
+
const calls = Array.isArray(event?.part?.toolCalls) ? event.part.toolCalls : event?.type === "tool" || event?.type === "tool_use" || event?.type === "tool_result" ? [event.part || event] : [];
|
|
143
|
+
return calls.flatMap((call) => {
|
|
144
|
+
const input = call?.args || call?.input || call?.state?.input || call?.part?.state?.input || {};
|
|
145
|
+
const command = input.command ?? input.CommandLine ?? call?.command;
|
|
146
|
+
if (typeof command !== "string" || !command.trim()) return [];
|
|
147
|
+
const rawExit = call?.exitCode ?? call?.output?.exitCode ?? call?.state?.metadata?.exitCode ?? event?.exitCode;
|
|
148
|
+
const exitCode = typeof rawExit === "number" ? rawExit : null;
|
|
149
|
+
return [{
|
|
150
|
+
command: command.trim(),
|
|
151
|
+
tool: String(call?.name || call?.tool || event?.tool || "command"),
|
|
152
|
+
status: exitCode === null ? "UNKNOWN" : exitCode === 0 ? "PASS" : "FAIL",
|
|
153
|
+
exitCode,
|
|
154
|
+
source: "json-event"
|
|
155
|
+
}];
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function extractDelegatedAgents(event) {
|
|
159
|
+
const calls = Array.isArray(event?.part?.toolCalls) ? event.part.toolCalls : ["tool", "tool_use"].includes(event?.type) ? [event?.part || event] : [];
|
|
160
|
+
const delegatedAgents = [];
|
|
161
|
+
for (const call of calls) {
|
|
162
|
+
const tool = String(call?.name || call?.tool || event?.tool || "").toLowerCase();
|
|
163
|
+
if (tool !== "task") continue;
|
|
164
|
+
const input = call?.args || call?.input || call?.state?.input || call?.part?.state?.input || {};
|
|
165
|
+
const delegated = input.subagent_type ?? input.agent ?? input.subagent ?? input.agentName;
|
|
166
|
+
if (typeof delegated === "string" && delegated.trim()) delegatedAgents.push(delegated.trim());
|
|
167
|
+
}
|
|
168
|
+
return delegatedAgents;
|
|
169
|
+
}
|
|
170
|
+
function countAstraCompletionMarkers(value) {
|
|
171
|
+
return [...String(value || "").matchAll(/(?:✓|✔).*\bAstra Agent\b/gi)].length;
|
|
172
|
+
}
|
|
173
|
+
var MUTATING_GIT_COMMANDS = /* @__PURE__ */ new Set([
|
|
174
|
+
"add",
|
|
175
|
+
"am",
|
|
176
|
+
"apply",
|
|
177
|
+
"bisect",
|
|
178
|
+
"checkout",
|
|
179
|
+
"cherry-pick",
|
|
180
|
+
"clean",
|
|
181
|
+
"clone",
|
|
182
|
+
"commit",
|
|
183
|
+
"fetch",
|
|
184
|
+
"gc",
|
|
185
|
+
"init",
|
|
186
|
+
"merge",
|
|
187
|
+
"mv",
|
|
188
|
+
"notes",
|
|
189
|
+
"pull",
|
|
190
|
+
"push",
|
|
191
|
+
"rebase",
|
|
192
|
+
"reset",
|
|
193
|
+
"restore",
|
|
194
|
+
"revert",
|
|
195
|
+
"rm",
|
|
196
|
+
"stash",
|
|
197
|
+
"switch",
|
|
198
|
+
"update-index"
|
|
199
|
+
]);
|
|
200
|
+
function gitCommandIsDestructive(command) {
|
|
201
|
+
for (const match of command.matchAll(/\bgit\b([^;&|]*)/gi)) {
|
|
202
|
+
const tokens = match[1].trim().split(/\s+/).filter(Boolean);
|
|
203
|
+
while (tokens[0]?.startsWith("-")) {
|
|
204
|
+
const option = tokens.shift();
|
|
205
|
+
if (["-C", "--git-dir", "--work-tree", "--namespace"].includes(option || "")) tokens.shift();
|
|
206
|
+
}
|
|
207
|
+
const subcommand = tokens.shift()?.toLowerCase();
|
|
208
|
+
if (!subcommand) continue;
|
|
209
|
+
if (MUTATING_GIT_COMMANDS.has(subcommand)) return true;
|
|
210
|
+
if (subcommand === "branch") {
|
|
211
|
+
if (tokens.length === 0) continue;
|
|
212
|
+
const mutatingBranchFlag = tokens.some(
|
|
213
|
+
(token) => /^(?:-[dDmMcC]|--(?:delete|move|copy|edit-description|set-upstream-to|unset-upstream))(?:=|$)/.test(token)
|
|
214
|
+
);
|
|
215
|
+
if (mutatingBranchFlag) return true;
|
|
216
|
+
const first = tokens[0];
|
|
217
|
+
const readOnlyBranchFlag = /^(?:--(?:show-current|list|all|remotes|contains|no-contains|merged|no-merged|points-at|format|sort|column|no-column|color|no-color)(?:=|$)|-[larv](?:$|v$))/.test(first);
|
|
218
|
+
if (!readOnlyBranchFlag) return true;
|
|
219
|
+
}
|
|
220
|
+
if (subcommand === "tag") {
|
|
221
|
+
if (tokens.length === 0) continue;
|
|
222
|
+
const first = tokens[0];
|
|
223
|
+
if (!/^(?:--(?:list|contains|no-contains|merged|no-merged|points-at|format|sort)(?:=|$)|-[ln])/.test(first)) return true;
|
|
224
|
+
}
|
|
225
|
+
if (subcommand === "remote" && tokens.length > 0 && !/^(?:-v|--verbose|show|get-url)$/.test(tokens[0])) return true;
|
|
226
|
+
if (subcommand === "worktree" && tokens[0] !== "list") return true;
|
|
227
|
+
}
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
function isDestructiveCommand(command) {
|
|
231
|
+
if (/(^|[^<])(?:>>|>)/.test(command)) return true;
|
|
232
|
+
if (/\b(?:touch|rm|mkdir|cp|mv|chmod|chown|tee)\b/.test(command)) return true;
|
|
233
|
+
if (/\bsed\b[^;&|]*(?:\s-i[^\s]*|\s--in-place(?:=|\s|$))/.test(command)) return true;
|
|
234
|
+
if (/\bawk\b[^;&|]*\s-i\s*inplace\b/.test(command)) return true;
|
|
235
|
+
return gitCommandIsDestructive(command);
|
|
236
|
+
}
|
|
112
237
|
var OpenCodeAdapter = class {
|
|
113
238
|
cwd;
|
|
114
239
|
constructor({ cwd = process.cwd() } = {}) {
|
|
@@ -148,7 +273,7 @@ var OpenCodeAdapter = class {
|
|
|
148
273
|
/**
|
|
149
274
|
* Runs opencode with a prompt and options.
|
|
150
275
|
*/
|
|
151
|
-
async execute(message, { agent = null, model = null, readOnly = false, fastTrack = false, requireActorConfirmation = false } = {}) {
|
|
276
|
+
async execute(message, { agent = null, model = null, readOnly = false, fastTrack = false, requireActorConfirmation = false, orchestratedChild = false } = {}) {
|
|
152
277
|
const inspection = await this.inspect();
|
|
153
278
|
const isSpecializedAgent = agent && ["Nexus", "Orion", "Astra", "Sage", "Phoenix"].includes(agent);
|
|
154
279
|
if (!readOnly) {
|
|
@@ -194,13 +319,11 @@ var OpenCodeAdapter = class {
|
|
|
194
319
|
};
|
|
195
320
|
}
|
|
196
321
|
const usePromptFallback = Boolean(isSpecializedAgent && !inspection.supports.agent && agent);
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
Runtime agent selection note: requested actor '${agent}' could not be applied with --agent because this OpenCode runtime does not support it. Continue as that actor by prompt contract and preserve all AI Workflow Kit safety rules.
|
|
322
|
+
const agentMessage = usePromptFallback ? buildPromptFallback(agent, message, orchestratedChild) : message;
|
|
323
|
+
const runtimeMessage = orchestratedChild ? `${agentMessage}
|
|
200
324
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const runtimeAgentSelectionMode = isSpecializedAgent ? usePromptFallback ? "prompt-fallback" : "explicit" : "default";
|
|
325
|
+
AIWK_ORCHESTRATED_CHILD: The parent execute process exclusively owns collect-evidence, handoff, and finalization. Do not invoke those operations or start another execute workflow.` : agentMessage;
|
|
326
|
+
const runtimeAgentSelectionMode = isSpecializedAgent ? usePromptFallback && agent === "Astra" ? "atlas-delegation-fallback" : usePromptFallback ? "prompt-fallback" : "explicit" : "default";
|
|
204
327
|
const runWithSdk = async (targetCwd) => {
|
|
205
328
|
if (!agent) {
|
|
206
329
|
return {
|
|
@@ -220,7 +343,15 @@ ${message}` : message;
|
|
|
220
343
|
let server;
|
|
221
344
|
try {
|
|
222
345
|
const { createOpencode } = await import("@opencode-ai/sdk/v2");
|
|
223
|
-
const
|
|
346
|
+
const previousFinalizationOwner = process.env.AI_WORKFLOW_FINALIZATION_OWNER;
|
|
347
|
+
if (orchestratedChild) process.env.AI_WORKFLOW_FINALIZATION_OWNER = "execute";
|
|
348
|
+
let runtime;
|
|
349
|
+
try {
|
|
350
|
+
runtime = await createOpencode({ port: 0, timeout: 1e4 });
|
|
351
|
+
} finally {
|
|
352
|
+
if (previousFinalizationOwner === void 0) delete process.env.AI_WORKFLOW_FINALIZATION_OWNER;
|
|
353
|
+
else process.env.AI_WORKFLOW_FINALIZATION_OWNER = previousFinalizationOwner;
|
|
354
|
+
}
|
|
224
355
|
server = runtime.server;
|
|
225
356
|
const permissions = readOnly ? [
|
|
226
357
|
{ permission: "edit", pattern: "*", action: "deny" },
|
|
@@ -238,7 +369,7 @@ ${message}` : message;
|
|
|
238
369
|
sessionID: session.data.id,
|
|
239
370
|
directory: targetCwd,
|
|
240
371
|
agent,
|
|
241
|
-
parts: [{ type: "text", text:
|
|
372
|
+
parts: [{ type: "text", text: runtimeMessage }]
|
|
242
373
|
}, { throwOnError: true });
|
|
243
374
|
const extracted = extractSdkExecution(response.data, agent);
|
|
244
375
|
if (extracted.output) process.stdout.write(extracted.output);
|
|
@@ -283,6 +414,7 @@ ${message}` : message;
|
|
|
283
414
|
console.log(`[RUNTIME] Delegating to OpenCode: opencode ${args.map((a) => a.includes(" ") ? `"${a}"` : a).join(" ")}`);
|
|
284
415
|
const child = spawn("opencode", args, {
|
|
285
416
|
cwd: targetCwd,
|
|
417
|
+
env: orchestratedChild ? { ...process.env, AI_WORKFLOW_FINALIZATION_OWNER: "execute" } : process.env,
|
|
286
418
|
stdio: ["ignore", "pipe", "inherit"]
|
|
287
419
|
// Inherit stderr to show warnings directly
|
|
288
420
|
});
|
|
@@ -291,35 +423,65 @@ ${message}` : message;
|
|
|
291
423
|
terminal: false
|
|
292
424
|
});
|
|
293
425
|
const commandsRun = [];
|
|
426
|
+
const commandEvents = [];
|
|
294
427
|
let eventCount = 0;
|
|
295
428
|
let output = "";
|
|
296
429
|
let confirmedAgent = null;
|
|
430
|
+
let delegatedAgent = null;
|
|
431
|
+
let astraTaskInvocations = 0;
|
|
432
|
+
let astraCompletionMarkers = 0;
|
|
297
433
|
rl.on("line", (line) => {
|
|
298
434
|
const trimmed = line.trim();
|
|
299
435
|
if (!trimmed) return;
|
|
300
436
|
try {
|
|
301
437
|
const event = JSON.parse(trimmed);
|
|
302
438
|
eventCount++;
|
|
439
|
+
const observedDelegations = extractDelegatedAgents(event);
|
|
440
|
+
astraTaskInvocations += observedDelegations.filter((value) => value === "Astra").length;
|
|
441
|
+
if (observedDelegations.includes("Astra")) delegatedAgent = "Astra";
|
|
442
|
+
for (const observation of extractCommandEvents(event)) {
|
|
443
|
+
commandEvents.push(observation);
|
|
444
|
+
if (!commandsRun.includes(observation.command)) commandsRun.push(observation.command);
|
|
445
|
+
}
|
|
446
|
+
if (readOnly) {
|
|
447
|
+
const unsafe = commandEvents.find((item) => isDestructiveCommand(item.command));
|
|
448
|
+
if (unsafe) {
|
|
449
|
+
child.kill();
|
|
450
|
+
resolve2({
|
|
451
|
+
success: false,
|
|
452
|
+
commandsRun,
|
|
453
|
+
commandEvents,
|
|
454
|
+
eventCount,
|
|
455
|
+
error: `Read-only confinement violation: command '${unsafe.command}' attempted write/modify operation during read-only task.`,
|
|
456
|
+
runtimeAgentRequested: agent || null,
|
|
457
|
+
runtimeAgentApplied: null,
|
|
458
|
+
runtimeAgentSupported: inspection.supports.agent,
|
|
459
|
+
runtimeAgentSelectionMode,
|
|
460
|
+
runtimeActorConfirmation: confirmedAgent ? "confirmed" : "unavailable",
|
|
461
|
+
output
|
|
462
|
+
});
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
303
466
|
if (event.type === "agent_identity" && event.confirmed === true && typeof event.agent === "string") {
|
|
304
467
|
confirmedAgent = event.agent;
|
|
305
468
|
}
|
|
306
469
|
if (event.type === "text" && event.part?.text) {
|
|
307
470
|
process.stdout.write(event.part.text);
|
|
308
471
|
output += event.part.text;
|
|
472
|
+
const markers = countAstraCompletionMarkers(event.part.text);
|
|
473
|
+
astraCompletionMarkers += markers;
|
|
474
|
+
if (markers > 0) delegatedAgent = "Astra";
|
|
309
475
|
}
|
|
310
476
|
if (event.type === "step_start" && event.part?.toolCalls) {
|
|
311
477
|
for (const call of event.part.toolCalls) {
|
|
312
|
-
if (call.name === "run_command" && call.args?.CommandLine) {
|
|
313
|
-
commandsRun.push(call.args.CommandLine);
|
|
314
|
-
}
|
|
315
478
|
if (readOnly) {
|
|
316
479
|
const name = call.name || "";
|
|
317
480
|
const isWriteTool = name.startsWith("write_") || name.includes("write") || name.includes("replace") || name.includes("edit") || name.includes("delete") || name.includes("remove");
|
|
318
481
|
let isDestructiveGit = false;
|
|
319
482
|
if (name === "run_command" && call.args?.CommandLine) {
|
|
320
483
|
const cmd = call.args.CommandLine;
|
|
321
|
-
|
|
322
|
-
if (destPattern.test(cmd)) {
|
|
484
|
+
if (isDestructiveCommand(cmd)) {
|
|
323
485
|
isDestructiveGit = true;
|
|
324
486
|
}
|
|
325
487
|
}
|
|
@@ -346,19 +508,38 @@ ${message}` : message;
|
|
|
346
508
|
}
|
|
347
509
|
} catch {
|
|
348
510
|
console.log(trimmed);
|
|
511
|
+
output += `${trimmed}
|
|
512
|
+
`;
|
|
513
|
+
const shellCommand = trimmed.match(/^\$\s+(.+)$/)?.[1];
|
|
514
|
+
if (shellCommand) {
|
|
515
|
+
const observation = { command: shellCommand, tool: "shell", status: "UNKNOWN", exitCode: null, source: "text-output" };
|
|
516
|
+
commandEvents.push(observation);
|
|
517
|
+
if (!commandsRun.includes(shellCommand)) commandsRun.push(shellCommand);
|
|
518
|
+
}
|
|
519
|
+
const markers = usePromptFallback && agent === "Astra" ? countAstraCompletionMarkers(trimmed) : 0;
|
|
520
|
+
if (markers > 0) {
|
|
521
|
+
astraCompletionMarkers += markers;
|
|
522
|
+
delegatedAgent = "Astra";
|
|
523
|
+
}
|
|
349
524
|
}
|
|
350
525
|
});
|
|
351
526
|
child.on("close", (code) => {
|
|
352
527
|
console.log("\n[RUNTIME] OpenCode finished execution.");
|
|
528
|
+
const fallbackDelegationRequired = usePromptFallback && agent === "Astra";
|
|
529
|
+
const observedAstraDelegations = astraTaskInvocations > 0 ? astraTaskInvocations : astraCompletionMarkers;
|
|
530
|
+
const fallbackDelegationConfirmed = !fallbackDelegationRequired || delegatedAgent === "Astra" && observedAstraDelegations === 1;
|
|
531
|
+
const appliedAgent = fallbackDelegationRequired ? delegatedAgent : isSpecializedAgent ? confirmedAgent : null;
|
|
353
532
|
resolve2({
|
|
354
|
-
success: code === 0,
|
|
533
|
+
success: code === 0 && fallbackDelegationConfirmed,
|
|
355
534
|
commandsRun,
|
|
535
|
+
commandEvents,
|
|
356
536
|
eventCount,
|
|
537
|
+
error: code === 0 && !fallbackDelegationConfirmed ? `OpenCode fallback requires exactly one observed Atlas-to-Astra delegation; observed ${observedAstraDelegations}.` : void 0,
|
|
357
538
|
runtimeAgentRequested: agent || null,
|
|
358
|
-
runtimeAgentApplied:
|
|
539
|
+
runtimeAgentApplied: appliedAgent,
|
|
359
540
|
runtimeAgentSupported: inspection.supports.agent,
|
|
360
541
|
runtimeAgentSelectionMode,
|
|
361
|
-
runtimeActorConfirmation:
|
|
542
|
+
runtimeActorConfirmation: appliedAgent ? "confirmed" : "unavailable",
|
|
362
543
|
output
|
|
363
544
|
});
|
|
364
545
|
});
|
|
@@ -368,6 +549,7 @@ ${message}` : message;
|
|
|
368
549
|
resolve2({
|
|
369
550
|
success: false,
|
|
370
551
|
commandsRun,
|
|
552
|
+
commandEvents,
|
|
371
553
|
eventCount: 0,
|
|
372
554
|
error: err.message,
|
|
373
555
|
runtimeAgentRequested: agent || null,
|
|
@@ -788,7 +970,7 @@ var EvidenceLedger = class {
|
|
|
788
970
|
observed,
|
|
789
971
|
runtime
|
|
790
972
|
}) {
|
|
791
|
-
const uniqueTerminalEvents = /* @__PURE__ */ new Set(["specification_complete", "planning_complete", "implementation_complete"]);
|
|
973
|
+
const uniqueTerminalEvents = /* @__PURE__ */ new Set(["specification_complete", "planning_complete", "implementation_complete", "finalization_completed"]);
|
|
792
974
|
if (uniqueTerminalEvents.has(eventType) && this.events.some((event2) => event2.eventType === eventType)) {
|
|
793
975
|
throw new Error(`Conflicting ledger record: terminal event '${eventType}' already exists for workflow '${this.workflowId}'.`);
|
|
794
976
|
}
|
|
@@ -1005,7 +1187,7 @@ var DelegationController = class {
|
|
|
1005
1187
|
runtimeActorConfirmation: "unavailable"
|
|
1006
1188
|
};
|
|
1007
1189
|
} else {
|
|
1008
|
-
runResult = await this.adapter.execute(prompt, { agent: actor, readOnly, requireActorConfirmation: true });
|
|
1190
|
+
runResult = await this.adapter.execute(prompt, { agent: actor, readOnly, requireActorConfirmation: true, orchestratedChild: true });
|
|
1009
1191
|
}
|
|
1010
1192
|
if (runResult.success && requireExplicitActor) {
|
|
1011
1193
|
if (!["explicit", "sdk-session"].includes(runResult.runtimeAgentSelectionMode || "") || runResult.runtimeAgentApplied !== actor || runResult.runtimeActorConfirmation !== "confirmed") {
|
|
@@ -1048,6 +1230,8 @@ var DelegationController = class {
|
|
|
1048
1230
|
runtimeActorConfirmation: runResult.runtimeActorConfirmation || "unavailable",
|
|
1049
1231
|
artifactPath: runResult.artifact?.artifactPath || null,
|
|
1050
1232
|
artifactHash: runResult.artifact?.artifactHash || null,
|
|
1233
|
+
commandsRun: runResult.commandsRun || [],
|
|
1234
|
+
commandEvents: runResult.commandEvents || [],
|
|
1051
1235
|
status: runResult.success ? "COMPLETED" : "BLOCKED"
|
|
1052
1236
|
}
|
|
1053
1237
|
});
|
|
@@ -1060,6 +1244,9 @@ var DelegationController = class {
|
|
|
1060
1244
|
const decision = this.lastRoutingDecision ?? {
|
|
1061
1245
|
operationType: "explain",
|
|
1062
1246
|
mutationIntent: "readonly",
|
|
1247
|
+
deliveryMode: "answer-only",
|
|
1248
|
+
mutationOwner: null,
|
|
1249
|
+
capabilityRoles: [],
|
|
1063
1250
|
permissionDecision: "allowed",
|
|
1064
1251
|
reason: "no routing decision",
|
|
1065
1252
|
workflowPath: []
|
|
@@ -1106,6 +1293,7 @@ var DelegationController = class {
|
|
|
1106
1293
|
data: {
|
|
1107
1294
|
success: runResult.success,
|
|
1108
1295
|
commandsRun: runResult.commandsRun || [],
|
|
1296
|
+
commandEvents: runResult.commandEvents || [],
|
|
1109
1297
|
eventCount: runResult.eventCount || 0,
|
|
1110
1298
|
error: runResult.error,
|
|
1111
1299
|
event: "implementation.completed",
|
|
@@ -1133,6 +1321,9 @@ var DelegationController = class {
|
|
|
1133
1321
|
const decision = this.lastRoutingDecision ?? {
|
|
1134
1322
|
operationType: "explain",
|
|
1135
1323
|
mutationIntent: "readonly",
|
|
1324
|
+
deliveryMode: "answer-only",
|
|
1325
|
+
mutationOwner: null,
|
|
1326
|
+
capabilityRoles: [],
|
|
1136
1327
|
permissionDecision: "allowed",
|
|
1137
1328
|
reason: "no routing decision",
|
|
1138
1329
|
workflowPath: []
|
|
@@ -1214,7 +1405,7 @@ ${JSON.stringify(result, null, 2)}`;
|
|
|
1214
1405
|
import fs5 from "fs/promises";
|
|
1215
1406
|
import path4 from "path";
|
|
1216
1407
|
import crypto2 from "crypto";
|
|
1217
|
-
import { execSync as execSync3 } from "child_process";
|
|
1408
|
+
import { execFileSync, execSync as execSync3 } from "child_process";
|
|
1218
1409
|
var WorkspaceSnapshot = class {
|
|
1219
1410
|
cwd;
|
|
1220
1411
|
fastTrack;
|
|
@@ -1237,7 +1428,12 @@ var WorkspaceSnapshot = class {
|
|
|
1237
1428
|
const files = {};
|
|
1238
1429
|
const isTest = process.env.NODE_ENV === "test" || process.env.VITEST === "true";
|
|
1239
1430
|
if (!this.fastTrack || isTest) {
|
|
1240
|
-
|
|
1431
|
+
const gitVisibleFiles = this.listGitVisibleFiles();
|
|
1432
|
+
if (gitVisibleFiles) {
|
|
1433
|
+
await this.scanFiles(gitVisibleFiles, files);
|
|
1434
|
+
} else {
|
|
1435
|
+
await this.scanDir(this.cwd, files);
|
|
1436
|
+
}
|
|
1241
1437
|
}
|
|
1242
1438
|
const execGit = (args) => {
|
|
1243
1439
|
try {
|
|
@@ -1265,6 +1461,40 @@ var WorkspaceSnapshot = class {
|
|
|
1265
1461
|
untrackedFilesHash: hashString(untrackedFiles)
|
|
1266
1462
|
};
|
|
1267
1463
|
}
|
|
1464
|
+
listGitVisibleFiles() {
|
|
1465
|
+
try {
|
|
1466
|
+
execFileSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
1467
|
+
cwd: this.cwd,
|
|
1468
|
+
encoding: "utf8",
|
|
1469
|
+
stdio: "pipe"
|
|
1470
|
+
});
|
|
1471
|
+
const output = execFileSync("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
|
|
1472
|
+
cwd: this.cwd,
|
|
1473
|
+
encoding: "utf8",
|
|
1474
|
+
stdio: "pipe"
|
|
1475
|
+
});
|
|
1476
|
+
return [...new Set(output.split("\0").filter(Boolean))];
|
|
1477
|
+
} catch {
|
|
1478
|
+
return null;
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
async scanFiles(relativePaths, filesMap) {
|
|
1482
|
+
for (const relativePath of relativePaths) {
|
|
1483
|
+
const normalizedPath = relativePath.replaceAll("\\", "/");
|
|
1484
|
+
if (this.isIgnored(normalizedPath)) continue;
|
|
1485
|
+
try {
|
|
1486
|
+
const fullPath = path4.join(this.cwd, relativePath);
|
|
1487
|
+
const stat = await fs5.stat(fullPath);
|
|
1488
|
+
if (!stat.isFile()) continue;
|
|
1489
|
+
const content = await fs5.readFile(fullPath);
|
|
1490
|
+
const sha256 = crypto2.createHash("sha256").update(content).digest("hex");
|
|
1491
|
+
const isExecutable = (stat.mode & 73) !== 0;
|
|
1492
|
+
const mode = isExecutable ? "100755" : "100644";
|
|
1493
|
+
filesMap[normalizedPath] = { sha256, mode };
|
|
1494
|
+
} catch {
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1268
1498
|
async scanDir(dir, filesMap) {
|
|
1269
1499
|
try {
|
|
1270
1500
|
const entries = await fs5.readdir(dir, { withFileTypes: true });
|
|
@@ -1539,271 +1769,6 @@ function resolveWorkflowProfile({ request = "", explicitProfile = null } = {}) {
|
|
|
1539
1769
|
return "generic";
|
|
1540
1770
|
}
|
|
1541
1771
|
|
|
1542
|
-
// src/core/request-router.ts
|
|
1543
|
-
import path6 from "path";
|
|
1544
|
-
import fs7 from "fs";
|
|
1545
|
-
var RequestRouter = class {
|
|
1546
|
-
cwd;
|
|
1547
|
-
constructor({ cwd = process.cwd() } = {}) {
|
|
1548
|
-
this.cwd = cwd;
|
|
1549
|
-
}
|
|
1550
|
-
/**
|
|
1551
|
-
* Understands and classifies a natural language request.
|
|
1552
|
-
*/
|
|
1553
|
-
understand(request) {
|
|
1554
|
-
const text = String(request).trim();
|
|
1555
|
-
if (!text) {
|
|
1556
|
-
throw new Error("Cannot classify an empty request.");
|
|
1557
|
-
}
|
|
1558
|
-
const { operationType, requestedCapability } = this.extractCapability(text);
|
|
1559
|
-
const mutationIntent = this.determineMutationIntent(text, operationType);
|
|
1560
|
-
const riskAssessment = this.determineRiskAssessment(text, mutationIntent);
|
|
1561
|
-
const riskLevel = riskAssessment.riskLevel;
|
|
1562
|
-
const { safetyConstraints, requiredEvidence } = this.determineSafetyAndEvidence(text, mutationIntent);
|
|
1563
|
-
return {
|
|
1564
|
-
rawRequest: text,
|
|
1565
|
-
taskGoal: `Perform ${operationType} operation under ${mutationIntent} intent`,
|
|
1566
|
-
requestedActor: void 0,
|
|
1567
|
-
invalidActor: void 0,
|
|
1568
|
-
requestedCapability,
|
|
1569
|
-
operationType,
|
|
1570
|
-
mutationIntent,
|
|
1571
|
-
riskLevel,
|
|
1572
|
-
requiredEvidence,
|
|
1573
|
-
safetyConstraints,
|
|
1574
|
-
specPolicy: riskAssessment.specPolicy,
|
|
1575
|
-
matchedSignals: riskAssessment.matchedSignals,
|
|
1576
|
-
riskDrivers: riskAssessment.riskDrivers
|
|
1577
|
-
};
|
|
1578
|
-
}
|
|
1579
|
-
extractCapability(text) {
|
|
1580
|
-
let operationType = "explain";
|
|
1581
|
-
let requestedCapability = void 0;
|
|
1582
|
-
const capabilityMappings = [
|
|
1583
|
-
{ op: "discover", pattern: /\b(discover|inspect|map|scan|structure|architecture|repo|search|find)\b/i },
|
|
1584
|
-
{ op: "validate", pattern: /\b(validate|audit|review|check|verify|test)\b/i },
|
|
1585
|
-
{ op: "implement", pattern: /\b(implement|implementa|build|create|crie|cria|add|develop|write|change|modify|atualiza|atualizar|refatora|refatorar)\b/i },
|
|
1586
|
-
{ op: "fix", pattern: /\b(fix|repair|correct|corrige|corrigir|heal|solve|remediate)\b/i },
|
|
1587
|
-
{ op: "release", pattern: /\b(release|tag|prepare release|prepara(?:r)?\s+(?:a\s+)?release)\b/i },
|
|
1588
|
-
{ op: "deploy", pattern: /\b(deploy|publish|push|produção|producao)\b/i }
|
|
1589
|
-
];
|
|
1590
|
-
for (const mapping of capabilityMappings) {
|
|
1591
|
-
const match = text.match(mapping.pattern);
|
|
1592
|
-
if (match) {
|
|
1593
|
-
operationType = mapping.op;
|
|
1594
|
-
requestedCapability = match[1];
|
|
1595
|
-
break;
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
return { operationType, requestedCapability };
|
|
1599
|
-
}
|
|
1600
|
-
determineMutationIntent(text, operationType) {
|
|
1601
|
-
const writePatterns = /\b(implement|implementa|build|fix|corrige|write|change|modify|create|crie|cria|add|refactor|refatora|refatorar|update|atualiza|atualizar)\b/i;
|
|
1602
|
-
const readOnlyPatterns = /\b(analyze|check|inspect|review|find|search|show|list|read|view|verify|validate|discover|map)\b/i;
|
|
1603
|
-
let mutationIntent = "write";
|
|
1604
|
-
if (/\b(read-only|readonly)\b/i.test(text)) {
|
|
1605
|
-
mutationIntent = "readonly";
|
|
1606
|
-
} else if (writePatterns.test(text)) {
|
|
1607
|
-
mutationIntent = "write";
|
|
1608
|
-
} else if (readOnlyPatterns.test(text) || ["discover", "validate"].includes(operationType)) {
|
|
1609
|
-
mutationIntent = "readonly";
|
|
1610
|
-
}
|
|
1611
|
-
if (/\b(publish|release|deploy|produção|producao|push to npm|push to remote)\b/i.test(text)) {
|
|
1612
|
-
mutationIntent = "publish";
|
|
1613
|
-
}
|
|
1614
|
-
return mutationIntent;
|
|
1615
|
-
}
|
|
1616
|
-
determineRiskAssessment(text, mutationIntent) {
|
|
1617
|
-
const matchedSignals = [];
|
|
1618
|
-
const add = (signal, pattern) => {
|
|
1619
|
-
if (pattern.test(text)) {
|
|
1620
|
-
matchedSignals.push(signal);
|
|
1621
|
-
return true;
|
|
1622
|
-
}
|
|
1623
|
-
return false;
|
|
1624
|
-
};
|
|
1625
|
-
const taskTypeSignals = {
|
|
1626
|
-
docsCopy: add("task:docs-copy", /\b(README|docs?|documenta[cç][aã]o|typo|copy|frase|comment|coment[áa]rio)\b/i),
|
|
1627
|
-
refactor: add("task:refactor", /\b(refactor|refatora|refatorar|simplificar|mais simples de manter|manuten[cç][aã]o)\b/i),
|
|
1628
|
-
noBehaviorChange: add("scope:no-behavior-change", /\b(sem alterar (?:o )?comportamento|without changing behavior|without behaviour change|no behavior change|comportamento existente)\b/i),
|
|
1629
|
-
landingPage: add("task:landing-page", /\b(landing page|hotsite|p[áa]gina de venda|p[áa]gina comercial)\b/i),
|
|
1630
|
-
dashboard: add("task:dashboard", /\b(dashboard|painel)\b/i),
|
|
1631
|
-
bugfix: add("task:bugfix", /\b(bug|fix|corrige|corrigir|erro|falha|n[aã]o envia|não envia)\b/i),
|
|
1632
|
-
release: add("task:release", /\b(release|deploy|produ[cç][aã]o|publish|publicar|lan[cç]amento)\b/i)
|
|
1633
|
-
};
|
|
1634
|
-
const domainRiskSignals = {
|
|
1635
|
-
adult: add("domain:adult", /\b(er[óo]tic[oa]s?|adult[oa]s?|sexual|sexo|porn(?:o|ografia)?|18\+)\b/i),
|
|
1636
|
-
auth: add("domain:auth", /\b(login|auth|autentica[cç][aã]o|autoriza[cç][aã]o|permiss(?:ão|oes|ões)|admin|administrador|roles?|rbac)\b/i),
|
|
1637
|
-
payment: add("domain:payment", /\b(pagamento|checkout|billing|cobran[cç]a|fatura[cç][aã]o|assinatura|cart[aã]o|stripe|paypal)\b/i),
|
|
1638
|
-
securityGovernance: add("domain:security-governance", /\b(SECURITY\.md|seguran[cç]a|security policy|pol[ií]tica de seguran[cç]a|governance|governan[cç]a|compliance|branch safety)\b/i)
|
|
1639
|
-
};
|
|
1640
|
-
const impactSignals = {
|
|
1641
|
-
personalData: add("impact:personal-data", /\b(leads?|dados pessoais|personal data|crm|contatos?|contactos?|clientes?|exporta[cç][aã]o|exportar|armazenamento|armazenar|integra[cç][aã]o|integrar)\b/i),
|
|
1642
|
-
productionRelease: mutationIntent === "publish" || add("impact:production-release", /\b(produ[cç][aã]o|release|deploy|publish|publicar|npm)\b/i),
|
|
1643
|
-
adminPermissions: add("impact:admin-permissions", /\b(admin|administrador|permiss(?:ão|oes|ões)|roles?|rbac)\b/i)
|
|
1644
|
-
};
|
|
1645
|
-
if (mutationIntent === "publish" && !matchedSignals.includes("impact:production-release")) {
|
|
1646
|
-
matchedSignals.push("impact:production-release");
|
|
1647
|
-
}
|
|
1648
|
-
const scopeSignals = {
|
|
1649
|
-
localized: add("scope:localized", /\b(localizado|uma frase|typo|pequeno|small|tiny|simples|README)\b/i),
|
|
1650
|
-
broad: add("scope:broad", /\b(plataforma|sistema|completo|premium|end-to-end|amplo|v[aá]rias|m[úu]ltiplas|empresa)\b/i),
|
|
1651
|
-
architectural: add("scope:architectural", /\b(deep|architectural|arquitetural|migration|migra[cç][aã]o|major|full|\[deep\])\b/i),
|
|
1652
|
-
explicitHigh: add("scope:explicit-high", /\b(high-risk|high risk|alto risco)\b/i),
|
|
1653
|
-
explicitRequiredSpec: add("scope:explicit-required-spec", /\b(formal spec|required spec|especifica[cç][aã]o formal)\b/i),
|
|
1654
|
-
explicitRequiredEvidence: add("scope:explicit-required-evidence", /\b(required evidence|evidence required|evid[eê]ncia obrigat[óo]ria)\b/i)
|
|
1655
|
-
};
|
|
1656
|
-
let riskLevel = "medium";
|
|
1657
|
-
const riskDrivers = [];
|
|
1658
|
-
const highDrivers = [
|
|
1659
|
-
["scope:explicit-high", scopeSignals.explicitHigh],
|
|
1660
|
-
["scope:architectural", scopeSignals.architectural],
|
|
1661
|
-
["domain:adult", domainRiskSignals.adult],
|
|
1662
|
-
["domain:auth", domainRiskSignals.auth],
|
|
1663
|
-
["domain:payment", domainRiskSignals.payment],
|
|
1664
|
-
["domain:security-governance", domainRiskSignals.securityGovernance],
|
|
1665
|
-
["impact:production-release", impactSignals.productionRelease],
|
|
1666
|
-
["impact:admin-permissions", impactSignals.adminPermissions],
|
|
1667
|
-
["impact:personal-data", taskTypeSignals.dashboard && impactSignals.personalData]
|
|
1668
|
-
];
|
|
1669
|
-
for (const [signal, active] of highDrivers) {
|
|
1670
|
-
if (active) {
|
|
1671
|
-
riskDrivers.push(signal);
|
|
1672
|
-
}
|
|
1673
|
-
}
|
|
1674
|
-
if (riskDrivers.length > 0) {
|
|
1675
|
-
riskLevel = "high";
|
|
1676
|
-
} else if (mutationIntent === "readonly") {
|
|
1677
|
-
riskLevel = "low";
|
|
1678
|
-
riskDrivers.push("intent:readonly");
|
|
1679
|
-
} else if (taskTypeSignals.docsCopy && scopeSignals.localized) {
|
|
1680
|
-
riskLevel = "low";
|
|
1681
|
-
riskDrivers.push("task:docs-copy");
|
|
1682
|
-
} else if (taskTypeSignals.refactor || taskTypeSignals.bugfix || taskTypeSignals.landingPage || taskTypeSignals.dashboard) {
|
|
1683
|
-
riskLevel = "medium";
|
|
1684
|
-
if (taskTypeSignals.refactor) riskDrivers.push("task:refactor");
|
|
1685
|
-
if (taskTypeSignals.bugfix) riskDrivers.push("task:bugfix");
|
|
1686
|
-
if (taskTypeSignals.landingPage) riskDrivers.push("task:landing-page");
|
|
1687
|
-
if (taskTypeSignals.dashboard) riskDrivers.push("task:dashboard");
|
|
1688
|
-
}
|
|
1689
|
-
const specPolicy = riskLevel === "high" || scopeSignals.explicitRequiredSpec || taskTypeSignals.landingPage && scopeSignals.broad ? "required" : "none";
|
|
1690
|
-
return {
|
|
1691
|
-
riskLevel,
|
|
1692
|
-
specPolicy,
|
|
1693
|
-
matchedSignals: [...new Set(matchedSignals)],
|
|
1694
|
-
riskDrivers: [...new Set(riskDrivers)]
|
|
1695
|
-
};
|
|
1696
|
-
}
|
|
1697
|
-
determineSafetyAndEvidence(text, mutationIntent) {
|
|
1698
|
-
const safetyConstraints = [];
|
|
1699
|
-
const requiredEvidence = [];
|
|
1700
|
-
if (mutationIntent === "publish") {
|
|
1701
|
-
safetyConstraints.push("Require release gate", "Awaiting user authorization");
|
|
1702
|
-
requiredEvidence.push("release-decision", "tarball-hash");
|
|
1703
|
-
} else if (mutationIntent === "write") {
|
|
1704
|
-
safetyConstraints.push("Require branch gate", "No direct commits to main");
|
|
1705
|
-
requiredEvidence.push("tests", "commit-hash");
|
|
1706
|
-
} else {
|
|
1707
|
-
safetyConstraints.push("No workspace mutations allowed");
|
|
1708
|
-
}
|
|
1709
|
-
if (/\b(bypass|force|direct)\b/i.test(text)) {
|
|
1710
|
-
safetyConstraints.push("Block bypass attempts");
|
|
1711
|
-
}
|
|
1712
|
-
if (/\b(required evidence|evidence required)\b/i.test(text)) {
|
|
1713
|
-
requiredEvidence.push("user-required-evidence");
|
|
1714
|
-
}
|
|
1715
|
-
if (/\b(formal spec|required spec)\b/i.test(text)) {
|
|
1716
|
-
safetyConstraints.push("Require formal specification");
|
|
1717
|
-
}
|
|
1718
|
-
return { safetyConstraints, requiredEvidence };
|
|
1719
|
-
}
|
|
1720
|
-
/**
|
|
1721
|
-
* Decides the routing decision.
|
|
1722
|
-
*/
|
|
1723
|
-
route(understanding) {
|
|
1724
|
-
const { operationType, mutationIntent, rawRequest } = understanding;
|
|
1725
|
-
const requestedActor = void 0;
|
|
1726
|
-
if (/\b(bypass safety|bypass validation|force push|directly to main|push to remote without gate)\b/i.test(rawRequest)) {
|
|
1727
|
-
return {
|
|
1728
|
-
requestedActor,
|
|
1729
|
-
selectedActor: "Atlas",
|
|
1730
|
-
operationType,
|
|
1731
|
-
mutationIntent,
|
|
1732
|
-
permissionDecision: "blocked",
|
|
1733
|
-
reason: "Security block: Attempt to bypass safety or push directly is forbidden.",
|
|
1734
|
-
workflowPath: ["Atlas"]
|
|
1735
|
-
};
|
|
1736
|
-
}
|
|
1737
|
-
let { selectedActor, permissionDecision, reason } = this.evaluateActorPermission(operationType, mutationIntent);
|
|
1738
|
-
let workflowPath = ["Atlas"];
|
|
1739
|
-
if (selectedActor === "Phoenix") {
|
|
1740
|
-
const requestPath = path6.join(this.cwd, ".ai-workflow/remediation-request.json");
|
|
1741
|
-
let hasFindings = false;
|
|
1742
|
-
if (fs7.existsSync(requestPath)) {
|
|
1743
|
-
try {
|
|
1744
|
-
const reqData = JSON.parse(fs7.readFileSync(requestPath, "utf8"));
|
|
1745
|
-
if (reqData.affectedChecks && reqData.affectedChecks.length > 0) {
|
|
1746
|
-
hasFindings = true;
|
|
1747
|
-
}
|
|
1748
|
-
} catch {
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
if (!hasFindings) {
|
|
1752
|
-
permissionDecision = "blocked";
|
|
1753
|
-
reason = "Blocked: Phoenix acts only with concrete findings and bounded remediation.";
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
if (understanding.specPolicy === "required") {
|
|
1757
|
-
workflowPath.push("Nexus", "Orion");
|
|
1758
|
-
}
|
|
1759
|
-
if (selectedActor && !workflowPath.includes(selectedActor)) {
|
|
1760
|
-
workflowPath.push(selectedActor);
|
|
1761
|
-
}
|
|
1762
|
-
if (selectedActor === "Atlas" && ["discover", "validate", "fix", "release", "deploy"].includes(operationType)) {
|
|
1763
|
-
permissionDecision = "blocked";
|
|
1764
|
-
reason = "Atlas self-execution guard: Atlas cannot silently execute specialized actor or capability requests.";
|
|
1765
|
-
}
|
|
1766
|
-
if (selectedActor === "Astra" && understanding.riskLevel === "high") {
|
|
1767
|
-
workflowPath.push("Sage", "Phoenix", "Sage");
|
|
1768
|
-
}
|
|
1769
|
-
if (understanding.specPolicy === "none") {
|
|
1770
|
-
workflowPath = workflowPath.filter((actor) => {
|
|
1771
|
-
if (actor === "Nexus" && selectedActor !== "Nexus") return false;
|
|
1772
|
-
if (actor === "Orion" && selectedActor !== "Orion") return false;
|
|
1773
|
-
return true;
|
|
1774
|
-
});
|
|
1775
|
-
}
|
|
1776
|
-
return {
|
|
1777
|
-
requestedActor,
|
|
1778
|
-
selectedActor,
|
|
1779
|
-
operationType,
|
|
1780
|
-
mutationIntent,
|
|
1781
|
-
permissionDecision,
|
|
1782
|
-
reason,
|
|
1783
|
-
workflowPath
|
|
1784
|
-
};
|
|
1785
|
-
}
|
|
1786
|
-
evaluateActorPermission(operationType, mutationIntent) {
|
|
1787
|
-
let selectedActor;
|
|
1788
|
-
let permissionDecision = "allowed";
|
|
1789
|
-
let reason = "Routed successfully.";
|
|
1790
|
-
if (operationType === "discover") {
|
|
1791
|
-
selectedActor = "Nexus";
|
|
1792
|
-
} else if (operationType === "validate") {
|
|
1793
|
-
selectedActor = "Sage";
|
|
1794
|
-
} else if (operationType === "fix") {
|
|
1795
|
-
selectedActor = "Phoenix";
|
|
1796
|
-
} else if (operationType === "implement") {
|
|
1797
|
-
selectedActor = "Astra";
|
|
1798
|
-
} else if (operationType === "release" || operationType === "deploy") {
|
|
1799
|
-
selectedActor = "Orion";
|
|
1800
|
-
} else {
|
|
1801
|
-
selectedActor = mutationIntent === "write" ? "Astra" : "Atlas";
|
|
1802
|
-
}
|
|
1803
|
-
return { selectedActor, permissionDecision, reason };
|
|
1804
|
-
}
|
|
1805
|
-
};
|
|
1806
|
-
|
|
1807
1772
|
// src/core/request-classifier.ts
|
|
1808
1773
|
var RequestClassifier = class {
|
|
1809
1774
|
/**
|
|
@@ -1817,12 +1782,10 @@ var RequestClassifier = class {
|
|
|
1817
1782
|
const cwd = options.cwd || process.cwd();
|
|
1818
1783
|
const profile = resolveWorkflowProfile({ request: text });
|
|
1819
1784
|
const profileDef = getWorkflowProfile(profile);
|
|
1820
|
-
const readOnlyPatterns = /\b(analyze|check|inspect|review|find|search|show|list|read|view|verify)\b/i;
|
|
1821
|
-
const isReadOnly = readOnlyPatterns.test(text);
|
|
1822
|
-
const intent = isReadOnly ? "read-only" : "write";
|
|
1823
1785
|
const router = new RequestRouter({ cwd });
|
|
1824
1786
|
const requestUnderstanding = router.understand(text);
|
|
1825
1787
|
const routingDecision = router.route(requestUnderstanding);
|
|
1788
|
+
const intent = requestUnderstanding.mutationIntent === "readonly" || requestUnderstanding.deliveryMode === "answer-only" ? "read-only" : "write";
|
|
1826
1789
|
const risk = requestUnderstanding.riskLevel;
|
|
1827
1790
|
const explicitRequiredEvidence = /\b(required evidence|evidence required)\b/i.test(text);
|
|
1828
1791
|
const explicitRequiredSpec = /\b(formal spec|required spec)\b/i.test(text);
|
|
@@ -1846,7 +1809,7 @@ var RequestClassifier = class {
|
|
|
1846
1809
|
request: text,
|
|
1847
1810
|
profile,
|
|
1848
1811
|
owner: routingDecision.selectedActor || profileDef.owner,
|
|
1849
|
-
intent
|
|
1812
|
+
intent,
|
|
1850
1813
|
mode: legacyMode,
|
|
1851
1814
|
risk,
|
|
1852
1815
|
specPolicy,
|
|
@@ -1864,7 +1827,7 @@ var RequestClassifier = class {
|
|
|
1864
1827
|
};
|
|
1865
1828
|
|
|
1866
1829
|
// src/core/execution-planner.ts
|
|
1867
|
-
import
|
|
1830
|
+
import path6 from "path";
|
|
1868
1831
|
var ExecutionPlanner = class {
|
|
1869
1832
|
cwd;
|
|
1870
1833
|
constructor({ cwd = process.cwd() } = {}) {
|
|
@@ -1876,8 +1839,8 @@ var ExecutionPlanner = class {
|
|
|
1876
1839
|
plan(classification, taskSlug = "task") {
|
|
1877
1840
|
const remediationLimit = classification.remediationLimit;
|
|
1878
1841
|
const branchNeeded = classification.intent === "write";
|
|
1879
|
-
const specPath = classification.specNeeded ?
|
|
1880
|
-
const owner = classification.routingDecision?.selectedActor || (classification.intent === "write" ? "Astra" : classification.owner);
|
|
1842
|
+
const specPath = classification.specNeeded ? path6.join("docs/workflows", taskSlug, "spec.md") : null;
|
|
1843
|
+
const owner = classification.routingDecision?.mutationOwner === "Astra" ? "Astra" : classification.routingDecision?.selectedActor || (classification.intent === "write" ? "Astra" : classification.owner);
|
|
1881
1844
|
const validationsExpected = [];
|
|
1882
1845
|
if (classification.validationNeeded) {
|
|
1883
1846
|
validationsExpected.push("test");
|
|
@@ -1981,4 +1944,4 @@ export {
|
|
|
1981
1944
|
ExecutionPlanner,
|
|
1982
1945
|
WorkflowStateMachine
|
|
1983
1946
|
};
|
|
1984
|
-
//# sourceMappingURL=chunk-
|
|
1947
|
+
//# sourceMappingURL=chunk-4FI5ODAM.js.map
|