@pellux/goodvibes-sdk 0.33.20 → 0.33.22

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 (65) hide show
  1. package/dist/browser-knowledge.d.ts +49 -0
  2. package/dist/browser-knowledge.d.ts.map +1 -1
  3. package/dist/browser-knowledge.js +22 -0
  4. package/dist/contracts/artifacts/operator-contract.json +4615 -4
  5. package/dist/events/agents.d.ts +11 -0
  6. package/dist/events/agents.d.ts.map +1 -1
  7. package/dist/events/index.d.ts +1 -1
  8. package/dist/events/index.d.ts.map +1 -1
  9. package/dist/events/planner.d.ts +69 -1
  10. package/dist/events/planner.d.ts.map +1 -1
  11. package/dist/platform/agents/wrfc-controller.d.ts +19 -0
  12. package/dist/platform/agents/wrfc-controller.d.ts.map +1 -1
  13. package/dist/platform/agents/wrfc-controller.js +286 -22
  14. package/dist/platform/agents/wrfc-reporting.d.ts.map +1 -1
  15. package/dist/platform/agents/wrfc-reporting.js +5 -1
  16. package/dist/platform/agents/wrfc-types.d.ts +1 -1
  17. package/dist/platform/agents/wrfc-types.d.ts.map +1 -1
  18. package/dist/platform/control-plane/method-catalog-knowledge.d.ts.map +1 -1
  19. package/dist/platform/control-plane/method-catalog-knowledge.js +154 -1
  20. package/dist/platform/control-plane/operator-contract-schemas-project-planning.d.ts +4 -0
  21. package/dist/platform/control-plane/operator-contract-schemas-project-planning.d.ts.map +1 -1
  22. package/dist/platform/control-plane/operator-contract-schemas-project-planning.js +78 -0
  23. package/dist/platform/core/orchestrator-turn-helpers.d.ts.map +1 -1
  24. package/dist/platform/core/orchestrator-turn-helpers.js +27 -11
  25. package/dist/platform/core/orchestrator-turn-loop.d.ts.map +1 -1
  26. package/dist/platform/core/orchestrator-turn-loop.js +4 -1
  27. package/dist/platform/core/wrfc-routing.d.ts +5 -0
  28. package/dist/platform/core/wrfc-routing.d.ts.map +1 -0
  29. package/dist/platform/core/wrfc-routing.js +51 -0
  30. package/dist/platform/daemon/http/project-planning-routes.d.ts.map +1 -1
  31. package/dist/platform/daemon/http/project-planning-routes.js +67 -0
  32. package/dist/platform/knowledge/index.d.ts +1 -1
  33. package/dist/platform/knowledge/index.d.ts.map +1 -1
  34. package/dist/platform/knowledge/project-planning/helpers.d.ts +1 -1
  35. package/dist/platform/knowledge/project-planning/helpers.d.ts.map +1 -1
  36. package/dist/platform/knowledge/project-planning/helpers.js +4 -0
  37. package/dist/platform/knowledge/project-planning/index.d.ts +1 -1
  38. package/dist/platform/knowledge/project-planning/index.d.ts.map +1 -1
  39. package/dist/platform/knowledge/project-planning/service.d.ts +21 -1
  40. package/dist/platform/knowledge/project-planning/service.d.ts.map +1 -1
  41. package/dist/platform/knowledge/project-planning/service.js +502 -1
  42. package/dist/platform/knowledge/project-planning/types.d.ts +140 -0
  43. package/dist/platform/knowledge/project-planning/types.d.ts.map +1 -1
  44. package/dist/platform/runtime/emitters/agents.d.ts +11 -0
  45. package/dist/platform/runtime/emitters/agents.d.ts.map +1 -1
  46. package/dist/platform/runtime/emitters/planner.d.ts +22 -0
  47. package/dist/platform/runtime/emitters/planner.d.ts.map +1 -1
  48. package/dist/platform/runtime/emitters/planner.js +15 -0
  49. package/dist/platform/runtime/events/index.d.ts +1 -1
  50. package/dist/platform/runtime/events/index.d.ts.map +1 -1
  51. package/dist/platform/runtime/services.d.ts.map +1 -1
  52. package/dist/platform/runtime/services.js +2 -0
  53. package/dist/platform/runtime/store/domains/agents.d.ts +3 -1
  54. package/dist/platform/runtime/store/domains/agents.d.ts.map +1 -1
  55. package/dist/platform/runtime/store/helpers/reducers/lifecycle.d.ts.map +1 -1
  56. package/dist/platform/runtime/store/helpers/reducers/lifecycle.js +25 -6
  57. package/dist/platform/tools/agent/index.d.ts.map +1 -1
  58. package/dist/platform/tools/agent/index.js +131 -64
  59. package/dist/platform/tools/agent/manager.d.ts +1 -0
  60. package/dist/platform/tools/agent/manager.d.ts.map +1 -1
  61. package/dist/platform/tools/agent/manager.js +36 -7
  62. package/dist/platform/tools/agent/schema.d.ts.map +1 -1
  63. package/dist/platform/tools/agent/schema.js +7 -6
  64. package/dist/platform/version.js +1 -1
  65. package/package.json +9 -9
@@ -2,5 +2,5 @@ export { ProjectPlanningService } from './service.js';
2
2
  export type { ProjectPlanningServiceOptions } from './service.js';
3
3
  export { PROJECT_PLANNING_CONNECTOR_ID, PROJECT_PLANNING_TAG, projectPlanningCanonicalUri, projectPlanningProjectIdFromPath, projectPlanningSourceId, resolveProjectPlanningSpace, } from './helpers.js';
4
4
  export { evaluateProjectPlanningReadiness } from './readiness.js';
