crewly 1.4.82 → 1.5.0

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 (189) hide show
  1. package/config/domain-sops/EXAMPLE.sop.md +21 -0
  2. package/config/overlays/can-decide.md +5 -0
  3. package/config/overlays/can-delegate.md +5 -0
  4. package/config/overlays/can-user-reply.md +5 -0
  5. package/config/overlays/can-verify.md +5 -0
  6. package/config/risk-policies/EXAMPLE.policy.md +22 -0
  7. package/config/roles/developer/fragments/role-boundary.md +30 -0
  8. package/config/roles/orchestrator/fragments/role-boundary.md +25 -0
  9. package/config/roles/orchestrator/prompt.md +40 -6
  10. package/config/roles/team-leader/fragments/role-boundary.md +22 -0
  11. package/config/skills/agent/core/get-my-tasks/execute.sh +16 -0
  12. package/config/skills/agent/core/save-working-state/execute.sh +19 -0
  13. package/config/skills/agent/core/update-user-profile/execute.sh +13 -0
  14. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts +34 -0
  15. package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
  16. package/dist/backend/backend/src/controllers/chat/chat.controller.js +107 -0
  17. package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
  18. package/dist/backend/backend/src/controllers/chat/chat.routes.d.ts.map +1 -1
  19. package/dist/backend/backend/src/controllers/chat/chat.routes.js +5 -1
  20. package/dist/backend/backend/src/controllers/chat/chat.routes.js.map +1 -1
  21. package/dist/backend/backend/src/controllers/chat/index.d.ts +1 -1
  22. package/dist/backend/backend/src/controllers/chat/index.d.ts.map +1 -1
  23. package/dist/backend/backend/src/controllers/chat/index.js +1 -1
  24. package/dist/backend/backend/src/controllers/chat/index.js.map +1 -1
  25. package/dist/backend/backend/src/controllers/memory/index.d.ts +1 -1
  26. package/dist/backend/backend/src/controllers/memory/index.d.ts.map +1 -1
  27. package/dist/backend/backend/src/controllers/memory/index.js +1 -1
  28. package/dist/backend/backend/src/controllers/memory/index.js.map +1 -1
  29. package/dist/backend/backend/src/controllers/memory/memory.controller.d.ts +35 -0
  30. package/dist/backend/backend/src/controllers/memory/memory.controller.d.ts.map +1 -1
  31. package/dist/backend/backend/src/controllers/memory/memory.controller.js +61 -1
  32. package/dist/backend/backend/src/controllers/memory/memory.controller.js.map +1 -1
  33. package/dist/backend/backend/src/controllers/memory/memory.routes.d.ts +2 -0
  34. package/dist/backend/backend/src/controllers/memory/memory.routes.d.ts.map +1 -1
  35. package/dist/backend/backend/src/controllers/memory/memory.routes.js +5 -1
  36. package/dist/backend/backend/src/controllers/memory/memory.routes.js.map +1 -1
  37. package/dist/backend/backend/src/controllers/system/cron-task.controller.d.ts +1 -0
  38. package/dist/backend/backend/src/controllers/system/cron-task.controller.d.ts.map +1 -1
  39. package/dist/backend/backend/src/controllers/system/cron-task.controller.js +12 -6
  40. package/dist/backend/backend/src/controllers/system/cron-task.controller.js.map +1 -1
  41. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +24 -0
  42. package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
  43. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +107 -0
  44. package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
  45. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  46. package/dist/backend/backend/src/controllers/team/team.controller.js +49 -0
  47. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  48. package/dist/backend/backend/src/index.d.ts.map +1 -1
  49. package/dist/backend/backend/src/index.js +46 -42
  50. package/dist/backend/backend/src/index.js.map +1 -1
  51. package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -1
  52. package/dist/backend/backend/src/routes/modules/task-management.routes.js +5 -0
  53. package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -1
  54. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +24 -0
  55. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  56. package/dist/backend/backend/src/services/agent/agent-registration.service.js +104 -2
  57. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  58. package/dist/backend/backend/src/services/ai/prompt-modules/capability-overlay.module.d.ts +33 -0
  59. package/dist/backend/backend/src/services/ai/prompt-modules/capability-overlay.module.d.ts.map +1 -0
  60. package/dist/backend/backend/src/services/ai/prompt-modules/capability-overlay.module.js +70 -0
  61. package/dist/backend/backend/src/services/ai/prompt-modules/capability-overlay.module.js.map +1 -0
  62. package/dist/backend/backend/src/services/ai/prompt-modules/domain-sop.module.d.ts +35 -0
  63. package/dist/backend/backend/src/services/ai/prompt-modules/domain-sop.module.d.ts.map +1 -0
  64. package/dist/backend/backend/src/services/ai/prompt-modules/domain-sop.module.js +50 -0
  65. package/dist/backend/backend/src/services/ai/prompt-modules/domain-sop.module.js.map +1 -0
  66. package/dist/backend/backend/src/services/ai/prompt-modules/index.d.ts +1 -0
  67. package/dist/backend/backend/src/services/ai/prompt-modules/index.d.ts.map +1 -1
  68. package/dist/backend/backend/src/services/ai/prompt-modules/index.js +1 -0
  69. package/dist/backend/backend/src/services/ai/prompt-modules/index.js.map +1 -1
  70. package/dist/backend/backend/src/services/ai/prompt-modules/markdown-file-module.d.ts +46 -0
  71. package/dist/backend/backend/src/services/ai/prompt-modules/markdown-file-module.d.ts.map +1 -0
  72. package/dist/backend/backend/src/services/ai/prompt-modules/markdown-file-module.js +44 -0
  73. package/dist/backend/backend/src/services/ai/prompt-modules/markdown-file-module.js.map +1 -0
  74. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts.map +1 -1
  75. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.js +13 -3
  76. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.js.map +1 -1
  77. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +22 -0
  78. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +1 -1
  79. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.js +2 -11
  80. package/dist/backend/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +1 -1
  81. package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.d.ts.map +1 -1
  82. package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js +10 -2
  83. package/dist/backend/backend/src/services/ai/prompt-modules/recovery.module.js.map +1 -1
  84. package/dist/backend/backend/src/services/ai/prompt-modules/risk-policy.module.d.ts +35 -0
  85. package/dist/backend/backend/src/services/ai/prompt-modules/risk-policy.module.d.ts.map +1 -0
  86. package/dist/backend/backend/src/services/ai/prompt-modules/risk-policy.module.js +50 -0
  87. package/dist/backend/backend/src/services/ai/prompt-modules/risk-policy.module.js.map +1 -0
  88. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts +67 -0
  89. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts.map +1 -0
  90. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js +172 -0
  91. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js.map +1 -0
  92. package/dist/backend/backend/src/services/ai/prompt-modules/user-profile-reference.module.d.ts +5 -1
  93. package/dist/backend/backend/src/services/ai/prompt-modules/user-profile-reference.module.d.ts.map +1 -1
  94. package/dist/backend/backend/src/services/ai/prompt-modules/user-profile-reference.module.js +18 -2
  95. package/dist/backend/backend/src/services/ai/prompt-modules/user-profile-reference.module.js.map +1 -1
  96. package/dist/backend/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -1
  97. package/dist/backend/backend/src/services/cloud/cloud-client.service.js +9 -2
  98. package/dist/backend/backend/src/services/cloud/cloud-client.service.js.map +1 -1
  99. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts +11 -0
  100. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts.map +1 -1
  101. package/dist/backend/backend/src/services/cloud/relay-client.service.js +41 -5
  102. package/dist/backend/backend/src/services/cloud/relay-client.service.js.map +1 -1
  103. package/dist/backend/backend/src/services/memory/agent-memory.service.d.ts +22 -0
  104. package/dist/backend/backend/src/services/memory/agent-memory.service.d.ts.map +1 -1
  105. package/dist/backend/backend/src/services/memory/agent-memory.service.js +103 -6
  106. package/dist/backend/backend/src/services/memory/agent-memory.service.js.map +1 -1
  107. package/dist/backend/backend/src/services/memory/index.d.ts +2 -1
  108. package/dist/backend/backend/src/services/memory/index.d.ts.map +1 -1
  109. package/dist/backend/backend/src/services/memory/index.js +1 -0
  110. package/dist/backend/backend/src/services/memory/index.js.map +1 -1
  111. package/dist/backend/backend/src/services/memory/memory.service.d.ts +43 -0
  112. package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
  113. package/dist/backend/backend/src/services/memory/memory.service.js +96 -0
  114. package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
  115. package/dist/backend/backend/src/services/memory/user-profile.service.d.ts +77 -0
  116. package/dist/backend/backend/src/services/memory/user-profile.service.d.ts.map +1 -0
  117. package/dist/backend/backend/src/services/memory/user-profile.service.js +171 -0
  118. package/dist/backend/backend/src/services/memory/user-profile.service.js.map +1 -0
  119. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts +8 -3
  120. package/dist/backend/backend/src/services/messaging/queue-processor.service.d.ts.map +1 -1
  121. package/dist/backend/backend/src/services/messaging/queue-processor.service.js +41 -16
  122. package/dist/backend/backend/src/services/messaging/queue-processor.service.js.map +1 -1
  123. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.d.ts +144 -1
  124. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.d.ts.map +1 -1
  125. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.js +259 -2
  126. package/dist/backend/backend/src/services/messaging/thread-status-queue.service.js.map +1 -1
  127. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +58 -2
  128. package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -1
  129. package/dist/backend/backend/src/services/project/task-tracking.service.js +189 -1
  130. package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -1
  131. package/dist/backend/backend/src/services/workflow/cron-task.service.d.ts.map +1 -1
  132. package/dist/backend/backend/src/services/workflow/cron-task.service.js +12 -0
  133. package/dist/backend/backend/src/services/workflow/cron-task.service.js.map +1 -1
  134. package/dist/backend/backend/src/types/event-bus.types.d.ts +1 -1
  135. package/dist/backend/backend/src/types/event-bus.types.d.ts.map +1 -1
  136. package/dist/backend/backend/src/types/event-bus.types.js +14 -0
  137. package/dist/backend/backend/src/types/event-bus.types.js.map +1 -1
  138. package/dist/backend/backend/src/types/index.d.ts +12 -0
  139. package/dist/backend/backend/src/types/index.d.ts.map +1 -1
  140. package/dist/backend/backend/src/types/index.js.map +1 -1
  141. package/dist/backend/backend/src/types/memory.types.d.ts +53 -0
  142. package/dist/backend/backend/src/types/memory.types.d.ts.map +1 -1
  143. package/dist/backend/backend/src/types/memory.types.js.map +1 -1
  144. package/dist/backend/backend/src/types/task-tracking.types.d.ts +28 -1
  145. package/dist/backend/backend/src/types/task-tracking.types.d.ts.map +1 -1
  146. package/dist/backend/backend/src/types/task-tracking.types.js.map +1 -1
  147. package/dist/backend/backend/src/types/thread-status.types.d.ts +4 -0
  148. package/dist/backend/backend/src/types/thread-status.types.d.ts.map +1 -1
  149. package/dist/backend/backend/src/types/thread-status.types.js +4 -1
  150. package/dist/backend/backend/src/types/thread-status.types.js.map +1 -1
  151. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts +157 -0
  152. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.d.ts.map +1 -0
  153. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js +37 -0
  154. package/dist/cli/backend/src/services/ai/prompt-modules/prompt-module.interface.js.map +1 -0
  155. package/dist/cli/backend/src/services/memory/agent-memory.service.d.ts +22 -0
  156. package/dist/cli/backend/src/services/memory/agent-memory.service.d.ts.map +1 -1
  157. package/dist/cli/backend/src/services/memory/agent-memory.service.js +103 -6
  158. package/dist/cli/backend/src/services/memory/agent-memory.service.js.map +1 -1
  159. package/dist/cli/backend/src/services/memory/goal-tracking.service.d.ts +239 -0
  160. package/dist/cli/backend/src/services/memory/goal-tracking.service.d.ts.map +1 -0
  161. package/dist/cli/backend/src/services/memory/goal-tracking.service.js +353 -0
  162. package/dist/cli/backend/src/services/memory/goal-tracking.service.js.map +1 -0
  163. package/dist/cli/backend/src/services/memory/memory.service.d.ts +43 -0
  164. package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
  165. package/dist/cli/backend/src/services/memory/memory.service.js +96 -0
  166. package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
  167. package/dist/cli/backend/src/services/project/task-tracking.service.d.ts +171 -0
  168. package/dist/cli/backend/src/services/project/task-tracking.service.d.ts.map +1 -0
  169. package/dist/cli/backend/src/services/project/task-tracking.service.js +725 -0
  170. package/dist/cli/backend/src/services/project/task-tracking.service.js.map +1 -0
  171. package/dist/cli/backend/src/types/index.d.ts +12 -0
  172. package/dist/cli/backend/src/types/index.d.ts.map +1 -1
  173. package/dist/cli/backend/src/types/index.js.map +1 -1
  174. package/dist/cli/backend/src/types/memory.types.d.ts +53 -0
  175. package/dist/cli/backend/src/types/memory.types.d.ts.map +1 -1
  176. package/dist/cli/backend/src/types/memory.types.js.map +1 -1
  177. package/dist/cli/backend/src/types/task-tracking.types.d.ts +206 -0
  178. package/dist/cli/backend/src/types/task-tracking.types.d.ts.map +1 -0
  179. package/dist/cli/backend/src/types/task-tracking.types.js +5 -0
  180. package/dist/cli/backend/src/types/task-tracking.types.js.map +1 -0
  181. package/dist/cli/backend/src/types/thread-status.types.d.ts +4 -0
  182. package/dist/cli/backend/src/types/thread-status.types.d.ts.map +1 -1
  183. package/dist/cli/backend/src/types/thread-status.types.js +4 -1
  184. package/dist/cli/backend/src/types/thread-status.types.js.map +1 -1
  185. package/frontend/dist/assets/index-512efc8e.js +4921 -0
  186. package/frontend/dist/assets/{index-975ccc95.css → index-dc6ac165.css} +1 -1
  187. package/frontend/dist/index.html +2 -2
  188. package/package.json +1 -1
  189. package/frontend/dist/assets/index-d28d1135.js +0 -5215
