agentplane 0.2.25 → 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.
Files changed (166) hide show
  1. package/bin/agentplane.js +91 -54
  2. package/dist/.build-manifest.json +11 -0
  3. package/dist/backends/task-backend/local-backend.d.ts +2 -0
  4. package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
  5. package/dist/backends/task-backend/local-backend.js +12 -1
  6. package/dist/backends/task-backend/redmine/mapping.d.ts.map +1 -1
  7. package/dist/backends/task-backend/redmine/mapping.js +26 -1
  8. package/dist/backends/task-backend/redmine-backend.d.ts +4 -0
  9. package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
  10. package/dist/backends/task-backend/redmine-backend.js +92 -9
  11. package/dist/backends/task-backend/shared/types.d.ts +1 -0
  12. package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
  13. package/dist/backends/task-index.d.ts.map +1 -1
  14. package/dist/backends/task-index.js +8 -1
  15. package/dist/cli/command-guide.d.ts.map +1 -1
  16. package/dist/cli/command-guide.js +21 -8
  17. package/dist/cli/command-snippets.d.ts +24 -0
  18. package/dist/cli/command-snippets.d.ts.map +1 -0
  19. package/dist/cli/command-snippets.js +23 -0
  20. package/dist/cli/reason-codes.d.ts +9 -0
  21. package/dist/cli/reason-codes.d.ts.map +1 -0
  22. package/dist/cli/reason-codes.js +79 -0
  23. package/dist/cli/recipes-bundled.d.ts +1 -0
  24. package/dist/cli/recipes-bundled.d.ts.map +1 -1
  25. package/dist/cli/recipes-bundled.js +4 -1
  26. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  27. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  28. package/dist/cli/run-cli/command-catalog.js +40 -1
  29. package/dist/cli/run-cli/commands/config.d.ts +5 -0
  30. package/dist/cli/run-cli/commands/config.d.ts.map +1 -1
  31. package/dist/cli/run-cli/commands/config.js +86 -1
  32. package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
  33. package/dist/cli/run-cli/commands/core.js +55 -0
  34. package/dist/cli/run-cli/commands/init/recipes.d.ts +5 -1
  35. package/dist/cli/run-cli/commands/init/recipes.d.ts.map +1 -1
  36. package/dist/cli/run-cli/commands/init/recipes.js +24 -4
  37. package/dist/cli/run-cli/commands/init/write-workflow.d.ts +7 -0
  38. package/dist/cli/run-cli/commands/init/write-workflow.d.ts.map +1 -0
  39. package/dist/cli/run-cli/commands/init/write-workflow.js +52 -0
  40. package/dist/cli/run-cli/commands/init.d.ts +2 -1
  41. package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
  42. package/dist/cli/run-cli/commands/init.js +104 -54
  43. package/dist/cli/run-cli.d.ts.map +1 -1
  44. package/dist/cli/run-cli.js +70 -1
  45. package/dist/commands/backend/sync.command.d.ts.map +1 -1
  46. package/dist/commands/backend/sync.command.js +7 -6
  47. package/dist/commands/backend.d.ts.map +1 -1
  48. package/dist/commands/backend.js +2 -0
  49. package/dist/commands/doctor.run.d.ts.map +1 -1
  50. package/dist/commands/doctor.run.js +96 -10
  51. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  52. package/dist/commands/guard/impl/commands.js +12 -6
  53. package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
  54. package/dist/commands/recipes/impl/commands/install.js +36 -13
  55. package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
  56. package/dist/commands/recipes/impl/scenario.js +25 -0
  57. package/dist/commands/recipes/impl/types.d.ts +4 -0
  58. package/dist/commands/recipes/impl/types.d.ts.map +1 -1
  59. package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
  60. package/dist/commands/scenario/impl/commands.js +74 -3
  61. package/dist/commands/scenario/impl/report.d.ts +8 -0
  62. package/dist/commands/scenario/impl/report.d.ts.map +1 -1
  63. package/dist/commands/scenario/impl/report.js +1 -0
  64. package/dist/commands/shared/reconcile-check.d.ts +7 -0
  65. package/dist/commands/shared/reconcile-check.d.ts.map +1 -0
  66. package/dist/commands/shared/reconcile-check.js +60 -0
  67. package/dist/commands/sync.command.d.ts.map +1 -1
  68. package/dist/commands/sync.command.js +9 -2
  69. package/dist/commands/task/finish.d.ts.map +1 -1
  70. package/dist/commands/task/finish.js +2 -0
  71. package/dist/commands/task/list.d.ts.map +1 -1
  72. package/dist/commands/task/list.js +2 -1
  73. package/dist/commands/task/list.spec.d.ts.map +1 -1
  74. package/dist/commands/task/list.spec.js +7 -0
  75. package/dist/commands/task/next.d.ts.map +1 -1
  76. package/dist/commands/task/next.js +2 -1
  77. package/dist/commands/task/next.spec.d.ts.map +1 -1
  78. package/dist/commands/task/next.spec.js +7 -0
  79. package/dist/commands/task/search.d.ts.map +1 -1
  80. package/dist/commands/task/search.js +2 -1
  81. package/dist/commands/task/search.spec.d.ts.map +1 -1
  82. package/dist/commands/task/search.spec.js +7 -0
  83. package/dist/commands/task/shared.d.ts +7 -0
  84. package/dist/commands/task/shared.d.ts.map +1 -1
  85. package/dist/commands/task/shared.js +21 -1
  86. package/dist/commands/task/verify-record.d.ts.map +1 -1
  87. package/dist/commands/task/verify-record.js +2 -0
  88. package/dist/commands/workflow-build.command.d.ts +8 -0
  89. package/dist/commands/workflow-build.command.d.ts.map +1 -0
  90. package/dist/commands/workflow-build.command.js +96 -0
  91. package/dist/commands/workflow-playbook.command.d.ts +10 -0
  92. package/dist/commands/workflow-playbook.command.d.ts.map +1 -0
  93. package/dist/commands/workflow-playbook.command.js +174 -0
  94. package/dist/commands/workflow-restore.command.d.ts +5 -0
  95. package/dist/commands/workflow-restore.command.d.ts.map +1 -0
  96. package/dist/commands/workflow-restore.command.js +30 -0
  97. package/dist/commands/workflow.command.d.ts +6 -0
  98. package/dist/commands/workflow.command.d.ts.map +1 -0
  99. package/dist/commands/workflow.command.js +36 -0
  100. package/dist/harness/dynamic-tool-contract.d.ts +29 -0
  101. package/dist/harness/dynamic-tool-contract.d.ts.map +1 -0
  102. package/dist/harness/dynamic-tool-contract.js +86 -0
  103. package/dist/harness/hooks-lifecycle.d.ts +27 -0
  104. package/dist/harness/hooks-lifecycle.d.ts.map +1 -0
  105. package/dist/harness/hooks-lifecycle.js +67 -0
  106. package/dist/harness/index.d.ts +9 -0
  107. package/dist/harness/index.d.ts.map +1 -0
  108. package/dist/harness/index.js +8 -0
  109. package/dist/harness/reconcile.d.ts +37 -0
  110. package/dist/harness/reconcile.d.ts.map +1 -0
  111. package/dist/harness/reconcile.js +42 -0
  112. package/dist/harness/retry-policy.d.ts +31 -0
  113. package/dist/harness/retry-policy.d.ts.map +1 -0
  114. package/dist/harness/retry-policy.js +33 -0
  115. package/dist/harness/scheduler.d.ts +18 -0
  116. package/dist/harness/scheduler.d.ts.map +1 -0
  117. package/dist/harness/scheduler.js +55 -0
  118. package/dist/harness/state-machine.d.ts +17 -0
  119. package/dist/harness/state-machine.d.ts.map +1 -0
  120. package/dist/harness/state-machine.js +70 -0
  121. package/dist/harness/token-accounting.d.ts +19 -0
  122. package/dist/harness/token-accounting.d.ts.map +1 -0
  123. package/dist/harness/token-accounting.js +77 -0
  124. package/dist/harness/workspace-safety.d.ts +14 -0
  125. package/dist/harness/workspace-safety.d.ts.map +1 -0
  126. package/dist/harness/workspace-safety.js +62 -0
  127. package/dist/recipes/bundled-recipes.d.ts +4 -0
  128. package/dist/recipes/bundled-recipes.d.ts.map +1 -1
  129. package/dist/recipes/bundled-recipes.js +11 -0
  130. package/dist/shared/errors.d.ts +6 -0
  131. package/dist/shared/errors.d.ts.map +1 -1
  132. package/dist/shared/errors.js +1 -0
  133. package/dist/workflow-runtime/build.d.ts +4 -0
  134. package/dist/workflow-runtime/build.d.ts.map +1 -0
  135. package/dist/workflow-runtime/build.js +114 -0
  136. package/dist/workflow-runtime/enforcement.d.ts +3 -0
  137. package/dist/workflow-runtime/enforcement.d.ts.map +1 -0
  138. package/dist/workflow-runtime/enforcement.js +10 -0
  139. package/dist/workflow-runtime/file-ops.d.ts +11 -0
  140. package/dist/workflow-runtime/file-ops.d.ts.map +1 -0
  141. package/dist/workflow-runtime/file-ops.js +248 -0
  142. package/dist/workflow-runtime/fix.d.ts +9 -0
  143. package/dist/workflow-runtime/fix.d.ts.map +1 -0
  144. package/dist/workflow-runtime/fix.js +107 -0
  145. package/dist/workflow-runtime/index.d.ts +11 -0
  146. package/dist/workflow-runtime/index.d.ts.map +1 -0
  147. package/dist/workflow-runtime/index.js +10 -0
  148. package/dist/workflow-runtime/markdown.d.ts +10 -0
  149. package/dist/workflow-runtime/markdown.d.ts.map +1 -0
  150. package/dist/workflow-runtime/markdown.js +147 -0
  151. package/dist/workflow-runtime/observability.d.ts +12 -0
  152. package/dist/workflow-runtime/observability.d.ts.map +1 -0
  153. package/dist/workflow-runtime/observability.js +14 -0
  154. package/dist/workflow-runtime/paths.d.ts +3 -0
  155. package/dist/workflow-runtime/paths.d.ts.map +1 -0
  156. package/dist/workflow-runtime/paths.js +11 -0
  157. package/dist/workflow-runtime/template.d.ts +7 -0
  158. package/dist/workflow-runtime/template.d.ts.map +1 -0
  159. package/dist/workflow-runtime/template.js +94 -0
  160. package/dist/workflow-runtime/types.d.ts +68 -0
  161. package/dist/workflow-runtime/types.d.ts.map +1 -0
  162. package/dist/workflow-runtime/types.js +1 -0
  163. package/dist/workflow-runtime/validate.d.ts +8 -0
  164. package/dist/workflow-runtime/validate.d.ts.map +1 -0
  165. package/dist/workflow-runtime/validate.js +331 -0
  166. package/package.json +3 -3
