@harness-engineering/intelligence 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +621 -2
- package/dist/index.d.ts +621 -2
- package/dist/index.js +415 -0
- package/dist/index.mjs +393 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -31,13 +31,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ACCEPTANCE_EVAL_SYSTEM_PROMPT: () => ACCEPTANCE_EVAL_SYSTEM_PROMPT,
|
|
34
|
+
AUTO_EXECUTE_CATEGORIES: () => AUTO_EXECUTE_CATEGORIES,
|
|
34
35
|
AcceptanceEvaluator: () => AcceptanceEvaluator,
|
|
35
36
|
AnthropicAnalysisProvider: () => AnthropicAnalysisProvider,
|
|
37
|
+
BLAST_TOLERANCE_ABS: () => BLAST_TOLERANCE_ABS,
|
|
38
|
+
BLAST_TOLERANCE_FACTOR: () => BLAST_TOLERANCE_FACTOR,
|
|
36
39
|
ClaudeCliAnalysisProvider: () => ClaudeCliAnalysisProvider,
|
|
37
40
|
DEFAULT_DEGRADE_AT_PCT: () => DEFAULT_DEGRADE_AT_PCT,
|
|
41
|
+
DEFAULT_RATCHET_CONFIG: () => DEFAULT_RATCHET_CONFIG,
|
|
42
|
+
DEFAULT_RETROSPECTIVE_CONFIG: () => DEFAULT_RETROSPECTIVE_CONFIG,
|
|
43
|
+
DEPTH_BY_LEVEL: () => DEPTH_BY_LEVEL,
|
|
38
44
|
ExecutionOutcomeConnector: () => ExecutionOutcomeConnector,
|
|
39
45
|
GraphValidator: () => GraphValidator,
|
|
40
46
|
IntelligencePipeline: () => IntelligencePipeline,
|
|
47
|
+
LEVEL_RANK: () => LEVEL_RANK,
|
|
41
48
|
OUTCOME_EVAL_SYSTEM_PROMPT: () => OUTCOME_EVAL_SYSTEM_PROMPT,
|
|
42
49
|
OpenAICompatibleAnalysisProvider: () => OpenAICompatibleAnalysisProvider,
|
|
43
50
|
OutcomeEvaluator: () => OutcomeEvaluator,
|
|
@@ -46,7 +53,9 @@ __export(index_exports, {
|
|
|
46
53
|
SENSITIVE_BLAST_THRESHOLD: () => SENSITIVE_BLAST_THRESHOLD,
|
|
47
54
|
STATIC_WEIGHTS: () => STATIC_WEIGHTS,
|
|
48
55
|
TIER_RANK: () => TIER_RANK,
|
|
56
|
+
V1_MAX_STAGE: () => V1_MAX_STAGE,
|
|
49
57
|
acceptanceVerdictSchema: () => acceptanceVerdictSchema,
|
|
58
|
+
aggregatePrecedent: () => aggregatePrecedent,
|
|
50
59
|
applyBudgetClamp: () => applyBudgetClamp,
|
|
51
60
|
baseTier: () => baseTier,
|
|
52
61
|
blastRadiusVeto: () => blastRadiusVeto,
|
|
@@ -54,6 +63,7 @@ __export(index_exports, {
|
|
|
54
63
|
buildSpecializationProfile: () => buildSpecializationProfile,
|
|
55
64
|
buildUserPrompt: () => buildUserPrompt2,
|
|
56
65
|
classify: () => classify,
|
|
66
|
+
compareToPrediction: () => compareToPrediction,
|
|
57
67
|
computeExpertiseLevel: () => computeExpertiseLevel,
|
|
58
68
|
computeHistoricalComplexity: () => computeHistoricalComplexity,
|
|
59
69
|
computePersonaEffectiveness: () => computePersonaEffectiveness,
|
|
@@ -62,11 +72,14 @@ __export(index_exports, {
|
|
|
62
72
|
computeStructuralComplexity: () => computeStructuralComplexity,
|
|
63
73
|
createCanaryAdapter: () => createCanaryAdapter,
|
|
64
74
|
decayWeight: () => decayWeight,
|
|
75
|
+
depthForLevel: () => depthForLevel,
|
|
65
76
|
deriveAcceptanceAuthority: () => deriveAcceptanceAuthority,
|
|
66
77
|
deriveAuthority: () => deriveAuthority,
|
|
67
78
|
deriveRequiredTier: () => deriveRequiredTier,
|
|
68
79
|
detectBlindSpots: () => detectBlindSpots,
|
|
80
|
+
dispatchableShapeKey: () => dispatchableShapeKey,
|
|
69
81
|
enrich: () => enrich,
|
|
82
|
+
extractEntities: () => extractEntities,
|
|
70
83
|
findingSchema: () => findingSchema,
|
|
71
84
|
githubToRawWorkItem: () => githubToRawWorkItem,
|
|
72
85
|
jiraToRawWorkItem: () => jiraToRawWorkItem,
|
|
@@ -74,16 +87,25 @@ __export(index_exports, {
|
|
|
74
87
|
llmTiebreak: () => llmTiebreak,
|
|
75
88
|
loadProfiles: () => loadProfiles,
|
|
76
89
|
manualToRawWorkItem: () => manualToRawWorkItem,
|
|
90
|
+
pilotScore: () => pilotScore,
|
|
91
|
+
precedentLookupFromRecords: () => precedentLookupFromRecords,
|
|
92
|
+
rankTriageCandidates: () => rankTriageCandidates,
|
|
77
93
|
recommendPersona: () => recommendPersona,
|
|
78
94
|
refreshProfiles: () => refreshProfiles,
|
|
95
|
+
resolveGoNoGo: () => resolveGoNoGo,
|
|
96
|
+
resolveGoNoGoStaged: () => resolveGoNoGoStaged,
|
|
79
97
|
resolveSection: () => resolveSection,
|
|
98
|
+
resolveStage: () => resolveStage,
|
|
99
|
+
runAutoBrainstorm: () => runAutoBrainstorm,
|
|
80
100
|
runGraphOnlyChecks: () => runGraphOnlyChecks,
|
|
81
101
|
runLlmSimulation: () => runLlmSimulation,
|
|
102
|
+
runScopingProbe: () => runScopingProbe,
|
|
82
103
|
runStaticPass: () => runStaticPass,
|
|
83
104
|
saveProfiles: () => saveProfiles,
|
|
84
105
|
scoreCML: () => score,
|
|
85
106
|
scoreToConcernSignals: () => scoreToConcernSignals,
|
|
86
107
|
serializeSignals: () => serializeSignals,
|
|
108
|
+
shapeKey: () => shapeKey,
|
|
87
109
|
temporalSuccessRate: () => temporalSuccessRate,
|
|
88
110
|
toRawWorkItem: () => toRawWorkItem,
|
|
89
111
|
verdictSchema: () => verdictSchema,
|
|
@@ -2344,16 +2366,394 @@ function deriveRequiredTier(complexity, risk, policy, spend, escalationFloor, sk
|
|
|
2344
2366
|
const clamped = applyBudgetClamp(base, risk, policy, spend);
|
|
2345
2367
|
return tierAtRank(Math.max(TIER_RANK[escalationFloor], TIER_RANK[clamped]));
|
|
2346
2368
|
}
|
|
2369
|
+
|
|
2370
|
+
// src/triage/record.ts
|
|
2371
|
+
function shapeKey(labels, category, level) {
|
|
2372
|
+
const sortedLabels = Array.from(
|
|
2373
|
+
new Set(labels.map((l) => l.trim().replace(/[,|]/g, "")).filter((l) => l.length > 0))
|
|
2374
|
+
).sort();
|
|
2375
|
+
return `${sortedLabels.join(",")}|${category}|${level}`;
|
|
2376
|
+
}
|
|
2377
|
+
function dispatchableShapeKey(labels, level) {
|
|
2378
|
+
return shapeKey(labels, "dispatchable", level);
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
// src/triage/precedent.ts
|
|
2382
|
+
function aggregatePrecedent(records, shapeKey2) {
|
|
2383
|
+
let matched = 0;
|
|
2384
|
+
let total = 0;
|
|
2385
|
+
for (const rec of records) {
|
|
2386
|
+
if (rec.shapeKey !== shapeKey2) continue;
|
|
2387
|
+
if (!rec.outcome) continue;
|
|
2388
|
+
total += 1;
|
|
2389
|
+
if (rec.outcome.matched) matched += 1;
|
|
2390
|
+
}
|
|
2391
|
+
if (total === 0) return { kind: "unknown" };
|
|
2392
|
+
return { kind: "rate", matched, total, rate: matched / total };
|
|
2393
|
+
}
|
|
2394
|
+
function precedentLookupFromRecords(records) {
|
|
2395
|
+
return {
|
|
2396
|
+
rateForShape: (shapeKey2) => aggregatePrecedent(records, shapeKey2)
|
|
2397
|
+
};
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
// src/triage/entities.ts
|
|
2401
|
+
var BACKTICKED_RE = /`([^`]+)`/g;
|
|
2402
|
+
var PATH_RE = /(?:\.\/)?(?:[A-Za-z0-9_@.-]+\/)+[A-Za-z0-9_.-]+/g;
|
|
2403
|
+
var CAMEL_RE = /\b([A-Z][a-z]+[A-Za-z0-9]*[A-Z][A-Za-z0-9]*|[a-z]+[A-Z][A-Za-z0-9]*)\b/g;
|
|
2404
|
+
var DOTTED_RE = /\b[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)+\b/g;
|
|
2405
|
+
function extractEntities(text) {
|
|
2406
|
+
if (typeof text !== "string") return [];
|
|
2407
|
+
const trimmed = text.trim();
|
|
2408
|
+
if (trimmed.length === 0) return [];
|
|
2409
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2410
|
+
const result = [];
|
|
2411
|
+
const add = (raw) => {
|
|
2412
|
+
const token = raw.trim();
|
|
2413
|
+
if (token.length === 0) return;
|
|
2414
|
+
if (seen.has(token)) return;
|
|
2415
|
+
seen.add(token);
|
|
2416
|
+
result.push(token);
|
|
2417
|
+
};
|
|
2418
|
+
for (const m of trimmed.matchAll(BACKTICKED_RE)) {
|
|
2419
|
+
const inner = m[1];
|
|
2420
|
+
if (inner !== void 0) add(inner);
|
|
2421
|
+
}
|
|
2422
|
+
for (const m of trimmed.matchAll(PATH_RE)) add(m[0]);
|
|
2423
|
+
for (const m of trimmed.matchAll(CAMEL_RE)) add(m[0]);
|
|
2424
|
+
for (const m of trimmed.matchAll(DOTTED_RE)) add(m[0]);
|
|
2425
|
+
return result;
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
// src/triage/probe.ts
|
|
2429
|
+
var import_zod7 = require("zod");
|
|
2430
|
+
var DEFAULT_CONFIG = {
|
|
2431
|
+
boundedScopeMax: 40,
|
|
2432
|
+
dispatchConfidence: "medium",
|
|
2433
|
+
precedentBlockRate: 0,
|
|
2434
|
+
precedentMinSample: 1
|
|
2435
|
+
};
|
|
2436
|
+
var OpenDecisionsSchema = import_zod7.z.object({
|
|
2437
|
+
openDecisions: import_zod7.z.array(import_zod7.z.object({ question: import_zod7.z.string() })).describe(
|
|
2438
|
+
"Choices requiring human judgment (API shape, product tradeoff, irreversible action)"
|
|
2439
|
+
)
|
|
2440
|
+
});
|
|
2441
|
+
var OPEN_DECISIONS_SYSTEM_PROMPT = "You are triaging a backlog item for autonomous execution. Identify ONLY choices that genuinely require human judgment before an agent could safely proceed \u2014 API/interface shape, product tradeoffs, or irreversible/outward-facing actions. If the item is fully scoped and an agent could proceed without a human decision, return an empty array. Do not invent decisions; be conservative about what truly needs a human.";
|
|
2442
|
+
async function runScopingProbe(input, deps = {}) {
|
|
2443
|
+
const config = { ...DEFAULT_CONFIG, ...deps.config };
|
|
2444
|
+
const scope = await runScopeLever(input, deps.graph);
|
|
2445
|
+
const semanticRead = await runSemanticReadLever(input, scope.value, deps);
|
|
2446
|
+
const openDecisions = await runOpenDecisionsLever(input, deps.provider);
|
|
2447
|
+
const precedent = runPrecedentLever(input, semanticRead.value, deps.precedent);
|
|
2448
|
+
const levers = { scope, semanticRead, openDecisions, precedent };
|
|
2449
|
+
const verdict = semanticRead.value === "unknown" ? { level: "moderate", confidence: "low", signals: {}, source: "static" } : semanticRead.value;
|
|
2450
|
+
const { dispatchable, holdReason } = gate(levers, config);
|
|
2451
|
+
const rationale = buildRationale(levers, dispatchable, holdReason);
|
|
2452
|
+
return {
|
|
2453
|
+
externalId: input.externalId,
|
|
2454
|
+
verdict,
|
|
2455
|
+
dispatchable,
|
|
2456
|
+
...holdReason !== void 0 ? { holdReason } : {},
|
|
2457
|
+
levers,
|
|
2458
|
+
rationale
|
|
2459
|
+
};
|
|
2460
|
+
}
|
|
2461
|
+
async function runScopeLever(input, graph) {
|
|
2462
|
+
if (graph === void 0) {
|
|
2463
|
+
return { value: "unknown", reason: "scope: no graph seam available" };
|
|
2464
|
+
}
|
|
2465
|
+
try {
|
|
2466
|
+
const resolved = [];
|
|
2467
|
+
for (const candidate of input.entityCandidates) {
|
|
2468
|
+
const hit = await graph.resolve(candidate);
|
|
2469
|
+
if (hit) resolved.push(hit);
|
|
2470
|
+
}
|
|
2471
|
+
const blastRadius = resolved.reduce((max, r) => Math.max(max, r.blastRadius), 0);
|
|
2472
|
+
const estimate = {
|
|
2473
|
+
candidates: input.entityCandidates,
|
|
2474
|
+
resolved,
|
|
2475
|
+
blastRadius,
|
|
2476
|
+
layersTouched: Math.min(resolved.length, 4),
|
|
2477
|
+
filesTouched: resolved.length
|
|
2478
|
+
};
|
|
2479
|
+
const note = resolved.length === 0 ? "scope: no entity resolved in graph (unresolved-scope)" : `scope: ${resolved.length} entity(ies) resolved, blastRadius ${blastRadius}`;
|
|
2480
|
+
return { value: estimate, reason: note };
|
|
2481
|
+
} catch (err) {
|
|
2482
|
+
return { value: "unknown", reason: `scope: graph lookup failed \u2014 ${errMsg(err)}` };
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
async function runSemanticReadLever(input, scope, deps) {
|
|
2486
|
+
try {
|
|
2487
|
+
const signals = {
|
|
2488
|
+
descriptionLength: input.taskText.descriptionLength,
|
|
2489
|
+
specExists: input.taskText.specExists,
|
|
2490
|
+
acceptanceMeasurable: input.taskText.acceptanceMeasurable,
|
|
2491
|
+
...scope !== "unknown" && scope.resolved.length > 0 ? {
|
|
2492
|
+
filesTouched: scope.filesTouched,
|
|
2493
|
+
layersTouched: scope.layersTouched,
|
|
2494
|
+
blastRadius: scope.blastRadius
|
|
2495
|
+
} : {}
|
|
2496
|
+
};
|
|
2497
|
+
const phase = scope !== "unknown" && scope.resolved.length > 0 ? "post-diff" : "pre-diff";
|
|
2498
|
+
const classifyInput = {
|
|
2499
|
+
signals,
|
|
2500
|
+
phase,
|
|
2501
|
+
riskHigh: input.riskHigh === true,
|
|
2502
|
+
prompt: input.taskText.prompt
|
|
2503
|
+
};
|
|
2504
|
+
const verdict = await classify(classifyInput, deps.provider, deps.models);
|
|
2505
|
+
return { value: verdict, reason: `semantic-read: ${verdict.level}/${verdict.confidence}` };
|
|
2506
|
+
} catch (err) {
|
|
2507
|
+
return { value: "unknown", reason: `semantic-read: classify failed \u2014 ${errMsg(err)}` };
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
async function runOpenDecisionsLever(input, provider) {
|
|
2511
|
+
if (provider === void 0) {
|
|
2512
|
+
return { value: "unknown", reason: "open-decisions: no provider (offline)" };
|
|
2513
|
+
}
|
|
2514
|
+
try {
|
|
2515
|
+
const { result } = await provider.analyze({
|
|
2516
|
+
prompt: input.taskText.prompt,
|
|
2517
|
+
systemPrompt: OPEN_DECISIONS_SYSTEM_PROMPT,
|
|
2518
|
+
responseSchema: OpenDecisionsSchema,
|
|
2519
|
+
maxTokens: 512
|
|
2520
|
+
});
|
|
2521
|
+
const decisions = result.openDecisions ?? [];
|
|
2522
|
+
const note = decisions.length === 0 ? "open-decisions: none surfaced" : `open-decisions: ${decisions.length} requiring human judgment`;
|
|
2523
|
+
return { value: decisions, reason: note };
|
|
2524
|
+
} catch (err) {
|
|
2525
|
+
return { value: "unknown", reason: `open-decisions: assessment failed \u2014 ${errMsg(err)}` };
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
function runPrecedentLever(input, verdict, precedent) {
|
|
2529
|
+
if (precedent === void 0) {
|
|
2530
|
+
return { value: "unknown", reason: "precedent: no store (cold-start)" };
|
|
2531
|
+
}
|
|
2532
|
+
try {
|
|
2533
|
+
const level = verdict === "unknown" ? "moderate" : verdict.level;
|
|
2534
|
+
const key = dispatchableShapeKey(input.labels, level);
|
|
2535
|
+
const rate = precedent.rateForShape(key);
|
|
2536
|
+
const note = rate.kind === "unknown" ? "precedent: unknown for this shape (no graded records)" : `precedent: ${rate.matched}/${rate.total} (${(rate.rate * 100).toFixed(0)}%)`;
|
|
2537
|
+
return { value: rate, reason: note };
|
|
2538
|
+
} catch (err) {
|
|
2539
|
+
return { value: "unknown", reason: `precedent: lookup failed \u2014 ${errMsg(err)}` };
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
function gate(levers, config) {
|
|
2543
|
+
const scope = levers.scope.value;
|
|
2544
|
+
if (scope === "unknown" || scope.resolved.length === 0) {
|
|
2545
|
+
return { dispatchable: false, holdReason: "unresolved-scope" };
|
|
2546
|
+
}
|
|
2547
|
+
if (scope.blastRadius > config.boundedScopeMax) {
|
|
2548
|
+
return { dispatchable: false, holdReason: "unresolved-scope" };
|
|
2549
|
+
}
|
|
2550
|
+
const read = levers.semanticRead.value;
|
|
2551
|
+
if (read === "unknown") {
|
|
2552
|
+
return { dispatchable: false, holdReason: "not-in-band" };
|
|
2553
|
+
}
|
|
2554
|
+
const inBand = read.level === "trivial" || read.level === "simple";
|
|
2555
|
+
const confidentEnough = CONFIDENCE_RANK[read.confidence] >= CONFIDENCE_RANK[config.dispatchConfidence];
|
|
2556
|
+
if (!inBand || !confidentEnough) {
|
|
2557
|
+
return { dispatchable: false, holdReason: "not-in-band" };
|
|
2558
|
+
}
|
|
2559
|
+
const decisions = levers.openDecisions.value;
|
|
2560
|
+
if (decisions === "unknown") {
|
|
2561
|
+
return { dispatchable: false, holdReason: "read-incomplete" };
|
|
2562
|
+
}
|
|
2563
|
+
if (decisions.length > 0) {
|
|
2564
|
+
return { dispatchable: false, holdReason: "open-decision" };
|
|
2565
|
+
}
|
|
2566
|
+
const precedent = levers.precedent.value;
|
|
2567
|
+
if (precedent !== "unknown" && precedent.kind === "rate" && precedent.total >= (config.precedentMinSample ?? 1) && precedent.rate <= (config.precedentBlockRate ?? 0)) {
|
|
2568
|
+
return { dispatchable: false, holdReason: "precedent-contradicts" };
|
|
2569
|
+
}
|
|
2570
|
+
return { dispatchable: true };
|
|
2571
|
+
}
|
|
2572
|
+
function buildRationale(levers, dispatchable, holdReason) {
|
|
2573
|
+
const parts = [];
|
|
2574
|
+
for (const lever of [levers.scope, levers.semanticRead, levers.openDecisions, levers.precedent]) {
|
|
2575
|
+
if (lever.reason) parts.push(lever.reason);
|
|
2576
|
+
}
|
|
2577
|
+
const decision = dispatchable ? "DISPATCHABLE \u2014 all levers corroborate." : `HELD (${holdReason}).`;
|
|
2578
|
+
return `${decision} ${parts.join("; ")}`;
|
|
2579
|
+
}
|
|
2580
|
+
function errMsg(err) {
|
|
2581
|
+
return err instanceof Error ? err.message : String(err);
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
// src/triage/rank.ts
|
|
2585
|
+
function pilotScore(c) {
|
|
2586
|
+
const effort = c.effort > 0 ? c.effort : 1e-6;
|
|
2587
|
+
const score2 = c.impact * c.confidence / effort;
|
|
2588
|
+
return Number.isFinite(score2) ? score2 : 0;
|
|
2589
|
+
}
|
|
2590
|
+
function rankTriageCandidates(candidates) {
|
|
2591
|
+
return [...candidates].sort((a, b) => {
|
|
2592
|
+
const sa = pilotScore(a);
|
|
2593
|
+
const sb = pilotScore(b);
|
|
2594
|
+
if (sa !== sb) return sb - sa;
|
|
2595
|
+
if (a.impact !== b.impact) return b.impact - a.impact;
|
|
2596
|
+
return a.externalId < b.externalId ? -1 : a.externalId > b.externalId ? 1 : 0;
|
|
2597
|
+
});
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
// src/triage/brainstorm/types.ts
|
|
2601
|
+
var DEPTH_BY_LEVEL = {
|
|
2602
|
+
trivial: { maxForks: 2 },
|
|
2603
|
+
simple: { maxForks: 4 },
|
|
2604
|
+
// moderate/complex are OUT of the eligible band (the probe holds them to human) — a depth
|
|
2605
|
+
// is defined only so the mapping is total; the brainstorm should never run on them.
|
|
2606
|
+
moderate: { maxForks: 4 },
|
|
2607
|
+
complex: { maxForks: 4 }
|
|
2608
|
+
};
|
|
2609
|
+
function depthForLevel(level) {
|
|
2610
|
+
return DEPTH_BY_LEVEL[level] ?? { maxForks: 2 };
|
|
2611
|
+
}
|
|
2612
|
+
|
|
2613
|
+
// src/triage/brainstorm/runner.ts
|
|
2614
|
+
async function runAutoBrainstorm(input, generator, depth) {
|
|
2615
|
+
const accepted = [];
|
|
2616
|
+
const ceiling = Math.max(0, depth.maxForks);
|
|
2617
|
+
for (let index = 0; index < ceiling; index++) {
|
|
2618
|
+
let decision;
|
|
2619
|
+
try {
|
|
2620
|
+
decision = await generator.next(index, accepted);
|
|
2621
|
+
} catch (err) {
|
|
2622
|
+
return {
|
|
2623
|
+
kind: "halted",
|
|
2624
|
+
fork: { id: `fork-${index}`, question: "brainstorm errored before deciding", options: [] },
|
|
2625
|
+
reason: "error",
|
|
2626
|
+
detail: errMsg2(err)
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2629
|
+
if (decision === null || decision === void 0) break;
|
|
2630
|
+
if (decision.confidence !== "high") {
|
|
2631
|
+
return {
|
|
2632
|
+
kind: "halted",
|
|
2633
|
+
fork: decision.fork,
|
|
2634
|
+
reason: "low-confidence",
|
|
2635
|
+
detail: `fork '${decision.fork.id}' recommended '${decision.recommendation}' at confidence '${decision.confidence}' (below the 'high' bar) \u2014 ${decision.rationale}`
|
|
2636
|
+
};
|
|
2637
|
+
}
|
|
2638
|
+
accepted.push(decision);
|
|
2639
|
+
}
|
|
2640
|
+
const spec = {
|
|
2641
|
+
externalId: input.externalId,
|
|
2642
|
+
title: input.title,
|
|
2643
|
+
summary: input.summary,
|
|
2644
|
+
decisions: accepted
|
|
2645
|
+
};
|
|
2646
|
+
return { kind: "completed", spec };
|
|
2647
|
+
}
|
|
2648
|
+
function errMsg2(err) {
|
|
2649
|
+
return err instanceof Error ? err.message : String(err);
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
// src/triage/retrospective.ts
|
|
2653
|
+
var LEVEL_RANK = {
|
|
2654
|
+
trivial: 0,
|
|
2655
|
+
simple: 1,
|
|
2656
|
+
moderate: 2,
|
|
2657
|
+
complex: 3
|
|
2658
|
+
};
|
|
2659
|
+
var BLAST_TOLERANCE_FACTOR = 1.5;
|
|
2660
|
+
var BLAST_TOLERANCE_ABS = 2;
|
|
2661
|
+
var DEFAULT_RETROSPECTIVE_CONFIG = { exceededByBands: 1 };
|
|
2662
|
+
function blockEscalate(exceededBy = 1) {
|
|
2663
|
+
return { matched: false, exceededBy: Math.max(1, exceededBy), action: "block-escalate" };
|
|
2664
|
+
}
|
|
2665
|
+
function isLevel(value) {
|
|
2666
|
+
return typeof value === "string" && Object.prototype.hasOwnProperty.call(LEVEL_RANK, value);
|
|
2667
|
+
}
|
|
2668
|
+
function blastRadiusOf(verdict) {
|
|
2669
|
+
const raw = verdict.signals?.blastRadius;
|
|
2670
|
+
return typeof raw === "number" && Number.isFinite(raw) ? raw : void 0;
|
|
2671
|
+
}
|
|
2672
|
+
function compareToPrediction(prediction, postDiffVerdict, config = DEFAULT_RETROSPECTIVE_CONFIG) {
|
|
2673
|
+
if (prediction == null || postDiffVerdict == null) return blockEscalate();
|
|
2674
|
+
const predictedLevel = prediction.verdict?.level;
|
|
2675
|
+
const actualLevel = postDiffVerdict.level;
|
|
2676
|
+
if (!isLevel(predictedLevel) || !isLevel(actualLevel)) return blockEscalate();
|
|
2677
|
+
const levelDelta = LEVEL_RANK[actualLevel] - LEVEL_RANK[predictedLevel];
|
|
2678
|
+
const bandThreshold = Math.max(1, Math.floor(config.exceededByBands));
|
|
2679
|
+
if (levelDelta >= bandThreshold) return blockEscalate(levelDelta);
|
|
2680
|
+
const predictedScope = typeof prediction.scopeEstimate === "number" && Number.isFinite(prediction.scopeEstimate) ? prediction.scopeEstimate : 0;
|
|
2681
|
+
const actualBlast = blastRadiusOf(postDiffVerdict);
|
|
2682
|
+
if (actualBlast !== void 0) {
|
|
2683
|
+
const threshold = predictedScope * BLAST_TOLERANCE_FACTOR + BLAST_TOLERANCE_ABS;
|
|
2684
|
+
if (actualBlast > threshold) return blockEscalate();
|
|
2685
|
+
}
|
|
2686
|
+
return { matched: true, exceededBy: 0, action: "verify" };
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
// src/triage/ratchet.ts
|
|
2690
|
+
var V1_MAX_STAGE = 2;
|
|
2691
|
+
var DEFAULT_RATCHET_CONFIG = {
|
|
2692
|
+
threshold: 0.9,
|
|
2693
|
+
minSample: 5,
|
|
2694
|
+
window: 10
|
|
2695
|
+
};
|
|
2696
|
+
function resolveStage(history, config = DEFAULT_RATCHET_CONFIG) {
|
|
2697
|
+
const window = Math.max(1, Math.floor(config.window));
|
|
2698
|
+
const ordered = history.length > 1 ? [...history].sort((a, b) => (a.ts ?? "").localeCompare(b.ts ?? "")) : history;
|
|
2699
|
+
const recent = ordered.slice(-window);
|
|
2700
|
+
if (recent.length < config.minSample) return 1;
|
|
2701
|
+
if (recent[recent.length - 1]?.matched === false) return 1;
|
|
2702
|
+
const matched = recent.reduce((n, o) => o.matched ? n + 1 : n, 0);
|
|
2703
|
+
const rate = matched / recent.length;
|
|
2704
|
+
if (rate < config.threshold) return 1;
|
|
2705
|
+
return Math.min(2, V1_MAX_STAGE);
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
// src/triage/gate.ts
|
|
2709
|
+
var AUTO_EXECUTE_CATEGORIES = /* @__PURE__ */ new Set([
|
|
2710
|
+
"quick-fix",
|
|
2711
|
+
"diagnostic"
|
|
2712
|
+
]);
|
|
2713
|
+
function resolveGoNoGoStaged(candidates) {
|
|
2714
|
+
const approved = [];
|
|
2715
|
+
const held = [];
|
|
2716
|
+
for (const c of candidates) {
|
|
2717
|
+
if (c.effectiveStage !== 1 && c.effectiveStage !== 2) {
|
|
2718
|
+
held.push({
|
|
2719
|
+
externalId: c.externalId,
|
|
2720
|
+
category: c.category,
|
|
2721
|
+
reason: "ratchet-stage-unsupported"
|
|
2722
|
+
});
|
|
2723
|
+
continue;
|
|
2724
|
+
}
|
|
2725
|
+
if (!AUTO_EXECUTE_CATEGORIES.has(c.category)) {
|
|
2726
|
+
held.push({ externalId: c.externalId, category: c.category, reason: "not-auto-executable" });
|
|
2727
|
+
continue;
|
|
2728
|
+
}
|
|
2729
|
+
if (!c.humanApproved) {
|
|
2730
|
+
held.push({ externalId: c.externalId, category: c.category, reason: "awaiting-human-go" });
|
|
2731
|
+
continue;
|
|
2732
|
+
}
|
|
2733
|
+
approved.push({ ...c, effectiveStage: c.effectiveStage });
|
|
2734
|
+
}
|
|
2735
|
+
return { approved, held };
|
|
2736
|
+
}
|
|
2737
|
+
function resolveGoNoGo(candidates, stage) {
|
|
2738
|
+
return resolveGoNoGoStaged(candidates.map((c) => ({ ...c, effectiveStage: stage })));
|
|
2739
|
+
}
|
|
2347
2740
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2348
2741
|
0 && (module.exports = {
|
|
2349
2742
|
ACCEPTANCE_EVAL_SYSTEM_PROMPT,
|
|
2743
|
+
AUTO_EXECUTE_CATEGORIES,
|
|
2350
2744
|
AcceptanceEvaluator,
|
|
2351
2745
|
AnthropicAnalysisProvider,
|
|
2746
|
+
BLAST_TOLERANCE_ABS,
|
|
2747
|
+
BLAST_TOLERANCE_FACTOR,
|
|
2352
2748
|
ClaudeCliAnalysisProvider,
|
|
2353
2749
|
DEFAULT_DEGRADE_AT_PCT,
|
|
2750
|
+
DEFAULT_RATCHET_CONFIG,
|
|
2751
|
+
DEFAULT_RETROSPECTIVE_CONFIG,
|
|
2752
|
+
DEPTH_BY_LEVEL,
|
|
2354
2753
|
ExecutionOutcomeConnector,
|
|
2355
2754
|
GraphValidator,
|
|
2356
2755
|
IntelligencePipeline,
|
|
2756
|
+
LEVEL_RANK,
|
|
2357
2757
|
OUTCOME_EVAL_SYSTEM_PROMPT,
|
|
2358
2758
|
OpenAICompatibleAnalysisProvider,
|
|
2359
2759
|
OutcomeEvaluator,
|
|
@@ -2362,7 +2762,9 @@ function deriveRequiredTier(complexity, risk, policy, spend, escalationFloor, sk
|
|
|
2362
2762
|
SENSITIVE_BLAST_THRESHOLD,
|
|
2363
2763
|
STATIC_WEIGHTS,
|
|
2364
2764
|
TIER_RANK,
|
|
2765
|
+
V1_MAX_STAGE,
|
|
2365
2766
|
acceptanceVerdictSchema,
|
|
2767
|
+
aggregatePrecedent,
|
|
2366
2768
|
applyBudgetClamp,
|
|
2367
2769
|
baseTier,
|
|
2368
2770
|
blastRadiusVeto,
|
|
@@ -2370,6 +2772,7 @@ function deriveRequiredTier(complexity, risk, policy, spend, escalationFloor, sk
|
|
|
2370
2772
|
buildSpecializationProfile,
|
|
2371
2773
|
buildUserPrompt,
|
|
2372
2774
|
classify,
|
|
2775
|
+
compareToPrediction,
|
|
2373
2776
|
computeExpertiseLevel,
|
|
2374
2777
|
computeHistoricalComplexity,
|
|
2375
2778
|
computePersonaEffectiveness,
|
|
@@ -2378,11 +2781,14 @@ function deriveRequiredTier(complexity, risk, policy, spend, escalationFloor, sk
|
|
|
2378
2781
|
computeStructuralComplexity,
|
|
2379
2782
|
createCanaryAdapter,
|
|
2380
2783
|
decayWeight,
|
|
2784
|
+
depthForLevel,
|
|
2381
2785
|
deriveAcceptanceAuthority,
|
|
2382
2786
|
deriveAuthority,
|
|
2383
2787
|
deriveRequiredTier,
|
|
2384
2788
|
detectBlindSpots,
|
|
2789
|
+
dispatchableShapeKey,
|
|
2385
2790
|
enrich,
|
|
2791
|
+
extractEntities,
|
|
2386
2792
|
findingSchema,
|
|
2387
2793
|
githubToRawWorkItem,
|
|
2388
2794
|
jiraToRawWorkItem,
|
|
@@ -2390,16 +2796,25 @@ function deriveRequiredTier(complexity, risk, policy, spend, escalationFloor, sk
|
|
|
2390
2796
|
llmTiebreak,
|
|
2391
2797
|
loadProfiles,
|
|
2392
2798
|
manualToRawWorkItem,
|
|
2799
|
+
pilotScore,
|
|
2800
|
+
precedentLookupFromRecords,
|
|
2801
|
+
rankTriageCandidates,
|
|
2393
2802
|
recommendPersona,
|
|
2394
2803
|
refreshProfiles,
|
|
2804
|
+
resolveGoNoGo,
|
|
2805
|
+
resolveGoNoGoStaged,
|
|
2395
2806
|
resolveSection,
|
|
2807
|
+
resolveStage,
|
|
2808
|
+
runAutoBrainstorm,
|
|
2396
2809
|
runGraphOnlyChecks,
|
|
2397
2810
|
runLlmSimulation,
|
|
2811
|
+
runScopingProbe,
|
|
2398
2812
|
runStaticPass,
|
|
2399
2813
|
saveProfiles,
|
|
2400
2814
|
scoreCML,
|
|
2401
2815
|
scoreToConcernSignals,
|
|
2402
2816
|
serializeSignals,
|
|
2817
|
+
shapeKey,
|
|
2403
2818
|
temporalSuccessRate,
|
|
2404
2819
|
toRawWorkItem,
|
|
2405
2820
|
verdictSchema,
|