@@ -0,0 +1,353 @@
1
+ /**
2
+ * Goal Tracking Service
3
+ *
4
+ * Manages project-level goal files, current team focus, and a decisions log
5
+ * with retrospective outcomes. All files are stored as Markdown under
6
+ * `{projectPath}/.crewly/goals/`.
7
+ *
8
+ * Files managed:
9
+ * - `goals.md` — Append-only log of user-stated goals
10
+ * - `current_focus.md` — Overwritten each time the team focus changes
11
+ * - `decisions_log.md` — Append-only decisions with mutable outcome sections
12
+ *
13
+ * @module services/memory/goal-tracking.service
14
+ */
15
+ import * as fs from 'fs/promises';
16
+ import * as path from 'path';
17
+ import { ensureDir, atomicWriteFile } from '../../utils/file-io.utils.js';
18
+ import { MEMORY_CONSTANTS } from '../../constants.js';
19
+ import { LoggerService } from '../core/logger.service.js';
20
+ /**
21
+ * Service for tracking project goals, team focus, and architectural decisions.
22
+ *
23
+ * Follows the singleton pattern for consistent state management across
24
+ * the backend. Uses atomic writes for full-file overwrites and plain
25
+ * `fs.appendFile` for append-only logs (goals, decisions) where partial
26
+ * writes are acceptable.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * const goalService = GoalTrackingService.getInstance();
31
+ *
32
+ * // Set a project goal
33
+ * await goalService.setGoal('/path/to/project', 'Ship v2.0 by March 15th', 'user');
34
+ *
35
+ * // Update team focus
36
+ * await goalService.updateFocus('/path/to/project', 'Completing auth module');
37
+ *
38
+ * // Log a decision
39
+ * const decId = await goalService.logDecision('/path/to/project', {
40
+ * title: 'Use PostgreSQL over MongoDB',
41
+ * decision: 'PostgreSQL for primary data store',
42
+ * rationale: 'Relational data model fits our schema better',
43
+ * decidedBy: 'orchestrator',
44
+ * alternatives: ['MongoDB', 'DynamoDB'],
45
+ * });
46
+ *
47
+ * // Later, record the outcome
48
+ * await goalService.updateDecisionOutcome(
49
+ * '/path/to/project',
50
+ * decId,
51
+ * 'Successful - query performance is excellent',
52
+ * 'Invest time in schema design upfront to avoid migrations',
53
+ * );
54
+ * ```
55
+ */
56
+ export class GoalTrackingService {
57
+ static instance = null;
58
+ /** Monotonic counter to ensure unique decision IDs even within the same millisecond */
59
+ decisionCounter = 0;
60
+ logger = LoggerService.getInstance().createComponentLogger('GoalTrackingService');
61
+ /**
62
+ * Creates a new GoalTrackingService instance.
63
+ * Use {@link getInstance} for the singleton.
64
+ */
65
+ constructor() {
66
+ // No initialization needed — all paths are derived from projectPath at call time
67
+ }
68
+ /**
69
+ * Gets the singleton instance of GoalTrackingService.
70
+ *
71
+ * @returns The singleton GoalTrackingService instance
72
+ */
73
+ static getInstance() {
74
+ if (!GoalTrackingService.instance) {
75
+ GoalTrackingService.instance = new GoalTrackingService();
76
+ }
77
+ return GoalTrackingService.instance;
78
+ }
79
+ /**
80
+ * Clears the singleton instance.
81
+ * Intended for test isolation only — never call in production.
82
+ */
83
+ static clearInstance() {
84
+ GoalTrackingService.instance = null;
85
+ }
86
+ // ========================= HELPERS =========================
87
+ /**
88
+ * Returns the absolute path to the goals directory for a project.
89
+ *
90
+ * @param projectPath - Absolute path to the project root
91
+ * @returns Absolute path to `{projectPath}/.crewly/goals`
92
+ */
93
+ getGoalsDir(projectPath) {
94
+ return path.join(projectPath, '.crewly', MEMORY_CONSTANTS.PATHS.GOALS_DIR);
95
+ }
96
+ /**
97
+ * Safely reads a file and returns its content, or `null` if the file
98
+ * does not exist.
99
+ *
100
+ * Permission errors and other unexpected failures are re-thrown.
101
+ *
102
+ * @param filePath - Absolute path to the file
103
+ * @returns File content as a UTF-8 string, or `null` if not found
104
+ */
105
+ async safeReadFile(filePath) {
106
+ try {
107
+ return await fs.readFile(filePath, 'utf-8');
108
+ }
109
+ catch (error) {
110
+ if (error.code === 'ENOENT') {
111
+ return null;
112
+ }
113
+ throw error;
114
+ }
115
+ }
116
+ // ========================= PUBLIC INTERFACE =========================
117
+ /**
118
+ * Appends a new goal entry to `goals.md`.
119
+ *
120
+ * If the file does not yet exist it is created with a Markdown header
121
+ * before the first entry is appended.
122
+ *
123
+ * @param projectPath - Absolute path to the project root
124
+ * @param goal - The goal text to record
125
+ * @param setBy - Who set the goal (defaults to `'user'`)
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * await goalService.setGoal('/projects/phoenix', 'Achieve 80% test coverage', 'user');
130
+ * ```
131
+ */
132
+ async setGoal(projectPath, goal, setBy = 'user') {
133
+ const goalsDir = this.getGoalsDir(projectPath);
134
+ await ensureDir(goalsDir);
135
+ const goalsFile = path.join(goalsDir, MEMORY_CONSTANTS.PATHS.GOALS_FILE);
136
+ const existing = await this.safeReadFile(goalsFile);
137
+ const timestamp = new Date().toISOString();
138
+ const entry = `\n### [${timestamp}] Set by ${setBy}\n${goal}\n`;
139
+ if (existing === null) {
140
+ const header = `# Project Goals\n\n`;
141
+ await fs.writeFile(goalsFile, header + entry, 'utf-8');
142
+ this.logger.debug('Created goals file with first entry', { projectPath, setBy });
143
+ }
144
+ else {
145
+ await fs.appendFile(goalsFile, entry, 'utf-8');
146
+ this.logger.debug('Appended goal entry', { projectPath, setBy });
147
+ }
148
+ }
149
+ /**
150
+ * Reads and returns the full contents of `goals.md`.
151
+ *
152
+ * @param projectPath - Absolute path to the project root
153
+ * @returns The goals file content, or `null` if the file does not exist
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const goals = await goalService.getGoals('/projects/phoenix');
158
+ * if (goals) {
159
+ * console.log(goals);
160
+ * }
161
+ * ```
162
+ */
163
+ async getGoals(projectPath) {
164
+ const goalsFile = path.join(this.getGoalsDir(projectPath), MEMORY_CONSTANTS.PATHS.GOALS_FILE);
165
+ return this.safeReadFile(goalsFile);
166
+ }
167
+ /**
168
+ * Overwrites `current_focus.md` with the new focus description.
169
+ *
170
+ * Uses {@link atomicWriteFile} to ensure the file is never left in a
171
+ * partial-write state.
172
+ *
173
+ * @param projectPath - Absolute path to the project root
174
+ * @param focus - The new focus description
175
+ * @param updatedBy - Who updated the focus (defaults to `'orchestrator'`)
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * await goalService.updateFocus(
180
+ * '/projects/phoenix',
181
+ * 'Completing the authentication module and writing integration tests',
182
+ * 'orchestrator',
183
+ * );
184
+ * ```
185
+ */
186
+ async updateFocus(projectPath, focus, updatedBy = 'orchestrator') {
187
+ const goalsDir = this.getGoalsDir(projectPath);
188
+ await ensureDir(goalsDir);
189
+ const focusFile = path.join(goalsDir, MEMORY_CONSTANTS.PATHS.FOCUS_FILE);
190
+ const timestamp = new Date().toISOString();
191
+ const content = `# Current Focus\n` +
192
+ `\n` +
193
+ `**Updated:** ${timestamp}\n` +
194
+ `**By:** ${updatedBy}\n` +
195
+ `\n` +
196
+ `${focus}\n`;
197
+ await atomicWriteFile(focusFile, content);
198
+ this.logger.debug('Updated current focus', { projectPath, updatedBy });
199
+ }
200
+ /**
201
+ * Reads and returns the full contents of `current_focus.md`.
202
+ *
203
+ * @param projectPath - Absolute path to the project root
204
+ * @returns The current focus file content, or `null` if the file does not exist
205
+ *
206
+ * @example
207
+ * ```typescript
208
+ * const focus = await goalService.getCurrentFocus('/projects/phoenix');
209
+ * ```
210
+ */
211
+ async getCurrentFocus(projectPath) {
212
+ const focusFile = path.join(this.getGoalsDir(projectPath), MEMORY_CONSTANTS.PATHS.FOCUS_FILE);
213
+ return this.safeReadFile(focusFile);
214
+ }
215
+ /**
216
+ * Appends a new decision entry to `decisions_log.md` and returns a
217
+ * unique decision ID.
218
+ *
219
+ * If the file does not yet exist it is created with a Markdown header
220
+ * before the first entry is appended.
221
+ *
222
+ * The outcome field is initially set to `_pending_` and can be updated
223
+ * later via {@link updateDecisionOutcome}.
224
+ *
225
+ * @param projectPath - Absolute path to the project root
226
+ * @param decision - Decision parameters (title, decision, rationale, etc.)
227
+ * @returns The generated decision ID (format: `dec-{timestamp}-{counter}`)
228
+ *
229
+ * @throws {Error} If the file system write fails
230
+ *
231
+ * @example
232
+ * ```typescript
233
+ * const decisionId = await goalService.logDecision('/projects/phoenix', {
234
+ * title: 'Use Redis for caching',
235
+ * decision: 'Redis over Memcached',
236
+ * rationale: 'Better data structure support and persistence options',
237
+ * decidedBy: 'orchestrator',
238
+ * alternatives: ['Memcached', 'In-memory Map'],
239
+ * });
240
+ * // decisionId => 'dec-1707500000000-0'
241
+ * ```
242
+ */
243
+ async logDecision(projectPath, decision) {
244
+ const goalsDir = this.getGoalsDir(projectPath);
245
+ await ensureDir(goalsDir);
246
+ const decisionsFile = path.join(goalsDir, MEMORY_CONSTANTS.PATHS.DECISIONS_LOG);
247
+ const existing = await this.safeReadFile(decisionsFile);
248
+ const timestamp = new Date().toISOString();
249
+ const decisionId = `dec-${Date.now()}-${this.decisionCounter++}`;
250
+ const alternativesText = decision.alternatives?.join(', ') || 'None recorded';
251
+ const entry = `\n## [${decisionId}] ${decision.title}\n` +
252
+ `**Date:** ${timestamp}\n` +
253
+ `**By:** ${decision.decidedBy}\n` +
254
+ `**Decision:** ${decision.decision}\n` +
255
+ `**Rationale:** ${decision.rationale}\n` +
256
+ `**Alternatives:** ${alternativesText}\n` +
257
+ `**Outcome:** _pending_\n` +
258
+ `\n---\n`;
259
+ if (existing === null) {
260
+ const header = `# Decisions Log\n\n`;
261
+ await fs.writeFile(decisionsFile, header + entry, 'utf-8');
262
+ this.logger.debug('Created decisions log with first entry', { projectPath, decisionId });
263
+ }
264
+ else {
265
+ await fs.appendFile(decisionsFile, entry, 'utf-8');
266
+ this.logger.debug('Appended decision entry', { projectPath, decisionId });
267
+ }
268
+ return decisionId;
269
+ }
270
+ /**
271
+ * Updates the outcome of a previously logged decision.
272
+ *
273
+ * Reads `decisions_log.md`, locates the section matching the given
274
+ * `decisionId`, replaces the `**Outcome:** _pending_` line with the
275
+ * actual outcome (plus optional learnings and a timestamp), and writes
276
+ * the file back atomically.
277
+ *
278
+ * If the decision ID is not found or the file does not exist, a warning
279
+ * is logged and the method returns without throwing.
280
+ *
281
+ * @param projectPath - Absolute path to the project root
282
+ * @param decisionId - The decision ID returned by {@link logDecision}
283
+ * @param outcome - Description of the actual outcome
284
+ * @param learnings - Optional lessons learned from this decision
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * await goalService.updateDecisionOutcome(
289
+ * '/projects/phoenix',
290
+ * 'dec-1707500000000',
291
+ * 'Successful - Redis reduced API latency by 40%',
292
+ * 'Set explicit TTLs on all cache keys to prevent stale data',
293
+ * );
294
+ * ```
295
+ */
296
+ async updateDecisionOutcome(projectPath, decisionId, outcome, learnings) {
297
+ const decisionsFile = path.join(this.getGoalsDir(projectPath), MEMORY_CONSTANTS.PATHS.DECISIONS_LOG);
298
+ const content = await this.safeReadFile(decisionsFile);
299
+ if (content === null) {
300
+ this.logger.warn('Decisions log not found, cannot update outcome', { projectPath, decisionId });
301
+ return;
302
+ }
303
+ // Verify the decision ID exists in the file
304
+ if (!content.includes(`[${decisionId}]`)) {
305
+ this.logger.warn('Decision ID not found in decisions log', { projectPath, decisionId });
306
+ return;
307
+ }
308
+ const timestamp = new Date().toISOString();
309
+ const learningsText = learnings || 'None recorded';
310
+ const replacement = `**Outcome:** ${outcome}\n` +
311
+ `**Learnings:** ${learningsText}\n` +
312
+ `**Recorded:** ${timestamp}`;
313
+ // Replace the first occurrence of _pending_ that belongs to this decision.
314
+ // We find the decision section header then replace the pending outcome within it.
315
+ const sectionMarker = `[${decisionId}]`;
316
+ const sectionStart = content.indexOf(sectionMarker);
317
+ if (sectionStart === -1) {
318
+ this.logger.warn('Decision section not found', { projectPath, decisionId });
319
+ return;
320
+ }
321
+ // Find the **Outcome:** _pending_ line within this decision's section
322
+ const pendingPattern = '**Outcome:** _pending_';
323
+ const pendingIndex = content.indexOf(pendingPattern, sectionStart);
324
+ if (pendingIndex === -1) {
325
+ this.logger.warn('Decision outcome already recorded or not in pending state', { projectPath, decisionId });
326
+ return;
327
+ }
328
+ const updatedContent = content.substring(0, pendingIndex) +
329
+ replacement +
330
+ content.substring(pendingIndex + pendingPattern.length);
331
+ await atomicWriteFile(decisionsFile, updatedContent);
332
+ this.logger.debug('Updated decision outcome', { projectPath, decisionId });
333
+ }
334
+ /**
335
+ * Reads and returns the full contents of `decisions_log.md`.
336
+ *
337
+ * @param projectPath - Absolute path to the project root
338
+ * @returns The decisions log content, or `null` if the file does not exist
339
+ *
340
+ * @example
341
+ * ```typescript
342
+ * const log = await goalService.getDecisionsLog('/projects/phoenix');
343
+ * if (log) {
344
+ * console.log(log);
345
+ * }
346
+ * ```
347
+ */
348
+ async getDecisionsLog(projectPath) {
349
+ const decisionsFile = path.join(this.getGoalsDir(projectPath), MEMORY_CONSTANTS.PATHS.DECISIONS_LOG);
350
+ return this.safeReadFile(decisionsFile);
351
+ }
352
+ }
353
+ //# sourceMappingURL=goal-tracking.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-tracking.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/memory/goal-tracking.service.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,7 @@ import { IAgentMemoryService } from './agent-memory.service.js';
10
10
  import { IProjectMemoryService } from './project-memory.service.js';
