pi-harness-runtime 0.10.6 → 0.10.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/index.ts +27 -0
  2. package/package.json +1 -1
  3. package/packages/a2a-adapter/package.json +1 -1
  4. package/packages/auth/package.json +1 -1
  5. package/packages/autonomous-refactor/package.json +1 -1
  6. package/packages/autonomous-runtime/package.json +1 -1
  7. package/packages/cache-strategy/package.json +1 -1
  8. package/packages/capability-registry/package.json +1 -1
  9. package/packages/checkpoint/package.json +1 -1
  10. package/packages/cli-plugin-sdk/package.json +1 -1
  11. package/packages/clipboard/package.json +1 -1
  12. package/packages/code-generation/package.json +1 -1
  13. package/packages/code-review/package.json +1 -1
  14. package/packages/codex-adapter/package.json +1 -1
  15. package/packages/config-capture/package.json +1 -1
  16. package/packages/context-compiler/package.json +1 -1
  17. package/packages/context-discovery/package.json +1 -1
  18. package/packages/context-manager/package.json +1 -1
  19. package/packages/cookie-sanitizer/package.json +1 -1
  20. package/packages/cost-optimizer/package.json +1 -1
  21. package/packages/dependency-analyzer/package.json +1 -1
  22. package/packages/django-plugin/package.json +1 -1
  23. package/packages/doc-generator/package.json +1 -1
  24. package/packages/evaluation-engine/package.json +1 -1
  25. package/packages/evaluation-runner/package.json +1 -1
  26. package/packages/event-bus/package.json +1 -1
  27. package/packages/event-store/package.json +1 -1
  28. package/packages/experience-replay/package.json +1 -1
  29. package/packages/feedback-collector/package.json +1 -1
  30. package/packages/framework-detector/package.json +1 -1
  31. package/packages/framework-plugin-sdk/package.json +1 -1
  32. package/packages/frappe-plugin/package.json +1 -1
  33. package/packages/generic-web-plugin/package.json +1 -1
  34. package/packages/health-monitor/package.json +1 -1
  35. package/packages/intent-analyzer/package.json +1 -1
  36. package/packages/laravel-plugin/package.json +1 -1
  37. package/packages/learning-engine/package.json +1 -1
  38. package/packages/mcp-adapter/package.json +1 -1
  39. package/packages/memory-engine/package.json +1 -1
  40. package/packages/model-registry/package.json +1 -1
  41. package/packages/nextjs-plugin/package.json +1 -1
  42. package/packages/notification/package.json +1 -1
  43. package/packages/observability/package.json +1 -1
  44. package/packages/performance-optimizer/package.json +1 -1
  45. package/packages/privilege-broker/package.json +1 -1
  46. package/packages/project-analyzer/package.json +1 -1
  47. package/packages/projection-engine/package.json +1 -1
  48. package/packages/prompt-compiler/package.json +1 -1
  49. package/packages/prompt-versioning/package.json +1 -1
  50. package/packages/provider-adapter-sdk/package.json +1 -1
  51. package/packages/provider-router/package.json +1 -1
  52. package/packages/provider-selector/package.json +1 -1
  53. package/packages/providers/package.json +1 -1
  54. package/packages/quota-manager/package.json +1 -1
  55. package/packages/rate-limiter/package.json +1 -1
  56. package/packages/react-vite-plugin/package.json +1 -1
  57. package/packages/release-manager/package.json +1 -1
  58. package/packages/requirement-compiler/package.json +1 -1
  59. package/packages/runtime/package.json +1 -1
  60. package/packages/scheduler/package.json +1 -1
  61. package/packages/scheduler-adapter/package.json +1 -1
  62. package/packages/session/package.json +1 -1
  63. package/packages/session-api/package.json +1 -1
  64. package/packages/session-export/package.json +1 -1
  65. package/packages/shared-context/package.json +1 -1
  66. package/packages/skill-registry/package.json +1 -1
  67. package/packages/sprint-planner/package.json +1 -1
  68. package/packages/subscription-engine/package.json +1 -1
  69. package/packages/task-compiler/package.json +1 -1
  70. package/packages/test-data-generator/package.json +1 -1
  71. package/packages/test-generator/package.json +1 -1
  72. package/packages/todo-bd-sync/package.json +1 -1
  73. package/packages/token-estimation/package.json +1 -1
  74. package/packages/token-optimizer/package.json +1 -1
  75. package/packages/tui/package.json +1 -1
  76. package/packages/types/package.json +1 -1
  77. package/packages/workflow-events/package.json +1 -1
  78. package/packages/workspace-scanner/package.json +1 -1
  79. package/packages/worktree/package.json +1 -1
  80. package/packages/write-review/package.json +22 -0
  81. package/packages/write-review/src/blackboard.ts +245 -0
  82. package/packages/write-review/src/gate.ts +167 -0
  83. package/packages/write-review/src/index.ts +18 -0
  84. package/packages/write-review/src/injection.ts +157 -0
  85. package/packages/write-review/src/review.ts +201 -0
  86. package/packages/write-review/src/trigger.ts +130 -0
  87. package/packages/write-review/src/types.ts +88 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/session-export",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/shared-context",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "pi-harness-runtime — shared-context",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/skill-registry",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Skill Registry for pi-harness-runtime — dynamic skill discovery and invocation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/sprint-planner",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "type": "module",
