pi-harness-runtime 1.1.95 → 1.1.97

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 (226) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/harness/loop-runtime.ts +3 -0
  3. package/index.ts +130 -29
  4. package/package.json +2 -1
  5. package/packages/a2a-adapter/package.json +1 -1
  6. package/packages/architecture-generator/package.json +1 -1
  7. package/packages/auth/package.json +1 -1
  8. package/packages/autonomous-refactor/package.json +1 -1
  9. package/packages/autonomous-runtime/package.json +1 -1
  10. package/packages/cache-strategy/package.json +1 -1
  11. package/packages/capability-registry/package.json +1 -1
  12. package/packages/checkpoint/package.json +1 -1
  13. package/packages/cli-plugin-sdk/package.json +1 -1
  14. package/packages/clipboard/package.json +1 -1
  15. package/packages/clipboard-plugin/package.json +1 -1
  16. package/packages/code-generation/package.json +1 -1
  17. package/packages/code-review/package.json +1 -1
  18. package/packages/codex-adapter/package.json +1 -1
  19. package/packages/config-capture/package.json +1 -1
  20. package/packages/context-compiler/package.json +1 -1
  21. package/packages/context-discovery/package.json +1 -1
  22. package/packages/context-manager/package.json +1 -1
  23. package/packages/cookie-sanitizer/package.json +1 -1
  24. package/packages/cost-optimizer/package.json +1 -1
  25. package/packages/dependency-analyzer/package.json +1 -1
  26. package/packages/django-plugin/package.json +1 -1
  27. package/packages/doc-generator/package.json +1 -1
  28. package/packages/evaluation-engine/package.json +1 -1
  29. package/packages/evaluation-runner/package.json +1 -1
  30. package/packages/event-bus/package.json +1 -1
  31. package/packages/event-store/package.json +1 -1
  32. package/packages/experience-replay/package.json +1 -1
  33. package/packages/feedback-collector/package.json +1 -1
  34. package/packages/file-copy-helper/package.json +1 -1
  35. package/packages/framework-detector/package.json +1 -1
  36. package/packages/framework-plugin-sdk/package.json +1 -1
  37. package/packages/frappe-plugin/package.json +1 -1
  38. package/packages/generic-web-plugin/package.json +1 -1
  39. package/packages/health-monitor/package.json +1 -1
  40. package/packages/intent-analyzer/package.json +1 -1
  41. package/packages/jev-judge/package.json +1 -1
  42. package/packages/knowledge-graph/package.json +1 -1
  43. package/packages/knowledge-retrieval/package.json +1 -1
  44. package/packages/laravel-plugin/package.json +1 -1
  45. package/packages/learning-engine/package.json +1 -1
  46. package/packages/mcp-adapter/package.json +1 -1
  47. package/packages/memory-engine/package.json +1 -1
  48. package/packages/milestone-manager/package.json +1 -1
  49. package/packages/model-registry/package.json +1 -1
  50. package/packages/nextjs-plugin/package.json +1 -1
  51. package/packages/notification/package.json +1 -1
  52. package/packages/observability/package.json +1 -1
  53. package/packages/okf-indexer/package.json +1 -1
  54. package/packages/performance-optimizer/package.json +1 -1
  55. package/packages/privilege-broker/package.json +1 -1
  56. package/packages/project-analyzer/package.json +1 -1
  57. package/packages/project-bootstrap/package.json +1 -1
  58. package/packages/projection-engine/package.json +1 -1
  59. package/packages/prompt-compiler/package.json +1 -1
  60. package/packages/prompt-versioning/package.json +1 -1
  61. package/packages/provider-adapter-sdk/package.json +1 -1
  62. package/packages/provider-router/package.json +1 -1
  63. package/packages/provider-selector/package.json +1 -1
  64. package/packages/providers/package.json +1 -1
  65. package/packages/qdrant-skills/dist/client.d.ts +51 -0
  66. package/packages/qdrant-skills/dist/client.d.ts.map +1 -0
  67. package/packages/qdrant-skills/dist/client.js +105 -0
  68. package/packages/qdrant-skills/dist/client.js.map +1 -0
  69. package/packages/qdrant-skills/dist/embedder.d.ts +39 -0
  70. package/packages/qdrant-skills/dist/embedder.d.ts.map +1 -0
  71. package/packages/qdrant-skills/dist/embedder.js +101 -0
  72. package/packages/qdrant-skills/dist/embedder.js.map +1 -0
  73. package/packages/qdrant-skills/dist/index.d.ts +25 -0
  74. package/packages/qdrant-skills/dist/index.d.ts.map +1 -0
  75. package/packages/qdrant-skills/dist/index.js +25 -0
  76. package/packages/qdrant-skills/dist/index.js.map +1 -0
  77. package/packages/qdrant-skills/package.json +27 -0
  78. package/packages/qdrant-skills/src/client.ts +178 -0
  79. package/packages/qdrant-skills/src/embedder.ts +137 -0
  80. package/packages/qdrant-skills/src/index.ts +42 -0
  81. package/packages/quota-manager/package.json +1 -1
  82. package/packages/rate-limiter/package.json +1 -1
  83. package/packages/react-vite-plugin/package.json +1 -1
  84. package/packages/release-manager/package.json +1 -1
  85. package/packages/requirement-compiler/package.json +1 -1
  86. package/packages/runtime/package.json +1 -1
  87. package/packages/scheduler/package.json +1 -1
  88. package/packages/scheduler-adapter/package.json +1 -1
  89. package/packages/session/package.json +1 -1
  90. package/packages/session-api/package.json +1 -1
  91. package/packages/session-export/package.json +1 -1
  92. package/packages/shared-context/package.json +1 -1
  93. package/packages/skill-mcp-client/package.json +1 -1
  94. package/packages/skill-registry/package.json +1 -1
  95. package/packages/skills/dist/index.d.ts +40 -0
  96. package/packages/skills/dist/index.d.ts.map +1 -0
  97. package/packages/skills/dist/index.js +84 -0
  98. package/packages/skills/dist/index.js.map +1 -0
  99. package/packages/skills/dist/linter.d.ts +38 -0
  100. package/packages/skills/dist/linter.d.ts.map +1 -0
  101. package/packages/skills/dist/linter.js +323 -0
  102. package/packages/skills/dist/linter.js.map +1 -0
  103. package/packages/skills/dist/loader.d.ts +74 -0
  104. package/packages/skills/dist/loader.d.ts.map +1 -0
  105. package/packages/skills/dist/loader.js +280 -0
  106. package/packages/skills/dist/loader.js.map +1 -0
  107. package/packages/skills/dist/parser.d.ts +32 -0
  108. package/packages/skills/dist/parser.d.ts.map +1 -0
  109. package/packages/skills/dist/parser.js +459 -0
  110. package/packages/skills/dist/parser.js.map +1 -0
  111. package/packages/skills/dist/scanner.d.ts +33 -0
  112. package/packages/skills/dist/scanner.d.ts.map +1 -0
  113. package/packages/skills/dist/scanner.js +257 -0
  114. package/packages/skills/dist/scanner.js.map +1 -0
  115. package/packages/skills/dist/skill-commands.d.ts +33 -0
  116. package/packages/skills/dist/skill-commands.d.ts.map +1 -0
  117. package/packages/skills/dist/skill-commands.js +239 -0
  118. package/packages/skills/dist/skill-commands.js.map +1 -0
  119. package/packages/skills/dist/skill-tool.d.ts +120 -0
  120. package/packages/skills/dist/skill-tool.d.ts.map +1 -0
  121. package/packages/skills/dist/skill-tool.js +239 -0
  122. package/packages/skills/dist/skill-tool.js.map +1 -0
  123. package/packages/skills/dist/skill-versioning.d.ts +123 -0
  124. package/packages/skills/dist/skill-versioning.d.ts.map +1 -0
  125. package/packages/skills/dist/skill-versioning.js +240 -0
  126. package/packages/skills/dist/skill-versioning.js.map +1 -0
  127. package/packages/skills/dist/types.d.ts +226 -0
  128. package/packages/skills/dist/types.d.ts.map +1 -0
  129. package/packages/skills/dist/types.js +21 -0
  130. package/packages/skills/dist/types.js.map +1 -0
  131. package/packages/skills/package.json +46 -0
  132. package/packages/skills/src/index.ts +95 -0
  133. package/packages/skills/src/linter.ts +371 -0
  134. package/packages/skills/src/loader.ts +335 -0
  135. package/packages/skills/src/parser.ts +548 -0
  136. package/packages/skills/src/scanner.ts +322 -0
  137. package/packages/skills/src/skill-commands.ts +318 -0
  138. package/packages/skills/src/skill-tool.ts +324 -0
  139. package/packages/skills/src/skill-versioning.ts +345 -0
  140. package/packages/skills/src/types.ts +259 -0
  141. package/packages/skills/test/init-skills.test.ts +118 -0
  142. package/packages/sprint-planner/package.json +1 -1
  143. package/packages/subscription-engine/package.json +1 -1
  144. package/packages/task-compiler/package.json +1 -1
  145. package/packages/tencentdb-memory/package.json +1 -1
  146. package/packages/tencentdb-sync/package.json +1 -1
  147. package/packages/test-data-generator/package.json +1 -1
  148. package/packages/test-generator/package.json +1 -1
  149. package/packages/todo-bd-sync/package.json +1 -1
  150. package/packages/token-estimation/package.json +1 -1
  151. package/packages/token-optimizer/package.json +1 -1
  152. package/packages/trajectory/dist/src/curator.d.ts +189 -0
  153. package/packages/trajectory/dist/src/curator.d.ts.map +1 -0
  154. package/packages/trajectory/dist/src/curator.js +340 -0
  155. package/packages/trajectory/dist/src/curator.js.map +1 -0
  156. package/packages/trajectory/dist/src/journey-renderer.d.ts +53 -0
  157. package/packages/trajectory/dist/src/journey-renderer.d.ts.map +1 -0
  158. package/packages/trajectory/dist/src/journey-renderer.js +324 -0
  159. package/packages/trajectory/dist/src/journey-renderer.js.map +1 -0
  160. package/packages/trajectory/dist/src/learning-graph.d.ts +159 -0
  161. package/packages/trajectory/dist/src/learning-graph.d.ts.map +1 -0
  162. package/packages/trajectory/dist/src/learning-graph.js +258 -0
  163. package/packages/trajectory/dist/src/learning-graph.js.map +1 -0
  164. package/packages/trajectory/dist/src/memory-store.d.ts +146 -0
  165. package/packages/trajectory/dist/src/memory-store.d.ts.map +1 -0
  166. package/packages/trajectory/dist/src/memory-store.js +472 -0
  167. package/packages/trajectory/dist/src/memory-store.js.map +1 -0
  168. package/packages/trajectory/dist/src/review-fork.d.ts +164 -0
  169. package/packages/trajectory/dist/src/review-fork.d.ts.map +1 -0
  170. package/packages/trajectory/dist/src/review-fork.js +332 -0
  171. package/packages/trajectory/dist/src/review-fork.js.map +1 -0
  172. package/packages/trajectory/dist/src/write-approval.d.ts +136 -0
  173. package/packages/trajectory/dist/src/write-approval.d.ts.map +1 -0
  174. package/packages/trajectory/dist/src/write-approval.js +281 -0
  175. package/packages/trajectory/dist/src/write-approval.js.map +1 -0
  176. package/packages/trajectory/package.json +1 -1
  177. package/packages/trajectory/src/curator.ts +485 -0
  178. package/packages/trajectory/src/journey-renderer.ts +399 -0
  179. package/packages/trajectory/src/learning-graph.ts +363 -0
  180. package/packages/trajectory/src/memory-store.ts +578 -0
  181. package/packages/trajectory/src/review-fork.ts +450 -0
  182. package/packages/trajectory/src/write-approval.ts +372 -0
  183. package/packages/tui/package.json +1 -1
  184. package/packages/types/package.json +1 -1
  185. package/packages/workflow-events/package.json +1 -1
  186. package/packages/workspace-scanner/package.json +1 -1
  187. package/packages/worktree/package.json +1 -1
  188. package/packages/write-review/dist/blackboard.d.ts +98 -0
  189. package/packages/write-review/dist/blackboard.d.ts.map +1 -0
  190. package/packages/write-review/dist/blackboard.js +289 -0
  191. package/packages/write-review/dist/blackboard.js.map +1 -0
  192. package/packages/write-review/dist/event-bus.d.ts +106 -0
  193. package/packages/write-review/dist/event-bus.d.ts.map +1 -0
  194. package/packages/write-review/dist/event-bus.js +294 -0
  195. package/packages/write-review/dist/event-bus.js.map +1 -0
  196. package/packages/write-review/dist/gate.d.ts +37 -0
  197. package/packages/write-review/dist/gate.d.ts.map +1 -0
  198. package/packages/write-review/dist/gate.js +138 -0
  199. package/packages/write-review/dist/gate.js.map +1 -0
  200. package/packages/write-review/dist/index.d.ts +22 -0
  201. package/packages/write-review/dist/index.d.ts.map +1 -0
  202. package/packages/write-review/dist/index.js +60 -0
  203. package/packages/write-review/dist/index.js.map +1 -0
  204. package/packages/write-review/dist/injection.d.ts +40 -0
  205. package/packages/write-review/dist/injection.d.ts.map +1 -0
  206. package/packages/write-review/dist/injection.js +179 -0
  207. package/packages/write-review/dist/injection.js.map +1 -0
  208. package/packages/write-review/dist/review.d.ts +54 -0
  209. package/packages/write-review/dist/review.d.ts.map +1 -0
  210. package/packages/write-review/dist/review.js +154 -0
  211. package/packages/write-review/dist/review.js.map +1 -0
  212. package/packages/write-review/dist/trigger.d.ts +39 -0
  213. package/packages/write-review/dist/trigger.d.ts.map +1 -0
  214. package/packages/write-review/dist/trigger.js +107 -0
  215. package/packages/write-review/dist/trigger.js.map +1 -0
  216. package/packages/write-review/dist/types.d.ts +78 -0
  217. package/packages/write-review/dist/types.d.ts.map +1 -0
  218. package/packages/write-review/dist/types.js +26 -0
  219. package/packages/write-review/dist/types.js.map +1 -0
  220. package/packages/write-review/package.json +1 -1
  221. package/packages/write-review/src/event-bus.ts +351 -0
  222. package/packages/write-review/src/index.ts +1 -0
  223. package/packages/write-review/src/injection.ts +25 -3
  224. package/proactive-compact.ts +51 -7
  225. package/scripts/sync-skills.ts +275 -0
  226. package/scripts/sync-to-qdrant.ts +398 -0