11
11
  import type { KnowledgeDocumentSummary } from '../../types/knowledge.types.js';
12
12
  import type { PatternCategory, GotchaSeverity } from '../../types/memory.types.js';
13
+ import type { TaskTrackingService } from '../project/task-tracking.service.js';
13
14
  /**
14
15
  * Categories for the unified remember operation
15
16
  */
@@ -58,6 +59,16 @@ export interface RememberParams {
58
59
  relationshipType?: 'depends-on' | 'uses' | 'extends' | 'implements' | 'calls' | 'imported-by';
59
60
  /** Target component for relationships */
60
61
  targetComponent?: string;
62
+ /** Task ID where this knowledge was learned */
63
+ sourceTaskId?: string;
64
+ /** Objective/goal ID this knowledge relates to */
65
+ sourceObjectiveId?: string;
66
+ /** Outcome of the task where this was learned */
67
+ sourceOutcome?: string;
68
+ /** What contexts/domains this knowledge applies to */
69
+ appliesTo?: string[];
70
+ /** ID of entry being superseded by this one */
71
+ supersedes?: string;
61
72
  };
62
73
  }
63
74
  /**
@@ -87,6 +98,17 @@ export interface RecallResult {
87
98
  combined: string;
88
99
  /** Matching knowledge documents (optional, from knowledge base search) */