5
5
  "description": "Sprint planning engine for pi-harness",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/subscription-engine",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/task-compiler",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Task Compiler for pi-harness-runtime — produces deterministic task DAG from CompiledRequirement",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/test-data-generator",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Test data generation for pi-harness-runtime",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/test-generator",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Auto-Test Generator — generate unit and E2E tests from source code (RFC-0013)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moocoding/todo-bd-sync",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Two-way sync between rpiv-todo overlay and bd issue tracker",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/token-estimation",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "pi-harness-runtime — token-estimation",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/token-optimizer",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Token Budget Optimizer — maximize prompt value within token limits (RFC-0011)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/tui",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "pi-harness-runtime — tui",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/types",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "Shared TypeScript types for pi-harness-runtime packages",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/workflow-events",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi/workspace-scanner",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "type": "module",
5
5
  "main": "src/index.ts",
6
6
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-harness/worktree",
3
- "version": "0.10.6",
3
+ "version": "0.10.7",
4
4
  "description": "pi-harness-runtime — worktree",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "@moocoding/write-review",
3
+ "version": "0.10.7",
4
+ "description": "Two-agent write-review loop with blackboard coordination",
5
+ "type": "module",
6
+ "main": "src/index.ts",
7
+ "types": "src/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./src/index.ts",
11
+ "types": "./src/index.ts"
12
+ }
13
+ },
14
+ "keywords": [
15
+ "pi-extension",
16
+ "write-review",
17
+ "blackboard",
18
+ "multi-agent"
19
+ ],
20
+ "author": "MooCoding",
21
+ "license": "MIT"
22
+ }
@@ -0,0 +1,245 @@
1
+ /**
2
+ * Write-Review Blackboard
3
+ *
4
+ * File-based coordination between writer and reviewer agents.
5
+ * Location: {project}/.write-review/status.json
6
+ */
7
+
8
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
9
+ import { join } from "path";
10
+ import type { WriteReviewStatus, ReviewPhase, Verdict } from "./types.js";
11
+
12
+ const DEFAULT_DIR = ".write-review";
13
+ const STATUS_FILE = "status.json";
14
+
15
+ export class WriteReviewBlackboard {
16
+ private readonly projectPath: string;
17
+ private readonly dir: string;
18
+ private status: WriteReviewStatus | null = null;
19
+
20
+ constructor(projectPath: string, dir: string = DEFAULT_DIR) {
21
+ this.projectPath = projectPath;
22
+ this.dir = join(projectPath, dir);
23
+ }
24
+
25
+ /**
26
+ * Initialize a new write-review session
27
+ */
28
+ init(): void {
29
+ mkdirSync(this.dir, { recursive: true });
30
+ this.status = {
31
+ projectPath: this.projectPath,
32
+ phase: "idle",
33
+ writerDone: false,
34
+ iteration: 0,
35
+ createdAt: new Date().toISOString(),
36
+ updatedAt: new Date().toISOString(),
37
+ };
38
+ this.save();
39
+ }
40
+
41
+ /**
42
+ * Load status from disk
43
+ */
44
+ load(): WriteReviewStatus | null {
45
+ const path = join(this.dir, STATUS_FILE);
46
+ if (!existsSync(path)) {
47
+ return null;
48
+ }
49
+ try {
50
+ this.status = JSON.parse(readFileSync(path, "utf-8"));
51
+ return this.status;
52
+ } catch {
53
+ return null;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * Save status to disk
59
+ */
60
+ save(): void {
61
+ if (!this.status) return;
62
+ this.status.updatedAt = new Date().toISOString();
63
+ mkdirSync(this.dir, { recursive: true });
64
+ const path = join(this.dir, STATUS_FILE);
65
+ writeFileSync(path, JSON.stringify(this.status, null, 2));
66
+ }
67
+
68
+ /**
69
+ * Get current status
70
+ */
71
+ getStatus(): WriteReviewStatus | null {
72
+ return this.status;
73
+ }
74
+
75
+ /**
76
+ * Start a new write session
77
+ */
78
+ startWriting(): void {
79
+ if (!this.status) this.init();
80
+ this.status!.phase = "writing";
81
+ this.status!.writerDone = false;
82
+ this.status!.iteration++;
83
+ this.save();
84
+ }
85
+
86
+ /**
87
+ * Mark writer as done
88
+ */
89
+ writerDone(message?: string): void {
90
+ if (!this.status) return;
91
+ this.status.writerDone = true;
92
+ this.status.writerMessage = message;
93
+ this.status.phase = "pending_review";
94
+ this.save();
95
+ }
96
+
97
+ /**
98
+ * Start reviewing
99
+ */
100
+ startReview(): void {
101
+ if (!this.status) return;
102
+ this.status.phase = "reviewing";
103
+ this.status.reviewerStarted = new Date().toISOString();
104
+ this.save();
105
+ }
106
+
107
+ /**
108
+ * Record verdict
109
+ */
110
+ setVerdict(verdict: Verdict, message?: string): void {
111
+ if (!this.status) return;
112
+ this.status.verdict = verdict;
113
+ this.status.verdictMessage = message;
114
+
115
+ switch (verdict) {
116
+ case "approved":
117
+ this.status.phase = "approved";
118
+ this.status.approvedAt = new Date().toISOString();
119
+ break;
120
+ case "blocked":
121
+ this.status.phase = "blocked";
122
+ this.status.blockedAt = new Date().toISOString();
123
+ break;
124
+ case "changes_requested":
125
+ this.status.phase = "changes_requested";
126
+ break;
127
+ }
128
+ this.save();
129
+ }
130
+
131
+ /**
132
+ * Record code files written
133
+ */
134
+ setCodeFiles(files: string[]): void {
135
+ if (!this.status) return;
136
+ this.status.codeFiles = files;
137
+ this.save();
138
+ }
139
+
140
+ /**
141
+ * Record requested changes
142
+ */
143
+ setChangesRequested(changes: string[]): void {
144
+ if (!this.status) return;
145
+ this.status.changesRequested = changes;
146
+ this.save();
147
+ }
148
+
149
+ /**
150
+ * Get current phase
151
+ */
152
+ getPhase(): ReviewPhase {
153
+ return this.status?.phase ?? "idle";
154
+ }
155
+
156
+ /**
157
+ * Get iteration number
158
+ */
159
+ getIteration(): number {
160
+ return this.status?.iteration ?? 0;
161
+ }
162
+
163
+ /**
164
+ * Check if build is allowed
165
+ */
166
+ canBuild(): boolean {
167
+ return this.status?.phase === "approved";
168
+ }
169
+
170
+ /**
171
+ * Get blackboard directory path
172
+ */
173
+ getPath(): string {
174
+ return this.dir;
175
+ }
176
+
177
+ /**
178
+ * Reset to idle
179
+ */
180
+ reset(): void {
181
+ if (!this.status) return;
182
+ this.status.phase = "idle";
183
+ this.status.writerDone = false;
184
+ this.status.verdict = undefined;
185
+ this.status.verdictMessage = undefined;
186
+ this.status.reviewerStarted = undefined;
187
+ this.status.approvedAt = undefined;
188
+ this.status.blockedAt = undefined;
189
+ this.status.codeFiles = undefined;
190
+ this.status.changesRequested = undefined;
191
+ this.save();
192
+ }
193
+
194
+ /**
195
+ * Check if a review session exists for this project
196
+ */
197
+ exists(): boolean {
198
+ const path = join(this.dir, STATUS_FILE);
199
+ return existsSync(path);
200
+ }
201
+
202
+ /**
203
+ * Export status as markdown for display
204
+ */
205
+ toMarkdown(): string {
206
+ if (!this.status) return "No active write-review session.";
207
+
208
+ const { phase, iteration, verdict, verdictMessage, codeFiles } = this.status;
209
+ const lines = [
210
+ `## Write-Review Status`,
211
+ ``,
212
+ `| Field | Value |`,
213
+ `|-------|-------|`,
214
+ `| Phase | ${phase} |`,
215
+ `| Iteration | ${iteration} |`,
216
+ `| Verdict | ${verdict ?? "pending"} |`,
217
+ ];
218
+
219
+ if (verdictMessage) {
220
+ lines.push(`| Message | ${verdictMessage} |`);
221
+ }
222
+
223
+ if (codeFiles && codeFiles.length > 0) {
224
+ lines.push(``, `### Code Files`);
225
+ for (const file of codeFiles) {
226
+ lines.push(`- ${file}`);
227
+ }
228
+ }
229
+
230
+ return lines.join("\n");
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Create or get blackboard for project
236
+ */
237
+ export function createBlackboard(projectPath: string, dir?: string): WriteReviewBlackboard {
238
+ const bb = new WriteReviewBlackboard(projectPath, dir);
239
+ if (!bb.exists()) {
240
+ bb.init();
241
+ } else {
242
+ bb.load();
243
+ }
244
+ return bb;
245
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * No-Build Gate
3
+ *
4
+ * Blocks build commands until review is approved.
5
+ */
6
+
7
+ import type { WriteReviewBlackboard } from "./blackboard.js";
8
+ import type { WriteReviewStatus } from "./types.js";
9
+
10
+ /**
11
+ * Commands that trigger build gate
12
+ */
13
+ const BUILD_COMMANDS = [
14
+ "bench build",
15
+ "npm run build",
16
+ "yarn build",
17
+ "pnpm build",
18
+ "bun run build",
19
+ "npm run dev",
20
+ "yarn dev",
21
+ "pnpm dev",
22
+ "./build",
23
+ "make build",
24
+ "gradle build",
25
+ "mvn package",
26
+ "dotnet build",
27
+ "cargo build",
28
+ "go build",
29
+ "python manage.py migrate",
30
+ "bench migrate",
31
+ "bench --site",
32
+ ];
33
+
34
+ /**
35
+ * Check if a command is a build command
36
+ */
37
+ export function isBuildCommand(command: string): boolean {
38
+ const lower = command.toLowerCase().trim();
39
+ return BUILD_COMMANDS.some((cmd) => lower.includes(cmd.toLowerCase()));
40
+ }
41
+
42
+ /**
43
+ * Gate result
44
+ */
45
+ export interface GateResult {
46
+ allowed: boolean;
47
+ reason?: string;
48
+ currentPhase?: string;
49
+ message?: string;
50
+ }
51
+
52
+ /**
53
+ * Check if build is allowed
54
+ */
55
+ export function checkBuildGate(
56
+ command: string,
57
+ blackboard: WriteReviewBlackboard
58
+ ): GateResult {
59
+ if (!isBuildCommand(command)) {
60
+ return { allowed: true };
61
+ }
62
+
63
+ const status = blackboard.load();
64
+ if (!status) {
65
+ // No review session - allow build
66
+ return { allowed: true };
67
+ }
68
+
69
+ if (status.phase === "approved") {
70
+ return {
71
+ allowed: true,
72
+ currentPhase: status.phase,
73
+ message: "Build allowed - review approved.",
74
+ };
75
+ }
76
+
77
+ return {
78
+ allowed: false,
79
+ reason: "REVIEW_NOT_APPROVED",
80
+ currentPhase: status.phase,
81
+ message: `Build blocked. Current review phase: ${status.phase}. Wait for "APPROVED" verdict.`,
82
+ };
83
+ }
84
+
85
+ /**
86
+ * Format gate rejection message
87
+ */
88
+ export function formatGateRejection(result: GateResult): string {
89
+ if (result.allowed) {
90
+ return "";
91
+ }
92
+
93
+ const lines = [
94
+ "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
95
+ "⚠️ BUILD BLOCKED",
96
+ "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
97
+ "",
98
+ `Current Phase: ${result.currentPhase}`,
99
+ "",
100
+ "The code is under review. Build is only allowed after APPROVED verdict.",
101
+ "",
102
+ "To check status:",
103
+ ` cat {project}/.write-review/status.json`,
104
+ "",
105
+ "To wait for approval, do nothing. The reviewer will post the verdict.",
106
+ "",
107
+ ];
108
+
109
+ if (result.currentPhase === "changes_requested") {
110
+ lines.push("Reviewer requested changes. Writer agent should update the code.");
111
+ } else if (result.currentPhase === "reviewing") {
112
+ lines.push("Review is in progress. Please wait...");
113
+ } else if (result.currentPhase === "pending_review") {
114
+ lines.push("Review not started yet. Waiting for reviewer...");
115
+ }
116
+
117
+ return lines.join("\n");
118
+ }
119
+
120
+ /**
121
+ * Get phase emoji
122
+ */
123
+ export function getPhaseEmoji(phase: string): string {
124
+ const emojis: Record<string, string> = {
125
+ idle: "💤",
126
+ writing: "✍️",
127
+ pending_review: "⏳",
128
+ reviewing: "🔍",
129
+ approved: "✅",
130
+ blocked: "🚫",
131
+ changes_requested: "🔄",
132
+ };
133
+ return emojis[phase] ?? "❓";
134
+ }
135
+
136
+ /**
137
+ * Format status for display
138
+ */
139
+ export function formatStatusDisplay(status: WriteReviewStatus): string {
140
+ const emoji = getPhaseEmoji(status.phase);
141
+ const lines = [
142
+ `${emoji} Write-Review Status`,
143
+ "",
144
+ `Phase: ${status.phase}`,
145
+ `Iteration: ${status.iteration}`,
146
+ ];
147
+
148
+ if (status.verdict) {
149
+ lines.push(`Verdict: ${status.verdict}`);
150
+ }
151
+
152
+ if (status.verdictMessage) {
153
+ lines.push("");
154
+ lines.push("Message:");
155
+ lines.push(status.verdictMessage);
156
+ }
157
+
158
+ if (status.codeFiles && status.codeFiles.length > 0) {
159
+ lines.push("");
160
+ lines.push("Code Files:");
161
+ for (const file of status.codeFiles) {
162
+ lines.push(` - ${file}`);
163
+ }
164
+ }
165
+
166
+ return lines.join("\n");
167
+ }
@@ -0,0 +1,18 @@
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
+ // Re-export all public APIs
13
+ export * from "./types.js";
14
+ export * from "./blackboard.js";
15
+ export * from "./trigger.js";
16
+ export * from "./injection.js";
17
+ export * from "./gate.js";
18
+ export * from "./review.js";