5
- export type { ProjectPlanningAgentAssignment, ProjectPlanningAmbiguity, ProjectPlanningDecision, ProjectPlanningDecisionRecordInput, ProjectPlanningDecisionResult, ProjectPlanningDecisionsResult, ProjectPlanningDecisionStatus, ProjectPlanningDependency, ProjectPlanningEvaluateInput, ProjectPlanningEvaluation, ProjectPlanningGap, ProjectPlanningGapKind, ProjectPlanningGapSeverity, ProjectPlanningGateStatus, ProjectPlanningLanguageArtifact, ProjectPlanningLanguageResult, ProjectPlanningLanguageUpsertInput, ProjectPlanningQuestion, ProjectPlanningQuestionStatus, ProjectPlanningReadiness, ProjectPlanningSpaceInput, ProjectPlanningState, ProjectPlanningStateResult, ProjectPlanningStateUpsertInput, ProjectPlanningStatus, ProjectPlanningTask, ProjectPlanningTaskStatus, ProjectPlanningTerm, ProjectPlanningVerificationGate, } from './types.js';
5
+ export type { ProjectPlanningAgentAssignment, ProjectPlanningAmbiguity, ProjectPlanningDecision, ProjectPlanningDecisionRecordInput, ProjectPlanningDecisionResult, ProjectPlanningDecisionsResult, ProjectPlanningDecisionStatus, ProjectPlanningDependency, ProjectPlanningEvaluateInput, ProjectPlanningEvaluation, ProjectPlanningGap, ProjectPlanningGapKind, ProjectPlanningGapSeverity, ProjectPlanningGateStatus, ProjectPlanningLanguageArtifact, ProjectPlanningLanguageResult, ProjectPlanningLanguageUpsertInput, ProjectPlanningQuestion, ProjectPlanningQuestionStatus, ProjectPlanningReadiness, ProjectPlanningSpaceInput, ProjectPlanningState, ProjectPlanningStateResult, ProjectPlanningStateUpsertInput, ProjectPlanningStatus, ProjectPlanningTask, ProjectPlanningTaskStatus, ProjectPlanningTerm, ProjectPlanningVerificationGate, ProjectWorkPlanArtifact, ProjectWorkPlanClearCompletedInput, ProjectWorkPlanCounts, ProjectWorkPlanMutationResult, ProjectWorkPlanSnapshot, ProjectWorkPlanTask, ProjectWorkPlanTaskCreateInput, ProjectWorkPlanTaskDeleteInput, ProjectWorkPlanTaskGetInput, ProjectWorkPlanTaskListInput, ProjectWorkPlanTaskMutationSource, ProjectWorkPlanTaskReorderInput, ProjectWorkPlanTaskResult, ProjectWorkPlanTaskStatus, ProjectWorkPlanTaskStatusInput, ProjectWorkPlanTaskUpdateInput, } from './types.js';
6
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/platform/knowledge/project-planning/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EACL,6BAA6B,EAC7B,oBAAoB,EACpB,2BAA2B,EAC3B,gCAAgC,EAChC,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EACV,8BAA8B,EAC9B,wBAAwB,EACxB,uBAAuB,EACvB,kCAAkC,EAClC,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,EAC7B,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,+BAA+B,EAC/B,6BAA6B,EAC7B,kCAAkC,EAClC,uBAAuB,EACvB,6BAA6B,EAC7B,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,+BAA+B,EAC/B,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/platform/knowledge/project-planning/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EACL,6BAA6B,EAC7B,oBAAoB,EACpB,2BAA2B,EAC3B,gCAAgC,EAChC,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gCAAgC,EAAE,MAAM,gBAAgB,CAAC;AAClE,YAAY,EACV,8BAA8B,EAC9B,wBAAwB,EACxB,uBAAuB,EACvB,kCAAkC,EAClC,6BAA6B,EAC7B,8BAA8B,EAC9B,6BAA6B,EAC7B,yBAAyB,EACzB,4BAA4B,EAC5B,yBAAyB,EACzB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,yBAAyB,EACzB,+BAA+B,EAC/B,6BAA6B,EAC7B,kCAAkC,EAClC,uBAAuB,EACvB,6BAA6B,EAC7B,wBAAwB,EACxB,yBAAyB,EACzB,oBAAoB,EACpB,0BAA0B,EAC1B,+BAA+B,EAC/B,qBAAqB,EACrB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,+BAA+B,EAC/B,uBAAuB,EACvB,kCAAkC,EAClC,qBAAqB,EACrB,6BAA6B,EAC7B,uBAAuB,EACvB,mBAAmB,EACnB,8BAA8B,EAC9B,8BAA8B,EAC9B,2BAA2B,EAC3B,4BAA4B,EAC5B,iCAAiC,EACjC,+BAA+B,EAC/B,yBAAyB,EACzB,yBAAyB,EACzB,8BAA8B,EAC9B,8BAA8B,GAC/B,MAAM,YAAY,CAAC"}
@@ -1,12 +1,16 @@
1
1
  import { KnowledgeStore } from '../store.js';
