pi-harness-runtime 1.1.357 → 1.1.359
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 +1 -1
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/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/codex-watcher/package.json +1 -1
- package/packages/config-capture/package.json +1 -1
- package/packages/connection-runtime/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/contracts/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/durable-review/package.json +1 -1
- package/packages/e2e-tester/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-sink/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/dist/delegation-harness.d.ts +60 -6
- package/packages/jev-judge/dist/delegation-harness.d.ts.map +1 -1
- package/packages/jev-judge/dist/delegation-harness.js +133 -37
- package/packages/jev-judge/dist/delegation-harness.js.map +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/jev-judge/src/delegation-harness.ts +222 -57
- 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/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/permission-mode/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/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/relay/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/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/telegram/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/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/voice-api/package.json +1 -1
- package/packages/webmcp-tester/package.json +1 -1
- package/packages/wiki/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 +1 -1
|
@@ -2,9 +2,62 @@
|
|
|
2
2
|
* Delegation Harness Integration
|
|
3
3
|
*
|
|
4
4
|
* Connects delegation assessment to the harness runtime.
|
|
5
|
+
* Uses inline types to avoid cross-package dependency.
|
|
5
6
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
8
|
+
import { join } from "path";
|
|
9
|
+
/**
|
|
10
|
+
* Store directory path
|
|
11
|
+
*/
|
|
12
|
+
const STORE_DIR = join(process.env.HOME || "/home/frappe", ".pi-harness-runtime", "delegation-state");
|
|
13
|
+
/**
|
|
14
|
+
* Ensure store directory exists
|
|
15
|
+
*/
|
|
16
|
+
function ensureStoreDir() {
|
|
17
|
+
if (!existsSync(STORE_DIR)) {
|
|
18
|
+
mkdirSync(STORE_DIR, { recursive: true });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get receipt file path
|
|
23
|
+
*/
|
|
24
|
+
function getReceiptPath(workspacePath, taskId) {
|
|
25
|
+
const safePath = workspacePath.replace(/[^a-zA-Z0-9_-]/g, "_").slice(-100);
|
|
26
|
+
const safeTask = taskId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
27
|
+
return join(STORE_DIR, `${safePath}__${safeTask}.json`);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Save delegation receipt
|
|
31
|
+
*/
|
|
32
|
+
function saveReceipt(receipt) {
|
|
33
|
+
ensureStoreDir();
|
|
34
|
+
const path = getReceiptPath(receipt.workspacePath, receipt.parentTaskId);
|
|
35
|
+
writeFileSync(path, JSON.stringify(receipt, null, 2), "utf8");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Load delegation receipt
|
|
39
|
+
*/
|
|
40
|
+
function loadReceipt(workspacePath, taskId) {
|
|
41
|
+
const path = getReceiptPath(workspacePath, taskId);
|
|
42
|
+
if (!existsSync(path))
|
|
43
|
+
return null;
|
|
44
|
+
try {
|
|
45
|
+
return JSON.parse(readFileSync(path, "utf8"));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if receipt exists
|
|
53
|
+
*/
|
|
54
|
+
function hasReceipt(workspacePath, taskId) {
|
|
55
|
+
return existsSync(getReceiptPath(workspacePath, taskId));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Sub-agent tool names
|
|
59
|
+
*/
|
|
60
|
+
const SUBAGENT_TOOLS = ["subagent", "spawn", "delegate", "run_subagent"];
|
|
8
61
|
/**
|
|
9
62
|
* Create delegation harness integration
|
|
10
63
|
*/
|
|
@@ -21,11 +74,29 @@ export function createDelegationHarness(pi, config = {}) {
|
|
|
21
74
|
* Discover and cache delegation capability
|
|
22
75
|
*/
|
|
23
76
|
async function discoverCapability() {
|
|
24
|
-
if (state.capability)
|
|
77
|
+
if (state.capability)
|
|
25
78
|
return state.capability;
|
|
79
|
+
try {
|
|
80
|
+
const allTools = pi.getAllTools();
|
|
81
|
+
const toolNames = allTools.map((t) => t.name);
|
|
82
|
+
const activeTools = pi.getActiveTools();
|
|
83
|
+
const hasSubagentTool = SUBAGENT_TOOLS.some((tool) => toolNames.includes(tool) || activeTools.includes(tool));
|
|
84
|
+
if (hasSubagentTool) {
|
|
85
|
+
state.capability = {
|
|
86
|
+
name: "subagent-extension",
|
|
87
|
+
supportsSubagents: true,
|
|
88
|
+
supportsWorkIsolation: true,
|
|
89
|
+
supportsCancellation: true,
|
|
90
|
+
availableTools: activeTools.filter((t) => SUBAGENT_TOOLS.some((st) => t.includes(st))),
|
|
91
|
+
verified: true,
|
|
92
|
+
};
|
|
93
|
+
return state.capability;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Discovery failed
|
|
26
98
|
}
|
|
27
|
-
|
|
28
|
-
return state.capability;
|
|
99
|
+
return null;
|
|
29
100
|
}
|
|
30
101
|
/**
|
|
31
102
|
* Check if delegation assessment should be triggered
|
|
@@ -39,29 +110,71 @@ export function createDelegationHarness(pi, config = {}) {
|
|
|
39
110
|
return true;
|
|
40
111
|
return false;
|
|
41
112
|
}
|
|
113
|
+
/**
|
|
114
|
+
* Make deterministic assessment
|
|
115
|
+
*/
|
|
116
|
+
function makeDeterministicAssessment(facts, capability) {
|
|
117
|
+
if (!capability?.verified) {
|
|
118
|
+
return {
|
|
119
|
+
strategy: "unavailable",
|
|
120
|
+
reason: "No verified sub-agent capability",
|
|
121
|
+
workGroups: [],
|
|
122
|
+
validationExpectations: "Parent handles validation",
|
|
123
|
+
confidence: "high",
|
|
124
|
+
jevUsed: false,
|
|
125
|
+
reassessmentTriggers: ["Extension available"],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
if (facts.isMechanical && !facts.isComplex) {
|
|
129
|
+
return {
|
|
130
|
+
strategy: "script_only",
|
|
131
|
+
reason: "Mechanical transformation",
|
|
132
|
+
workGroups: [],
|
|
133
|
+
validationExpectations: "Script output validation",
|
|
134
|
+
confidence: "high",
|
|
135
|
+
jevUsed: false,
|
|
136
|
+
reassessmentTriggers: ["Transformation unreliable"],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
if (facts.independentComponents >= 2 && !facts.tightlyCoupled) {
|
|
140
|
+
return {
|
|
141
|
+
strategy: "delegate",
|
|
142
|
+
reason: `${facts.independentComponents} independent components`,
|
|
143
|
+
workGroups: [],
|
|
144
|
+
validationExpectations: "Each group validated, then integrated",
|
|
145
|
+
confidence: "medium",
|
|
146
|
+
jevUsed: false,
|
|
147
|
+
reassessmentTriggers: ["Scope expands", "Coupling discovered"],
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
strategy: "single_agent",
|
|
152
|
+
reason: "Default to single agent",
|
|
153
|
+
workGroups: [],
|
|
154
|
+
validationExpectations: "Parent validates",
|
|
155
|
+
confidence: "low",
|
|
156
|
+
jevUsed: false,
|
|
157
|
+
reassessmentTriggers: ["Scope exceeds threshold"],
|
|
158
|
+
};
|
|
159
|
+
}
|
|
42
160
|
/**
|
|
43
161
|
* Assess delegation for given scope facts
|
|
44
162
|
*/
|
|
45
163
|
async function assess(facts, parentTaskId) {
|
|
46
|
-
|
|
47
|
-
if (!shouldAssess(facts)) {
|
|
164
|
+
if (!shouldAssess(facts))
|
|
48
165
|
return null;
|
|
49
|
-
}
|
|
50
|
-
// Check for existing receipt (avoid reassessment)
|
|
51
166
|
const workspacePath = process.cwd();
|
|
167
|
+
// Check existing receipt
|
|
52
168
|
if (hasReceipt(workspacePath, parentTaskId)) {
|
|
53
|
-
const existing =
|
|
169
|
+
const existing = loadReceipt(workspacePath, parentTaskId);
|
|
54
170
|
if (existing && existing.scopeFingerprint === facts.fingerprint) {
|
|
55
171
|
state.currentReceipt = existing;
|
|
56
172
|
return existing.decision;
|
|
57
173
|
}
|
|
58
174
|
}
|
|
59
|
-
// Discover capability
|
|
60
175
|
const capability = await discoverCapability();
|
|
61
|
-
// Make assessment
|
|
62
176
|
const decision = makeDeterministicAssessment(facts, capability);
|
|
63
177
|
state.lastAssessment = decision;
|
|
64
|
-
// Create receipt
|
|
65
178
|
const receipt = {
|
|
66
179
|
version: 1,
|
|
67
180
|
workspacePath,
|
|
@@ -76,37 +189,20 @@ export function createDelegationHarness(pi, config = {}) {
|
|
|
76
189
|
pendingValidation: [],
|
|
77
190
|
userConstraints: [],
|
|
78
191
|
};
|
|
79
|
-
|
|
80
|
-
saveDelegationReceipt(receipt);
|
|
192
|
+
saveReceipt(receipt);
|
|
81
193
|
state.currentReceipt = receipt;
|
|
82
194
|
return decision;
|
|
83
195
|
}
|
|
84
|
-
/**
|
|
85
|
-
* Get current receipt
|
|
86
|
-
*/
|
|
87
|
-
function getReceipt() {
|
|
88
|
-
return state.currentReceipt;
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Get current assessment decision
|
|
92
|
-
*/
|
|
93
|
-
function getLastDecision() {
|
|
94
|
-
return state.lastAssessment;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Clear cached state (on session switch)
|
|
98
|
-
*/
|
|
99
|
-
function clear() {
|
|
100
|
-
state.currentReceipt = null;
|
|
101
|
-
state.lastAssessment = null;
|
|
102
|
-
}
|
|
103
196
|
return {
|
|
104
197
|
discoverCapability,
|
|
105
198
|
shouldAssess,
|
|
106
199
|
assess,
|
|
107
|
-
getReceipt,
|
|
108
|
-
getLastDecision,
|
|
109
|
-
clear
|
|
200
|
+
getReceipt: () => state.currentReceipt,
|
|
201
|
+
getLastDecision: () => state.lastAssessment,
|
|
202
|
+
clear: () => {
|
|
203
|
+
state.currentReceipt = null;
|
|
204
|
+
state.lastAssessment = null;
|
|
205
|
+
},
|
|
110
206
|
};
|
|
111
207
|
}
|
|
112
208
|
//# sourceMappingURL=delegation-harness.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegation-harness.js","sourceRoot":"","sources":["../src/delegation-harness.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"delegation-harness.js","sourceRoot":"","sources":["../src/delegation-harness.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,31 +2,140 @@
|
|
|
2
2
|
* Delegation Harness Integration
|
|
3
3
|
*
|
|
4
4
|
* Connects delegation assessment to the harness runtime.
|
|
5
|
+
* Uses inline types to avoid cross-package dependency.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
8
|
-
import
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Extension capability for delegation (inline to avoid dependency)
|
|
14
|
+
*/
|
|
15
|
+
export interface ExtensionCapability {
|
|
16
|
+
name: string;
|
|
17
|
+
supportsSubagents: boolean;
|
|
18
|
+
supportsWorkIsolation: boolean;
|
|
19
|
+
supportsCancellation: boolean;
|
|
20
|
+
availableTools: string[];
|
|
21
|
+
verified: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Delegation strategy decision
|
|
26
|
+
*/
|
|
27
|
+
export type DelegationStrategy =
|
|
28
|
+
| "delegate"
|
|
29
|
+
| "script_then_delegate"
|
|
30
|
+
| "script_only"
|
|
31
|
+
| "single_agent"
|
|
32
|
+
| "unavailable";
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Delegation decision
|
|
36
|
+
*/
|
|
37
|
+
export interface DelegationDecision {
|
|
38
|
+
strategy: DelegationStrategy;
|
|
39
|
+
reason: string;
|
|
40
|
+
workGroups: unknown[];
|
|
41
|
+
validationExpectations: string;
|
|
42
|
+
confidence: "high" | "medium" | "low";
|
|
43
|
+
jevUsed: boolean;
|
|
44
|
+
reassessmentTriggers: string[];
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Scope facts
|
|
49
|
+
*/
|
|
50
|
+
export interface ScopeFacts {
|
|
51
|
+
estimatedFiles: number;
|
|
52
|
+
observedFiles: number;
|
|
53
|
+
estimatedCallSites: number;
|
|
54
|
+
observedCallSites: number;
|
|
55
|
+
independentComponents: number;
|
|
56
|
+
tightlyCoupled: boolean;
|
|
57
|
+
isMechanical: boolean;
|
|
58
|
+
isComplex: boolean;
|
|
59
|
+
fileTypes: Record<string, number>;
|
|
60
|
+
fingerprint: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Delegation receipt
|
|
65
|
+
*/
|
|
66
|
+
export interface DelegationReceipt {
|
|
67
|
+
version: number;
|
|
68
|
+
workspacePath: string;
|
|
69
|
+
sessionId: string;
|
|
70
|
+
parentTaskId: string;
|
|
71
|
+
scopeFingerprint: string;
|
|
72
|
+
decision: DelegationDecision;
|
|
73
|
+
createdAt: number;
|
|
74
|
+
updatedAt: number;
|
|
75
|
+
status: "assessing" | "in_progress" | "completed" | "failed" | "cancelled";
|
|
76
|
+
childIds: string[];
|
|
77
|
+
pendingValidation: string[];
|
|
78
|
+
userConstraints: string[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Store directory path
|
|
83
|
+
*/
|
|
84
|
+
const STORE_DIR = join(process.env.HOME || "/home/frappe", ".pi-harness-runtime", "delegation-state");
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Ensure store directory exists
|
|
88
|
+
*/
|
|
89
|
+
function ensureStoreDir(): void {
|
|
90
|
+
if (!existsSync(STORE_DIR)) {
|
|
91
|
+
mkdirSync(STORE_DIR, { recursive: true });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Get receipt file path
|
|
97
|
+
*/
|
|
98
|
+
function getReceiptPath(workspacePath: string, taskId: string): string {
|
|
99
|
+
const safePath = workspacePath.replace(/[^a-zA-Z0-9_-]/g, "_").slice(-100);
|
|
100
|
+
const safeTask = taskId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
101
|
+
return join(STORE_DIR, `${safePath}__${safeTask}.json`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Save delegation receipt
|
|
106
|
+
*/
|
|
107
|
+
function saveReceipt(receipt: DelegationReceipt): void {
|
|
108
|
+
ensureStoreDir();
|
|
109
|
+
const path = getReceiptPath(receipt.workspacePath, receipt.parentTaskId);
|
|
110
|
+
writeFileSync(path, JSON.stringify(receipt, null, 2), "utf8");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Load delegation receipt
|
|
115
|
+
*/
|
|
116
|
+
function loadReceipt(workspacePath: string, taskId: string): DelegationReceipt | null {
|
|
117
|
+
const path = getReceiptPath(workspacePath, taskId);
|
|
118
|
+
if (!existsSync(path)) return null;
|
|
119
|
+
try {
|
|
120
|
+
return JSON.parse(readFileSync(path, "utf8")) as DelegationReceipt;
|
|
121
|
+
} catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if receipt exists
|
|
128
|
+
*/
|
|
129
|
+
function hasReceipt(workspacePath: string, taskId: string): boolean {
|
|
130
|
+
return existsSync(getReceiptPath(workspacePath, taskId));
|
|
131
|
+
}
|
|
20
132
|
|
|
21
133
|
/**
|
|
22
134
|
* Delegation harness configuration
|
|
23
135
|
*/
|
|
24
136
|
export interface DelegationHarnessConfig {
|
|
25
|
-
/** Minimum files to trigger assessment */
|
|
26
137
|
minFiles?: number;
|
|
27
|
-
/** Minimum call sites to trigger assessment */
|
|
28
138
|
minCallSites?: number;
|
|
29
|
-
/** Minimum independent components for delegation */
|
|
30
139
|
minComponents?: number;
|
|
31
140
|
}
|
|
32
141
|
|
|
@@ -39,6 +148,11 @@ interface DelegationState {
|
|
|
39
148
|
lastAssessment: DelegationDecision | null;
|
|
40
149
|
}
|
|
41
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Sub-agent tool names
|
|
153
|
+
*/
|
|
154
|
+
const SUBAGENT_TOOLS = ["subagent", "spawn", "delegate", "run_subagent"];
|
|
155
|
+
|
|
42
156
|
/**
|
|
43
157
|
* Create delegation harness integration
|
|
44
158
|
*/
|
|
@@ -60,11 +174,35 @@ export function createDelegationHarness(
|
|
|
60
174
|
* Discover and cache delegation capability
|
|
61
175
|
*/
|
|
62
176
|
async function discoverCapability(): Promise<ExtensionCapability | null> {
|
|
63
|
-
if (state.capability)
|
|
64
|
-
|
|
177
|
+
if (state.capability) return state.capability;
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
const allTools = pi.getAllTools();
|
|
181
|
+
const toolNames = allTools.map((t) => t.name);
|
|
182
|
+
const activeTools = pi.getActiveTools();
|
|
183
|
+
|
|
184
|
+
const hasSubagentTool = SUBAGENT_TOOLS.some(
|
|
185
|
+
(tool) => toolNames.includes(tool) || activeTools.includes(tool)
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (hasSubagentTool) {
|
|
189
|
+
state.capability = {
|
|
190
|
+
name: "subagent-extension",
|
|
191
|
+
supportsSubagents: true,
|
|
192
|
+
supportsWorkIsolation: true,
|
|
193
|
+
supportsCancellation: true,
|
|
194
|
+
availableTools: activeTools.filter((t) =>
|
|
195
|
+
SUBAGENT_TOOLS.some((st) => t.includes(st))
|
|
196
|
+
),
|
|
197
|
+
verified: true,
|
|
198
|
+
};
|
|
199
|
+
return state.capability;
|
|
200
|
+
}
|
|
201
|
+
} catch {
|
|
202
|
+
// Discovery failed
|
|
65
203
|
}
|
|
66
|
-
|
|
67
|
-
return
|
|
204
|
+
|
|
205
|
+
return null;
|
|
68
206
|
}
|
|
69
207
|
|
|
70
208
|
/**
|
|
@@ -77,6 +215,60 @@ export function createDelegationHarness(
|
|
|
77
215
|
return false;
|
|
78
216
|
}
|
|
79
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Make deterministic assessment
|
|
220
|
+
*/
|
|
221
|
+
function makeDeterministicAssessment(
|
|
222
|
+
facts: ScopeFacts,
|
|
223
|
+
capability: ExtensionCapability | null
|
|
224
|
+
): DelegationDecision {
|
|
225
|
+
if (!capability?.verified) {
|
|
226
|
+
return {
|
|
227
|
+
strategy: "unavailable",
|
|
228
|
+
reason: "No verified sub-agent capability",
|
|
229
|
+
workGroups: [],
|
|
230
|
+
validationExpectations: "Parent handles validation",
|
|
231
|
+
confidence: "high",
|
|
232
|
+
jevUsed: false,
|
|
233
|
+
reassessmentTriggers: ["Extension available"],
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (facts.isMechanical && !facts.isComplex) {
|
|
238
|
+
return {
|
|
239
|
+
strategy: "script_only",
|
|
240
|
+
reason: "Mechanical transformation",
|
|
241
|
+
workGroups: [],
|
|
242
|
+
validationExpectations: "Script output validation",
|
|
243
|
+
confidence: "high",
|
|
244
|
+
jevUsed: false,
|
|
245
|
+
reassessmentTriggers: ["Transformation unreliable"],
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (facts.independentComponents >= 2 && !facts.tightlyCoupled) {
|
|
250
|
+
return {
|
|
251
|
+
strategy: "delegate",
|
|
252
|
+
reason: `${facts.independentComponents} independent components`,
|
|
253
|
+
workGroups: [],
|
|
254
|
+
validationExpectations: "Each group validated, then integrated",
|
|
255
|
+
confidence: "medium",
|
|
256
|
+
jevUsed: false,
|
|
257
|
+
reassessmentTriggers: ["Scope expands", "Coupling discovered"],
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return {
|
|
262
|
+
strategy: "single_agent",
|
|
263
|
+
reason: "Default to single agent",
|
|
264
|
+
workGroups: [],
|
|
265
|
+
validationExpectations: "Parent validates",
|
|
266
|
+
confidence: "low",
|
|
267
|
+
jevUsed: false,
|
|
268
|
+
reassessmentTriggers: ["Scope exceeds threshold"],
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
|
|
80
272
|
/**
|
|
81
273
|
* Assess delegation for given scope facts
|
|
82
274
|
*/
|
|
@@ -84,29 +276,23 @@ export function createDelegationHarness(
|
|
|
84
276
|
facts: ScopeFacts,
|
|
85
277
|
parentTaskId: string
|
|
86
278
|
): Promise<DelegationDecision | null> {
|
|
87
|
-
|
|
88
|
-
if (!shouldAssess(facts)) {
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
279
|
+
if (!shouldAssess(facts)) return null;
|
|
91
280
|
|
|
92
|
-
// Check for existing receipt (avoid reassessment)
|
|
93
281
|
const workspacePath = process.cwd();
|
|
282
|
+
|
|
283
|
+
// Check existing receipt
|
|
94
284
|
if (hasReceipt(workspacePath, parentTaskId)) {
|
|
95
|
-
const existing =
|
|
285
|
+
const existing = loadReceipt(workspacePath, parentTaskId);
|
|
96
286
|
if (existing && existing.scopeFingerprint === facts.fingerprint) {
|
|
97
287
|
state.currentReceipt = existing;
|
|
98
288
|
return existing.decision;
|
|
99
289
|
}
|
|
100
290
|
}
|
|
101
291
|
|
|
102
|
-
// Discover capability
|
|
103
292
|
const capability = await discoverCapability();
|
|
104
|
-
|
|
105
|
-
// Make assessment
|
|
106
293
|
const decision = makeDeterministicAssessment(facts, capability);
|
|
107
294
|
state.lastAssessment = decision;
|
|
108
295
|
|
|
109
|
-
// Create receipt
|
|
110
296
|
const receipt: DelegationReceipt = {
|
|
111
297
|
version: 1,
|
|
112
298
|
workspacePath,
|
|
@@ -122,42 +308,21 @@ export function createDelegationHarness(
|
|
|
122
308
|
userConstraints: [],
|
|
123
309
|
};
|
|
124
310
|
|
|
125
|
-
|
|
126
|
-
saveDelegationReceipt(receipt);
|
|
311
|
+
saveReceipt(receipt);
|
|
127
312
|
state.currentReceipt = receipt;
|
|
128
|
-
|
|
129
313
|
return decision;
|
|
130
314
|
}
|
|
131
315
|
|
|
132
|
-
/**
|
|
133
|
-
* Get current receipt
|
|
134
|
-
*/
|
|
135
|
-
function getReceipt(): DelegationReceipt | null {
|
|
136
|
-
return state.currentReceipt;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Get current assessment decision
|
|
141
|
-
*/
|
|
142
|
-
function getLastDecision(): DelegationDecision | null {
|
|
143
|
-
return state.lastAssessment;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Clear cached state (on session switch)
|
|
148
|
-
*/
|
|
149
|
-
function clear(): void {
|
|
150
|
-
state.currentReceipt = null;
|
|
151
|
-
state.lastAssessment = null;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
316
|
return {
|
|
155
317
|
discoverCapability,
|
|
156
318
|
shouldAssess,
|
|
157
319
|
assess,
|
|
158
|
-
getReceipt,
|
|
159
|
-
getLastDecision,
|
|
160
|
-
clear
|
|
320
|
+
getReceipt: () => state.currentReceipt,
|
|
321
|
+
getLastDecision: () => state.lastAssessment,
|
|
322
|
+
clear: () => {
|
|
323
|
+
state.currentReceipt = null;
|
|
324
|
+
state.lastAssessment = null;
|
|
325
|
+
},
|
|
161
326
|
};
|
|
162
327
|
}
|
|
163
328
|
|