agentplane 0.2.24 → 0.2.26
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/bin/agentplane.js +91 -54
- package/dist/.build-manifest.json +11 -0
- package/dist/backends/task-backend/local-backend.d.ts +2 -0
- package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/local-backend.js +12 -1
- package/dist/backends/task-backend/redmine/mapping.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine/mapping.js +26 -1
- package/dist/backends/task-backend/redmine-backend.d.ts +4 -0
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +92 -9
- package/dist/backends/task-backend/shared/types.d.ts +1 -0
- package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
- package/dist/backends/task-index.d.ts.map +1 -1
- package/dist/backends/task-index.js +8 -1
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +21 -8
- package/dist/cli/command-snippets.d.ts +24 -0
- package/dist/cli/command-snippets.d.ts.map +1 -0
- package/dist/cli/command-snippets.js +23 -0
- package/dist/cli/reason-codes.d.ts +9 -0
- package/dist/cli/reason-codes.d.ts.map +1 -0
- package/dist/cli/reason-codes.js +79 -0
- package/dist/cli/recipes-bundled.d.ts +1 -0
- package/dist/cli/recipes-bundled.d.ts.map +1 -1
- package/dist/cli/recipes-bundled.js +4 -1
- package/dist/cli/run-cli/command-catalog.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog.js +40 -1
- package/dist/cli/run-cli/commands/config.d.ts +5 -0
- package/dist/cli/run-cli/commands/config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/config.js +86 -1
- package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/core.js +55 -0
- package/dist/cli/run-cli/commands/init/recipes.d.ts +5 -1
- package/dist/cli/run-cli/commands/init/recipes.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/recipes.js +24 -4
- package/dist/cli/run-cli/commands/init/write-workflow.d.ts +7 -0
- package/dist/cli/run-cli/commands/init/write-workflow.d.ts.map +1 -0
- package/dist/cli/run-cli/commands/init/write-workflow.js +52 -0
- package/dist/cli/run-cli/commands/init.d.ts +2 -1
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +104 -54
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +70 -1
- package/dist/commands/backend/sync.command.d.ts.map +1 -1
- package/dist/commands/backend/sync.command.js +7 -6
- package/dist/commands/backend.d.ts.map +1 -1
- package/dist/commands/backend.js +2 -0
- package/dist/commands/block.spec.d.ts.map +1 -1
- package/dist/commands/block.spec.js +23 -2
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +18 -6
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +96 -10
- package/dist/commands/finish.spec.d.ts.map +1 -1
- package/dist/commands/finish.spec.js +53 -4
- package/dist/commands/guard/commit.command.d.ts.map +1 -1
- package/dist/commands/guard/commit.command.js +26 -20
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +8 -1
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +19 -21
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +8 -17
- package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +36 -13
- package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
- package/dist/commands/recipes/impl/scenario.js +25 -0
- package/dist/commands/recipes/impl/types.d.ts +4 -0
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.js +74 -3
- package/dist/commands/scenario/impl/report.d.ts +8 -0
- package/dist/commands/scenario/impl/report.d.ts.map +1 -1
- package/dist/commands/scenario/impl/report.js +1 -0
- package/dist/commands/shared/reconcile-check.d.ts +7 -0
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -0
- package/dist/commands/shared/reconcile-check.js +60 -0
- package/dist/commands/start.spec.d.ts.map +1 -1
- package/dist/commands/start.spec.js +23 -2
- package/dist/commands/sync.command.d.ts.map +1 -1
- package/dist/commands/sync.command.js +9 -2
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +34 -10
- package/dist/commands/task/list.d.ts.map +1 -1
- package/dist/commands/task/list.js +2 -1
- package/dist/commands/task/list.spec.d.ts.map +1 -1
- package/dist/commands/task/list.spec.js +7 -0
- package/dist/commands/task/next.d.ts.map +1 -1
- package/dist/commands/task/next.js +2 -1
- package/dist/commands/task/next.spec.d.ts.map +1 -1
- package/dist/commands/task/next.spec.js +7 -0
- package/dist/commands/task/search.d.ts.map +1 -1
- package/dist/commands/task/search.js +2 -1
- package/dist/commands/task/search.spec.d.ts.map +1 -1
- package/dist/commands/task/search.spec.js +7 -0
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +22 -2
- package/dist/commands/task/shared.d.ts +7 -0
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +21 -1
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +2 -0
- package/dist/commands/workflow-build.command.d.ts +8 -0
- package/dist/commands/workflow-build.command.d.ts.map +1 -0
- package/dist/commands/workflow-build.command.js +96 -0
- package/dist/commands/workflow-playbook.command.d.ts +10 -0
- package/dist/commands/workflow-playbook.command.d.ts.map +1 -0
- package/dist/commands/workflow-playbook.command.js +174 -0
- package/dist/commands/workflow-restore.command.d.ts +5 -0
- package/dist/commands/workflow-restore.command.d.ts.map +1 -0
- package/dist/commands/workflow-restore.command.js +30 -0
- package/dist/commands/workflow.command.d.ts +6 -0
- package/dist/commands/workflow.command.d.ts.map +1 -0
- package/dist/commands/workflow.command.js +36 -0
- package/dist/harness/dynamic-tool-contract.d.ts +29 -0
- package/dist/harness/dynamic-tool-contract.d.ts.map +1 -0
- package/dist/harness/dynamic-tool-contract.js +86 -0
- package/dist/harness/hooks-lifecycle.d.ts +27 -0
- package/dist/harness/hooks-lifecycle.d.ts.map +1 -0
- package/dist/harness/hooks-lifecycle.js +67 -0
- package/dist/harness/index.d.ts +9 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +8 -0
- package/dist/harness/reconcile.d.ts +37 -0
- package/dist/harness/reconcile.d.ts.map +1 -0
- package/dist/harness/reconcile.js +42 -0
- package/dist/harness/retry-policy.d.ts +31 -0
- package/dist/harness/retry-policy.d.ts.map +1 -0
- package/dist/harness/retry-policy.js +33 -0
- package/dist/harness/scheduler.d.ts +18 -0
- package/dist/harness/scheduler.d.ts.map +1 -0
- package/dist/harness/scheduler.js +55 -0
- package/dist/harness/state-machine.d.ts +17 -0
- package/dist/harness/state-machine.d.ts.map +1 -0
- package/dist/harness/state-machine.js +70 -0
- package/dist/harness/token-accounting.d.ts +19 -0
- package/dist/harness/token-accounting.d.ts.map +1 -0
- package/dist/harness/token-accounting.js +77 -0
- package/dist/harness/workspace-safety.d.ts +14 -0
- package/dist/harness/workspace-safety.d.ts.map +1 -0
- package/dist/harness/workspace-safety.js +62 -0
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +9 -0
- package/dist/recipes/bundled-recipes.d.ts +4 -0
- package/dist/recipes/bundled-recipes.d.ts.map +1 -1
- package/dist/recipes/bundled-recipes.js +11 -0
- package/dist/shared/allow-prefix-policy.d.ts +3 -0
- package/dist/shared/allow-prefix-policy.d.ts.map +1 -0
- package/dist/shared/allow-prefix-policy.js +8 -0
- package/dist/shared/errors.d.ts +6 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +1 -0
- package/dist/workflow-runtime/build.d.ts +4 -0
- package/dist/workflow-runtime/build.d.ts.map +1 -0
- package/dist/workflow-runtime/build.js +114 -0
- package/dist/workflow-runtime/enforcement.d.ts +3 -0
- package/dist/workflow-runtime/enforcement.d.ts.map +1 -0
- package/dist/workflow-runtime/enforcement.js +10 -0
- package/dist/workflow-runtime/file-ops.d.ts +11 -0
- package/dist/workflow-runtime/file-ops.d.ts.map +1 -0
- package/dist/workflow-runtime/file-ops.js +248 -0
- package/dist/workflow-runtime/fix.d.ts +9 -0
- package/dist/workflow-runtime/fix.d.ts.map +1 -0
- package/dist/workflow-runtime/fix.js +107 -0
- package/dist/workflow-runtime/index.d.ts +11 -0
- package/dist/workflow-runtime/index.d.ts.map +1 -0
- package/dist/workflow-runtime/index.js +10 -0
- package/dist/workflow-runtime/markdown.d.ts +10 -0
- package/dist/workflow-runtime/markdown.d.ts.map +1 -0
- package/dist/workflow-runtime/markdown.js +147 -0
- package/dist/workflow-runtime/observability.d.ts +12 -0
- package/dist/workflow-runtime/observability.d.ts.map +1 -0
- package/dist/workflow-runtime/observability.js +14 -0
- package/dist/workflow-runtime/paths.d.ts +3 -0
- package/dist/workflow-runtime/paths.d.ts.map +1 -0
- package/dist/workflow-runtime/paths.js +11 -0
- package/dist/workflow-runtime/template.d.ts +7 -0
- package/dist/workflow-runtime/template.d.ts.map +1 -0
- package/dist/workflow-runtime/template.js +94 -0
- package/dist/workflow-runtime/types.d.ts +68 -0
- package/dist/workflow-runtime/types.d.ts.map +1 -0
- package/dist/workflow-runtime/types.js +1 -0
- package/dist/workflow-runtime/validate.d.ts +8 -0
- package/dist/workflow-runtime/validate.d.ts.map +1 -0
- package/dist/workflow-runtime/validate.js +331 -0
- package/package.json +3 -3
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { loadConfig } from "@agentplaneorg/core";
|
|
4
|
+
import { parseWorkflowMarkdown } from "./markdown.js";
|
|
5
|
+
import { emitWorkflowEvent } from "./observability.js";
|
|
6
|
+
import { resolveWorkflowPaths } from "./paths.js";
|
|
7
|
+
import { validateWorkflowDocument } from "./validate.js";
|
|
8
|
+
async function pathExists(absPath) {
|
|
9
|
+
try {
|
|
10
|
+
await fs.access(absPath);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function resolveWorkflowReadPath(paths) {
|
|
18
|
+
if (await pathExists(paths.workflowPath))
|
|
19
|
+
return paths.workflowPath;
|
|
20
|
+
if (await pathExists(paths.legacyWorkflowPath))
|
|
21
|
+
return paths.legacyWorkflowPath;
|
|
22
|
+
return paths.workflowPath;
|
|
23
|
+
}
|
|
24
|
+
async function removeLegacyWorkflowIfPresent(paths) {
|
|
25
|
+
if (paths.workflowPath === paths.legacyWorkflowPath)
|
|
26
|
+
return;
|
|
27
|
+
try {
|
|
28
|
+
await fs.rm(paths.legacyWorkflowPath, { force: true });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// best effort cleanup
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
async function listAgentIds(agentplaneDir) {
|
|
35
|
+
const ids = new Set();
|
|
36
|
+
const dir = path.join(agentplaneDir, "agents");
|
|
37
|
+
try {
|
|
38
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
39
|
+
for (const ent of entries) {
|
|
40
|
+
if (ent.isFile() && ent.name.endsWith(".json")) {
|
|
41
|
+
ids.add(ent.name.replace(/\.json$/i, ""));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// best effort
|
|
47
|
+
}
|
|
48
|
+
return ids;
|
|
49
|
+
}
|
|
50
|
+
export async function readWorkflowDocument(repoRoot, absPath) {
|
|
51
|
+
const paths = resolveWorkflowPaths(repoRoot);
|
|
52
|
+
const targetPath = absPath ?? (await resolveWorkflowReadPath(paths));
|
|
53
|
+
try {
|
|
54
|
+
const content = await fs.readFile(targetPath, "utf8");
|
|
55
|
+
const parsed = parseWorkflowMarkdown(content, targetPath);
|
|
56
|
+
return {
|
|
57
|
+
document: parsed.document,
|
|
58
|
+
diagnostics: parsed.diagnostics,
|
|
59
|
+
path: targetPath,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return {
|
|
64
|
+
document: null,
|
|
65
|
+
diagnostics: [
|
|
66
|
+
{
|
|
67
|
+
code: (await pathExists(targetPath)) ? "WF_READ_FAILED" : "WF_MISSING_FILE",
|
|
68
|
+
severity: "ERROR",
|
|
69
|
+
path: "file",
|
|
70
|
+
message: `Cannot read workflow file ${targetPath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
path: targetPath,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export async function validateWorkflowAtPath(repoRoot, absPath) {
|
|
78
|
+
const read = await readWorkflowDocument(repoRoot, absPath);
|
|
79
|
+
const diagnostics = [...read.diagnostics];
|
|
80
|
+
if (!read.document) {
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
diagnostics,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const loaded = await loadConfig(path.join(repoRoot, ".agentplane"));
|
|
87
|
+
const knownAgentIds = await listAgentIds(path.join(repoRoot, ".agentplane"));
|
|
88
|
+
const validated = validateWorkflowDocument(read.document, {
|
|
89
|
+
repoRoot,
|
|
90
|
+
knownAgentIds,
|
|
91
|
+
config: loaded.config,
|
|
92
|
+
});
|
|
93
|
+
diagnostics.push(...validated.diagnostics);
|
|
94
|
+
return {
|
|
95
|
+
ok: diagnostics.every((d) => d.severity !== "ERROR"),
|
|
96
|
+
diagnostics,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export async function validateWorkflowText(repoRoot, workflowText) {
|
|
100
|
+
const parsed = parseWorkflowMarkdown(workflowText);
|
|
101
|
+
const loaded = await loadConfig(path.join(repoRoot, ".agentplane"));
|
|
102
|
+
const knownAgentIds = await listAgentIds(path.join(repoRoot, ".agentplane"));
|
|
103
|
+
const validated = validateWorkflowDocument(parsed.document, {
|
|
104
|
+
repoRoot,
|
|
105
|
+
knownAgentIds,
|
|
106
|
+
config: loaded.config,
|
|
107
|
+
});
|
|
108
|
+
return {
|
|
109
|
+
ok: [...parsed.diagnostics, ...validated.diagnostics].every((d) => d.severity !== "ERROR"),
|
|
110
|
+
diagnostics: [...parsed.diagnostics, ...validated.diagnostics],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
export async function publishWorkflowCandidate(repoRoot, candidateText) {
|
|
114
|
+
const paths = resolveWorkflowPaths(repoRoot);
|
|
115
|
+
const tempPath = `${paths.workflowPath}.tmp.${Date.now()}`;
|
|
116
|
+
const parsed = parseWorkflowMarkdown(candidateText, paths.workflowPath);
|
|
117
|
+
const configLoaded = await loadConfig(path.join(repoRoot, ".agentplane"));
|
|
118
|
+
const validation = validateWorkflowDocument(parsed.document, {
|
|
119
|
+
repoRoot,
|
|
120
|
+
knownAgentIds: await listAgentIds(path.join(repoRoot, ".agentplane")),
|
|
121
|
+
config: configLoaded.config,
|
|
122
|
+
});
|
|
123
|
+
const diagnostics = [...parsed.diagnostics, ...validation.diagnostics];
|
|
124
|
+
if (diagnostics.some((d) => d.severity === "ERROR")) {
|
|
125
|
+
emitWorkflowEvent({
|
|
126
|
+
event: "workflow_publish_failed",
|
|
127
|
+
code: "WF_PARSE_ERROR",
|
|
128
|
+
details: { reason: "validation failed before publish", diagnostics: diagnostics.length },
|
|
129
|
+
});
|
|
130
|
+
return { ok: false, diagnostics };
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
await fs.mkdir(path.dirname(paths.workflowPath), { recursive: true });
|
|
134
|
+
await fs.mkdir(paths.workflowDir, { recursive: true });
|
|
135
|
+
await fs.writeFile(tempPath, candidateText, "utf8");
|
|
136
|
+
await fs.rename(tempPath, paths.workflowPath);
|
|
137
|
+
await removeLegacyWorkflowIfPresent(paths);
|
|
138
|
+
await fs.copyFile(paths.workflowPath, paths.lastKnownGoodPath);
|
|
139
|
+
emitWorkflowEvent({
|
|
140
|
+
event: "workflow_publish_completed",
|
|
141
|
+
details: { workflowPath: paths.workflowPath, lastKnownGoodPath: paths.lastKnownGoodPath },
|
|
142
|
+
});
|
|
143
|
+
return { ok: true, diagnostics };
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
try {
|
|
147
|
+
await fs.rm(tempPath, { force: true });
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// best effort cleanup
|
|
151
|
+
}
|
|
152
|
+
emitWorkflowEvent({
|
|
153
|
+
event: "workflow_publish_failed",
|
|
154
|
+
code: "WF_READ_FAILED",
|
|
155
|
+
details: { reason: error instanceof Error ? error.message : String(error) },
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
ok: false,
|
|
159
|
+
diagnostics: [
|
|
160
|
+
...diagnostics,
|
|
161
|
+
{
|
|
162
|
+
code: "WF_READ_FAILED",
|
|
163
|
+
severity: "ERROR",
|
|
164
|
+
path: "file",
|
|
165
|
+
message: `Failed to atomically publish workflow: ${error instanceof Error ? error.message : String(error)}`,
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export async function restoreWorkflowFromLastKnownGood(repoRoot) {
|
|
172
|
+
const paths = resolveWorkflowPaths(repoRoot);
|
|
173
|
+
const tempPath = `${paths.workflowPath}.restore.tmp.${Date.now()}`;
|
|
174
|
+
let lkgText = "";
|
|
175
|
+
try {
|
|
176
|
+
lkgText = await fs.readFile(paths.lastKnownGoodPath, "utf8");
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
emitWorkflowEvent({
|
|
180
|
+
event: "workflow_restore_failed",
|
|
181
|
+
code: "WF_MISSING_FILE",
|
|
182
|
+
details: { reason: error instanceof Error ? error.message : String(error) },
|
|
183
|
+
});
|
|
184
|
+
return {
|
|
185
|
+
ok: false,
|
|
186
|
+
diagnostics: [
|
|
187
|
+
{
|
|
188
|
+
code: "WF_MISSING_FILE",
|
|
189
|
+
severity: "ERROR",
|
|
190
|
+
path: "file",
|
|
191
|
+
message: `Missing last-known-good workflow snapshot at ${paths.lastKnownGoodPath}`,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
const parsed = parseWorkflowMarkdown(lkgText, paths.lastKnownGoodPath);
|
|
197
|
+
const configLoaded = await loadConfig(path.join(repoRoot, ".agentplane"));
|
|
198
|
+
const validated = validateWorkflowDocument(parsed.document, {
|
|
199
|
+
repoRoot,
|
|
200
|
+
knownAgentIds: await listAgentIds(path.join(repoRoot, ".agentplane")),
|
|
201
|
+
config: configLoaded.config,
|
|
202
|
+
});
|
|
203
|
+
const diagnostics = [...parsed.diagnostics, ...validated.diagnostics];
|
|
204
|
+
if (diagnostics.some((d) => d.severity === "ERROR")) {
|
|
205
|
+
emitWorkflowEvent({
|
|
206
|
+
event: "workflow_restore_failed",
|
|
207
|
+
code: "WF_PARSE_ERROR",
|
|
208
|
+
details: { reason: "last-known-good validation failed" },
|
|
209
|
+
});
|
|
210
|
+
return { ok: false, diagnostics };
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
await fs.mkdir(path.dirname(paths.workflowPath), { recursive: true });
|
|
214
|
+
await fs.writeFile(tempPath, lkgText, "utf8");
|
|
215
|
+
await fs.rename(tempPath, paths.workflowPath);
|
|
216
|
+
await removeLegacyWorkflowIfPresent(paths);
|
|
217
|
+
emitWorkflowEvent({
|
|
218
|
+
event: "workflow_restore_completed",
|
|
219
|
+
details: { workflowPath: paths.workflowPath, from: paths.lastKnownGoodPath },
|
|
220
|
+
});
|
|
221
|
+
return { ok: true, diagnostics };
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
try {
|
|
225
|
+
await fs.rm(tempPath, { force: true });
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// best effort cleanup
|
|
229
|
+
}
|
|
230
|
+
emitWorkflowEvent({
|
|
231
|
+
event: "workflow_restore_failed",
|
|
232
|
+
code: "WF_READ_FAILED",
|
|
233
|
+
details: { reason: error instanceof Error ? error.message : String(error) },
|
|
234
|
+
});
|
|
235
|
+
return {
|
|
236
|
+
ok: false,
|
|
237
|
+
diagnostics: [
|
|
238
|
+
...diagnostics,
|
|
239
|
+
{
|
|
240
|
+
code: "WF_READ_FAILED",
|
|
241
|
+
severity: "ERROR",
|
|
242
|
+
path: "file",
|
|
243
|
+
message: `Failed to restore workflow from snapshot: ${error instanceof Error ? error.message : String(error)}`,
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { WorkflowDiagnostic } from "./types.js";
|
|
2
|
+
type WorkflowFixResult = {
|
|
3
|
+
changed: boolean;
|
|
4
|
+
text: string;
|
|
5
|
+
diagnostics: WorkflowDiagnostic[];
|
|
6
|
+
};
|
|
7
|
+
export declare function safeAutofixWorkflowText(text: string): WorkflowFixResult;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=fix.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fix.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/fix.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAuB,MAAM,YAAY,CAAC;AAE1E,KAAK,iBAAiB,GAAG;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC,CAAC;AAoFF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA6CvE"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { parseWorkflowMarkdown, serializeWorkflowMarkdown } from "./markdown.js";
|
|
2
|
+
const DEFAULT_FRONT_MATTER = {
|
|
3
|
+
version: 1,
|
|
4
|
+
mode: "direct",
|
|
5
|
+
owners: { orchestrator: "ORCHESTRATOR" },
|
|
6
|
+
approvals: {
|
|
7
|
+
require_plan: true,
|
|
8
|
+
require_verify: true,
|
|
9
|
+
require_network: true,
|
|
10
|
+
},
|
|
11
|
+
retry_policy: {
|
|
12
|
+
normal_exit_continuation: true,
|
|
13
|
+
abnormal_backoff: "exponential",
|
|
14
|
+
max_attempts: 5,
|
|
15
|
+
},
|
|
16
|
+
timeouts: {
|
|
17
|
+
stall_seconds: 900,
|
|
18
|
+
},
|
|
19
|
+
in_scope_paths: ["packages/**"],
|
|
20
|
+
};
|
|
21
|
+
function isRecord(value) {
|
|
22
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
23
|
+
}
|
|
24
|
+
function withDefaults(raw) {
|
|
25
|
+
const out = { ...raw };
|
|
26
|
+
if (typeof out.version !== "number" || !Number.isInteger(out.version) || out.version < 1) {
|
|
27
|
+
out.version = 1;
|
|
28
|
+
}
|
|
29
|
+
if (out.mode !== "direct" && out.mode !== "branch_pr") {
|
|
30
|
+
out.mode = DEFAULT_FRONT_MATTER.mode;
|
|
31
|
+
}
|
|
32
|
+
const owners = isRecord(out.owners) ? { ...out.owners } : {};
|
|
33
|
+
if (typeof owners.orchestrator !== "string" || owners.orchestrator.trim().length === 0) {
|
|
34
|
+
owners.orchestrator = DEFAULT_FRONT_MATTER.owners.orchestrator;
|
|
35
|
+
}
|
|
36
|
+
out.owners = owners;
|
|
37
|
+
const approvals = isRecord(out.approvals) ? { ...out.approvals } : {};
|
|
38
|
+
for (const key of ["require_plan", "require_verify", "require_network"]) {
|
|
39
|
+
if (typeof approvals[key] !== "boolean")
|
|
40
|
+
approvals[key] = DEFAULT_FRONT_MATTER.approvals[key];
|
|
41
|
+
}
|
|
42
|
+
out.approvals = approvals;
|
|
43
|
+
const retryPolicy = isRecord(out.retry_policy) ? { ...out.retry_policy } : {};
|
|
44
|
+
if (typeof retryPolicy.normal_exit_continuation !== "boolean") {
|
|
45
|
+
retryPolicy.normal_exit_continuation =
|
|
46
|
+
DEFAULT_FRONT_MATTER.retry_policy.normal_exit_continuation;
|
|
47
|
+
}
|
|
48
|
+
if (retryPolicy.abnormal_backoff !== "exponential") {
|
|
49
|
+
retryPolicy.abnormal_backoff = DEFAULT_FRONT_MATTER.retry_policy.abnormal_backoff;
|
|
50
|
+
}
|
|
51
|
+
if (typeof retryPolicy.max_attempts !== "number" ||
|
|
52
|
+
!Number.isInteger(retryPolicy.max_attempts) ||
|
|
53
|
+
retryPolicy.max_attempts < 1) {
|
|
54
|
+
retryPolicy.max_attempts = DEFAULT_FRONT_MATTER.retry_policy.max_attempts;
|
|
55
|
+
}
|
|
56
|
+
out.retry_policy = retryPolicy;
|
|
57
|
+
const timeouts = isRecord(out.timeouts) ? { ...out.timeouts } : {};
|
|
58
|
+
if (typeof timeouts.stall_seconds !== "number" ||
|
|
59
|
+
!Number.isInteger(timeouts.stall_seconds) ||
|
|
60
|
+
timeouts.stall_seconds < 1) {
|
|
61
|
+
timeouts.stall_seconds = DEFAULT_FRONT_MATTER.timeouts.stall_seconds;
|
|
62
|
+
}
|
|
63
|
+
out.timeouts = timeouts;
|
|
64
|
+
const inScope = Array.isArray(out.in_scope_paths)
|
|
65
|
+
? out.in_scope_paths.filter((v) => typeof v === "string" && v.trim().length > 0)
|
|
66
|
+
: [];
|
|
67
|
+
out.in_scope_paths = inScope.length > 0 ? inScope : DEFAULT_FRONT_MATTER.in_scope_paths;
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
export function safeAutofixWorkflowText(text) {
|
|
71
|
+
const parsed = parseWorkflowMarkdown(text);
|
|
72
|
+
const diagnostics = [];
|
|
73
|
+
const unknownKeyDiagnostics = Object.keys(parsed.document.frontMatterRaw)
|
|
74
|
+
.filter((key) => ![
|
|
75
|
+
"version",
|
|
76
|
+
"mode",
|
|
77
|
+
"owners",
|
|
78
|
+
"approvals",
|
|
79
|
+
"retry_policy",
|
|
80
|
+
"timeouts",
|
|
81
|
+
"in_scope_paths",
|
|
82
|
+
].includes(key))
|
|
83
|
+
.map((key) => ({
|
|
84
|
+
code: "WF_FIX_SKIPPED_UNSAFE",
|
|
85
|
+
severity: "WARN",
|
|
86
|
+
path: `front_matter.${key}`,
|
|
87
|
+
message: `Unsafe autofix skipped for unknown key: ${key}`,
|
|
88
|
+
}));
|
|
89
|
+
diagnostics.push(...unknownKeyDiagnostics);
|
|
90
|
+
if (unknownKeyDiagnostics.length > 0) {
|
|
91
|
+
return { changed: false, text, diagnostics };
|
|
92
|
+
}
|
|
93
|
+
const nextFrontMatter = withDefaults(parsed.document.frontMatterRaw);
|
|
94
|
+
const sections = {
|
|
95
|
+
...parsed.document.sections,
|
|
96
|
+
"Prompt Template": parsed.document.sections["Prompt Template"] ?? "",
|
|
97
|
+
Checks: parsed.document.sections.Checks ?? "- preflight\n- verify\n- finish",
|
|
98
|
+
Fallback: parsed.document.sections.Fallback ??
|
|
99
|
+
"last_known_good: .agentplane/workflows/last-known-good.md",
|
|
100
|
+
};
|
|
101
|
+
const nextText = serializeWorkflowMarkdown(nextFrontMatter, sections);
|
|
102
|
+
return {
|
|
103
|
+
changed: nextText !== text,
|
|
104
|
+
text: nextText,
|
|
105
|
+
diagnostics,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./paths.js";
|
|
3
|
+
export * from "./observability.js";
|
|
4
|
+
export * from "./enforcement.js";
|
|
5
|
+
export * from "./markdown.js";
|
|
6
|
+
export * from "./validate.js";
|
|
7
|
+
export * from "./template.js";
|
|
8
|
+
export * from "./build.js";
|
|
9
|
+
export * from "./file-ops.js";
|
|
10
|
+
export * from "./fix.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,eAAe,CAAC;AAC9B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
2
|
+
export * from "./paths.js";
|
|
3
|
+
export * from "./observability.js";
|
|
4
|
+
export * from "./enforcement.js";
|
|
5
|
+
export * from "./markdown.js";
|
|
6
|
+
export * from "./validate.js";
|
|
7
|
+
export * from "./template.js";
|
|
8
|
+
export * from "./build.js";
|
|
9
|
+
export * from "./file-ops.js";
|
|
10
|
+
export * from "./fix.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WorkflowDiagnostic, WorkflowDocument, WorkflowFrontMatter, WorkflowSections, WorkflowValidationResult } from "./types.js";
|
|
2
|
+
export declare function parseWorkflowMarkdown(text: string, sourcePath?: string): {
|
|
3
|
+
document: Omit<WorkflowDocument, "frontMatter"> & {
|
|
4
|
+
frontMatter: WorkflowFrontMatter;
|
|
5
|
+
};
|
|
6
|
+
diagnostics: WorkflowDiagnostic[];
|
|
7
|
+
};
|
|
8
|
+
export declare function serializeWorkflowMarkdown(frontMatter: Record<string, unknown>, sections: WorkflowSections): string;
|
|
9
|
+
export declare function diagnosticsToValidationResult(diagnostics: WorkflowDiagnostic[]): WorkflowValidationResult;
|
|
10
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,EAChB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAmHpB,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,GAClB;IACD,QAAQ,EAAE,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,GAAG;QAAE,WAAW,EAAE,mBAAmB,CAAA;KAAE,CAAC;IACvF,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC,CAmBA;AAOD,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,QAAQ,EAAE,gBAAgB,GACzB,MAAM,CAkBR;AAED,wBAAgB,6BAA6B,CAC3C,WAAW,EAAE,kBAAkB,EAAE,GAChC,wBAAwB,CAM1B"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { parseTaskReadme, renderTaskFrontmatter } from "@agentplaneorg/core";
|
|
2
|
+
const REQUIRED_SECTIONS = ["Prompt Template", "Checks", "Fallback"];
|
|
3
|
+
function sectionDiagnostics(sections) {
|
|
4
|
+
const out = [];
|
|
5
|
+
for (const section of REQUIRED_SECTIONS) {
|
|
6
|
+
const value = sections[section];
|
|
7
|
+
if (!value || value.trim().length === 0) {
|
|
8
|
+
out.push({
|
|
9
|
+
code: "WF_REQUIRED_SECTION_MISSING",
|
|
10
|
+
severity: "ERROR",
|
|
11
|
+
path: `sections.${section}`,
|
|
12
|
+
message: `Missing required section: ${section}`,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
function splitFrontMatter(input) {
|
|
19
|
+
const normalized = input.replaceAll("\r\n", "\n");
|
|
20
|
+
if (!normalized.startsWith("---\n")) {
|
|
21
|
+
return { frontMatterText: "", body: normalized };
|
|
22
|
+
}
|
|
23
|
+
const end = normalized.indexOf("\n---\n", 4);
|
|
24
|
+
if (end === -1) {
|
|
25
|
+
return {
|
|
26
|
+
frontMatterText: normalized.slice(4),
|
|
27
|
+
body: "",
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
frontMatterText: normalized.slice(4, end),
|
|
32
|
+
body: normalized.slice(end + 5),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function parseSections(body) {
|
|
36
|
+
const lines = body.replaceAll("\r\n", "\n").split("\n");
|
|
37
|
+
const sections = {};
|
|
38
|
+
let current = null;
|
|
39
|
+
let buffer = [];
|
|
40
|
+
const flush = () => {
|
|
41
|
+
if (!current)
|
|
42
|
+
return;
|
|
43
|
+
sections[current] = buffer.join("\n").trim();
|
|
44
|
+
buffer = [];
|
|
45
|
+
};
|
|
46
|
+
for (const line of lines) {
|
|
47
|
+
const heading = /^##\s+(.+)\s*$/.exec(line);
|
|
48
|
+
if (heading?.[1]) {
|
|
49
|
+
flush();
|
|
50
|
+
current = heading[1].trim();
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (current)
|
|
54
|
+
buffer.push(line);
|
|
55
|
+
}
|
|
56
|
+
flush();
|
|
57
|
+
return sections;
|
|
58
|
+
}
|
|
59
|
+
function readFrontMatterMap(frontMatterText) {
|
|
60
|
+
if (!frontMatterText.trim()) {
|
|
61
|
+
return {
|
|
62
|
+
value: {},
|
|
63
|
+
diagnostics: [
|
|
64
|
+
{
|
|
65
|
+
code: "WF_SCHEMA_MISSING",
|
|
66
|
+
severity: "ERROR",
|
|
67
|
+
path: "front_matter",
|
|
68
|
+
message: "Front matter is required.",
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const parsed = parseTaskReadme(`---\n${frontMatterText}\n---\n`).frontmatter;
|
|
75
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
76
|
+
return {
|
|
77
|
+
value: {},
|
|
78
|
+
diagnostics: [
|
|
79
|
+
{
|
|
80
|
+
code: "WF_FRONTMATTER_NOT_OBJECT",
|
|
81
|
+
severity: "ERROR",
|
|
82
|
+
path: "front_matter",
|
|
83
|
+
message: "Workflow front matter must decode to an object.",
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
return { value: parsed, diagnostics: [] };
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
return {
|
|
92
|
+
value: {},
|
|
93
|
+
diagnostics: [
|
|
94
|
+
{
|
|
95
|
+
code: "WF_PARSE_ERROR",
|
|
96
|
+
severity: "ERROR",
|
|
97
|
+
path: "front_matter",
|
|
98
|
+
message: `Failed to parse workflow front matter: ${error instanceof Error ? error.message : String(error)}`,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function parseWorkflowMarkdown(text, sourcePath) {
|
|
105
|
+
const { frontMatterText, body } = splitFrontMatter(text);
|
|
106
|
+
const fm = readFrontMatterMap(frontMatterText);
|
|
107
|
+
const sections = parseSections(body);
|
|
108
|
+
const diagnostics = [...fm.diagnostics, ...sectionDiagnostics(sections)];
|
|
109
|
+
const frontMatter = fm.value;
|
|
110
|
+
return {
|
|
111
|
+
document: {
|
|
112
|
+
frontMatter,
|
|
113
|
+
frontMatterRaw: fm.value,
|
|
114
|
+
body,
|
|
115
|
+
sections,
|
|
116
|
+
promptTemplate: sections["Prompt Template"] ?? "",
|
|
117
|
+
sourcePath,
|
|
118
|
+
},
|
|
119
|
+
diagnostics,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function toYamlObject(frontMatter) {
|
|
123
|
+
const fm = renderTaskFrontmatter(frontMatter);
|
|
124
|
+
return fm.replace(/^---\n/, "").replace(/\n---\n$/, "");
|
|
125
|
+
}
|
|
126
|
+
export function serializeWorkflowMarkdown(frontMatter, sections) {
|
|
127
|
+
const orderedSections = ["Prompt Template", "Checks", "Fallback"];
|
|
128
|
+
const renderedSections = [];
|
|
129
|
+
for (const name of orderedSections) {
|
|
130
|
+
const content = sections[name] ?? "";
|
|
131
|
+
renderedSections.push(`## ${name}\n${content}`.trimEnd());
|
|
132
|
+
}
|
|
133
|
+
const extras = Object.keys(sections)
|
|
134
|
+
.filter((name) => !orderedSections.includes(name))
|
|
135
|
+
.toSorted();
|
|
136
|
+
for (const name of extras) {
|
|
137
|
+
renderedSections.push(`## ${name}\n${sections[name] ?? ""}`.trimEnd());
|
|
138
|
+
}
|
|
139
|
+
return `---\n${toYamlObject(frontMatter)}\n---\n\n${renderedSections.join("\n\n")}\n`;
|
|
140
|
+
}
|
|
141
|
+
export function diagnosticsToValidationResult(diagnostics) {
|
|
142
|
+
const hasError = diagnostics.some((d) => d.severity === "ERROR");
|
|
143
|
+
return {
|
|
144
|
+
ok: !hasError,
|
|
145
|
+
diagnostics,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { WorkflowDiagnostic, WorkflowErrorCode } from "./types.js";
|
|
2
|
+
type WorkflowEventName = "workflow_build_started" | "workflow_build_completed" | "workflow_build_failed" | "workflow_publish_completed" | "workflow_publish_failed" | "workflow_restore_completed" | "workflow_restore_failed" | "workflow_doctor_check";
|
|
3
|
+
export type WorkflowEvent = {
|
|
4
|
+
event: WorkflowEventName;
|
|
5
|
+
code?: WorkflowErrorCode;
|
|
6
|
+
path?: string;
|
|
7
|
+
details?: Record<string, unknown>;
|
|
8
|
+
};
|
|
9
|
+
export declare function emitWorkflowEvent(event: WorkflowEvent): void;
|
|
10
|
+
export declare function diagnosticsSummary(diagnostics: WorkflowDiagnostic[]): string;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=observability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/observability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAExE,KAAK,iBAAiB,GAClB,wBAAwB,GACxB,0BAA0B,GAC1B,uBAAuB,GACvB,4BAA4B,GAC5B,yBAAyB,GACzB,4BAA4B,GAC5B,yBAAyB,GACzB,uBAAuB,CAAC;AAE5B,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,iBAAiB,CAAC;IACzB,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAO5D;AAED,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,kBAAkB,EAAE,GAAG,MAAM,CAK5E"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function emitWorkflowEvent(event) {
|
|
2
|
+
const payload = {
|
|
3
|
+
ts: new Date().toISOString(),
|
|
4
|
+
component: "workflow-runtime",
|
|
5
|
+
...event,
|
|
6
|
+
};
|
|
7
|
+
process.stderr.write(`${JSON.stringify(payload)}\n`);
|
|
8
|
+
}
|
|
9
|
+
export function diagnosticsSummary(diagnostics) {
|
|
10
|
+
const errors = diagnostics.filter((d) => d.severity === "ERROR").length;
|
|
11
|
+
const warnings = diagnostics.filter((d) => d.severity === "WARN").length;
|
|
12
|
+
const infos = diagnostics.filter((d) => d.severity === "INFO").length;
|
|
13
|
+
return `errors=${errors} warnings=${warnings} infos=${infos}`;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CASpE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
export function resolveWorkflowPaths(repoRoot) {
|
|
3
|
+
const workflowDir = path.join(repoRoot, ".agentplane", "workflows");
|
|
4
|
+
const workflowPath = path.join(repoRoot, ".agentplane", "WORKFLOW.md");
|
|
5
|
+
return {
|
|
6
|
+
workflowPath,
|
|
7
|
+
legacyWorkflowPath: path.join(repoRoot, "WORKFLOW.md"),
|
|
8
|
+
lastKnownGoodPath: path.join(workflowDir, "last-known-good.md"),
|
|
9
|
+
workflowDir,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WorkflowDiagnostic, WorkflowTemplateRenderOptions, WorkflowValidationResult } from "./types.js";
|
|
2
|
+
export declare function validateTemplateStrict(template: string, context: Record<string, unknown>, options?: Partial<WorkflowTemplateRenderOptions>): WorkflowValidationResult;
|
|
3
|
+
export declare function renderTemplateStrict(template: string, context: Record<string, unknown>, options?: Partial<WorkflowTemplateRenderOptions>): {
|
|
4
|
+
text: string;
|
|
5
|
+
diagnostics: WorkflowDiagnostic[];
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=template.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/template.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAuCpB,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,GAAE,OAAO,CAAC,6BAA6B,CAAM,GACnD,wBAAwB,CAqC1B;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAChC,OAAO,GAAE,OAAO,CAAC,6BAA6B,CAAM,GACnD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,kBAAkB,EAAE,CAAA;CAAE,CA8BrD"}
|