harnery 0.17.0 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +187 -4
- package/dist/commands/supervisor.d.ts.map +1 -1
- package/dist/commands/supervisor.js +76 -4
- package/dist/core/supervisor/index.d.ts +3 -3
- package/dist/core/supervisor/index.d.ts.map +1 -1
- package/dist/core/supervisor/index.js +2 -2
- package/dist/core/supervisor/plan-read.d.ts +2 -1
- package/dist/core/supervisor/plan-read.d.ts.map +1 -1
- package/dist/core/supervisor/plan-read.js +222 -3
- package/dist/core/supervisor/plan-types.d.ts +60 -3
- package/dist/core/supervisor/plan-types.d.ts.map +1 -1
- package/dist/core/supervisor/plan-types.js +2 -0
- package/dist/core/supervisor/planning.d.ts.map +1 -1
- package/dist/core/supervisor/planning.js +804 -56
- package/dist/core/supervisor/read.d.ts +3 -3
- package/dist/core/supervisor/read.d.ts.map +1 -1
- package/dist/core/supervisor/read.js +2 -2
- package/dist/core/supervisor/runner.d.ts.map +1 -1
- package/dist/core/supervisor/runner.js +7 -2
- package/dist/core/supervisor/service.js +3 -0
- package/dist/core/supervisor/state.d.ts +17 -2
- package/dist/core/supervisor/state.d.ts.map +1 -1
- package/dist/core/supervisor/state.js +211 -33
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +24 -6
- package/dist/core/workflow/types.d.ts +6 -0
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/validate.d.ts +3 -2
- package/dist/core/workflow/validate.d.ts.map +1 -1
- package/dist/core/workflow/validate.js +31 -3
- package/dist/lib/browser/client.d.ts +18 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +39 -0
- package/dist/lib/browser/geometry.d.ts +146 -0
- package/dist/lib/browser/geometry.d.ts.map +1 -0
- package/dist/lib/browser/geometry.js +525 -0
- package/dist/lib/browser/index.d.ts +2 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/target-size.d.ts +65 -0
- package/dist/lib/browser/target-size.d.ts.map +1 -0
- package/dist/lib/browser/target-size.js +108 -0
- package/package.json +7 -1
- package/src/commands/browse.ts +319 -0
- package/src/commands/supervisor.ts +92 -5
- package/src/core/supervisor/index.ts +17 -1
- package/src/core/supervisor/plan-read.ts +292 -2
- package/src/core/supervisor/plan-types.ts +69 -1
- package/src/core/supervisor/planning.ts +1012 -51
- package/src/core/supervisor/read.ts +16 -1
- package/src/core/supervisor/runner.ts +9 -2
- package/src/core/supervisor/service.ts +3 -0
- package/src/core/supervisor/state.ts +272 -31
- package/src/core/workflow/engine.ts +29 -6
- package/src/core/workflow/types.ts +6 -0
- package/src/core/workflow/validate.ts +34 -3
- package/src/lib/browser/client.ts +62 -0
- package/src/lib/browser/geometry.ts +695 -0
- package/src/lib/browser/index.ts +25 -0
- package/src/lib/browser/target-size.ts +180 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
2
3
|
import { join, resolve } from "node:path";
|
|
3
|
-
import {
|
|
4
|
+
import { readWorkItem } from "../work/read.js";
|
|
5
|
+
import { MAX_SUPERVISOR_PLAN_REVIEWERS, MAX_SUPERVISOR_PLAN_REVISION_ROUNDS, SUPERVISOR_PLAN_SCHEMA_VERSION, } from "./plan-types.js";
|
|
4
6
|
const PLAN_ID = /^plan-[0-9]{4}-[a-f0-9]{8}$/;
|
|
5
7
|
const GOAL_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
6
8
|
const WORK_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}$/;
|
|
@@ -14,8 +16,10 @@ const MAX_EVENTS = 100;
|
|
|
14
16
|
const EVENT_TYPES = new Set([
|
|
15
17
|
"plan.awaiting_approval",
|
|
16
18
|
"plan.resumed",
|
|
19
|
+
"plan.reviewed",
|
|
17
20
|
"plan.proposed",
|
|
18
21
|
"plan.applied",
|
|
22
|
+
"plan.completed",
|
|
19
23
|
"plan.rejected",
|
|
20
24
|
"plan.attention",
|
|
21
25
|
"plan.failed",
|
|
@@ -32,6 +36,8 @@ export function readSupervisorPlans(coordRootRaw, goalId, originalRootWorkId) {
|
|
|
32
36
|
generation: 0,
|
|
33
37
|
applied_work_ids: [],
|
|
34
38
|
materialized_work_ids: [],
|
|
39
|
+
milestones_completed: 0,
|
|
40
|
+
completed: false,
|
|
35
41
|
};
|
|
36
42
|
}
|
|
37
43
|
const entries = readdirSync(root, { withFileTypes: true })
|
|
@@ -51,6 +57,8 @@ export function readSupervisorPlans(coordRootRaw, goalId, originalRootWorkId) {
|
|
|
51
57
|
}
|
|
52
58
|
let activeRoot = originalRootWorkId;
|
|
53
59
|
let generation = 0;
|
|
60
|
+
let milestonesCompleted = 0;
|
|
61
|
+
let completed = false;
|
|
54
62
|
const appliedWork = new Set();
|
|
55
63
|
const materializedWork = new Set();
|
|
56
64
|
for (const plan of plans) {
|
|
@@ -64,15 +72,27 @@ export function readSupervisorPlans(coordRootRaw, goalId, originalRootWorkId) {
|
|
|
64
72
|
continue;
|
|
65
73
|
activeRoot = plan.root_work_id;
|
|
66
74
|
generation++;
|
|
75
|
+
if (plan.proposal?.milestone &&
|
|
76
|
+
readWorkItem(coordRoot, plan.root_work_id).projection.state === "succeeded") {
|
|
77
|
+
milestonesCompleted++;
|
|
78
|
+
}
|
|
67
79
|
for (const workId of plan.work_ids)
|
|
68
80
|
appliedWork.add(workId);
|
|
69
81
|
}
|
|
82
|
+
const completedPlans = plans.filter((plan) => plan.status === "completed");
|
|
83
|
+
if (completedPlans.length > 1 ||
|
|
84
|
+
(completedPlans.length === 1 && completedPlans[0] !== plans.at(-1))) {
|
|
85
|
+
throw new Error(`supervisor ${goalId} has invalid completion history`);
|
|
86
|
+
}
|
|
87
|
+
completed = completedPlans.length === 1;
|
|
70
88
|
return {
|
|
71
89
|
plans,
|
|
72
90
|
active_root_work_id: activeRoot,
|
|
73
91
|
generation,
|
|
74
92
|
applied_work_ids: [...appliedWork],
|
|
75
93
|
materialized_work_ids: [...materializedWork],
|
|
94
|
+
milestones_completed: milestonesCompleted,
|
|
95
|
+
completed,
|
|
76
96
|
latest: plans.at(-1),
|
|
77
97
|
};
|
|
78
98
|
}
|
|
@@ -89,12 +109,37 @@ export function readSupervisorPlan(coordRootRaw, goalId, planId) {
|
|
|
89
109
|
: undefined;
|
|
90
110
|
if (proposal)
|
|
91
111
|
validateProposalEnvelope(proposal, planId);
|
|
112
|
+
const review = readSupervisorPlanReviewReceipt(coordRootRaw, goalId, planId);
|
|
92
113
|
const events = readEvents(join(dir, "events.jsonl"), planId);
|
|
93
114
|
const derived = deriveStatus(coordRoot, events, proposal);
|
|
94
|
-
return {
|
|
115
|
+
return {
|
|
116
|
+
request,
|
|
117
|
+
proposal,
|
|
118
|
+
review: review ? summarizeReview(review) : undefined,
|
|
119
|
+
events,
|
|
120
|
+
...derived,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
export function readSupervisorPlanReviewReceipt(coordRootRaw, goalId, planId) {
|
|
124
|
+
assertId(goalId, GOAL_ID, "supervisor id");
|
|
125
|
+
assertId(planId, PLAN_ID, "supervisor plan id");
|
|
126
|
+
const coordRoot = resolve(coordRootRaw);
|
|
127
|
+
const path = join(planDir(coordRoot, goalId, planId), "review.json");
|
|
128
|
+
if (!existsSync(path))
|
|
129
|
+
return undefined;
|
|
130
|
+
const receipt = readJson(path, "plan review receipt");
|
|
131
|
+
validateReviewReceipt(receipt, planId);
|
|
132
|
+
const reviewPolicy = readFrozenReviewPolicy(coordRoot, goalId);
|
|
133
|
+
if (reviewPolicy)
|
|
134
|
+
validateReviewReceiptMatchesPolicy(receipt, planId, reviewPolicy);
|
|
135
|
+
return receipt;
|
|
95
136
|
}
|
|
96
137
|
function deriveStatus(coordRoot, events, proposal) {
|
|
97
138
|
const latest = events.at(-1);
|
|
139
|
+
const completed = [...events].reverse().find((event) => event.event === "plan.completed");
|
|
140
|
+
if (completed) {
|
|
141
|
+
return { status: "completed", work_ids: [], reason: completed.reason };
|
|
142
|
+
}
|
|
98
143
|
const applied = [...events].reverse().find((event) => event.event === "plan.applied");
|
|
99
144
|
if (applied) {
|
|
100
145
|
return {
|
|
@@ -159,6 +204,8 @@ function validateRequest(request, goalId, planId) {
|
|
|
159
204
|
!Number.isSafeInteger(request.sequence) ||
|
|
160
205
|
request.sequence < 1 ||
|
|
161
206
|
request.sequence > MAX_PLANS ||
|
|
207
|
+
(request.trigger !== undefined &&
|
|
208
|
+
!["initial", "recovery", "milestone"].includes(request.trigger)) ||
|
|
162
209
|
typeof request.trigger_fingerprint !== "string" ||
|
|
163
210
|
request.trigger_fingerprint.length < 1 ||
|
|
164
211
|
request.trigger_fingerprint.length > 64_000 ||
|
|
@@ -171,7 +218,7 @@ function validateRequest(request, goalId, planId) {
|
|
|
171
218
|
function validateProposalEnvelope(proposal, planId) {
|
|
172
219
|
if (proposal.schema_version !== SUPERVISOR_PLAN_SCHEMA_VERSION ||
|
|
173
220
|
proposal.plan_id !== planId ||
|
|
174
|
-
!["apply", "attention"].includes(proposal.decision) ||
|
|
221
|
+
!["apply", "complete", "attention"].includes(proposal.decision) ||
|
|
175
222
|
typeof proposal.rationale !== "string" ||
|
|
176
223
|
proposal.rationale.length < 1 ||
|
|
177
224
|
proposal.rationale.length > 2_000 ||
|
|
@@ -182,6 +229,28 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
182
229
|
!validTimestamp(proposal.proposed_at)) {
|
|
183
230
|
throw new Error(`supervisor plan proposal ${planId} has an unsupported schema`);
|
|
184
231
|
}
|
|
232
|
+
if (proposal.milestone !== undefined) {
|
|
233
|
+
const milestone = proposal.milestone;
|
|
234
|
+
if (!Number.isSafeInteger(milestone.sequence) ||
|
|
235
|
+
milestone.sequence < 1 ||
|
|
236
|
+
milestone.sequence > 20 ||
|
|
237
|
+
typeof milestone.title !== "string" ||
|
|
238
|
+
milestone.title.length < 1 ||
|
|
239
|
+
milestone.title.length > 200 ||
|
|
240
|
+
typeof milestone.objective !== "string" ||
|
|
241
|
+
milestone.objective.length < 1 ||
|
|
242
|
+
milestone.objective.length > 4_000 ||
|
|
243
|
+
!Array.isArray(milestone.acceptance) ||
|
|
244
|
+
milestone.acceptance.length < 1 ||
|
|
245
|
+
milestone.acceptance.length > 50 ||
|
|
246
|
+
milestone.acceptance.some((criterion) => typeof criterion !== "string" || criterion.length < 1 || criterion.length > 500)) {
|
|
247
|
+
throw new Error(`supervisor plan proposal ${planId} milestone is invalid`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
if ((proposal.decision === "attention" || proposal.decision === "complete") &&
|
|
251
|
+
(proposal.root !== "" || proposal.work.length > 0 || proposal.milestone !== undefined)) {
|
|
252
|
+
throw new Error(`supervisor plan proposal ${planId} terminal decision contains work`);
|
|
253
|
+
}
|
|
185
254
|
for (const [index, spec] of proposal.work.entries()) {
|
|
186
255
|
if (!spec ||
|
|
187
256
|
typeof spec !== "object" ||
|
|
@@ -203,6 +272,156 @@ function validateProposalEnvelope(proposal, planId) {
|
|
|
203
272
|
}
|
|
204
273
|
}
|
|
205
274
|
}
|
|
275
|
+
function validateReviewReceipt(receipt, planId) {
|
|
276
|
+
if (!receipt ||
|
|
277
|
+
typeof receipt !== "object" ||
|
|
278
|
+
receipt.schema_version !== SUPERVISOR_PLAN_SCHEMA_VERSION ||
|
|
279
|
+
receipt.plan_id !== planId ||
|
|
280
|
+
!["passed", "revision_exhausted", "attention", "failed"].includes(receipt.status) ||
|
|
281
|
+
!/^[a-f0-9]{64}$/.test(receipt.candidate_sha256) ||
|
|
282
|
+
!Array.isArray(receipt.rounds) ||
|
|
283
|
+
receipt.rounds.length < 1 ||
|
|
284
|
+
receipt.rounds.length > MAX_SUPERVISOR_PLAN_REVISION_ROUNDS + 1) {
|
|
285
|
+
throw new Error(`supervisor plan review ${planId} has an unsupported schema`);
|
|
286
|
+
}
|
|
287
|
+
validateProposalEnvelope(receipt.final_candidate, planId);
|
|
288
|
+
if (receipt.candidate_sha256 !== candidateDigest(receipt.final_candidate)) {
|
|
289
|
+
throw new Error(`supervisor plan review ${planId} has invalid candidate digest`);
|
|
290
|
+
}
|
|
291
|
+
receipt.rounds.forEach((round, index) => {
|
|
292
|
+
validateReviewRound(round, planId, index + 1);
|
|
293
|
+
});
|
|
294
|
+
const finalRound = receipt.rounds.at(-1);
|
|
295
|
+
if (finalRound?.candidate_sha256 !== receipt.candidate_sha256) {
|
|
296
|
+
throw new Error(`supervisor plan review ${planId} final round does not match its candidate`);
|
|
297
|
+
}
|
|
298
|
+
if (receipt.status === "passed" && finalRound?.outcome !== "approved") {
|
|
299
|
+
throw new Error(`supervisor plan review ${planId} passed without approval`);
|
|
300
|
+
}
|
|
301
|
+
if (receipt.status === "attention" && finalRound?.outcome === "approved") {
|
|
302
|
+
throw new Error(`supervisor plan review ${planId} attention conflicts with approval`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
function readFrozenReviewPolicy(coordRoot, goalId) {
|
|
306
|
+
const path = join(coordRoot, ".harnery", "supervisors", goalId, "intent.json");
|
|
307
|
+
if (!existsSync(path))
|
|
308
|
+
return undefined;
|
|
309
|
+
const intent = readJson(path, "supervisor intent");
|
|
310
|
+
return intent.replanning?.review;
|
|
311
|
+
}
|
|
312
|
+
function validateReviewReceiptMatchesPolicy(receipt, planId, review) {
|
|
313
|
+
if (receipt.rounds.length > review.max_revision_rounds + 1) {
|
|
314
|
+
throw new Error(`supervisor plan review ${planId} exceeds the frozen review policy`);
|
|
315
|
+
}
|
|
316
|
+
for (const round of receipt.rounds) {
|
|
317
|
+
if (round.reviewers.length !== review.reviewer_specialists.length) {
|
|
318
|
+
throw new Error(`supervisor plan review ${planId} does not match the frozen review policy`);
|
|
319
|
+
}
|
|
320
|
+
round.reviewers.forEach((reviewer, index) => {
|
|
321
|
+
if (reviewer.specialist !== review.reviewer_specialists[index]) {
|
|
322
|
+
throw new Error(`supervisor plan review ${planId} does not match the frozen review policy`);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
const outcome = aggregateReviewers(round.reviewers);
|
|
326
|
+
if (round.outcome !== outcome) {
|
|
327
|
+
throw new Error(`supervisor plan review ${planId} has an invalid reviewer outcome`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const finalRound = receipt.rounds.at(-1);
|
|
331
|
+
if (receipt.status === "passed" && finalRound.outcome !== "approved") {
|
|
332
|
+
throw new Error(`supervisor plan review ${planId} passed without policy approval`);
|
|
333
|
+
}
|
|
334
|
+
if (receipt.status === "revision_exhausted" && finalRound.round <= review.max_revision_rounds) {
|
|
335
|
+
throw new Error(`supervisor plan review ${planId} exhausted before the frozen review limit`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
function aggregateReviewers(reviewers) {
|
|
339
|
+
if (reviewers.length < 1)
|
|
340
|
+
return "failed";
|
|
341
|
+
if (reviewers.some((reviewer) => reviewer.verdict === "attention"))
|
|
342
|
+
return "attention";
|
|
343
|
+
if (reviewers.some((reviewer) => reviewer.verdict === "revise" ||
|
|
344
|
+
reviewer.findings.some((finding) => finding.severity === "blocking"))) {
|
|
345
|
+
return "revise";
|
|
346
|
+
}
|
|
347
|
+
return "approved";
|
|
348
|
+
}
|
|
349
|
+
function candidateDigest(candidate) {
|
|
350
|
+
return createHash("sha256")
|
|
351
|
+
.update(JSON.stringify(canonicalCandidate(candidate)))
|
|
352
|
+
.digest("hex");
|
|
353
|
+
}
|
|
354
|
+
function canonicalCandidate(candidate) {
|
|
355
|
+
return {
|
|
356
|
+
schema_version: candidate.schema_version,
|
|
357
|
+
plan_id: candidate.plan_id,
|
|
358
|
+
decision: candidate.decision,
|
|
359
|
+
rationale: candidate.rationale,
|
|
360
|
+
root: candidate.root,
|
|
361
|
+
work: candidate.work,
|
|
362
|
+
milestone: candidate.milestone,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function validateReviewRound(round, planId, sequence) {
|
|
366
|
+
if (!round ||
|
|
367
|
+
typeof round !== "object" ||
|
|
368
|
+
round.round !== sequence ||
|
|
369
|
+
!/^[a-f0-9]{64}$/.test(round.candidate_sha256) ||
|
|
370
|
+
!Array.isArray(round.reviewers) ||
|
|
371
|
+
round.reviewers.length < 1 ||
|
|
372
|
+
round.reviewers.length > MAX_SUPERVISOR_PLAN_REVIEWERS ||
|
|
373
|
+
!["approved", "revise", "attention", "failed"].includes(round.outcome) ||
|
|
374
|
+
(round.revision_workflow_run_id !== undefined &&
|
|
375
|
+
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,199}$/.test(round.revision_workflow_run_id))) {
|
|
376
|
+
throw new Error(`supervisor plan review ${planId} round ${sequence} is invalid`);
|
|
377
|
+
}
|
|
378
|
+
round.reviewers.forEach((reviewer, index) => {
|
|
379
|
+
validateReviewReviewer(reviewer, planId, sequence, index);
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function validateReviewReviewer(reviewer, planId, round, index) {
|
|
383
|
+
if (!reviewer ||
|
|
384
|
+
typeof reviewer !== "object" ||
|
|
385
|
+
typeof reviewer.specialist !== "string" ||
|
|
386
|
+
reviewer.specialist.length < 1 ||
|
|
387
|
+
reviewer.specialist.length > 100 ||
|
|
388
|
+
!["approve", "revise", "attention"].includes(reviewer.verdict) ||
|
|
389
|
+
typeof reviewer.rationale !== "string" ||
|
|
390
|
+
reviewer.rationale.length < 1 ||
|
|
391
|
+
reviewer.rationale.length > 2_000 ||
|
|
392
|
+
!Array.isArray(reviewer.findings) ||
|
|
393
|
+
reviewer.findings.length > 50) {
|
|
394
|
+
throw new Error(`supervisor plan review ${planId} round ${round} reviewer ${index} is invalid`);
|
|
395
|
+
}
|
|
396
|
+
reviewer.findings.forEach((finding, findingIndex) => {
|
|
397
|
+
validateReviewFinding(finding, planId, round, index, findingIndex);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
function validateReviewFinding(finding, planId, round, reviewerIndex, findingIndex) {
|
|
401
|
+
if (!finding ||
|
|
402
|
+
typeof finding !== "object" ||
|
|
403
|
+
typeof finding.code !== "string" ||
|
|
404
|
+
!/^[a-z][a-z0-9._-]{0,99}$/.test(finding.code) ||
|
|
405
|
+
!["blocking", "advisory"].includes(finding.severity) ||
|
|
406
|
+
typeof finding.summary !== "string" ||
|
|
407
|
+
finding.summary.length < 1 ||
|
|
408
|
+
finding.summary.length > 1_000 ||
|
|
409
|
+
typeof finding.recommendation !== "string" ||
|
|
410
|
+
finding.recommendation.length < 1 ||
|
|
411
|
+
finding.recommendation.length > 1_000) {
|
|
412
|
+
throw new Error(`supervisor plan review ${planId} round ${round} reviewer ${reviewerIndex} finding ${findingIndex} is invalid`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
function summarizeReview(receipt) {
|
|
416
|
+
const findings = receipt.rounds.flatMap((round) => round.reviewers.flatMap((reviewer) => reviewer.findings));
|
|
417
|
+
return {
|
|
418
|
+
status: receipt.status,
|
|
419
|
+
candidate_sha256: receipt.candidate_sha256,
|
|
420
|
+
rounds: receipt.rounds.length,
|
|
421
|
+
blocking_findings: findings.filter((finding) => finding.severity === "blocking").length,
|
|
422
|
+
advisory_findings: findings.filter((finding) => finding.severity === "advisory").length,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
206
425
|
function validateEvent(event, planId, sequence) {
|
|
207
426
|
if (event.schema_version !== SUPERVISOR_PLAN_SCHEMA_VERSION ||
|
|
208
427
|
event.plan_id !== planId ||
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export declare const SUPERVISOR_PLAN_SCHEMA_VERSION: 1;
|
|
2
|
+
export declare const MAX_SUPERVISOR_PLAN_REVIEWERS: 5;
|
|
3
|
+
export declare const MAX_SUPERVISOR_PLAN_REVISION_ROUNDS: 3;
|
|
2
4
|
export interface SupervisorPlanTemplate {
|
|
3
5
|
workflow: {
|
|
4
6
|
path: string;
|
|
@@ -14,6 +16,10 @@ export interface SupervisorReplanningPolicy {
|
|
|
14
16
|
max_work_items_per_plan: number;
|
|
15
17
|
max_total_work_items: number;
|
|
16
18
|
templates: Record<string, SupervisorPlanTemplate>;
|
|
19
|
+
review?: {
|
|
20
|
+
reviewer_specialists: string[];
|
|
21
|
+
max_revision_rounds: number;
|
|
22
|
+
};
|
|
17
23
|
}
|
|
18
24
|
export interface CreateSupervisorPlanTemplateInput {
|
|
19
25
|
workflowPath: string;
|
|
@@ -27,17 +33,28 @@ export interface CreateSupervisorReplanningInput {
|
|
|
27
33
|
maxWorkItemsPerPlan?: number;
|
|
28
34
|
maxTotalWorkItems?: number;
|
|
29
35
|
templates: Readonly<Record<string, CreateSupervisorPlanTemplateInput>>;
|
|
36
|
+
review?: {
|
|
37
|
+
reviewerSpecialists: readonly string[];
|
|
38
|
+
maxRevisionRounds: number;
|
|
39
|
+
};
|
|
30
40
|
}
|
|
31
41
|
export interface SupervisorPlanRequest {
|
|
32
42
|
schema_version: typeof SUPERVISOR_PLAN_SCHEMA_VERSION;
|
|
33
43
|
id: string;
|
|
34
44
|
goal_id: string;
|
|
35
45
|
sequence: number;
|
|
46
|
+
trigger?: "initial" | "recovery" | "milestone";
|
|
36
47
|
trigger_fingerprint: string;
|
|
37
48
|
prior_root_work_id: string;
|
|
38
49
|
workflow_run_id: string;
|
|
39
50
|
created_at: string;
|
|
40
51
|
}
|
|
52
|
+
export interface SupervisorPlanMilestone {
|
|
53
|
+
sequence: number;
|
|
54
|
+
title: string;
|
|
55
|
+
objective: string;
|
|
56
|
+
acceptance: string[];
|
|
57
|
+
}
|
|
41
58
|
export interface SupervisorPlanWorkSpec {
|
|
42
59
|
key: string;
|
|
43
60
|
title: string;
|
|
@@ -49,13 +66,50 @@ export interface SupervisorPlanWorkSpec {
|
|
|
49
66
|
export interface SupervisorPlanProposal {
|
|
50
67
|
schema_version: typeof SUPERVISOR_PLAN_SCHEMA_VERSION;
|
|
51
68
|
plan_id: string;
|
|
52
|
-
decision: "apply" | "attention";
|
|
69
|
+
decision: "apply" | "complete" | "attention";
|
|
53
70
|
rationale: string;
|
|
54
71
|
root: string;
|
|
55
72
|
work: SupervisorPlanWorkSpec[];
|
|
73
|
+
milestone?: SupervisorPlanMilestone;
|
|
56
74
|
proposed_at: string;
|
|
57
75
|
}
|
|
58
|
-
export type SupervisorPlanEventType = "plan.awaiting_approval" | "plan.resumed" | "plan.proposed" | "plan.applied" | "plan.rejected" | "plan.attention" | "plan.failed";
|
|
76
|
+
export type SupervisorPlanEventType = "plan.awaiting_approval" | "plan.resumed" | "plan.reviewed" | "plan.proposed" | "plan.applied" | "plan.completed" | "plan.rejected" | "plan.attention" | "plan.failed";
|
|
77
|
+
export type SupervisorPlanReviewStatus = "passed" | "revision_exhausted" | "attention" | "failed";
|
|
78
|
+
export type SupervisorPlanReviewVerdict = "approve" | "revise" | "attention";
|
|
79
|
+
export interface SupervisorPlanReviewFinding {
|
|
80
|
+
code: string;
|
|
81
|
+
severity: "blocking" | "advisory";
|
|
82
|
+
summary: string;
|
|
83
|
+
recommendation: string;
|
|
84
|
+
}
|
|
85
|
+
export interface SupervisorPlanReviewReviewer {
|
|
86
|
+
specialist: string;
|
|
87
|
+
verdict: SupervisorPlanReviewVerdict;
|
|
88
|
+
rationale: string;
|
|
89
|
+
findings: SupervisorPlanReviewFinding[];
|
|
90
|
+
}
|
|
91
|
+
export interface SupervisorPlanReviewRound {
|
|
92
|
+
round: number;
|
|
93
|
+
candidate_sha256: string;
|
|
94
|
+
reviewers: SupervisorPlanReviewReviewer[];
|
|
95
|
+
outcome: "approved" | "revise" | "attention" | "failed";
|
|
96
|
+
revision_workflow_run_id?: string;
|
|
97
|
+
}
|
|
98
|
+
export interface SupervisorPlanReviewReceipt {
|
|
99
|
+
schema_version: typeof SUPERVISOR_PLAN_SCHEMA_VERSION;
|
|
100
|
+
plan_id: string;
|
|
101
|
+
status: SupervisorPlanReviewStatus;
|
|
102
|
+
candidate_sha256: string;
|
|
103
|
+
final_candidate: SupervisorPlanProposal;
|
|
104
|
+
rounds: SupervisorPlanReviewRound[];
|
|
105
|
+
}
|
|
106
|
+
export interface SupervisorPlanReviewSummary {
|
|
107
|
+
status: SupervisorPlanReviewStatus;
|
|
108
|
+
candidate_sha256: string;
|
|
109
|
+
rounds: number;
|
|
110
|
+
blocking_findings: number;
|
|
111
|
+
advisory_findings: number;
|
|
112
|
+
}
|
|
59
113
|
export interface SupervisorPlanEvent {
|
|
60
114
|
schema_version: typeof SUPERVISOR_PLAN_SCHEMA_VERSION;
|
|
61
115
|
plan_id: string;
|
|
@@ -68,10 +122,11 @@ export interface SupervisorPlanEvent {
|
|
|
68
122
|
root_work_id?: string;
|
|
69
123
|
work_ids?: string[];
|
|
70
124
|
}
|
|
71
|
-
export type SupervisorPlanStatus = "interrupted" | "awaiting_approval" | "resumable" | "proposed" | "applied" | "rejected" | "attention" | "failed";
|
|
125
|
+
export type SupervisorPlanStatus = "interrupted" | "awaiting_approval" | "resumable" | "proposed" | "applied" | "completed" | "rejected" | "attention" | "failed";
|
|
72
126
|
export interface SupervisorPlanRecord {
|
|
73
127
|
request: SupervisorPlanRequest;
|
|
74
128
|
proposal?: SupervisorPlanProposal;
|
|
129
|
+
review?: SupervisorPlanReviewSummary;
|
|
75
130
|
events: SupervisorPlanEvent[];
|
|
76
131
|
status: SupervisorPlanStatus;
|
|
77
132
|
approval_id?: string;
|
|
@@ -85,6 +140,8 @@ export interface SupervisorPlanHistory {
|
|
|
85
140
|
generation: number;
|
|
86
141
|
applied_work_ids: string[];
|
|
87
142
|
materialized_work_ids: string[];
|
|
143
|
+
milestones_completed: number;
|
|
144
|
+
completed: boolean;
|
|
88
145
|
latest?: SupervisorPlanRecord;
|
|
89
146
|
}
|
|
90
147
|
export interface SupervisorPlanOutcome {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan-types.d.ts","sourceRoot":"","sources":["../../../src/core/supervisor/plan-types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,8BAA8B,EAAG,CAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"plan-types.d.ts","sourceRoot":"","sources":["../../../src/core/supervisor/plan-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planning.d.ts","sourceRoot":"","sources":["../../../src/core/supervisor/planning.ts"],"names":[],"mappings":"AAcA,OAAO,
|
|
1
|
+
{"version":3,"file":"planning.d.ts","sourceRoot":"","sources":["../../../src/core/supervisor/planning.ts"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,UAAU,EAOhB,MAAM,sBAAsB,CAAC;AAM9B,OAAO,EAIL,KAAK,qBAAqB,EAU3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQnD,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,WAAW,GAAG,OAAO,GAAG,aAAa,GAAG,aAAa,CAAC,CAAC;IAChF,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,qBAAqB,CAAC,CA+LhC;AAuLD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,qBAAqB,CAsHxB;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,qBAAqB,CAYxB"}
|