@@ -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,3 @@
1
+ import type { WorkflowPaths } from "./types.js";
2
+ export declare function resolveWorkflowPaths(repoRoot: string): WorkflowPaths;
3
+ //# sourceMappingURL=paths.d.ts.map
@@ -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"}
@@ -0,0 +1,94 @@
1
+ import { diagnosticsToValidationResult } from "./markdown.js";
2
+ function stringifyTemplateValue(value) {
3
+ if (value === undefined || value === null)
4
+ return "";
5
+ if (typeof value === "string")
6
+ return value;
7
+ if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
8
+ return String(value);
9
+ }
10
+ if (typeof value === "symbol") {
11
+ return value.description ? `Symbol(${value.description})` : "Symbol()";
12
+ }
13
+ return JSON.stringify(value) ?? "";
14
+ }
15
+ const DEFAULT_FILTERS = {
16
+ upper: (value) => stringifyTemplateValue(value).toUpperCase(),
17
+ lower: (value) => stringifyTemplateValue(value).toLowerCase(),
18
+ trim: (value) => stringifyTemplateValue(value).trim(),
19
+ json: (value) => JSON.stringify(value),
20
+ };
21
+ const DEFAULT_OPTIONS = {
22
+ strictVariables: true,
23
+ strictFilters: true,
24
+ allowedFilters: DEFAULT_FILTERS,
25
+ };
26
+ function getPathValue(context, dottedPath) {
27
+ const segments = dottedPath.split(".");
28
+ let current = context;
29
+ for (const segment of segments) {
30
+ if (!current || typeof current !== "object")
31
+ return undefined;
32
+ const record = current;
33
+ current = record[segment];
34
+ }
35
+ return current;
36
+ }
37
+ export function validateTemplateStrict(template, context, options = {}) {
38
+ const opts = {
39
+ ...DEFAULT_OPTIONS,
40
+ ...options,
41
+ allowedFilters: { ...DEFAULT_FILTERS, ...options.allowedFilters },
42
+ };
43
+ const diagnostics = [];
44
+ const re = /{{\s*([a-zA-Z_][\w.]*)(?:\s*\|\s*([a-zA-Z_][\w-]*))?\s*}}/g;
45
+ for (const match of template.matchAll(re)) {
46
+ const variable = match[1];
47
+ const filter = match[2];
48
+ if (variable && opts.strictVariables) {
49
+ const value = getPathValue(context, variable);
50
+ if (value === undefined) {
51
+ diagnostics.push({
52
+ code: "WF_TEMPLATE_UNKNOWN_VARIABLE",
53
+ severity: "ERROR",
54
+ path: `template.${variable}`,
55
+ message: `Unknown template variable: ${variable}`,
56
+ });
57
+ }
58
+ }
59
+ if (filter && opts.strictFilters && !opts.allowedFilters[filter]) {
60
+ diagnostics.push({
61
+ code: "WF_TEMPLATE_UNKNOWN_FILTER",
62
+ severity: "ERROR",
63
+ path: `template.filter.${filter}`,
64
+ message: `Unknown template filter: ${filter}`,
65
+ });
66
+ }
67
+ }
68
+ return diagnosticsToValidationResult(diagnostics);
69
+ }
70
+ export function renderTemplateStrict(template, context, options = {}) {
71
+ const opts = {
72
+ ...DEFAULT_OPTIONS,
73
+ ...options,
74
+ allowedFilters: { ...DEFAULT_FILTERS, ...options.allowedFilters },
75
+ };
76
+ const validation = validateTemplateStrict(template, context, opts);
77
+ if (!validation.ok) {
78
+ return {
79
+ text: template,
80
+ diagnostics: validation.diagnostics,
81
+ };
82
+ }
83
+ const rendered = template.replaceAll(/{{\s*([a-zA-Z_][\w.]*)(?:\s*\|\s*([a-zA-Z_][\w-]*))?\s*}}/g, (_full, variable, filter) => {
84
+ let value = getPathValue(context, variable);
85
+ if (filter) {
86
+ value = opts.allowedFilters[filter]?.(value);
87
+ }
88
+ return stringifyTemplateValue(value);
89
+ });
90
+ return {
91
+ text: rendered,
92
+ diagnostics: [],
93
+ };
94
+ }
@@ -0,0 +1,68 @@
1
+ export type WorkflowMode = "direct" | "branch_pr";
2
+ export type WorkflowApprovals = {
3
+ require_plan: boolean;
4
+ require_verify: boolean;
5
+ require_network: boolean;
6
+ };
7
+ export type WorkflowRetryPolicy = {
8
+ normal_exit_continuation: boolean;
9
+ abnormal_backoff: "exponential";
10
+ max_attempts: number;
11
+ };
12
+ export type WorkflowTimeouts = {
13
+ stall_seconds: number;
14
+ };
15
+ export type WorkflowFrontMatter = {
16
+ version: number;
17
+ mode: WorkflowMode;
18
+ owners: {
19
+ orchestrator: string;
20
+ };
21
+ approvals: WorkflowApprovals;
22
+ retry_policy: WorkflowRetryPolicy;
23
+ timeouts: WorkflowTimeouts;
24
+ in_scope_paths: string[];
25
+ };
26
+ export type WorkflowSectionName = "Prompt Template" | "Checks" | "Fallback";
27
+ export type WorkflowSections = Record<string, string>;
28
+ export type WorkflowDocument = {
29
+ frontMatter: WorkflowFrontMatter;
30
+ frontMatterRaw: Record<string, unknown>;
31
+ body: string;
32
+ sections: WorkflowSections;
33
+ promptTemplate: string;
34
+ sourcePath?: string;
35
+ };
36
+ export type WorkflowSeverity = "ERROR" | "WARN" | "INFO";
37
+ export type WorkflowErrorCode = "WF_MISSING_FILE" | "WF_READ_FAILED" | "WF_FRONTMATTER_NOT_OBJECT" | "WF_PARSE_ERROR" | "WF_SCHEMA_MISSING" | "WF_SCHEMA_TYPE" | "WF_SCHEMA_ENUM" | "WF_SCHEMA_RANGE" | "WF_SCHEMA_UNKNOWN_KEY" | "WF_REQUIRED_SECTION_MISSING" | "WF_TEMPLATE_UNKNOWN_VARIABLE" | "WF_TEMPLATE_UNKNOWN_FILTER" | "WF_PATH_OUTSIDE_ROOT" | "WF_OWNER_NOT_FOUND" | "WF_POLICY_MISMATCH" | "WF_FIX_SKIPPED_UNSAFE";
38
+ export type WorkflowDiagnostic = {
39
+ code: WorkflowErrorCode;
40
+ severity: WorkflowSeverity;
41
+ path: string;
42
+ message: string;
43
+ };
44
+ export type WorkflowValidationResult = {
45
+ ok: boolean;
46
+ diagnostics: WorkflowDiagnostic[];
47
+ };
48
+ export type WorkflowTemplateRenderOptions = {
49
+ strictVariables: boolean;
50
+ strictFilters: boolean;
51
+ allowedFilters: Record<string, (value: unknown) => unknown>;
52
+ };
53
+ export type WorkflowPaths = {
54
+ workflowPath: string;
55
+ legacyWorkflowPath: string;
56
+ lastKnownGoodPath: string;
57
+ workflowDir: string;
58
+ };
59
+ export type WorkflowBuildInput = {
60
+ baseTemplate: string;
61
+ projectOverrideTemplate?: string;
62
+ runtimeContext: Record<string, unknown>;
63
+ };
64
+ export type WorkflowBuildOutput = {
65
+ text: string;
66
+ diagnostics: WorkflowDiagnostic[];
67
+ };
68
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,WAAW,CAAC;AAElD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,wBAAwB,EAAE,OAAO,CAAC;IAClC,gBAAgB,EAAE,aAAa,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;IACF,SAAS,EAAE,iBAAiB,CAAC;IAC7B,YAAY,EAAE,mBAAmB,CAAC;IAClC,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE5E,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,mBAAmB,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GACzB,iBAAiB,GACjB,gBAAgB,GAChB,2BAA2B,GAC3B,gBAAgB,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,uBAAuB,GACvB,6BAA6B,GAC7B,8BAA8B,GAC9B,4BAA4B,GAC5B,sBAAsB,GACtB,oBAAoB,GACpB,oBAAoB,GACpB,uBAAuB,CAAC;AAE5B,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,iBAAiB,CAAC;IACxB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,kBAAkB,EAAE,CAAC;CACnC,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { AgentplaneConfig } from "@agentplaneorg/core";
2
+ import type { WorkflowDocument, WorkflowValidationResult } from "./types.js";
3
+ export declare function validateWorkflowDocument(document: WorkflowDocument, opts?: {
4
+ repoRoot?: string;
5
+ knownAgentIds?: Set<string>;
6
+ config?: AgentplaneConfig | null;
7
+ }): WorkflowValidationResult;
8
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/workflow-runtime/validate.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,KAAK,EAEV,gBAAgB,EAEhB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AA8VpB,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,gBAAgB,EAC1B,IAAI,CAAC,EAAE;IACL,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAClC,GACA,wBAAwB,CA0F1B"}