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.
- package/index.ts +27 -0
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/observability/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +22 -0
- package/packages/write-review/src/blackboard.ts +245 -0
- package/packages/write-review/src/gate.ts +167 -0
- package/packages/write-review/src/index.ts +18 -0
- package/packages/write-review/src/injection.ts +157 -0
- package/packages/write-review/src/review.ts +201 -0
- package/packages/write-review/src/trigger.ts +130 -0
- package/packages/write-review/src/types.ts +88 -0
|
@@ -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";
|