pi-harness-runtime 1.1.356 → 1.1.358
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 +11 -0
- 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 +87 -0
- package/packages/jev-judge/dist/delegation-harness.d.ts.map +1 -0
- package/packages/jev-judge/dist/delegation-harness.js +208 -0
- package/packages/jev-judge/dist/delegation-harness.js.map +1 -0
- package/packages/jev-judge/package.json +1 -1
- package/packages/jev-judge/src/delegation-harness.ts +329 -0
- 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
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation Harness Integration
|
|
3
|
+
*
|
|
4
|
+
* Connects delegation assessment to the harness runtime.
|
|
5
|
+
* Uses inline types to avoid cross-package dependency.
|
|
6
|
+
*/
|
|
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"];
|
|
61
|
+
/**
|
|
62
|
+
* Create delegation harness integration
|
|
63
|
+
*/
|
|
64
|
+
export function createDelegationHarness(pi, config = {}) {
|
|
65
|
+
const state = {
|
|
66
|
+
currentReceipt: null,
|
|
67
|
+
capability: null,
|
|
68
|
+
lastAssessment: null,
|
|
69
|
+
};
|
|
70
|
+
const minFiles = config.minFiles ?? 10;
|
|
71
|
+
const minCallSites = config.minCallSites ?? 50;
|
|
72
|
+
const minComponents = config.minComponents ?? 2;
|
|
73
|
+
/**
|
|
74
|
+
* Discover and cache delegation capability
|
|
75
|
+
*/
|
|
76
|
+
async function discoverCapability() {
|
|
77
|
+
if (state.capability)
|
|
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
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Check if delegation assessment should be triggered
|
|
103
|
+
*/
|
|
104
|
+
function shouldAssess(facts) {
|
|
105
|
+
if (facts.observedFiles >= minFiles)
|
|
106
|
+
return true;
|
|
107
|
+
if (facts.observedCallSites >= minCallSites)
|
|
108
|
+
return true;
|
|
109
|
+
if (facts.independentComponents >= minComponents)
|
|
110
|
+
return true;
|
|
111
|
+
return false;
|
|
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
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Assess delegation for given scope facts
|
|
162
|
+
*/
|
|
163
|
+
async function assess(facts, parentTaskId) {
|
|
164
|
+
if (!shouldAssess(facts))
|
|
165
|
+
return null;
|
|
166
|
+
const workspacePath = process.cwd();
|
|
167
|
+
// Check existing receipt
|
|
168
|
+
if (hasReceipt(workspacePath, parentTaskId)) {
|
|
169
|
+
const existing = loadReceipt(workspacePath, parentTaskId);
|
|
170
|
+
if (existing && existing.scopeFingerprint === facts.fingerprint) {
|
|
171
|
+
state.currentReceipt = existing;
|
|
172
|
+
return existing.decision;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const capability = await discoverCapability();
|
|
176
|
+
const decision = makeDeterministicAssessment(facts, capability);
|
|
177
|
+
state.lastAssessment = decision;
|
|
178
|
+
const receipt = {
|
|
179
|
+
version: 1,
|
|
180
|
+
workspacePath,
|
|
181
|
+
sessionId: pi.getSessionName?.() ?? "unknown",
|
|
182
|
+
parentTaskId,
|
|
183
|
+
scopeFingerprint: facts.fingerprint,
|
|
184
|
+
decision,
|
|
185
|
+
createdAt: Date.now(),
|
|
186
|
+
updatedAt: Date.now(),
|
|
187
|
+
status: "assessing",
|
|
188
|
+
childIds: [],
|
|
189
|
+
pendingValidation: [],
|
|
190
|
+
userConstraints: [],
|
|
191
|
+
};
|
|
192
|
+
saveReceipt(receipt);
|
|
193
|
+
state.currentReceipt = receipt;
|
|
194
|
+
return decision;
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
discoverCapability,
|
|
198
|
+
shouldAssess,
|
|
199
|
+
assess,
|
|
200
|
+
getReceipt: () => state.currentReceipt,
|
|
201
|
+
getLastDecision: () => state.lastAssessment,
|
|
202
|
+
clear: () => {
|
|
203
|
+
state.currentReceipt = null;
|
|
204
|
+
state.lastAssessment = null;
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=delegation-harness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegation-harness.js","sourceRoot":"","sources":["../src/delegation-harness.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAuE5B;;GAEG;AACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,cAAc,EAAE,qBAAqB,EAAE,kBAAkB,CAAC,CAAC;AAEtG;;GAEG;AACH,SAAS,cAAc;IACrB,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,aAAqB,EAAE,MAAc;IAC3D,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;IAC3E,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,SAAS,EAAE,GAAG,QAAQ,KAAK,QAAQ,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,OAA0B;IAC7C,cAAc,EAAE,CAAC;IACjB,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IACzE,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AAChE,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,aAAqB,EAAE,MAAc;IACxD,MAAM,IAAI,GAAG,cAAc,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAsB,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,UAAU,CAAC,aAAqB,EAAE,MAAc;IACvD,OAAO,UAAU,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;AAC3D,CAAC;AAoBD;;GAEG;AACH,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC,CAAC;AAEzE;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,EAAgB,EAChB,MAAM,GAA4B,EAAE;IAEpC,MAAM,KAAK,GAAoB;QAC7B,cAAc,EAAE,IAAI;QACpB,UAAU,EAAE,IAAI;QAChB,cAAc,EAAE,IAAI;KACrB,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACvC,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;IAC/C,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,IAAI,CAAC,CAAC;IAEhD;;OAEG;IACH,KAAK,UAAU,kBAAkB;QAC/B,IAAI,KAAK,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC,UAAU,CAAC;QAE9C,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,EAAE,CAAC,WAAW,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC9C,MAAM,WAAW,GAAG,EAAE,CAAC,cAAc,EAAE,CAAC;YAExC,MAAM,eAAe,GAAG,cAAc,CAAC,IAAI,CACzC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,CACjE,CAAC;YAEF,IAAI,eAAe,EAAE,CAAC;gBACpB,KAAK,CAAC,UAAU,GAAG;oBACjB,IAAI,EAAE,oBAAoB;oBAC1B,iBAAiB,EAAE,IAAI;oBACvB,qBAAqB,EAAE,IAAI;oBAC3B,oBAAoB,EAAE,IAAI;oBAC1B,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CACvC,cAAc,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAC5C;oBACD,QAAQ,EAAE,IAAI;iBACf,CAAC;gBACF,OAAO,KAAK,CAAC,UAAU,CAAC;YAC1B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,mBAAmB;QACrB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;OAEG;IACH,SAAS,YAAY,CAAC,KAAiB;QACrC,IAAI,KAAK,CAAC,aAAa,IAAI,QAAQ;YAAE,OAAO,IAAI,CAAC;QACjD,IAAI,KAAK,CAAC,iBAAiB,IAAI,YAAY;YAAE,OAAO,IAAI,CAAC;QACzD,IAAI,KAAK,CAAC,qBAAqB,IAAI,aAAa;YAAE,OAAO,IAAI,CAAC;QAC9D,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;OAEG;IACH,SAAS,2BAA2B,CAClC,KAAiB,EACjB,UAAsC;QAEtC,IAAI,CAAC,UAAU,EAAE,QAAQ,EAAE,CAAC;YAC1B,OAAO;gBACL,QAAQ,EAAE,aAAa;gBACvB,MAAM,EAAE,kCAAkC;gBAC1C,UAAU,EAAE,EAAE;gBACd,sBAAsB,EAAE,2BAA2B;gBACnD,UAAU,EAAE,MAAM;gBAClB,OAAO,EAAE,KAAK;gBACd,oBAAoB,EAAE,CAAC,qBAAqB,CAAC;aAC9C,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YAC3C,OAAO;gBACL,QAAQ,EAAE,aAAa;gBACvB,MAAM,EAAE,2BAA2B;gBACnC,UAAU,EAAE,EAAE;gBACd,sBAAsB,EAAE,0BAA0B;gBAClD,UAAU,EAAE,MAAM;gBAClB,OAAO,EAAE,KAAK;gBACd,oBAAoB,EAAE,CAAC,2BAA2B,CAAC;aACpD,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,CAAC,qBAAqB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;YAC9D,OAAO;gBACL,QAAQ,EAAE,UAAU;gBACpB,MAAM,EAAE,GAAG,KAAK,CAAC,qBAAqB,yBAAyB;gBAC/D,UAAU,EAAE,EAAE;gBACd,sBAAsB,EAAE,uCAAuC;gBAC/D,UAAU,EAAE,QAAQ;gBACpB,OAAO,EAAE,KAAK;gBACd,oBAAoB,EAAE,CAAC,eAAe,EAAE,qBAAqB,CAAC;aAC/D,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,cAAc;YACxB,MAAM,EAAE,yBAAyB;YACjC,UAAU,EAAE,EAAE;YACd,sBAAsB,EAAE,kBAAkB;YAC1C,UAAU,EAAE,KAAK;YACjB,OAAO,EAAE,KAAK;YACd,oBAAoB,EAAE,CAAC,yBAAyB,CAAC;SAClD,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,UAAU,MAAM,CACnB,KAAiB,EACjB,YAAoB;QAEpB,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEtC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAEpC,yBAAyB;QACzB,IAAI,UAAU,CAAC,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC;YAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;YAC1D,IAAI,QAAQ,IAAI,QAAQ,CAAC,gBAAgB,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;gBAChE,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;gBAChC,OAAO,QAAQ,CAAC,QAAQ,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,2BAA2B,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAChE,KAAK,CAAC,cAAc,GAAG,QAAQ,CAAC;QAEhC,MAAM,OAAO,GAAsB;YACjC,OAAO,EAAE,CAAC;YACV,aAAa;YACb,SAAS,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,IAAI,SAAS;YAC7C,YAAY;YACZ,gBAAgB,EAAE,KAAK,CAAC,WAAW;YACnC,QAAQ;YACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,MAAM,EAAE,WAAW;YACnB,QAAQ,EAAE,EAAE;YACZ,iBAAiB,EAAE,EAAE;YACrB,eAAe,EAAE,EAAE;SACpB,CAAC;QAEF,WAAW,CAAC,OAAO,CAAC,CAAC;QACrB,KAAK,CAAC,cAAc,GAAG,OAAO,CAAC;QAC/B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO;QACL,kBAAkB;QAClB,YAAY;QACZ,MAAM;QACN,UAAU,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc;QACtC,eAAe,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,cAAc;QAC3C,KAAK,EAAE,GAAG,EAAE;YACV,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;YAC5B,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC;QAC9B,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation Harness Integration
|
|
3
|
+
*
|
|
4
|
+
* Connects delegation assessment to the harness runtime.
|
|
5
|
+
* Uses inline types to avoid cross-package dependency.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
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
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Delegation harness configuration
|
|
135
|
+
*/
|
|
136
|
+
export interface DelegationHarnessConfig {
|
|
137
|
+
minFiles?: number;
|
|
138
|
+
minCallSites?: number;
|
|
139
|
+
minComponents?: number;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Delegation harness state
|
|
144
|
+
*/
|
|
145
|
+
interface DelegationState {
|
|
146
|
+
currentReceipt: DelegationReceipt | null;
|
|
147
|
+
capability: ExtensionCapability | null;
|
|
148
|
+
lastAssessment: DelegationDecision | null;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Sub-agent tool names
|
|
153
|
+
*/
|
|
154
|
+
const SUBAGENT_TOOLS = ["subagent", "spawn", "delegate", "run_subagent"];
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Create delegation harness integration
|
|
158
|
+
*/
|
|
159
|
+
export function createDelegationHarness(
|
|
160
|
+
pi: ExtensionAPI,
|
|
161
|
+
config: DelegationHarnessConfig = {}
|
|
162
|
+
) {
|
|
163
|
+
const state: DelegationState = {
|
|
164
|
+
currentReceipt: null,
|
|
165
|
+
capability: null,
|
|
166
|
+
lastAssessment: null,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const minFiles = config.minFiles ?? 10;
|
|
170
|
+
const minCallSites = config.minCallSites ?? 50;
|
|
171
|
+
const minComponents = config.minComponents ?? 2;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Discover and cache delegation capability
|
|
175
|
+
*/
|
|
176
|
+
async function discoverCapability(): Promise<ExtensionCapability | null> {
|
|
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
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Check if delegation assessment should be triggered
|
|
210
|
+
*/
|
|
211
|
+
function shouldAssess(facts: ScopeFacts): boolean {
|
|
212
|
+
if (facts.observedFiles >= minFiles) return true;
|
|
213
|
+
if (facts.observedCallSites >= minCallSites) return true;
|
|
214
|
+
if (facts.independentComponents >= minComponents) return true;
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
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
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Assess delegation for given scope facts
|
|
274
|
+
*/
|
|
275
|
+
async function assess(
|
|
276
|
+
facts: ScopeFacts,
|
|
277
|
+
parentTaskId: string
|
|
278
|
+
): Promise<DelegationDecision | null> {
|
|
279
|
+
if (!shouldAssess(facts)) return null;
|
|
280
|
+
|
|
281
|
+
const workspacePath = process.cwd();
|
|
282
|
+
|
|
283
|
+
// Check existing receipt
|
|
284
|
+
if (hasReceipt(workspacePath, parentTaskId)) {
|
|
285
|
+
const existing = loadReceipt(workspacePath, parentTaskId);
|
|
286
|
+
if (existing && existing.scopeFingerprint === facts.fingerprint) {
|
|
287
|
+
state.currentReceipt = existing;
|
|
288
|
+
return existing.decision;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const capability = await discoverCapability();
|
|
293
|
+
const decision = makeDeterministicAssessment(facts, capability);
|
|
294
|
+
state.lastAssessment = decision;
|
|
295
|
+
|
|
296
|
+
const receipt: DelegationReceipt = {
|
|
297
|
+
version: 1,
|
|
298
|
+
workspacePath,
|
|
299
|
+
sessionId: pi.getSessionName?.() ?? "unknown",
|
|
300
|
+
parentTaskId,
|
|
301
|
+
scopeFingerprint: facts.fingerprint,
|
|
302
|
+
decision,
|
|
303
|
+
createdAt: Date.now(),
|
|
304
|
+
updatedAt: Date.now(),
|
|
305
|
+
status: "assessing",
|
|
306
|
+
childIds: [],
|
|
307
|
+
pendingValidation: [],
|
|
308
|
+
userConstraints: [],
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
saveReceipt(receipt);
|
|
312
|
+
state.currentReceipt = receipt;
|
|
313
|
+
return decision;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
discoverCapability,
|
|
318
|
+
shouldAssess,
|
|
319
|
+
assess,
|
|
320
|
+
getReceipt: () => state.currentReceipt,
|
|
321
|
+
getLastDecision: () => state.lastAssessment,
|
|
322
|
+
clear: () => {
|
|
323
|
+
state.currentReceipt = null;
|
|
324
|
+
state.lastAssessment = null;
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export type DelegationHarness = ReturnType<typeof createDelegationHarness>;
|