89
100
  knowledgeDocuments?: KnowledgeDocumentSummary[];
101
+ /** Current project goals (if projectPath provided) */
102
+ activeGoals?: string[];
103
+ /** Current team focus (if projectPath provided) */
104
+ currentFocus?: string;
105
+ /** Active tasks for this agent */
106
+ activeTasks?: Array<{
107
+ id: string;
108
+ name: string;
109
+ status: string;
110
+ hasWorkingNotes: boolean;
111
+ }>;
90
112
  }
91
113
  /**
92
114
  * Parameters for recording a learning
@@ -148,6 +170,8 @@ export declare class MemoryService implements IMemoryService {
148
170
  private static instance;
149
171
  private readonly agentMemory;
150
172
  private readonly projectMemory;
173
+ /** Shared or lazily-cached TaskTrackingService instance for operational context enrichment */
174
+ private taskTrackingServiceRef;
151
175
  private readonly logger;
152
176
  private embeddingProvider;
153
177
  private embeddingProviderInitialized;
@@ -155,6 +179,20 @@ export declare class MemoryService implements IMemoryService {
155
179
  * Creates a new MemoryService instance
156
180
  */
157
181
  private constructor();
182
+ /**
183
+ * Set the shared TaskTrackingService instance to avoid creating
184
+ * disposable instances on every recall. Call during app startup.
185
+ *
186
+ * @param service - The application's shared TaskTrackingService
187
+ */
188
+ setTaskTrackingService(service: TaskTrackingService): void;
189
+ /**
190
+ * Get or lazily create a TaskTrackingService.
191
+ * Prefers the shared instance set via setTaskTrackingService().
192
+ *
193
+ * @returns TaskTrackingService instance
194
+ */
195
+ private getTaskTrackingService;
158
196
  /**
159
197
  * Lazily initializes the embedding provider on first use.
160
198
  * Returns null if no embedding API key is configured.
@@ -298,6 +336,11 @@ export declare class MemoryService implements IMemoryService {
298
336
  * ```
299
337
  */
300
338
  recall(params: RecallParams): Promise<RecallResult>;
339
+ /**
340
+ * Enrich recall result with operational context: goals, focus, active tasks.
341
+ * All lookups are non-fatal — missing data is silently skipped.
342
+ */
343
+ private enrichWithOperationalContext;
301
344
  /**
302
345
  * Searches knowledge documents across global and project scopes.
303
346
  *
@@ -1 +1 @@
1
- {"version":3,"file":"memory.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/memory/memory.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/memory/memory.service.ts"],"names":[],"mappings":"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"}
@@ -46,6 +46,8 @@ export class MemoryService {
46
46
  static instance = null;
47
47
  agentMemory;
48
48
  projectMemory;
49
+ /** Shared or lazily-cached TaskTrackingService instance for operational context enrichment */
50
+ taskTrackingServiceRef = null;
49
51
  logger = LoggerService.getInstance().createComponentLogger('MemoryService');
50
52
  embeddingProvider = null;
51
53
  embeddingProviderInitialized = false;
@@ -56,6 +58,30 @@ export class MemoryService {
56
58
  this.agentMemory = AgentMemoryService.getInstance();
57
59
  this.projectMemory = ProjectMemoryService.getInstance();
58
60
  }
61
+ /**
62
+ * Set the shared TaskTrackingService instance to avoid creating
63
+ * disposable instances on every recall. Call during app startup.
64
+ *
65
+ * @param service - The application's shared TaskTrackingService
66
+ */
67
+ setTaskTrackingService(service) {
68
+ this.taskTrackingServiceRef = service;
69
+ }
70
+ /**
71
+ * Get or lazily create a TaskTrackingService.
72
+ * Prefers the shared instance set via setTaskTrackingService().
73
+ *
74
+ * @returns TaskTrackingService instance
75
+ */
76
+ async getTaskTrackingService() {
77
+ if (this.taskTrackingServiceRef) {
78
+ return this.taskTrackingServiceRef;
79
+ }
80
+ // Lazy fallback: create and cache one instance
81
+ const { TaskTrackingService: TTS } = await import('../project/task-tracking.service.js');
82
+ this.taskTrackingServiceRef = new TTS();
83
+ return this.taskTrackingServiceRef;
84
+ }
59
85
  /**
60
86
  * Lazily initializes the embedding provider on first use.
61
87
  * Returns null if no embedding API key is configured.
@@ -369,6 +395,11 @@ export class MemoryService {
369
395
  content: params.content,
370
396
  learnedFrom: params.metadata?.taskId,
371
397
  confidence: 0.5,
398
+ // v2: Task-linked provenance
399
+ sourceTaskId: params.metadata?.sourceTaskId || params.metadata?.taskId,
400
+ sourceObjectiveId: params.metadata?.sourceObjectiveId,
401
+ sourceOutcome: params.metadata?.sourceOutcome,
402
+ appliesTo: params.metadata?.appliesTo,
372
403
  });
373
404
  case 'preference':
374
405
  await this.agentMemory.updatePreferences(params.agentId, this.parsePreference(params.content));
@@ -393,6 +424,9 @@ export class MemoryService {
393
424
  example: params.metadata?.example,
394
425
  files: params.metadata?.files,
395
426
  discoveredBy: params.agentId,
427
+ // v2: provenance
428
+ sourceTaskId: params.metadata?.sourceTaskId || params.metadata?.taskId,
429
+ sourceOutcome: params.metadata?.sourceOutcome,
396
430
  });
397
431
  case 'decision':
398
432
  return this.projectMemory.addDecision(params.projectPath, {
@@ -410,6 +444,9 @@ export class MemoryService {
410
444
  solution: params.metadata?.solution || '',
411
445
  severity: params.metadata?.severity || 'medium',
412
446
  discoveredBy: params.agentId,
447
+ // v2: provenance
448
+ sourceTaskId: params.metadata?.sourceTaskId || params.metadata?.taskId,
449
+ sourceOutcome: params.metadata?.sourceOutcome,
413
450
  });
414
451
  case 'relationship':
415
452
  if (!params.metadata?.targetComponent) {
@@ -503,9 +540,68 @@ export class MemoryService {
503
540
  }));
504
541
  }
505
542
  await Promise.all(promises);
543
+ // v2: Enrich with operational context (goals, focus, active tasks)
544
+ await this.enrichWithOperationalContext(result, params);
506
545
  result.combined = this.combineMemories(result);
546
+ // v2: Append operational context to combined text
547
+ if (result.activeGoals?.length || result.currentFocus || result.activeTasks?.length) {
548
+ const opLines = ['\n### Operational Context'];
549
+ if (result.currentFocus)
550
+ opLines.push(`**Current Focus:** ${result.currentFocus}`);
551
+ if (result.activeGoals?.length)
552
+ opLines.push(`**Goals:** ${result.activeGoals.join('; ')}`);
553
+ if (result.activeTasks?.length) {
554
+ opLines.push('**Your Active Tasks:**');
555
+ for (const t of result.activeTasks) {
556
+ opLines.push(`- [${t.status}] ${t.name}${t.hasWorkingNotes ? ' (has working notes)' : ''}`);
557
+ }
558
+ }
559
+ result.combined += opLines.join('\n');
560
+ }
507
561
  return result;
508
562
  }
563
+ /**
564
+ * Enrich recall result with operational context: goals, focus, active tasks.
565
+ * All lookups are non-fatal — missing data is silently skipped.
566
+ */
567
+ async enrichWithOperationalContext(result, params) {
568
+ const opPromises = [];
569
+ if (params.projectPath) {
570
+ opPromises.push((async () => {
571
+ try {
572
+ const { GoalTrackingService } = await import('./goal-tracking.service.js');
573
+ const gts = GoalTrackingService.getInstance();
574
+ const goalsText = await gts.getGoals(params.projectPath);
575
+ if (goalsText)
576
+ result.activeGoals = [goalsText];
577
+ const focus = await gts.getCurrentFocus(params.projectPath);
578
+ if (focus)
579
+ result.currentFocus = focus;
580
+ }
581
+ catch { /* non-fatal — goal tracking may not be initialized */ }
582
+ })());
583
+ }
584
+ if (params.agentId) {
585
+ opPromises.push((async () => {
586
+ try {
587
+ const tts = await this.getTaskTrackingService();
588
+ const tasks = await tts.getTasksBySessionName(params.agentId);
589
+ const terminalStatuses = ['completed', 'verified', 'cancelled'];
590
+ const active = tasks.filter((t) => !terminalStatuses.includes(t.status));
591
+ if (active.length) {
592
+ result.activeTasks = active.map((t) => ({
593
+ id: t.id,
594
+ name: t.taskName,
595
+ status: t.status,
596
+ hasWorkingNotes: !!t.workingNotes,
597
+ }));
598
+ }
599
+ }
600
+ catch { /* non-fatal */ }
601
+ })());
602
+ }
603
+ await Promise.all(opPromises);
604
+ }
509
605
  /**
510
606
  * Searches knowledge documents across global and project scopes.
511
607
  *