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.
- package/CHANGELOG.md +33 -0
- package/harness/loop-runtime.ts +3 -0
- package/index.ts +130 -29
- package/package.json +2 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/architecture-generator/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/clipboard-plugin/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/file-copy-helper/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/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/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/milestone-manager/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/okf-indexer/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/project-bootstrap/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/qdrant-skills/dist/client.d.ts +51 -0
- package/packages/qdrant-skills/dist/client.d.ts.map +1 -0
- package/packages/qdrant-skills/dist/client.js +105 -0
- package/packages/qdrant-skills/dist/client.js.map +1 -0
- package/packages/qdrant-skills/dist/embedder.d.ts +39 -0
- package/packages/qdrant-skills/dist/embedder.d.ts.map +1 -0
- package/packages/qdrant-skills/dist/embedder.js +101 -0
- package/packages/qdrant-skills/dist/embedder.js.map +1 -0
- package/packages/qdrant-skills/dist/index.d.ts +25 -0
- package/packages/qdrant-skills/dist/index.d.ts.map +1 -0
- package/packages/qdrant-skills/dist/index.js +25 -0
- package/packages/qdrant-skills/dist/index.js.map +1 -0
- package/packages/qdrant-skills/package.json +27 -0
- package/packages/qdrant-skills/src/client.ts +178 -0
- package/packages/qdrant-skills/src/embedder.ts +137 -0
- package/packages/qdrant-skills/src/index.ts +42 -0
- 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-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/dist/index.d.ts +40 -0
- package/packages/skills/dist/index.d.ts.map +1 -0
- package/packages/skills/dist/index.js +84 -0
- package/packages/skills/dist/index.js.map +1 -0
- package/packages/skills/dist/linter.d.ts +38 -0
- package/packages/skills/dist/linter.d.ts.map +1 -0
- package/packages/skills/dist/linter.js +323 -0
- package/packages/skills/dist/linter.js.map +1 -0
- package/packages/skills/dist/loader.d.ts +74 -0
- package/packages/skills/dist/loader.d.ts.map +1 -0
- package/packages/skills/dist/loader.js +280 -0
- package/packages/skills/dist/loader.js.map +1 -0
- package/packages/skills/dist/parser.d.ts +32 -0
- package/packages/skills/dist/parser.d.ts.map +1 -0
- package/packages/skills/dist/parser.js +459 -0
- package/packages/skills/dist/parser.js.map +1 -0
- package/packages/skills/dist/scanner.d.ts +33 -0
- package/packages/skills/dist/scanner.d.ts.map +1 -0
- package/packages/skills/dist/scanner.js +257 -0
- package/packages/skills/dist/scanner.js.map +1 -0
- package/packages/skills/dist/skill-commands.d.ts +33 -0
- package/packages/skills/dist/skill-commands.d.ts.map +1 -0
- package/packages/skills/dist/skill-commands.js +239 -0
- package/packages/skills/dist/skill-commands.js.map +1 -0
- package/packages/skills/dist/skill-tool.d.ts +120 -0
- package/packages/skills/dist/skill-tool.d.ts.map +1 -0
- package/packages/skills/dist/skill-tool.js +239 -0
- package/packages/skills/dist/skill-tool.js.map +1 -0
- package/packages/skills/dist/skill-versioning.d.ts +123 -0
- package/packages/skills/dist/skill-versioning.d.ts.map +1 -0
- package/packages/skills/dist/skill-versioning.js +240 -0
- package/packages/skills/dist/skill-versioning.js.map +1 -0
- package/packages/skills/dist/types.d.ts +226 -0
- package/packages/skills/dist/types.d.ts.map +1 -0
- package/packages/skills/dist/types.js +21 -0
- package/packages/skills/dist/types.js.map +1 -0
- package/packages/skills/package.json +46 -0
- package/packages/skills/src/index.ts +95 -0
- package/packages/skills/src/linter.ts +371 -0
- package/packages/skills/src/loader.ts +335 -0
- package/packages/skills/src/parser.ts +548 -0
- package/packages/skills/src/scanner.ts +322 -0
- package/packages/skills/src/skill-commands.ts +318 -0
- package/packages/skills/src/skill-tool.ts +324 -0
- package/packages/skills/src/skill-versioning.ts +345 -0
- package/packages/skills/src/types.ts +259 -0
- package/packages/skills/test/init-skills.test.ts +118 -0
- 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/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/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/trajectory/dist/src/curator.d.ts +189 -0
- package/packages/trajectory/dist/src/curator.d.ts.map +1 -0
- package/packages/trajectory/dist/src/curator.js +340 -0
- package/packages/trajectory/dist/src/curator.js.map +1 -0
- package/packages/trajectory/dist/src/journey-renderer.d.ts +53 -0
- package/packages/trajectory/dist/src/journey-renderer.d.ts.map +1 -0
- package/packages/trajectory/dist/src/journey-renderer.js +324 -0
- package/packages/trajectory/dist/src/journey-renderer.js.map +1 -0
- package/packages/trajectory/dist/src/learning-graph.d.ts +159 -0
- package/packages/trajectory/dist/src/learning-graph.d.ts.map +1 -0
- package/packages/trajectory/dist/src/learning-graph.js +258 -0
- package/packages/trajectory/dist/src/learning-graph.js.map +1 -0
- package/packages/trajectory/dist/src/memory-store.d.ts +146 -0
- package/packages/trajectory/dist/src/memory-store.d.ts.map +1 -0
- package/packages/trajectory/dist/src/memory-store.js +472 -0
- package/packages/trajectory/dist/src/memory-store.js.map +1 -0
- package/packages/trajectory/dist/src/review-fork.d.ts +164 -0
- package/packages/trajectory/dist/src/review-fork.d.ts.map +1 -0
- package/packages/trajectory/dist/src/review-fork.js +332 -0
- package/packages/trajectory/dist/src/review-fork.js.map +1 -0
- package/packages/trajectory/dist/src/write-approval.d.ts +136 -0
- package/packages/trajectory/dist/src/write-approval.d.ts.map +1 -0
- package/packages/trajectory/dist/src/write-approval.js +281 -0
- package/packages/trajectory/dist/src/write-approval.js.map +1 -0
- package/packages/trajectory/package.json +1 -1
- package/packages/trajectory/src/curator.ts +485 -0
- package/packages/trajectory/src/journey-renderer.ts +399 -0
- package/packages/trajectory/src/learning-graph.ts +363 -0
- package/packages/trajectory/src/memory-store.ts +578 -0
- package/packages/trajectory/src/review-fork.ts +450 -0
- package/packages/trajectory/src/write-approval.ts +372 -0
- 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/dist/blackboard.d.ts +98 -0
- package/packages/write-review/dist/blackboard.d.ts.map +1 -0
- package/packages/write-review/dist/blackboard.js +289 -0
- package/packages/write-review/dist/blackboard.js.map +1 -0
- package/packages/write-review/dist/event-bus.d.ts +106 -0
- package/packages/write-review/dist/event-bus.d.ts.map +1 -0
- package/packages/write-review/dist/event-bus.js +294 -0
- package/packages/write-review/dist/event-bus.js.map +1 -0
- package/packages/write-review/dist/gate.d.ts +37 -0
- package/packages/write-review/dist/gate.d.ts.map +1 -0
- package/packages/write-review/dist/gate.js +138 -0
- package/packages/write-review/dist/gate.js.map +1 -0
- package/packages/write-review/dist/index.d.ts +22 -0
- package/packages/write-review/dist/index.d.ts.map +1 -0
- package/packages/write-review/dist/index.js +60 -0
- package/packages/write-review/dist/index.js.map +1 -0
- package/packages/write-review/dist/injection.d.ts +40 -0
- package/packages/write-review/dist/injection.d.ts.map +1 -0
- package/packages/write-review/dist/injection.js +179 -0
- package/packages/write-review/dist/injection.js.map +1 -0
- package/packages/write-review/dist/review.d.ts +54 -0
- package/packages/write-review/dist/review.d.ts.map +1 -0
- package/packages/write-review/dist/review.js +154 -0
- package/packages/write-review/dist/review.js.map +1 -0
- package/packages/write-review/dist/trigger.d.ts +39 -0
- package/packages/write-review/dist/trigger.d.ts.map +1 -0
- package/packages/write-review/dist/trigger.js +107 -0
- package/packages/write-review/dist/trigger.js.map +1 -0
- package/packages/write-review/dist/types.d.ts +78 -0
- package/packages/write-review/dist/types.d.ts.map +1 -0
- package/packages/write-review/dist/types.js +26 -0
- package/packages/write-review/dist/types.js.map +1 -0
- package/packages/write-review/package.json +1 -1
- package/packages/write-review/src/event-bus.ts +351 -0
- package/packages/write-review/src/index.ts +1 -0
- package/packages/write-review/src/injection.ts +25 -3
- package/proactive-compact.ts +51 -7
- package/scripts/sync-skills.ts +275 -0
- package/scripts/sync-to-qdrant.ts +398 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write Approval Gate
|
|
3
|
+
*
|
|
4
|
+
* Stage writes (memory, skills) for human review before they land.
|
|
5
|
+
* Based on Hermes Agent's consent-aware learning loop.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
9
|
+
import { join, dirname } from "node:path";
|
|
10
|
+
import { homedir } from "node:os";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Pending write types
|
|
14
|
+
*/
|
|
15
|
+
export type PendingWriteType =
|
|
16
|
+
| "memory_add"
|
|
17
|
+
| "memory_replace"
|
|
18
|
+
| "memory_remove"
|
|
19
|
+
| "skill_create"
|
|
20
|
+
| "skill_patch"
|
|
21
|
+
| "skill_delete"
|
|
22
|
+
| "skill_file_write"
|
|
23
|
+
| "skill_file_remove"
|
|
24
|
+
| "user_profile_add";
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Pending write action
|
|
28
|
+
*/
|
|
29
|
+
export interface PendingWriteAction {
|
|
30
|
+
type: PendingWriteType;
|
|
31
|
+
target: string; // memory entry id, skill id, etc.
|
|
32
|
+
content?: string; // new content for add/replace
|
|
33
|
+
oldContent?: string; // old content for replace/remove
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Pending write record
|
|
39
|
+
*/
|
|
40
|
+
export interface PendingWrite {
|
|
41
|
+
id: string;
|
|
42
|
+
action: PendingWriteAction;
|
|
43
|
+
author: "agent" | "user" | "curator";
|
|
44
|
+
timestamp: number;
|
|
45
|
+
summary: string; // One-line summary for display
|
|
46
|
+
details?: string; // Full diff or content for review
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Write approval configuration
|
|
51
|
+
*/
|
|
52
|
+
export interface WriteApprovalConfig {
|
|
53
|
+
/** Enable write approval */
|
|
54
|
+
enabled: boolean;
|
|
55
|
+
/** Directory to store pending writes */
|
|
56
|
+
pendingDir: string;
|
|
57
|
+
/** Max pending writes before warning */
|
|
58
|
+
maxPending: number;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Default configuration
|
|
63
|
+
*/
|
|
64
|
+
export const DEFAULT_APPROVAL_CONFIG: WriteApprovalConfig = {
|
|
65
|
+
enabled: false,
|
|
66
|
+
pendingDir: "~/.pi-harness/pending",
|
|
67
|
+
maxPending: 50,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Expand path with ~
|
|
72
|
+
*/
|
|
73
|
+
function expandPath(path: string): string {
|
|
74
|
+
if (path.startsWith("~/")) {
|
|
75
|
+
return join(homedir(), path.slice(2));
|
|
76
|
+
}
|
|
77
|
+
return path;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Write Approval Gate
|
|
82
|
+
*/
|
|
83
|
+
export class WriteApprovalGate {
|
|
84
|
+
private config: WriteApprovalConfig;
|
|
85
|
+
private pending: PendingWrite[] = [];
|
|
86
|
+
|
|
87
|
+
constructor(config?: Partial<WriteApprovalConfig>) {
|
|
88
|
+
this.config = { ...DEFAULT_APPROVAL_CONFIG, ...config };
|
|
89
|
+
this.config.pendingDir = expandPath(this.config.pendingDir);
|
|
90
|
+
this.load();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Load pending writes from disk
|
|
95
|
+
*/
|
|
96
|
+
private load(): void {
|
|
97
|
+
const pendingFile = join(this.config.pendingDir, "writes.json");
|
|
98
|
+
|
|
99
|
+
if (!existsSync(pendingFile)) {
|
|
100
|
+
this.pending = [];
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const content = readFileSync(pendingFile, "utf-8");
|
|
106
|
+
this.pending = JSON.parse(content);
|
|
107
|
+
} catch (err) {
|
|
108
|
+
console.error("[WriteApprovalGate] Failed to load:", err);
|
|
109
|
+
this.pending = [];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Save pending writes to disk
|
|
115
|
+
*/
|
|
116
|
+
private save(): void {
|
|
117
|
+
mkdirSync(this.config.pendingDir, { recursive: true });
|
|
118
|
+
const pendingFile = join(this.config.pendingDir, "writes.json");
|
|
119
|
+
writeFileSync(pendingFile, JSON.stringify(this.pending, null, 2), "utf-8");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Stage a write for approval
|
|
124
|
+
*/
|
|
125
|
+
stage(action: PendingWriteAction, author: "agent" | "user" | "curator"): PendingWrite {
|
|
126
|
+
// Generate ID
|
|
127
|
+
const id = `pw_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
128
|
+
|
|
129
|
+
// Generate summary
|
|
130
|
+
const summary = this.generateSummary(action);
|
|
131
|
+
|
|
132
|
+
// Generate details (diff)
|
|
133
|
+
const details = this.generateDetails(action);
|
|
134
|
+
|
|
135
|
+
const pending: PendingWrite = {
|
|
136
|
+
id,
|
|
137
|
+
action,
|
|
138
|
+
author,
|
|
139
|
+
timestamp: Date.now(),
|
|
140
|
+
summary,
|
|
141
|
+
details,
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
this.pending.push(pending);
|
|
145
|
+
this.save();
|
|
146
|
+
|
|
147
|
+
return pending;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate one-line summary for action
|
|
152
|
+
*/
|
|
153
|
+
private generateSummary(action: PendingWriteAction): string {
|
|
154
|
+
switch (action.type) {
|
|
155
|
+
case "memory_add":
|
|
156
|
+
return `Add memory: "${action.content?.slice(0, 50)}..."`;
|
|
157
|
+
case "memory_replace":
|
|
158
|
+
return `Replace memory`;
|
|
159
|
+
case "memory_remove":
|
|
160
|
+
return `Remove memory`;
|
|
161
|
+
case "skill_create":
|
|
162
|
+
return `Create skill: ${action.target}`;
|
|
163
|
+
case "skill_patch":
|
|
164
|
+
return `Patch skill: ${action.target}`;
|
|
165
|
+
case "skill_delete":
|
|
166
|
+
return `Delete skill: ${action.target}`;
|
|
167
|
+
case "skill_file_write":
|
|
168
|
+
return `Write file to skill ${action.target}: ${action.metadata?.file}`;
|
|
169
|
+
case "skill_file_remove":
|
|
170
|
+
return `Remove file from skill ${action.target}: ${action.metadata?.file}`;
|
|
171
|
+
case "user_profile_add":
|
|
172
|
+
return `Add user preference: "${action.content?.slice(0, 50)}..."`;
|
|
173
|
+
default:
|
|
174
|
+
return `Unknown action: ${action.type}`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Generate details (diff) for action
|
|
180
|
+
*/
|
|
181
|
+
private generateDetails(action: PendingWriteAction): string | undefined {
|
|
182
|
+
switch (action.type) {
|
|
183
|
+
case "memory_add":
|
|
184
|
+
case "user_profile_add":
|
|
185
|
+
return action.content;
|
|
186
|
+
case "memory_replace":
|
|
187
|
+
return `OLD:\n${action.oldContent}\n\nNEW:\n${action.content}`;
|
|
188
|
+
case "skill_create":
|
|
189
|
+
case "skill_patch":
|
|
190
|
+
return action.content;
|
|
191
|
+
default:
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Approve a pending write
|
|
198
|
+
*/
|
|
199
|
+
approve(writeId: string): PendingWrite | null {
|
|
200
|
+
const index = this.pending.findIndex((w) => w.id === writeId);
|
|
201
|
+
if (index < 0) return null;
|
|
202
|
+
|
|
203
|
+
const write = this.pending[index];
|
|
204
|
+
this.pending.splice(index, 1);
|
|
205
|
+
this.save();
|
|
206
|
+
|
|
207
|
+
return write;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Approve all pending writes
|
|
212
|
+
*/
|
|
213
|
+
approveAll(): PendingWrite[] {
|
|
214
|
+
const approved = [...this.pending];
|
|
215
|
+
this.pending = [];
|
|
216
|
+
this.save();
|
|
217
|
+
return approved;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Reject a pending write
|
|
222
|
+
*/
|
|
223
|
+
reject(writeId: string): PendingWrite | null {
|
|
224
|
+
const index = this.pending.findIndex((w) => w.id === writeId);
|
|
225
|
+
if (index < 0) return null;
|
|
226
|
+
|
|
227
|
+
const write = this.pending[index];
|
|
228
|
+
this.pending.splice(index, 1);
|
|
229
|
+
this.save();
|
|
230
|
+
|
|
231
|
+
return write;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Reject all pending writes
|
|
236
|
+
*/
|
|
237
|
+
rejectAll(): PendingWrite[] {
|
|
238
|
+
const rejected = [...this.pending];
|
|
239
|
+
this.pending = [];
|
|
240
|
+
this.save();
|
|
241
|
+
return rejected;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Get all pending writes
|
|
246
|
+
*/
|
|
247
|
+
list(): PendingWrite[] {
|
|
248
|
+
return [...this.pending];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Get pending writes by type
|
|
253
|
+
*/
|
|
254
|
+
listByType(type: PendingWriteType): PendingWrite[] {
|
|
255
|
+
return this.pending.filter((w) => w.action.type === type);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Get pending writes by author
|
|
260
|
+
*/
|
|
261
|
+
listByAuthor(author: "agent" | "user" | "curator"): PendingWrite[] {
|
|
262
|
+
return this.pending.filter((w) => w.author === author);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Get pending count
|
|
267
|
+
*/
|
|
268
|
+
count(): number {
|
|
269
|
+
return this.pending.length;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Check if approval is required
|
|
274
|
+
*/
|
|
275
|
+
requiresApproval(): boolean {
|
|
276
|
+
return this.config.enabled;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Update configuration
|
|
281
|
+
*/
|
|
282
|
+
updateConfig(config: Partial<WriteApprovalConfig>): void {
|
|
283
|
+
this.config = { ...this.config, ...config };
|
|
284
|
+
if (config.pendingDir) {
|
|
285
|
+
this.config.pendingDir = expandPath(config.pendingDir);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Get configuration
|
|
291
|
+
*/
|
|
292
|
+
getConfig(): WriteApprovalConfig {
|
|
293
|
+
return { ...this.config };
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Format pending writes for display
|
|
298
|
+
*/
|
|
299
|
+
formatList(): string {
|
|
300
|
+
if (this.pending.length === 0) {
|
|
301
|
+
return "No pending writes.";
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const lines: string[] = [];
|
|
305
|
+
for (const write of this.pending) {
|
|
306
|
+
const age = this.getAgeString(write.timestamp);
|
|
307
|
+
lines.push(`[${write.id}] ${age} ${write.author}: ${write.summary}`);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return lines.join("\n");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Get age string for timestamp
|
|
315
|
+
*/
|
|
316
|
+
private getAgeString(timestamp: number): string {
|
|
317
|
+
const age = Date.now() - timestamp;
|
|
318
|
+
const minutes = Math.floor(age / 60000);
|
|
319
|
+
|
|
320
|
+
if (minutes < 1) return "<1m";
|
|
321
|
+
if (minutes < 60) return `${minutes}m`;
|
|
322
|
+
|
|
323
|
+
const hours = Math.floor(minutes / 60);
|
|
324
|
+
if (hours < 24) return `${hours}h`;
|
|
325
|
+
|
|
326
|
+
const days = Math.floor(hours / 24);
|
|
327
|
+
return `${days}d`;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Global instance
|
|
332
|
+
let globalGate: WriteApprovalGate | null = null;
|
|
333
|
+
|
|
334
|
+
export function getGlobalApprovalGate(): WriteApprovalGate {
|
|
335
|
+
if (!globalGate) {
|
|
336
|
+
globalGate = new WriteApprovalGate();
|
|
337
|
+
}
|
|
338
|
+
return globalGate;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function createApprovalGate(config?: Partial<WriteApprovalConfig>): WriteApprovalGate {
|
|
342
|
+
return new WriteApprovalGate(config);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Helper to stage write with auto-approval if disabled
|
|
347
|
+
*/
|
|
348
|
+
export function stageWrite(
|
|
349
|
+
action: PendingWriteAction,
|
|
350
|
+
author: "agent" | "user" | "curator",
|
|
351
|
+
autoApprove: boolean = false
|
|
352
|
+
): { staged: boolean; write?: PendingWrite } {
|
|
353
|
+
const gate = getGlobalApprovalGate();
|
|
354
|
+
|
|
355
|
+
if (!gate.requiresApproval() || autoApprove) {
|
|
356
|
+
// Return action directly for execution
|
|
357
|
+
return {
|
|
358
|
+
staged: false,
|
|
359
|
+
write: {
|
|
360
|
+
id: "auto",
|
|
361
|
+
action,
|
|
362
|
+
author,
|
|
363
|
+
timestamp: Date.now(),
|
|
364
|
+
summary: `Auto-approved: ${action.type}`,
|
|
365
|
+
},
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Stage for approval
|
|
370
|
+
const write = gate.stage(action, author);
|
|
371
|
+
return { staged: true, write };
|
|
372
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Write-Review Blackboard
|
|
3
|
+
*
|
|
4
|
+
* File-based coordination between writer and reviewer agents.
|
|
5
|
+
* Location: {project}/.write-review/status.json
|
|
6
|
+
*/
|
|
7
|
+
import type { WriteReviewStatus, ReviewPhase, Verdict, PingPongDecisionSnapshot } from "./types.js";
|
|
8
|
+
export declare class WriteReviewBlackboard {
|
|
9
|
+
private readonly projectPath;
|
|
10
|
+
private readonly dir;
|
|
11
|
+
private status;
|
|
12
|
+
constructor(projectPath: string, dir?: string);
|
|
13
|
+
/**
|
|
14
|
+
* Initialize a new write-review session
|
|
15
|
+
*/
|
|
16
|
+
init(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Load status from disk
|
|
19
|
+
*/
|
|
20
|
+
load(): WriteReviewStatus | null;
|
|
21
|
+
/**
|
|
22
|
+
* Save status to disk
|
|
23
|
+
*/
|
|
24
|
+
save(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get current status
|
|
27
|
+
*/
|
|
28
|
+
getStatus(): WriteReviewStatus | null;
|
|
29
|
+
/**
|
|
30
|
+
* Record the automatic decision that selected or skipped PING-PONG.
|
|
31
|
+
* This is the durable middleware state shared by separate agent terminals.
|
|
32
|
+
*/
|
|
33
|
+
recordPingPongDecision(snapshot: PingPongDecisionSnapshot): void;
|
|
34
|
+
/**
|
|
35
|
+
* Start a new write session
|
|
36
|
+
*/
|
|
37
|
+
startWriting(): void;
|
|
38
|
+
/**
|
|
39
|
+
* Mark writer as done
|
|
40
|
+
*/
|
|
41
|
+
writerDone(message?: string): void;
|
|
42
|
+
/**
|
|
43
|
+
* Start reviewing
|
|
44
|
+
*/
|
|
45
|
+
startReview(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Record verdict
|
|
48
|
+
*/
|
|
49
|
+
setVerdict(verdict: Verdict, message?: string): void;
|
|
50
|
+
/**
|
|
51
|
+
* Record code files written
|
|
52
|
+
*/
|
|
53
|
+
setCodeFiles(files: string[]): void;
|
|
54
|
+
/**
|
|
55
|
+
* Record requested changes
|
|
56
|
+
*/
|
|
57
|
+
setChangesRequested(changes: string[]): void;
|
|
58
|
+
/**
|
|
59
|
+
* Get current phase
|
|
60
|
+
*/
|
|
61
|
+
getPhase(): ReviewPhase;
|
|
62
|
+
/**
|
|
63
|
+
* Get iteration number
|
|
64
|
+
*/
|
|
65
|
+
getIteration(): number;
|
|
66
|
+
/**
|
|
67
|
+
* Check if build is allowed
|
|
68
|
+
*/
|
|
69
|
+
canBuild(): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Get blackboard directory path
|
|
72
|
+
*/
|
|
73
|
+
getPath(): string;
|
|
74
|
+
/**
|
|
75
|
+
* Reset to idle
|
|
76
|
+
*/
|
|
77
|
+
reset(): void;
|
|
78
|
+
/**
|
|
79
|
+
* Check if a review session exists for this project
|
|
80
|
+
*/
|
|
81
|
+
exists(): boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Export status as markdown for display.
|
|
84
|
+
* Injected into every agent prompt so each agent sees the shared scoreboard.
|
|
85
|
+
* Matches the pi-lens pattern: persistent artifact encountered naturally.
|
|
86
|
+
*/
|
|
87
|
+
toMarkdown(): string;
|
|
88
|
+
/**
|
|
89
|
+
* Extract file paths from a fenced code block string.
|
|
90
|
+
* Looks for common patterns: ```path/to/file
|
|
91
|
+
*/
|
|
92
|
+
extractFilePaths(code: string): string[];
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create or get blackboard for project
|
|
96
|
+
*/
|
|
97
|
+
export declare function createBlackboard(projectPath: string, dir?: string): WriteReviewBlackboard;
|
|
98
|
+
//# sourceMappingURL=blackboard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blackboard.d.ts","sourceRoot":"","sources":["../src/blackboard.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACX,iBAAiB,EACjB,WAAW,EACX,OAAO,EACP,wBAAwB,EACxB,MAAM,YAAY,CAAC;AAKpB,qBAAa,qBAAqB;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,MAAM,CAAkC;IAEhD,YAAY,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,MAAoB,EAGzD;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,CAWX;IAED;;OAEG;IACH,IAAI,IAAI,iBAAiB,GAAG,IAAI,CAW/B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,CAMX;IAED;;OAEG;IACH,SAAS,IAAI,iBAAiB,GAAG,IAAI,CAEpC;IAED;;;OAGG;IACH,sBAAsB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,IAAI,CAY/D;IAED;;OAEG;IACH,YAAY,IAAI,IAAI,CAMnB;IAED;;OAEG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAMjC;IAED;;OAEG;IACH,WAAW,IAAI,IAAI,CAKlB;IAED;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAmBnD;IAED;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAIlC;IAED;;OAEG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAI3C;IAED;;OAEG;IACH,QAAQ,IAAI,WAAW,CAEtB;IAED;;OAEG;IACH,YAAY,IAAI,MAAM,CAErB;IAED;;OAEG;IACH,QAAQ,IAAI,OAAO,CAElB;IAED;;OAEG;IACH,OAAO,IAAI,MAAM,CAEhB;IAED;;OAEG;IACH,KAAK,IAAI,IAAI,CAYZ;IAED;;OAEG;IACH,MAAM,IAAI,OAAO,CAGhB;IAED;;;;OAIG;IACH,UAAU,IAAI,MAAM,CAkDnB;IAED;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAuBvC;CACD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC/B,WAAW,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,MAAM,GACV,qBAAqB,CAQvB"}
|