@ai-sdlc/orchestrator 0.6.0 → 0.9.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/admission-composite.d.ts +67 -0
- package/dist/admission-composite.js +158 -0
- package/dist/admission-enrichment.d.ts +142 -0
- package/dist/admission-enrichment.js +331 -0
- package/dist/admission-hc.d.ts +62 -0
- package/dist/admission-hc.js +83 -0
- package/dist/admission-score.d.ts +95 -5
- package/dist/admission-score.js +84 -11
- package/dist/analysis/analyzer.js +3 -2
- package/dist/analysis/convention-detector.d.ts +85 -2
- package/dist/analysis/convention-detector.js +375 -70
- package/dist/analysis/diff-analyzer.d.ts +33 -0
- package/dist/analysis/diff-analyzer.js +122 -0
- package/dist/analysis/hotspot-analyzer.js +3 -1
- package/dist/analysis/index.d.ts +2 -1
- package/dist/analysis/index.js +2 -1
- package/dist/artifacts/index.d.ts +65 -0
- package/dist/artifacts/index.js +142 -0
- package/dist/backlog-adapter.d.ts +121 -0
- package/dist/backlog-adapter.js +438 -0
- package/dist/calibration.d.ts +43 -0
- package/dist/calibration.js +76 -0
- package/dist/cli/commands/agents.d.ts +24 -0
- package/dist/cli/commands/agents.js +66 -1
- package/dist/cli/commands/git-remote.d.ts +49 -0
- package/dist/cli/commands/git-remote.js +91 -0
- package/dist/cli/commands/health.d.ts +4 -0
- package/dist/cli/commands/health.js +13 -1
- package/dist/cli/commands/init.d.ts +26 -0
- package/dist/cli/commands/init.js +164 -22
- package/dist/cli/commands/mcp-setup.d.ts +31 -0
- package/dist/cli/commands/mcp-setup.js +78 -8
- package/dist/cli/formatters/table.js +15 -2
- package/dist/cli/index.d.ts +14 -1
- package/dist/cli/index.js +81 -20
- package/dist/cli/versions.d.ts +57 -0
- package/dist/cli/versions.js +128 -0
- package/dist/code-area-classifier.d.ts +21 -0
- package/dist/code-area-classifier.js +48 -0
- package/dist/config.d.ts +33 -1
- package/dist/config.js +78 -8
- package/dist/database/adapters/external.d.ts +24 -0
- package/dist/database/adapters/external.js +80 -0
- package/dist/database/adapters/neon.d.ts +41 -0
- package/dist/database/adapters/neon.js +98 -0
- package/dist/database/adapters/pg-snapshot-restore.d.ts +28 -0
- package/dist/database/adapters/pg-snapshot-restore.js +68 -0
- package/dist/database/adapters/sqlite-copy.d.ts +32 -0
- package/dist/database/adapters/sqlite-copy.js +145 -0
- package/dist/database/connection-injection.d.ts +35 -0
- package/dist/database/connection-injection.js +93 -0
- package/dist/database/index.d.ts +12 -0
- package/dist/database/index.js +23 -0
- package/dist/database/registry.d.ts +13 -0
- package/dist/database/registry.js +27 -0
- package/dist/database/topology.d.ts +52 -0
- package/dist/database/topology.js +44 -0
- package/dist/database/types.d.ts +89 -0
- package/dist/database/types.js +26 -0
- package/dist/design-authority.d.ts +40 -0
- package/dist/design-authority.js +71 -0
- package/dist/design-lookahead.d.ts +64 -0
- package/dist/design-lookahead.js +86 -0
- package/dist/design-quality-trend.d.ts +87 -0
- package/dist/design-quality-trend.js +190 -0
- package/dist/design-system-context.d.ts +46 -0
- package/dist/design-system-context.js +80 -0
- package/dist/design-system-correction-loop.d.ts +64 -0
- package/dist/design-system-correction-loop.js +128 -0
- package/dist/design-system-metrics.d.ts +61 -0
- package/dist/design-system-metrics.js +104 -0
- package/dist/design-system-stewardship.d.ts +22 -0
- package/dist/design-system-stewardship.js +85 -0
- package/dist/design-system-validation.d.ts +37 -0
- package/dist/design-system-validation.js +88 -0
- package/dist/dispatch/index.d.ts +4 -0
- package/dist/dispatch/index.js +4 -0
- package/dist/dispatch/merge-gate.d.ts +46 -0
- package/dist/dispatch/merge-gate.js +90 -0
- package/dist/dispatch/requeue.d.ts +57 -0
- package/dist/dispatch/requeue.js +131 -0
- package/dist/dispatch/worker-pool.d.ts +62 -0
- package/dist/dispatch/worker-pool.js +60 -0
- package/dist/execute.d.ts +40 -0
- package/dist/execute.js +185 -15
- package/dist/fix-ci.js +8 -1
- package/dist/fix-review.js +8 -1
- package/dist/harness/adapters/claude-code.d.ts +29 -0
- package/dist/harness/adapters/claude-code.js +191 -0
- package/dist/harness/adapters/codex.d.ts +25 -0
- package/dist/harness/adapters/codex.js +61 -0
- package/dist/harness/independence.d.ts +51 -0
- package/dist/harness/independence.js +67 -0
- package/dist/harness/index.d.ts +14 -0
- package/dist/harness/index.js +20 -0
- package/dist/harness/registry.d.ts +17 -0
- package/dist/harness/registry.js +31 -0
- package/dist/harness/types.d.ts +123 -0
- package/dist/harness/types.js +8 -0
- package/dist/harness/version-probe.d.ts +14 -0
- package/dist/harness/version-probe.js +123 -0
- package/dist/index.d.ts +30 -4
- package/dist/index.js +35 -2
- package/dist/models/classifier.d.ts +76 -0
- package/dist/models/classifier.js +221 -0
- package/dist/models/index.d.ts +3 -0
- package/dist/models/index.js +3 -0
- package/dist/models/registry.d.ts +97 -0
- package/dist/models/registry.js +173 -0
- package/dist/pillar-breakdown.d.ts +63 -0
- package/dist/pillar-breakdown.js +153 -0
- package/dist/priority.d.ts +5 -0
- package/dist/priority.js +18 -5
- package/dist/review-meta.d.ts +65 -0
- package/dist/review-meta.js +149 -0
- package/dist/review.d.ts +4 -0
- package/dist/review.js +12 -2
- package/dist/runners/claude-code-sdk.d.ts +31 -0
- package/dist/runners/claude-code-sdk.js +238 -0
- package/dist/runners/claude-code.d.ts +3 -0
- package/dist/runners/claude-code.js +30 -66
- package/dist/runners/codex.js +4 -1
- package/dist/runners/copilot.js +4 -1
- package/dist/runners/cursor.js +4 -1
- package/dist/runners/git-utils.d.ts +81 -0
- package/dist/runners/git-utils.js +201 -0
- package/dist/runners/index.d.ts +3 -0
- package/dist/runners/index.js +3 -0
- package/dist/runners/review-agent.d.ts +20 -0
- package/dist/runners/review-agent.js +171 -41
- package/dist/runners/runner-registry.js +10 -0
- package/dist/runners/sdk-review-runner.d.ts +65 -0
- package/dist/runners/sdk-review-runner.js +185 -0
- package/dist/runners/security-triage.d.ts +20 -4
- package/dist/runners/security-triage.js +39 -15
- package/dist/runners/types.d.ts +6 -0
- package/dist/runtime/attestations.d.ts +274 -0
- package/dist/runtime/attestations.js +460 -0
- package/dist/runtime/git-env.d.ts +53 -0
- package/dist/runtime/git-env.js +60 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.js +7 -0
- package/dist/runtime/parallelism-flag.d.ts +10 -0
- package/dist/runtime/parallelism-flag.js +18 -0
- package/dist/runtime/port-allocator.d.ts +21 -0
- package/dist/runtime/port-allocator.js +66 -0
- package/dist/runtime/worktree-pool.d.ts +86 -0
- package/dist/runtime/worktree-pool.js +204 -0
- package/dist/runtime/worktree.d.ts +25 -0
- package/dist/runtime/worktree.js +111 -0
- package/dist/sa-scoring/auto-calibrate.d.ts +69 -0
- package/dist/sa-scoring/auto-calibrate.js +107 -0
- package/dist/sa-scoring/c1-sa2-computable.d.ts +42 -0
- package/dist/sa-scoring/c1-sa2-computable.js +59 -0
- package/dist/sa-scoring/composite.d.ts +107 -0
- package/dist/sa-scoring/composite.js +139 -0
- package/dist/sa-scoring/depparse-client.d.ts +79 -0
- package/dist/sa-scoring/depparse-client.js +187 -0
- package/dist/sa-scoring/did-compiler.d.ts +122 -0
- package/dist/sa-scoring/did-compiler.js +286 -0
- package/dist/sa-scoring/drift-monitor.d.ts +84 -0
- package/dist/sa-scoring/drift-monitor.js +186 -0
- package/dist/sa-scoring/exemplar-bank.d.ts +78 -0
- package/dist/sa-scoring/exemplar-bank.js +154 -0
- package/dist/sa-scoring/feedback-store.d.ts +100 -0
- package/dist/sa-scoring/feedback-store.js +156 -0
- package/dist/sa-scoring/index.d.ts +71 -0
- package/dist/sa-scoring/index.js +158 -0
- package/dist/sa-scoring/layer1-deterministic.d.ts +115 -0
- package/dist/sa-scoring/layer1-deterministic.js +298 -0
- package/dist/sa-scoring/layer2-structural.d.ts +71 -0
- package/dist/sa-scoring/layer2-structural.js +151 -0
- package/dist/sa-scoring/layer3-llm.d.ts +86 -0
- package/dist/sa-scoring/layer3-llm.js +282 -0
- package/dist/sa-scoring/rescore-orchestrator.d.ts +52 -0
- package/dist/sa-scoring/rescore-orchestrator.js +47 -0
- package/dist/scheduling/burn-down.d.ts +27 -0
- package/dist/scheduling/burn-down.js +43 -0
- package/dist/scheduling/calibration.d.ts +42 -0
- package/dist/scheduling/calibration.js +150 -0
- package/dist/scheduling/index.d.ts +8 -0
- package/dist/scheduling/index.js +8 -0
- package/dist/scheduling/ledger.d.ts +59 -0
- package/dist/scheduling/ledger.js +216 -0
- package/dist/scheduling/off-peak.d.ts +27 -0
- package/dist/scheduling/off-peak.js +112 -0
- package/dist/scheduling/schedule-decision.d.ts +39 -0
- package/dist/scheduling/schedule-decision.js +89 -0
- package/dist/scheduling/tier-analysis.d.ts +47 -0
- package/dist/scheduling/tier-analysis.js +81 -0
- package/dist/scheduling/types.d.ts +140 -0
- package/dist/scheduling/types.js +11 -0
- package/dist/shared.d.ts +13 -0
- package/dist/shared.js +32 -0
- package/dist/state/schema.d.ts +5 -1
- package/dist/state/schema.js +223 -1
- package/dist/state/store.d.ts +55 -1
- package/dist/state/store.js +342 -7
- package/dist/state/types.d.ts +139 -0
- package/dist/types.d.ts +1 -1
- package/dist/validate-agent-output.js +4 -1
- package/dist/watch.js +6 -0
- package/package.json +2 -2
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C1 — SA-2 computable component (RFC-0008 v4 §5.2).
|
|
3
|
+
*
|
|
4
|
+
* SA-2 ("soul alignment with design system") has two halves:
|
|
5
|
+
* - Computable: deterministic formula over DSB status fields
|
|
6
|
+
* - LLM: structured assessment of principle coverage (M5)
|
|
7
|
+
*
|
|
8
|
+
* This module implements the computable half only. LLM is returned as
|
|
9
|
+
* `null` until M5 (AISDLC-59/60) replaces it.
|
|
10
|
+
*
|
|
11
|
+
* Formula (§5.2):
|
|
12
|
+
* computableComponent = 0.3 × tokenCompliance + 0.2 × catalogHealth
|
|
13
|
+
*
|
|
14
|
+
* Where `tokenCompliance` and `catalogHealth` are normalized to [0, 1]
|
|
15
|
+
* from the DSB's published status.
|
|
16
|
+
*/
|
|
17
|
+
import type { DesignIntentDocument, DesignSystemBinding } from '@ai-sdlc/reference';
|
|
18
|
+
export interface Sa2ComputableResult {
|
|
19
|
+
/** Normalized token-compliance value in [0, 1]. */
|
|
20
|
+
tokenCompliance: number;
|
|
21
|
+
/** Normalized catalog-health coverage in [0, 1]. */
|
|
22
|
+
catalogHealth: number;
|
|
23
|
+
/** 0.3 × tokenCompliance + 0.2 × catalogHealth. */
|
|
24
|
+
computableComponent: number;
|
|
25
|
+
/** LLM component — filled by M5. Always `null` in Phase 1. */
|
|
26
|
+
llmComponent: null;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Compute the SA-2 computable half from a DID and its resolved DSB.
|
|
30
|
+
*
|
|
31
|
+
* Returns `undefined` (caller falls back to label-based `soulAlignment`)
|
|
32
|
+
* when:
|
|
33
|
+
* - `dsb` is undefined, OR
|
|
34
|
+
* - Neither `tokenCompliance.currentCoverage` nor `catalogHealth.coveragePercent`
|
|
35
|
+
* is present on the DSB status (can't compute either term).
|
|
36
|
+
*
|
|
37
|
+
* The DID is accepted for API symmetry and future extension (e.g. when
|
|
38
|
+
* individual principles select which DSB metrics to include); §5.2
|
|
39
|
+
* itself only reads DSB status.
|
|
40
|
+
*/
|
|
41
|
+
export declare function computeSa2Computable(did: DesignIntentDocument, dsb: DesignSystemBinding | undefined): Sa2ComputableResult | undefined;
|
|
42
|
+
//# sourceMappingURL=c1-sa2-computable.d.ts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C1 — SA-2 computable component (RFC-0008 v4 §5.2).
|
|
3
|
+
*
|
|
4
|
+
* SA-2 ("soul alignment with design system") has two halves:
|
|
5
|
+
* - Computable: deterministic formula over DSB status fields
|
|
6
|
+
* - LLM: structured assessment of principle coverage (M5)
|
|
7
|
+
*
|
|
8
|
+
* This module implements the computable half only. LLM is returned as
|
|
9
|
+
* `null` until M5 (AISDLC-59/60) replaces it.
|
|
10
|
+
*
|
|
11
|
+
* Formula (§5.2):
|
|
12
|
+
* computableComponent = 0.3 × tokenCompliance + 0.2 × catalogHealth
|
|
13
|
+
*
|
|
14
|
+
* Where `tokenCompliance` and `catalogHealth` are normalized to [0, 1]
|
|
15
|
+
* from the DSB's published status.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Compute the SA-2 computable half from a DID and its resolved DSB.
|
|
19
|
+
*
|
|
20
|
+
* Returns `undefined` (caller falls back to label-based `soulAlignment`)
|
|
21
|
+
* when:
|
|
22
|
+
* - `dsb` is undefined, OR
|
|
23
|
+
* - Neither `tokenCompliance.currentCoverage` nor `catalogHealth.coveragePercent`
|
|
24
|
+
* is present on the DSB status (can't compute either term).
|
|
25
|
+
*
|
|
26
|
+
* The DID is accepted for API symmetry and future extension (e.g. when
|
|
27
|
+
* individual principles select which DSB metrics to include); §5.2
|
|
28
|
+
* itself only reads DSB status.
|
|
29
|
+
*/
|
|
30
|
+
export function computeSa2Computable(did, dsb) {
|
|
31
|
+
void did;
|
|
32
|
+
if (!dsb?.status)
|
|
33
|
+
return undefined;
|
|
34
|
+
const rawTokenCoverage = dsb.status.tokenCompliance?.currentCoverage;
|
|
35
|
+
const rawCatalogCoverage = dsb.status.catalogHealth?.coveragePercent;
|
|
36
|
+
if (rawTokenCoverage === undefined && rawCatalogCoverage === undefined) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
const tokenCompliance = normalizeCoverage(rawTokenCoverage);
|
|
40
|
+
const catalogHealth = normalizeCoverage(rawCatalogCoverage);
|
|
41
|
+
const computableComponent = 0.3 * tokenCompliance + 0.2 * catalogHealth;
|
|
42
|
+
return {
|
|
43
|
+
tokenCompliance,
|
|
44
|
+
catalogHealth,
|
|
45
|
+
computableComponent,
|
|
46
|
+
llmComponent: null,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Normalize a coverage value to [0, 1]. Accepts percentages (0–100) or
|
|
51
|
+
* ratios (0–1). Missing values are treated as 0.
|
|
52
|
+
*/
|
|
53
|
+
function normalizeCoverage(value) {
|
|
54
|
+
if (value === undefined || Number.isNaN(value))
|
|
55
|
+
return 0;
|
|
56
|
+
const clamped = value > 1 ? value / 100 : value;
|
|
57
|
+
return Math.min(1, Math.max(0, clamped));
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=c1-sa2-computable.js.map
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA-1 / SA-2 composite (RFC-0008 Addendum B §B.7).
|
|
3
|
+
*
|
|
4
|
+
* Combines Layer 1 deterministic results, Layer 2 BM25 structural
|
|
5
|
+
* scores, and Layer 3 LLM structured assessments into the two
|
|
6
|
+
* soul-alignment dimensions used by the admission composite.
|
|
7
|
+
*
|
|
8
|
+
* SA-1 per §B.7.1:
|
|
9
|
+
* hard gate: scopeGate core → SA-1 = 0.0 (STOP)
|
|
10
|
+
* coreConflictPenalty = min(0.8, coreViolationCount × 0.4)
|
|
11
|
+
* evolvingConflictPenalty = min(0.3, evolvingViolationCount × 0.1)
|
|
12
|
+
* conflictPenalty = 1.0 − coreConflictPenalty − evolvingConflictPenalty
|
|
13
|
+
* subtleMult = 0.5 if any high-severity conflict, else 1.0
|
|
14
|
+
* blended = w_s × domainRelevance + w_l × domainIntent × subtleMult
|
|
15
|
+
* SA-1 = blended × conflictPenalty
|
|
16
|
+
*
|
|
17
|
+
* SA-2 per corrected §B.7.2 (CR-1 — no self-multiplication):
|
|
18
|
+
* computableScore = 0.3 × tokenCompliance + 0.2 × catalogHealth
|
|
19
|
+
* designConflictPenalty = 1.0 − min(0.6, coreAp × 0.3 + evolvingAp × 0.1)
|
|
20
|
+
* llmTerm = w_l × principleAlignment × subtleMult
|
|
21
|
+
* blendedScore = w_s × principleCoverage + llmTerm
|
|
22
|
+
* llmComponent = blendedScore × designConflictPenalty
|
|
23
|
+
* SA-2 = computableScore + 0.5 × llmComponent
|
|
24
|
+
*
|
|
25
|
+
* Phase weights (§B.7.3):
|
|
26
|
+
* 2a shadow → (0, 0) — computed but not used in ranking
|
|
27
|
+
* 2b blended → (0.20, 0.80)
|
|
28
|
+
* 2c calibrating → (0.35, 0.65)
|
|
29
|
+
* 3 calibrated → flywheel-driven; w_structural floored at 0.20 (CR-2)
|
|
30
|
+
*/
|
|
31
|
+
import type { SubtleConflict, SubtleDesignConflict } from './layer3-llm.js';
|
|
32
|
+
export type SaPhase = '2a' | '2b' | '2c' | '3';
|
|
33
|
+
export interface PhaseWeights {
|
|
34
|
+
wStructural: number;
|
|
35
|
+
wLlm: number;
|
|
36
|
+
}
|
|
37
|
+
/** CR-2: Phase 3 must never drop w_structural below this floor. */
|
|
38
|
+
export declare const W_STRUCTURAL_FLOOR = 0.2;
|
|
39
|
+
export declare function getPhaseWeights(phase: SaPhase, calibrated?: PhaseWeights): PhaseWeights;
|
|
40
|
+
export interface Sa1Inputs {
|
|
41
|
+
/** True when Layer 1 scope gate flagged a core out-of-scope hit. */
|
|
42
|
+
hardGated: boolean;
|
|
43
|
+
coreViolationCount: number;
|
|
44
|
+
evolvingViolationCount: number;
|
|
45
|
+
/** Layer 2 SA-1 domainRelevance in [0, 1]. */
|
|
46
|
+
domainRelevance: number;
|
|
47
|
+
/** Layer 3 SA-1 domainIntent in [0, 1] (already confidence-filtered). */
|
|
48
|
+
domainIntent: number;
|
|
49
|
+
/** Layer 3 SA-1 subtle conflicts (already confidence-filtered). */
|
|
50
|
+
subtleConflicts: SubtleConflict[];
|
|
51
|
+
}
|
|
52
|
+
export interface Sa2Inputs {
|
|
53
|
+
/** From DSB status, normalized to [0, 1]. */
|
|
54
|
+
tokenCompliance: number;
|
|
55
|
+
/** From DSB status, normalized to [0, 1]. */
|
|
56
|
+
catalogHealth: number;
|
|
57
|
+
/** Layer 2 SA-2 principleCoverage (weighted mean) in [0, 1]. */
|
|
58
|
+
principleCoverage: number;
|
|
59
|
+
/** Layer 3 SA-2 principleAlignment in [0, 1] (confidence-filtered). */
|
|
60
|
+
principleAlignment: number;
|
|
61
|
+
/** Count of core-classified design anti-pattern hits. */
|
|
62
|
+
coreDesignAntiPatternCount: number;
|
|
63
|
+
/** Count of evolving-classified design anti-pattern hits. */
|
|
64
|
+
evolvingDesignAntiPatternCount: number;
|
|
65
|
+
/** Layer 3 SA-2 subtle design conflicts (confidence-filtered). */
|
|
66
|
+
subtleDesignConflicts: SubtleDesignConflict[];
|
|
67
|
+
}
|
|
68
|
+
export interface Sa1Result {
|
|
69
|
+
sa1: number;
|
|
70
|
+
hardGated: boolean;
|
|
71
|
+
/** Structural contribution: w_s × domainRelevance. */
|
|
72
|
+
structuralContribution: number;
|
|
73
|
+
/** LLM contribution: w_l × domainIntent × subtleMult. */
|
|
74
|
+
llmContribution: number;
|
|
75
|
+
blended: number;
|
|
76
|
+
conflictPenalty: number;
|
|
77
|
+
subtleMult: number;
|
|
78
|
+
}
|
|
79
|
+
export interface Sa2Result {
|
|
80
|
+
sa2: number;
|
|
81
|
+
computableScore: number;
|
|
82
|
+
structuralContribution: number;
|
|
83
|
+
llmContribution: number;
|
|
84
|
+
blendedScore: number;
|
|
85
|
+
designConflictPenalty: number;
|
|
86
|
+
subtleMult: number;
|
|
87
|
+
llmComponent: number;
|
|
88
|
+
}
|
|
89
|
+
export interface SoulAlignmentResult {
|
|
90
|
+
phase: SaPhase;
|
|
91
|
+
weights: PhaseWeights;
|
|
92
|
+
/** True for Phase 2a — consumers must NOT use sa1/sa2 in ranking. */
|
|
93
|
+
shadowMode: boolean;
|
|
94
|
+
sa1: Sa1Result;
|
|
95
|
+
sa2: Sa2Result;
|
|
96
|
+
}
|
|
97
|
+
export declare function computeSa1(inputs: Sa1Inputs, weights: PhaseWeights): Sa1Result;
|
|
98
|
+
export declare function computeSa2(inputs: Sa2Inputs, weights: PhaseWeights): Sa2Result;
|
|
99
|
+
export interface SoulAlignmentInput {
|
|
100
|
+
phase: SaPhase;
|
|
101
|
+
/** Required for Phase 3 if calibrated weights differ from the 2c default. */
|
|
102
|
+
calibratedWeights?: PhaseWeights;
|
|
103
|
+
sa1: Sa1Inputs;
|
|
104
|
+
sa2: Sa2Inputs;
|
|
105
|
+
}
|
|
106
|
+
export declare function computeSoulAlignment(input: SoulAlignmentInput): SoulAlignmentResult;
|
|
107
|
+
//# sourceMappingURL=composite.d.ts.map
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA-1 / SA-2 composite (RFC-0008 Addendum B §B.7).
|
|
3
|
+
*
|
|
4
|
+
* Combines Layer 1 deterministic results, Layer 2 BM25 structural
|
|
5
|
+
* scores, and Layer 3 LLM structured assessments into the two
|
|
6
|
+
* soul-alignment dimensions used by the admission composite.
|
|
7
|
+
*
|
|
8
|
+
* SA-1 per §B.7.1:
|
|
9
|
+
* hard gate: scopeGate core → SA-1 = 0.0 (STOP)
|
|
10
|
+
* coreConflictPenalty = min(0.8, coreViolationCount × 0.4)
|
|
11
|
+
* evolvingConflictPenalty = min(0.3, evolvingViolationCount × 0.1)
|
|
12
|
+
* conflictPenalty = 1.0 − coreConflictPenalty − evolvingConflictPenalty
|
|
13
|
+
* subtleMult = 0.5 if any high-severity conflict, else 1.0
|
|
14
|
+
* blended = w_s × domainRelevance + w_l × domainIntent × subtleMult
|
|
15
|
+
* SA-1 = blended × conflictPenalty
|
|
16
|
+
*
|
|
17
|
+
* SA-2 per corrected §B.7.2 (CR-1 — no self-multiplication):
|
|
18
|
+
* computableScore = 0.3 × tokenCompliance + 0.2 × catalogHealth
|
|
19
|
+
* designConflictPenalty = 1.0 − min(0.6, coreAp × 0.3 + evolvingAp × 0.1)
|
|
20
|
+
* llmTerm = w_l × principleAlignment × subtleMult
|
|
21
|
+
* blendedScore = w_s × principleCoverage + llmTerm
|
|
22
|
+
* llmComponent = blendedScore × designConflictPenalty
|
|
23
|
+
* SA-2 = computableScore + 0.5 × llmComponent
|
|
24
|
+
*
|
|
25
|
+
* Phase weights (§B.7.3):
|
|
26
|
+
* 2a shadow → (0, 0) — computed but not used in ranking
|
|
27
|
+
* 2b blended → (0.20, 0.80)
|
|
28
|
+
* 2c calibrating → (0.35, 0.65)
|
|
29
|
+
* 3 calibrated → flywheel-driven; w_structural floored at 0.20 (CR-2)
|
|
30
|
+
*/
|
|
31
|
+
/** CR-2: Phase 3 must never drop w_structural below this floor. */
|
|
32
|
+
export const W_STRUCTURAL_FLOOR = 0.2;
|
|
33
|
+
export function getPhaseWeights(phase, calibrated) {
|
|
34
|
+
switch (phase) {
|
|
35
|
+
case '2a':
|
|
36
|
+
return { wStructural: 0, wLlm: 0 };
|
|
37
|
+
case '2b':
|
|
38
|
+
return { wStructural: 0.2, wLlm: 0.8 };
|
|
39
|
+
case '2c':
|
|
40
|
+
return { wStructural: 0.35, wLlm: 0.65 };
|
|
41
|
+
case '3': {
|
|
42
|
+
if (!calibrated)
|
|
43
|
+
return { wStructural: 0.35, wLlm: 0.65 };
|
|
44
|
+
const wStructural = Math.max(W_STRUCTURAL_FLOOR, calibrated.wStructural);
|
|
45
|
+
// wLlm is whatever is left after clamping — keeps the pair summing to 1.0.
|
|
46
|
+
const wLlm = Math.max(0, 1 - wStructural);
|
|
47
|
+
return { wStructural, wLlm };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// ── Helpers ──────────────────────────────────────────────────────────
|
|
52
|
+
function clamp01(value) {
|
|
53
|
+
if (Number.isNaN(value))
|
|
54
|
+
return 0;
|
|
55
|
+
return Math.min(1, Math.max(0, value));
|
|
56
|
+
}
|
|
57
|
+
function hasHighSeverity(conflicts) {
|
|
58
|
+
return conflicts.some((c) => c.severity === 'high');
|
|
59
|
+
}
|
|
60
|
+
function normalizeCoverage(value) {
|
|
61
|
+
if (value === undefined || Number.isNaN(value))
|
|
62
|
+
return 0;
|
|
63
|
+
const clamped = value > 1 ? value / 100 : value;
|
|
64
|
+
return clamp01(clamped);
|
|
65
|
+
}
|
|
66
|
+
// ── SA-1 ─────────────────────────────────────────────────────────────
|
|
67
|
+
export function computeSa1(inputs, weights) {
|
|
68
|
+
// Hard gate: core out-of-scope match forces SA-1 = 0 irrespective of
|
|
69
|
+
// Layer 2/3 output (§B.7.1 STOP condition).
|
|
70
|
+
if (inputs.hardGated) {
|
|
71
|
+
return {
|
|
72
|
+
sa1: 0,
|
|
73
|
+
hardGated: true,
|
|
74
|
+
structuralContribution: 0,
|
|
75
|
+
llmContribution: 0,
|
|
76
|
+
blended: 0,
|
|
77
|
+
conflictPenalty: 0,
|
|
78
|
+
subtleMult: 1,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const coreConflictPenalty = Math.min(0.8, inputs.coreViolationCount * 0.4);
|
|
82
|
+
const evolvingConflictPenalty = Math.min(0.3, inputs.evolvingViolationCount * 0.1);
|
|
83
|
+
const conflictPenalty = Math.max(0, 1 - coreConflictPenalty - evolvingConflictPenalty);
|
|
84
|
+
const subtleMult = hasHighSeverity(inputs.subtleConflicts) ? 0.5 : 1.0;
|
|
85
|
+
const structuralContribution = weights.wStructural * clamp01(inputs.domainRelevance);
|
|
86
|
+
const llmContribution = weights.wLlm * clamp01(inputs.domainIntent) * subtleMult;
|
|
87
|
+
const blended = structuralContribution + llmContribution;
|
|
88
|
+
const sa1 = clamp01(blended * conflictPenalty);
|
|
89
|
+
return {
|
|
90
|
+
sa1,
|
|
91
|
+
hardGated: false,
|
|
92
|
+
structuralContribution,
|
|
93
|
+
llmContribution,
|
|
94
|
+
blended,
|
|
95
|
+
conflictPenalty,
|
|
96
|
+
subtleMult,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// ── SA-2 ─────────────────────────────────────────────────────────────
|
|
100
|
+
export function computeSa2(inputs, weights) {
|
|
101
|
+
const tc = normalizeCoverage(inputs.tokenCompliance);
|
|
102
|
+
const ch = normalizeCoverage(inputs.catalogHealth);
|
|
103
|
+
// RFC §B.7.2: computableScore tops out at 0.5 by design — it's half
|
|
104
|
+
// the final SA-2 score. The other half comes from `0.5 × llmComponent`
|
|
105
|
+
// below, so perfect inputs on both layers yield SA-2 = 1.0. See the
|
|
106
|
+
// worked example in composite.test.ts: tc=0.88, ch=0.95 → 0.454.
|
|
107
|
+
const computableScore = 0.3 * tc + 0.2 * ch;
|
|
108
|
+
const rawPenalty = inputs.coreDesignAntiPatternCount * 0.3 + inputs.evolvingDesignAntiPatternCount * 0.1;
|
|
109
|
+
const designConflictPenalty = Math.max(0, 1 - Math.min(0.6, rawPenalty));
|
|
110
|
+
const subtleMult = hasHighSeverity(inputs.subtleDesignConflicts) ? 0.5 : 1.0;
|
|
111
|
+
const structuralContribution = weights.wStructural * clamp01(inputs.principleCoverage);
|
|
112
|
+
const llmContribution = weights.wLlm * clamp01(inputs.principleAlignment) * subtleMult;
|
|
113
|
+
const blendedScore = structuralContribution + llmContribution;
|
|
114
|
+
const llmComponent = blendedScore * designConflictPenalty;
|
|
115
|
+
const sa2 = clamp01(computableScore + 0.5 * llmComponent);
|
|
116
|
+
return {
|
|
117
|
+
sa2,
|
|
118
|
+
computableScore,
|
|
119
|
+
structuralContribution,
|
|
120
|
+
llmContribution,
|
|
121
|
+
blendedScore,
|
|
122
|
+
designConflictPenalty,
|
|
123
|
+
subtleMult,
|
|
124
|
+
llmComponent,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export function computeSoulAlignment(input) {
|
|
128
|
+
const weights = getPhaseWeights(input.phase, input.calibratedWeights);
|
|
129
|
+
const sa1 = computeSa1(input.sa1, weights);
|
|
130
|
+
const sa2 = computeSa2(input.sa2, weights);
|
|
131
|
+
return {
|
|
132
|
+
phase: input.phase,
|
|
133
|
+
weights,
|
|
134
|
+
shadowMode: input.phase === '2a',
|
|
135
|
+
sa1,
|
|
136
|
+
sa2,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=composite.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript client for the `sidecar-depparse` HTTP service.
|
|
3
|
+
*
|
|
4
|
+
* Used by Layer 1 deterministic SA scoring (RFC-0008 §B.4.2) to detect
|
|
5
|
+
* requirement constructions (`requires X`, `must have X`, `X required`,
|
|
6
|
+
* passive + negation-aware) in issue text.
|
|
7
|
+
*
|
|
8
|
+
* The client is injectable — production code wires in `HttpDepparseClient`
|
|
9
|
+
* pointing at the sidecar URL, tests inject a `FakeDepparseClient` to
|
|
10
|
+
* avoid the Python dependency.
|
|
11
|
+
*
|
|
12
|
+
* Retry semantics: one retry on 5xx responses (network or transient),
|
|
13
|
+
* typed failure on anything else. Fail-soft by default — caller can
|
|
14
|
+
* treat a `DepparseUnavailable` failure as "no matches" when the
|
|
15
|
+
* sidecar is optional.
|
|
16
|
+
*/
|
|
17
|
+
export interface DepparseMatch {
|
|
18
|
+
pattern: string;
|
|
19
|
+
matchedText: string;
|
|
20
|
+
depPath: string[];
|
|
21
|
+
construction: string;
|
|
22
|
+
}
|
|
23
|
+
export interface DepparseMatchRequest {
|
|
24
|
+
text: string;
|
|
25
|
+
patterns: string[];
|
|
26
|
+
}
|
|
27
|
+
export interface DepparseMatchResponse {
|
|
28
|
+
matches: DepparseMatch[];
|
|
29
|
+
}
|
|
30
|
+
export interface DepparseHealth {
|
|
31
|
+
status: string;
|
|
32
|
+
model?: string;
|
|
33
|
+
modelLoaded: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface DepparseClient {
|
|
36
|
+
match(request: DepparseMatchRequest): Promise<DepparseMatchResponse>;
|
|
37
|
+
healthz(): Promise<DepparseHealth>;
|
|
38
|
+
}
|
|
39
|
+
export type DepparseErrorKind = 'network' | 'bad-request' | 'server-error' | 'model-unavailable' | 'timeout';
|
|
40
|
+
export declare class DepparseError extends Error {
|
|
41
|
+
readonly kind: DepparseErrorKind;
|
|
42
|
+
readonly status?: number;
|
|
43
|
+
constructor(kind: DepparseErrorKind, message: string, status?: number);
|
|
44
|
+
}
|
|
45
|
+
export interface HttpDepparseClientOptions {
|
|
46
|
+
baseUrl: string;
|
|
47
|
+
/** Per-request timeout in ms. Default 5 000. */
|
|
48
|
+
timeoutMs?: number;
|
|
49
|
+
/** Number of retries on 5xx / network errors. Default 1. */
|
|
50
|
+
retries?: number;
|
|
51
|
+
/** Injectable fetch — lets tests stub without overriding globalThis. */
|
|
52
|
+
fetchImpl?: typeof fetch;
|
|
53
|
+
}
|
|
54
|
+
export declare class HttpDepparseClient implements DepparseClient {
|
|
55
|
+
private readonly baseUrl;
|
|
56
|
+
private readonly timeoutMs;
|
|
57
|
+
private readonly retries;
|
|
58
|
+
private readonly fetchImpl;
|
|
59
|
+
constructor(opts: HttpDepparseClientOptions);
|
|
60
|
+
healthz(): Promise<DepparseHealth>;
|
|
61
|
+
match(request: DepparseMatchRequest): Promise<DepparseMatchResponse>;
|
|
62
|
+
private requestJson;
|
|
63
|
+
private doFetch;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* In-memory test double that matches patterns by exact substring —
|
|
67
|
+
* sufficient for unit tests that don't care about dependency-parse
|
|
68
|
+
* semantics. Real scoring tests use recorded fixtures.
|
|
69
|
+
*/
|
|
70
|
+
export declare class FakeDepparseClient implements DepparseClient {
|
|
71
|
+
private responses;
|
|
72
|
+
private healthResponse;
|
|
73
|
+
callLog: DepparseMatchRequest[];
|
|
74
|
+
setResponse(response: DepparseMatchResponse): void;
|
|
75
|
+
setHealth(health: DepparseHealth): void;
|
|
76
|
+
match(request: DepparseMatchRequest): Promise<DepparseMatchResponse>;
|
|
77
|
+
healthz(): Promise<DepparseHealth>;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=depparse-client.d.ts.map
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript client for the `sidecar-depparse` HTTP service.
|
|
3
|
+
*
|
|
4
|
+
* Used by Layer 1 deterministic SA scoring (RFC-0008 §B.4.2) to detect
|
|
5
|
+
* requirement constructions (`requires X`, `must have X`, `X required`,
|
|
6
|
+
* passive + negation-aware) in issue text.
|
|
7
|
+
*
|
|
8
|
+
* The client is injectable — production code wires in `HttpDepparseClient`
|
|
9
|
+
* pointing at the sidecar URL, tests inject a `FakeDepparseClient` to
|
|
10
|
+
* avoid the Python dependency.
|
|
11
|
+
*
|
|
12
|
+
* Retry semantics: one retry on 5xx responses (network or transient),
|
|
13
|
+
* typed failure on anything else. Fail-soft by default — caller can
|
|
14
|
+
* treat a `DepparseUnavailable` failure as "no matches" when the
|
|
15
|
+
* sidecar is optional.
|
|
16
|
+
*/
|
|
17
|
+
export class DepparseError extends Error {
|
|
18
|
+
kind;
|
|
19
|
+
status;
|
|
20
|
+
constructor(kind, message, status) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = 'DepparseError';
|
|
23
|
+
this.kind = kind;
|
|
24
|
+
this.status = status;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class HttpDepparseClient {
|
|
28
|
+
baseUrl;
|
|
29
|
+
timeoutMs;
|
|
30
|
+
retries;
|
|
31
|
+
fetchImpl;
|
|
32
|
+
constructor(opts) {
|
|
33
|
+
this.baseUrl = assertHttpUrl(opts.baseUrl).replace(/\/$/, '');
|
|
34
|
+
this.timeoutMs = opts.timeoutMs ?? 5_000;
|
|
35
|
+
this.retries = opts.retries ?? 1;
|
|
36
|
+
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
37
|
+
}
|
|
38
|
+
async healthz() {
|
|
39
|
+
const res = await this.requestJson('GET', '/healthz');
|
|
40
|
+
return {
|
|
41
|
+
status: res.status,
|
|
42
|
+
model: res.model ?? undefined,
|
|
43
|
+
modelLoaded: Boolean(res.model_loaded),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async match(request) {
|
|
47
|
+
const body = JSON.stringify(request);
|
|
48
|
+
const res = await this.requestJson('POST', '/v1/match', body);
|
|
49
|
+
return {
|
|
50
|
+
matches: res.matches.map((m) => ({
|
|
51
|
+
pattern: m.pattern,
|
|
52
|
+
matchedText: m.matched_text,
|
|
53
|
+
depPath: m.dep_path,
|
|
54
|
+
construction: m.construction,
|
|
55
|
+
})),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// ── Internals ──────────────────────────────────────────────────
|
|
59
|
+
async requestJson(method, path, body) {
|
|
60
|
+
const url = `${this.baseUrl}${path}`;
|
|
61
|
+
let lastError;
|
|
62
|
+
const attempts = this.retries + 1;
|
|
63
|
+
for (let attempt = 0; attempt < attempts; attempt++) {
|
|
64
|
+
try {
|
|
65
|
+
const res = await this.doFetch(url, method, body);
|
|
66
|
+
if (res.ok) {
|
|
67
|
+
return (await res.json());
|
|
68
|
+
}
|
|
69
|
+
if (res.status === 503) {
|
|
70
|
+
// Model not yet loaded — permanent for this request window.
|
|
71
|
+
const text = await safeText(res);
|
|
72
|
+
throw new DepparseError('model-unavailable', text || `503 at ${url}`, 503);
|
|
73
|
+
}
|
|
74
|
+
if (res.status >= 500) {
|
|
75
|
+
lastError = new DepparseError('server-error', `${res.status} at ${url}`, res.status);
|
|
76
|
+
continue; // retry
|
|
77
|
+
}
|
|
78
|
+
const text = await safeText(res);
|
|
79
|
+
throw new DepparseError('bad-request', text || `${res.status} at ${url}`, res.status);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
if (err instanceof DepparseError) {
|
|
83
|
+
if (err.kind === 'server-error' && attempt + 1 < attempts) {
|
|
84
|
+
lastError = err;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
throw err;
|
|
88
|
+
}
|
|
89
|
+
// Network / abort / unknown — retry once
|
|
90
|
+
lastError = new DepparseError(errIsAbort(err) ? 'timeout' : 'network', err instanceof Error ? err.message : String(err));
|
|
91
|
+
if (attempt + 1 >= attempts)
|
|
92
|
+
throw lastError;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
throw lastError ?? new DepparseError('network', `No response from ${url}`);
|
|
96
|
+
}
|
|
97
|
+
async doFetch(url, method, body) {
|
|
98
|
+
const controller = new AbortController();
|
|
99
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
100
|
+
try {
|
|
101
|
+
return await this.fetchImpl(url, {
|
|
102
|
+
method,
|
|
103
|
+
headers: body ? { 'content-type': 'application/json' } : undefined,
|
|
104
|
+
body,
|
|
105
|
+
signal: controller.signal,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
clearTimeout(timer);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function safeText(res) {
|
|
114
|
+
try {
|
|
115
|
+
return await res.text();
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
return '';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Refuses non-HTTP schemes. Env-var or CLI-supplied `baseUrl` with
|
|
123
|
+
* `file://`, `data:`, `javascript:`, or similar could trigger local
|
|
124
|
+
* file reads or arbitrary protocol handlers when passed to `fetch()`.
|
|
125
|
+
*/
|
|
126
|
+
function assertHttpUrl(url) {
|
|
127
|
+
let parsed;
|
|
128
|
+
try {
|
|
129
|
+
parsed = new URL(url);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
throw new DepparseError('bad-request', `depparse baseUrl is not a valid URL: ${url}`);
|
|
133
|
+
}
|
|
134
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
135
|
+
throw new DepparseError('bad-request', `depparse baseUrl must use http: or https: (got ${parsed.protocol})`);
|
|
136
|
+
}
|
|
137
|
+
return url;
|
|
138
|
+
}
|
|
139
|
+
function errIsAbort(err) {
|
|
140
|
+
return (typeof err === 'object' &&
|
|
141
|
+
err !== null &&
|
|
142
|
+
'name' in err &&
|
|
143
|
+
err.name === 'AbortError');
|
|
144
|
+
}
|
|
145
|
+
// ── Fake client for tests ────────────────────────────────────────────
|
|
146
|
+
/**
|
|
147
|
+
* In-memory test double that matches patterns by exact substring —
|
|
148
|
+
* sufficient for unit tests that don't care about dependency-parse
|
|
149
|
+
* semantics. Real scoring tests use recorded fixtures.
|
|
150
|
+
*/
|
|
151
|
+
export class FakeDepparseClient {
|
|
152
|
+
responses;
|
|
153
|
+
healthResponse = {
|
|
154
|
+
status: 'ok',
|
|
155
|
+
model: 'fake',
|
|
156
|
+
modelLoaded: true,
|
|
157
|
+
};
|
|
158
|
+
callLog = [];
|
|
159
|
+
setResponse(response) {
|
|
160
|
+
this.responses = response;
|
|
161
|
+
}
|
|
162
|
+
setHealth(health) {
|
|
163
|
+
this.healthResponse = health;
|
|
164
|
+
}
|
|
165
|
+
async match(request) {
|
|
166
|
+
this.callLog.push(request);
|
|
167
|
+
if (this.responses)
|
|
168
|
+
return this.responses;
|
|
169
|
+
// Fallback: return substring matches with no dep_path info.
|
|
170
|
+
const matches = [];
|
|
171
|
+
for (const pattern of request.patterns) {
|
|
172
|
+
if (request.text.toLowerCase().includes(pattern.toLowerCase())) {
|
|
173
|
+
matches.push({
|
|
174
|
+
pattern,
|
|
175
|
+
matchedText: pattern,
|
|
176
|
+
depPath: [],
|
|
177
|
+
construction: 'substring',
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return { matches };
|
|
182
|
+
}
|
|
183
|
+
async healthz() {
|
|
184
|
+
return this.healthResponse;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=depparse-client.js.map
|