@harness-engineering/intelligence 0.4.3 → 0.6.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 +160 -2
- package/dist/index.d.ts +160 -2
- package/dist/index.js +243 -1
- package/dist/index.mjs +230 -1
- package/package.json +3 -3
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _harness_engineering_types from '@harness-engineering/types';
|
|
2
|
-
import { Issue, ConcernSignal, ScopeTier, EscalationConfig } from '@harness-engineering/types';
|
|
2
|
+
import { Issue, ConcernSignal, ScopeTier, EscalationConfig, ComplexityLevel, ComplexityVerdict, CapabilityTier, RoutingRisk, RoutingPolicy } from '@harness-engineering/types';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { GraphStore } from '@harness-engineering/graph';
|
|
5
5
|
|
|
@@ -406,6 +406,14 @@ interface OpenAICompatibleProviderOptions {
|
|
|
406
406
|
baseUrl: string;
|
|
407
407
|
/** Default model name (e.g., 'deepseek-coder-v2'). */
|
|
408
408
|
defaultModel?: string;
|
|
409
|
+
/**
|
|
410
|
+
* Consumption Phase 1 (T3): live model resolver, read at request time. When
|
|
411
|
+
* provided and it returns a non-empty name, that name is used in preference to
|
|
412
|
+
* `defaultModel` so a pool install/swap is consumed by analysis without a
|
|
413
|
+
* restart. `request.model` (an explicit per-call override) still wins; a
|
|
414
|
+
* null/undefined/empty return falls through to `defaultModel`.
|
|
415
|
+
*/
|
|
416
|
+
getModel?: () => string | null | undefined;
|
|
409
417
|
/** Request timeout in ms (default: 90000). */
|
|
410
418
|
timeoutMs?: number;
|
|
411
419
|
/**
|
|
@@ -430,6 +438,7 @@ interface OpenAICompatibleProviderOptions {
|
|
|
430
438
|
declare class OpenAICompatibleAnalysisProvider implements AnalysisProvider {
|
|
431
439
|
private readonly client;
|
|
432
440
|
private readonly defaultModel;
|
|
441
|
+
private readonly getModel?;
|
|
433
442
|
private readonly promptSuffix;
|
|
434
443
|
private readonly jsonMode;
|
|
435
444
|
constructor(options: OpenAICompatibleProviderOptions);
|
|
@@ -1333,4 +1342,153 @@ declare function saveProfiles(projectRoot: string, store: ProfileStore): void;
|
|
|
1333
1342
|
*/
|
|
1334
1343
|
declare function refreshProfiles(projectRoot: string, graphStore: GraphStore, opts?: Omit<SpecializationOptions, 'persona'>): ProfileStore;
|
|
1335
1344
|
|
|
1336
|
-
|
|
1345
|
+
/** Which signal set is available at this invocation phase (S3-001). */
|
|
1346
|
+
type Phase = 'pre-diff' | 'post-diff';
|
|
1347
|
+
/** Raw signals gathered for the static pass. Diff-based fields are undefined pre-diff. */
|
|
1348
|
+
interface ComplexitySignals {
|
|
1349
|
+
/** Files touched by the diff/target. Undefined pre-diff. */
|
|
1350
|
+
filesTouched?: number;
|
|
1351
|
+
/** Distinct architectural layers touched. Undefined pre-diff. */
|
|
1352
|
+
layersTouched?: number;
|
|
1353
|
+
/** compute_blast_radius result. Undefined pre-diff. */
|
|
1354
|
+
blastRadius?: number;
|
|
1355
|
+
/** hotspot × churn heat. Undefined pre-diff. */
|
|
1356
|
+
hotspotChurn?: number;
|
|
1357
|
+
/** Text-only fallback signals (always available). */
|
|
1358
|
+
descriptionLength: number;
|
|
1359
|
+
specExists: boolean;
|
|
1360
|
+
acceptanceMeasurable: boolean;
|
|
1361
|
+
}
|
|
1362
|
+
/** Provisional static verdict before any LLM tie-break. */
|
|
1363
|
+
interface StaticVerdict {
|
|
1364
|
+
level: ComplexityLevel;
|
|
1365
|
+
confidence: 'high' | 'medium' | 'low';
|
|
1366
|
+
/** Serialized subset of signals for the ComplexityVerdict.signals map. */
|
|
1367
|
+
signals: Record<string, number | boolean | string>;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/** Inputs to the cheap-first complexity cascade (D4). */
|
|
1371
|
+
interface ClassifyInput {
|
|
1372
|
+
signals: ComplexitySignals;
|
|
1373
|
+
phase: Phase;
|
|
1374
|
+
/** Whether the invocation's risk band is high (drives standard-tier escalation). */
|
|
1375
|
+
riskHigh: boolean;
|
|
1376
|
+
/** Prompt handed to the LLM tie-break / escalation. */
|
|
1377
|
+
prompt: string;
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* D4 cascade: static pass → (if low confidence) fast-tier tie-break → (if still
|
|
1381
|
+
* low AND risk high) standard-tier escalation. Emits a `ComplexityVerdict` whose
|
|
1382
|
+
* `source` records which stage produced it. The static-only path resolves
|
|
1383
|
+
* without any LLM call ("never pay strong to route"); when `provider` is absent
|
|
1384
|
+
* the classifier stays fully offline and returns the static verdict.
|
|
1385
|
+
*
|
|
1386
|
+
* The LLM only sets `level`/`confidence`; the tier is always TS-derived (D3).
|
|
1387
|
+
*/
|
|
1388
|
+
declare function classify(input: ClassifyInput, provider?: AnalysisProvider, models?: {
|
|
1389
|
+
fast?: string;
|
|
1390
|
+
standard?: string;
|
|
1391
|
+
}): Promise<ComplexityVerdict>;
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* Documented seed weights for the free static pass (D4a). Each raw signal is
|
|
1395
|
+
* normalized against a reference maximum, multiplied by its weight, and the
|
|
1396
|
+
* weighted contributions are summed and re-normalized to a [0,1] score.
|
|
1397
|
+
*
|
|
1398
|
+
* Diff-based signals dominate post-diff; text-only signals carry the pre-diff
|
|
1399
|
+
* pass. Weights are tunable (DEFERRABLE per plan) — this is a documented seed.
|
|
1400
|
+
*/
|
|
1401
|
+
declare const STATIC_WEIGHTS: {
|
|
1402
|
+
readonly filesTouched: 0.25;
|
|
1403
|
+
readonly layersTouched: 0.2;
|
|
1404
|
+
readonly blastRadius: 0.3;
|
|
1405
|
+
readonly hotspotChurn: 0.1;
|
|
1406
|
+
/** Text-only signals — the only inputs available pre-diff. */
|
|
1407
|
+
readonly descriptionLength: 0.1;
|
|
1408
|
+
/** A present spec / measurable acceptance *lowers* complexity (well-scoped). */
|
|
1409
|
+
readonly specExists: 0.025;
|
|
1410
|
+
readonly acceptanceMeasurable: 0.025;
|
|
1411
|
+
};
|
|
1412
|
+
/**
|
|
1413
|
+
* D4a: free static pass. Phase-aware (S3-001): pre-diff uses text-only signals
|
|
1414
|
+
* and caps confidence at `medium`; post-diff uses the full signal set. Pure —
|
|
1415
|
+
* never calls an LLM. `source` is stamped by the classifier, not here.
|
|
1416
|
+
*/
|
|
1417
|
+
declare function runStaticPass(signals: ComplexitySignals, phase: Phase): StaticVerdict;
|
|
1418
|
+
|
|
1419
|
+
interface TiebreakResult {
|
|
1420
|
+
level: ComplexityLevel;
|
|
1421
|
+
confidence: 'high' | 'medium' | 'low';
|
|
1422
|
+
}
|
|
1423
|
+
/** D4b: fast-tier structured tie-break. Never sets a tier; falls back conservatively on error. */
|
|
1424
|
+
declare function llmTiebreak(provider: AnalysisProvider, prompt: string, fastModel?: string): Promise<TiebreakResult>;
|
|
1425
|
+
|
|
1426
|
+
declare const TIER_RANK: {
|
|
1427
|
+
fast: number;
|
|
1428
|
+
standard: number;
|
|
1429
|
+
strong: number;
|
|
1430
|
+
};
|
|
1431
|
+
declare const RANK_TIER: readonly ["fast", "standard", "strong"];
|
|
1432
|
+
/**
|
|
1433
|
+
* Documented seed threshold for the D5 high-blast veto. The spec lists
|
|
1434
|
+
* sensitive-path / core|types layer / public API explicitly but pins no numeric
|
|
1435
|
+
* blast threshold, so this is a plan-chosen seed — overridable later.
|
|
1436
|
+
*/
|
|
1437
|
+
declare const SENSITIVE_BLAST_THRESHOLD = 25;
|
|
1438
|
+
/**
|
|
1439
|
+
* D5: any sensitive-path / core|types layer / public API / high blast → force
|
|
1440
|
+
* `strong`, regardless of complexity (SC5). This is a HARD floor; downstream
|
|
1441
|
+
* budget clamping (D8) must not undercut it.
|
|
1442
|
+
*/
|
|
1443
|
+
declare function blastRadiusVeto(risk?: RoutingRisk): boolean;
|
|
1444
|
+
/**
|
|
1445
|
+
* Pre-budget tier resolution (Task 7): skillTierOverride → matrix → D5 veto →
|
|
1446
|
+
* low-confidence bump. Pure; the LLM never influences it (mirrors
|
|
1447
|
+
* outcome-eval/authority.ts). Task 8's `deriveRequiredTier` calls this then
|
|
1448
|
+
* applies the D8 budget clamp and D10 escalation floor.
|
|
1449
|
+
*
|
|
1450
|
+
* SC6: a `low`-confidence verdict degrades the tier UP one step (never below the
|
|
1451
|
+
* matrix default and never to a cheaper tier) — uncertainty routes to a more
|
|
1452
|
+
* capable model, never a Tier-A cheap one.
|
|
1453
|
+
*/
|
|
1454
|
+
declare function baseTier(complexity: ComplexityVerdict, risk: RoutingRisk | undefined, policy: RoutingPolicy, skillKey?: string): CapabilityTier;
|
|
1455
|
+
/** Default budget degrade threshold (% of cap) when policy omits one (D8). */
|
|
1456
|
+
declare const DEFAULT_DEGRADE_AT_PCT = 90;
|
|
1457
|
+
/**
|
|
1458
|
+
* D8: budget-pressure tier clamp. Two thresholds:
|
|
1459
|
+
*
|
|
1460
|
+
* - **Soft (`degradeAtPct`, default 90%):** clamp the tier DOWN one step
|
|
1461
|
+
* (`strong→standard→fast`, `fast→fast`) — a lagging degrade signal.
|
|
1462
|
+
* - **Hard (100% of `capUsd`):** for `degrade`/`pause` policies, force the tier
|
|
1463
|
+
* all the way to `fast` — the strongest sound floor on the routing DECISION
|
|
1464
|
+
* (it is not an admission gate; the monotonic accumulator lags under
|
|
1465
|
+
* concurrency, so it cannot prevent overshoot, only route the cheapest tier
|
|
1466
|
+
* once the read crosses the cap). `human` mode is handled one layer up in
|
|
1467
|
+
* `AdaptiveRouter.route()`, which surfaces the unit to a steward instead of
|
|
1468
|
+
* routing; here it falls through to the soft one-step degrade.
|
|
1469
|
+
*
|
|
1470
|
+
* The D5 blast-radius veto is a HARD `strong` floor the clamp must NOT undercut
|
|
1471
|
+
* (SC5 says sensitive-path / core|types / publicApi force `strong` "regardless"),
|
|
1472
|
+
* so a vetoed request stays `strong` even at the hard cap — the veto guard sits
|
|
1473
|
+
* ABOVE both the hard-floor and the soft-step branches. No budget block ⇒ no clamp.
|
|
1474
|
+
*/
|
|
1475
|
+
declare function applyBudgetClamp(tier: CapabilityTier, risk: RoutingRisk | undefined, policy: RoutingPolicy, spend: {
|
|
1476
|
+
spentUsd: number;
|
|
1477
|
+
}): CapabilityTier;
|
|
1478
|
+
/**
|
|
1479
|
+
* Pure (complexity × risk × policy × spend × floor) → required tier.
|
|
1480
|
+
*
|
|
1481
|
+
* `baseTier` resolves override → matrix → D5 veto → low-confidence bump; the D8
|
|
1482
|
+
* budget clamp lowers one step under budget pressure (never below the veto
|
|
1483
|
+
* floor); the D10 escalation floor raises the result but never lowers it. The
|
|
1484
|
+
* LLM never influences this — mirrors outcome-eval/authority.ts (TS-derived
|
|
1485
|
+
* authority). Referentially transparent; never mutates `policy`.
|
|
1486
|
+
*/
|
|
1487
|
+
declare function deriveRequiredTier(complexity: ComplexityVerdict, risk: RoutingRisk | undefined, policy: RoutingPolicy, spend: {
|
|
1488
|
+
spentUsd: number;
|
|
1489
|
+
}, escalationFloor: CapabilityTier, skillKey?: string): CapabilityTier;
|
|
1490
|
+
|
|
1491
|
+
/** Flatten signals into the ComplexityVerdict.signals map, dropping undefined fields. */
|
|
1492
|
+
declare function serializeSignals(s: ComplexitySignals): Record<string, number | boolean | string>;
|
|
1493
|
+
|
|
1494
|
+
export { ACCEPTANCE_EVAL_SYSTEM_PROMPT, type AcceptanceEvalInput, AcceptanceEvaluator, type AcceptanceEvaluatorOptions, type AcceptanceVerdict, type AffectedSystem, type AnalysisProvider, type AnalysisRequest, type AnalysisResponse, AnthropicAnalysisProvider, type Authority, type BlastRadius, type BlindSpot, type CanaryAdapter, type CanaryDegradeReason, type CanaryExec, type CanaryFinding, type CanaryProbe, type ClassifyInput, ClaudeCliAnalysisProvider, type ComplexityScore, type ComplexitySignals, type Confidence, DEFAULT_DEGRADE_AT_PCT, type EnrichedSpec, type ExecutionOutcome, ExecutionOutcomeConnector, type ExpertiseLevel, type Finding, type FrameworkRecommendation, type GitHubIssue, GraphValidator, IntelligencePipeline, type JiraIssue, type JudgedAgainst, type LinearIssue, type LlmAcceptanceVerdict, type LlmVerdict, type ManualInput, type Measurability, OUTCOME_EVAL_SYSTEM_PROMPT, OpenAICompatibleAnalysisProvider, type OutcomeEvalInput, OutcomeEvaluator, type OutcomeEvaluatorOptions, type OutcomeIngestResult, type OutcomeVerdict, type PersonaEffectivenessScore, type PersonaRecommendation, PeslSimulator, type Phase, type PreprocessResult, type ProfileStore, RANK_TIER, type RawWorkItem, type ResolvedSection, SENSITIVE_BLAST_THRESHOLD, STATIC_WEIGHTS, type SimulationResult, type SpecializationEntry, type SpecializationProfile, type SpecializationScore, type StaticVerdict, TIER_RANK, type TaskType, type TemporalConfig, type TiebreakResult, type Verdict, type WeightedRecommendation, acceptanceVerdictSchema, applyBudgetClamp, baseTier, blastRadiusVeto, buildUserPrompt as buildAcceptanceUserPrompt, buildSpecializationProfile, buildUserPrompt$1 as buildUserPrompt, classify, computeExpertiseLevel, computeHistoricalComplexity, computePersonaEffectiveness, computeSemanticComplexity, computeSpecialization, computeStructuralComplexity, createCanaryAdapter, decayWeight, deriveAcceptanceAuthority, deriveAuthority, deriveRequiredTier, detectBlindSpots, enrich, findingSchema, githubToRawWorkItem, jiraToRawWorkItem, linearToRawWorkItem, llmTiebreak, loadProfiles, manualToRawWorkItem, recommendPersona, refreshProfiles, resolveSection, runGraphOnlyChecks, runLlmSimulation, runStaticPass, saveProfiles, score as scoreCML, scoreToConcernSignals, serializeSignals, temporalSuccessRate, toRawWorkItem, verdictSchema, weightedRecommendPersona };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _harness_engineering_types from '@harness-engineering/types';
|
|
2
|
-
import { Issue, ConcernSignal, ScopeTier, EscalationConfig } from '@harness-engineering/types';
|
|
2
|
+
import { Issue, ConcernSignal, ScopeTier, EscalationConfig, ComplexityLevel, ComplexityVerdict, CapabilityTier, RoutingRisk, RoutingPolicy } from '@harness-engineering/types';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { GraphStore } from '@harness-engineering/graph';
|
|
5
5
|
|
|
@@ -406,6 +406,14 @@ interface OpenAICompatibleProviderOptions {
|
|
|
406
406
|
baseUrl: string;
|
|
407
407
|
/** Default model name (e.g., 'deepseek-coder-v2'). */
|
|
408
408
|
defaultModel?: string;
|
|
409
|
+
/**
|
|
410
|
+
* Consumption Phase 1 (T3): live model resolver, read at request time. When
|
|
411
|
+
* provided and it returns a non-empty name, that name is used in preference to
|
|
412
|
+
* `defaultModel` so a pool install/swap is consumed by analysis without a
|
|
413
|
+
* restart. `request.model` (an explicit per-call override) still wins; a
|
|
414
|
+
* null/undefined/empty return falls through to `defaultModel`.
|
|
415
|
+
*/
|
|
416
|
+
getModel?: () => string | null | undefined;
|
|
409
417
|
/** Request timeout in ms (default: 90000). */
|
|
410
418
|
timeoutMs?: number;
|
|
411
419
|
/**
|
|
@@ -430,6 +438,7 @@ interface OpenAICompatibleProviderOptions {
|
|
|
430
438
|
declare class OpenAICompatibleAnalysisProvider implements AnalysisProvider {
|
|
431
439
|
private readonly client;
|
|
432
440
|
private readonly defaultModel;
|
|
441
|
+
private readonly getModel?;
|
|
433
442
|
private readonly promptSuffix;
|
|
434
443
|
private readonly jsonMode;
|
|
435
444
|
constructor(options: OpenAICompatibleProviderOptions);
|
|
@@ -1333,4 +1342,153 @@ declare function saveProfiles(projectRoot: string, store: ProfileStore): void;
|
|
|
1333
1342
|
*/
|
|
1334
1343
|
declare function refreshProfiles(projectRoot: string, graphStore: GraphStore, opts?: Omit<SpecializationOptions, 'persona'>): ProfileStore;
|
|
1335
1344
|
|
|
1336
|
-
|
|
1345
|
+
/** Which signal set is available at this invocation phase (S3-001). */
|
|
1346
|
+
type Phase = 'pre-diff' | 'post-diff';
|
|
1347
|
+
/** Raw signals gathered for the static pass. Diff-based fields are undefined pre-diff. */
|
|
1348
|
+
interface ComplexitySignals {
|
|
1349
|
+
/** Files touched by the diff/target. Undefined pre-diff. */
|
|
1350
|
+
filesTouched?: number;
|
|
1351
|
+
/** Distinct architectural layers touched. Undefined pre-diff. */
|
|
1352
|
+
layersTouched?: number;
|
|
1353
|
+
/** compute_blast_radius result. Undefined pre-diff. */
|
|
1354
|
+
blastRadius?: number;
|
|
1355
|
+
/** hotspot × churn heat. Undefined pre-diff. */
|
|
1356
|
+
hotspotChurn?: number;
|
|
1357
|
+
/** Text-only fallback signals (always available). */
|
|
1358
|
+
descriptionLength: number;
|
|
1359
|
+
specExists: boolean;
|
|
1360
|
+
acceptanceMeasurable: boolean;
|
|
1361
|
+
}
|
|
1362
|
+
/** Provisional static verdict before any LLM tie-break. */
|
|
1363
|
+
interface StaticVerdict {
|
|
1364
|
+
level: ComplexityLevel;
|
|
1365
|
+
confidence: 'high' | 'medium' | 'low';
|
|
1366
|
+
/** Serialized subset of signals for the ComplexityVerdict.signals map. */
|
|
1367
|
+
signals: Record<string, number | boolean | string>;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/** Inputs to the cheap-first complexity cascade (D4). */
|
|
1371
|
+
interface ClassifyInput {
|
|
1372
|
+
signals: ComplexitySignals;
|
|
1373
|
+
phase: Phase;
|
|
1374
|
+
/** Whether the invocation's risk band is high (drives standard-tier escalation). */
|
|
1375
|
+
riskHigh: boolean;
|
|
1376
|
+
/** Prompt handed to the LLM tie-break / escalation. */
|
|
1377
|
+
prompt: string;
|
|
1378
|
+
}
|
|
1379
|
+
/**
|
|
1380
|
+
* D4 cascade: static pass → (if low confidence) fast-tier tie-break → (if still
|
|
1381
|
+
* low AND risk high) standard-tier escalation. Emits a `ComplexityVerdict` whose
|
|
1382
|
+
* `source` records which stage produced it. The static-only path resolves
|
|
1383
|
+
* without any LLM call ("never pay strong to route"); when `provider` is absent
|
|
1384
|
+
* the classifier stays fully offline and returns the static verdict.
|
|
1385
|
+
*
|
|
1386
|
+
* The LLM only sets `level`/`confidence`; the tier is always TS-derived (D3).
|
|
1387
|
+
*/
|
|
1388
|
+
declare function classify(input: ClassifyInput, provider?: AnalysisProvider, models?: {
|
|
1389
|
+
fast?: string;
|
|
1390
|
+
standard?: string;
|
|
1391
|
+
}): Promise<ComplexityVerdict>;
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* Documented seed weights for the free static pass (D4a). Each raw signal is
|
|
1395
|
+
* normalized against a reference maximum, multiplied by its weight, and the
|
|
1396
|
+
* weighted contributions are summed and re-normalized to a [0,1] score.
|
|
1397
|
+
*
|
|
1398
|
+
* Diff-based signals dominate post-diff; text-only signals carry the pre-diff
|
|
1399
|
+
* pass. Weights are tunable (DEFERRABLE per plan) — this is a documented seed.
|
|
1400
|
+
*/
|
|
1401
|
+
declare const STATIC_WEIGHTS: {
|
|
1402
|
+
readonly filesTouched: 0.25;
|
|
1403
|
+
readonly layersTouched: 0.2;
|
|
1404
|
+
readonly blastRadius: 0.3;
|
|
1405
|
+
readonly hotspotChurn: 0.1;
|
|
1406
|
+
/** Text-only signals — the only inputs available pre-diff. */
|
|
1407
|
+
readonly descriptionLength: 0.1;
|
|
1408
|
+
/** A present spec / measurable acceptance *lowers* complexity (well-scoped). */
|
|
1409
|
+
readonly specExists: 0.025;
|
|
1410
|
+
readonly acceptanceMeasurable: 0.025;
|
|
1411
|
+
};
|
|
1412
|
+
/**
|
|
1413
|
+
* D4a: free static pass. Phase-aware (S3-001): pre-diff uses text-only signals
|
|
1414
|
+
* and caps confidence at `medium`; post-diff uses the full signal set. Pure —
|
|
1415
|
+
* never calls an LLM. `source` is stamped by the classifier, not here.
|
|
1416
|
+
*/
|
|
1417
|
+
declare function runStaticPass(signals: ComplexitySignals, phase: Phase): StaticVerdict;
|
|
1418
|
+
|
|
1419
|
+
interface TiebreakResult {
|
|
1420
|
+
level: ComplexityLevel;
|
|
1421
|
+
confidence: 'high' | 'medium' | 'low';
|
|
1422
|
+
}
|
|
1423
|
+
/** D4b: fast-tier structured tie-break. Never sets a tier; falls back conservatively on error. */
|
|
1424
|
+
declare function llmTiebreak(provider: AnalysisProvider, prompt: string, fastModel?: string): Promise<TiebreakResult>;
|
|
1425
|
+
|
|
1426
|
+
declare const TIER_RANK: {
|
|
1427
|
+
fast: number;
|
|
1428
|
+
standard: number;
|
|
1429
|
+
strong: number;
|
|
1430
|
+
};
|
|
1431
|
+
declare const RANK_TIER: readonly ["fast", "standard", "strong"];
|
|
1432
|
+
/**
|
|
1433
|
+
* Documented seed threshold for the D5 high-blast veto. The spec lists
|
|
1434
|
+
* sensitive-path / core|types layer / public API explicitly but pins no numeric
|
|
1435
|
+
* blast threshold, so this is a plan-chosen seed — overridable later.
|
|
1436
|
+
*/
|
|
1437
|
+
declare const SENSITIVE_BLAST_THRESHOLD = 25;
|
|
1438
|
+
/**
|
|
1439
|
+
* D5: any sensitive-path / core|types layer / public API / high blast → force
|
|
1440
|
+
* `strong`, regardless of complexity (SC5). This is a HARD floor; downstream
|
|
1441
|
+
* budget clamping (D8) must not undercut it.
|
|
1442
|
+
*/
|
|
1443
|
+
declare function blastRadiusVeto(risk?: RoutingRisk): boolean;
|
|
1444
|
+
/**
|
|
1445
|
+
* Pre-budget tier resolution (Task 7): skillTierOverride → matrix → D5 veto →
|
|
1446
|
+
* low-confidence bump. Pure; the LLM never influences it (mirrors
|
|
1447
|
+
* outcome-eval/authority.ts). Task 8's `deriveRequiredTier` calls this then
|
|
1448
|
+
* applies the D8 budget clamp and D10 escalation floor.
|
|
1449
|
+
*
|
|
1450
|
+
* SC6: a `low`-confidence verdict degrades the tier UP one step (never below the
|
|
1451
|
+
* matrix default and never to a cheaper tier) — uncertainty routes to a more
|
|
1452
|
+
* capable model, never a Tier-A cheap one.
|
|
1453
|
+
*/
|
|
1454
|
+
declare function baseTier(complexity: ComplexityVerdict, risk: RoutingRisk | undefined, policy: RoutingPolicy, skillKey?: string): CapabilityTier;
|
|
1455
|
+
/** Default budget degrade threshold (% of cap) when policy omits one (D8). */
|
|
1456
|
+
declare const DEFAULT_DEGRADE_AT_PCT = 90;
|
|
1457
|
+
/**
|
|
1458
|
+
* D8: budget-pressure tier clamp. Two thresholds:
|
|
1459
|
+
*
|
|
1460
|
+
* - **Soft (`degradeAtPct`, default 90%):** clamp the tier DOWN one step
|
|
1461
|
+
* (`strong→standard→fast`, `fast→fast`) — a lagging degrade signal.
|
|
1462
|
+
* - **Hard (100% of `capUsd`):** for `degrade`/`pause` policies, force the tier
|
|
1463
|
+
* all the way to `fast` — the strongest sound floor on the routing DECISION
|
|
1464
|
+
* (it is not an admission gate; the monotonic accumulator lags under
|
|
1465
|
+
* concurrency, so it cannot prevent overshoot, only route the cheapest tier
|
|
1466
|
+
* once the read crosses the cap). `human` mode is handled one layer up in
|
|
1467
|
+
* `AdaptiveRouter.route()`, which surfaces the unit to a steward instead of
|
|
1468
|
+
* routing; here it falls through to the soft one-step degrade.
|
|
1469
|
+
*
|
|
1470
|
+
* The D5 blast-radius veto is a HARD `strong` floor the clamp must NOT undercut
|
|
1471
|
+
* (SC5 says sensitive-path / core|types / publicApi force `strong` "regardless"),
|
|
1472
|
+
* so a vetoed request stays `strong` even at the hard cap — the veto guard sits
|
|
1473
|
+
* ABOVE both the hard-floor and the soft-step branches. No budget block ⇒ no clamp.
|
|
1474
|
+
*/
|
|
1475
|
+
declare function applyBudgetClamp(tier: CapabilityTier, risk: RoutingRisk | undefined, policy: RoutingPolicy, spend: {
|
|
1476
|
+
spentUsd: number;
|
|
1477
|
+
}): CapabilityTier;
|
|
1478
|
+
/**
|
|
1479
|
+
* Pure (complexity × risk × policy × spend × floor) → required tier.
|
|
1480
|
+
*
|
|
1481
|
+
* `baseTier` resolves override → matrix → D5 veto → low-confidence bump; the D8
|
|
1482
|
+
* budget clamp lowers one step under budget pressure (never below the veto
|
|
1483
|
+
* floor); the D10 escalation floor raises the result but never lowers it. The
|
|
1484
|
+
* LLM never influences this — mirrors outcome-eval/authority.ts (TS-derived
|
|
1485
|
+
* authority). Referentially transparent; never mutates `policy`.
|
|
1486
|
+
*/
|
|
1487
|
+
declare function deriveRequiredTier(complexity: ComplexityVerdict, risk: RoutingRisk | undefined, policy: RoutingPolicy, spend: {
|
|
1488
|
+
spentUsd: number;
|
|
1489
|
+
}, escalationFloor: CapabilityTier, skillKey?: string): CapabilityTier;
|
|
1490
|
+
|
|
1491
|
+
/** Flatten signals into the ComplexityVerdict.signals map, dropping undefined fields. */
|
|
1492
|
+
declare function serializeSignals(s: ComplexitySignals): Record<string, number | boolean | string>;
|
|
1493
|
+
|
|
1494
|
+
export { ACCEPTANCE_EVAL_SYSTEM_PROMPT, type AcceptanceEvalInput, AcceptanceEvaluator, type AcceptanceEvaluatorOptions, type AcceptanceVerdict, type AffectedSystem, type AnalysisProvider, type AnalysisRequest, type AnalysisResponse, AnthropicAnalysisProvider, type Authority, type BlastRadius, type BlindSpot, type CanaryAdapter, type CanaryDegradeReason, type CanaryExec, type CanaryFinding, type CanaryProbe, type ClassifyInput, ClaudeCliAnalysisProvider, type ComplexityScore, type ComplexitySignals, type Confidence, DEFAULT_DEGRADE_AT_PCT, type EnrichedSpec, type ExecutionOutcome, ExecutionOutcomeConnector, type ExpertiseLevel, type Finding, type FrameworkRecommendation, type GitHubIssue, GraphValidator, IntelligencePipeline, type JiraIssue, type JudgedAgainst, type LinearIssue, type LlmAcceptanceVerdict, type LlmVerdict, type ManualInput, type Measurability, OUTCOME_EVAL_SYSTEM_PROMPT, OpenAICompatibleAnalysisProvider, type OutcomeEvalInput, OutcomeEvaluator, type OutcomeEvaluatorOptions, type OutcomeIngestResult, type OutcomeVerdict, type PersonaEffectivenessScore, type PersonaRecommendation, PeslSimulator, type Phase, type PreprocessResult, type ProfileStore, RANK_TIER, type RawWorkItem, type ResolvedSection, SENSITIVE_BLAST_THRESHOLD, STATIC_WEIGHTS, type SimulationResult, type SpecializationEntry, type SpecializationProfile, type SpecializationScore, type StaticVerdict, TIER_RANK, type TaskType, type TemporalConfig, type TiebreakResult, type Verdict, type WeightedRecommendation, acceptanceVerdictSchema, applyBudgetClamp, baseTier, blastRadiusVeto, buildUserPrompt as buildAcceptanceUserPrompt, buildSpecializationProfile, buildUserPrompt$1 as buildUserPrompt, classify, computeExpertiseLevel, computeHistoricalComplexity, computePersonaEffectiveness, computeSemanticComplexity, computeSpecialization, computeStructuralComplexity, createCanaryAdapter, decayWeight, deriveAcceptanceAuthority, deriveAuthority, deriveRequiredTier, detectBlindSpots, enrich, findingSchema, githubToRawWorkItem, jiraToRawWorkItem, linearToRawWorkItem, llmTiebreak, loadProfiles, manualToRawWorkItem, recommendPersona, refreshProfiles, resolveSection, runGraphOnlyChecks, runLlmSimulation, runStaticPass, saveProfiles, score as scoreCML, scoreToConcernSignals, serializeSignals, temporalSuccessRate, toRawWorkItem, verdictSchema, weightedRecommendPersona };
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,7 @@ __export(index_exports, {
|
|
|
34
34
|
AcceptanceEvaluator: () => AcceptanceEvaluator,
|
|
35
35
|
AnthropicAnalysisProvider: () => AnthropicAnalysisProvider,
|
|
36
36
|
ClaudeCliAnalysisProvider: () => ClaudeCliAnalysisProvider,
|
|
37
|
+
DEFAULT_DEGRADE_AT_PCT: () => DEFAULT_DEGRADE_AT_PCT,
|
|
37
38
|
ExecutionOutcomeConnector: () => ExecutionOutcomeConnector,
|
|
38
39
|
GraphValidator: () => GraphValidator,
|
|
39
40
|
IntelligencePipeline: () => IntelligencePipeline,
|
|
@@ -41,10 +42,18 @@ __export(index_exports, {
|
|
|
41
42
|
OpenAICompatibleAnalysisProvider: () => OpenAICompatibleAnalysisProvider,
|
|
42
43
|
OutcomeEvaluator: () => OutcomeEvaluator,
|
|
43
44
|
PeslSimulator: () => PeslSimulator,
|
|
45
|
+
RANK_TIER: () => RANK_TIER,
|
|
46
|
+
SENSITIVE_BLAST_THRESHOLD: () => SENSITIVE_BLAST_THRESHOLD,
|
|
47
|
+
STATIC_WEIGHTS: () => STATIC_WEIGHTS,
|
|
48
|
+
TIER_RANK: () => TIER_RANK,
|
|
44
49
|
acceptanceVerdictSchema: () => acceptanceVerdictSchema,
|
|
50
|
+
applyBudgetClamp: () => applyBudgetClamp,
|
|
51
|
+
baseTier: () => baseTier,
|
|
52
|
+
blastRadiusVeto: () => blastRadiusVeto,
|
|
45
53
|
buildAcceptanceUserPrompt: () => buildUserPrompt3,
|
|
46
54
|
buildSpecializationProfile: () => buildSpecializationProfile,
|
|
47
55
|
buildUserPrompt: () => buildUserPrompt2,
|
|
56
|
+
classify: () => classify,
|
|
48
57
|
computeExpertiseLevel: () => computeExpertiseLevel,
|
|
49
58
|
computeHistoricalComplexity: () => computeHistoricalComplexity,
|
|
50
59
|
computePersonaEffectiveness: () => computePersonaEffectiveness,
|
|
@@ -55,12 +64,14 @@ __export(index_exports, {
|
|
|
55
64
|
decayWeight: () => decayWeight,
|
|
56
65
|
deriveAcceptanceAuthority: () => deriveAcceptanceAuthority,
|
|
57
66
|
deriveAuthority: () => deriveAuthority,
|
|
67
|
+
deriveRequiredTier: () => deriveRequiredTier,
|
|
58
68
|
detectBlindSpots: () => detectBlindSpots,
|
|
59
69
|
enrich: () => enrich,
|
|
60
70
|
findingSchema: () => findingSchema,
|
|
61
71
|
githubToRawWorkItem: () => githubToRawWorkItem,
|
|
62
72
|
jiraToRawWorkItem: () => jiraToRawWorkItem,
|
|
63
73
|
linearToRawWorkItem: () => linearToRawWorkItem,
|
|
74
|
+
llmTiebreak: () => llmTiebreak,
|
|
64
75
|
loadProfiles: () => loadProfiles,
|
|
65
76
|
manualToRawWorkItem: () => manualToRawWorkItem,
|
|
66
77
|
recommendPersona: () => recommendPersona,
|
|
@@ -68,9 +79,11 @@ __export(index_exports, {
|
|
|
68
79
|
resolveSection: () => resolveSection,
|
|
69
80
|
runGraphOnlyChecks: () => runGraphOnlyChecks,
|
|
70
81
|
runLlmSimulation: () => runLlmSimulation,
|
|
82
|
+
runStaticPass: () => runStaticPass,
|
|
71
83
|
saveProfiles: () => saveProfiles,
|
|
72
84
|
scoreCML: () => score,
|
|
73
85
|
scoreToConcernSignals: () => scoreToConcernSignals,
|
|
86
|
+
serializeSignals: () => serializeSignals,
|
|
74
87
|
temporalSuccessRate: () => temporalSuccessRate,
|
|
75
88
|
toRawWorkItem: () => toRawWorkItem,
|
|
76
89
|
verdictSchema: () => verdictSchema,
|
|
@@ -415,6 +428,7 @@ var DEFAULT_TIMEOUT_MS = 9e4;
|
|
|
415
428
|
var OpenAICompatibleAnalysisProvider = class {
|
|
416
429
|
client;
|
|
417
430
|
defaultModel;
|
|
431
|
+
getModel;
|
|
418
432
|
promptSuffix;
|
|
419
433
|
jsonMode;
|
|
420
434
|
constructor(options) {
|
|
@@ -424,11 +438,15 @@ var OpenAICompatibleAnalysisProvider = class {
|
|
|
424
438
|
timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
425
439
|
});
|
|
426
440
|
this.defaultModel = options.defaultModel ?? DEFAULT_MODEL2;
|
|
441
|
+
if (options.getModel !== void 0) {
|
|
442
|
+
this.getModel = options.getModel;
|
|
443
|
+
}
|
|
427
444
|
this.promptSuffix = options.promptSuffix ?? null;
|
|
428
445
|
this.jsonMode = options.jsonMode ?? true;
|
|
429
446
|
}
|
|
430
447
|
async analyze(request) {
|
|
431
|
-
const
|
|
448
|
+
const resolved = this.getModel?.();
|
|
449
|
+
const model = request.model ?? (resolved != null && resolved !== "" ? resolved : this.defaultModel);
|
|
432
450
|
const maxTokens = request.maxTokens ?? DEFAULT_MAX_TOKENS2;
|
|
433
451
|
const jsonSchema = zodToJsonSchema(request.responseSchema);
|
|
434
452
|
const systemParts = [];
|
|
@@ -2115,12 +2133,224 @@ function refreshProfiles(projectRoot, graphStore, opts) {
|
|
|
2115
2133
|
saveProfiles(projectRoot, store);
|
|
2116
2134
|
return store;
|
|
2117
2135
|
}
|
|
2136
|
+
|
|
2137
|
+
// src/complexity/signals.ts
|
|
2138
|
+
function serializeSignals(s) {
|
|
2139
|
+
const out = {
|
|
2140
|
+
descriptionLength: s.descriptionLength,
|
|
2141
|
+
specExists: s.specExists,
|
|
2142
|
+
acceptanceMeasurable: s.acceptanceMeasurable
|
|
2143
|
+
};
|
|
2144
|
+
if (s.filesTouched !== void 0) out.filesTouched = s.filesTouched;
|
|
2145
|
+
if (s.layersTouched !== void 0) out.layersTouched = s.layersTouched;
|
|
2146
|
+
if (s.blastRadius !== void 0) out.blastRadius = s.blastRadius;
|
|
2147
|
+
if (s.hotspotChurn !== void 0) out.hotspotChurn = s.hotspotChurn;
|
|
2148
|
+
return out;
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
// src/complexity/static-pass.ts
|
|
2152
|
+
var STATIC_WEIGHTS = {
|
|
2153
|
+
filesTouched: 0.25,
|
|
2154
|
+
layersTouched: 0.2,
|
|
2155
|
+
blastRadius: 0.3,
|
|
2156
|
+
hotspotChurn: 0.1,
|
|
2157
|
+
/** Text-only signals — the only inputs available pre-diff. */
|
|
2158
|
+
descriptionLength: 0.1,
|
|
2159
|
+
/** A present spec / measurable acceptance *lowers* complexity (well-scoped). */
|
|
2160
|
+
specExists: 0.025,
|
|
2161
|
+
acceptanceMeasurable: 0.025
|
|
2162
|
+
};
|
|
2163
|
+
var REF_MAX = {
|
|
2164
|
+
filesTouched: 20,
|
|
2165
|
+
layersTouched: 4,
|
|
2166
|
+
blastRadius: 40,
|
|
2167
|
+
hotspotChurn: 1,
|
|
2168
|
+
descriptionLength: 500
|
|
2169
|
+
};
|
|
2170
|
+
var CONFIDENCE_RANK = {
|
|
2171
|
+
low: 0,
|
|
2172
|
+
medium: 1,
|
|
2173
|
+
high: 2
|
|
2174
|
+
};
|
|
2175
|
+
function clamp01(n) {
|
|
2176
|
+
return Math.max(0, Math.min(1, n));
|
|
2177
|
+
}
|
|
2178
|
+
function scoreToLevel(score2) {
|
|
2179
|
+
if (score2 < 0.2) return "trivial";
|
|
2180
|
+
if (score2 < 0.45) return "simple";
|
|
2181
|
+
if (score2 < 0.7) return "moderate";
|
|
2182
|
+
return "complex";
|
|
2183
|
+
}
|
|
2184
|
+
function scoreToConfidence(score2) {
|
|
2185
|
+
const boundaries = [0.2, 0.45, 0.7];
|
|
2186
|
+
const nearest = Math.min(...boundaries.map((b) => Math.abs(score2 - b)));
|
|
2187
|
+
const atExtremeEnd = score2 < 0.2 || score2 >= 0.7;
|
|
2188
|
+
if (nearest < 0.1) return "low";
|
|
2189
|
+
if (nearest < 0.18 && !atExtremeEnd) return "medium";
|
|
2190
|
+
return "high";
|
|
2191
|
+
}
|
|
2192
|
+
function runStaticPass(signals, phase) {
|
|
2193
|
+
const isPostDiff = phase === "post-diff";
|
|
2194
|
+
const contributions = [];
|
|
2195
|
+
const weightsUsed = [];
|
|
2196
|
+
if (isPostDiff) {
|
|
2197
|
+
if (signals.filesTouched !== void 0) {
|
|
2198
|
+
contributions.push(
|
|
2199
|
+
clamp01(signals.filesTouched / REF_MAX.filesTouched) * STATIC_WEIGHTS.filesTouched
|
|
2200
|
+
);
|
|
2201
|
+
weightsUsed.push(STATIC_WEIGHTS.filesTouched);
|
|
2202
|
+
}
|
|
2203
|
+
if (signals.layersTouched !== void 0) {
|
|
2204
|
+
contributions.push(
|
|
2205
|
+
clamp01(signals.layersTouched / REF_MAX.layersTouched) * STATIC_WEIGHTS.layersTouched
|
|
2206
|
+
);
|
|
2207
|
+
weightsUsed.push(STATIC_WEIGHTS.layersTouched);
|
|
2208
|
+
}
|
|
2209
|
+
if (signals.blastRadius !== void 0) {
|
|
2210
|
+
contributions.push(
|
|
2211
|
+
clamp01(signals.blastRadius / REF_MAX.blastRadius) * STATIC_WEIGHTS.blastRadius
|
|
2212
|
+
);
|
|
2213
|
+
weightsUsed.push(STATIC_WEIGHTS.blastRadius);
|
|
2214
|
+
}
|
|
2215
|
+
if (signals.hotspotChurn !== void 0) {
|
|
2216
|
+
contributions.push(
|
|
2217
|
+
clamp01(signals.hotspotChurn / REF_MAX.hotspotChurn) * STATIC_WEIGHTS.hotspotChurn
|
|
2218
|
+
);
|
|
2219
|
+
weightsUsed.push(STATIC_WEIGHTS.hotspotChurn);
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
contributions.push(
|
|
2223
|
+
clamp01(signals.descriptionLength / REF_MAX.descriptionLength) * STATIC_WEIGHTS.descriptionLength
|
|
2224
|
+
);
|
|
2225
|
+
weightsUsed.push(STATIC_WEIGHTS.descriptionLength);
|
|
2226
|
+
const scopeReduction = (signals.specExists ? STATIC_WEIGHTS.specExists : 0) + (signals.acceptanceMeasurable ? STATIC_WEIGHTS.acceptanceMeasurable : 0);
|
|
2227
|
+
const totalWeight = weightsUsed.reduce((a, b) => a + b, 0);
|
|
2228
|
+
const rawScore = contributions.reduce((a, b) => a + b, 0);
|
|
2229
|
+
const normalized = totalWeight > 0 ? rawScore / totalWeight : 0;
|
|
2230
|
+
const score2 = clamp01(normalized - scopeReduction);
|
|
2231
|
+
const level = scoreToLevel(score2);
|
|
2232
|
+
let confidence = scoreToConfidence(score2);
|
|
2233
|
+
if (!isPostDiff && CONFIDENCE_RANK[confidence] > CONFIDENCE_RANK.medium) {
|
|
2234
|
+
confidence = "medium";
|
|
2235
|
+
}
|
|
2236
|
+
return {
|
|
2237
|
+
level,
|
|
2238
|
+
confidence,
|
|
2239
|
+
signals: serializeSignals(signals)
|
|
2240
|
+
};
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
// src/complexity/tiebreak.ts
|
|
2244
|
+
var import_zod6 = require("zod");
|
|
2245
|
+
var TiebreakSchema = import_zod6.z.object({
|
|
2246
|
+
level: import_zod6.z.enum(["trivial", "simple", "moderate", "complex"]),
|
|
2247
|
+
confidence: import_zod6.z.enum(["high", "medium", "low"])
|
|
2248
|
+
});
|
|
2249
|
+
async function llmTiebreak(provider, prompt, fastModel) {
|
|
2250
|
+
try {
|
|
2251
|
+
const { result } = await provider.analyze({
|
|
2252
|
+
prompt,
|
|
2253
|
+
responseSchema: TiebreakSchema,
|
|
2254
|
+
// Only include `model` when supplied (exactOptionalPropertyTypes).
|
|
2255
|
+
...fastModel !== void 0 ? { model: fastModel } : {},
|
|
2256
|
+
maxTokens: 256
|
|
2257
|
+
});
|
|
2258
|
+
return result;
|
|
2259
|
+
} catch {
|
|
2260
|
+
return { level: "moderate", confidence: "low" };
|
|
2261
|
+
}
|
|
2262
|
+
}
|
|
2263
|
+
|
|
2264
|
+
// src/complexity/classifier.ts
|
|
2265
|
+
var CONFIDENCE_RANK2 = { low: 0, medium: 1, high: 2 };
|
|
2266
|
+
function capForPhase(confidence, phase) {
|
|
2267
|
+
if (phase === "pre-diff" && CONFIDENCE_RANK2[confidence] > CONFIDENCE_RANK2.medium) {
|
|
2268
|
+
return "medium";
|
|
2269
|
+
}
|
|
2270
|
+
return confidence;
|
|
2271
|
+
}
|
|
2272
|
+
async function classify(input, provider, models) {
|
|
2273
|
+
const staticVerdict = runStaticPass(input.signals, input.phase);
|
|
2274
|
+
if (staticVerdict.confidence !== "low" || provider === void 0) {
|
|
2275
|
+
return {
|
|
2276
|
+
level: staticVerdict.level,
|
|
2277
|
+
confidence: staticVerdict.confidence,
|
|
2278
|
+
signals: staticVerdict.signals,
|
|
2279
|
+
source: "static"
|
|
2280
|
+
};
|
|
2281
|
+
}
|
|
2282
|
+
const tiebreak = await llmTiebreak(provider, input.prompt, models?.fast);
|
|
2283
|
+
if (tiebreak.confidence === "low" && input.riskHigh) {
|
|
2284
|
+
const escalated = await llmTiebreak(provider, input.prompt, models?.standard);
|
|
2285
|
+
return {
|
|
2286
|
+
level: escalated.level,
|
|
2287
|
+
confidence: capForPhase(escalated.confidence, input.phase),
|
|
2288
|
+
signals: staticVerdict.signals,
|
|
2289
|
+
source: "escalated"
|
|
2290
|
+
};
|
|
2291
|
+
}
|
|
2292
|
+
return {
|
|
2293
|
+
level: tiebreak.level,
|
|
2294
|
+
confidence: capForPhase(tiebreak.confidence, input.phase),
|
|
2295
|
+
signals: staticVerdict.signals,
|
|
2296
|
+
source: "llm-tiebreak"
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2300
|
+
// src/complexity/derive-tier.ts
|
|
2301
|
+
var TIER_RANK = { fast: 0, standard: 1, strong: 2 };
|
|
2302
|
+
var RANK_TIER = ["fast", "standard", "strong"];
|
|
2303
|
+
var SENSITIVE_BLAST_THRESHOLD = 25;
|
|
2304
|
+
var DEFAULT_MATRIX = {
|
|
2305
|
+
trivial: "fast",
|
|
2306
|
+
simple: "fast",
|
|
2307
|
+
moderate: "standard",
|
|
2308
|
+
complex: "strong"
|
|
2309
|
+
};
|
|
2310
|
+
function tierAtRank(rank) {
|
|
2311
|
+
const clamped = Math.max(0, Math.min(RANK_TIER.length - 1, rank));
|
|
2312
|
+
return RANK_TIER[clamped];
|
|
2313
|
+
}
|
|
2314
|
+
function blastRadiusVeto(risk) {
|
|
2315
|
+
if (!risk) return false;
|
|
2316
|
+
return risk.sensitivePath === true || risk.publicApi === true || risk.layer === "core" || risk.layer === "types" || typeof risk.blastRadius === "number" && risk.blastRadius >= SENSITIVE_BLAST_THRESHOLD;
|
|
2317
|
+
}
|
|
2318
|
+
function baseTier(complexity, risk, policy, skillKey) {
|
|
2319
|
+
const veto = blastRadiusVeto(risk);
|
|
2320
|
+
const override = skillKey !== void 0 ? policy.skillTierOverrides?.[skillKey] : void 0;
|
|
2321
|
+
const matrix = policy.complexityTierMatrix ?? {};
|
|
2322
|
+
const fromMatrix = matrix[complexity.level] ?? DEFAULT_MATRIX[complexity.level];
|
|
2323
|
+
let rank = Math.max(override !== void 0 ? TIER_RANK[override] : 0, TIER_RANK[fromMatrix]);
|
|
2324
|
+
if (complexity.confidence === "low") {
|
|
2325
|
+
rank = rank + 1;
|
|
2326
|
+
}
|
|
2327
|
+
if (veto) rank = Math.max(rank, TIER_RANK.strong);
|
|
2328
|
+
return tierAtRank(rank);
|
|
2329
|
+
}
|
|
2330
|
+
var DEFAULT_DEGRADE_AT_PCT = 90;
|
|
2331
|
+
function applyBudgetClamp(tier, risk, policy, spend) {
|
|
2332
|
+
const budget = policy.budget;
|
|
2333
|
+
if (!budget || budget.capUsd <= 0) return tier;
|
|
2334
|
+
const degradeAt = (budget.degradeAtPct ?? DEFAULT_DEGRADE_AT_PCT) / 100;
|
|
2335
|
+
const spentFraction = spend.spentUsd / budget.capUsd;
|
|
2336
|
+
if (spentFraction < degradeAt) return tier;
|
|
2337
|
+
if (blastRadiusVeto(risk)) return tier;
|
|
2338
|
+
const mode = budget.onBudgetExhausted ?? "degrade";
|
|
2339
|
+
if (spentFraction >= 1 && mode !== "human") return "fast";
|
|
2340
|
+
return tierAtRank(TIER_RANK[tier] - 1);
|
|
2341
|
+
}
|
|
2342
|
+
function deriveRequiredTier(complexity, risk, policy, spend, escalationFloor, skillKey) {
|
|
2343
|
+
const base = baseTier(complexity, risk, policy, skillKey);
|
|
2344
|
+
const clamped = applyBudgetClamp(base, risk, policy, spend);
|
|
2345
|
+
return tierAtRank(Math.max(TIER_RANK[escalationFloor], TIER_RANK[clamped]));
|
|
2346
|
+
}
|
|
2118
2347
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2119
2348
|
0 && (module.exports = {
|
|
2120
2349
|
ACCEPTANCE_EVAL_SYSTEM_PROMPT,
|
|
2121
2350
|
AcceptanceEvaluator,
|
|
2122
2351
|
AnthropicAnalysisProvider,
|
|
2123
2352
|
ClaudeCliAnalysisProvider,
|
|
2353
|
+
DEFAULT_DEGRADE_AT_PCT,
|
|
2124
2354
|
ExecutionOutcomeConnector,
|
|
2125
2355
|
GraphValidator,
|
|
2126
2356
|
IntelligencePipeline,
|
|
@@ -2128,10 +2358,18 @@ function refreshProfiles(projectRoot, graphStore, opts) {
|
|
|
2128
2358
|
OpenAICompatibleAnalysisProvider,
|
|
2129
2359
|
OutcomeEvaluator,
|
|
2130
2360
|
PeslSimulator,
|
|
2361
|
+
RANK_TIER,
|
|
2362
|
+
SENSITIVE_BLAST_THRESHOLD,
|
|
2363
|
+
STATIC_WEIGHTS,
|
|
2364
|
+
TIER_RANK,
|
|
2131
2365
|
acceptanceVerdictSchema,
|
|
2366
|
+
applyBudgetClamp,
|
|
2367
|
+
baseTier,
|
|
2368
|
+
blastRadiusVeto,
|
|
2132
2369
|
buildAcceptanceUserPrompt,
|
|
2133
2370
|
buildSpecializationProfile,
|
|
2134
2371
|
buildUserPrompt,
|
|
2372
|
+
classify,
|
|
2135
2373
|
computeExpertiseLevel,
|
|
2136
2374
|
computeHistoricalComplexity,
|
|
2137
2375
|
computePersonaEffectiveness,
|
|
@@ -2142,12 +2380,14 @@ function refreshProfiles(projectRoot, graphStore, opts) {
|
|
|
2142
2380
|
decayWeight,
|
|
2143
2381
|
deriveAcceptanceAuthority,
|
|
2144
2382
|
deriveAuthority,
|
|
2383
|
+
deriveRequiredTier,
|
|
2145
2384
|
detectBlindSpots,
|
|
2146
2385
|
enrich,
|
|
2147
2386
|
findingSchema,
|
|
2148
2387
|
githubToRawWorkItem,
|
|
2149
2388
|
jiraToRawWorkItem,
|
|
2150
2389
|
linearToRawWorkItem,
|
|
2390
|
+
llmTiebreak,
|
|
2151
2391
|
loadProfiles,
|
|
2152
2392
|
manualToRawWorkItem,
|
|
2153
2393
|
recommendPersona,
|
|
@@ -2155,9 +2395,11 @@ function refreshProfiles(projectRoot, graphStore, opts) {
|
|
|
2155
2395
|
resolveSection,
|
|
2156
2396
|
runGraphOnlyChecks,
|
|
2157
2397
|
runLlmSimulation,
|
|
2398
|
+
runStaticPass,
|
|
2158
2399
|
saveProfiles,
|
|
2159
2400
|
scoreCML,
|
|
2160
2401
|
scoreToConcernSignals,
|
|
2402
|
+
serializeSignals,
|
|
2161
2403
|
temporalSuccessRate,
|
|
2162
2404
|
toRawWorkItem,
|
|
2163
2405
|
verdictSchema,
|
package/dist/index.mjs
CHANGED
|
@@ -335,6 +335,7 @@ var DEFAULT_TIMEOUT_MS = 9e4;
|
|
|
335
335
|
var OpenAICompatibleAnalysisProvider = class {
|
|
336
336
|
client;
|
|
337
337
|
defaultModel;
|
|
338
|
+
getModel;
|
|
338
339
|
promptSuffix;
|
|
339
340
|
jsonMode;
|
|
340
341
|
constructor(options) {
|
|
@@ -344,11 +345,15 @@ var OpenAICompatibleAnalysisProvider = class {
|
|
|
344
345
|
timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
345
346
|
});
|
|
346
347
|
this.defaultModel = options.defaultModel ?? DEFAULT_MODEL2;
|
|
348
|
+
if (options.getModel !== void 0) {
|
|
349
|
+
this.getModel = options.getModel;
|
|
350
|
+
}
|
|
347
351
|
this.promptSuffix = options.promptSuffix ?? null;
|
|
348
352
|
this.jsonMode = options.jsonMode ?? true;
|
|
349
353
|
}
|
|
350
354
|
async analyze(request) {
|
|
351
|
-
const
|
|
355
|
+
const resolved = this.getModel?.();
|
|
356
|
+
const model = request.model ?? (resolved != null && resolved !== "" ? resolved : this.defaultModel);
|
|
352
357
|
const maxTokens = request.maxTokens ?? DEFAULT_MAX_TOKENS2;
|
|
353
358
|
const jsonSchema = zodToJsonSchema(request.responseSchema);
|
|
354
359
|
const systemParts = [];
|
|
@@ -2035,11 +2040,223 @@ function refreshProfiles(projectRoot, graphStore, opts) {
|
|
|
2035
2040
|
saveProfiles(projectRoot, store);
|
|
2036
2041
|
return store;
|
|
2037
2042
|
}
|
|
2043
|
+
|
|
2044
|
+
// src/complexity/signals.ts
|
|
2045
|
+
function serializeSignals(s) {
|
|
2046
|
+
const out = {
|
|
2047
|
+
descriptionLength: s.descriptionLength,
|
|
2048
|
+
specExists: s.specExists,
|
|
2049
|
+
acceptanceMeasurable: s.acceptanceMeasurable
|
|
2050
|
+
};
|
|
2051
|
+
if (s.filesTouched !== void 0) out.filesTouched = s.filesTouched;
|
|
2052
|
+
if (s.layersTouched !== void 0) out.layersTouched = s.layersTouched;
|
|
2053
|
+
if (s.blastRadius !== void 0) out.blastRadius = s.blastRadius;
|
|
2054
|
+
if (s.hotspotChurn !== void 0) out.hotspotChurn = s.hotspotChurn;
|
|
2055
|
+
return out;
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
// src/complexity/static-pass.ts
|
|
2059
|
+
var STATIC_WEIGHTS = {
|
|
2060
|
+
filesTouched: 0.25,
|
|
2061
|
+
layersTouched: 0.2,
|
|
2062
|
+
blastRadius: 0.3,
|
|
2063
|
+
hotspotChurn: 0.1,
|
|
2064
|
+
/** Text-only signals — the only inputs available pre-diff. */
|
|
2065
|
+
descriptionLength: 0.1,
|
|
2066
|
+
/** A present spec / measurable acceptance *lowers* complexity (well-scoped). */
|
|
2067
|
+
specExists: 0.025,
|
|
2068
|
+
acceptanceMeasurable: 0.025
|
|
2069
|
+
};
|
|
2070
|
+
var REF_MAX = {
|
|
2071
|
+
filesTouched: 20,
|
|
2072
|
+
layersTouched: 4,
|
|
2073
|
+
blastRadius: 40,
|
|
2074
|
+
hotspotChurn: 1,
|
|
2075
|
+
descriptionLength: 500
|
|
2076
|
+
};
|
|
2077
|
+
var CONFIDENCE_RANK = {
|
|
2078
|
+
low: 0,
|
|
2079
|
+
medium: 1,
|
|
2080
|
+
high: 2
|
|
2081
|
+
};
|
|
2082
|
+
function clamp01(n) {
|
|
2083
|
+
return Math.max(0, Math.min(1, n));
|
|
2084
|
+
}
|
|
2085
|
+
function scoreToLevel(score2) {
|
|
2086
|
+
if (score2 < 0.2) return "trivial";
|
|
2087
|
+
if (score2 < 0.45) return "simple";
|
|
2088
|
+
if (score2 < 0.7) return "moderate";
|
|
2089
|
+
return "complex";
|
|
2090
|
+
}
|
|
2091
|
+
function scoreToConfidence(score2) {
|
|
2092
|
+
const boundaries = [0.2, 0.45, 0.7];
|
|
2093
|
+
const nearest = Math.min(...boundaries.map((b) => Math.abs(score2 - b)));
|
|
2094
|
+
const atExtremeEnd = score2 < 0.2 || score2 >= 0.7;
|
|
2095
|
+
if (nearest < 0.1) return "low";
|
|
2096
|
+
if (nearest < 0.18 && !atExtremeEnd) return "medium";
|
|
2097
|
+
return "high";
|
|
2098
|
+
}
|
|
2099
|
+
function runStaticPass(signals, phase) {
|
|
2100
|
+
const isPostDiff = phase === "post-diff";
|
|
2101
|
+
const contributions = [];
|
|
2102
|
+
const weightsUsed = [];
|
|
2103
|
+
if (isPostDiff) {
|
|
2104
|
+
if (signals.filesTouched !== void 0) {
|
|
2105
|
+
contributions.push(
|
|
2106
|
+
clamp01(signals.filesTouched / REF_MAX.filesTouched) * STATIC_WEIGHTS.filesTouched
|
|
2107
|
+
);
|
|
2108
|
+
weightsUsed.push(STATIC_WEIGHTS.filesTouched);
|
|
2109
|
+
}
|
|
2110
|
+
if (signals.layersTouched !== void 0) {
|
|
2111
|
+
contributions.push(
|
|
2112
|
+
clamp01(signals.layersTouched / REF_MAX.layersTouched) * STATIC_WEIGHTS.layersTouched
|
|
2113
|
+
);
|
|
2114
|
+
weightsUsed.push(STATIC_WEIGHTS.layersTouched);
|
|
2115
|
+
}
|
|
2116
|
+
if (signals.blastRadius !== void 0) {
|
|
2117
|
+
contributions.push(
|
|
2118
|
+
clamp01(signals.blastRadius / REF_MAX.blastRadius) * STATIC_WEIGHTS.blastRadius
|
|
2119
|
+
);
|
|
2120
|
+
weightsUsed.push(STATIC_WEIGHTS.blastRadius);
|
|
2121
|
+
}
|
|
2122
|
+
if (signals.hotspotChurn !== void 0) {
|
|
2123
|
+
contributions.push(
|
|
2124
|
+
clamp01(signals.hotspotChurn / REF_MAX.hotspotChurn) * STATIC_WEIGHTS.hotspotChurn
|
|
2125
|
+
);
|
|
2126
|
+
weightsUsed.push(STATIC_WEIGHTS.hotspotChurn);
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
contributions.push(
|
|
2130
|
+
clamp01(signals.descriptionLength / REF_MAX.descriptionLength) * STATIC_WEIGHTS.descriptionLength
|
|
2131
|
+
);
|
|
2132
|
+
weightsUsed.push(STATIC_WEIGHTS.descriptionLength);
|
|
2133
|
+
const scopeReduction = (signals.specExists ? STATIC_WEIGHTS.specExists : 0) + (signals.acceptanceMeasurable ? STATIC_WEIGHTS.acceptanceMeasurable : 0);
|
|
2134
|
+
const totalWeight = weightsUsed.reduce((a, b) => a + b, 0);
|
|
2135
|
+
const rawScore = contributions.reduce((a, b) => a + b, 0);
|
|
2136
|
+
const normalized = totalWeight > 0 ? rawScore / totalWeight : 0;
|
|
2137
|
+
const score2 = clamp01(normalized - scopeReduction);
|
|
2138
|
+
const level = scoreToLevel(score2);
|
|
2139
|
+
let confidence = scoreToConfidence(score2);
|
|
2140
|
+
if (!isPostDiff && CONFIDENCE_RANK[confidence] > CONFIDENCE_RANK.medium) {
|
|
2141
|
+
confidence = "medium";
|
|
2142
|
+
}
|
|
2143
|
+
return {
|
|
2144
|
+
level,
|
|
2145
|
+
confidence,
|
|
2146
|
+
signals: serializeSignals(signals)
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
// src/complexity/tiebreak.ts
|
|
2151
|
+
import { z as z6 } from "zod";
|
|
2152
|
+
var TiebreakSchema = z6.object({
|
|
2153
|
+
level: z6.enum(["trivial", "simple", "moderate", "complex"]),
|
|
2154
|
+
confidence: z6.enum(["high", "medium", "low"])
|
|
2155
|
+
});
|
|
2156
|
+
async function llmTiebreak(provider, prompt, fastModel) {
|
|
2157
|
+
try {
|
|
2158
|
+
const { result } = await provider.analyze({
|
|
2159
|
+
prompt,
|
|
2160
|
+
responseSchema: TiebreakSchema,
|
|
2161
|
+
// Only include `model` when supplied (exactOptionalPropertyTypes).
|
|
2162
|
+
...fastModel !== void 0 ? { model: fastModel } : {},
|
|
2163
|
+
maxTokens: 256
|
|
2164
|
+
});
|
|
2165
|
+
return result;
|
|
2166
|
+
} catch {
|
|
2167
|
+
return { level: "moderate", confidence: "low" };
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
|
|
2171
|
+
// src/complexity/classifier.ts
|
|
2172
|
+
var CONFIDENCE_RANK2 = { low: 0, medium: 1, high: 2 };
|
|
2173
|
+
function capForPhase(confidence, phase) {
|
|
2174
|
+
if (phase === "pre-diff" && CONFIDENCE_RANK2[confidence] > CONFIDENCE_RANK2.medium) {
|
|
2175
|
+
return "medium";
|
|
2176
|
+
}
|
|
2177
|
+
return confidence;
|
|
2178
|
+
}
|
|
2179
|
+
async function classify(input, provider, models) {
|
|
2180
|
+
const staticVerdict = runStaticPass(input.signals, input.phase);
|
|
2181
|
+
if (staticVerdict.confidence !== "low" || provider === void 0) {
|
|
2182
|
+
return {
|
|
2183
|
+
level: staticVerdict.level,
|
|
2184
|
+
confidence: staticVerdict.confidence,
|
|
2185
|
+
signals: staticVerdict.signals,
|
|
2186
|
+
source: "static"
|
|
2187
|
+
};
|
|
2188
|
+
}
|
|
2189
|
+
const tiebreak = await llmTiebreak(provider, input.prompt, models?.fast);
|
|
2190
|
+
if (tiebreak.confidence === "low" && input.riskHigh) {
|
|
2191
|
+
const escalated = await llmTiebreak(provider, input.prompt, models?.standard);
|
|
2192
|
+
return {
|
|
2193
|
+
level: escalated.level,
|
|
2194
|
+
confidence: capForPhase(escalated.confidence, input.phase),
|
|
2195
|
+
signals: staticVerdict.signals,
|
|
2196
|
+
source: "escalated"
|
|
2197
|
+
};
|
|
2198
|
+
}
|
|
2199
|
+
return {
|
|
2200
|
+
level: tiebreak.level,
|
|
2201
|
+
confidence: capForPhase(tiebreak.confidence, input.phase),
|
|
2202
|
+
signals: staticVerdict.signals,
|
|
2203
|
+
source: "llm-tiebreak"
|
|
2204
|
+
};
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
// src/complexity/derive-tier.ts
|
|
2208
|
+
var TIER_RANK = { fast: 0, standard: 1, strong: 2 };
|
|
2209
|
+
var RANK_TIER = ["fast", "standard", "strong"];
|
|
2210
|
+
var SENSITIVE_BLAST_THRESHOLD = 25;
|
|
2211
|
+
var DEFAULT_MATRIX = {
|
|
2212
|
+
trivial: "fast",
|
|
2213
|
+
simple: "fast",
|
|
2214
|
+
moderate: "standard",
|
|
2215
|
+
complex: "strong"
|
|
2216
|
+
};
|
|
2217
|
+
function tierAtRank(rank) {
|
|
2218
|
+
const clamped = Math.max(0, Math.min(RANK_TIER.length - 1, rank));
|
|
2219
|
+
return RANK_TIER[clamped];
|
|
2220
|
+
}
|
|
2221
|
+
function blastRadiusVeto(risk) {
|
|
2222
|
+
if (!risk) return false;
|
|
2223
|
+
return risk.sensitivePath === true || risk.publicApi === true || risk.layer === "core" || risk.layer === "types" || typeof risk.blastRadius === "number" && risk.blastRadius >= SENSITIVE_BLAST_THRESHOLD;
|
|
2224
|
+
}
|
|
2225
|
+
function baseTier(complexity, risk, policy, skillKey) {
|
|
2226
|
+
const veto = blastRadiusVeto(risk);
|
|
2227
|
+
const override = skillKey !== void 0 ? policy.skillTierOverrides?.[skillKey] : void 0;
|
|
2228
|
+
const matrix = policy.complexityTierMatrix ?? {};
|
|
2229
|
+
const fromMatrix = matrix[complexity.level] ?? DEFAULT_MATRIX[complexity.level];
|
|
2230
|
+
let rank = Math.max(override !== void 0 ? TIER_RANK[override] : 0, TIER_RANK[fromMatrix]);
|
|
2231
|
+
if (complexity.confidence === "low") {
|
|
2232
|
+
rank = rank + 1;
|
|
2233
|
+
}
|
|
2234
|
+
if (veto) rank = Math.max(rank, TIER_RANK.strong);
|
|
2235
|
+
return tierAtRank(rank);
|
|
2236
|
+
}
|
|
2237
|
+
var DEFAULT_DEGRADE_AT_PCT = 90;
|
|
2238
|
+
function applyBudgetClamp(tier, risk, policy, spend) {
|
|
2239
|
+
const budget = policy.budget;
|
|
2240
|
+
if (!budget || budget.capUsd <= 0) return tier;
|
|
2241
|
+
const degradeAt = (budget.degradeAtPct ?? DEFAULT_DEGRADE_AT_PCT) / 100;
|
|
2242
|
+
const spentFraction = spend.spentUsd / budget.capUsd;
|
|
2243
|
+
if (spentFraction < degradeAt) return tier;
|
|
2244
|
+
if (blastRadiusVeto(risk)) return tier;
|
|
2245
|
+
const mode = budget.onBudgetExhausted ?? "degrade";
|
|
2246
|
+
if (spentFraction >= 1 && mode !== "human") return "fast";
|
|
2247
|
+
return tierAtRank(TIER_RANK[tier] - 1);
|
|
2248
|
+
}
|
|
2249
|
+
function deriveRequiredTier(complexity, risk, policy, spend, escalationFloor, skillKey) {
|
|
2250
|
+
const base = baseTier(complexity, risk, policy, skillKey);
|
|
2251
|
+
const clamped = applyBudgetClamp(base, risk, policy, spend);
|
|
2252
|
+
return tierAtRank(Math.max(TIER_RANK[escalationFloor], TIER_RANK[clamped]));
|
|
2253
|
+
}
|
|
2038
2254
|
export {
|
|
2039
2255
|
ACCEPTANCE_EVAL_SYSTEM_PROMPT,
|
|
2040
2256
|
AcceptanceEvaluator,
|
|
2041
2257
|
AnthropicAnalysisProvider,
|
|
2042
2258
|
ClaudeCliAnalysisProvider,
|
|
2259
|
+
DEFAULT_DEGRADE_AT_PCT,
|
|
2043
2260
|
ExecutionOutcomeConnector,
|
|
2044
2261
|
GraphValidator,
|
|
2045
2262
|
IntelligencePipeline,
|
|
@@ -2047,10 +2264,18 @@ export {
|
|
|
2047
2264
|
OpenAICompatibleAnalysisProvider,
|
|
2048
2265
|
OutcomeEvaluator,
|
|
2049
2266
|
PeslSimulator,
|
|
2267
|
+
RANK_TIER,
|
|
2268
|
+
SENSITIVE_BLAST_THRESHOLD,
|
|
2269
|
+
STATIC_WEIGHTS,
|
|
2270
|
+
TIER_RANK,
|
|
2050
2271
|
acceptanceVerdictSchema,
|
|
2272
|
+
applyBudgetClamp,
|
|
2273
|
+
baseTier,
|
|
2274
|
+
blastRadiusVeto,
|
|
2051
2275
|
buildUserPrompt3 as buildAcceptanceUserPrompt,
|
|
2052
2276
|
buildSpecializationProfile,
|
|
2053
2277
|
buildUserPrompt2 as buildUserPrompt,
|
|
2278
|
+
classify,
|
|
2054
2279
|
computeExpertiseLevel,
|
|
2055
2280
|
computeHistoricalComplexity,
|
|
2056
2281
|
computePersonaEffectiveness,
|
|
@@ -2061,12 +2286,14 @@ export {
|
|
|
2061
2286
|
decayWeight,
|
|
2062
2287
|
deriveAcceptanceAuthority,
|
|
2063
2288
|
deriveAuthority,
|
|
2289
|
+
deriveRequiredTier,
|
|
2064
2290
|
detectBlindSpots,
|
|
2065
2291
|
enrich,
|
|
2066
2292
|
findingSchema,
|
|
2067
2293
|
githubToRawWorkItem,
|
|
2068
2294
|
jiraToRawWorkItem,
|
|
2069
2295
|
linearToRawWorkItem,
|
|
2296
|
+
llmTiebreak,
|
|
2070
2297
|
loadProfiles,
|
|
2071
2298
|
manualToRawWorkItem,
|
|
2072
2299
|
recommendPersona,
|
|
@@ -2074,9 +2301,11 @@ export {
|
|
|
2074
2301
|
resolveSection,
|
|
2075
2302
|
runGraphOnlyChecks,
|
|
2076
2303
|
runLlmSimulation,
|
|
2304
|
+
runStaticPass,
|
|
2077
2305
|
saveProfiles,
|
|
2078
2306
|
score as scoreCML,
|
|
2079
2307
|
scoreToConcernSignals,
|
|
2308
|
+
serializeSignals,
|
|
2080
2309
|
temporalSuccessRate,
|
|
2081
2310
|
toRawWorkItem,
|
|
2082
2311
|
verdictSchema,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harness-engineering/intelligence",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Intelligence pipeline for spec enrichment, complexity modeling, and pre-execution simulation",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"@anthropic-ai/sdk": "^0.95.1",
|
|
41
41
|
"openai": "^6.0.0",
|
|
42
42
|
"zod": "^3.25.76",
|
|
43
|
-
"@harness-engineering/graph": "0.11.
|
|
44
|
-
"@harness-engineering/types": "0.
|
|
43
|
+
"@harness-engineering/graph": "0.11.7",
|
|
44
|
+
"@harness-engineering/types": "0.21.0"
|
|
45
45
|
},
|
|
46
46
|
"optionalDependencies": {
|
|
47
47
|
"canary-test-cli": "^5.4.0"
|