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.
Files changed (187) 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/block.spec.d.ts.map +1 -1
  50. package/dist/commands/block.spec.js +23 -2
  51. package/dist/commands/commit.spec.d.ts.map +1 -1
  52. package/dist/commands/commit.spec.js +18 -6
  53. package/dist/commands/doctor.run.d.ts.map +1 -1
  54. package/dist/commands/doctor.run.js +96 -10
  55. package/dist/commands/finish.spec.d.ts.map +1 -1
  56. package/dist/commands/finish.spec.js +53 -4
  57. package/dist/commands/guard/commit.command.d.ts.map +1 -1
  58. package/dist/commands/guard/commit.command.js +26 -20
  59. package/dist/commands/guard/impl/allow.d.ts.map +1 -1
  60. package/dist/commands/guard/impl/allow.js +8 -1
  61. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  62. package/dist/commands/guard/impl/commands.js +19 -21
  63. package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
  64. package/dist/commands/guard/impl/comment-commit.js +8 -17
  65. package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
  66. package/dist/commands/recipes/impl/commands/install.js +36 -13
  67. package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
  68. package/dist/commands/recipes/impl/scenario.js +25 -0
  69. package/dist/commands/recipes/impl/types.d.ts +4 -0
  70. package/dist/commands/recipes/impl/types.d.ts.map +1 -1
  71. package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
  72. package/dist/commands/scenario/impl/commands.js +74 -3
  73. package/dist/commands/scenario/impl/report.d.ts +8 -0
  74. package/dist/commands/scenario/impl/report.d.ts.map +1 -1
  75. package/dist/commands/scenario/impl/report.js +1 -0
  76. package/dist/commands/shared/reconcile-check.d.ts +7 -0
  77. package/dist/commands/shared/reconcile-check.d.ts.map +1 -0
  78. package/dist/commands/shared/reconcile-check.js +60 -0
  79. package/dist/commands/start.spec.d.ts.map +1 -1
  80. package/dist/commands/start.spec.js +23 -2
  81. package/dist/commands/sync.command.d.ts.map +1 -1
  82. package/dist/commands/sync.command.js +9 -2
  83. package/dist/commands/task/finish.d.ts.map +1 -1
  84. package/dist/commands/task/finish.js +34 -10
  85. package/dist/commands/task/list.d.ts.map +1 -1
  86. package/dist/commands/task/list.js +2 -1
  87. package/dist/commands/task/list.spec.d.ts.map +1 -1
  88. package/dist/commands/task/list.spec.js +7 -0
  89. package/dist/commands/task/next.d.ts.map +1 -1
  90. package/dist/commands/task/next.js +2 -1
  91. package/dist/commands/task/next.spec.d.ts.map +1 -1
  92. package/dist/commands/task/next.spec.js +7 -0
  93. package/dist/commands/task/search.d.ts.map +1 -1
  94. package/dist/commands/task/search.js +2 -1
  95. package/dist/commands/task/search.spec.d.ts.map +1 -1
  96. package/dist/commands/task/search.spec.js +7 -0
  97. package/dist/commands/task/set-status.command.d.ts.map +1 -1
  98. package/dist/commands/task/set-status.command.js +22 -2
  99. package/dist/commands/task/shared.d.ts +7 -0
  100. package/dist/commands/task/shared.d.ts.map +1 -1
  101. package/dist/commands/task/shared.js +21 -1
  102. package/dist/commands/task/verify-record.d.ts.map +1 -1
  103. package/dist/commands/task/verify-record.js +2 -0
  104. package/dist/commands/workflow-build.command.d.ts +8 -0
  105. package/dist/commands/workflow-build.command.d.ts.map +1 -0
  106. package/dist/commands/workflow-build.command.js +96 -0
  107. package/dist/commands/workflow-playbook.command.d.ts +10 -0
  108. package/dist/commands/workflow-playbook.command.d.ts.map +1 -0
  109. package/dist/commands/workflow-playbook.command.js +174 -0
  110. package/dist/commands/workflow-restore.command.d.ts +5 -0
  111. package/dist/commands/workflow-restore.command.d.ts.map +1 -0
  112. package/dist/commands/workflow-restore.command.js +30 -0
  113. package/dist/commands/workflow.command.d.ts +6 -0
  114. package/dist/commands/workflow.command.d.ts.map +1 -0
  115. package/dist/commands/workflow.command.js +36 -0
  116. package/dist/harness/dynamic-tool-contract.d.ts +29 -0
  117. package/dist/harness/dynamic-tool-contract.d.ts.map +1 -0
  118. package/dist/harness/dynamic-tool-contract.js +86 -0
  119. package/dist/harness/hooks-lifecycle.d.ts +27 -0
  120. package/dist/harness/hooks-lifecycle.d.ts.map +1 -0
  121. package/dist/harness/hooks-lifecycle.js +67 -0
  122. package/dist/harness/index.d.ts +9 -0
  123. package/dist/harness/index.d.ts.map +1 -0
  124. package/dist/harness/index.js +8 -0
  125. package/dist/harness/reconcile.d.ts +37 -0
  126. package/dist/harness/reconcile.d.ts.map +1 -0
  127. package/dist/harness/reconcile.js +42 -0
  128. package/dist/harness/retry-policy.d.ts +31 -0
  129. package/dist/harness/retry-policy.d.ts.map +1 -0
  130. package/dist/harness/retry-policy.js +33 -0
  131. package/dist/harness/scheduler.d.ts +18 -0
  132. package/dist/harness/scheduler.d.ts.map +1 -0
  133. package/dist/harness/scheduler.js +55 -0
  134. package/dist/harness/state-machine.d.ts +17 -0
  135. package/dist/harness/state-machine.d.ts.map +1 -0
  136. package/dist/harness/state-machine.js +70 -0
  137. package/dist/harness/token-accounting.d.ts +19 -0
  138. package/dist/harness/token-accounting.d.ts.map +1 -0
  139. package/dist/harness/token-accounting.js +77 -0
  140. package/dist/harness/workspace-safety.d.ts +14 -0
  141. package/dist/harness/workspace-safety.d.ts.map +1 -0
  142. package/dist/harness/workspace-safety.js +62 -0
  143. package/dist/policy/rules/allowlist.d.ts.map +1 -1
  144. package/dist/policy/rules/allowlist.js +9 -0
  145. package/dist/recipes/bundled-recipes.d.ts +4 -0
  146. package/dist/recipes/bundled-recipes.d.ts.map +1 -1
  147. package/dist/recipes/bundled-recipes.js +11 -0
  148. package/dist/shared/allow-prefix-policy.d.ts +3 -0
  149. package/dist/shared/allow-prefix-policy.d.ts.map +1 -0
  150. package/dist/shared/allow-prefix-policy.js +8 -0
  151. package/dist/shared/errors.d.ts +6 -0
  152. package/dist/shared/errors.d.ts.map +1 -1
  153. package/dist/shared/errors.js +1 -0
  154. package/dist/workflow-runtime/build.d.ts +4 -0
  155. package/dist/workflow-runtime/build.d.ts.map +1 -0
  156. package/dist/workflow-runtime/build.js +114 -0
  157. package/dist/workflow-runtime/enforcement.d.ts +3 -0
  158. package/dist/workflow-runtime/enforcement.d.ts.map +1 -0
  159. package/dist/workflow-runtime/enforcement.js +10 -0
  160. package/dist/workflow-runtime/file-ops.d.ts +11 -0
  161. package/dist/workflow-runtime/file-ops.d.ts.map +1 -0
  162. package/dist/workflow-runtime/file-ops.js +248 -0
  163. package/dist/workflow-runtime/fix.d.ts +9 -0
  164. package/dist/workflow-runtime/fix.d.ts.map +1 -0
  165. package/dist/workflow-runtime/fix.js +107 -0
  166. package/dist/workflow-runtime/index.d.ts +11 -0
  167. package/dist/workflow-runtime/index.d.ts.map +1 -0
  168. package/dist/workflow-runtime/index.js +10 -0
  169. package/dist/workflow-runtime/markdown.d.ts +10 -0
  170. package/dist/workflow-runtime/markdown.d.ts.map +1 -0
  171. package/dist/workflow-runtime/markdown.js +147 -0
  172. package/dist/workflow-runtime/observability.d.ts +12 -0
  173. package/dist/workflow-runtime/observability.d.ts.map +1 -0
  174. package/dist/workflow-runtime/observability.js +14 -0
  175. package/dist/workflow-runtime/paths.d.ts +3 -0
  176. package/dist/workflow-runtime/paths.d.ts.map +1 -0
  177. package/dist/workflow-runtime/paths.js +11 -0
  178. package/dist/workflow-runtime/template.d.ts +7 -0
  179. package/dist/workflow-runtime/template.d.ts.map +1 -0
  180. package/dist/workflow-runtime/template.js +94 -0
  181. package/dist/workflow-runtime/types.d.ts +68 -0
  182. package/dist/workflow-runtime/types.d.ts.map +1 -0
  183. package/dist/workflow-runtime/types.js +1 -0
  184. package/dist/workflow-runtime/validate.d.ts +8 -0
  185. package/dist/workflow-runtime/validate.d.ts.map +1 -0
  186. package/dist/workflow-runtime/validate.js +331 -0
  187. package/package.json +3 -3
