agentplane 0.3.5 → 0.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -75
- package/assets/AGENTS.md +4 -2
- package/bin/dist-guard.js +13 -3
- package/bin/runtime-watch.d.ts +1 -0
- package/bin/runtime-watch.js +22 -5
- package/bin/stale-dist-policy.js +9 -2
- package/dist/.build-manifest.json +251 -821
- package/dist/adapters/task-backend/task-backend-adapter.d.ts +2 -2
- package/dist/adapters/task-backend/task-backend-adapter.d.ts.map +1 -1
- package/dist/adapters/task-backend/task-backend-adapter.js +2 -2
- package/dist/backends/task-backend/local-backend.d.ts +7 -5
- package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/local-backend.js +79 -7
- package/dist/backends/task-backend/redmine/env.d.ts +1 -1
- package/dist/backends/task-backend/redmine/env.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine/env.js +3 -0
- package/dist/backends/task-backend/redmine/inspect.d.ts +11 -0
- package/dist/backends/task-backend/redmine/inspect.d.ts.map +1 -0
- package/dist/backends/task-backend/redmine/inspect.js +75 -0
- package/dist/backends/task-backend/redmine/mapping.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine/mapping.js +21 -2
- package/dist/backends/task-backend/redmine/state.d.ts +17 -0
- package/dist/backends/task-backend/redmine/state.d.ts.map +1 -0
- package/dist/backends/task-backend/redmine/state.js +95 -0
- package/dist/backends/task-backend/redmine-backend.d.ts +10 -16
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +205 -15
- package/dist/backends/task-backend/shared/constants.d.ts +1 -1
- package/dist/backends/task-backend/shared/constants.js +1 -1
- package/dist/backends/task-backend/shared/record.d.ts.map +1 -1
- package/dist/backends/task-backend/shared/record.js +20 -1
- package/dist/backends/task-backend/shared/types.d.ts +42 -4
- package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
- package/dist/backends/task-backend/shared.d.ts +1 -1
- package/dist/backends/task-backend/shared.d.ts.map +1 -1
- package/dist/backends/task-backend.d.ts +1 -1
- package/dist/backends/task-backend.d.ts.map +1 -1
- package/dist/backends/task-backend.test-helpers.d.ts +4 -0
- package/dist/backends/task-backend.test-helpers.d.ts.map +1 -0
- package/dist/backends/task-backend.test-helpers.js +33 -0
- package/dist/backends/task-index.d.ts.map +1 -1
- package/dist/backends/task-index.js +1 -0
- package/dist/cli/bootstrap-guide.d.ts.map +1 -1
- package/dist/cli/bootstrap-guide.js +1 -0
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +3 -2
- package/dist/cli/reason-codes.d.ts.map +1 -1
- package/dist/cli/reason-codes.js +30 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/core.js +137 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.js +52 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/project.js +80 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts +19 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/shared.js +9 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/task.js +85 -0
- package/dist/cli/run-cli/command-catalog.d.ts +3 -18
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog.js +8 -337
- package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/ide.js +64 -2
- package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/ui.js +33 -13
- package/dist/cli/run-cli/commands/init/write-env.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-env.js +12 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.js +41 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts +2 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.js +6 -0
- package/dist/cli/run-cli.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +140 -6
- package/dist/commands/backend/sync.command.d.ts +5 -1
- package/dist/commands/backend/sync.command.d.ts.map +1 -1
- package/dist/commands/backend/sync.command.js +67 -3
- package/dist/commands/backend.d.ts +22 -0
- package/dist/commands/backend.d.ts.map +1 -1
- package/dist/commands/backend.js +110 -1
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +31 -7
- package/dist/commands/doctor/runtime.d.ts.map +1 -1
- package/dist/commands/doctor/runtime.js +3 -6
- package/dist/commands/doctor/workspace.d.ts +8 -0
- package/dist/commands/doctor/workspace.d.ts.map +1 -1
- package/dist/commands/doctor/workspace.js +127 -3
- package/dist/commands/guard/commit.command.d.ts.map +1 -1
- package/dist/commands/guard/commit.command.js +30 -6
- package/dist/commands/guard/impl/allow.d.ts +9 -0
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +26 -10
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +146 -18
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +2 -0
- package/dist/commands/hooks/index.d.ts.map +1 -1
- package/dist/commands/hooks/index.js +8 -35
- package/dist/commands/recipes/impl/apply.d.ts +4 -0
- package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
- package/dist/commands/recipes/impl/apply.js +34 -0
- package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/explain.js +70 -11
- package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/info.js +24 -12
- package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +32 -36
- package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list.js +7 -4
- package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/remove.js +9 -11
- package/dist/commands/recipes/impl/constants.d.ts +2 -0
- package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
- package/dist/commands/recipes/impl/constants.js +2 -0
- package/dist/commands/recipes/impl/manifest.d.ts.map +1 -1
- package/dist/commands/recipes/impl/manifest.js +219 -23
- package/dist/commands/recipes/impl/normalize.d.ts +3 -0
- package/dist/commands/recipes/impl/normalize.d.ts.map +1 -1
- package/dist/commands/recipes/impl/normalize.js +28 -24
- package/dist/commands/recipes/impl/paths.d.ts +9 -0
- package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
- package/dist/commands/recipes/impl/paths.js +10 -1
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts +7 -0
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -0
- package/dist/commands/recipes/impl/project-installed-recipes.js +102 -0
- package/dist/commands/recipes/impl/resolver.d.ts +20 -0
- package/dist/commands/recipes/impl/resolver.d.ts.map +1 -0
- package/dist/commands/recipes/impl/resolver.js +220 -0
- package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
- package/dist/commands/recipes/impl/scenario.js +40 -11
- package/dist/commands/recipes/impl/types.d.ts +145 -16
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.js +3 -2
- package/dist/commands/recipes.d.ts +6 -4
- package/dist/commands/recipes.d.ts.map +1 -1
- package/dist/commands/recipes.js +5 -3
- package/dist/commands/recipes.test-helpers.d.ts +185 -0
- package/dist/commands/recipes.test-helpers.d.ts.map +1 -0
- package/dist/commands/recipes.test-helpers.js +339 -0
- package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.js +192 -336
- package/dist/commands/scenario/info.command.d.ts.map +1 -1
- package/dist/commands/scenario/info.command.js +7 -2
- package/dist/commands/scenario/list.command.js +2 -2
- package/dist/commands/scenario/run.command.d.ts.map +1 -1
- package/dist/commands/scenario/run.command.js +7 -2
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
- package/dist/commands/shared/reconcile-check.js +77 -2
- package/dist/commands/shared/task-backend.d.ts +1 -1
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +9 -0
- package/dist/commands/shared/task-store.d.ts +92 -2
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +405 -43
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +84 -46
- package/dist/commands/task/close-duplicate.d.ts.map +1 -1
- package/dist/commands/task/close-duplicate.js +12 -37
- package/dist/commands/task/close-noop.d.ts.map +1 -1
- package/dist/commands/task/close-noop.js +12 -30
- package/dist/commands/task/close-shared.d.ts +14 -0
- package/dist/commands/task/close-shared.d.ts.map +1 -0
- package/dist/commands/task/close-shared.js +73 -0
- package/dist/commands/task/comment.d.ts.map +1 -1
- package/dist/commands/task/comment.js +34 -21
- package/dist/commands/task/derive.command.d.ts +1 -0
- package/dist/commands/task/derive.command.d.ts.map +1 -1
- package/dist/commands/task/derive.command.js +15 -2
- package/dist/commands/task/derive.d.ts +1 -0
- package/dist/commands/task/derive.d.ts.map +1 -1
- package/dist/commands/task/derive.js +27 -4
- package/dist/commands/task/doc-set.command.d.ts +2 -1
- package/dist/commands/task/doc-set.command.d.ts.map +1 -1
- package/dist/commands/task/doc-set.command.js +36 -4
- package/dist/commands/task/doc-template.d.ts.map +1 -1
- package/dist/commands/task/doc-template.js +2 -7
- package/dist/commands/task/doc.command.js +1 -1
- package/dist/commands/task/doc.d.ts +2 -1
- package/dist/commands/task/doc.d.ts.map +1 -1
- package/dist/commands/task/doc.js +139 -76
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +142 -80
- package/dist/commands/task/migrate-doc.d.ts +15 -0
- package/dist/commands/task/migrate-doc.d.ts.map +1 -1
- package/dist/commands/task/migrate-doc.js +128 -43
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +3 -1
- package/dist/commands/task/plan-set.command.js +1 -1
- package/dist/commands/task/plan.command.d.ts +8 -0
- package/dist/commands/task/plan.command.d.ts.map +1 -0
- package/dist/commands/task/plan.command.js +37 -0
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +198 -101
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +1 -1
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +115 -35
- package/dist/commands/task/shared/dependencies.d.ts +1 -0
- package/dist/commands/task/shared/dependencies.d.ts.map +1 -1
- package/dist/commands/task/shared/dependencies.js +10 -0
- package/dist/commands/task/shared/docs.d.ts +1 -0
- package/dist/commands/task/shared/docs.d.ts.map +1 -1
- package/dist/commands/task/shared/docs.js +8 -1
- package/dist/commands/task/shared/transitions.d.ts +17 -2
- package/dist/commands/task/shared/transitions.d.ts.map +1 -1
- package/dist/commands/task/shared/transitions.js +20 -13
- package/dist/commands/task/shared.d.ts +3 -3
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +3 -3
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +101 -71
- package/dist/commands/task/task.command.d.ts +8 -0
- package/dist/commands/task/task.command.d.ts.map +1 -0
- package/dist/commands/task/task.command.js +71 -0
- package/dist/commands/task/verify-command-shared.d.ts +16 -0
- package/dist/commands/task/verify-command-shared.d.ts.map +1 -0
- package/dist/commands/task/verify-command-shared.js +53 -0
- package/dist/commands/task/verify-ok.command.d.ts +2 -6
- package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
- package/dist/commands/task/verify-ok.command.js +8 -50
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +124 -145
- package/dist/commands/task/verify-rework.command.d.ts +2 -6
- package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
- package/dist/commands/task/verify-rework.command.js +8 -50
- package/dist/commands/upgrade/apply.d.ts +2 -0
- package/dist/commands/upgrade/apply.d.ts.map +1 -1
- package/dist/commands/upgrade/apply.js +33 -1
- package/dist/commands/upgrade.command.d.ts.map +1 -1
- package/dist/commands/upgrade.command.js +25 -0
- package/dist/commands/upgrade.d.ts +1 -0
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +34 -0
- package/dist/commands/verify.spec.d.ts.map +1 -1
- package/dist/commands/verify.spec.js +3 -12
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +16 -4
- package/dist/policy/rules/protected-paths.d.ts.map +1 -1
- package/dist/policy/rules/protected-paths.js +6 -1
- package/dist/ports/task-backend-port.d.ts +2 -2
- package/dist/ports/task-backend-port.d.ts.map +1 -1
- package/dist/shared/agent-emoji.d.ts.map +1 -1
- package/dist/shared/protected-paths.d.ts +17 -0
- package/dist/shared/protected-paths.d.ts.map +1 -1
- package/dist/shared/protected-paths.js +59 -10
- package/dist/shared/repo-cli-version.d.ts.map +1 -1
- package/dist/shared/repo-cli-version.js +9 -3
- package/package.json +2 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TaskData } from "../../backends/task-backend.js";
|
|
1
|
+
import type { TaskData, TaskWriteOptions } from "../../backends/task-backend.js";
|
|
2
2
|
import type { TaskBackendPort } from "../../ports/task-backend-port.js";
|
|
3
3
|
import type { CommandContext } from "../../commands/shared/task-backend.js";
|
|
4
4
|
export declare class TaskBackendAdapter implements TaskBackendPort {
|
|
@@ -6,7 +6,7 @@ export declare class TaskBackendAdapter implements TaskBackendPort {
|
|
|
6
6
|
constructor(ctx: CommandContext);
|
|
7
7
|
listTasks(): Promise<TaskData[]>;
|
|
8
8
|
getTask(id: string): Promise<TaskData | null>;
|
|
9
|
-
writeTask(task: TaskData): Promise<void>;
|
|
9
|
+
writeTask(task: TaskData, opts?: TaskWriteOptions): Promise<void>;
|
|
10
10
|
exportProjectionSnapshot(path: string): Promise<void>;
|
|
11
11
|
}
|
|
12
12
|
//# sourceMappingURL=task-backend-adapter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-backend-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/task-backend/task-backend-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"task-backend-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/task-backend/task-backend-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAE5E,qBAAa,kBAAmB,YAAW,eAAe;IACxD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAiB;gBAEzB,GAAG,EAAE,cAAc;IAI/B,SAAS,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIhC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAI7C,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAUtD"}
|
|
@@ -9,8 +9,8 @@ export class TaskBackendAdapter {
|
|
|
9
9
|
getTask(id) {
|
|
10
10
|
return this.ctx.taskBackend.getTask(id);
|
|
11
11
|
}
|
|
12
|
-
writeTask(task) {
|
|
13
|
-
return this.ctx.taskBackend.writeTask(task);
|
|
12
|
+
writeTask(task, opts) {
|
|
13
|
+
return this.ctx.taskBackend.writeTask(task, opts);
|
|
14
14
|
}
|
|
15
15
|
exportProjectionSnapshot(path) {
|
|
16
16
|
const backend = this.ctx.taskBackend;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type TaskBackend, type TaskData } from "./shared.js";
|
|
1
|
+
import { type TaskBackend, type TaskData, type TaskWriteOptions } from "./shared.js";
|
|
2
2
|
export declare class LocalBackend implements TaskBackend {
|
|
3
3
|
id: string;
|
|
4
4
|
capabilities: {
|
|
@@ -6,6 +6,8 @@ export declare class LocalBackend implements TaskBackend {
|
|
|
6
6
|
readonly projection: "canonical";
|
|
7
7
|
readonly reads_from_projection_by_default: true;
|
|
8
8
|
readonly writes_task_readmes: true;
|
|
9
|
+
readonly supports_task_revisions: true;
|
|
10
|
+
readonly supports_revision_guarded_writes: true;
|
|
9
11
|
readonly may_access_network_on_read: false;
|
|
10
12
|
readonly may_access_network_on_write: false;
|
|
11
13
|
readonly supports_projection_refresh: false;
|
|
@@ -29,10 +31,10 @@ export declare class LocalBackend implements TaskBackend {
|
|
|
29
31
|
getTask(taskId: string): Promise<TaskData | null>;
|
|
30
32
|
getTasks(taskIds: string[]): Promise<(TaskData | null)[]>;
|
|
31
33
|
getTaskDoc(taskId: string): Promise<string>;
|
|
32
|
-
writeTask(task: TaskData): Promise<void>;
|
|
33
|
-
setTaskDoc(taskId: string, doc: string, updatedBy?: string): Promise<void>;
|
|
34
|
-
touchTaskDocMetadata(taskId: string, updatedBy?: string): Promise<void>;
|
|
35
|
-
writeTasks(tasks: TaskData[]): Promise<void>;
|
|
34
|
+
writeTask(task: TaskData, opts?: TaskWriteOptions): Promise<void>;
|
|
35
|
+
setTaskDoc(taskId: string, doc: string, updatedBy?: string, opts?: TaskWriteOptions): Promise<void>;
|
|
36
|
+
touchTaskDocMetadata(taskId: string, updatedBy?: string, opts?: TaskWriteOptions): Promise<void>;
|
|
37
|
+
writeTasks(tasks: TaskData[], opts?: TaskWriteOptions): Promise<void>;
|
|
36
38
|
normalizeTasks(): Promise<{
|
|
37
39
|
scanned: number;
|
|
38
40
|
changed: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/local-backend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"local-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/local-backend.ts"],"names":[],"mappings":"AAsBA,OAAO,EAkBL,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AA4BrB,qBAAa,YAAa,YAAW,WAAW;IAC9C,EAAE,SAAW;IACb,YAAY;;;;;;;;;;;;MAYD;IACX,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;IAwHhC,mBAAmB,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAIhD,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,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA0GjE,UAAU,CACd,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,EACX,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,gBAAgB,GACtB,OAAO,CAAC,IAAI,CAAC;IA4BV,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,gBAAgB,GACtB,OAAO,CAAC,IAAI,CAAC;IAyBV,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOrE,cAAc,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAoG/D,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAGlE"}
|
|
@@ -1,10 +1,26 @@
|
|
|
1
1
|
import { mkdir, readdir, readFile, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { docChanged, parseTaskReadme, renderTaskReadme, taskReadmePath, } from "@agentplaneorg/core";
|
|
3
|
+
import { docChanged, parseTaskReadme, renderTaskReadme, taskDocToSectionMap, taskReadmePath, } from "@agentplaneorg/core";
|
|
4
4
|
import { isRecord } from "../../shared/guards.js";
|
|
5
5
|
import { writeTextIfChanged } from "../../shared/write-if-changed.js";
|
|
6
6
|
import { buildTaskIndexEntry, loadTaskIndex, resolveTaskIndexPath, saveTaskIndex, } from "../task-index.js";
|
|
7
|
-
import { DEFAULT_DOC_UPDATED_BY, defaultPlanApproval, defaultVerificationResult, extractTaskDoc, generateTaskId, invalidLengthMessage, mapLimit, mergeTaskDoc, missingTaskIdMessage, normalizeDocVersion, nowIso, resolveDocUpdatedByFromFrontmatter, resolveDocUpdatedByFromTask, taskRecordToData, validateTaskId, writeTasksExportFromTasks, } from "./shared.js";
|
|
7
|
+
import { DEFAULT_DOC_UPDATED_BY, defaultPlanApproval, defaultVerificationResult, extractTaskDoc, generateTaskId, invalidLengthMessage, mapLimit, mergeTaskDoc, missingTaskIdMessage, normalizeDocVersion, nowIso, resolveDocUpdatedByFromFrontmatter, resolveDocUpdatedByFromTask, taskRecordToData, validateTaskId, writeTasksExportFromTasks, BackendError, } from "./shared.js";
|
|
8
|
+
function storedRevisionFromFrontmatter(frontmatter, fallback) {
|
|
9
|
+
return Number.isInteger(frontmatter.revision) &&
|
|
10
|
+
typeof frontmatter.revision === "number" &&
|
|
11
|
+
frontmatter.revision > 0
|
|
12
|
+
? frontmatter.revision
|
|
13
|
+
: fallback;
|
|
14
|
+
}
|
|
15
|
+
function assertExpectedRevision(opts) {
|
|
16
|
+
if (opts.expectedRevision === undefined)
|
|
17
|
+
return;
|
|
18
|
+
const expected = Math.trunc(opts.expectedRevision);
|
|
19
|
+
if (expected <= 0 || expected === opts.currentRevision)
|
|
20
|
+
return;
|
|
21
|
+
throw new BackendError(`Task revision changed concurrently: ${opts.taskId} ` +
|
|
22
|
+
`(expected revision ${expected}, current revision ${opts.currentRevision})`, "E_BACKEND");
|
|
23
|
+
}
|
|
8
24
|
export class LocalBackend {
|
|
9
25
|
id = "local";
|
|
10
26
|
capabilities = {
|
|
@@ -12,6 +28,8 @@ export class LocalBackend {
|
|
|
12
28
|
projection: "canonical",
|
|
13
29
|
reads_from_projection_by_default: true,
|
|
14
30
|
writes_task_readmes: true,
|
|
31
|
+
supports_task_revisions: true,
|
|
32
|
+
supports_revision_guarded_writes: true,
|
|
15
33
|
may_access_network_on_read: false,
|
|
16
34
|
may_access_network_on_write: false,
|
|
17
35
|
supports_projection_refresh: false,
|
|
@@ -199,7 +217,7 @@ export class LocalBackend {
|
|
|
199
217
|
const parsed = parseTaskReadme(text);
|
|
200
218
|
return extractTaskDoc(parsed.body);
|
|
201
219
|
}
|
|
202
|
-
async writeTask(task) {
|
|
220
|
+
async writeTask(task, opts) {
|
|
203
221
|
const taskId = task.id.trim();
|
|
204
222
|
if (!taskId)
|
|
205
223
|
throw new Error(missingTaskIdMessage());
|
|
@@ -220,8 +238,25 @@ export class LocalBackend {
|
|
|
220
238
|
if (code !== "ENOENT")
|
|
221
239
|
throw err;
|
|
222
240
|
}
|
|
241
|
+
assertExpectedRevision({
|
|
242
|
+
taskId,
|
|
243
|
+
expectedRevision: opts?.expectedRevision,
|
|
244
|
+
currentRevision: Object.keys(existingFrontmatter).length > 0
|
|
245
|
+
? storedRevisionFromFrontmatter(existingFrontmatter, 1)
|
|
246
|
+
: 0,
|
|
247
|
+
});
|
|
223
248
|
const payload = { ...task };
|
|
224
249
|
delete payload.doc;
|
|
250
|
+
if (!Number.isInteger(payload.revision) ||
|
|
251
|
+
typeof payload.revision !== "number" ||
|
|
252
|
+
payload.revision <= 0) {
|
|
253
|
+
payload.revision =
|
|
254
|
+
Number.isInteger(existingFrontmatter.revision) &&
|
|
255
|
+
typeof existingFrontmatter.revision === "number" &&
|
|
256
|
+
existingFrontmatter.revision > 0
|
|
257
|
+
? existingFrontmatter.revision
|
|
258
|
+
: 1;
|
|
259
|
+
}
|
|
225
260
|
for (const [key, value] of Object.entries(payload)) {
|
|
226
261
|
if (value === undefined)
|
|
227
262
|
delete payload[key];
|
|
@@ -244,6 +279,17 @@ export class LocalBackend {
|
|
|
244
279
|
payload.verification = defaultVerificationResult();
|
|
245
280
|
}
|
|
246
281
|
const existingDocVersion = normalizeDocVersion(existingFrontmatter.doc_version);
|
|
282
|
+
const effectiveDoc = task.doc === undefined ? null : String(task.doc ?? "");
|
|
283
|
+
const nextSections = effectiveDoc === null
|
|
284
|
+
? task.sections && Object.keys(task.sections).length > 0
|
|
285
|
+
? task.sections
|
|
286
|
+
: existingDoc
|
|
287
|
+
? taskDocToSectionMap(existingDoc)
|
|
288
|
+
: undefined
|
|
289
|
+
: taskDocToSectionMap(effectiveDoc);
|
|
290
|
+
if (nextSections && Object.keys(nextSections).length > 0) {
|
|
291
|
+
payload.sections = nextSections;
|
|
292
|
+
}
|
|
247
293
|
if (task.doc !== undefined) {
|
|
248
294
|
const docText = String(task.doc ?? "");
|
|
249
295
|
body = mergeTaskDoc(body, docText);
|
|
@@ -264,10 +310,15 @@ export class LocalBackend {
|
|
|
264
310
|
const text = renderTaskReadme(payload, body || "");
|
|
265
311
|
await writeTextIfChanged(readme, text.endsWith("\n") ? text : `${text}\n`);
|
|
266
312
|
}
|
|
267
|
-
async setTaskDoc(taskId, doc, updatedBy) {
|
|
313
|
+
async setTaskDoc(taskId, doc, updatedBy, opts) {
|
|
268
314
|
const readme = taskReadmePath(this.root, taskId);
|
|
269
315
|
const text = await readFile(readme, "utf8");
|
|
270
316
|
const parsed = parseTaskReadme(text);
|
|
317
|
+
assertExpectedRevision({
|
|
318
|
+
taskId,
|
|
319
|
+
expectedRevision: opts?.expectedRevision,
|
|
320
|
+
currentRevision: storedRevisionFromFrontmatter(parsed.frontmatter, 1),
|
|
321
|
+
});
|
|
271
322
|
const docText = String(doc ?? "");
|
|
272
323
|
const body = mergeTaskDoc(parsed.body, docText);
|
|
273
324
|
const frontmatter = { ...parsed.frontmatter };
|
|
@@ -277,24 +328,34 @@ export class LocalBackend {
|
|
|
277
328
|
frontmatter.doc_updated_at = nowIso();
|
|
278
329
|
frontmatter.doc_updated_by = resolveDocUpdatedByFromFrontmatter(frontmatter, updatedBy, this.updatedBy);
|
|
279
330
|
}
|
|
331
|
+
frontmatter.sections = taskDocToSectionMap(docText);
|
|
280
332
|
frontmatter.doc_version = normalizeDocVersion(frontmatter.doc_version, currentDocVersion);
|
|
281
333
|
const next = renderTaskReadme(frontmatter, body);
|
|
282
334
|
await writeTextIfChanged(readme, next.endsWith("\n") ? next : `${next}\n`);
|
|
283
335
|
}
|
|
284
|
-
async touchTaskDocMetadata(taskId, updatedBy) {
|
|
336
|
+
async touchTaskDocMetadata(taskId, updatedBy, opts) {
|
|
285
337
|
const readme = taskReadmePath(this.root, taskId);
|
|
286
338
|
const text = await readFile(readme, "utf8");
|
|
287
339
|
const parsed = parseTaskReadme(text);
|
|
340
|
+
assertExpectedRevision({
|
|
341
|
+
taskId,
|
|
342
|
+
expectedRevision: opts?.expectedRevision,
|
|
343
|
+
currentRevision: storedRevisionFromFrontmatter(parsed.frontmatter, 1),
|
|
344
|
+
});
|
|
288
345
|
const frontmatter = { ...parsed.frontmatter };
|
|
289
346
|
frontmatter.doc_version = normalizeDocVersion(frontmatter.doc_version);
|
|
290
347
|
frontmatter.doc_updated_at = nowIso();
|
|
291
348
|
frontmatter.doc_updated_by = resolveDocUpdatedByFromFrontmatter(frontmatter, updatedBy, this.updatedBy);
|
|
349
|
+
frontmatter.sections =
|
|
350
|
+
isRecord(frontmatter.sections) && Object.keys(frontmatter.sections).length > 0
|
|
351
|
+
? frontmatter.sections
|
|
352
|
+
: taskDocToSectionMap(extractTaskDoc(parsed.body));
|
|
292
353
|
const next = renderTaskReadme(frontmatter, parsed.body || "");
|
|
293
354
|
await writeTextIfChanged(readme, next.endsWith("\n") ? next : `${next}\n`);
|
|
294
355
|
}
|
|
295
|
-
async writeTasks(tasks) {
|
|
356
|
+
async writeTasks(tasks, opts) {
|
|
296
357
|
await mapLimit(tasks, 4, async (task) => {
|
|
297
|
-
await this.writeTask(task);
|
|
358
|
+
await this.writeTask(task, opts);
|
|
298
359
|
return null;
|
|
299
360
|
});
|
|
300
361
|
}
|
|
@@ -334,6 +395,14 @@ export class LocalBackend {
|
|
|
334
395
|
// rendered output is identical (prevents mtime churn and diff-noise).
|
|
335
396
|
const payload = { ...task };
|
|
336
397
|
delete payload.doc;
|
|
398
|
+
if (!Number.isInteger(payload.revision) ||
|
|
399
|
+
typeof payload.revision !== "number" ||
|
|
400
|
+
payload.revision <= 0) {
|
|
401
|
+
payload.revision =
|
|
402
|
+
Number.isInteger(fm.revision) && typeof fm.revision === "number" && fm.revision > 0
|
|
403
|
+
? fm.revision
|
|
404
|
+
: 1;
|
|
405
|
+
}
|
|
337
406
|
for (const [key, value] of Object.entries(payload)) {
|
|
338
407
|
if (value === undefined)
|
|
339
408
|
delete payload[key];
|
|
@@ -359,6 +428,9 @@ export class LocalBackend {
|
|
|
359
428
|
if (payload.doc_updated_by === undefined || payload.doc_updated_by === "") {
|
|
360
429
|
payload.doc_updated_by = resolveDocUpdatedByFromTask(task, this.updatedBy);
|
|
361
430
|
}
|
|
431
|
+
if (!payload.sections && task.doc) {
|
|
432
|
+
payload.sections = taskDocToSectionMap(task.doc);
|
|
433
|
+
}
|
|
362
434
|
const next = renderTaskReadme(payload, parsed.body || "");
|
|
363
435
|
const didWrite = await writeTextIfChanged(readme, next.endsWith("\n") ? next : `${next}\n`);
|
|
364
436
|
return { taskId, scanned: true, changed: didWrite };
|
|
@@ -10,7 +10,7 @@ export type RedmineEnvConfig = {
|
|
|
10
10
|
pauseMs?: number;
|
|
11
11
|
};
|
|
12
12
|
};
|
|
13
|
-
type RedmineCustomFieldKey = "task_id" | "doc" | "doc_version" | "doc_updated_at" | "doc_updated_by" | "tags" | "priority" | "owner";
|
|
13
|
+
type RedmineCustomFieldKey = "task_id" | "canonical_state" | "doc" | "doc_version" | "doc_updated_at" | "doc_updated_by" | "tags" | "priority" | "owner";
|
|
14
14
|
export declare function readRedmineEnv(): RedmineEnvConfig;
|
|
15
15
|
export {};
|
|
16
16
|
//# sourceMappingURL=env.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/env.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,KAAK,qBAAqB,GACtB,SAAS,GACT,KAAK,GACL,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,MAAM,GACN,UAAU,GACV,OAAO,CAAC;AA6BZ,wBAAgB,cAAc,IAAI,gBAAgB,
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/env.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,KAAK,qBAAqB,GACtB,SAAS,GACT,iBAAiB,GACjB,KAAK,GACL,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,MAAM,GACN,UAAU,GACV,OAAO,CAAC;AA6BZ,wBAAgB,cAAc,IAAI,gBAAgB,CAmCjD"}
|
|
@@ -25,6 +25,9 @@ export function readRedmineEnv() {
|
|
|
25
25
|
const taskId = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_TASK_ID");
|
|
26
26
|
if (taskId !== undefined)
|
|
27
27
|
customFields.task_id = taskId;
|
|
28
|
+
const canonicalState = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_CANONICAL_STATE");
|
|
29
|
+
if (canonicalState !== undefined)
|
|
30
|
+
customFields.canonical_state = canonicalState;
|
|
28
31
|
const doc = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_DOC");
|
|
29
32
|
if (doc !== undefined)
|
|
30
33
|
customFields.doc = doc;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type TaskBackendFieldNameDrift, type TaskBackendVisibleField } from "../shared.js";
|
|
2
|
+
export declare function inspectVisibleCustomFields(opts: {
|
|
3
|
+
projectId: string;
|
|
4
|
+
requestJson: (method: string, reqPath: string, payload?: Record<string, unknown>, params?: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
5
|
+
}): Promise<TaskBackendVisibleField[]>;
|
|
6
|
+
export declare function inferVisibleCanonicalStateFieldId(visibleFields: TaskBackendVisibleField[]): number | null;
|
|
7
|
+
export declare function detectConfiguredFieldNameDrift(opts: {
|
|
8
|
+
configuredFields: Record<string, unknown>;
|
|
9
|
+
visibleFields: TaskBackendVisibleField[];
|
|
10
|
+
}): TaskBackendFieldNameDrift[];
|
|
11
|
+
//# sourceMappingURL=inspect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/inspect.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,yBAAyB,EAC9B,KAAK,uBAAuB,EAC7B,MAAM,cAAc,CAAC;AAYtB,wBAAsB,0BAA0B,CAAC,IAAI,EAAE;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,CACX,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACvC,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CA6CrC;AAED,wBAAgB,iCAAiC,CAC/C,aAAa,EAAE,uBAAuB,EAAE,GACvC,MAAM,GAAG,IAAI,CAGf;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE;IACnD,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,aAAa,EAAE,uBAAuB,EAAE,CAAC;CAC1C,GAAG,yBAAyB,EAAE,CAkB9B"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { isRecord } from "../../../shared/guards.js";
|
|
2
|
+
import { toStringSafe, } from "../shared.js";
|
|
3
|
+
function expectedFieldNameForKey(key) {
|
|
4
|
+
return key;
|
|
5
|
+
}
|
|
6
|
+
export async function inspectVisibleCustomFields(opts) {
|
|
7
|
+
const fields = new Map();
|
|
8
|
+
let offset = 0;
|
|
9
|
+
const limit = 100;
|
|
10
|
+
while (true) {
|
|
11
|
+
const payload = await opts.requestJson("GET", "issues.json", undefined, {
|
|
12
|
+
project_id: opts.projectId,
|
|
13
|
+
limit,
|
|
14
|
+
offset,
|
|
15
|
+
status_id: "*",
|
|
16
|
+
});
|
|
17
|
+
const issues = Array.isArray(payload.issues) ? payload.issues : [];
|
|
18
|
+
const pageIssues = issues.filter((issue) => isRecord(issue));
|
|
19
|
+
for (const issue of pageIssues) {
|
|
20
|
+
const customFields = Array.isArray(issue.custom_fields) ? issue.custom_fields : [];
|
|
21
|
+
for (const field of customFields) {
|
|
22
|
+
if (!isRecord(field) || typeof field.id !== "number")
|
|
23
|
+
continue;
|
|
24
|
+
const name = toStringSafe(field.name).trim();
|
|
25
|
+
if (!name)
|
|
26
|
+
continue;
|
|
27
|
+
const current = fields.get(field.id) ?? {
|
|
28
|
+
id: field.id,
|
|
29
|
+
name,
|
|
30
|
+
nonEmptyCount: 0,
|
|
31
|
+
};
|
|
32
|
+
const value = field.value;
|
|
33
|
+
if (value !== undefined && value !== null && toStringSafe(value).trim().length > 0) {
|
|
34
|
+
current.nonEmptyCount += 1;
|
|
35
|
+
}
|
|
36
|
+
fields.set(field.id, current);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const total = Number(payload.total_count ?? 0);
|
|
40
|
+
if (total === 0 || offset + limit >= total)
|
|
41
|
+
break;
|
|
42
|
+
offset += limit;
|
|
43
|
+
}
|
|
44
|
+
return [...fields.values()]
|
|
45
|
+
.toSorted((a, b) => a.id - b.id)
|
|
46
|
+
.map((field) => ({
|
|
47
|
+
id: field.id,
|
|
48
|
+
name: field.name,
|
|
49
|
+
nonEmptyCount: field.nonEmptyCount,
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
export function inferVisibleCanonicalStateFieldId(visibleFields) {
|
|
53
|
+
const field = visibleFields.find((entry) => entry.name.trim() === "canonical_state");
|
|
54
|
+
return field?.id ?? null;
|
|
55
|
+
}
|
|
56
|
+
export function detectConfiguredFieldNameDrift(opts) {
|
|
57
|
+
const byId = new Map(opts.visibleFields.map((field) => [field.id, field]));
|
|
58
|
+
const drift = [];
|
|
59
|
+
for (const [key, rawId] of Object.entries(opts.configuredFields)) {
|
|
60
|
+
if (typeof rawId !== "number")
|
|
61
|
+
continue;
|
|
62
|
+
const visible = byId.get(rawId);
|
|
63
|
+
if (!visible)
|
|
64
|
+
continue;
|
|
65
|
+
const expectedName = expectedFieldNameForKey(key);
|
|
66
|
+
if (visible.name.trim() === expectedName)
|
|
67
|
+
continue;
|
|
68
|
+
drift.push({
|
|
69
|
+
key,
|
|
70
|
+
configuredId: rawId,
|
|
71
|
+
visibleName: visible.name,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return drift.toSorted((a, b) => a.configuredId - b.configuredId || a.key.localeCompare(b.key));
|
|
75
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/mapping.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/mapping.ts"],"names":[],"mappings":"AAIA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AAOtB,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,CAqFlB;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,CA6C1B"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { renderTaskDocFromSections, taskDocToSectionMap } from "@agentplaneorg/core";
|
|
1
2
|
import { isRecord } from "../../../shared/guards.js";
|
|
2
3
|
import { ensureDocMetadata, normalizePriority, nowIso, toStringSafe, } from "../shared.js";
|
|
3
4
|
import { customFieldValue } from "./fields.js";
|
|
4
5
|
import { coerceDocVersion, maybeParseJson } from "./parse.js";
|
|
5
6
|
import { normalizeComments } from "./comments.js";
|
|
7
|
+
import { buildRedmineCanonicalState, parseRedmineCanonicalState } from "./state.js";
|
|
6
8
|
export function startDateFromTaskId(taskId) {
|
|
7
9
|
if (!taskId.includes("-"))
|
|
8
10
|
return null;
|
|
@@ -67,11 +69,13 @@ export function issueToTask(opts) {
|
|
|
67
69
|
const docVersionVal = customFieldValue(opts.issue, opts.customFields.doc_version);
|
|
68
70
|
const docUpdatedAtVal = customFieldValue(opts.issue, opts.customFields.doc_updated_at);
|
|
69
71
|
const docUpdatedByVal = customFieldValue(opts.issue, opts.customFields.doc_updated_by);
|
|
72
|
+
const canonicalStateVal = customFieldValue(opts.issue, opts.customFields.canonical_state);
|
|
70
73
|
const updatedOn = typeof opts.issue.updated_on === "string"
|
|
71
74
|
? opts.issue.updated_on
|
|
72
75
|
: typeof opts.issue.created_on === "string"
|
|
73
76
|
? opts.issue.created_on
|
|
74
77
|
: null;
|
|
78
|
+
const canonicalState = parseRedmineCanonicalState(canonicalStateVal);
|
|
75
79
|
const priorityVal = isRecord(opts.issue.priority) ? opts.issue.priority : null;
|
|
76
80
|
const priorityName = normalizePriority(priorityVal?.name ?? priorityFieldVal);
|
|
77
81
|
const tags = [];
|
|
@@ -104,15 +108,26 @@ export function issueToTask(opts) {
|
|
|
104
108
|
status: status ?? "TODO",
|
|
105
109
|
priority: priorityName,
|
|
106
110
|
owner: toStringSafe(ownerFieldVal ?? opts.ownerAgent),
|
|
111
|
+
revision: canonicalState?.revision ?? 1,
|
|
107
112
|
tags: mergedTags,
|
|
108
113
|
depends_on: [],
|
|
109
114
|
verify: maybeParseJson(verifyVal),
|
|
110
115
|
commit: maybeParseJson(commitVal),
|
|
111
116
|
comments: normalizeComments(maybeParseJson(commentsVal)),
|
|
117
|
+
plan_approval: canonicalState?.plan_approval,
|
|
118
|
+
verification: canonicalState?.verification,
|
|
119
|
+
events: canonicalState?.events,
|
|
112
120
|
id_source: "custom",
|
|
113
121
|
};
|
|
114
|
-
|
|
115
|
-
|
|
122
|
+
const canonicalSections = canonicalState?.sections;
|
|
123
|
+
const derivedDoc = canonicalSections
|
|
124
|
+
? renderTaskDocFromSections(canonicalSections)
|
|
125
|
+
: docVal
|
|
126
|
+
? toStringSafe(docVal)
|
|
127
|
+
: "";
|
|
128
|
+
if (derivedDoc)
|
|
129
|
+
task.doc = derivedDoc;
|
|
130
|
+
task.sections = canonicalSections ?? (derivedDoc ? taskDocToSectionMap(derivedDoc) : undefined);
|
|
116
131
|
const docVersion = coerceDocVersion(docVersionVal);
|
|
117
132
|
task.doc_version = docVersion ?? opts.defaultDocVersion;
|
|
118
133
|
task.doc_updated_at = docUpdatedAtVal ? toStringSafe(docUpdatedAtVal) : (updatedOn ?? nowIso());
|
|
@@ -145,6 +160,10 @@ export function taskToIssuePayload(opts) {
|
|
|
145
160
|
const customFields = [];
|
|
146
161
|
ensureDocMetadata(opts.task);
|
|
147
162
|
opts.appendCustomField(customFields, "task_id", opts.task.id);
|
|
163
|
+
const canonicalState = buildRedmineCanonicalState(opts.task);
|
|
164
|
+
if (canonicalState) {
|
|
165
|
+
opts.appendCustomField(customFields, "canonical_state", canonicalState);
|
|
166
|
+
}
|
|
148
167
|
opts.appendCustomField(customFields, "verify", opts.task.verify);
|
|
149
168
|
opts.appendCustomField(customFields, "commit", opts.task.commit);
|
|
150
169
|
opts.appendCustomField(customFields, "comments", opts.task.comments);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { TaskData } from "../shared/types.js";
|
|
2
|
+
export type RedmineCanonicalState = {
|
|
3
|
+
revision?: number;
|
|
4
|
+
sections?: Record<string, string>;
|
|
5
|
+
plan_approval?: TaskData["plan_approval"];
|
|
6
|
+
verification?: TaskData["verification"];
|
|
7
|
+
events?: TaskData["events"];
|
|
8
|
+
};
|
|
9
|
+
type BuildRedmineCanonicalStateOptions = {
|
|
10
|
+
base?: RedmineCanonicalState | null;
|
|
11
|
+
revision?: number | null;
|
|
12
|
+
};
|
|
13
|
+
export declare function parseRedmineCanonicalState(value: unknown): RedmineCanonicalState | null;
|
|
14
|
+
export declare function buildRedmineCanonicalState(task: TaskData): RedmineCanonicalState | null;
|
|
15
|
+
export declare function buildRedmineCanonicalStateWithOptions(task: TaskData, opts?: BuildRedmineCanonicalStateOptions): RedmineCanonicalState | null;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/state.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,aAAa,CAAC,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAC1C,YAAY,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IACxC,MAAM,CAAC,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;CAC7B,CAAC;AAEF,KAAK,iCAAiC,GAAG;IACvC,IAAI,CAAC,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B,CAAC;AA6BF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,qBAAqB,GAAG,IAAI,CA2BvF;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,QAAQ,GAAG,qBAAqB,GAAG,IAAI,CAEvF;AAED,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,QAAQ,EACd,IAAI,CAAC,EAAE,iCAAiC,GACvC,qBAAqB,GAAG,IAAI,CAwC9B"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { taskDocToSectionMap } from "@agentplaneorg/core";
|
|
2
|
+
import { isRecord } from "../../../shared/guards.js";
|
|
3
|
+
import { normalizeEvents } from "../shared/events.js";
|
|
4
|
+
import { normalizePlanApproval, normalizeVerificationResult } from "../shared/normalize.js";
|
|
5
|
+
import { toStringSafe } from "../shared/strings.js";
|
|
6
|
+
function normalizeRevision(value) {
|
|
7
|
+
return Number.isInteger(value) && Number(value) > 0 ? Number(value) : undefined;
|
|
8
|
+
}
|
|
9
|
+
function normalizeCanonicalSections(value) {
|
|
10
|
+
if (!isRecord(value))
|
|
11
|
+
return undefined;
|
|
12
|
+
const out = {};
|
|
13
|
+
for (const [title, text] of Object.entries(value)) {
|
|
14
|
+
const normalizedTitle = title.trim();
|
|
15
|
+
if (!normalizedTitle || typeof text !== "string")
|
|
16
|
+
continue;
|
|
17
|
+
out[normalizedTitle] = text.replaceAll("\r\n", "\n").trimEnd();
|
|
18
|
+
}
|
|
19
|
+
return Object.keys(out).length > 0 ? out : undefined;
|
|
20
|
+
}
|
|
21
|
+
function maybeParseJsonString(value) {
|
|
22
|
+
if (value === null || value === undefined)
|
|
23
|
+
return null;
|
|
24
|
+
const raw = toStringSafe(value).trim();
|
|
25
|
+
if (!raw)
|
|
26
|
+
return null;
|
|
27
|
+
if (!raw.startsWith("{"))
|
|
28
|
+
return raw;
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(raw);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return raw;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function parseRedmineCanonicalState(value) {
|
|
37
|
+
const parsed = maybeParseJsonString(value);
|
|
38
|
+
if (!isRecord(parsed))
|
|
39
|
+
return null;
|
|
40
|
+
const revision = normalizeRevision(parsed.revision);
|
|
41
|
+
const sections = normalizeCanonicalSections(parsed.sections);
|
|
42
|
+
const planApproval = normalizePlanApproval(parsed.plan_approval) ?? undefined;
|
|
43
|
+
const verification = normalizeVerificationResult(parsed.verification) ?? undefined;
|
|
44
|
+
const events = normalizeEvents(parsed.events);
|
|
45
|
+
if (revision === undefined &&
|
|
46
|
+
sections === undefined &&
|
|
47
|
+
planApproval === undefined &&
|
|
48
|
+
verification === undefined &&
|
|
49
|
+
events.length === 0) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
...(revision === undefined ? {} : { revision }),
|
|
54
|
+
...(sections ? { sections } : {}),
|
|
55
|
+
...(planApproval ? { plan_approval: planApproval } : {}),
|
|
56
|
+
...(verification ? { verification } : {}),
|
|
57
|
+
...(events.length > 0 ? { events } : {}),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function buildRedmineCanonicalState(task) {
|
|
61
|
+
return buildRedmineCanonicalStateWithOptions(task);
|
|
62
|
+
}
|
|
63
|
+
export function buildRedmineCanonicalStateWithOptions(task, opts) {
|
|
64
|
+
const base = opts?.base ?? null;
|
|
65
|
+
const revision = normalizeRevision(opts?.revision) ??
|
|
66
|
+
normalizeRevision(task.revision) ??
|
|
67
|
+
normalizeRevision(base?.revision);
|
|
68
|
+
const sections = normalizeCanonicalSections(task.sections) ??
|
|
69
|
+
(typeof task.doc === "string" && task.doc.trim().length > 0
|
|
70
|
+
? taskDocToSectionMap(task.doc)
|
|
71
|
+
: undefined) ??
|
|
72
|
+
normalizeCanonicalSections(base?.sections);
|
|
73
|
+
const planApproval = normalizePlanApproval(task.plan_approval) ??
|
|
74
|
+
normalizePlanApproval(base?.plan_approval) ??
|
|
75
|
+
undefined;
|
|
76
|
+
const verification = normalizeVerificationResult(task.verification) ??
|
|
77
|
+
normalizeVerificationResult(base?.verification) ??
|
|
78
|
+
undefined;
|
|
79
|
+
const events = normalizeEvents(task.events);
|
|
80
|
+
const fallbackEvents = events.length > 0 ? events : normalizeEvents(base?.events);
|
|
81
|
+
if (revision === undefined &&
|
|
82
|
+
sections === undefined &&
|
|
83
|
+
planApproval === undefined &&
|
|
84
|
+
verification === undefined &&
|
|
85
|
+
fallbackEvents.length === 0) {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
...(revision === undefined ? {} : { revision }),
|
|
90
|
+
...(sections ? { sections } : {}),
|
|
91
|
+
...(planApproval ? { plan_approval: planApproval } : {}),
|
|
92
|
+
...(verification ? { verification } : {}),
|
|
93
|
+
...(fallbackEvents.length > 0 ? { events: fallbackEvents } : {}),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { LocalBackend } from "./local-backend.js";
|
|
2
|
-
import { type TaskBackend, type TaskData } from "./shared.js";
|
|
2
|
+
import { type TaskCanonicalStateMigrationResult, type TaskBackend, type TaskBackendInspectionResult, type TaskData, type TaskWriteOptions } from "./shared.js";
|
|
3
3
|
export type RedmineSettings = {
|
|
4
4
|
url?: string;
|
|
5
5
|
api_key?: string;
|
|
@@ -13,17 +13,7 @@ export type RedmineSettings = {
|
|
|
13
13
|
};
|
|
14
14
|
export declare class RedmineBackend implements TaskBackend {
|
|
15
15
|
id: string;
|
|
16
|
-
capabilities:
|
|
17
|
-
readonly canonical_source: "remote";
|
|
18
|
-
readonly projection: "cache";
|
|
19
|
-
readonly reads_from_projection_by_default: true;
|
|
20
|
-
readonly writes_task_readmes: true;
|
|
21
|
-
readonly may_access_network_on_read: false;
|
|
22
|
-
readonly may_access_network_on_write: true;
|
|
23
|
-
readonly supports_projection_refresh: true;
|
|
24
|
-
readonly supports_push_sync: true;
|
|
25
|
-
readonly supports_snapshot_export: true;
|
|
26
|
-
};
|
|
16
|
+
capabilities: TaskBackend["capabilities"];
|
|
27
17
|
baseUrl: string;
|
|
28
18
|
apiKey: string;
|
|
29
19
|
projectId: string;
|
|
@@ -57,13 +47,15 @@ export declare class RedmineBackend implements TaskBackend {
|
|
|
57
47
|
scanned: number;
|
|
58
48
|
changed: number;
|
|
59
49
|
}>;
|
|
50
|
+
migrateCanonicalState(): Promise<TaskCanonicalStateMigrationResult>;
|
|
51
|
+
inspectConfiguration(): Promise<TaskBackendInspectionResult>;
|
|
60
52
|
getTask(taskId: string): Promise<TaskData | null>;
|
|
61
53
|
getTasks(taskIds: string[]): Promise<(TaskData | null)[]>;
|
|
62
54
|
getTaskDoc(taskId: string): Promise<string>;
|
|
63
|
-
setTaskDoc(taskId: string, doc: string, updatedBy?: string): Promise<void>;
|
|
64
|
-
touchTaskDocMetadata(taskId: string, updatedBy?: string): Promise<void>;
|
|
65
|
-
writeTask(task: TaskData): Promise<void>;
|
|
66
|
-
writeTasks(tasks: TaskData[]): Promise<void>;
|
|
55
|
+
setTaskDoc(taskId: string, doc: string, updatedBy?: string, opts?: TaskWriteOptions): Promise<void>;
|
|
56
|
+
touchTaskDocMetadata(taskId: string, updatedBy?: string, opts?: TaskWriteOptions): Promise<void>;
|
|
57
|
+
writeTask(task: TaskData, opts?: TaskWriteOptions): Promise<void>;
|
|
58
|
+
writeTasks(tasks: TaskData[], opts?: TaskWriteOptions): Promise<void>;
|
|
67
59
|
sync(opts: {
|
|
68
60
|
direction: "push" | "pull";
|
|
69
61
|
conflict: "diff" | "prefer-local" | "prefer-remote" | "fail";
|
|
@@ -77,6 +69,8 @@ export declare class RedmineBackend implements TaskBackend {
|
|
|
77
69
|
private diffTasks;
|
|
78
70
|
private tasksDiffer;
|
|
79
71
|
private cacheTask;
|
|
72
|
+
private assertExpectedRevisionSupported;
|
|
73
|
+
private assertExpectedRevision;
|
|
80
74
|
private taskIdFieldId;
|
|
81
75
|
private setIssueCustomFieldValue;
|
|
82
76
|
private listTasksRemote;
|
|
@@ -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;
|
|
1
|
+
{"version":3,"file":"redmine-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/redmine-backend.ts"],"names":[],"mappings":"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"}
|