@@ -0,0 +1,294 @@
1
+ /**
2
+ * Ping-Pong Event Bus
3
+ *
4
+ * Lightweight event bus for two-agent coordination.
5
+ * Watches blackboard status.json for state changes.
6
+ * Emits events and notifies agents via ExtensionAPI.
7
+ *
8
+ * NO AI NEEDED - deterministic file watching + state machine.
9
+ */
10
+ import { existsSync, readFileSync, watch } from "node:fs";
11
+ import { join } from "node:path";
12
+ /**
13
+ * Ping-Pong Events
14
+ */
15
+ export var PingPongEvent;
16
+ (function (PingPongEvent) {
17
+ PingPongEvent["SESSION_STARTED"] = "session_started";
18
+ PingPongEvent["WRITING_STARTED"] = "writing_started";
19
+ PingPongEvent["WRITER_DONE"] = "writer_done";
20
+ PingPongEvent["REVIEW_NEEDED"] = "review_needed";
21
+ PingPongEvent["REVIEW_STARTED"] = "review_started";
22
+ PingPongEvent["REVIEW_COMPLETE"] = "review_complete";
23
+ PingPongEvent["APPROVED"] = "approved";
24
+ PingPongEvent["CHANGES_REQUESTED"] = "changes_requested";
25
+ PingPongEvent["BLOCKED"] = "blocked";
26
+ PingPongEvent["SESSION_ENDED"] = "session_ended";
27
+ })(PingPongEvent || (PingPongEvent = {}));
28
+ /**
29
+ * Phase to event mapping
30
+ */
31
+ const PHASE_TO_EVENT = {
32
+ idle: PingPongEvent.SESSION_STARTED,
33
+ writing: PingPongEvent.WRITING_STARTED,
34
+ pending_review: PingPongEvent.REVIEW_NEEDED,
35
+ reviewing: PingPongEvent.REVIEW_STARTED,
36
+ approved: PingPongEvent.APPROVED,
37
+ blocked: PingPongEvent.BLOCKED,
38
+ changes_requested: PingPongEvent.CHANGES_REQUESTED,
39
+ };
40
+ /**
41
+ * Simple Event Bus for ping-pong coordination
42
+ */
43
+ export class PingPongEventBus {
44
+ listeners = new Map();
45
+ watchers = new Map();
46
+ lastStatusHash = null;
47
+ pi = null;
48
+ projectPath = null;
49
+ /**
50
+ * Register an event listener
51
+ */
52
+ on(event, listener) {
53
+ if (!this.listeners.has(event)) {
54
+ this.listeners.set(event, new Set());
55
+ }
56
+ this.listeners.get(event).add(listener);
57
+ // Return unsubscribe function
58
+ return () => {
59
+ this.listeners.get(event)?.delete(listener);
60
+ };
61
+ }
62
+ /**
63
+ * Register a listener for all events
64
+ */
65
+ onAny(listener) {
66
+ const wrappedListener = (payload) => {
67
+ return listener(payload);
68
+ };
69
+ // Listen to all events
70
+ for (const event of Object.values(PingPongEvent)) {
71
+ this.on(event, wrappedListener);
72
+ }
73
+ // Return unsubscribe for all
74
+ return () => {
75
+ for (const event of Object.values(PingPongEvent)) {
76
+ this.listeners.get(event)?.delete(wrappedListener);
77
+ }
78
+ };
79
+ }
80
+ /**
81
+ * Emit an event
82
+ */
83
+ emit(event, payload) {
84
+ const fullPayload = {
85
+ event,
86
+ ...payload,
87
+ };
88
+ // Call specific listeners
89
+ const listeners = this.listeners.get(event);
90
+ if (listeners) {
91
+ for (const listener of listeners) {
92
+ try {
93
+ const result = listener(fullPayload);
94
+ if (result instanceof Promise) {
95
+ result.catch((err) => {
96
+ console.error(`[PingPong] Listener error:`, err);
97
+ });
98
+ }
99
+ }
100
+ catch (err) {
101
+ console.error(`[PingPong] Listener error:`, err);
102
+ }
103
+ }
104
+ }
105
+ // Notify via ExtensionAPI if available
106
+ if (this.pi) {
107
+ this.notifyAgents(fullPayload);
108
+ }
109
+ // Log for debugging
110
+ console.error(`[PingPong] Event: ${event}, phase=${payload.phase}, iteration=${payload.iteration}`);
111
+ }
112
+ /**
113
+ * Notify agents via ExtensionAPI
114
+ */
115
+ notifyAgents(payload) {
116
+ if (!this.pi)
117
+ return;
118
+ const { event, phase, iteration } = payload;
119
+ // Map events to user-facing notifications
120
+ const messages = {
121
+ [PingPongEvent.SESSION_STARTED]: `Write-review session started`,
122
+ [PingPongEvent.WRITING_STARTED]: `Writer agent started (iteration ${iteration})`,
123
+ [PingPongEvent.WRITER_DONE]: `Writer done! Code ready for review`,
124
+ [PingPongEvent.REVIEW_NEEDED]: `Review needed - iteration ${iteration}`,
125
+ [PingPongEvent.REVIEW_STARTED]: `Reviewer agent started`,
126
+ [PingPongEvent.REVIEW_COMPLETE]: `Review complete - verdict: ${phase}`,
127
+ [PingPongEvent.APPROVED]: `APPROVED! Code ready to build/commit`,
128
+ [PingPongEvent.CHANGES_REQUESTED]: `Changes requested - iteration ${iteration}`,
129
+ [PingPongEvent.BLOCKED]: `BLOCKED - human intervention needed`,
130
+ [PingPongEvent.SESSION_ENDED]: `Write-review session ended`,
131
+ };
132
+ const message = messages[event];
133
+ if (message) {
134
+ const level = event === PingPongEvent.APPROVED
135
+ ? "success"
136
+ : event === PingPongEvent.BLOCKED
137
+ ? "error"
138
+ : "info";
139
+ // Use ui.notify if available on ExtensionContext
140
+ try {
141
+ // SAFETY: ExtensionAPI doesn't export ui type, we access it via dynamic lookup
142
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
143
+ const ui = this.pi?.ui;
144
+ if (ui?.notify) {
145
+ ui.notify(message, level);
146
+ }
147
+ }
148
+ catch {
149
+ // ExtensionAPI ui.notify not available
150
+ }
151
+ }
152
+ }
153
+ /**
154
+ * Start watching a blackboard status.json
155
+ */
156
+ startWatching(blackboardPath) {
157
+ // Stop any existing watcher
158
+ this.stopWatching();
159
+ const statusPath = join(blackboardPath, "status.json");
160
+ this.projectPath = blackboardPath.replace("/.write-review", "");
161
+ if (!existsSync(statusPath)) {
162
+ console.error(`[PingPong] status.json not found at ${statusPath}`);
163
+ return;
164
+ }
165
+ // Read initial status
166
+ this.readAndEmit(statusPath);
167
+ // Watch for changes
168
+ try {
169
+ const watcher = watch(blackboardPath, { persistent: true }, (_eventType, filename) => {
170
+ if (filename === "status.json") {
171
+ this.readAndEmit(statusPath);
172
+ }
173
+ });
174
+ this.watchers.set(statusPath, watcher);
175
+ console.error(`[PingPong] Started watching ${blackboardPath}`);
176
+ }
177
+ catch (err) {
178
+ console.error(`[PingPong] Failed to watch ${statusPath}:`, err);
179
+ }
180
+ }
181
+ /**
182
+ * Read status.json and emit events if changed
183
+ */
184
+ readAndEmit(statusPath) {
185
+ try {
186
+ const content = readFileSync(statusPath, "utf-8");
187
+ const status = JSON.parse(content);
188
+ // Check if status changed
189
+ const statusHash = JSON.stringify({
190
+ phase: status.phase,
191
+ writerDone: status.writerDone,
192
+ iteration: status.iteration,
193
+ verdict: status.verdict,
194
+ });
195
+ if (statusHash === this.lastStatusHash) {
196
+ return; // No change
197
+ }
198
+ const previousHash = this.lastStatusHash;
199
+ this.lastStatusHash = statusHash;
200
+ // Emit events based on phase transition
201
+ const phase = status.phase;
202
+ const iteration = status.iteration || 1;
203
+ // Detect writer done (was false, now true)
204
+ const wasWriterDone = previousHash ? previousHash.includes('"writerDone":true') : false;
205
+ if (status.writerDone && !wasWriterDone) {
206
+ this.emit(PingPongEvent.WRITER_DONE, {
207
+ phase,
208
+ iteration,
209
+ timestamp: new Date().toISOString(),
210
+ data: { writerMessage: status.writerMessage },
211
+ });
212
+ }
213
+ // Emit phase event
214
+ const event = PHASE_TO_EVENT[phase];
215
+ if (event) {
216
+ this.emit(event, {
217
+ phase,
218
+ iteration,
219
+ timestamp: new Date().toISOString(),
220
+ data: { verdict: status.verdict, verdictMessage: status.verdictMessage },
221
+ });
222
+ }
223
+ }
224
+ catch (err) {
225
+ console.error(`[PingPong] Failed to read status.json:`, err);
226
+ }
227
+ }
228
+ /**
229
+ * Stop watching
230
+ */
231
+ stopWatching() {
232
+ for (const [path, watcher] of this.watchers) {
233
+ watcher.close();
234
+ this.watchers.delete(path);
235
+ }
236
+ console.error(`[PingPong] Stopped watching`);
237
+ }
238
+ /**
239
+ * Set ExtensionAPI for notifications
240
+ */
241
+ setExtensionAPI(pi) {
242
+ this.pi = pi;
243
+ }
244
+ /**
245
+ * Get current status hash
246
+ */
247
+ getLastStatusHash() {
248
+ return this.lastStatusHash;
249
+ }
250
+ /**
251
+ * Clean up
252
+ */
253
+ destroy() {
254
+ this.stopWatching();
255
+ this.listeners.clear();
256
+ this.pi = null;
257
+ }
258
+ }
259
+ // Singleton instance
260
+ let globalEventBus = null;
261
+ /**
262
+ * Get global event bus instance
263
+ */
264
+ export function getPingPongEventBus() {
265
+ if (!globalEventBus) {
266
+ globalEventBus = new PingPongEventBus();
267
+ }
268
+ return globalEventBus;
269
+ }
270
+ /**
271
+ * Create a new event bus instance
272
+ */
273
+ export function createPingPongEventBus() {
274
+ return new PingPongEventBus();
275
+ }
276
+ /**
277
+ * Helper: Check if status changed from previous
278
+ */
279
+ export function hasStatusChanged(current, previous) {
280
+ const currentHash = JSON.stringify({
281
+ phase: current.phase,
282
+ writerDone: current.writerDone,
283
+ iteration: current.iteration,
284
+ verdict: current.verdict,
285
+ });
286
+ return currentHash !== previous;
287
+ }
288
+ /**
289
+ * Helper: Format event for logging
290
+ */
291
+ export function formatPingPongEvent(event) {
292
+ return `[PingPong:${event.event}] phase=${event.phase}, iteration=${event.iteration}, time=${event.timestamp}`;
293
+ }
294
+ //# sourceMappingURL=event-bus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../src/event-bus.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * No-Build Gate
3
+ *
4
+ * Blocks build commands until review is approved.
5
+ */
6
+ import type { WriteReviewBlackboard } from "./blackboard.js";
7
+ import type { WriteReviewStatus } from "./types.js";
8
+ /**
9
+ * Check if a command is a build command
10
+ */
11
+ export declare function isBuildCommand(command: string): boolean;
12
+ /**
13
+ * Gate result
14
+ */
15
+ export interface GateResult {
16
+ allowed: boolean;
17
+ reason?: string;
18
+ currentPhase?: string;
19
+ message?: string;
20
+ }
21
+ /**
22
+ * Check if build is allowed
23
+ */
24
+ export declare function checkBuildGate(command: string, blackboard: WriteReviewBlackboard): GateResult;
25
+ /**
26
+ * Format gate rejection message
27
+ */
28
+ export declare function formatGateRejection(result: GateResult): string;
29
+ /**
30
+ * Get phase emoji
31
+ */
32
+ export declare function getPhaseEmoji(phase: string): string;
33
+ /**
34
+ * Format status for display
35
+ */
36
+ export declare function formatStatusDisplay(status: WriteReviewStatus): string;
37
+ //# sourceMappingURL=gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA0BpD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGvD;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC7B,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,qBAAqB,GAC/B,UAAU,CAyBZ;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAgC9D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAWnD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CA4BrE"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * No-Build Gate
3
+ *
4
+ * Blocks build commands until review is approved.
5
+ */
6
+ /**
7
+ * Commands that trigger build gate
8
+ */
9
+ const BUILD_COMMANDS = [
10
+ "bench build",
11
+ "npm run build",
12
+ "yarn build",
13
+ "pnpm build",
14
+ "bun run build",
15
+ "npm run dev",
16
+ "yarn dev",
17
+ "pnpm dev",
18
+ "./build",
19
+ "make build",
20
+ "gradle build",
21
+ "mvn package",
22
+ "dotnet build",
23
+ "cargo build",
24
+ "go build",
25
+ "python manage.py migrate",
26
+ "bench migrate",
27
+ "bench --site",
28
+ ];
29
+ /**
30
+ * Check if a command is a build command
31
+ */
32
+ export function isBuildCommand(command) {
33
+ const lower = command.toLowerCase().trim();
34
+ return BUILD_COMMANDS.some((cmd) => lower.includes(cmd.toLowerCase()));
35
+ }
36
+ /**
37
+ * Check if build is allowed
38
+ */
39
+ export function checkBuildGate(command, blackboard) {
40
+ if (!isBuildCommand(command)) {
41
+ return { allowed: true };
42
+ }
43
+ const status = blackboard.load();
44
+ if (!status) {
45
+ // No review session - allow build
46
+ return { allowed: true };
47
+ }
48
+ if (status.phase === "approved") {
49
+ return {
50
+ allowed: true,
51
+ currentPhase: status.phase,
52
+ message: "Build allowed - review approved.",
53
+ };
54
+ }
55
+ return {
56
+ allowed: false,
57
+ reason: "REVIEW_NOT_APPROVED",
58
+ currentPhase: status.phase,
59
+ message: `Build blocked. Current review phase: ${status.phase}. Wait for "APPROVED" verdict.`,
60
+ };
61
+ }
62
+ /**
63
+ * Format gate rejection message
64
+ */
65
+ export function formatGateRejection(result) {
66
+ if (result.allowed) {
67
+ return "";
68
+ }
69
+ const lines = [
70
+ "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
71
+ "⚠️ BUILD BLOCKED",
72
+ "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
73
+ "",
74
+ `Current Phase: ${result.currentPhase}`,
75
+ "",
76
+ "The code is under review. Build is only allowed after APPROVED verdict.",
77
+ "",
78
+ "To check status:",
79
+ ` cat {project}/.write-review/status.json`,
80
+ "",
81
+ "To wait for approval, do nothing. The reviewer will post the verdict.",
82
+ "",
83
+ ];
84
+ if (result.currentPhase === "changes_requested") {
85
+ lines.push("Reviewer requested changes. Writer agent should update the code.");
86
+ }
87
+ else if (result.currentPhase === "reviewing") {
88
+ lines.push("Review is in progress. Please wait...");
89
+ }
90
+ else if (result.currentPhase === "pending_review") {
91
+ lines.push("Review not started yet. Waiting for reviewer...");
92
+ }
93
+ return lines.join("\n");
94
+ }
95
+ /**
96
+ * Get phase emoji
97
+ */
98
+ export function getPhaseEmoji(phase) {
99
+ const emojis = {
100
+ idle: "💤",
101
+ writing: "✍️",
102
+ pending_review: "⏳",
103
+ reviewing: "🔍",
104
+ approved: "✅",
105
+ blocked: "🚫",
106
+ changes_requested: "🔄",
107
+ };
108
+ return emojis[phase] ?? "❓";
109
+ }
110
+ /**
111
+ * Format status for display
112
+ */
113
+ export function formatStatusDisplay(status) {
114
+ const emoji = getPhaseEmoji(status.phase);
115
+ const lines = [
116
+ `${emoji} Write-Review Status`,
117
+ "",
118
+ `Phase: ${status.phase}`,
119
+ `Iteration: ${status.iteration}`,
120
+ ];
121
+ if (status.verdict) {
122
+ lines.push(`Verdict: ${status.verdict}`);
123
+ }
124
+ if (status.verdictMessage) {
125
+ lines.push("");
126
+ lines.push("Message:");
127
+ lines.push(status.verdictMessage);
128
+ }
129
+ if (status.codeFiles && status.codeFiles.length > 0) {
130
+ lines.push("");
131
+ lines.push("Code Files:");
132
+ for (const file of status.codeFiles) {
133
+ lines.push(` - ${file}`);
134
+ }
135
+ }
136
+ return lines.join("\n");
137
+ }
138
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * write-review - Two-agent code writing with review loop
3
+ *
4
+ * Integrates with pi-harness-runtime via:
5
+ * - Smart trigger detection (prompt files in wiki/)
6
+ * - System prompt injection for writer agent
7
+ * - Subagent integration for reviewer agent
8
+ *
9
+ * Directory structure: {project}/.write-review/
10
+ */
11
+ /**
12
+ * Auto-cleanup old review history files older than MAX_AGE_DAYS
13
+ */
14
+ export declare function cleanupOldReviews(projectPath: string): number;
15
+ export * from "./types.js";
16
+ export * from "./blackboard.js";
17
+ export * from "./trigger.js";
18
+ export * from "./injection.js";
19
+ export * from "./gate.js";
20
+ export * from "./review.js";
21
+ export * from "./event-bus.js";
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAOH;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAqC7D;AAGD,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * write-review - Two-agent code writing with review loop
3
+ *
4
+ * Integrates with pi-harness-runtime via:
5
+ * - Smart trigger detection (prompt files in wiki/)
6
+ * - System prompt injection for writer agent
7
+ * - Subagent integration for reviewer agent
8
+ *
9
+ * Directory structure: {project}/.write-review/
10
+ */
11
+ import { rmSync, readdirSync, statSync, existsSync } from "node:fs";
12
+ import { join, resolve } from "node:path";
13
+ const MAX_AGE_DAYS = 3;
14
+ /**
15
+ * Auto-cleanup old review history files older than MAX_AGE_DAYS
16
+ */
17
+ export function cleanupOldReviews(projectPath) {
18
+ // Resolve path to prevent traversal attacks
19
+ const basePath = resolve(projectPath);
20
+ const reviewDir = join(basePath, ".write-review");
21
+ // Ensure reviewDir is within basePath (traversal guard)
22
+ if (!reviewDir.startsWith(basePath + '/')) {
23
+ return 0; // Invalid path, skip
24
+ }
25
+ if (!existsSync(reviewDir)) {
26
+ return 0; // Directory doesn't exist
27
+ }
28
+ let deleted = 0;
29
+ const files = readdirSync(reviewDir);
30
+ const cutoff = Date.now() - MAX_AGE_DAYS * 24 * 60 * 60 * 1000;
31
+ for (const file of files) {
32
+ if (file === "status.json")
33
+ continue; // Keep status file
34
+ // Sanitize filename to prevent path traversal
35
+ const sanitized = file.replace(/[^a-zA-Z0-9_.-]/g, '_');
36
+ if (sanitized !== file)
37
+ continue; // Skip suspicious filenames
38
+ const filePath = join(reviewDir, sanitized);
39
+ try {
40
+ const stats = statSync(filePath);
41
+ if (stats.mtimeMs < cutoff) {
42
+ rmSync(filePath, { force: true });
43
+ deleted++;
44
+ }
45
+ }
46
+ catch {
47
+ // Ignore files that can't be read
48
+ }
49
+ }
50
+ return deleted;
51
+ }
52
+ // Re-export all public APIs
53
+ export * from "./types.js";
54
+ export * from "./blackboard.js";
55
+ export * from "./trigger.js";
56
+ export * from "./injection.js";
57
+ export * from "./gate.js";
58
+ export * from "./review.js";
59
+ export * from "./event-bus.js";
60
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,YAAY,GAAG,CAAC,CAAC;AAEvB;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,WAAmB;IACnD,4CAA4C;IAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAElD,wDAAwD;IACxD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,EAAE,CAAC;QAC1C,OAAO,CAAC,CAAC,CAAC,qBAAqB;IACjC,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,CAAC,CAAC,0BAA0B;IACtC,CAAC;IAED,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,MAAM,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAE/D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,aAAa;YAAE,SAAS,CAAC,mBAAmB;QACzD,8CAA8C;QAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,SAAS,KAAK,IAAI;YAAE,SAAS,CAAC,4BAA4B;QAE9D,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC5C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACjC,IAAI,KAAK,CAAC,OAAO,GAAG,MAAM,EAAE,CAAC;gBAC3B,MAAM,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClC,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kCAAkC;QACpC,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,4BAA4B;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * System Prompt Injection
3
+ *
4
+ * Adds write-review hints to the agent's system prompt.
5
+ */
6
+ /**
7
+ * Write-review hint for system prompt
8
+ */
9
+ export declare const WRITE_REVIEW_HINT = "\n\n## Write-Review Loop\n\nWhen reading a prompt from {project}/wiki/*:\n\n1. You are the **WRITER** agent (Minimax). Read the wiki prompt and write code.\n2. After writing code, write \"## WRITER_DONE\" to signal completion.\n3. Do NOT build or commit until you receive \"APPROVED\" verdict.\n4. If you receive \"CHANGES_REQUESTED\", update the code accordingly.\n5. Acknowledge each verdict in your response.\n\n### Blackboard Path\n{p}/.write-review/status.json\n\n### Verdict Types\n- **APPROVED**: Code is ready. You may build/commit.\n- **CHANGES_REQUESTED**: Reviewer found issues. Update code.\n- **BLOCKED**: Critical issues. Human intervention needed.\n";
10
+ /**
11
+ * Helper agent hint (for worker agent)
12
+ */
13
+ export declare const HELPER_HINT = "\n\n## Helper Agent Task\n\nThe writer agent is busy or needs assistance. Your task:\n\n1. Note any pending tasks to the Todos list using the todo tool.\n2. Review the changes requested and prepare notes for the writer.\n3. Do NOT write code directly - that's the writer's job.\n4. Write a summary of pending tasks to the blackboard.\n";
14
+ /**
15
+ * Review reminder hint
16
+ */
17
+ export declare const REVIEW_REMINDER_HINT = "\n\n## Review Reminder\n\nBefore committing or building, ALWAYS check the write-review status:\n\n```bash\ncat {project}/.write-review/status.json\n```\n\nOnly build/commit if the status shows \"approved\" or \"phase\": \"approved\".\n";
18
+ /**
19
+ * Format hint with project path
20
+ */
21
+ export declare function formatWriteReviewHint(projectPath: string): string;
22
+ /**
23
+ * Format review reminder with project path
24
+ */
25
+ export declare function formatReviewReminder(projectPath: string): string;
26
+ /**
27
+ * Get all hints to inject
28
+ */
29
+ export declare function getWriteReviewHints(projectPath: string): {
30
+ writeHint: string;
31
+ reminderHint: string;
32
+ };
33
+ /**
34
+ * Register write-review extension with pi
35
+ */
36
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
37
+ export declare function injectWriterInstructions(pi: ExtensionAPI, config?: {
38
+ debug?: boolean;
39
+ }): void;
40
+ //# sourceMappingURL=injection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"injection.d.ts","sourceRoot":"","sources":["../src/injection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAsBH;;GAEG;AACH,eAAO,MAAM,iBAAiB,6pBAmB7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,oVAUvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,gPAWhC,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAKjE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;CACrB,CAKA;AAED;;GAEG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAKpE,wBAAgB,wBAAwB,CACvC,EAAE,EAAE,YAAY,EAChB,MAAM,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1B,IAAI,CAyFN"}