@polderlabs/bizar-omp 0.8.0 → 0.8.1
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 +42 -6
- package/agents/bizar-architect.md +1 -1
- package/agents/bizar-implementer.md +12 -2
- package/agents/bizar-planner.md +1 -1
- package/agents/bizar-researcher.md +1 -1
- package/agents/bizar-reviewer.md +7 -1
- package/agents/bizar-security-reviewer.md +1 -1
- package/agents/bizar-verifier.md +4 -0
- package/dist/cli/agents-ink.d.ts +12 -0
- package/dist/cli/agents-ink.d.ts.map +1 -1
- package/dist/cli/agents-ink.js +22 -7
- package/dist/cli/agents-ink.js.map +1 -1
- package/dist/cli/agents.d.ts.map +1 -1
- package/dist/cli/agents.js +6 -2
- package/dist/cli/agents.js.map +1 -1
- package/dist/cli/install.d.ts +1 -7
- package/dist/cli/install.d.ts.map +1 -1
- package/dist/cli/install.js +75 -81
- package/dist/cli/install.js.map +1 -1
- package/dist/cli/main.js +5 -1
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/mobile-claim.d.ts.map +1 -1
- package/dist/cli/mobile-claim.js +26 -18
- package/dist/cli/mobile-claim.js.map +1 -1
- package/dist/cli/omb-daemon.d.ts.map +1 -1
- package/dist/cli/omb-daemon.js +43 -11
- package/dist/cli/omb-daemon.js.map +1 -1
- package/dist/cli/omb-mobile.d.ts.map +1 -1
- package/dist/cli/omb-mobile.js +9 -3
- package/dist/cli/omb-mobile.js.map +1 -1
- package/dist/cli/omb-runtime.d.ts.map +1 -1
- package/dist/cli/omb-runtime.js +2 -0
- package/dist/cli/omb-runtime.js.map +1 -1
- package/dist/cli/omb-sessions.js +18 -7
- package/dist/cli/omb-sessions.js.map +1 -1
- package/dist/cli/omb-update.d.ts +1 -1
- package/dist/cli/omb-update.d.ts.map +1 -1
- package/dist/cli/omb-update.js +7 -36
- package/dist/cli/omb-update.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +2 -1
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/update-ink.d.ts.map +1 -1
- package/dist/cli/update-ink.js +8 -23
- package/dist/cli/update-ink.js.map +1 -1
- package/dist/core/acceptance.d.ts +20 -1
- package/dist/core/acceptance.d.ts.map +1 -1
- package/dist/core/acceptance.js +50 -2
- package/dist/core/acceptance.js.map +1 -1
- package/dist/core/policies.d.ts +11 -0
- package/dist/core/policies.d.ts.map +1 -1
- package/dist/core/policies.js +41 -10
- package/dist/core/policies.js.map +1 -1
- package/dist/core/transitions.d.ts.map +1 -1
- package/dist/core/transitions.js +4 -3
- package/dist/core/transitions.js.map +1 -1
- package/dist/core/types.d.ts +35 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/extension.d.ts +4 -0
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +377 -71
- package/dist/extension.js.map +1 -1
- package/dist/omp/daemon-service.d.ts.map +1 -1
- package/dist/omp/daemon-service.js +151 -21
- package/dist/omp/daemon-service.js.map +1 -1
- package/dist/omp/daemon.d.ts +18 -4
- package/dist/omp/daemon.d.ts.map +1 -1
- package/dist/omp/daemon.js +209 -76
- package/dist/omp/daemon.js.map +1 -1
- package/dist/omp/dispatch-lifecycle.d.ts +47 -0
- package/dist/omp/dispatch-lifecycle.d.ts.map +1 -0
- package/dist/omp/dispatch-lifecycle.js +92 -0
- package/dist/omp/dispatch-lifecycle.js.map +1 -0
- package/dist/omp/model-role-assignment.d.ts +5 -0
- package/dist/omp/model-role-assignment.d.ts.map +1 -1
- package/dist/omp/model-role-assignment.js +5 -0
- package/dist/omp/model-role-assignment.js.map +1 -1
- package/dist/omp/model-roles.d.ts +8 -0
- package/dist/omp/model-roles.d.ts.map +1 -1
- package/dist/omp/model-roles.js +10 -0
- package/dist/omp/model-roles.js.map +1 -1
- package/dist/omp/omb-sessions.d.ts.map +1 -1
- package/dist/omp/omb-sessions.js +20 -6
- package/dist/omp/omb-sessions.js.map +1 -1
- package/dist/omp/omb-settings.d.ts +5 -1
- package/dist/omp/omb-settings.d.ts.map +1 -1
- package/dist/omp/omb-settings.js +75 -26
- package/dist/omp/omb-settings.js.map +1 -1
- package/dist/omp/omp-provider-config.d.ts +3 -0
- package/dist/omp/omp-provider-config.d.ts.map +1 -1
- package/dist/omp/omp-provider-config.js +80 -30
- package/dist/omp/omp-provider-config.js.map +1 -1
- package/dist/omp/tmux.d.ts.map +1 -1
- package/dist/omp/tmux.js +10 -5
- package/dist/omp/tmux.js.map +1 -1
- package/dist/omp/tray.d.ts +9 -1
- package/dist/omp/tray.d.ts.map +1 -1
- package/dist/omp/tray.js +210 -56
- package/dist/omp/tray.js.map +1 -1
- package/dist/services/benchmarks.d.ts +68 -0
- package/dist/services/benchmarks.d.ts.map +1 -0
- package/dist/services/benchmarks.js +105 -0
- package/dist/services/benchmarks.js.map +1 -0
- package/dist/services/budget.d.ts +40 -1
- package/dist/services/budget.d.ts.map +1 -1
- package/dist/services/budget.js +74 -3
- package/dist/services/budget.js.map +1 -1
- package/dist/services/change-impact.d.ts +33 -0
- package/dist/services/change-impact.d.ts.map +1 -0
- package/dist/services/change-impact.js +103 -0
- package/dist/services/change-impact.js.map +1 -0
- package/dist/services/efficiency.d.ts +101 -0
- package/dist/services/efficiency.d.ts.map +1 -0
- package/dist/services/efficiency.js +170 -0
- package/dist/services/efficiency.js.map +1 -0
- package/dist/services/hypothesis-ledger.d.ts +66 -0
- package/dist/services/hypothesis-ledger.d.ts.map +1 -0
- package/dist/services/hypothesis-ledger.js +92 -0
- package/dist/services/hypothesis-ledger.js.map +1 -0
- package/dist/services/lesson-extraction.d.ts +27 -0
- package/dist/services/lesson-extraction.d.ts.map +1 -0
- package/dist/services/lesson-extraction.js +49 -0
- package/dist/services/lesson-extraction.js.map +1 -0
- package/dist/services/parallel-work.d.ts +44 -0
- package/dist/services/parallel-work.d.ts.map +1 -0
- package/dist/services/parallel-work.js +68 -0
- package/dist/services/parallel-work.js.map +1 -0
- package/dist/services/pr-shepherd.d.ts +83 -0
- package/dist/services/pr-shepherd.d.ts.map +1 -0
- package/dist/services/pr-shepherd.js +129 -0
- package/dist/services/pr-shepherd.js.map +1 -0
- package/dist/services/recipes.d.ts +12 -2
- package/dist/services/recipes.d.ts.map +1 -1
- package/dist/services/recipes.js +100 -8
- package/dist/services/recipes.js.map +1 -1
- package/dist/services/run-contract.d.ts +18 -0
- package/dist/services/run-contract.d.ts.map +1 -0
- package/dist/services/run-contract.js +32 -0
- package/dist/services/run-contract.js.map +1 -0
- package/dist/services/snapshots.d.ts +78 -0
- package/dist/services/snapshots.d.ts.map +1 -0
- package/dist/services/snapshots.js +194 -0
- package/dist/services/snapshots.js.map +1 -0
- package/dist/services/specialist-contracts.d.ts +58 -0
- package/dist/services/specialist-contracts.d.ts.map +1 -0
- package/dist/services/specialist-contracts.js +109 -0
- package/dist/services/specialist-contracts.js.map +1 -0
- package/dist/services/stall-detector.d.ts +27 -0
- package/dist/services/stall-detector.d.ts.map +1 -0
- package/dist/services/stall-detector.js +53 -0
- package/dist/services/stall-detector.js.map +1 -0
- package/dist/storage/resources.d.ts +1 -0
- package/dist/storage/resources.d.ts.map +1 -1
- package/dist/storage/resources.js +13 -11
- package/dist/storage/resources.js.map +1 -1
- package/dist/tools/integrate.d.ts.map +1 -1
- package/dist/tools/integrate.js +8 -7
- package/dist/tools/integrate.js.map +1 -1
- package/dist/tools/verify.d.ts +5 -2
- package/dist/tools/verify.d.ts.map +1 -1
- package/dist/tools/verify.js +84 -14
- package/dist/tools/verify.js.map +1 -1
- package/dist/tools/workflow.d.ts +2 -2
- package/dist/tools/workflow.d.ts.map +1 -1
- package/dist/tools/workflow.js +7 -0
- package/dist/tools/workflow.js.map +1 -1
- package/docs/07-bizarharness-integration.md +12 -0
- package/docs/compatibility/baseline.json +1 -1
- package/docs/compatibility/lifecycle-observation.md +15 -1
- package/docs/releases/0.8.1.md +53 -0
- package/docs/security/project-audit-2026-10-01.md +145 -0
- package/package.json +9 -5
- package/skills/bizar-omp/SKILL.md +54 -0
package/dist/extension.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extension.d.ts","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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"}
|
package/dist/extension.js
CHANGED
|
@@ -10,10 +10,21 @@ import { result } from "./tools/result.js";
|
|
|
10
10
|
import { runVerification } from "./tools/verify.js";
|
|
11
11
|
import { runWorkflow } from "./tools/workflow.js";
|
|
12
12
|
import { analyzeRecipe } from "./services/recipes.js";
|
|
13
|
-
import { freezeCheckSpec } from "./core/acceptance.js";
|
|
13
|
+
import { admittedRequirements, freezeCheckSpec, receiptIntegrityHash } from "./core/acceptance.js";
|
|
14
|
+
import { completableObjective } from "./services/run-contract.js";
|
|
14
15
|
import { freezeObjective } from "./core/transitions.js";
|
|
15
16
|
import { runCandidateCheck } from "./services/candidate-verify.js";
|
|
17
|
+
import { admitNativeTasks, settleNativeCall } from "./omp/dispatch-lifecycle.js";
|
|
18
|
+
import { readStructuredOutput } from "./services/specialist-contracts.js";
|
|
19
|
+
import { detectStall } from "./services/stall-detector.js";
|
|
20
|
+
import { lessonForNativeLearn, proposeLessons } from "./services/lesson-extraction.js";
|
|
21
|
+
import { analyzeChangeImpact } from "./services/change-impact.js";
|
|
22
|
+
import { createEfficiencyRecorder, recommendFromRoles, recommendFromTimeline, roleCostByDispatch } from "./services/efficiency.js";
|
|
23
|
+
import { captureSnapshot, listSnapshots, previewSnapshot, restoreSnapshot, sealSnapshot } from "./services/snapshots.js";
|
|
16
24
|
import { inspectEvidence } from "./services/inspector.js";
|
|
25
|
+
import { addHypothesis, attachEvidence, readyToImplement, recordRepair, requiresLedger, setHypothesisStatus } from "./services/hypothesis-ledger.js";
|
|
26
|
+
import { SCENARIOS, scoreAll, scoreScenario } from "./services/benchmarks.js";
|
|
27
|
+
import { auxiliaryWork, emptyShepherd, observeChecks, observeReviews, recordMerge, recordPush, recordRepair as recordShepherdRepair } from "./services/pr-shepherd.js";
|
|
17
28
|
import { projectWorkflow } from "./services/projection.js";
|
|
18
29
|
import { capabilityReport } from "./omp/capabilities.js";
|
|
19
30
|
import { repositoryIdentity, statePath, workingTreeDigest } from "./storage/repository-identity.js";
|
|
@@ -24,7 +35,7 @@ import { acquireOmpSessionLease, clearOmbSessionReference, indexOmbSessionFile,
|
|
|
24
35
|
import { clearOmbHostGeneration, rebindOmbHostGeneration } from "./omp/tmux.js";
|
|
25
36
|
import { createSessionTitleController, resolveSessionTitleLabel } from "./omp/terminal-title.js";
|
|
26
37
|
import { bindSession } from "./omp/lifecycle.js";
|
|
27
|
-
import { BIZAR_MODEL_ROLE_AGENT_PROMPT, BIZAR_MODEL_ROLE_TOOL, BIZAR_MODEL_ROLES,
|
|
38
|
+
import { BIZAR_MODEL_ROLE_AGENT_PROMPT, BIZAR_MODEL_ROLE_TOOL, BIZAR_MODEL_ROLES, buildAgentEvaluationRequest, clipOperatorNotice, commitRolePlan, diffCatalog, formatCatalogDelta, formatRoleAssignmentPlan, planBizarModelRoles, planFromRecommendations, recordOf, reviewRoleRecommendations, roleAssignmentRoute, snapshotCatalog, isOpaqueOmniRouteCombo, omniRouteFailureGuidance, } from "./omp/model-role-assignment.js";
|
|
28
39
|
import { AGENT_ROLES } from "./omp/model-roles.js";
|
|
29
40
|
import { loadOmbSettings, recordCatalogObservation } from "./omp/omb-settings.js";
|
|
30
41
|
import { isRunPhaseActive } from "./core/types.js";
|
|
@@ -202,18 +213,6 @@ function applyBizarModelRoles(pi, assignments) {
|
|
|
202
213
|
settings.setModelRole(assignment.role, assignment.selector);
|
|
203
214
|
return "global";
|
|
204
215
|
}
|
|
205
|
-
async function setNativeSetting(pi, settings, key, value, cwd) {
|
|
206
|
-
if (settings?.set) {
|
|
207
|
-
settings.set(key, value);
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
if (!pi.exec)
|
|
211
|
-
throw new ContractError(`OMP cannot update ${key}: its settings writer is unavailable`);
|
|
212
|
-
const command = findOnPath("omp", process.env) ?? "omp";
|
|
213
|
-
const result = await pi.exec(command, ["config", "set", key, JSON.stringify(value)], { cwd });
|
|
214
|
-
if (result.code !== 0)
|
|
215
|
-
throw new ContractError(`OMP could not update ${key} through its config command (exit ${result.code ?? "unknown"})`);
|
|
216
|
-
}
|
|
217
216
|
async function getNativeSetting(pi, settings, key, cwd) {
|
|
218
217
|
if (settings?.get)
|
|
219
218
|
return settings.get(key);
|
|
@@ -230,33 +229,6 @@ async function getNativeSetting(pi, settings, key, cwd) {
|
|
|
230
229
|
throw new ContractError(`OMP returned invalid JSON while reading ${key}`);
|
|
231
230
|
}
|
|
232
231
|
}
|
|
233
|
-
async function ensureBizarModelRoles(pi, cwd) {
|
|
234
|
-
const settings = pi.pi?.settings;
|
|
235
|
-
if (!settings && !pi.exec)
|
|
236
|
-
return;
|
|
237
|
-
const currentRoles = recordOf(await getNativeSetting(pi, settings, "modelRoles", cwd));
|
|
238
|
-
const missingRoles = Object.entries(BIZAR_MODEL_ROLES).filter(([role]) => typeof currentRoles[role] !== "string");
|
|
239
|
-
const projectStorage = await getNativeSetting(pi, settings, "modelRoleStorage", cwd) === "project";
|
|
240
|
-
const roleSetter = projectStorage ? settings?.setProjectModelRole : settings?.setModelRole;
|
|
241
|
-
if (roleSetter) {
|
|
242
|
-
for (const [role, selector] of missingRoles)
|
|
243
|
-
roleSetter.call(settings, role, selector);
|
|
244
|
-
}
|
|
245
|
-
const currentTags = recordOf(await getNativeSetting(pi, settings, "modelTags", cwd));
|
|
246
|
-
const nextTags = { ...currentTags };
|
|
247
|
-
for (const [role, tag] of Object.entries(BIZAR_MODEL_TAGS))
|
|
248
|
-
if (!Object.hasOwn(nextTags, role))
|
|
249
|
-
nextTags[role] = tag;
|
|
250
|
-
if (JSON.stringify(nextTags) !== JSON.stringify(currentTags))
|
|
251
|
-
await setNativeSetting(pi, settings, "modelTags", nextTags, cwd);
|
|
252
|
-
const currentCycle = await getNativeSetting(pi, settings, "cycleOrder", cwd);
|
|
253
|
-
const nextCycle = Array.isArray(currentCycle) ? currentCycle.filter((role) => typeof role === "string") : [];
|
|
254
|
-
for (const role of Object.keys(BIZAR_MODEL_ROLES))
|
|
255
|
-
if (!nextCycle.includes(role))
|
|
256
|
-
nextCycle.push(role);
|
|
257
|
-
if (JSON.stringify(nextCycle) !== JSON.stringify(currentCycle))
|
|
258
|
-
await setNativeSetting(pi, settings, "cycleOrder", nextCycle, cwd);
|
|
259
|
-
}
|
|
260
232
|
async function modelRoleHealth(pi, ctx, routeResponses) {
|
|
261
233
|
const settings = pi.pi?.settings;
|
|
262
234
|
if (!settings?.get && !pi.exec)
|
|
@@ -427,11 +399,30 @@ function applyOrchestratorPolicy(systemPrompt) {
|
|
|
427
399
|
}
|
|
428
400
|
return [MAIN_ORCHESTRATOR_POLICY];
|
|
429
401
|
}
|
|
402
|
+
/** Remove only Bizar's exact main-session block from a reused native prompt. */
|
|
403
|
+
function removeOrchestratorPolicy(systemPrompt) {
|
|
404
|
+
if (typeof systemPrompt === "string")
|
|
405
|
+
return systemPrompt.replace(MAIN_ORCHESTRATOR_POLICY, "");
|
|
406
|
+
if (Array.isArray(systemPrompt))
|
|
407
|
+
return systemPrompt.map(String).filter(prompt => prompt !== MAIN_ORCHESTRATOR_POLICY);
|
|
408
|
+
return [];
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* OMP's public extension context identifies both the session class and its
|
|
412
|
+
* host-owned session id. Do not substitute task depth, agent names, or process
|
|
413
|
+
* state: `/tan` children have depth zero and extension factories are rebound.
|
|
414
|
+
*/
|
|
415
|
+
function mainSessionId(ctx) {
|
|
416
|
+
if (ctx.agent?.kind !== "main")
|
|
417
|
+
return undefined;
|
|
418
|
+
const id = ctx.sessionManager?.getSessionId?.();
|
|
419
|
+
return typeof id === "string" && id.length > 0 ? id : undefined;
|
|
420
|
+
}
|
|
430
421
|
export default function bizarExtension(pi) {
|
|
431
422
|
pi.setLabel?.("Bizar Orchestrator");
|
|
432
423
|
let binding;
|
|
433
424
|
// Main orchestrator role is opt-in: task children must NEVER see it.
|
|
434
|
-
let
|
|
425
|
+
let orchestratorSessionId;
|
|
435
426
|
// The tab title is owned here because an extension override is rendered
|
|
436
427
|
// verbatim: OMP's own run-state spinner would never animate it. A Bizar host
|
|
437
428
|
// would otherwise show the bare binary name in every tab, with nothing to
|
|
@@ -487,7 +478,7 @@ export default function bizarExtension(pi) {
|
|
|
487
478
|
});
|
|
488
479
|
pi.on("session_start", async (_event, ctx) => {
|
|
489
480
|
binding = undefined;
|
|
490
|
-
|
|
481
|
+
orchestratorSessionId = undefined;
|
|
491
482
|
releaseNativeLease();
|
|
492
483
|
extensionUi = ctx.ui;
|
|
493
484
|
// The tab should name the conversation. OMP's own session name is the bare
|
|
@@ -507,12 +498,6 @@ export default function bizarExtension(pi) {
|
|
|
507
498
|
ctx.shutdown?.();
|
|
508
499
|
}
|
|
509
500
|
}
|
|
510
|
-
try {
|
|
511
|
-
await ensureBizarModelRoles(pi, ctx.cwd ?? process.cwd());
|
|
512
|
-
}
|
|
513
|
-
catch (error) {
|
|
514
|
-
ctx.ui?.notify(`Bizar could not apply its OMP settings; continuing without the failed setting update. ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
515
|
-
}
|
|
516
501
|
});
|
|
517
502
|
pi.on("session_before_switch", async (event, ctx) => {
|
|
518
503
|
binding = undefined;
|
|
@@ -540,6 +525,9 @@ export default function bizarExtension(pi) {
|
|
|
540
525
|
}
|
|
541
526
|
});
|
|
542
527
|
pi.on("session_switch", async (_event, ctx) => {
|
|
528
|
+
// OMP only emits this after a switch commits. Keep activation intact when a
|
|
529
|
+
// preflight is cancelled, but never carry it across a committed session.
|
|
530
|
+
orchestratorSessionId = undefined;
|
|
543
531
|
const file = ctx.sessionManager?.getSessionFile?.();
|
|
544
532
|
if (!file || !existsSync(file)) {
|
|
545
533
|
try {
|
|
@@ -626,17 +614,20 @@ export default function bizarExtension(pi) {
|
|
|
626
614
|
pi.on("session_shutdown", async () => {
|
|
627
615
|
releaseNativeLease();
|
|
628
616
|
binding = undefined;
|
|
629
|
-
|
|
617
|
+
orchestratorSessionId = undefined;
|
|
630
618
|
sessionTitle.dispose();
|
|
631
619
|
extensionUi = undefined;
|
|
632
620
|
});
|
|
633
621
|
pi.on("before_agent_start", (event, ctx) => {
|
|
634
622
|
extensionUi = ctx?.ui ?? extensionUi;
|
|
635
623
|
sessionTitle.setState("working");
|
|
624
|
+
const sessionId = mainSessionId(ctx ?? {});
|
|
625
|
+
const systemPrompt = paramsOf(event).systemPrompt;
|
|
626
|
+
const active = orchestratorSessionId !== undefined && orchestratorSessionId === sessionId;
|
|
636
627
|
return {
|
|
637
|
-
systemPrompt: appendUserIdentityInvariant(
|
|
638
|
-
? applyOrchestratorPolicy(appendBizarInvariant(
|
|
639
|
-
: appendBizarInvariant(
|
|
628
|
+
systemPrompt: appendUserIdentityInvariant(active
|
|
629
|
+
? applyOrchestratorPolicy(appendBizarInvariant(systemPrompt))
|
|
630
|
+
: appendBizarInvariant(removeOrchestratorPolicy(systemPrompt))),
|
|
640
631
|
};
|
|
641
632
|
});
|
|
642
633
|
pi.on("agent_end", (event, ctx) => {
|
|
@@ -669,11 +660,12 @@ export default function bizarExtension(pi) {
|
|
|
669
660
|
*/
|
|
670
661
|
const requestedTasks = (input) => {
|
|
671
662
|
if (!Array.isArray(input.tasks)) {
|
|
672
|
-
|
|
663
|
+
const flat = paramsOf(input);
|
|
664
|
+
return [{ name: typeof flat.name === "string" ? flat.name : undefined, agent: typeof flat.agent === "string" ? flat.agent : "", isolated: flat.isolated === true, task: typeof flat.task === "string" ? flat.task : undefined }];
|
|
673
665
|
}
|
|
674
666
|
return input.tasks.map(entry => {
|
|
675
667
|
const task = paramsOf(entry);
|
|
676
|
-
return { agent: typeof task.agent === "string" ? task.agent : "", isolated: task.isolated === true };
|
|
668
|
+
return { name: typeof task.name === "string" ? task.name : undefined, agent: typeof task.agent === "string" ? task.agent : "", isolated: task.isolated === true, task: typeof task.task === "string" ? task.task : undefined };
|
|
677
669
|
});
|
|
678
670
|
};
|
|
679
671
|
/**
|
|
@@ -705,6 +697,35 @@ export default function bizarExtension(pi) {
|
|
|
705
697
|
if (!BIZAR_PACKAGED_AGENTS[task.agent])
|
|
706
698
|
return { block: true, reason: `A002: managed workflow refused native \`task\` to non-packaged agent ${task.agent || "(unspecified)"}; only packaged Bizar specialists are admitted.${managedRunNotice(run)}` };
|
|
707
699
|
}
|
|
700
|
+
// A002: the dispatch is journaled only once every task in the call is
|
|
701
|
+
// admitted, and before OMP runs any of them. A refused call leaves no
|
|
702
|
+
// dispatch behind, so nothing waits on work that will never happen.
|
|
703
|
+
try {
|
|
704
|
+
admitNativeTasks(active, run, tasks, String(params.toolCallId ?? ""));
|
|
705
|
+
}
|
|
706
|
+
catch (error) {
|
|
707
|
+
return { block: true, reason: `A002: ${error instanceof Error ? error.message : String(error)}.${managedRunNotice(run)}` };
|
|
708
|
+
}
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
catch {
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
});
|
|
715
|
+
// A002: settle on OMP's own tool result. The recorded outcome is the host's,
|
|
716
|
+
// never the model's, so a task that errored cannot settle as success.
|
|
717
|
+
pi.on("tool_result", (event, ctx) => {
|
|
718
|
+
try {
|
|
719
|
+
const params = paramsOf(event);
|
|
720
|
+
const toolCallId = String(params.toolCallId ?? "");
|
|
721
|
+
if (!toolCallId)
|
|
722
|
+
return;
|
|
723
|
+
const active = currentBinding(ctx);
|
|
724
|
+
const run = active.journal.snapshot().run;
|
|
725
|
+
if (!run || !isRunPhaseActive(run.phase))
|
|
726
|
+
return;
|
|
727
|
+
recorderFor(run.runId).callEnded(toolCallId, params.isError === true);
|
|
728
|
+
settleNativeCall(active, run, toolCallId, { isError: params.isError === true, ...readStructuredOutput(params.details) });
|
|
708
729
|
}
|
|
709
730
|
catch {
|
|
710
731
|
return;
|
|
@@ -732,12 +753,81 @@ export default function bizarExtension(pi) {
|
|
|
732
753
|
return;
|
|
733
754
|
}
|
|
734
755
|
});
|
|
756
|
+
// A005: notice a repeating call before it burns more turns. This never blocks
|
|
757
|
+
// a call — a stalled agent is the one least able to recover from being
|
|
758
|
+
// refused — but the notice names the repetition and the way out.
|
|
759
|
+
const recentCalls = new Map();
|
|
760
|
+
const efficiency = new Map();
|
|
761
|
+
const recorderFor = (runId) => {
|
|
762
|
+
const existing = efficiency.get(runId);
|
|
763
|
+
if (existing)
|
|
764
|
+
return existing;
|
|
765
|
+
const recorder = createEfficiencyRecorder(runId);
|
|
766
|
+
efficiency.set(runId, recorder);
|
|
767
|
+
return recorder;
|
|
768
|
+
};
|
|
769
|
+
pi.on("tool_call", (event, ctx) => {
|
|
770
|
+
try {
|
|
771
|
+
const params = paramsOf(event);
|
|
772
|
+
const toolName = String(params.toolName ?? "");
|
|
773
|
+
if (!toolName)
|
|
774
|
+
return;
|
|
775
|
+
const active = currentBinding(ctx);
|
|
776
|
+
const run = active.journal.snapshot().run;
|
|
777
|
+
if (!isRunPhaseActive(run?.phase))
|
|
778
|
+
return;
|
|
779
|
+
// The fingerprint is a digest: the input may carry a credential, and the
|
|
780
|
+
// detector needs to compare calls, never to retain what they contained.
|
|
781
|
+
const fingerprint = createHash("sha256").update(JSON.stringify(params.input ?? null)).digest("hex").slice(0, 16);
|
|
782
|
+
// Only an admitted call is timed: a call the gates refused never ran, and
|
|
783
|
+
// charging the run for it would understate what it actually cost.
|
|
784
|
+
if (params.toolCallId)
|
|
785
|
+
recorderFor(run.runId).callStarted(String(params.toolCallId), toolName, fingerprint);
|
|
786
|
+
const history = [...(recentCalls.get(run.runId) ?? []), { toolName, fingerprint }].slice(-8);
|
|
787
|
+
recentCalls.set(run.runId, history);
|
|
788
|
+
const signal = detectStall(history);
|
|
789
|
+
if (signal)
|
|
790
|
+
ctx.ui?.notify(`${signal.message} ${signal.advice}`, "warning");
|
|
791
|
+
}
|
|
792
|
+
catch {
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
// A006: compaction is where Bizar's contract leaves the context window. It
|
|
797
|
+
// lives in the run journal, so it survives — but an agent working from a
|
|
798
|
+
// summary is working from something the gate never admitted. After a
|
|
799
|
+
// compaction that actually completed, say what the authoritative source is.
|
|
800
|
+
let compactionStarted;
|
|
801
|
+
pi.on("auto_compaction_start", (event) => {
|
|
802
|
+
const params = paramsOf(event);
|
|
803
|
+
compactionStarted = { reason: String(params.reason ?? "unknown"), action: String(params.action ?? "unknown") };
|
|
804
|
+
});
|
|
805
|
+
pi.on("auto_compaction_end", (event, ctx) => {
|
|
806
|
+
const params = paramsOf(event);
|
|
807
|
+
const started = compactionStarted;
|
|
808
|
+
compactionStarted = undefined;
|
|
809
|
+
if (params.aborted === true)
|
|
810
|
+
return;
|
|
811
|
+
const active = currentBinding(ctx);
|
|
812
|
+
const run = active.journal.snapshot().run;
|
|
813
|
+
if (!run || !isRunPhaseActive(run.phase))
|
|
814
|
+
return;
|
|
815
|
+
recorderFor(run.runId).compaction(started ? started.action : String(params.action ?? "auto"), false);
|
|
816
|
+
// Counted from the admitted objective rather than through the working-tree
|
|
817
|
+
// digest, so a session outside a repository still gets the pointer.
|
|
818
|
+
const admitted = run.objective.checkSpecs?.length ? run.objective.checkSpecs : run.objective.verificationPlan;
|
|
819
|
+
const criteria = (run.objective.criteria ?? []).filter(criterion => criterion.applicable).length;
|
|
820
|
+
ctx.ui?.notify(`Context compacted (${started ? `${started.reason}/${started.action}` : "auto"}). The admitted contract is in the run journal, not in this context: re-read it with bizar_inspect before continuing — ${admitted.length} admitted checks, ${criteria} criteria.`, "warning");
|
|
821
|
+
});
|
|
735
822
|
pi.registerTool({
|
|
736
823
|
name: "bizar_apply_main_orchestrator_role", label: "Bizar Apply Main Orchestrator Role",
|
|
737
824
|
description: "Activate the main orchestrator role in this session; required so that before_agent_start injects the orchestrator policy. Task children must never invoke this.",
|
|
738
825
|
parameters: pi.zod.object({}),
|
|
739
|
-
async execute(_id, _raw, _signal, _onUpdate,
|
|
740
|
-
|
|
826
|
+
async execute(_id, _raw, _signal, _onUpdate, ctx) {
|
|
827
|
+
const sessionId = mainSessionId(ctx);
|
|
828
|
+
if (!sessionId)
|
|
829
|
+
return failure(new ContractError("The main orchestrator role can only be activated from an identified OMP main session; subagents and hosts without a native session identity are refused."));
|
|
830
|
+
orchestratorSessionId = sessionId;
|
|
741
831
|
return result({ orchestratorActive: true, scope: "main-session-only", note: "Main orchestrator policy will be appended to subsequent agent system prompts in this session. Task children must not invoke this tool." });
|
|
742
832
|
},
|
|
743
833
|
});
|
|
@@ -778,15 +868,17 @@ export default function bizarExtension(pi) {
|
|
|
778
868
|
const receiptId = `receipt_${randomUUID()}`;
|
|
779
869
|
const issuedAt = new Date().toISOString();
|
|
780
870
|
const verdict = String(p.verdict);
|
|
781
|
-
const signedContent = JSON.stringify({ workItemId: p.workItemId, evidenceId, verdict, operatorId, issuedAt });
|
|
782
|
-
const signedContentHash = createHash("sha256").update(signedContent).digest("hex");
|
|
783
871
|
const receipt = {
|
|
784
872
|
id: receiptId, runId: state.run.runId, workItemId: String(p.workItemId),
|
|
785
873
|
evidenceId, verdict, rationale: String(p.rationale),
|
|
786
|
-
operatorId, signedContentHash, issuedAt,
|
|
874
|
+
operatorId, signedContentHash: "", issuedAt,
|
|
875
|
+
authority: "environment-configured-identity",
|
|
787
876
|
};
|
|
877
|
+
// Hash the assembled receipt so the digest covers every field the
|
|
878
|
+
// verdict asserts, and acceptance can re-derive it later.
|
|
879
|
+
receipt.signedContentHash = receiptIntegrityHash(receipt);
|
|
788
880
|
active.journal.append({ type: "operator.receipt.recorded", runId: state.run.runId, receipt }, `receipt:${receiptId}`, state.revision);
|
|
789
|
-
return result({ receiptId, verdict, operatorId, signedContentHash });
|
|
881
|
+
return result({ receiptId, verdict, operatorId, signedContentHash: receipt.signedContentHash, authority: receipt.authority });
|
|
790
882
|
}
|
|
791
883
|
catch (error) {
|
|
792
884
|
return failure(error);
|
|
@@ -796,7 +888,7 @@ export default function bizarExtension(pi) {
|
|
|
796
888
|
pi.registerTool({
|
|
797
889
|
name: "bizar_workflow", label: "Bizar Workflow", description: "Create, inspect, and advance a typed Bizar workflow; transitions are journaled and revision checked.",
|
|
798
890
|
parameters: pi.zod.object({
|
|
799
|
-
action: pi.zod.enum(["start", "status", "transition", "add-work", "accept-work", "complete", "cancel", "next", "amend-objective"]),
|
|
891
|
+
action: pi.zod.enum(["start", "status", "transition", "add-work", "accept-work", "complete", "cancel", "next", "next-batch", "amend-objective"]),
|
|
800
892
|
objective: pi.zod.union([pi.zod.string(), objectiveSchema(pi.zod)]).optional(),
|
|
801
893
|
to: pi.zod.string().optional(),
|
|
802
894
|
reason: pi.zod.string().optional(),
|
|
@@ -805,13 +897,14 @@ export default function bizarExtension(pi) {
|
|
|
805
897
|
evidenceIds: pi.zod.array(pi.zod.string()).optional(),
|
|
806
898
|
requiredChecks: pi.zod.array(pi.zod.string()).optional(),
|
|
807
899
|
by: pi.zod.enum(["criterion", "check-spec"]).optional(),
|
|
900
|
+
capacity: pi.zod.number().optional(),
|
|
808
901
|
}),
|
|
809
902
|
async execute(_id, raw, _signal, _onUpdate, ctx) {
|
|
810
903
|
try {
|
|
811
904
|
const active = currentBinding(ctx);
|
|
812
905
|
const p = paramsOf(raw);
|
|
813
906
|
const action = String(p.action);
|
|
814
|
-
const payload = action === "start" ? { ...p, objective: objectiveOf(p.objective) } : p;
|
|
907
|
+
const payload = action === "start" ? { ...p, objective: completableObjective(objectiveOf(p.objective), ctx.cwd ?? active.cwd) } : p;
|
|
815
908
|
return result(runWorkflow(active, action, payload));
|
|
816
909
|
}
|
|
817
910
|
catch (error) {
|
|
@@ -928,16 +1021,225 @@ export default function bizarExtension(pi) {
|
|
|
928
1021
|
}
|
|
929
1022
|
},
|
|
930
1023
|
});
|
|
1024
|
+
pi.registerTool({
|
|
1025
|
+
name: "bizar_propose_lesson", label: "Bizar Propose Lesson",
|
|
1026
|
+
description: "Derive post-run lessons from accepted work and the evidence that proved it. Hand each returned rule to OMP's native `learn` tool; OMP owns memory, Bizar owns the derivation.",
|
|
1027
|
+
parameters: pi.zod.object({}),
|
|
1028
|
+
async execute(_id, _raw, _signal, _onUpdate, ctx) {
|
|
1029
|
+
try {
|
|
1030
|
+
const active = currentBinding(ctx);
|
|
1031
|
+
const state = active.journal.snapshot();
|
|
1032
|
+
if (!state.run)
|
|
1033
|
+
throw new ContractError("No workflow run exists; start one first");
|
|
1034
|
+
const lessons = proposeLessons(state, state.run);
|
|
1035
|
+
return result({
|
|
1036
|
+
count: lessons.length,
|
|
1037
|
+
lessons: lessons.map(lessonForNativeLearn),
|
|
1038
|
+
source: lessons,
|
|
1039
|
+
note: lessons.length
|
|
1040
|
+
? "Pass each rule to OMP's `learn` tool; Bizar derives lessons from evidence and never writes memory itself."
|
|
1041
|
+
: "No accepted work carries passing evidence yet, so there is nothing to learn from without laundering an assertion.",
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
1044
|
+
catch (error) {
|
|
1045
|
+
return failure(error);
|
|
1046
|
+
}
|
|
1047
|
+
},
|
|
1048
|
+
});
|
|
931
1049
|
pi.registerTool({
|
|
932
1050
|
name: "bizar_inspect", label: "Bizar Inspector", description: "Explain acceptance blockers and evidence lineage using the same decision function as completion.",
|
|
933
|
-
parameters: pi.zod.object({
|
|
1051
|
+
parameters: pi.zod.object({}),
|
|
934
1052
|
async execute(_id, raw, _signal, _onUpdate, ctx) {
|
|
935
1053
|
try {
|
|
936
1054
|
const active = currentBinding(ctx);
|
|
937
|
-
const
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1055
|
+
const state = active.journal.snapshot();
|
|
1056
|
+
if (!state.run)
|
|
1057
|
+
throw new ContractError("No workflow run exists; start one first");
|
|
1058
|
+
// The admitted contract, not the caller's list. A caller able to narrow
|
|
1059
|
+
// the requirement set could report a run as unblocked that completion
|
|
1060
|
+
// will refuse.
|
|
1061
|
+
const requirements = admittedRequirements(state.run, state.run.workItems, workingTreeDigest(active.cwd));
|
|
1062
|
+
return result({ inspection: inspectEvidence(state, requirements, active), projection: projectWorkflow(state, requirements) });
|
|
1063
|
+
}
|
|
1064
|
+
catch (error) {
|
|
1065
|
+
return failure(error);
|
|
1066
|
+
}
|
|
1067
|
+
},
|
|
1068
|
+
});
|
|
1069
|
+
pi.registerTool({
|
|
1070
|
+
name: "bizar_change_impact", label: "Bizar Change Impact",
|
|
1071
|
+
description: "Read the changed paths' blast radius from the tree: trust boundaries, entry points, workspace crossings and the method tier that follows.",
|
|
1072
|
+
parameters: pi.zod.object({}),
|
|
1073
|
+
async execute(_id, _raw, _signal, _onUpdate, ctx) {
|
|
1074
|
+
try {
|
|
1075
|
+
return result(analyzeChangeImpact(ctx.cwd ?? process.cwd()));
|
|
1076
|
+
}
|
|
1077
|
+
catch (error) {
|
|
1078
|
+
return failure(error);
|
|
1079
|
+
}
|
|
1080
|
+
},
|
|
1081
|
+
});
|
|
1082
|
+
pi.registerTool({
|
|
1083
|
+
name: "bizar_run_efficiency", label: "Bizar Run Efficiency",
|
|
1084
|
+
description: "Report what this managed run actually spent time on: call durations, failures, repeated inputs and compactions, with advisory recommendations and the signals the host cannot expose.",
|
|
1085
|
+
parameters: pi.zod.object({}),
|
|
1086
|
+
async execute(_id, _raw, _signal, _onUpdate, ctx) {
|
|
1087
|
+
try {
|
|
1088
|
+
const active = currentBinding(ctx);
|
|
1089
|
+
const state = active.journal.snapshot();
|
|
1090
|
+
if (!state.run)
|
|
1091
|
+
throw new ContractError("No workflow run exists; start one first");
|
|
1092
|
+
const timeline = recorderFor(state.run.runId).timeline();
|
|
1093
|
+
const costs = roleCostByDispatch(timeline, state.dispatches);
|
|
1094
|
+
return result({ ...timeline, recommendations: recommendFromTimeline(timeline), roleCosts: costs, roleRecommendations: recommendFromRoles(costs) });
|
|
1095
|
+
}
|
|
1096
|
+
catch (error) {
|
|
1097
|
+
return failure(error);
|
|
1098
|
+
}
|
|
1099
|
+
},
|
|
1100
|
+
});
|
|
1101
|
+
pi.registerTool({
|
|
1102
|
+
name: "bizar_edit_snapshot", label: "Bizar Edit Snapshot",
|
|
1103
|
+
description: "Capture a bounded pre-edit baseline for the paths a focused task will touch, seal it after the edit, and undo exactly those paths when the change turns out to be wrong.",
|
|
1104
|
+
parameters: pi.zod.object({
|
|
1105
|
+
action: pi.zod.enum(["capture", "seal", "preview", "restore", "list"]),
|
|
1106
|
+
id: pi.zod.string().optional(),
|
|
1107
|
+
paths: pi.zod.array(pi.zod.string()).optional(),
|
|
1108
|
+
}),
|
|
1109
|
+
async execute(_id, raw, _signal, _onUpdate, ctx) {
|
|
1110
|
+
try {
|
|
1111
|
+
const cwd = ctx.cwd ?? process.cwd();
|
|
1112
|
+
const params = paramsOf(raw);
|
|
1113
|
+
const action = String(params.action);
|
|
1114
|
+
if (action === "list")
|
|
1115
|
+
return result({ snapshots: listSnapshots(cwd) });
|
|
1116
|
+
if (action === "capture") {
|
|
1117
|
+
if (!Array.isArray(params.paths) || params.paths.length === 0)
|
|
1118
|
+
throw new ContractError("capture needs the paths the task will edit");
|
|
1119
|
+
return result({ snapshot: captureSnapshot(cwd, params.paths.map(String), { runId: currentBinding(ctx).journal.snapshot().run?.runId }) });
|
|
1120
|
+
}
|
|
1121
|
+
const snapshotId = String(params.id ?? "");
|
|
1122
|
+
if (!snapshotId)
|
|
1123
|
+
throw new ContractError(`The ${action} action needs a snapshot id`);
|
|
1124
|
+
if (action === "seal")
|
|
1125
|
+
return result({ snapshot: sealSnapshot(cwd, snapshotId) });
|
|
1126
|
+
if (action === "preview")
|
|
1127
|
+
return result(previewSnapshot(cwd, snapshotId));
|
|
1128
|
+
return result(restoreSnapshot(cwd, snapshotId));
|
|
1129
|
+
}
|
|
1130
|
+
catch (error) {
|
|
1131
|
+
return failure(error);
|
|
1132
|
+
}
|
|
1133
|
+
},
|
|
1134
|
+
});
|
|
1135
|
+
/** Run-scoped ledgers. Survives compaction and session switch; does not outlive the host process. */
|
|
1136
|
+
const hypothesisLedgers = new Map();
|
|
1137
|
+
/** Run-scoped shepherd state. Bizar holds policy here; the host owns the GitHub calls. */
|
|
1138
|
+
const shepherds = new Map();
|
|
1139
|
+
pi.registerTool({
|
|
1140
|
+
name: "bizar_hypothesis_ledger", label: "Bizar Hypothesis Ledger",
|
|
1141
|
+
description: "Track competing root-cause hypotheses and the repairs attempted against them, so an unknown-cause bug stops turning into patch churn.",
|
|
1142
|
+
parameters: pi.zod.object({
|
|
1143
|
+
action: pi.zod.enum(["required", "add", "attach", "support", "refute", "repair", "status"]),
|
|
1144
|
+
statement: pi.zod.string().optional(),
|
|
1145
|
+
hypothesisId: pi.zod.string().optional(),
|
|
1146
|
+
evidenceIds: pi.zod.array(pi.zod.string()).optional(),
|
|
1147
|
+
outcome: pi.zod.enum(["failed", "confirmed", "inconclusive"]).optional(),
|
|
1148
|
+
note: pi.zod.string().optional(),
|
|
1149
|
+
text: pi.zod.string().optional(),
|
|
1150
|
+
}),
|
|
1151
|
+
async execute(_id, raw, _signal, _onUpdate, ctx) {
|
|
1152
|
+
try {
|
|
1153
|
+
const params = paramsOf(raw);
|
|
1154
|
+
const action = String(params.action);
|
|
1155
|
+
if (action === "required")
|
|
1156
|
+
return result({ required: requiresLedger({ text: String(params.text ?? "") }) });
|
|
1157
|
+
const active = currentBinding(ctx);
|
|
1158
|
+
const state = active.journal.snapshot();
|
|
1159
|
+
if (!state.run)
|
|
1160
|
+
throw new ContractError("No workflow run exists; start one first");
|
|
1161
|
+
const runId = state.run.runId;
|
|
1162
|
+
const ledgers = hypothesisLedgers.get(runId) ?? { hypotheses: [], attempts: [] };
|
|
1163
|
+
const evidenceIds = Array.isArray(params.evidenceIds) ? params.evidenceIds.map(String) : [];
|
|
1164
|
+
const hypothesisId = String(params.hypothesisId ?? "");
|
|
1165
|
+
const save = (ledger, extra = {}) => { hypothesisLedgers.set(runId, ledger); return result({ ledger, readyToImplement: readyToImplement(ledger), ...extra }); };
|
|
1166
|
+
if (action === "status")
|
|
1167
|
+
return save(ledgers);
|
|
1168
|
+
if (action === "add")
|
|
1169
|
+
return save(addHypothesis(ledgers, String(params.statement ?? ""), evidenceIds));
|
|
1170
|
+
if (action === "attach")
|
|
1171
|
+
return save(attachEvidence(ledgers, hypothesisId, evidenceIds));
|
|
1172
|
+
if (action === "support" || action === "refute")
|
|
1173
|
+
return save(setHypothesisStatus(ledgers, hypothesisId, action === "support" ? "supported" : "refuted", String(params.note ?? "")));
|
|
1174
|
+
const outcome = recordRepair(ledgers, hypothesisId, params.outcome === "confirmed" || params.outcome === "inconclusive" ? params.outcome : "failed", String(params.note ?? ""));
|
|
1175
|
+
return save(outcome.ledger, { advice: outcome.advice });
|
|
1176
|
+
}
|
|
1177
|
+
catch (error) {
|
|
1178
|
+
return failure(error);
|
|
1179
|
+
}
|
|
1180
|
+
},
|
|
1181
|
+
});
|
|
1182
|
+
pi.registerTool({
|
|
1183
|
+
name: "bizar_benchmarks", label: "Bizar Behaviour Benchmarks",
|
|
1184
|
+
description: "Score this run's observed behaviour against the scenarios the operator actually pays for: avoidable spawns, repeated calls, retry loops and repository-wide gates.",
|
|
1185
|
+
parameters: pi.zod.object({ scenarioId: pi.zod.string().optional() }),
|
|
1186
|
+
async execute(_id, raw, _signal, _onUpdate, ctx) {
|
|
1187
|
+
try {
|
|
1188
|
+
const active = currentBinding(ctx);
|
|
1189
|
+
const state = active.journal.snapshot();
|
|
1190
|
+
if (!state.run)
|
|
1191
|
+
throw new ContractError("No workflow run exists; start one first");
|
|
1192
|
+
const timeline = recorderFor(state.run.runId).timeline();
|
|
1193
|
+
const observed = {
|
|
1194
|
+
toolCalls: timeline.entries.filter(entry => entry.kind === "tool" && entry.tool !== undefined).map(entry => ({ tool: entry.tool, fingerprint: entry.fingerprint ?? "", ...(entry.failed === undefined ? {} : { failed: entry.failed }) })),
|
|
1195
|
+
spawnedAgents: state.dispatches.length,
|
|
1196
|
+
validatedChecks: [...new Set(state.evidence.map(record => record.checkId))],
|
|
1197
|
+
totals: timeline.totals,
|
|
1198
|
+
};
|
|
1199
|
+
const requested = String(paramsOf(raw).scenarioId ?? "");
|
|
1200
|
+
const scores = requested ? SCENARIOS.filter(entry => entry.id === requested).map(entry => scoreScenario(entry, observed)) : scoreAll(observed);
|
|
1201
|
+
if (requested && !scores.length)
|
|
1202
|
+
throw new ContractError(`No benchmark scenario named ${requested}`);
|
|
1203
|
+
return result({ scores, passed: scores.every(entry => entry.passed) });
|
|
1204
|
+
}
|
|
1205
|
+
catch (error) {
|
|
1206
|
+
return failure(error);
|
|
1207
|
+
}
|
|
1208
|
+
},
|
|
1209
|
+
});
|
|
1210
|
+
pi.registerTool({
|
|
1211
|
+
name: "bizar_pr_shepherd", label: "Bizar PR Shepherd",
|
|
1212
|
+
description: "Track the pull-request lifecycle as a state machine: the exact SHA under review, observed checks and reviews, a bounded repair budget, and the next condition to wait for. Bizar does not talk to GitHub; report what the host's native tool saw.",
|
|
1213
|
+
parameters: pi.zod.object({
|
|
1214
|
+
action: pi.zod.enum(["status", "push", "checks", "reviews", "repair", "merge", "auxiliary"]),
|
|
1215
|
+
pullRequest: pi.zod.number().optional(),
|
|
1216
|
+
sha: pi.zod.string().optional(),
|
|
1217
|
+
mergeability: pi.zod.enum(["mergeable", "blocked", "conflicted", "unknown"]).optional(),
|
|
1218
|
+
checks: pi.zod.array(pi.zod.object({ name: pi.zod.string(), required: pi.zod.boolean(), state: pi.zod.enum(["pending", "passing", "failing"]) })).optional(),
|
|
1219
|
+
reviews: pi.zod.array(pi.zod.object({ id: pi.zod.string(), blocking: pi.zod.boolean(), resolved: pi.zod.boolean(), summary: pi.zod.string() })).optional(),
|
|
1220
|
+
note: pi.zod.string().optional(),
|
|
1221
|
+
}),
|
|
1222
|
+
async execute(_id, raw, _signal, _onUpdate, ctx) {
|
|
1223
|
+
try {
|
|
1224
|
+
const params = paramsOf(raw);
|
|
1225
|
+
const action = String(params.action);
|
|
1226
|
+
const active = currentBinding(ctx);
|
|
1227
|
+
const runId = active.journal.snapshot().run?.runId ?? "no-run";
|
|
1228
|
+
const store = shepherds.get(runId) ?? emptyShepherd(active.cwd, currentBinding(ctx).journal.snapshot().run?.objective ? "current" : "unknown");
|
|
1229
|
+
const save = (state, extra = {}) => { shepherds.set(runId, state); return result({ ...state, ...extra }); };
|
|
1230
|
+
if (action === "status")
|
|
1231
|
+
return save(store);
|
|
1232
|
+
if (action === "auxiliary")
|
|
1233
|
+
return save(store, { auxiliaryWork: auxiliaryWork(store) });
|
|
1234
|
+
if (action === "push")
|
|
1235
|
+
return save(recordPush(store, { sha: String(params.sha ?? ""), pullRequest: Number(params.pullRequest ?? 0), mergeability: params.mergeability }));
|
|
1236
|
+
if (action === "checks")
|
|
1237
|
+
return save(observeChecks(store, { sha: String(params.sha ?? ""), checks: Array.isArray(params.checks) ? params.checks : [], mergeability: params.mergeability }));
|
|
1238
|
+
if (action === "reviews")
|
|
1239
|
+
return save(observeReviews(store, Array.isArray(params.reviews) ? params.reviews : []));
|
|
1240
|
+
if (action === "repair")
|
|
1241
|
+
return save(recordShepherdRepair(store, { sha: String(params.sha ?? ""), note: String(params.note ?? "") }));
|
|
1242
|
+
return save(recordMerge(store));
|
|
941
1243
|
}
|
|
942
1244
|
catch (error) {
|
|
943
1245
|
return failure(error);
|
|
@@ -1012,7 +1314,7 @@ export default function bizarExtension(pi) {
|
|
|
1012
1314
|
else {
|
|
1013
1315
|
const active = currentBinding(ctx);
|
|
1014
1316
|
if (command === "run" || command === "init")
|
|
1015
|
-
value = runWorkflow(active, "start", { objective: objectiveOf(words.join(" ")) });
|
|
1317
|
+
value = runWorkflow(active, "start", { objective: completableObjective(objectiveOf(words.join(" ")), active.cwd) });
|
|
1016
1318
|
else if (command === "status" || command === "next")
|
|
1017
1319
|
value = runWorkflow(active, command === "next" ? "next" : "status", {});
|
|
1018
1320
|
else if (command === "cancel")
|
|
@@ -1021,8 +1323,12 @@ export default function bizarExtension(pi) {
|
|
|
1021
1323
|
value = listEvidence(active);
|
|
1022
1324
|
else if (command === "recipe")
|
|
1023
1325
|
value = analyzeRecipe(active.cwd, objectiveOf(words.join(" ")));
|
|
1024
|
-
else if (command === "inspect")
|
|
1025
|
-
|
|
1326
|
+
else if (command === "inspect") {
|
|
1327
|
+
const state = active.journal.snapshot();
|
|
1328
|
+
if (!state.run)
|
|
1329
|
+
throw new ContractError("No workflow run exists; start one first");
|
|
1330
|
+
value = projectWorkflow(state, admittedRequirements(state.run, state.run.workItems, workingTreeDigest(active.cwd)));
|
|
1331
|
+
}
|
|
1026
1332
|
else
|
|
1027
1333
|
throw new ContractError(`Unknown /bizar command: ${command}`);
|
|
1028
1334
|
}
|