2
- import type { ProjectPlanningDecisionRecordInput, ProjectPlanningDecisionResult, ProjectPlanningDecisionsResult, ProjectPlanningEvaluateInput, ProjectPlanningEvaluation, ProjectPlanningLanguageResult, ProjectPlanningLanguageUpsertInput, ProjectPlanningSpaceInput, ProjectPlanningStateResult, ProjectPlanningStateUpsertInput, ProjectPlanningStatus } from './types.js';
2
+ import type { RuntimeEventBus } from '../../runtime/events/index.js';
3
+ import type { ProjectPlanningDecisionRecordInput, ProjectPlanningDecisionResult, ProjectPlanningDecisionsResult, ProjectPlanningEvaluateInput, ProjectPlanningEvaluation, ProjectPlanningLanguageResult, ProjectPlanningLanguageUpsertInput, ProjectPlanningSpaceInput, ProjectPlanningStateResult, ProjectPlanningStateUpsertInput, ProjectPlanningStatus, ProjectWorkPlanClearCompletedInput, ProjectWorkPlanMutationResult, ProjectWorkPlanSnapshot, ProjectWorkPlanTaskCreateInput, ProjectWorkPlanTaskDeleteInput, ProjectWorkPlanTaskGetInput, ProjectWorkPlanTaskListInput, ProjectWorkPlanTaskReorderInput, ProjectWorkPlanTaskResult, ProjectWorkPlanTaskStatusInput, ProjectWorkPlanTaskUpdateInput } from './types.js';
3
4
  export interface ProjectPlanningServiceOptions {
4
5
  readonly defaultProjectId?: string | undefined;
6
+ readonly runtimeBus?: RuntimeEventBus | null | undefined;
5
7
  }
