agentplane 0.3.4 → 0.3.6
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/README.md +103 -75
- package/assets/AGENTS.md +4 -2
- package/bin/dist-guard.js +13 -3
- package/bin/runtime-watch.d.ts +1 -0
- package/bin/runtime-watch.js +22 -5
- package/bin/stale-dist-policy.js +9 -2
- package/dist/.build-manifest.json +220 -790
- package/dist/adapters/task-backend/task-backend-adapter.d.ts +1 -1
- package/dist/adapters/task-backend/task-backend-adapter.d.ts.map +1 -1
- package/dist/adapters/task-backend/task-backend-adapter.js +5 -2
- package/dist/backends/task-backend/local-backend.d.ts +13 -0
- package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/local-backend.js +17 -0
- package/dist/backends/task-backend/redmine-backend.d.ts +18 -0
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +35 -25
- package/dist/backends/task-backend/shared/types.d.ts +20 -0
- package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
- package/dist/backends/task-backend/shared.d.ts +1 -1
- package/dist/backends/task-backend/shared.d.ts.map +1 -1
- package/dist/backends/task-backend.d.ts +1 -1
- package/dist/backends/task-backend.d.ts.map +1 -1
- package/dist/backends/task-backend.test-helpers.d.ts +4 -0
- package/dist/backends/task-backend.test-helpers.d.ts.map +1 -0
- package/dist/backends/task-backend.test-helpers.js +33 -0
- package/dist/cli/bootstrap-guide.d.ts.map +1 -1
- package/dist/cli/bootstrap-guide.js +1 -0
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +3 -2
- package/dist/cli/reason-codes.d.ts.map +1 -1
- package/dist/cli/reason-codes.js +30 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/core.js +137 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.js +52 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/project.js +78 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts +19 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/shared.js +9 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/task.js +85 -0
- package/dist/cli/run-cli/command-catalog.d.ts +3 -18
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog.js +8 -337
- package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/ide.js +64 -2
- package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/ui.js +33 -13
- package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.js +41 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts +2 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.js +6 -0
- package/dist/cli/run-cli.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +138 -6
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +2 -2
- package/dist/commands/doctor/runtime.d.ts.map +1 -1
- package/dist/commands/doctor/runtime.js +3 -6
- package/dist/commands/doctor/workspace.d.ts +4 -1
- package/dist/commands/doctor/workspace.d.ts.map +1 -1
- package/dist/commands/doctor/workspace.js +87 -4
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +8 -1
- package/dist/commands/guard/commit.command.js +1 -1
- package/dist/commands/guard/impl/allow.d.ts +5 -0
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +15 -10
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +137 -18
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +2 -0
- package/dist/commands/hooks/index.d.ts.map +1 -1
- package/dist/commands/hooks/index.js +8 -35
- package/dist/commands/recipes/impl/apply.d.ts +4 -0
- package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
- package/dist/commands/recipes/impl/apply.js +34 -0
- package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/explain.js +70 -11
- package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/info.js +24 -12
- package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +32 -36
- package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list.js +7 -4
- package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/remove.js +9 -11
- package/dist/commands/recipes/impl/constants.d.ts +2 -0
- package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
- package/dist/commands/recipes/impl/constants.js +2 -0
- package/dist/commands/recipes/impl/manifest.d.ts.map +1 -1
- package/dist/commands/recipes/impl/manifest.js +219 -23
- package/dist/commands/recipes/impl/normalize.d.ts +3 -0
- package/dist/commands/recipes/impl/normalize.d.ts.map +1 -1
- package/dist/commands/recipes/impl/normalize.js +28 -24
- package/dist/commands/recipes/impl/paths.d.ts +9 -0
- package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
- package/dist/commands/recipes/impl/paths.js +10 -1
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts +7 -0
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -0
- package/dist/commands/recipes/impl/project-installed-recipes.js +102 -0
- package/dist/commands/recipes/impl/resolver.d.ts +20 -0
- package/dist/commands/recipes/impl/resolver.d.ts.map +1 -0
- package/dist/commands/recipes/impl/resolver.js +220 -0
- package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
- package/dist/commands/recipes/impl/scenario.js +40 -11
- package/dist/commands/recipes/impl/types.d.ts +145 -16
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.js +3 -2
- package/dist/commands/recipes.d.ts +6 -4
- package/dist/commands/recipes.d.ts.map +1 -1
- package/dist/commands/recipes.js +5 -3
- package/dist/commands/recipes.test-helpers.d.ts +185 -0
- package/dist/commands/recipes.test-helpers.d.ts.map +1 -0
- package/dist/commands/recipes.test-helpers.js +339 -0
- package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.js +192 -336
- package/dist/commands/scenario/info.command.d.ts.map +1 -1
- package/dist/commands/scenario/info.command.js +7 -2
- package/dist/commands/scenario/list.command.js +2 -2
- package/dist/commands/scenario/run.command.d.ts.map +1 -1
- package/dist/commands/scenario/run.command.js +7 -2
- package/dist/commands/shared/git-context.d.ts +1 -0
- package/dist/commands/shared/git-context.d.ts.map +1 -1
- package/dist/commands/shared/git-context.js +4 -0
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
- package/dist/commands/shared/reconcile-check.js +77 -2
- package/dist/commands/shared/task-backend.d.ts +5 -0
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +24 -0
- package/dist/commands/shared/task-store.d.ts +32 -1
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +166 -42
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +46 -29
- package/dist/commands/task/close-duplicate.d.ts.map +1 -1
- package/dist/commands/task/close-duplicate.js +12 -37
- package/dist/commands/task/close-noop.d.ts.map +1 -1
- package/dist/commands/task/close-noop.js +12 -30
- package/dist/commands/task/close-shared.d.ts +14 -0
- package/dist/commands/task/close-shared.d.ts.map +1 -0
- package/dist/commands/task/close-shared.js +76 -0
- package/dist/commands/task/comment.d.ts.map +1 -1
- package/dist/commands/task/comment.js +35 -17
- package/dist/commands/task/doc-set.command.d.ts +2 -1
- package/dist/commands/task/doc-set.command.d.ts.map +1 -1
- package/dist/commands/task/doc-set.command.js +36 -4
- package/dist/commands/task/doc-template.d.ts.map +1 -1
- package/dist/commands/task/doc-template.js +2 -7
- package/dist/commands/task/doc.command.js +1 -1
- package/dist/commands/task/doc.d.ts +2 -1
- package/dist/commands/task/doc.d.ts.map +1 -1
- package/dist/commands/task/doc.js +123 -71
- package/dist/commands/task/export.d.ts.map +1 -1
- package/dist/commands/task/export.js +4 -4
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +141 -78
- package/dist/commands/task/migrate-doc.d.ts.map +1 -1
- package/dist/commands/task/migrate-doc.js +15 -11
- package/dist/commands/task/plan-set.command.js +1 -1
- package/dist/commands/task/plan.command.d.ts +8 -0
- package/dist/commands/task/plan.command.d.ts.map +1 -0
- package/dist/commands/task/plan.command.js +37 -0
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +190 -93
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +1 -1
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +40 -3
- package/dist/commands/task/shared/docs.d.ts +1 -0
- package/dist/commands/task/shared/docs.d.ts.map +1 -1
- package/dist/commands/task/shared/docs.js +7 -0
- package/dist/commands/task/shared/transitions.d.ts +0 -2
- package/dist/commands/task/shared/transitions.d.ts.map +1 -1
- package/dist/commands/task/shared/transitions.js +0 -6
- package/dist/commands/task/shared.d.ts +2 -2
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +2 -2
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +88 -63
- package/dist/commands/task/task.command.d.ts +8 -0
- package/dist/commands/task/task.command.d.ts.map +1 -0
- package/dist/commands/task/task.command.js +71 -0
- package/dist/commands/task/verify-command-shared.d.ts +16 -0
- package/dist/commands/task/verify-command-shared.d.ts.map +1 -0
- package/dist/commands/task/verify-command-shared.js +53 -0
- package/dist/commands/task/verify-ok.command.d.ts +2 -6
- package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
- package/dist/commands/task/verify-ok.command.js +8 -50
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +119 -140
- package/dist/commands/task/verify-rework.command.d.ts +2 -6
- package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
- package/dist/commands/task/verify-rework.command.js +8 -50
- package/dist/commands/verify.spec.d.ts.map +1 -1
- package/dist/commands/verify.spec.js +3 -12
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +13 -4
- package/dist/policy/rules/protected-paths.d.ts.map +1 -1
- package/dist/policy/rules/protected-paths.js +6 -1
- package/dist/ports/task-backend-port.d.ts +1 -1
- package/dist/ports/task-backend-port.d.ts.map +1 -1
- package/dist/shared/agent-emoji.d.ts.map +1 -1
- package/dist/shared/protected-paths.d.ts +7 -0
- package/dist/shared/protected-paths.d.ts.map +1 -1
- package/dist/shared/protected-paths.js +26 -10
- package/dist/shared/repo-cli-version.d.ts.map +1 -1
- package/dist/shared/repo-cli-version.js +9 -3
- package/package.json +2 -2
|
@@ -1,16 +1,149 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { mkdir, readdir } from "node:fs/promises";
|
|
3
2
|
import path from "node:path";
|
|
4
3
|
import { promisify } from "node:util";
|
|
5
|
-
import {
|
|
4
|
+
import { resolveProject } from "@agentplaneorg/core";
|
|
6
5
|
import { mapCoreError } from "../../../cli/error-map.js";
|
|
7
6
|
import { exitCodeForError } from "../../../cli/exit-codes.js";
|
|
8
|
-
import { fileExists
|
|
7
|
+
import { fileExists } from "../../../cli/fs-utils.js";
|
|
9
8
|
import { emptyStateMessage } from "../../../cli/output.js";
|
|
10
9
|
import { CliError } from "../../../shared/errors.js";
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { formatJsonBlock } from "../../recipes/impl/format.js";
|
|
11
|
+
import { listResolvedRecipeScenarios, readProjectInstalledRecipes, readScenarioDefinition, resolveRecipeScenarioSelection, } from "../../recipes.js";
|
|
13
12
|
const execFileAsync = promisify(execFile);
|
|
13
|
+
function printJsonSection(label, value) {
|
|
14
|
+
const payload = formatJsonBlock(value, " ");
|
|
15
|
+
if (!payload)
|
|
16
|
+
return;
|
|
17
|
+
process.stdout.write(`${label}:\n${payload}\n`);
|
|
18
|
+
}
|
|
19
|
+
function buildScenarioNotFoundError(recipeId, scenarioId) {
|
|
20
|
+
return new CliError({
|
|
21
|
+
exitCode: exitCodeForError("E_IO"),
|
|
22
|
+
code: "E_IO",
|
|
23
|
+
message: `Scenario not found: ${recipeId}:${scenarioId}`,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
async function resolveScenarioForCli(opts) {
|
|
27
|
+
const installed = await readProjectInstalledRecipes(opts.project);
|
|
28
|
+
const entry = installed.recipes.find((recipe) => recipe.id === opts.recipeId);
|
|
29
|
+
if (!entry) {
|
|
30
|
+
throw new CliError({
|
|
31
|
+
exitCode: exitCodeForError("E_IO"),
|
|
32
|
+
code: "E_IO",
|
|
33
|
+
message: `Recipe not installed: ${opts.recipeId}`,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const selection = await resolveRecipeScenarioSelection({
|
|
38
|
+
project: opts.project,
|
|
39
|
+
flags: {
|
|
40
|
+
recipeId: opts.recipeId,
|
|
41
|
+
scenarioId: opts.scenarioId,
|
|
42
|
+
includeIncompatible: true,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return { entry, selection };
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
49
|
+
if (message.startsWith("No recipe scenario matches")) {
|
|
50
|
+
throw buildScenarioNotFoundError(opts.recipeId, opts.scenarioId);
|
|
51
|
+
}
|
|
52
|
+
if (message.startsWith("Scenario selection is ambiguous")) {
|
|
53
|
+
throw new CliError({
|
|
54
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
55
|
+
code: "E_VALIDATION",
|
|
56
|
+
message,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async function readValidatedScenarioDefinition(opts) {
|
|
63
|
+
if (!(await fileExists(opts.selection.scenario_file))) {
|
|
64
|
+
throw new CliError({
|
|
65
|
+
exitCode: exitCodeForError("E_IO"),
|
|
66
|
+
code: "E_IO",
|
|
67
|
+
message: `Scenario definition not found: ${opts.selection.scenario_file}`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
const scenario = await readScenarioDefinition(opts.selection.scenario_file);
|
|
72
|
+
if (scenario.id !== opts.selection.scenario_id) {
|
|
73
|
+
throw new CliError({
|
|
74
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
75
|
+
code: "E_VALIDATION",
|
|
76
|
+
message: `Scenario definition id mismatch: manifest expects ${opts.selection.scenario_id}, ` +
|
|
77
|
+
`file defines ${scenario.id}`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
return scenario;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (error instanceof CliError)
|
|
84
|
+
throw error;
|
|
85
|
+
throw new CliError({
|
|
86
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
87
|
+
code: "E_VALIDATION",
|
|
88
|
+
message: error instanceof Error ? error.message : String(error),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function validateScenarioRecipeFiles(opts) {
|
|
93
|
+
const checks = [];
|
|
94
|
+
const agents = opts.entry.manifest.agents ?? [];
|
|
95
|
+
const skills = opts.entry.manifest.skills ?? [];
|
|
96
|
+
const tools = opts.entry.manifest.tools ?? [];
|
|
97
|
+
const selectedAgents = agents.filter((agent) => opts.selection.run_profile.agents_involved.includes(agent.id));
|
|
98
|
+
const selectedSkills = skills.filter((skill) => opts.selection.run_profile.skills_used.includes(skill.id));
|
|
99
|
+
const selectedTools = tools.filter((tool) => opts.selection.run_profile.tools_used.includes(tool.id));
|
|
100
|
+
for (const agent of selectedAgents) {
|
|
101
|
+
const agentFile = path.join(opts.selection.recipe_dir, agent.file);
|
|
102
|
+
if (!(await fileExists(agentFile))) {
|
|
103
|
+
throw new CliError({
|
|
104
|
+
exitCode: exitCodeForError("E_IO"),
|
|
105
|
+
code: "E_IO",
|
|
106
|
+
message: `Recipe agent file not found: ${agent.file}`,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
checks.push(`agent files ok: ${selectedAgents.length}`);
|
|
111
|
+
for (const skill of selectedSkills) {
|
|
112
|
+
const skillFile = path.join(opts.selection.recipe_dir, skill.file);
|
|
113
|
+
if (!(await fileExists(skillFile))) {
|
|
114
|
+
throw new CliError({
|
|
115
|
+
exitCode: exitCodeForError("E_IO"),
|
|
116
|
+
code: "E_IO",
|
|
117
|
+
message: `Recipe skill file not found: ${skill.file}`,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
checks.push(`skill files ok: ${selectedSkills.length}`);
|
|
122
|
+
for (const tool of selectedTools) {
|
|
123
|
+
const toolEntrypoint = path.join(opts.selection.recipe_dir, tool.entrypoint);
|
|
124
|
+
if (!(await fileExists(toolEntrypoint))) {
|
|
125
|
+
throw new CliError({
|
|
126
|
+
exitCode: exitCodeForError("E_IO"),
|
|
127
|
+
code: "E_IO",
|
|
128
|
+
message: `Tool entrypoint not found: ${tool.entrypoint}`,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
checks.push(`tool entrypoints ok: ${selectedTools.length}`);
|
|
133
|
+
return checks;
|
|
134
|
+
}
|
|
135
|
+
function assertScenarioCompatibility(selection) {
|
|
136
|
+
if (selection.compatibility.ok)
|
|
137
|
+
return;
|
|
138
|
+
const reasons = selection.compatibility.failures
|
|
139
|
+
.map((failure) => `- ${failure.reason}`)
|
|
140
|
+
.join("\n");
|
|
141
|
+
throw new CliError({
|
|
142
|
+
exitCode: exitCodeForError("E_VALIDATION"),
|
|
143
|
+
code: "E_VALIDATION",
|
|
144
|
+
message: `Scenario is not compatible with the current runtime:\n${reasons}`,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
14
147
|
export function resolveRecipeToolInvocation(runtime, entrypoint, args) {
|
|
15
148
|
if (runtime === "node") {
|
|
16
149
|
return { command: "node", args: [entrypoint, ...args] };
|
|
@@ -22,44 +155,22 @@ export function resolveRecipeToolInvocation(runtime, entrypoint, args) {
|
|
|
22
155
|
}
|
|
23
156
|
export async function cmdScenarioListParsed(opts) {
|
|
24
157
|
try {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
for (const file of jsonFiles) {
|
|
34
|
-
const scenario = await readScenarioDefinition(path.join(scenariosDir, file));
|
|
35
|
-
entries.push({ recipeId: recipe.id, scenarioId: scenario.id, summary: scenario.summary });
|
|
36
|
-
}
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
const scenariosIndexPath = path.join(recipeDir, RECIPES_SCENARIOS_INDEX_NAME);
|
|
40
|
-
if (await fileExists(scenariosIndexPath)) {
|
|
41
|
-
const index = await readScenarioIndex(scenariosIndexPath);
|
|
42
|
-
for (const scenario of index.scenarios) {
|
|
43
|
-
entries.push({
|
|
44
|
-
recipeId: recipe.id,
|
|
45
|
-
scenarioId: scenario.id,
|
|
46
|
-
summary: scenario.summary,
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
158
|
+
const project = await resolveProject({
|
|
159
|
+
cwd: opts.cwd,
|
|
160
|
+
rootOverride: opts.rootOverride ?? null,
|
|
161
|
+
});
|
|
162
|
+
const entries = await listResolvedRecipeScenarios({
|
|
163
|
+
project,
|
|
164
|
+
includeIncompatible: true,
|
|
165
|
+
});
|
|
51
166
|
if (entries.length === 0) {
|
|
52
167
|
process.stdout.write(`${emptyStateMessage("scenarios", "Install a recipe to add scenarios.")}\n`);
|
|
53
168
|
return 0;
|
|
54
169
|
}
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return a.scenarioId.localeCompare(b.scenarioId);
|
|
60
|
-
});
|
|
61
|
-
for (const entry of sorted) {
|
|
62
|
-
process.stdout.write(`${entry.recipeId}:${entry.scenarioId} - ${entry.summary ?? "No summary"}\n`);
|
|
170
|
+
for (const entry of entries) {
|
|
171
|
+
const compatibilityLabel = entry.compatibility.ok ? "compatible" : "incompatible";
|
|
172
|
+
process.stdout.write(`${entry.recipe_id}:${entry.scenario_id} - ${entry.scenario_summary} ` +
|
|
173
|
+
`[mode=${entry.run_profile.mode}] [${compatibilityLabel}]\n`);
|
|
63
174
|
}
|
|
64
175
|
return 0;
|
|
65
176
|
}
|
|
@@ -70,72 +181,33 @@ export async function cmdScenarioListParsed(opts) {
|
|
|
70
181
|
}
|
|
71
182
|
}
|
|
72
183
|
export async function cmdScenarioInfoParsed(opts) {
|
|
73
|
-
const { recipeId, scenarioId } = opts;
|
|
74
184
|
try {
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
const jsonFiles = files.filter((file) => file.toLowerCase().endsWith(".json")).toSorted();
|
|
90
|
-
for (const file of jsonFiles) {
|
|
91
|
-
const candidate = await readScenarioDefinition(path.join(scenariosDir, file));
|
|
92
|
-
if (candidate.id === scenarioId) {
|
|
93
|
-
scenario = candidate;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
let summary;
|
|
99
|
-
if (!scenario) {
|
|
100
|
-
const scenariosIndexPath = path.join(recipeDir, RECIPES_SCENARIOS_INDEX_NAME);
|
|
101
|
-
if (await fileExists(scenariosIndexPath)) {
|
|
102
|
-
const index = await readScenarioIndex(scenariosIndexPath);
|
|
103
|
-
const entrySummary = index.scenarios.find((item) => item.id === scenarioId);
|
|
104
|
-
summary = entrySummary?.summary;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (!scenario && !summary) {
|
|
108
|
-
throw new CliError({
|
|
109
|
-
exitCode: exitCodeForError("E_IO"),
|
|
110
|
-
code: "E_IO",
|
|
111
|
-
message: `Scenario not found: ${recipeId}:${scenarioId}`,
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
process.stdout.write(`Scenario: ${recipeId}:${scenarioId}\n`);
|
|
115
|
-
if (summary)
|
|
116
|
-
process.stdout.write(`Summary: ${summary}\n`);
|
|
117
|
-
if (!scenario) {
|
|
118
|
-
process.stdout.write("Details: Scenario definition not found in recipe.\n");
|
|
119
|
-
return 0;
|
|
185
|
+
const project = await resolveProject({
|
|
186
|
+
cwd: opts.cwd,
|
|
187
|
+
rootOverride: opts.rootOverride ?? null,
|
|
188
|
+
});
|
|
189
|
+
const { selection } = await resolveScenarioForCli({
|
|
190
|
+
project,
|
|
191
|
+
recipeId: opts.recipeId,
|
|
192
|
+
scenarioId: opts.scenarioId,
|
|
193
|
+
});
|
|
194
|
+
process.stdout.write(`Scenario: ${selection.recipe_id}:${selection.scenario_id}\n`);
|
|
195
|
+
process.stdout.write(`Recipe: ${selection.recipe_name} (${selection.recipe_id}@${selection.recipe_version})\n`);
|
|
196
|
+
process.stdout.write(`Summary: ${selection.scenario_summary}\n`);
|
|
197
|
+
if (selection.scenario_description) {
|
|
198
|
+
process.stdout.write(`Description: ${selection.scenario_description}\n`);
|
|
120
199
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
process.stdout.write(`Description: ${scenario.description}\n`);
|
|
125
|
-
process.stdout.write(`Goal: ${scenario.goal}\n`);
|
|
126
|
-
process.stdout.write(`Inputs: ${JSON.stringify(scenario.inputs, null, 2)}\n`);
|
|
127
|
-
process.stdout.write(`Outputs: ${JSON.stringify(scenario.outputs, null, 2)}\n`);
|
|
128
|
-
if (scenario.evidence?.required) {
|
|
129
|
-
process.stdout.write(`Evidence: required (${normalizeExpectedEvidenceFiles(scenario.evidence.files).join(", ")})\n`);
|
|
200
|
+
printJsonSection("Use when", selection.use_when);
|
|
201
|
+
if (selection.avoid_when.length > 0) {
|
|
202
|
+
printJsonSection("Avoid when", selection.avoid_when);
|
|
130
203
|
}
|
|
131
|
-
|
|
132
|
-
|
|
204
|
+
printJsonSection("Run profile", selection.run_profile);
|
|
205
|
+
process.stdout.write(`Scenario file: ${path.relative(project.gitRoot, selection.scenario_file)}\n`);
|
|
206
|
+
if (selection.compatibility.ok) {
|
|
207
|
+
process.stdout.write("Compatibility: satisfied\n");
|
|
133
208
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
for (const step of scenario.steps) {
|
|
137
|
-
process.stdout.write(` ${stepIndex}. ${JSON.stringify(step)}\n`);
|
|
138
|
-
stepIndex += 1;
|
|
209
|
+
else {
|
|
210
|
+
printJsonSection("Compatibility failures", selection.compatibility.failures);
|
|
139
211
|
}
|
|
140
212
|
return 0;
|
|
141
213
|
}
|
|
@@ -188,248 +260,32 @@ export async function executeRecipeTool(opts) {
|
|
|
188
260
|
};
|
|
189
261
|
}
|
|
190
262
|
}
|
|
191
|
-
function sanitizeRunId(value) {
|
|
192
|
-
return value.replaceAll(/[^a-zA-Z0-9._-]/g, "_");
|
|
193
|
-
}
|
|
194
|
-
function normalizeExpectedEvidenceFiles(raw) {
|
|
195
|
-
if (!raw || raw.length === 0)
|
|
196
|
-
return ["evidence.json"];
|
|
197
|
-
const unique = [];
|
|
198
|
-
for (const value of raw) {
|
|
199
|
-
const file = value.trim();
|
|
200
|
-
if (!file)
|
|
201
|
-
continue;
|
|
202
|
-
if (unique.includes(file))
|
|
203
|
-
continue;
|
|
204
|
-
unique.push(file);
|
|
205
|
-
}
|
|
206
|
-
return unique.length > 0 ? unique : ["evidence.json"];
|
|
207
|
-
}
|
|
208
|
-
async function collectStepEvidenceFiles(stepDir, expectedFiles) {
|
|
209
|
-
const present = [];
|
|
210
|
-
const missing = [];
|
|
211
|
-
for (const file of expectedFiles) {
|
|
212
|
-
if (await fileExists(path.join(stepDir, file))) {
|
|
213
|
-
present.push(file);
|
|
214
|
-
}
|
|
215
|
-
else {
|
|
216
|
-
missing.push(file);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
return { present, missing };
|
|
220
|
-
}
|
|
221
263
|
export async function cmdScenarioRunParsed(opts) {
|
|
222
|
-
const
|
|
264
|
+
const project = opts.resolved ??
|
|
223
265
|
(await resolveProject({
|
|
224
266
|
cwd: opts.cwd,
|
|
225
267
|
rootOverride: opts.rootOverride ?? null,
|
|
226
268
|
}));
|
|
227
|
-
const { recipeId, scenarioId } = opts;
|
|
228
269
|
try {
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
exitCode: exitCodeForError("E_IO"),
|
|
234
|
-
code: "E_IO",
|
|
235
|
-
message: `Recipe not installed: ${recipeId}`,
|
|
236
|
-
});
|
|
237
|
-
}
|
|
238
|
-
const recipeDir = resolveInstalledRecipeDir(entry);
|
|
239
|
-
const manifestPath = path.join(recipeDir, "manifest.json");
|
|
240
|
-
const manifest = await readRecipeManifest(manifestPath);
|
|
241
|
-
const scenariosDir = path.join(recipeDir, RECIPES_SCENARIOS_DIR_NAME);
|
|
242
|
-
if ((await getPathKind(scenariosDir)) !== "dir") {
|
|
243
|
-
throw new CliError({
|
|
244
|
-
exitCode: exitCodeForError("E_IO"),
|
|
245
|
-
code: "E_IO",
|
|
246
|
-
message: `Scenario definitions not found for recipe: ${recipeId}`,
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
let scenario = null;
|
|
250
|
-
const files = await readdir(scenariosDir);
|
|
251
|
-
const jsonFiles = files.filter((file) => file.toLowerCase().endsWith(".json")).toSorted();
|
|
252
|
-
for (const file of jsonFiles) {
|
|
253
|
-
const candidate = await readScenarioDefinition(path.join(scenariosDir, file));
|
|
254
|
-
if (candidate.id === scenarioId) {
|
|
255
|
-
scenario = candidate;
|
|
256
|
-
break;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
if (!scenario) {
|
|
260
|
-
throw new CliError({
|
|
261
|
-
exitCode: exitCodeForError("E_IO"),
|
|
262
|
-
code: "E_IO",
|
|
263
|
-
message: `Scenario not found: ${recipeId}:${scenarioId}`,
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
const runsRoot = path.join(resolved.agentplaneDir, RECIPES_DIR_NAME, recipeId, "runs");
|
|
267
|
-
await mkdir(runsRoot, { recursive: true });
|
|
268
|
-
const recipesCacheDir = resolveProjectRecipesCacheDir(resolved);
|
|
269
|
-
await mkdir(recipesCacheDir, { recursive: true });
|
|
270
|
-
const runStartedAt = new Date().toISOString();
|
|
271
|
-
const runId = `${new Date()
|
|
272
|
-
.toISOString()
|
|
273
|
-
.replaceAll(":", "-")
|
|
274
|
-
.replaceAll(".", "-")}-${sanitizeRunId(scenarioId)}`;
|
|
275
|
-
const runDir = path.join(runsRoot, runId);
|
|
276
|
-
await mkdir(runDir, { recursive: true });
|
|
277
|
-
const evidenceRequired = scenario.evidence?.required === true;
|
|
278
|
-
const expectedEvidenceFiles = evidenceRequired
|
|
279
|
-
? normalizeExpectedEvidenceFiles(scenario.evidence?.files)
|
|
280
|
-
: normalizeExpectedEvidenceFiles(scenario.evidence?.files && scenario.evidence.files.length > 0
|
|
281
|
-
? scenario.evidence.files
|
|
282
|
-
: undefined);
|
|
283
|
-
const missingEvidenceSteps = [];
|
|
284
|
-
const stepsMeta = [];
|
|
285
|
-
const stepsReport = [];
|
|
286
|
-
for (let index = 0; index < scenario.steps.length; index++) {
|
|
287
|
-
const step = normalizeScenarioToolStep(scenario.steps[index], `${recipeId}:${scenarioId}`);
|
|
288
|
-
const toolEntry = manifest.tools?.find((tool) => tool?.id === step.tool);
|
|
289
|
-
if (!toolEntry) {
|
|
290
|
-
throw new CliError({
|
|
291
|
-
exitCode: exitCodeForError("E_IO"),
|
|
292
|
-
code: "E_IO",
|
|
293
|
-
message: `Tool not found in recipe manifest: ${step.tool}`,
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
const runtime = toolEntry.runtime === "node" || toolEntry.runtime === "bash"
|
|
297
|
-
? toolEntry.runtime
|
|
298
|
-
: "";
|
|
299
|
-
const entrypoint = typeof toolEntry.entrypoint === "string" ? toolEntry.entrypoint : "";
|
|
300
|
-
if (!runtime || !entrypoint) {
|
|
301
|
-
throw new CliError({
|
|
302
|
-
exitCode: 3,
|
|
303
|
-
code: "E_VALIDATION",
|
|
304
|
-
message: `Tool entry is missing runtime/entrypoint: ${step.tool}`,
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
if (Array.isArray(toolEntry.permissions) && toolEntry.permissions.length > 0) {
|
|
308
|
-
process.stdout.write(`Warning: tool ${toolEntry.id} declares permissions: ${toolEntry.permissions.join(", ")}\n`);
|
|
309
|
-
}
|
|
310
|
-
const entrypointPath = path.join(recipeDir, entrypoint);
|
|
311
|
-
if (!(await fileExists(entrypointPath))) {
|
|
312
|
-
throw new CliError({
|
|
313
|
-
exitCode: exitCodeForError("E_IO"),
|
|
314
|
-
code: "E_IO",
|
|
315
|
-
message: `Tool entrypoint not found: ${entrypoint}`,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
const stepDir = path.join(runDir, `step-${index + 1}-${sanitizeRunId(step.tool)}`);
|
|
319
|
-
await mkdir(stepDir, { recursive: true });
|
|
320
|
-
const stepEnvKeys = collectScenarioEnvKeys(step.env);
|
|
321
|
-
const env = {
|
|
322
|
-
...process.env,
|
|
323
|
-
...step.env,
|
|
324
|
-
AGENTPLANE_RUN_DIR: runDir,
|
|
325
|
-
AGENTPLANE_STEP_DIR: stepDir,
|
|
326
|
-
AGENTPLANE_RECIPES_CACHE_DIR: recipesCacheDir,
|
|
327
|
-
AGENTPLANE_RECIPE_ID: recipeId,
|
|
328
|
-
AGENTPLANE_SCENARIO_ID: scenarioId,
|
|
329
|
-
AGENTPLANE_TOOL_ID: step.tool,
|
|
330
|
-
};
|
|
331
|
-
const startedAt = Date.now();
|
|
332
|
-
const result = await executeRecipeTool({
|
|
333
|
-
runtime,
|
|
334
|
-
entrypoint: entrypointPath,
|
|
335
|
-
args: step.args,
|
|
336
|
-
cwd: recipeDir,
|
|
337
|
-
env,
|
|
338
|
-
});
|
|
339
|
-
const durationMs = Date.now() - startedAt;
|
|
340
|
-
await atomicWriteFile(path.join(stepDir, "stdout.log"), result.stdout, "utf8");
|
|
341
|
-
await atomicWriteFile(path.join(stepDir, "stderr.log"), result.stderr, "utf8");
|
|
342
|
-
const stepEvidence = await collectStepEvidenceFiles(stepDir, expectedEvidenceFiles);
|
|
343
|
-
const missingRequiredEvidence = evidenceRequired ? stepEvidence.missing : [];
|
|
344
|
-
if (missingRequiredEvidence.length > 0) {
|
|
345
|
-
missingEvidenceSteps.push(index + 1);
|
|
346
|
-
}
|
|
347
|
-
stepsMeta.push({
|
|
348
|
-
tool: step.tool,
|
|
349
|
-
runtime,
|
|
350
|
-
entrypoint,
|
|
351
|
-
exitCode: result.exitCode,
|
|
352
|
-
duration_ms: durationMs,
|
|
353
|
-
});
|
|
354
|
-
stepsReport.push({
|
|
355
|
-
step: index + 1,
|
|
356
|
-
tool: step.tool,
|
|
357
|
-
runtime,
|
|
358
|
-
entrypoint,
|
|
359
|
-
args: redactArgs(step.args),
|
|
360
|
-
env_keys: stepEnvKeys,
|
|
361
|
-
evidence_files: stepEvidence.present,
|
|
362
|
-
missing_evidence_files: missingRequiredEvidence.length > 0 ? missingRequiredEvidence : undefined,
|
|
363
|
-
exit_code: result.exitCode,
|
|
364
|
-
duration_ms: durationMs,
|
|
365
|
-
});
|
|
366
|
-
if (result.exitCode !== 0 || missingRequiredEvidence.length > 0) {
|
|
367
|
-
const gitSummary = await getGitDiffSummary(resolved.gitRoot);
|
|
368
|
-
await writeScenarioReport({
|
|
369
|
-
runDir,
|
|
370
|
-
recipeId,
|
|
371
|
-
scenarioId,
|
|
372
|
-
runId,
|
|
373
|
-
startedAt: runStartedAt,
|
|
374
|
-
status: "failed",
|
|
375
|
-
steps: stepsReport,
|
|
376
|
-
evidence: {
|
|
377
|
-
required: evidenceRequired,
|
|
378
|
-
expected_files: expectedEvidenceFiles,
|
|
379
|
-
missing_steps: missingEvidenceSteps,
|
|
380
|
-
},
|
|
381
|
-
gitSummary,
|
|
382
|
-
});
|
|
383
|
-
await atomicWriteFile(path.join(runDir, "meta.json"), `${JSON.stringify({
|
|
384
|
-
recipe: recipeId,
|
|
385
|
-
scenario: scenarioId,
|
|
386
|
-
run_id: runId,
|
|
387
|
-
evidence: {
|
|
388
|
-
required: evidenceRequired,
|
|
389
|
-
expected_files: expectedEvidenceFiles,
|
|
390
|
-
missing_steps: missingEvidenceSteps,
|
|
391
|
-
},
|
|
392
|
-
steps: stepsMeta,
|
|
393
|
-
}, null, 2)}\n`, "utf8");
|
|
394
|
-
const reason = missingRequiredEvidence.length > 0
|
|
395
|
-
? `Scenario step missing required evidence: ${step.tool} (${missingRequiredEvidence.join(", ")})`
|
|
396
|
-
: `Scenario step failed: ${step.tool}`;
|
|
397
|
-
const stepExitCode = result.exitCode === 0 ? 1 : result.exitCode;
|
|
398
|
-
throw new CliError({
|
|
399
|
-
exitCode: stepExitCode,
|
|
400
|
-
code: "E_INTERNAL",
|
|
401
|
-
message: reason,
|
|
402
|
-
});
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
const gitSummary = await getGitDiffSummary(resolved.gitRoot);
|
|
406
|
-
await writeScenarioReport({
|
|
407
|
-
runDir,
|
|
408
|
-
recipeId,
|
|
409
|
-
scenarioId,
|
|
410
|
-
runId,
|
|
411
|
-
startedAt: runStartedAt,
|
|
412
|
-
status: "success",
|
|
413
|
-
steps: stepsReport,
|
|
414
|
-
evidence: {
|
|
415
|
-
required: evidenceRequired,
|
|
416
|
-
expected_files: expectedEvidenceFiles,
|
|
417
|
-
missing_steps: missingEvidenceSteps,
|
|
418
|
-
},
|
|
419
|
-
gitSummary,
|
|
270
|
+
const { entry, selection } = await resolveScenarioForCli({
|
|
271
|
+
project,
|
|
272
|
+
recipeId: opts.recipeId,
|
|
273
|
+
scenarioId: opts.scenarioId,
|
|
420
274
|
});
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
275
|
+
assertScenarioCompatibility(selection);
|
|
276
|
+
const scenarioDefinition = await readValidatedScenarioDefinition({ selection });
|
|
277
|
+
const validationChecks = await validateScenarioRecipeFiles({ entry, selection });
|
|
278
|
+
process.stdout.write(`Prepared run plan: ${selection.recipe_id}:${selection.scenario_id}\n`);
|
|
279
|
+
process.stdout.write(`Recipe: ${selection.recipe_name} (${selection.recipe_id}@${selection.recipe_version})\n`);
|
|
280
|
+
process.stdout.write(`Goal: ${scenarioDefinition.goal}\n`);
|
|
281
|
+
process.stdout.write(`Scenario file: ${path.relative(project.gitRoot, selection.scenario_file)}\n`);
|
|
282
|
+
printJsonSection("Run profile", selection.run_profile);
|
|
283
|
+
printJsonSection("Selection reasons", selection.selection_reasons);
|
|
284
|
+
printJsonSection("Validation", [
|
|
285
|
+
`scenario definition ok: ${path.relative(project.gitRoot, selection.scenario_file)}`,
|
|
286
|
+
...validationChecks,
|
|
287
|
+
]);
|
|
288
|
+
process.stdout.write("Status: scenario orchestration runtime is not implemented yet.\n");
|
|
433
289
|
return 0;
|
|
434
290
|
}
|
|
435
291
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"info.command.d.ts","sourceRoot":"","sources":["../../../src/commands/scenario/info.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1E,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,
|
|
1
|
+
{"version":3,"file":"info.command.d.ts","sourceRoot":"","sources":["../../../src/commands/scenario/info.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1E,MAAM,MAAM,kBAAkB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,CAuB5D,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,kBAAkB,CAM3D,CAAC"}
|
|
@@ -3,9 +3,14 @@ import { cmdScenarioInfoParsed } from "../scenario.js";
|
|
|
3
3
|
export const scenarioInfoSpec = {
|
|
4
4
|
id: ["scenario", "info"],
|
|
5
5
|
group: "Scenario",
|
|
6
|
-
summary: "Show scenario details
|
|
6
|
+
summary: "Show manifest-backed scenario details and normalized run profile.",
|
|
7
7
|
args: [{ name: "id", required: true, valueHint: "<recipe:scenario>" }],
|
|
8
|
-
examples: [
|
|
8
|
+
examples: [
|
|
9
|
+
{
|
|
10
|
+
cmd: "agentplane scenario info viewer:demo",
|
|
11
|
+
why: "Inspect resolver-backed scenario metadata before execution.",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
9
14
|
parse: (raw) => {
|
|
10
15
|
const id = String(raw.args.id ?? "");
|
|
11
16
|
const [recipeId, scenarioId] = id.split(":", 2);
|
|
@@ -2,8 +2,8 @@ import { cmdScenarioListParsed } from "../scenario.js";
|
|
|
2
2
|
export const scenarioListSpec = {
|
|
3
3
|
id: ["scenario", "list"],
|
|
4
4
|
group: "Scenario",
|
|
5
|
-
summary: "List
|
|
5
|
+
summary: "List resolver-backed scenario descriptors from installed recipes.",
|
|
6
6
|
parse: () => ({}),
|
|
7
|
-
examples: [{ cmd: "agentplane scenario list", why: "List scenarios." }],
|
|
7
|
+
examples: [{ cmd: "agentplane scenario list", why: "List available recipe scenarios." }],
|
|
8
8
|
};
|
|
9
9
|
export const runScenarioList = (ctx) => cmdScenarioListParsed({ cwd: ctx.cwd, rootOverride: ctx.rootOverride });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.command.d.ts","sourceRoot":"","sources":["../../../src/commands/scenario/run.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1E,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,iBAAiB,
|
|
1
|
+
{"version":3,"file":"run.command.d.ts","sourceRoot":"","sources":["../../../src/commands/scenario/run.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAI1E,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,iBAAiB,CAuB1D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,iBAAiB,CAMzD,CAAC"}
|
|
@@ -3,9 +3,14 @@ import { cmdScenarioRunParsed } from "../scenario.js";
|
|
|
3
3
|
export const scenarioRunSpec = {
|
|
4
4
|
id: ["scenario", "run"],
|
|
5
5
|
group: "Scenario",
|
|
6
|
-
summary: "
|
|
6
|
+
summary: "Validate a scenario and print a prepared run plan (no execution).",
|
|
7
7
|
args: [{ name: "id", required: true, valueHint: "<recipe:scenario>" }],
|
|
8
|
-
examples: [
|
|
8
|
+
examples: [
|
|
9
|
+
{
|
|
10
|
+
cmd: "agentplane scenario run viewer:demo",
|
|
11
|
+
why: "Validate a scenario and inspect the prepared run plan.",
|
|
12
|
+
},
|
|
13
|
+
],
|
|
9
14
|
parse: (raw) => {
|
|
10
15
|
const id = String(raw.args.id ?? "");
|
|
11
16
|
const [recipeId, scenarioId] = id.split(":", 2);
|
|
@@ -7,6 +7,7 @@ export declare class GitContext {
|
|
|
7
7
|
private statusPorcelainZ;
|
|
8
8
|
statusChangedPaths(): Promise<string[]>;
|
|
9
9
|
statusStagedPaths(): Promise<string[]>;
|
|
10
|
+
statusUntrackedPaths(): Promise<string[]>;
|
|
10
11
|
statusUnstagedTrackedPaths(): Promise<string[]>;
|
|
11
12
|
headCommit(): Promise<string>;
|
|
12
13
|
stage(paths: string[]): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-context.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git-context.ts"],"names":[],"mappings":"AAyEA,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,IAAI,CAGL;gBAEK,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;YAIvB,gBAAgB;IAmBxB,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKvC,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC,0BAA0B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKrD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAWvB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxF,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpE,eAAe,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAWpE"}
|
|
1
|
+
{"version":3,"file":"git-context.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git-context.ts"],"names":[],"mappings":"AAyEA,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAEzB,OAAO,CAAC,IAAI,CAGL;gBAEK,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE;YAIvB,gBAAgB;IAmBxB,kBAAkB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKvC,iBAAiB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKtC,oBAAoB,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKzC,0BAA0B,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAKrD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAWvB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrC,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcxF,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpE,eAAe,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAWpE"}
|
|
@@ -87,6 +87,10 @@ export class GitContext {
|
|
|
87
87
|
const status = await this.statusPorcelainZ();
|
|
88
88
|
return status.stagedPaths;
|
|
89
89
|
}
|
|
90
|
+
async statusUntrackedPaths() {
|
|
91
|
+
const status = await this.statusPorcelainZ();
|
|
92
|
+
return status.untrackedPaths;
|
|
93
|
+
}
|
|
90
94
|
async statusUnstagedTrackedPaths() {
|
|
91
95
|
const status = await this.statusPorcelainZ();
|
|
92
96
|
return status.unstagedTrackedPaths;
|