@ai-sdlc/orchestrator 0.6.0 → 0.10.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/__test-helpers/git-env.d.ts +40 -0
- package/dist/__test-helpers/git-env.js +73 -0
- package/dist/admission-composite.d.ts +89 -0
- package/dist/admission-composite.js +241 -0
- package/dist/admission-enrichment.d.ts +142 -0
- package/dist/admission-enrichment.js +341 -0
- package/dist/admission-hc.d.ts +81 -0
- package/dist/admission-hc.js +94 -0
- package/dist/admission-score.d.ts +109 -5
- package/dist/admission-score.js +90 -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 +74 -0
- package/dist/cli/commands/git-remote.js +170 -0
- package/dist/cli/commands/health.d.ts +4 -0
- package/dist/cli/commands/health.js +13 -1
- package/dist/cli/commands/init-features.d.ts +208 -0
- package/dist/cli/commands/init-features.js +473 -0
- package/dist/cli/commands/init-templates.d.ts +104 -0
- package/dist/cli/commands/init-templates.js +399 -0
- package/dist/cli/commands/init.d.ts +48 -0
- package/dist/cli/commands/init.js +322 -23
- 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 +53 -0
- package/dist/design-authority.js +84 -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 +188 -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 +78 -0
- package/dist/models/classifier.js +277 -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 +85 -0
- package/dist/pillar-breakdown.js +162 -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 +766 -0
- package/dist/runtime/attestations.js +1195 -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 +28 -0
- package/dist/runtime/parallelism-flag.js +39 -0
- package/dist/runtime/port-allocator.d.ts +32 -0
- package/dist/runtime/port-allocator.js +96 -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 +3 -2
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA feedback store (RFC-0008 Addendum B §B.8).
|
|
3
|
+
*
|
|
4
|
+
* Wraps the `did_feedback_events` table and exposes precision
|
|
5
|
+
* aggregations used by the feedback flywheel (AISDLC-65 Cκ
|
|
6
|
+
* calibration, AISDLC-66 phase-weight auto-calibration).
|
|
7
|
+
*
|
|
8
|
+
* Signal semantics (§B.8.1):
|
|
9
|
+
* accept — admitted item was correctly scored (true-positive on positive path)
|
|
10
|
+
* dismiss — admitted item should NOT have been (false-positive)
|
|
11
|
+
* escalate — scored too low; should have been ranked higher (false-negative)
|
|
12
|
+
* override — HC_override bypass triggered; feedback auto-emitted
|
|
13
|
+
*/
|
|
14
|
+
// Directional-correctness threshold: score ≥ this counts as "high" for
|
|
15
|
+
// dismiss-signal evaluation (a high-scored item that got dismissed was
|
|
16
|
+
// over-scored, so directionally incorrect).
|
|
17
|
+
const HIGH_SCORE_THRESHOLD = 0.5;
|
|
18
|
+
// ── Store ────────────────────────────────────────────────────────────
|
|
19
|
+
export class SAFeedbackStore {
|
|
20
|
+
store;
|
|
21
|
+
constructor(store) {
|
|
22
|
+
this.store = store;
|
|
23
|
+
}
|
|
24
|
+
record(input) {
|
|
25
|
+
return this.store.recordDidFeedback({
|
|
26
|
+
didName: input.didName,
|
|
27
|
+
issueNumber: input.issueNumber,
|
|
28
|
+
dimension: input.dimension,
|
|
29
|
+
signal: input.signal,
|
|
30
|
+
principal: input.principal,
|
|
31
|
+
category: input.category,
|
|
32
|
+
structuralScore: input.structuralScore,
|
|
33
|
+
llmScore: input.llmScore,
|
|
34
|
+
compositeScore: input.compositeScore,
|
|
35
|
+
notes: input.notes,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
list(window = {}) {
|
|
39
|
+
return this.store.getDidFeedbackEvents({
|
|
40
|
+
dimension: window.dimension,
|
|
41
|
+
since: window.since,
|
|
42
|
+
limit: 5000,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Directional correctness of the Layer 2 structural score.
|
|
47
|
+
*
|
|
48
|
+
* signal=accept + structural ≥ 0.5 → correct (high score → accepted)
|
|
49
|
+
* signal=accept + structural < 0.5 → incorrect (low score → accepted anyway, underconfident)
|
|
50
|
+
* signal=dismiss + structural ≥ 0.5 → incorrect (high score → dismissed, overconfident)
|
|
51
|
+
* signal=dismiss + structural < 0.5 → correct (low score → dismissed)
|
|
52
|
+
* signal=escalate + structural < 0.5 → correct (low score → escalated, was underscored)
|
|
53
|
+
* signal=escalate + structural ≥ 0.5 → incorrect (high score → escalated? unusual)
|
|
54
|
+
* signal=override → EXCLUDED (bypass, not a judgement on structural)
|
|
55
|
+
*/
|
|
56
|
+
structuralPrecision(window = {}) {
|
|
57
|
+
return this.computeDirectionalPrecision(window, (e) => e.structuralScore);
|
|
58
|
+
}
|
|
59
|
+
llmPrecision(window = {}) {
|
|
60
|
+
return this.computeDirectionalPrecision(window, (e) => e.llmScore);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Categories with the highest false-positive rates — i.e. where
|
|
64
|
+
* `dismiss` signals dominate `accept`. Phase 3 calibration
|
|
65
|
+
* (AISDLC-66) should prioritise tuning these.
|
|
66
|
+
*/
|
|
67
|
+
highFalsePositiveCategories(window = {}, minSampleSize = 3) {
|
|
68
|
+
const events = this.list(window).filter((e) => e.category);
|
|
69
|
+
const grouped = new Map();
|
|
70
|
+
for (const e of events) {
|
|
71
|
+
const key = e.category;
|
|
72
|
+
const bucket = grouped.get(key) ?? { accept: 0, dismiss: 0 };
|
|
73
|
+
if (e.signal === 'accept')
|
|
74
|
+
bucket.accept++;
|
|
75
|
+
else if (e.signal === 'dismiss')
|
|
76
|
+
bucket.dismiss++;
|
|
77
|
+
grouped.set(key, bucket);
|
|
78
|
+
}
|
|
79
|
+
const rows = [];
|
|
80
|
+
for (const [category, counts] of grouped) {
|
|
81
|
+
const sampleSize = counts.accept + counts.dismiss;
|
|
82
|
+
if (sampleSize < minSampleSize)
|
|
83
|
+
continue;
|
|
84
|
+
rows.push({
|
|
85
|
+
category,
|
|
86
|
+
sampleSize,
|
|
87
|
+
falsePositiveCount: counts.dismiss,
|
|
88
|
+
falsePositiveRate: sampleSize === 0 ? 0 : counts.dismiss / sampleSize,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
rows.sort((a, b) => b.falsePositiveRate - a.falsePositiveRate);
|
|
92
|
+
return rows;
|
|
93
|
+
}
|
|
94
|
+
computeDirectionalPrecision(window, scoreOf) {
|
|
95
|
+
const events = this.list(window);
|
|
96
|
+
let sampleSize = 0;
|
|
97
|
+
let correct = 0;
|
|
98
|
+
for (const e of events) {
|
|
99
|
+
if (e.signal === 'override')
|
|
100
|
+
continue;
|
|
101
|
+
const score = scoreOf(e);
|
|
102
|
+
if (score === undefined)
|
|
103
|
+
continue;
|
|
104
|
+
sampleSize++;
|
|
105
|
+
const high = score >= HIGH_SCORE_THRESHOLD;
|
|
106
|
+
const directionallyCorrect = (e.signal === 'accept' && high) ||
|
|
107
|
+
(e.signal === 'dismiss' && !high) ||
|
|
108
|
+
(e.signal === 'escalate' && !high);
|
|
109
|
+
if (directionallyCorrect)
|
|
110
|
+
correct++;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
sampleSize,
|
|
114
|
+
correct,
|
|
115
|
+
precision: sampleSize === 0 ? 0 : correct / sampleSize,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// ── Signal classification ────────────────────────────────────────────
|
|
120
|
+
const SA_LABELS = Object.freeze({
|
|
121
|
+
'sa/accept': 'accept',
|
|
122
|
+
'sa/dismiss': 'dismiss',
|
|
123
|
+
'sa/escalate': 'escalate',
|
|
124
|
+
});
|
|
125
|
+
/**
|
|
126
|
+
* Map a GitHub label addition event to a feedback signal, or
|
|
127
|
+
* undefined if the label isn't one of our SA signals.
|
|
128
|
+
*/
|
|
129
|
+
export function classifyLabel(label) {
|
|
130
|
+
return SA_LABELS[label.toLowerCase()];
|
|
131
|
+
}
|
|
132
|
+
export const SA_FEEDBACK_LABELS = Object.freeze([
|
|
133
|
+
'sa/accept',
|
|
134
|
+
'sa/dismiss',
|
|
135
|
+
'sa/escalate',
|
|
136
|
+
]);
|
|
137
|
+
/**
|
|
138
|
+
* Emit an `override` feedback row when an admission score carries an
|
|
139
|
+
* `override` bypass. Safe no-op when `override` is undefined — callers
|
|
140
|
+
* can invoke unconditionally.
|
|
141
|
+
*/
|
|
142
|
+
export function recordOverrideFeedback(feedback, override, context) {
|
|
143
|
+
if (!override)
|
|
144
|
+
return;
|
|
145
|
+
feedback.record({
|
|
146
|
+
didName: context.didName,
|
|
147
|
+
issueNumber: context.issueNumber,
|
|
148
|
+
// Override is a bypass of the whole SA score; by convention we
|
|
149
|
+
// record against SA-1 (the dimension that gates admission).
|
|
150
|
+
dimension: 'SA-1',
|
|
151
|
+
signal: 'override',
|
|
152
|
+
principal: context.principal,
|
|
153
|
+
notes: override.reason ?? context.reason,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=feedback-store.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA scoring orchestration (RFC-0008 Addendum B §B.7.3).
|
|
3
|
+
*
|
|
4
|
+
* `scoreSoulAlignment(input, deps)` runs the three-layer SA scorer end
|
|
5
|
+
* to end with phase-aware short-circuits:
|
|
6
|
+
*
|
|
7
|
+
* - Layer 1 hard gate → skips Layer 2/3, SA-1 forced to 0
|
|
8
|
+
* - Phase 2a shadow → all layers computed + persisted, but
|
|
9
|
+
* shadowMode=true signals caller to use
|
|
10
|
+
* label-based soulAlignment in ranking
|
|
11
|
+
* - Phase 2b/2c/3 → sa1 replaces label-based soulAlignment
|
|
12
|
+
*
|
|
13
|
+
* Persists one `did_scoring_events` row per dimension so operators can
|
|
14
|
+
* query per-dimension precision by phase.
|
|
15
|
+
*/
|
|
16
|
+
import type { DesignIntentDocument, DesignSystemBinding } from '@ai-sdlc/reference';
|
|
17
|
+
import type { StateStore } from '../state/store.js';
|
|
18
|
+
import { type CompiledDid } from './did-compiler.js';
|
|
19
|
+
import type { DepparseClient } from './depparse-client.js';
|
|
20
|
+
import type { LLMClient } from './layer3-llm.js';
|
|
21
|
+
import { type DeterministicScoringResult } from './layer1-deterministic.js';
|
|
22
|
+
import { type DomainRelevanceResult, type PrincipleCoverageVector } from './layer2-structural.js';
|
|
23
|
+
import { type LLMScoringResult } from './layer3-llm.js';
|
|
24
|
+
import { type PhaseWeights, type SaPhase, type SoulAlignmentResult } from './composite.js';
|
|
25
|
+
export interface ScoreSoulAlignmentInput {
|
|
26
|
+
issueText: string;
|
|
27
|
+
did: DesignIntentDocument;
|
|
28
|
+
dsb?: DesignSystemBinding;
|
|
29
|
+
phase: SaPhase;
|
|
30
|
+
calibratedWeights?: PhaseWeights;
|
|
31
|
+
/** Observed metrics keyed by signal metric name (for Layer 1). */
|
|
32
|
+
observedMetrics?: Record<string, number>;
|
|
33
|
+
/** Issue number for audit trail — used when persisting did_scoring_events. */
|
|
34
|
+
issueNumber?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface ScoreSoulAlignmentDeps {
|
|
37
|
+
depparse: DepparseClient;
|
|
38
|
+
llm: LLMClient;
|
|
39
|
+
stateStore?: StateStore;
|
|
40
|
+
/** Pre-compiled DID (skip recompilation). */
|
|
41
|
+
compiledDid?: CompiledDid;
|
|
42
|
+
}
|
|
43
|
+
export interface SoulAlignmentScoringResult {
|
|
44
|
+
/** Final composite SA-1/SA-2 (respecting shadow mode). */
|
|
45
|
+
sa1: number;
|
|
46
|
+
sa2: number;
|
|
47
|
+
/** Full composite result including per-layer contributions. */
|
|
48
|
+
composite: SoulAlignmentResult;
|
|
49
|
+
/** Raw Layer 1 output (useful for preVerifiedSummary). */
|
|
50
|
+
layer1: DeterministicScoringResult;
|
|
51
|
+
/** Raw Layer 2 outputs. Always computed (even in shadow mode). */
|
|
52
|
+
layer2: {
|
|
53
|
+
domainRelevance: DomainRelevanceResult;
|
|
54
|
+
principleCoverage: PrincipleCoverageVector;
|
|
55
|
+
};
|
|
56
|
+
/** Raw Layer 3 output. Absent when Layer 1 hard-gated (skipped). */
|
|
57
|
+
layer3?: LLMScoringResult;
|
|
58
|
+
/** True when Phase 2a — caller must use label-based soulAlignment. */
|
|
59
|
+
shadowMode: boolean;
|
|
60
|
+
/** Audit — phase + weights used. */
|
|
61
|
+
phase: SaPhase;
|
|
62
|
+
weights: PhaseWeights;
|
|
63
|
+
}
|
|
64
|
+
export declare function scoreSoulAlignment(input: ScoreSoulAlignmentInput, deps: ScoreSoulAlignmentDeps): Promise<SoulAlignmentScoringResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Resolve the soulAlignment value to feed the admission composite
|
|
67
|
+
* based on phase + SA result. In shadow mode (2a), returns undefined
|
|
68
|
+
* so the caller falls back to the label-based heuristic.
|
|
69
|
+
*/
|
|
70
|
+
export declare function resolveSoulAlignmentOverride(result: SoulAlignmentScoringResult): number | undefined;
|
|
71
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SA scoring orchestration (RFC-0008 Addendum B §B.7.3).
|
|
3
|
+
*
|
|
4
|
+
* `scoreSoulAlignment(input, deps)` runs the three-layer SA scorer end
|
|
5
|
+
* to end with phase-aware short-circuits:
|
|
6
|
+
*
|
|
7
|
+
* - Layer 1 hard gate → skips Layer 2/3, SA-1 forced to 0
|
|
8
|
+
* - Phase 2a shadow → all layers computed + persisted, but
|
|
9
|
+
* shadowMode=true signals caller to use
|
|
10
|
+
* label-based soulAlignment in ranking
|
|
11
|
+
* - Phase 2b/2c/3 → sa1 replaces label-based soulAlignment
|
|
12
|
+
*
|
|
13
|
+
* Persists one `did_scoring_events` row per dimension so operators can
|
|
14
|
+
* query per-dimension precision by phase.
|
|
15
|
+
*/
|
|
16
|
+
import { compileDid } from './did-compiler.js';
|
|
17
|
+
import { runLayer1 } from './layer1-deterministic.js';
|
|
18
|
+
import { computeDomainRelevance, computePrincipleCoverage, } from './layer2-structural.js';
|
|
19
|
+
import { runLayer3 } from './layer3-llm.js';
|
|
20
|
+
import { computeSoulAlignment, } from './composite.js';
|
|
21
|
+
// ── Orchestration ───────────────────────────────────────────────────
|
|
22
|
+
export async function scoreSoulAlignment(input, deps) {
|
|
23
|
+
const compiled = deps.compiledDid ?? compileDid(input.did);
|
|
24
|
+
// ── Layer 1 (deterministic) ────────────────────────────────────
|
|
25
|
+
const layer1 = await runLayer1({
|
|
26
|
+
issueText: input.issueText,
|
|
27
|
+
compiled,
|
|
28
|
+
depparse: deps.depparse,
|
|
29
|
+
observedMetrics: input.observedMetrics,
|
|
30
|
+
});
|
|
31
|
+
// ── Layer 2 (BM25 structural) ──────────────────────────────────
|
|
32
|
+
// Always compute, even in shadow mode, so precision tracking works.
|
|
33
|
+
const domainRelevance = computeDomainRelevance(input.issueText, compiled.bm25Corpus);
|
|
34
|
+
const principleCoverage = computePrincipleCoverage(input.issueText, compiled.principleCorpora);
|
|
35
|
+
// ── Layer 3 (LLM) ──────────────────────────────────────────────
|
|
36
|
+
// Skip Layer 3 if hard-gated — SA-1 = 0 short-circuits regardless
|
|
37
|
+
// of what the LLM might say. Matches §B.7.1 STOP condition.
|
|
38
|
+
let layer3;
|
|
39
|
+
if (!layer1.hardGated) {
|
|
40
|
+
layer3 = await runLayer3({
|
|
41
|
+
issueText: input.issueText,
|
|
42
|
+
did: input.did,
|
|
43
|
+
dsb: input.dsb,
|
|
44
|
+
preVerifiedSummary: layer1.preVerifiedSummary,
|
|
45
|
+
llm: deps.llm,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// ── DSB-derived computable inputs for SA-2 ────────────────────
|
|
49
|
+
const tokenCompliance = input.dsb?.status?.tokenCompliance?.currentCoverage ?? 0;
|
|
50
|
+
const catalogHealth = input.dsb?.status?.catalogHealth?.coveragePercent ?? 0;
|
|
51
|
+
// Count design anti-pattern hits for SA-2 conflict penalty.
|
|
52
|
+
const coreDesignAntiPatternCount = layer1.designAntiPatternHits.hits.filter((h) => h.identityClass === 'core').length;
|
|
53
|
+
const evolvingDesignAntiPatternCount = layer1.designAntiPatternHits.hits.filter((h) => h.identityClass === 'evolving').length;
|
|
54
|
+
// ── Composite ─────────────────────────────────────────────────
|
|
55
|
+
const composite = computeSoulAlignment({
|
|
56
|
+
phase: input.phase,
|
|
57
|
+
calibratedWeights: input.calibratedWeights,
|
|
58
|
+
sa1: {
|
|
59
|
+
hardGated: layer1.hardGated,
|
|
60
|
+
coreViolationCount: layer1.coreViolationCount,
|
|
61
|
+
evolvingViolationCount: layer1.evolvingViolationCount,
|
|
62
|
+
domainRelevance: domainRelevance.score,
|
|
63
|
+
domainIntent: layer3?.domainIntent ?? 0,
|
|
64
|
+
subtleConflicts: layer3?.subtleConflicts ?? [],
|
|
65
|
+
},
|
|
66
|
+
sa2: {
|
|
67
|
+
tokenCompliance,
|
|
68
|
+
catalogHealth,
|
|
69
|
+
principleCoverage: principleCoverage.overallCoverage,
|
|
70
|
+
principleAlignment: layer3?.principleAlignment ?? 0,
|
|
71
|
+
coreDesignAntiPatternCount,
|
|
72
|
+
evolvingDesignAntiPatternCount,
|
|
73
|
+
subtleDesignConflicts: layer3?.subtleDesignConflicts ?? [],
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
// ── Persist to did_scoring_events (one row per dimension) ─────
|
|
77
|
+
if (deps.stateStore && input.issueNumber !== undefined) {
|
|
78
|
+
persistScoringEvent(deps.stateStore, {
|
|
79
|
+
didName: input.did.metadata.name,
|
|
80
|
+
issueNumber: input.issueNumber,
|
|
81
|
+
dimension: 'SA-1',
|
|
82
|
+
phase: input.phase,
|
|
83
|
+
weights: composite.weights,
|
|
84
|
+
layer1,
|
|
85
|
+
layer2: domainRelevance,
|
|
86
|
+
layer3Sa1: layer3
|
|
87
|
+
? {
|
|
88
|
+
domainIntent: layer3.domainIntent,
|
|
89
|
+
domainIntentConfidence: layer3.domainIntentConfidence,
|
|
90
|
+
subtleConflicts: layer3.subtleConflicts,
|
|
91
|
+
}
|
|
92
|
+
: undefined,
|
|
93
|
+
compositeScore: composite.sa1.sa1,
|
|
94
|
+
});
|
|
95
|
+
persistScoringEvent(deps.stateStore, {
|
|
96
|
+
didName: input.did.metadata.name,
|
|
97
|
+
issueNumber: input.issueNumber,
|
|
98
|
+
dimension: 'SA-2',
|
|
99
|
+
phase: input.phase,
|
|
100
|
+
weights: composite.weights,
|
|
101
|
+
layer1,
|
|
102
|
+
layer2: principleCoverage,
|
|
103
|
+
layer3Sa2: layer3
|
|
104
|
+
? {
|
|
105
|
+
principleAlignment: layer3.principleAlignment,
|
|
106
|
+
principleAlignmentConfidence: layer3.principleAlignmentConfidence,
|
|
107
|
+
subtleDesignConflicts: layer3.subtleDesignConflicts,
|
|
108
|
+
}
|
|
109
|
+
: undefined,
|
|
110
|
+
compositeScore: composite.sa2.sa2,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
sa1: composite.sa1.sa1,
|
|
115
|
+
sa2: composite.sa2.sa2,
|
|
116
|
+
composite,
|
|
117
|
+
layer1,
|
|
118
|
+
layer2: { domainRelevance, principleCoverage },
|
|
119
|
+
layer3,
|
|
120
|
+
shadowMode: composite.shadowMode,
|
|
121
|
+
phase: input.phase,
|
|
122
|
+
weights: composite.weights,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function persistScoringEvent(store, input) {
|
|
126
|
+
const layer1Summary = {
|
|
127
|
+
hardGated: input.layer1.hardGated,
|
|
128
|
+
coreViolationCount: input.layer1.coreViolationCount,
|
|
129
|
+
evolvingViolationCount: input.layer1.evolvingViolationCount,
|
|
130
|
+
scopeOutOfScopeHits: input.layer1.scopeGate.outOfScopeHits.length,
|
|
131
|
+
constraintViolations: input.layer1.constraintViolations.violations.length,
|
|
132
|
+
antiPatternHits: input.layer1.antiPatternHits.hits.length + input.layer1.designAntiPatternHits.hits.length,
|
|
133
|
+
};
|
|
134
|
+
const layer3Payload = input.layer3Sa1 ?? input.layer3Sa2;
|
|
135
|
+
store.recordDidScoringEvent({
|
|
136
|
+
didName: input.didName,
|
|
137
|
+
issueNumber: input.issueNumber,
|
|
138
|
+
saDimension: input.dimension,
|
|
139
|
+
phase: input.phase,
|
|
140
|
+
layer1ResultJson: JSON.stringify(layer1Summary),
|
|
141
|
+
layer2ResultJson: JSON.stringify(input.layer2),
|
|
142
|
+
layer3ResultJson: layer3Payload ? JSON.stringify(layer3Payload) : undefined,
|
|
143
|
+
compositeScore: input.compositeScore,
|
|
144
|
+
phaseWeightsJson: JSON.stringify(input.weights),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// ── Admission-composite integration helpers ──────────────────────────
|
|
148
|
+
/**
|
|
149
|
+
* Resolve the soulAlignment value to feed the admission composite
|
|
150
|
+
* based on phase + SA result. In shadow mode (2a), returns undefined
|
|
151
|
+
* so the caller falls back to the label-based heuristic.
|
|
152
|
+
*/
|
|
153
|
+
export function resolveSoulAlignmentOverride(result) {
|
|
154
|
+
if (result.shadowMode)
|
|
155
|
+
return undefined;
|
|
156
|
+
return result.sa1;
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1 — Deterministic SA scorer (RFC-0008 Addendum B §B.4).
|
|
3
|
+
*
|
|
4
|
+
* Consumes a `CompiledDid` + issue text + state store metrics and
|
|
5
|
+
* produces a fully-deterministic scoring result. Layer 1 never makes
|
|
6
|
+
* network or LLM calls *except* for the dep-parse sidecar (for
|
|
7
|
+
* requirement-construction detection).
|
|
8
|
+
*
|
|
9
|
+
* A `core` out-of-scope match is a **hard gate** — downstream SA-1
|
|
10
|
+
* scoring must treat `hardGated=true` as SA-1 = 0.0 regardless of
|
|
11
|
+
* Layer 2/3 output. Evolving matches surface as warnings but do not
|
|
12
|
+
* gate admission.
|
|
13
|
+
*/
|
|
14
|
+
import type { CompiledDid } from './did-compiler.js';
|
|
15
|
+
import type { DepparseClient } from './depparse-client.js';
|
|
16
|
+
export interface ScopeGateMatch {
|
|
17
|
+
label: string;
|
|
18
|
+
synonym?: string;
|
|
19
|
+
identityClass: 'core' | 'evolving';
|
|
20
|
+
matchedText: string;
|
|
21
|
+
}
|
|
22
|
+
export interface ScopeGateResult {
|
|
23
|
+
inScopeHits: ScopeGateMatch[];
|
|
24
|
+
outOfScopeHits: ScopeGateMatch[];
|
|
25
|
+
/** True when a core out-of-scope term matched (hard gate). */
|
|
26
|
+
hardGated: boolean;
|
|
27
|
+
/** Warnings for evolving out-of-scope hits (soft gate). */
|
|
28
|
+
warnings: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface ConstraintViolation {
|
|
31
|
+
constraintId: string;
|
|
32
|
+
concept: string;
|
|
33
|
+
relationship: string;
|
|
34
|
+
pattern: string;
|
|
35
|
+
matchedText: string;
|
|
36
|
+
construction?: string;
|
|
37
|
+
depPath?: string[];
|
|
38
|
+
identityClass: 'core' | 'evolving';
|
|
39
|
+
}
|
|
40
|
+
export interface ConstraintViolationResult {
|
|
41
|
+
violations: ConstraintViolation[];
|
|
42
|
+
/** True when the depparse sidecar was unavailable (fail-soft skip). */
|
|
43
|
+
depparseSkipped: boolean;
|
|
44
|
+
}
|
|
45
|
+
export interface AntiPatternHit {
|
|
46
|
+
id: string;
|
|
47
|
+
label: string;
|
|
48
|
+
pattern: string;
|
|
49
|
+
matchedText: string;
|
|
50
|
+
identityClass: 'core' | 'evolving';
|
|
51
|
+
scope: 'product' | 'design-principle' | 'voice' | 'visual';
|
|
52
|
+
/** Present only for scope='design-principle'. */
|
|
53
|
+
principleId?: string;
|
|
54
|
+
}
|
|
55
|
+
export interface AntiPatternResult {
|
|
56
|
+
hits: AntiPatternHit[];
|
|
57
|
+
}
|
|
58
|
+
export type MeasurableSignalStatus = 'pass' | 'fail' | 'missing';
|
|
59
|
+
export interface MeasurableSignalCheck {
|
|
60
|
+
id: string;
|
|
61
|
+
metric: string;
|
|
62
|
+
threshold: number;
|
|
63
|
+
operator: string;
|
|
64
|
+
observedValue?: number;
|
|
65
|
+
status: MeasurableSignalStatus;
|
|
66
|
+
identityClass: 'core' | 'evolving';
|
|
67
|
+
}
|
|
68
|
+
export interface MeasurableSignalResult {
|
|
69
|
+
checks: MeasurableSignalCheck[];
|
|
70
|
+
/** Count of signals with status='fail' on a core-classified signal. */
|
|
71
|
+
coreFailureCount: number;
|
|
72
|
+
}
|
|
73
|
+
export interface DeterministicScoringResult {
|
|
74
|
+
scopeGate: ScopeGateResult;
|
|
75
|
+
constraintViolations: ConstraintViolationResult;
|
|
76
|
+
antiPatternHits: AntiPatternResult;
|
|
77
|
+
designAntiPatternHits: AntiPatternResult;
|
|
78
|
+
measurableSignalChecks: MeasurableSignalResult;
|
|
79
|
+
/** Shortcut — true when the scope gate (core) fails. */
|
|
80
|
+
hardGated: boolean;
|
|
81
|
+
/** Total count of `core` violations across all sources. */
|
|
82
|
+
coreViolationCount: number;
|
|
83
|
+
/** Total count of `evolving` violations across all sources. */
|
|
84
|
+
evolvingViolationCount: number;
|
|
85
|
+
/** Human-readable pre-verified summary for Layer 3 prompt injection. */
|
|
86
|
+
preVerifiedSummary: string;
|
|
87
|
+
}
|
|
88
|
+
export declare function checkScopeGate(issueText: string, compiled: CompiledDid): ScopeGateResult;
|
|
89
|
+
export declare function detectConstraintViolations(issueText: string, compiled: CompiledDid, client: DepparseClient): Promise<ConstraintViolationResult>;
|
|
90
|
+
export declare function detectAntiPatterns(issueText: string, compiled: CompiledDid): {
|
|
91
|
+
product: AntiPatternResult;
|
|
92
|
+
design: AntiPatternResult;
|
|
93
|
+
};
|
|
94
|
+
export declare function checkMeasurableSignals(observed: Record<string, number>, compiled: CompiledDid): MeasurableSignalResult;
|
|
95
|
+
export interface Layer1Input {
|
|
96
|
+
issueText: string;
|
|
97
|
+
compiled: CompiledDid;
|
|
98
|
+
depparse: DepparseClient;
|
|
99
|
+
/** Observed metric values keyed by signal metric name. */
|
|
100
|
+
observedMetrics?: Record<string, number>;
|
|
101
|
+
}
|
|
102
|
+
export declare function runLayer1(input: Layer1Input): Promise<DeterministicScoringResult>;
|
|
103
|
+
interface SummaryInput {
|
|
104
|
+
scopeGate: ScopeGateResult;
|
|
105
|
+
constraintViolations: ConstraintViolationResult;
|
|
106
|
+
product: AntiPatternResult;
|
|
107
|
+
design: AntiPatternResult;
|
|
108
|
+
measurable: MeasurableSignalResult;
|
|
109
|
+
hardGated: boolean;
|
|
110
|
+
coreViolationCount: number;
|
|
111
|
+
evolvingViolationCount: number;
|
|
112
|
+
}
|
|
113
|
+
export declare function renderPreVerifiedSummary(input: SummaryInput): string;
|
|
114
|
+
export {};
|
|
115
|
+
//# sourceMappingURL=layer1-deterministic.d.ts.map
|