package/bin/agentplane.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import { execFileSync } from "node:child_process";
2
3
  import path from "node:path";
3
- import { readdir, stat } from "node:fs/promises";
4
+ import { readFile, stat } from "node:fs/promises";
4
5
  import { fileURLToPath } from "node:url";
5
6
 
6
7
  async function exists(p) {
@@ -35,47 +36,88 @@ async function maybeWarnGlobalBinaryInRepoCheckout() {
35
36
  );
36
37
  }
37
38
 
38
- function isTestLikePath(absPath) {
39
- // The repo build does not emit test files to dist. If we treat test mtimes as
40
- // "src is newer than dist", we can block normal commits that only change tests.
41
- const normalized = absPath.replaceAll("\\", "/");
42
- if (normalized.includes("/__snapshots__/")) return true;
43
- if (normalized.endsWith(".snap")) return true;
44
- if (/\.(unit\.)?test\.[cm]?ts$/.test(normalized)) return true;
45
- if (/\.(unit\.)?test\.tsx$/.test(normalized)) return true;
46
- return false;
39
+ async function readJsonIfExists(p) {
40
+ let raw = "";
41
+ try {
42
+ raw = await readFile(p, "utf8");
43
+ } catch {
44
+ return null;
45
+ }
46
+ try {
47
+ return JSON.parse(raw);
48
+ } catch {
49
+ return null;
50
+ }
47
51
  }
48
52
 
49
- // Keep this file dependency-free and simple: rely on directory mtime scans below.
50
- async function newestMtimeMsInDir(dir) {
51
- let newest = 0;
52
- const stack = [dir];
53
- while (stack.length > 0) {
54
- const current = stack.pop();
55
- if (!current) continue;
56
- let entries;
57
- try {
58
- entries = await readdir(current, { withFileTypes: true });
59
- } catch {
60
- continue;
61
- }
62
- for (const entry of entries) {
63
- const abs = path.join(current, entry.name);
64
- if (entry.isDirectory()) {
65
- stack.push(abs);
66
- continue;
67
- }
68
- if (!entry.isFile()) continue;
69
- if (isTestLikePath(abs)) continue;
70
- try {
71
- const s = await stat(abs);
72
- if (s.mtimeMs > newest) newest = s.mtimeMs;
73
- } catch {
74
- // ignore
75
- }
76
- }
53
+ function resolveGitHead(cwd) {
54
+ try {
55
+ return execFileSync("git", ["rev-parse", "HEAD"], { cwd, encoding: "utf8" }).trim() || null;
56
+ } catch {
57
+ return null;
77
58
  }
78
- return newest;
59
+ }
60
+
61
+ function hasSrcChanges(cwd) {
62
+ try {
63
+ const out = execFileSync(
64
+ "git",
65
+ ["status", "--porcelain", "--untracked-files=all", "--", "src"],
66
+ {
67
+ cwd,
68
+ encoding: "utf8",
69
+ },
70
+ );
71
+ return out.trim().length > 0;
72
+ } catch {
73
+ return false;
74
+ }
75
+ }
76
+
77
+ async function fileMtimeMs(p) {
78
+ try {
79
+ const s = await stat(p);
80
+ if (!s.isFile()) return null;
81
+ return s.mtimeMs;
82
+ } catch {
83
+ return null;
84
+ }
85
+ }
86
+
87
+ async function isPackageBuildFresh(packageRoot) {
88
+ const manifestPath = path.join(packageRoot, "dist", ".build-manifest.json");
89
+ const manifest = await readJsonIfExists(manifestPath);
90
+ if (!manifest || manifest.schema_version !== 1) {
91
+ return { ok: false, reason: "manifest_missing" };
92
+ }
93
+
94
+ const currentHead = resolveGitHead(packageRoot);
95
+ if (manifest.git_head && currentHead && manifest.git_head !== currentHead) {
96
+ return { ok: false, reason: "git_head_changed" };
97
+ }
98
+
99
+ if (hasSrcChanges(packageRoot)) {
100
+ return { ok: false, reason: "src_dirty" };
101
+ }
102
+
103
+ const srcCliMtimeMs = await fileMtimeMs(path.join(packageRoot, "src", "cli.ts"));
104
+ const srcIndexMtimeMs = await fileMtimeMs(path.join(packageRoot, "src", "index.ts"));
105
+ if (
106
+ typeof manifest.src_cli_mtime_ms === "number" &&
107
+ typeof srcCliMtimeMs === "number" &&
108
+ srcCliMtimeMs > manifest.src_cli_mtime_ms
109
+ ) {
110
+ return { ok: false, reason: "src_cli_newer_than_manifest" };
111
+ }
112
+ if (
113
+ typeof manifest.src_index_mtime_ms === "number" &&
114
+ typeof srcIndexMtimeMs === "number" &&
115
+ srcIndexMtimeMs > manifest.src_index_mtime_ms
116
+ ) {
117
+ return { ok: false, reason: "src_index_newer_than_manifest" };
118
+ }
119
+
120
+ return { ok: true, reason: "fresh" };
79
121
  }
80
122
 
81
123
  async function assertDistUpToDate() {
@@ -97,29 +139,24 @@ async function assertDistUpToDate() {
97
139
  return false;
98
140
  }
99
141
 
100
- const agentplaneSrcDir = path.join(agentplaneRoot, "src");
101
- const agentplaneSrcNewest = await newestMtimeMsInDir(agentplaneSrcDir);
102
- const agentplaneDistNewest = await newestMtimeMsInDir(agentplaneDistDir);
103
- const isStaleAgentplane = agentplaneSrcNewest > agentplaneDistNewest;
104
-
105
- // If we're in the monorepo, also check core dist because the CLI imports it.
106
142
  const repoRoot = path.resolve(agentplaneRoot, "..", "..");
107
143
  const coreRoot = path.join(repoRoot, "packages", "core");
108
- const coreSrcDir = path.join(coreRoot, "src");
109
- const coreDistDir = path.join(coreRoot, "dist");
110
- let isStaleCore = false;
111
- if ((await exists(coreSrcDir)) && (await exists(coreDistDir))) {
112
- const coreSrcNewest = await newestMtimeMsInDir(coreSrcDir);
113
- const coreDistNewest = await newestMtimeMsInDir(coreDistDir);
114
- isStaleCore = coreSrcNewest > coreDistNewest;
144
+ const checks = [{ name: "agentplane", root: agentplaneRoot }];
145
+ if (await exists(path.join(coreRoot, "src"))) checks.push({ name: "core", root: coreRoot });
146
+
147
+ const staleReasons = [];
148
+ for (const check of checks) {
149
+ const result = await isPackageBuildFresh(check.root);
150
+ if (!result.ok) staleReasons.push(`${check.name}:${result.reason}`);
115
151
  }
116
152
 
117
- if ((isStaleAgentplane || isStaleCore) && !allowStale) {
153
+ if (staleReasons.length > 0 && !allowStale) {
118
154
  process.stderr.write(
119
- "error: refusing to run a stale repo build (dist is older than src).\n" +
155
+ "error: refusing to run a stale repo build (manifest/git quick-check failed).\n" +
120
156
  "Fix:\n" +
121
157
  " bun run --filter=@agentplaneorg/core build\n" +
122
158
  " bun run --filter=agentplane build\n" +
159
+ `Detected: ${staleReasons.join(", ")}\n` +
123
160
  "Override (not recommended): set AGENTPLANE_DEV_ALLOW_STALE_DIST=1\n",
124
161
  );
125
162
  process.exitCode = 2;
@@ -0,0 +1,11 @@
1
+ {
2
+ "schema_version": 1,
3
+ "package_dir": "/home/runner/work/agentplane/agentplane/packages/agentplane",
4
+ "generated_at": "2026-03-05T13:42:04.968Z",
5
+ "git_head": "7fdf3f088d7d98748b9ef5db06f5bef3766b534d",
6
+ "src_cli_mtime_ms": 1772718067546.3232,
7
+ "src_index_mtime_ms": null,
8
+ "dist_cli_mtime_ms": 1772718124490.9443,
9
+ "dist_index_mtime_ms": null,
10
+ "tsbuildinfo_mtime_ms": 1772718124554.9443
11
+ }
@@ -3,6 +3,7 @@ export declare class LocalBackend implements TaskBackend {
3
3
  id: string;
4
4
  root: string;
5
5
  updatedBy: string;
6
+ private lastListWarnings;
6
7
  constructor(settings?: {
7
8
  dir?: string;
8
9
  updatedBy?: string;
@@ -12,6 +13,7 @@ export declare class LocalBackend implements TaskBackend {
12
13
  attempts: number;
13
14
  }): Promise<string>;
14
15
  listTasks(): Promise<TaskData[]>;
16
+ getLastListWarnings(): string[];
15
17
  getTask(taskId: string): Promise<TaskData | null>;
16
18
  getTasks(taskIds: string[]): Promise<(TaskData | null)[]>;
17
19
  getTaskDoc(taskId: string): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"local-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/local-backend.ts"],"names":[],"mappings":"AAqBA,OAAO,EAiBL,KAAK,WAAW,EAChB,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAErB,qBAAa,YAAa,YAAW,WAAW;IAC9C,EAAE,SAAW;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;gBAEN,QAAQ,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAKrD,cAAc,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB3E,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgHhC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAoBjD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;IAKzD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO3C,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAyExC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB1E,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvE,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,cAAc,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAoF/D,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAIzD"}
1
+ {"version":3,"file":"local-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/local-backend.ts"],"names":[],"mappings":"AAqBA,OAAO,EAiBL,KAAK,WAAW,EAChB,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAErB,qBAAa,YAAa,YAAW,WAAW;IAC9C,EAAE,SAAW;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,gBAAgB,CAAgB;gBAE5B,QAAQ,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE;IAKrD,cAAc,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB3E,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAwHtC,mBAAmB,IAAI,MAAM,EAAE;IAIzB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAoBjD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;IAKzD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAO3C,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAyExC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB1E,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvE,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAO5C,cAAc,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAoF/D,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAIzD"}
@@ -9,6 +9,7 @@ export class LocalBackend {
9
9
  id = "local";
10
10
  root;
11
11
  updatedBy;
12
+ lastListWarnings = [];
12
13
  constructor(settings) {
13
14
  this.root = path.resolve(settings?.dir ?? ".agentplane/tasks");
14
15
  this.updatedBy = settings?.updatedBy ?? DEFAULT_DOC_UPDATED_BY;
@@ -38,6 +39,7 @@ export class LocalBackend {
38
39
  }
39
40
  async listTasks() {
40
41
  const tasks = [];
42
+ const warnings = [];
41
43
  const entries = await readdir(this.root, { withFileTypes: true }).catch(() => []);
42
44
  const indexPath = resolveTaskIndexPath(this.root);
43
45
  const cachedIndex = await loadTaskIndex(indexPath);
@@ -65,6 +67,7 @@ export class LocalBackend {
65
67
  stats = await stat(readme);
66
68
  }
67
69
  catch {
70
+ warnings.push(`skip:${dirName}: missing_or_unreadable_readme`);
68
71
  return null;
69
72
  }
70
73
  if (!stats.isFile())
@@ -79,6 +82,7 @@ export class LocalBackend {
79
82
  text = await readFile(readme, "utf8");
80
83
  }
81
84
  catch {
85
+ warnings.push(`skip:${dirName}: unreadable_readme`);
82
86
  return null;
83
87
  }
84
88
  let parsed;
@@ -86,11 +90,14 @@ export class LocalBackend {
86
90
  parsed = parseTaskReadme(text);
87
91
  }
88
92
  catch {
93
+ warnings.push(`skip:${dirName}: invalid_readme_frontmatter`);
89
94
  return null;
90
95
  }
91
96
  const fm = parsed.frontmatter;
92
- if (!isRecord(fm) || Object.keys(fm).length === 0)
97
+ if (!isRecord(fm) || Object.keys(fm).length === 0) {
98
+ warnings.push(`skip:${dirName}: empty_or_invalid_frontmatter`);
93
99
  return null;
100
+ }
94
101
  const taskId = (typeof fm.id === "string" ? fm.id : dirName).trim();
95
102
  const task = taskRecordToData({
96
103
  id: taskId,
@@ -141,8 +148,12 @@ export class LocalBackend {
141
148
  // Best-effort cache; ignore failures.
142
149
  }
143
150
  }
151
+ this.lastListWarnings = warnings;
144
152
  return tasks;
145
153
  }
154
+ getLastListWarnings() {
155
+ return [...this.lastListWarnings];
156
+ }
146
157
  async getTask(taskId) {
147
158
  const readme = taskReadmePath(this.root, taskId);
148
159
  let text = "";
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/mapping.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AAMtB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIhE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,QAAQ,GAAG,IAAI,CAwElB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7F,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyC1B"}
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/mapping.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AAMtB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIhE;AA2BD,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,QAAQ,GAAG,IAAI,CAwElB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7F,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyC1B"}
@@ -23,6 +23,31 @@ export function doneRatioForStatus(status) {
23
23
  return 100;
24
24
  return 0;
25
25
  }
26
+ function inferStatusFromIssue(issue) {
27
+ const statusVal = isRecord(issue.status) ? issue.status : null;
28
+ const statusName = toStringSafe(statusVal?.name).trim().toLowerCase();
29
+ const doneRatio = typeof issue.done_ratio === "number" ? issue.done_ratio : null;
30
+ const isClosed = statusVal?.is_closed === true;
31
+ // Redmine defaults (without explicit status_map) commonly use these ids.
32
+ const statusId = typeof statusVal?.id === "number" ? statusVal.id : null;
33
+ if (statusId === 2)
34
+ return "DOING";
35
+ if (statusId === 3 || statusId === 5 || statusId === 6)
36
+ return "DONE";
37
+ if (isClosed || (doneRatio !== null && doneRatio >= 100))
38
+ return "DONE";
39
+ if (statusName.includes("progress") || statusName.includes("doing"))
40
+ return "DOING";
41
+ if (statusName.includes("done") ||
42
+ statusName.includes("closed") ||
43
+ statusName.includes("resolved") ||
44
+ statusName.includes("complete")) {
45
+ return "DONE";
46
+ }
47
+ if (doneRatio !== null && doneRatio > 0)
48
+ return "DOING";
49
+ return "TODO";
50
+ }
26
51
  export function issueToTask(opts) {
27
52
  const taskId = opts.taskIdOverride ?? customFieldValue(opts.issue, opts.customFields.task_id);
28
53
  if (!taskId)
@@ -31,7 +56,7 @@ export function issueToTask(opts) {
31
56
  const statusId = statusVal && typeof statusVal.id === "number" ? statusVal.id : null;
32
57
  const status = statusId !== null && opts.reverseStatus.has(statusId)
33
58
  ? opts.reverseStatus.get(statusId)
34
- : "TODO";
59
+ : inferStatusFromIssue(opts.issue);
35
60
  const verifyVal = customFieldValue(opts.issue, opts.customFields.verify);
36
61
  const commitVal = customFieldValue(opts.issue, opts.customFields.commit);
37
62
  const docVal = customFieldValue(opts.issue, opts.customFields.doc);
@@ -25,6 +25,7 @@ export declare class RedmineBackend implements TaskBackend {
25
25
  cache: LocalBackend | null;
26
26
  issueCache: Map<string, Record<string, unknown>>;
27
27
  reverseStatus: Map<number, string>;
28
+ inferredStatusByTaskStatus: Map<string, number> | null;
28
29
  constructor(settings: RedmineSettings, opts: {
29
30
  cache?: LocalBackend | null;
30
31
  });
@@ -62,6 +63,9 @@ export declare class RedmineBackend implements TaskBackend {
62
63
  private setIssueCustomFieldValue;
63
64
  private listTasksRemote;
64
65
  private issueFromPayload;
66
+ private inferStatusIdForTaskStatus;
67
+ private loadInferredStatusByTaskStatus;
68
+ private selectInferredStatus;
65
69
  private findIssueByTaskId;
66
70
  private issueToTask;
67
71
  private taskToIssuePayload;
@@ -1 +1 @@
1
- {"version":3,"file":"redmine-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/redmine-backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA2BvD,OAAO,EAkBL,KAAK,WAAW,EAChB,KAAK,QAAQ,EAEd,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,cAAe,YAAW,WAAW;IAChD,EAAE,SAAa;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,UAAU,uCAA8C;IACxD,aAAa,sBAA6B;gBAE9B,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE;IA8CtE,cAAc,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB3E,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAgBhC,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD,cAAc,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAM/D,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAiBjD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;IAKzD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM3C,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6C1E,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCvE,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA0DxC,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C,IAAI,CAAC,IAAI,EAAE;QACf,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;QAC3B,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,eAAe,GAAG,MAAM,CAAC;QAC7D,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjB,OAAO,CAAC,iBAAiB;YAOX,QAAQ;YAoBR,QAAQ;YAoCR,cAAc;IAsB5B,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,WAAW;YAML,SAAS;IAMvB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,wBAAwB;YAQlB,eAAe;IAa7B,OAAO,CAAC,gBAAgB;YAIV,iBAAiB;IAgB/B,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,iBAAiB;YAIX,kBAAkB;IAchC,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;YAIV,WAAW;CAgB1B"}
1
+ {"version":3,"file":"redmine-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/redmine-backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA2BvD,OAAO,EAkBL,KAAK,WAAW,EAChB,KAAK,QAAQ,EAEd,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,qBAAa,cAAe,YAAW,WAAW;IAChD,EAAE,SAAa;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,YAAY,GAAG,IAAI,CAAC;IAC3B,UAAU,uCAA8C;IACxD,aAAa,sBAA6B;IAC1C,0BAA0B,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAQ;gBAElD,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE;QAAE,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE;IA8CtE,cAAc,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAoB3E,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAahC,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD,cAAc,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAM/D,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAgBjD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAC;IAKzD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAM3C,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6C1E,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuCvE,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA8DxC,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5C,IAAI,CAAC,IAAI,EAAE;QACf,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;QAC3B,QAAQ,EAAE,MAAM,GAAG,cAAc,GAAG,eAAe,GAAG,MAAM,CAAC;QAC7D,KAAK,EAAE,OAAO,CAAC;QACf,OAAO,EAAE,OAAO,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;IAYjB,OAAO,CAAC,iBAAiB;YAOX,QAAQ;YAoBR,QAAQ;YAoCR,cAAc;IAsB5B,OAAO,CAAC,SAAS;IAejB,OAAO,CAAC,WAAW;YAML,SAAS;IAMvB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,wBAAwB;YAQlB,eAAe;IAa7B,OAAO,CAAC,gBAAgB;YAIV,0BAA0B;YAW1B,8BAA8B;IAwC5C,OAAO,CAAC,oBAAoB;YAqCd,iBAAiB;IAgB/B,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,iBAAiB;YAIX,kBAAkB;IAchC,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,gBAAgB;YAIV,WAAW;CAgB1B"}
@@ -22,6 +22,7 @@ export class RedmineBackend {
22
22
  cache;
23
23
  issueCache = new Map();
24
24
  reverseStatus = new Map();
25
+ inferredStatusByTaskStatus = null;
25
26
  constructor(settings, opts) {
26
27
  const env = readRedmineEnv();
27
28
  this.baseUrl = firstNonEmptyString(env.url, settings.url).replaceAll(/\/+$/gu, "");
@@ -89,11 +90,8 @@ export class RedmineBackend {
89
90
  }
90
91
  async listTasks() {
91
92
  try {
92
- const tasks = await this.listTasksRemote();
93
- for (const task of tasks) {
94
- await this.cacheTask(task, false);
95
- }
96
- return tasks;
93
+ // Read-only listing must not rewrite local task READMEs through cache updates.
94
+ return await this.listTasksRemote();
97
95
  }
98
96
  catch (err) {
99
97
  if (err instanceof RedmineUnavailable) {
@@ -119,10 +117,8 @@ export class RedmineBackend {
119
117
  const issue = await this.findIssueByTaskId(taskId);
120
118
  if (!issue)
121
119
  return null;
122
- const task = this.issueToTask(issue, taskId);
123
- if (task)
124
- await this.cacheTask(task, false);
125
- return task;
120
+ // Read-only fetch must not rewrite local task READMEs through cache updates.
121
+ return this.issueToTask(issue, taskId);
126
122
  }
127
123
  catch (err) {
128
124
  if (err instanceof RedmineUnavailable) {
@@ -249,6 +245,11 @@ export class RedmineBackend {
249
245
  existingIssue = this.issueFromPayload(payload);
250
246
  }
251
247
  const payload = this.taskToIssuePayload(task, existingIssue ?? undefined);
248
+ if (payload.status_id === undefined) {
249
+ const inferredStatusId = await this.inferStatusIdForTaskStatus(task.status);
250
+ if (inferredStatusId !== null)
251
+ payload.status_id = inferredStatusId;
252
+ }
252
253
  if (issueIdText) {
253
254
  await this.requestJson("PUT", `issues/${issueIdText}.json`, { issue: payload });
254
255
  }
@@ -437,6 +438,88 @@ export class RedmineBackend {
437
438
  issueFromPayload(payload) {
438
439
  return isRecord(payload.issue) ? payload.issue : null;
439
440
  }
441
+ async inferStatusIdForTaskStatus(statusRaw) {
442
+ const status = toStringSafe(statusRaw).trim().toUpperCase();
443
+ if (!status)
444
+ return null;
445
+ const explicit = this.statusMap?.[status];
446
+ if (typeof explicit === "number" && Number.isFinite(explicit))
447
+ return explicit;
448
+ const inferred = await this.loadInferredStatusByTaskStatus();
449
+ return inferred.get(status) ?? null;
450
+ }
451
+ async loadInferredStatusByTaskStatus() {
452
+ if (this.inferredStatusByTaskStatus)
453
+ return this.inferredStatusByTaskStatus;
454
+ const map = new Map();
455
+ this.inferredStatusByTaskStatus = map;
456
+ try {
457
+ const payload = await this.requestJson("GET", "issue_statuses.json");
458
+ const statuses = Array.isArray(payload.issue_statuses) ? payload.issue_statuses : [];
459
+ const parsed = [];
460
+ for (const item of statuses) {
461
+ if (!isRecord(item))
462
+ continue;
463
+ const id = typeof item.id === "number" ? item.id : null;
464
+ if (!id || !Number.isFinite(id))
465
+ continue;
466
+ parsed.push({
467
+ id,
468
+ name: toStringSafe(item.name).trim().toLowerCase(),
469
+ isClosed: item.is_closed === true,
470
+ isDefault: item.is_default === true,
471
+ });
472
+ }
473
+ const done = this.selectInferredStatus(parsed, "DONE");
474
+ const doing = this.selectInferredStatus(parsed, "DOING");
475
+ const todo = this.selectInferredStatus(parsed, "TODO");
476
+ if (done !== null)
477
+ map.set("DONE", done);
478
+ if (doing !== null)
479
+ map.set("DOING", doing);
480
+ if (todo !== null)
481
+ map.set("TODO", todo);
482
+ }
483
+ catch {
484
+ // Best effort: keep previous behavior when status discovery is unavailable.
485
+ }
486
+ return map;
487
+ }
488
+ selectInferredStatus(statuses, target) {
489
+ if (statuses.length === 0)
490
+ return null;
491
+ if (target === "DOING") {
492
+ const byId = statuses.find((item) => item.id === 2);
493
+ if (byId)
494
+ return byId.id;
495
+ const byName = statuses.find((item) => item.name.includes("progress") || item.name.includes("doing"));
496
+ if (byName)
497
+ return byName.id;
498
+ return null;
499
+ }
500
+ if (target === "DONE") {
501
+ const closed = statuses.find((item) => item.isClosed);
502
+ if (closed)
503
+ return closed.id;
504
+ const byId = statuses.find((item) => item.id === 5 || item.id === 3 || item.id === 6);
505
+ if (byId)
506
+ return byId.id;
507
+ const byName = statuses.find((item) => item.name.includes("done") ||
508
+ item.name.includes("closed") ||
509
+ item.name.includes("resolved") ||
510
+ item.name.includes("complete"));
511
+ if (byName)
512
+ return byName.id;
513
+ return null;
514
+ }
515
+ const byDefault = statuses.find((item) => item.isDefault);
516
+ if (byDefault)
517
+ return byDefault.id;
518
+ const byId = statuses.find((item) => item.id === 1);
519
+ if (byId)
520
+ return byId.id;
521
+ return statuses[0]?.id ?? null;
522
+ }
440
523
  async findIssueByTaskId(taskId) {
441
524
  const taskFieldId = this.taskIdFieldId();
442
525
  return await findIssueByTaskIdImpl({
@@ -58,6 +58,7 @@ export type TaskDocMeta = Pick<TaskData, "doc" | "doc_version" | "doc_updated_at
58
58
  export type TaskBackend = {
59
59
  id: string;
60
60
  listTasks(): Promise<TaskData[]>;
61
+ getLastListWarnings?(): string[];
61
62
  getTask(taskId: string): Promise<TaskData | null>;
62
63
  getTasks?(taskIds: string[]): Promise<(TaskData | null)[]>;
63
64
  writeTask(task: TaskData): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/shared/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/shared/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"task-index.d.ts","sourceRoot":"","sources":["../../src/backends/task-index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAI3C,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,CAAC,CAAC;IAClB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,CAAC,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC;AAE5C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU7D;AA8ED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAWpF;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5F;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,cAAc,CAMhB"}
1
+ {"version":3,"file":"task-index.d.ts","sourceRoot":"","sources":["../../src/backends/task-index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAI3C,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,CAAC,CAAC;IAClB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,cAAc,EAAE,CAAC,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,eAAe,CAAC;AAE5C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAU7D;AA8ED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAWpF;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5F;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,cAAc,CAahB"}
@@ -123,8 +123,15 @@ export async function saveTaskIndex(indexPath, index) {
123
123
  await writeJsonStableIfChanged(indexPath, index);
124
124
  }
125
125
  export function buildTaskIndexEntry(task, readmePath, mtimeMs) {
126
+ const compactTask = {
127
+ ...task,
128
+ // Keep the index payload lean for list/search/next paths.
129
+ doc: undefined,
130
+ comments: undefined,
131
+ events: undefined,
132
+ };
126
133
  return {
127
- task,
134
+ task: compactTask,
128
135
  readmePath,
129
136
  mtimeMs,
130
137
  };
@@ -1 +1 @@
1
- {"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../../src/cli/command-guide.ts"],"names":[],"mappings":"AAgMA,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CA8EzC"}
1
+ {"version":3,"file":"command-guide.d.ts","sourceRoot":"","sources":["../../src/cli/command-guide.ts"],"names":[],"mappings":"AAkMA,wBAAgB,SAAS,IAAI,MAAM,EAAE,CAEpC;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOzD;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CA2FzC"}
@@ -1,3 +1,4 @@
1
+ import { COMMAND_SNIPPETS } from "./command-snippets.js";
1
2
  const CHEAT_SHEET_ROWS = [
2
3
  {
3
4
  operation: "PLANNER: list/show tasks",
@@ -143,7 +144,7 @@ const ROLE_GUIDES = [
143
144
  {
144
145
  role: "REDMINE",
145
146
  lines: [
146
- "- Sync before/after updates: `agentplane sync redmine --direction pull` / `agentplane sync redmine --direction push --yes`",
147
+ `- Sync before/after updates: \`${COMMAND_SNIPPETS.sync.pullRedmineExplicit}\` / \`${COMMAND_SNIPPETS.sync.pushRedmineExplicitWithYes}\``,
147
148
  "- Then use normal task/doc commands (`agentplane task list` / `agentplane task show` / `agentplane task update` / `agentplane task doc set`) as needed.",
148
149
  ],
149
150
  },
@@ -201,11 +202,18 @@ export function renderQuickstart() {
201
202
  "",
202
203
  "## Daily task workflow",
203
204
  "",
204
- "- `agentplane task list` / `agentplane task show <task-id>`",
205
- '- `agentplane task new --title "..." --description "..." --priority med --owner CODER --tag <tag>`',
206
- '- `agentplane start <task-id> --author <ROLE> --body "Start: ..."`',
207
- '- `agentplane verify <task-id> --ok|--rework --by <ROLE> --note "..."`',
208
- '- `agentplane finish <task-id> --author <ROLE> --body "Verified: ..." --commit <git-rev> --close-commit`',
205
+ `- \`${COMMAND_SNIPPETS.core.taskList}\` / \`${COMMAND_SNIPPETS.core.taskShow}\``,
206
+ `- \`${COMMAND_SNIPPETS.core.taskNew}\``,
207
+ `- \`${COMMAND_SNIPPETS.core.startTask}\``,
208
+ `- \`${COMMAND_SNIPPETS.core.verifyTask}\``,
209
+ `- \`${COMMAND_SNIPPETS.core.finishTask}\``,
210
+ "",
211
+ "## Harness engeneering loop",
212
+ "",
213
+ "- Constrain: policy + workflow contract first.",
214
+ "- Execute: small explicit transitions.",
215
+ "- Observe: structured artifacts and diagnostics.",
216
+ "- Recover: deterministic fallback before manual repair.",
209
217
  "",
210
218
  "## Branch workflow (branch_pr)",
211
219
  "",
@@ -213,7 +221,12 @@ export function renderQuickstart() {
213
221
  "- `agentplane pr open <task-id>` / `agentplane pr update <task-id>` / `agentplane pr check <task-id>`",
214
222
  "- `agentplane integrate <task-id> --branch task/<task-id>/<slug> --run-verify`",
215
223
  "",
216
- "## Recipes and scenarios",
224
+ "## Workflow operations (core)",
225
+ "- `agentplane workflow debug`",
226
+ "- `agentplane workflow sync`",
227
+ "- `agentplane workflow land`",
228
+ "",
229
+ "## Recipes and scenarios (extensions)",
217
230
  "",
218
231
  "- `agentplane recipes list`",
219
232
  "- `agentplane recipes list --tag <tag>`",
@@ -223,7 +236,7 @@ export function renderQuickstart() {
223
236
  "",
224
237
  "## More guidance",
225
238
  "",
226
- "- `agentplane quickstart` and `agentplane role <ROLE>` show command guidance.",
239
+ `- \`${COMMAND_SNIPPETS.core.quickstart}\` and \`${COMMAND_SNIPPETS.core.role}\` show command guidance.`,
227
240
  "",
228
241
  "## Agent cheat sheet",
229
242
  "",
@@ -0,0 +1,24 @@
1
+ export declare const COMMAND_SNIPPETS: {
2
+ readonly core: {
3
+ readonly taskList: "agentplane task list";
4
+ readonly taskShow: "agentplane task show <task-id>";
5
+ readonly taskNew: "agentplane task new --title \"...\" --description \"...\" --priority med --owner CODER --tag <tag>";
6
+ readonly startTask: "agentplane start <task-id> --author <ROLE> --body \"Start: ...\"";
7
+ readonly verifyTask: "agentplane verify <task-id> --ok|--rework --by <ROLE> --note \"...\"";
8
+ readonly finishTask: "agentplane finish <task-id> --author <ROLE> --body \"Verified: ...\" --commit <git-rev> --close-commit";
9
+ readonly quickstart: "agentplane quickstart";
10
+ readonly role: "agentplane role <ROLE>";
11
+ };
12
+ readonly sync: {
13
+ readonly pullConfigured: "agentplane sync --direction pull";
14
+ readonly pushConfiguredWithYes: "agentplane sync --direction push --yes";
15
+ readonly pullRedmineExplicit: "agentplane sync redmine --direction pull";
16
+ readonly pushRedmineExplicitWithYes: "agentplane sync redmine --direction push --yes";
17
+ };
18
+ readonly backendSync: {
19
+ readonly pullLocal: "agentplane backend sync local --direction pull";
20
+ readonly pullRedmine: "agentplane backend sync redmine --direction pull";
21
+ readonly pushRedmineWithYes: "agentplane backend sync redmine --direction push --yes";
22
+ };
23
+ };
24
+ //# sourceMappingURL=command-snippets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-snippets.d.ts","sourceRoot":"","sources":["../../src/cli/command-snippets.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;CAwBnB,CAAC"}