6
8
  export declare class ProjectPlanningService {
7
9
  private readonly store;
8
10
  private readonly defaultProjectId;
11
+ private runtimeBus;
9
12
  constructor(store: KnowledgeStore, options?: ProjectPlanningServiceOptions);
13
+ attachRuntimeBus(runtimeBus: RuntimeEventBus | null | undefined): void;
10
14
  status(input?: ProjectPlanningSpaceInput): Promise<ProjectPlanningStatus>;
11
15
  getState(input?: ProjectPlanningSpaceInput & {
12
16
  readonly planningId?: string | undefined;
@@ -17,9 +21,25 @@ export declare class ProjectPlanningService {
17
21
  recordDecision(input: ProjectPlanningDecisionRecordInput): Promise<ProjectPlanningDecisionResult>;
18
22
  getLanguage(input?: ProjectPlanningSpaceInput): Promise<ProjectPlanningLanguageResult>;
19
23
  upsertLanguage(input: ProjectPlanningLanguageUpsertInput): Promise<ProjectPlanningLanguageResult>;
24
+ getWorkPlanSnapshot(input?: ProjectWorkPlanTaskListInput): Promise<ProjectWorkPlanSnapshot>;
25
+ getWorkPlanTask(input: ProjectWorkPlanTaskGetInput): Promise<ProjectWorkPlanTaskResult>;
26
+ createWorkPlanTask(input: ProjectWorkPlanTaskCreateInput): Promise<ProjectWorkPlanMutationResult>;
27
+ updateWorkPlanTask(input: ProjectWorkPlanTaskUpdateInput): Promise<ProjectWorkPlanMutationResult>;
28
+ setWorkPlanTaskStatus(input: ProjectWorkPlanTaskStatusInput): Promise<ProjectWorkPlanMutationResult>;
29
+ reorderWorkPlanTasks(input: ProjectWorkPlanTaskReorderInput): Promise<ProjectWorkPlanSnapshot>;
30
+ deleteWorkPlanTask(input: ProjectWorkPlanTaskDeleteInput): Promise<ProjectWorkPlanMutationResult>;
31
+ clearCompletedWorkPlanTasks(input?: ProjectWorkPlanClearCompletedInput): Promise<ProjectWorkPlanMutationResult>;
20
32
  private resolveSpace;
21
33
  private sourcesForSpace;
22
34
  private getArtifactSource;
35
+ private getWorkPlanArtifact;
36
+ private saveWorkPlanArtifact;
37
+ private syncPlanningStateTasksToWorkPlan;
23
38
  private upsertArtifactSource;
39
+ private emitWorkPlanTaskCreated;
40
+ private emitWorkPlanTaskUpdated;
41
+ private emitWorkPlanTaskStatusChanged;
42
+ private emitWorkPlanTaskDeleted;
43
+ private emitWorkPlanSnapshotInvalidated;
24
44
  }
25
45
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/platform/knowledge/project-planning/service.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAa7C,OAAO,KAAK,EAEV,kCAAkC,EAClC,6BAA6B,EAC7B,8BAA8B,EAC9B,4BAA4B,EAC5B,yBAAyB,EAEzB,6BAA6B,EAC7B,kCAAkC,EAClC,yBAAyB,EAEzB,0BAA0B,EAC1B,+BAA+B,EAC/B,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChD;AAED,qBAAa,sBAAsB;IAI/B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAHxB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;gBAGvB,KAAK,EAAE,cAAc,EACtC,OAAO,GAAE,6BAAkC;IAKvC,MAAM,CAAC,KAAK,GAAE,yBAA8B,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAyB7E,QAAQ,CAAC,KAAK,GAAE,yBAAyB,GAAG;QAAE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAenI,WAAW,CAAC,KAAK,EAAE,+BAA+B,GAAG,OAAO,CAAC,0BAA0B,CAAC;IAgBxF,QAAQ,CAAC,KAAK,GAAE,4BAAiC,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAWtF,aAAa,CAAC,KAAK,GAAE,yBAA8B,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAgB7F,cAAc,CAAC,KAAK,EAAE,kCAAkC,GAAG,OAAO,CAAC,6BAA6B,CAAC;IA2BjG,WAAW,CAAC,KAAK,GAAE,yBAA8B,GAAG,OAAO,CAAC,6BAA6B,CAAC;IAc1F,cAAc,CAAC,KAAK,EAAE,kCAAkC,GAAG,OAAO,CAAC,6BAA6B,CAAC;IA2BvG,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,eAAe;IAOvB,OAAO,CAAC,iBAAiB;YASX,oBAAoB;CAyBnC"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/platform/knowledge/project-planning/service.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,20 @@
1
+ import { randomUUID } from 'node:crypto';
1
2
  import { knowledgeSpaceMetadata, normalizeProjectId, } from '../spaces.js';
2
3
  import { KnowledgeStore } from '../store.js';
4
+ import { emitWorkPlanSnapshotInvalidated, emitWorkPlanTaskCreated, emitWorkPlanTaskDeleted, emitWorkPlanTaskStatusChanged, emitWorkPlanTaskUpdated, } from '../../runtime/emitters/index.js';
3
5
  import { PROJECT_PLANNING_CONNECTOR_ID, PROJECT_PLANNING_TAG, projectPlanningArtifactSummary, projectPlanningCanonicalUri, projectPlanningSourceId, readPlanningMetadataObject, resolveProjectPlanningSpace, stablePlanningId, } from './helpers.js';
4
6
  import { evaluateProjectPlanningReadiness } from './readiness.js';
5
7
  export class ProjectPlanningService {
6
8
  store;
7
9
  defaultProjectId;
10
+ runtimeBus;
8
11
  constructor(store, options = {}) {
9
12
  this.store = store;
10
13
  this.defaultProjectId = normalizeProjectId(options.defaultProjectId ?? 'default');
14
+ this.runtimeBus = options.runtimeBus ?? null;
15
+ }
16
+ attachRuntimeBus(runtimeBus) {
17
+ this.runtimeBus = runtimeBus ?? null;
11
18
  }
12
19
  async status(input = {}) {
13
20
  await this.store.init();
@@ -22,12 +29,18 @@ export class ProjectPlanningService {
22
29
  states: sources.filter((source) => artifactKind(source) === 'state').length,
23
30
  decisions: sources.filter((source) => artifactKind(source) === 'decision').length,
24
31
  languageArtifacts: sources.filter((source) => artifactKind(source) === 'language').length,
32
+ workPlans: sources.filter((source) => artifactKind(source) === 'work-plan').length,
33
+ workPlanTasks: sources
34
+ .filter((source) => artifactKind(source) === 'work-plan')
35
+ .reduce((count, source) => count + (readWorkPlan(source)?.tasks.length ?? 0), 0),
25
36
  },
26
37
  capabilities: [
27
38
  'project-scoped-storage',
28
39
  'planning-state-validation',
29
40
  'project-language-artifacts',
30
41
  'decision-records',
42
+ 'durable-work-plan-tasks',
43
+ 'work-plan-transition-events',
31
44
  'agent-task-graph-metadata',
32
45
  'passive-daemon-only',
33
46
  ],
@@ -54,6 +67,7 @@ export class ProjectPlanningService {
54
67
  const evaluation = evaluateProjectPlanningReadiness(state);
55
68
  const normalized = evaluation.state;
56
69
  const source = await this.upsertArtifactSource(space, 'state', normalized.id, normalized);
70
+ await this.syncPlanningStateTasksToWorkPlan(space, normalized);
57
71
  return {
58
72
  ok: true,
59
73
  projectId: space.projectId,
@@ -152,6 +166,205 @@ export class ProjectPlanningService {
152
166
  source,
153
167
  };
154
168
  }
169
+ async getWorkPlanSnapshot(input = {}) {
170
+ await this.store.init();
171
+ const space = this.resolveSpace(input);
172
+ const workPlan = this.getWorkPlanArtifact(space, normalizeWorkPlanId(input.workPlanId));
173
+ return snapshotFromWorkPlan(space, workPlan, {
174
+ status: input.status,
175
+ parentTaskId: input.parentTaskId,
176
+ chainId: input.chainId,
177
+ owner: input.owner,
178
+ limit: input.limit,
179
+ });
180
+ }
181
+ async getWorkPlanTask(input) {
182
+ await this.store.init();
183
+ const snapshot = await this.getWorkPlanSnapshot(input);
184
+ return {
185
+ ok: true,
186
+ projectId: snapshot.projectId,
187
+ knowledgeSpaceId: snapshot.knowledgeSpaceId,
188
+ workPlanId: snapshot.workPlanId,
189
+ task: snapshot.tasks.find((task) => task.taskId === input.taskId) ?? null,
190
+ snapshot,
191
+ };
192
+ }
193
+ async createWorkPlanTask(input) {
194
+ await this.store.init();
195
+ const space = this.resolveSpace(input);
196
+ const workPlanId = normalizeWorkPlanId(input.workPlanId);
197
+ const existing = this.getWorkPlanArtifact(space, workPlanId);
198
+ const now = Date.now();
199
+ const task = normalizeWorkPlanTask(input.task, {
200
+ projectId: space.projectId,
201
+ knowledgeSpaceId: space.knowledgeSpaceId,
202
+ now,
203
+ fallbackOrder: nextWorkPlanOrder(existing.tasks),
204
+ });
205
+ if (existing.tasks.some((entry) => entry.taskId === task.taskId)) {
206
+ throw new Error(`Work plan task already exists: ${task.taskId}`);
207
+ }
208
+ const workPlan = await this.saveWorkPlanArtifact(space, {
209
+ ...existing,
210
+ tasks: sortWorkPlanTasks([...existing.tasks, task]),
211
+ updatedAt: now,
212
+ });
213
+ const snapshot = snapshotFromWorkPlan(space, workPlan);
214
+ this.emitWorkPlanTaskCreated(snapshot, task);
215
+ return {
216
+ ok: true,
217
+ projectId: space.projectId,
218
+ knowledgeSpaceId: space.knowledgeSpaceId,
219
+ workPlanId,
220
+ task,
221
+ snapshot,
222
+ };
223
+ }
224
+ async updateWorkPlanTask(input) {
225
+ await this.store.init();
226
+ const space = this.resolveSpace(input);
227
+ const workPlanId = normalizeWorkPlanId(input.workPlanId);
228
+ const existing = this.getWorkPlanArtifact(space, workPlanId);
229
+ const previousTask = existing.tasks.find((task) => task.taskId === input.taskId);
230
+ if (!previousTask)
231
+ throw new Error(`Work plan task not found: ${input.taskId}`);
232
+ const now = Date.now();
233
+ const task = normalizeWorkPlanTask({
234
+ ...previousTask,
235
+ ...input.patch,
236
+ metadata: {
237
+ ...(previousTask.metadata ?? {}),
238
+ ...(input.patch.metadata ?? {}),
239
+ },
240
+ taskId: previousTask.taskId,
241
+ createdAt: previousTask.createdAt,
242
+ updatedAt: now,
243
+ }, {
244
+ projectId: space.projectId,
245
+ knowledgeSpaceId: space.knowledgeSpaceId,
246
+ now,
247
+ fallbackOrder: previousTask.order,
248
+ });
249
+ const workPlan = await this.saveWorkPlanArtifact(space, {
250
+ ...existing,
251
+ tasks: sortWorkPlanTasks(existing.tasks.map((entry) => entry.taskId === input.taskId ? task : entry)),
252
+ updatedAt: now,
253
+ });
254
+ const snapshot = snapshotFromWorkPlan(space, workPlan);
255
+ this.emitWorkPlanTaskUpdated(snapshot, task, previousTask);
256
+ if (previousTask.status !== task.status) {
257
+ this.emitWorkPlanTaskStatusChanged(snapshot, task, previousTask);
258
+ }
259
+ return {
260
+ ok: true,
261
+ projectId: space.projectId,
262
+ knowledgeSpaceId: space.knowledgeSpaceId,
263
+ workPlanId,
264
+ task,
265
+ previousTask,
266
+ snapshot,
267
+ };
268
+ }
269
+ async setWorkPlanTaskStatus(input) {
270
+ return this.updateWorkPlanTask({
271
+ projectId: input.projectId,
272
+ knowledgeSpaceId: input.knowledgeSpaceId,
273
+ workPlanId: input.workPlanId,
274
+ taskId: input.taskId,
275
+ patch: {
276
+ status: normalizeWorkPlanStatus(input.status),
277
+ ...(input.source ? { source: input.source } : {}),
278
+ metadata: {
279
+ ...(input.reason ? { statusReason: input.reason } : {}),
280
+ },
281
+ },
282
+ });
283
+ }
284
+ async reorderWorkPlanTasks(input) {
285
+ await this.store.init();
286
+ const space = this.resolveSpace(input);
287
+ const workPlanId = normalizeWorkPlanId(input.workPlanId);
288
+ const existing = this.getWorkPlanArtifact(space, workPlanId);
289
+ const previousById = new Map(existing.tasks.map((task) => [task.taskId, task]));
290
+ const orderById = new Map(input.orderedTaskIds.map((taskId, index) => [taskId, index]));
291
+ for (const taskId of orderById.keys()) {
292
+ if (!previousById.has(taskId))
293
+ throw new Error(`Work plan task not found: ${taskId}`);
294
+ }
295
+ const now = Date.now();
296
+ const tasks = sortWorkPlanTasks(existing.tasks.map((task) => ({
297
+ ...task,
298
+ order: orderById.get(task.taskId) ?? task.order + input.orderedTaskIds.length,
299
+ updatedAt: orderById.has(task.taskId) ? now : task.updatedAt,
300
+ })));
301
+ const workPlan = await this.saveWorkPlanArtifact(space, {
302
+ ...existing,
303
+ tasks,
304
+ updatedAt: now,
305
+ });
306
+ const snapshot = snapshotFromWorkPlan(space, workPlan);
307
+ for (const task of tasks) {
308
+ const previousTask = previousById.get(task.taskId);
309
+ if (previousTask && previousTask.order !== task.order) {
310
+ this.emitWorkPlanTaskUpdated(snapshot, task, previousTask, true);
311
+ }
312
+ }
313
+ this.emitWorkPlanSnapshotInvalidated(snapshot, 'reordered');
314
+ return snapshot;
315
+ }
316
+ async deleteWorkPlanTask(input) {
317
+ await this.store.init();
318
+ const space = this.resolveSpace(input);
319
+ const workPlanId = normalizeWorkPlanId(input.workPlanId);
320
+ const existing = this.getWorkPlanArtifact(space, workPlanId);
321
+ const deletedTask = existing.tasks.find((task) => task.taskId === input.taskId);
322
+ if (!deletedTask)
323
+ throw new Error(`Work plan task not found: ${input.taskId}`);
324
+ const now = Date.now();
325
+ const workPlan = await this.saveWorkPlanArtifact(space, {
326
+ ...existing,
327
+ tasks: existing.tasks.filter((task) => task.taskId !== input.taskId),
328
+ updatedAt: now,
329
+ });
330
+ const snapshot = snapshotFromWorkPlan(space, workPlan);
331
+ this.emitWorkPlanTaskDeleted(snapshot, deletedTask);
332
+ return {
333
+ ok: true,
334
+ projectId: space.projectId,
335
+ knowledgeSpaceId: space.knowledgeSpaceId,
336
+ workPlanId,
337
+ deletedTask,
338
+ snapshot,
339
+ };
340
+ }
341
+ async clearCompletedWorkPlanTasks(input = {}) {
342
+ await this.store.init();
343
+ const space = this.resolveSpace(input);
344
+ const workPlanId = normalizeWorkPlanId(input.workPlanId);
345
+ const existing = this.getWorkPlanArtifact(space, workPlanId);
346
+ const statuses = new Set(input.statuses?.length ? input.statuses.map(normalizeWorkPlanStatus) : ['done']);
347
+ const cleared = existing.tasks.filter((task) => statuses.has(task.status));
348
+ const now = Date.now();
349
+ const workPlan = await this.saveWorkPlanArtifact(space, {
350
+ ...existing,
351
+ tasks: existing.tasks.filter((task) => !statuses.has(task.status)),
352
+ updatedAt: now,
353
+ });
354
+ const snapshot = snapshotFromWorkPlan(space, workPlan);
355
+ for (const task of cleared) {
356
+ this.emitWorkPlanTaskDeleted(snapshot, task, true);
357
+ }
358
+ this.emitWorkPlanSnapshotInvalidated(snapshot, 'cleared-completed');
359
+ return {
360
+ ok: true,
361
+ projectId: space.projectId,
362
+ knowledgeSpaceId: space.knowledgeSpaceId,
363
+ workPlanId,
364
+ clearedTaskIds: cleared.map((task) => task.taskId),
365
+ snapshot,
366
+ };
367
+ }
155
368
  resolveSpace(input = {}) {
156
369
  return resolveProjectPlanningSpace(input, this.defaultProjectId);
157
370
  }
@@ -165,6 +378,75 @@ export class ProjectPlanningService {
165
378
  const sourceId = projectPlanningSourceId(spaceId, kind, id);
166
379
  return this.store.getSource(sourceId) ?? this.store.getSourceByCanonicalUri(projectPlanningCanonicalUri(spaceId, kind, id));
167
380
  }
381
+ getWorkPlanArtifact(space, workPlanId) {
382
+ const source = this.getArtifactSource(space.knowledgeSpaceId, 'work-plan', workPlanId);
383
+ const value = source?.metadata.value;
384
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
385
+ return normalizeWorkPlanArtifact(value, space, workPlanId);
386
+ }
387
+ const now = Date.now();
388
+ return {
389
+ id: workPlanId,
390
+ projectId: space.projectId,
391
+ knowledgeSpaceId: space.knowledgeSpaceId,
392
+ tasks: [],
393
+ createdAt: now,
394
+ updatedAt: now,
395
+ };
396
+ }
397
+ async saveWorkPlanArtifact(space, workPlan) {
398
+ const normalized = normalizeWorkPlanArtifact(workPlan, space, workPlan.id);
399
+ await this.upsertArtifactSource(space, 'work-plan', normalized.id, normalized);
400
+ return normalized;
401
+ }
402
+ async syncPlanningStateTasksToWorkPlan(space, state) {
403
+ for (const [index, task] of state.tasks.entries()) {
404
+ if (!task.title?.trim())
405
+ continue;
406
+ const taskId = normalizeWorkPlanTaskId(`planning-${state.id}-${task.id || task.title}`);
407
+ const workPlanTask = {
408
+ taskId,
409
+ title: task.title,
410
+ notes: task.why,
411
+ owner: task.recommendedAgent,
412
+ status: workPlanStatusFromPlanningTask(task),
413
+ priority: task.needsReview ? 10 : 0,
414
+ order: index,
415
+ source: 'planning',
416
+ tags: [
417
+ 'planning',
418
+ ...(task.needsReview ? ['needs-review'] : []),
419
+ ...(task.blockedOnUserInput ? ['blocked-on-user-input'] : []),
420
+ ],
421
+ originSurface: 'daemon',
422
+ metadata: {
423
+ planningId: state.id,
424
+ planningTaskId: task.id,
425
+ dependencies: task.dependencies ?? [],
426
+ likelyFiles: task.likelyFiles ?? [],
427
+ verification: task.verification ?? [],
428
+ canRunConcurrently: task.canRunConcurrently === true,
429
+ },
430
+ };
431
+ try {
432
+ await this.createWorkPlanTask({
433
+ projectId: space.projectId,
434
+ knowledgeSpaceId: space.knowledgeSpaceId,
435
+ task: workPlanTask,
436
+ });
437
+ }
438
+ catch (error) {
439
+ if (!(error instanceof Error) || !error.message.includes('already exists'))
440
+ throw error;
441
+ await this.updateWorkPlanTask({
442
+ projectId: space.projectId,
443
+ knowledgeSpaceId: space.knowledgeSpaceId,
444
+ taskId,
445
+ patch: workPlanTask,
446
+ });
447
+ }
448
+ }
449
+ }
168
450
  async upsertArtifactSource(space, kind, id, value) {
169
451
  const spaceId = space.knowledgeSpaceId;
170
452
  return this.store.upsertSource({
@@ -185,6 +467,67 @@ export class ProjectPlanningService {
185
467
  }),
186
468
  });
187
469
  }
470
+ emitWorkPlanTaskCreated(snapshot, task) {
471
+ if (!this.runtimeBus)
472
+ return;
473
+ emitWorkPlanTaskCreated(this.runtimeBus, workPlanEmitterContext(snapshot), {
474
+ projectId: snapshot.projectId,
475
+ knowledgeSpaceId: snapshot.knowledgeSpaceId,
476
+ workPlanId: snapshot.workPlanId,
477
+ task,
478
+ });
479
+ this.emitWorkPlanSnapshotInvalidated(snapshot, 'task-created');
480
+ }
481
+ emitWorkPlanTaskUpdated(snapshot, task, previousTask, skipSnapshotInvalidation = false) {
482
+ if (!this.runtimeBus)
483
+ return;
484
+ emitWorkPlanTaskUpdated(this.runtimeBus, workPlanEmitterContext(snapshot), {
485
+ projectId: snapshot.projectId,
486
+ knowledgeSpaceId: snapshot.knowledgeSpaceId,
487
+ workPlanId: snapshot.workPlanId,
488
+ task,
489
+ previousTask,
490
+ });
491
+ if (!skipSnapshotInvalidation)
492
+ this.emitWorkPlanSnapshotInvalidated(snapshot, 'task-updated');
493
+ }
494
+ emitWorkPlanTaskStatusChanged(snapshot, task, previousTask) {
495
+ if (!this.runtimeBus)
496
+ return;
497
+ emitWorkPlanTaskStatusChanged(this.runtimeBus, workPlanEmitterContext(snapshot), {
498
+ projectId: snapshot.projectId,
499
+ knowledgeSpaceId: snapshot.knowledgeSpaceId,
500
+ workPlanId: snapshot.workPlanId,
501
+ taskId: task.taskId,
502
+ status: task.status,
503
+ previousStatus: previousTask.status,
504
+ task,
505
+ });
506
+ }
507
+ emitWorkPlanTaskDeleted(snapshot, task, skipSnapshotInvalidation = false) {
508
+ if (!this.runtimeBus)
509
+ return;
510
+ emitWorkPlanTaskDeleted(this.runtimeBus, workPlanEmitterContext(snapshot), {
511
+ projectId: snapshot.projectId,
512
+ knowledgeSpaceId: snapshot.knowledgeSpaceId,
513
+ workPlanId: snapshot.workPlanId,
514
+ taskId: task.taskId,
515
+ task,
516
+ });
517
+ if (!skipSnapshotInvalidation)
518
+ this.emitWorkPlanSnapshotInvalidated(snapshot, 'task-deleted');
519
+ }
520
+ emitWorkPlanSnapshotInvalidated(snapshot, reason) {
521
+ if (!this.runtimeBus)
522
+ return;
523
+ emitWorkPlanSnapshotInvalidated(this.runtimeBus, workPlanEmitterContext(snapshot), {
524
+ projectId: snapshot.projectId,
525
+ knowledgeSpaceId: snapshot.knowledgeSpaceId,
526
+ workPlanId: snapshot.workPlanId,
527
+ reason,
528
+ snapshot,
529
+ });
530
+ }
188
531
  }
189
532
  function normalizeState(input, projectId, knowledgeSpaceId) {
190
533
  const now = Date.now();
@@ -213,6 +556,158 @@ function normalizeState(input, projectId, knowledgeSpaceId) {
213
556
  metadata: readPlanningMetadataObject(input.metadata),
214
557
  };
215
558
  }
559
+ function normalizeWorkPlanArtifact(input, space, workPlanId) {
560
+ const now = Date.now();
561
+ const createdAt = typeof input.createdAt === 'number' ? input.createdAt : now;
562
+ const tasks = Array.isArray(input.tasks)
563
+ ? input.tasks.map((task, index) => normalizeWorkPlanTask(task, {
564
+ projectId: space.projectId,
565
+ knowledgeSpaceId: space.knowledgeSpaceId,
566
+ now,
567
+ fallbackOrder: index,
568
+ }))
569
+ : [];
570
+ return {
571
+ id: normalizeWorkPlanId(input.id ?? workPlanId),
572
+ projectId: space.projectId,
573
+ knowledgeSpaceId: space.knowledgeSpaceId,
574
+ tasks: sortWorkPlanTasks(tasks),
575
+ createdAt,
576
+ updatedAt: typeof input.updatedAt === 'number' ? input.updatedAt : now,
577
+ ...(input.metadata ? { metadata: readPlanningMetadataObject(input.metadata) } : {}),
578
+ };
579
+ }
580
+ function normalizeWorkPlanTask(input, options) {
581
+ const title = typeof input.title === 'string' ? input.title.trim() : '';
582
+ if (!title)
583
+ throw new Error('Work plan task title is required.');
584
+ const status = normalizeWorkPlanStatus(input.status ?? 'pending');
585
+ const createdAt = typeof input.createdAt === 'number' ? input.createdAt : options.now;
586
+ return {
587
+ taskId: normalizeWorkPlanTaskId(input.taskId ?? `task-${randomUUID().slice(0, 12)}`),
588
+ projectId: options.projectId,
589
+ knowledgeSpaceId: options.knowledgeSpaceId,
590
+ title,
591
+ ...(typeof input.notes === 'string' ? { notes: input.notes } : {}),
592
+ ...(typeof input.owner === 'string' && input.owner.trim() ? { owner: input.owner.trim() } : {}),
593
+ status,
594
+ ...(typeof input.priority === 'number' && Number.isFinite(input.priority) ? { priority: input.priority } : {}),
595
+ order: typeof input.order === 'number' && Number.isFinite(input.order) ? input.order : options.fallbackOrder,
596
+ ...(typeof input.source === 'string' && input.source.trim() ? { source: input.source.trim() } : {}),
597
+ tags: stringList(input.tags),
598
+ ...(typeof input.parentTaskId === 'string' && input.parentTaskId.trim() ? { parentTaskId: normalizeWorkPlanTaskId(input.parentTaskId) } : {}),
599
+ ...(typeof input.chainId === 'string' && input.chainId.trim() ? { chainId: input.chainId.trim() } : {}),
600
+ ...(typeof input.phaseId === 'string' && input.phaseId.trim() ? { phaseId: input.phaseId.trim() } : {}),
601
+ ...(typeof input.agentId === 'string' && input.agentId.trim() ? { agentId: input.agentId.trim() } : {}),
602
+ ...(typeof input.turnId === 'string' && input.turnId.trim() ? { turnId: input.turnId.trim() } : {}),
603
+ ...(typeof input.decisionId === 'string' && input.decisionId.trim() ? { decisionId: input.decisionId.trim() } : {}),
604
+ ...(typeof input.sourceMessageId === 'string' && input.sourceMessageId.trim() ? { sourceMessageId: input.sourceMessageId.trim() } : {}),
605
+ linkedArtifactIds: stringList(input.linkedArtifactIds),
606
+ linkedSourceIds: stringList(input.linkedSourceIds),
607
+ linkedNodeIds: stringList(input.linkedNodeIds),
608
+ ...(typeof input.originSurface === 'string' && input.originSurface.trim() ? { originSurface: input.originSurface.trim() } : {}),
609
+ createdAt,
610
+ updatedAt: typeof input.updatedAt === 'number' ? input.updatedAt : options.now,
611
+ ...(status === 'done' || status === 'failed' || status === 'cancelled'
612
+ ? { completedAt: typeof input.completedAt === 'number' ? input.completedAt : options.now }
613
+ : {}),
614
+ ...(input.metadata ? { metadata: readPlanningMetadataObject(input.metadata) } : {}),
615
+ };
616
+ }
617
+ function normalizeWorkPlanId(value) {
618
+ return typeof value === 'string' && value.trim().length > 0
619
+ ? stablePlanningId('work-plan', value)
620
+ : 'current';
621
+ }
622
+ function normalizeWorkPlanTaskId(value) {
623
+ return typeof value === 'string' && value.trim().length > 0
624
+ ? stablePlanningId('task', value)
625
+ : `task-${randomUUID().slice(0, 12)}`;
626
+ }
627
+ function normalizeWorkPlanStatus(value) {
628
+ if (value === 'pending'
629
+ || value === 'in_progress'
630
+ || value === 'blocked'
631
+ || value === 'done'
632
+ || value === 'failed'
633
+ || value === 'cancelled') {
634
+ return value;
635
+ }
636
+ if (value === 'in-progress')
637
+ return 'in_progress';
638
+ if (value === 'completed')
639
+ return 'done';
640
+ throw new Error(`Invalid work plan task status: ${String(value)}`);
641
+ }
642
+ function workPlanStatusFromPlanningTask(task) {
643
+ if (task.status === 'in-progress')
644
+ return 'in_progress';
645
+ if (task.status === 'blocked')
646
+ return 'blocked';
647
+ if (task.status === 'completed')
648
+ return 'done';
649
+ if (task.blockedOnUserInput === true)
650
+ return 'blocked';
651
+ return 'pending';
652
+ }
653
+ function stringList(value) {
654
+ if (!Array.isArray(value))
655
+ return [];
656
+ return [...new Set(value.filter((entry) => typeof entry === 'string' && entry.trim().length > 0).map((entry) => entry.trim()))];
657
+ }
658
+ function nextWorkPlanOrder(tasks) {
659
+ return tasks.reduce((max, task) => Math.max(max, task.order), -1) + 1;
660
+ }
661
+ function sortWorkPlanTasks(tasks) {
662
+ return [...tasks].sort((a, b) => a.order - b.order || a.createdAt - b.createdAt || a.taskId.localeCompare(b.taskId));
663
+ }
664
+ function snapshotFromWorkPlan(space, workPlan, filter = {}) {
665
+ const tasks = sortWorkPlanTasks(workPlan.tasks).filter((task) => {
666
+ if (filter.status && task.status !== filter.status)
667
+ return false;
668
+ if (filter.parentTaskId && task.parentTaskId !== filter.parentTaskId)
669
+ return false;
670
+ if (filter.chainId && task.chainId !== filter.chainId)
671
+ return false;
672
+ if (filter.owner && task.owner !== filter.owner)
673
+ return false;
674
+ return true;
675
+ });
676
+ const limit = typeof filter.limit === 'number' && Number.isFinite(filter.limit) && filter.limit > 0
677
+ ? Math.floor(filter.limit)
678
+ : undefined;
679
+ return {
680
+ ok: true,
681
+ projectId: space.projectId,
682
+ knowledgeSpaceId: space.knowledgeSpaceId,
683
+ workPlanId: workPlan.id,
684
+ tasks: limit ? tasks.slice(0, limit) : tasks,
685
+ counts: countWorkPlanTasks(workPlan.tasks),
686
+ updatedAt: workPlan.updatedAt,
687
+ };
688
+ }
689
+ function countWorkPlanTasks(tasks) {
690
+ const counts = {
691
+ total: tasks.length,
692
+ pending: 0,
693
+ in_progress: 0,
694
+ blocked: 0,
695
+ done: 0,
696
+ failed: 0,
697
+ cancelled: 0,
698
+ };
699
+ for (const task of tasks) {
700
+ counts[task.status] += 1;
701
+ }
702
+ return counts;
703
+ }
704
+ function workPlanEmitterContext(snapshot) {
705
+ return {
706
+ traceId: `project-planning:work-plan:${snapshot.workPlanId}:${snapshot.updatedAt}`,
707
+ sessionId: `project:${snapshot.projectId}`,
708
+ source: 'project-planning.work-plan',
709
+ };
710
+ }
216
711
  function normalizePlanningId(value) {
217
712
  return typeof value === 'string' && value.trim().length > 0
218
713
  ? stablePlanningId('plan', value)
@@ -236,7 +731,7 @@ function arrayOfObjectsOrStrings(value) {
236
731
  }
237
732
  function artifactKind(source) {
238
733
  const kind = source.metadata.planningArtifactKind;
239
- return kind === 'state' || kind === 'decision' || kind === 'language' ? kind : null;
734
+ return kind === 'state' || kind === 'decision' || kind === 'language' || kind === 'work-plan' ? kind : null;
240
735
  }
241
736
  function readState(source) {
242
737
  const value = source.metadata.value;
@@ -250,10 +745,16 @@ function readLanguage(source) {
250
745
  const value = source.metadata.value;
251
746
  return value && typeof value === 'object' ? value : null;
252
747
  }
748
+ function readWorkPlan(source) {
749
+ const value = source.metadata.value;
750
+ return value && typeof value === 'object' ? value : null;
751
+ }
253
752
  function titleForArtifact(kind, value) {
254
753
  if (kind === 'state')
255
754
  return `Planning: ${value.goal || 'Current plan'}`;
256
755
  if (kind === 'decision')
257
756
  return `Decision: ${value.title}`;
757
+ if (kind === 'work-plan')
758
+ return 'Project Work Plan';
258
759
  return 'Project Language';
259
760
  }