@substrate-ai/sdlc 0.19.54
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/events.d.ts +336 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +11 -0
- package/dist/events.js.map +1 -0
- package/dist/gating/conflict-detector.d.ts +59 -0
- package/dist/gating/conflict-detector.d.ts.map +1 -0
- package/dist/gating/conflict-detector.js +101 -0
- package/dist/gating/conflict-detector.js.map +1 -0
- package/dist/gating/dispatch-gate.d.ts +42 -0
- package/dist/gating/dispatch-gate.d.ts.map +1 -0
- package/dist/gating/dispatch-gate.js +197 -0
- package/dist/gating/dispatch-gate.js.map +1 -0
- package/dist/gating/index.d.ts +9 -0
- package/dist/gating/index.d.ts.map +1 -0
- package/dist/gating/index.js +8 -0
- package/dist/gating/index.js.map +1 -0
- package/dist/gating/types.d.ts +98 -0
- package/dist/gating/types.d.ts.map +1 -0
- package/dist/gating/types.js +8 -0
- package/dist/gating/types.js.map +1 -0
- package/dist/handlers/event-bridge.d.ts +56 -0
- package/dist/handlers/event-bridge.d.ts.map +1 -0
- package/dist/handlers/event-bridge.js +140 -0
- package/dist/handlers/event-bridge.js.map +1 -0
- package/dist/handlers/index.d.ts +15 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +14 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/sdlc-code-review-handler.d.ts +119 -0
- package/dist/handlers/sdlc-code-review-handler.d.ts.map +1 -0
- package/dist/handlers/sdlc-code-review-handler.js +131 -0
- package/dist/handlers/sdlc-code-review-handler.js.map +1 -0
- package/dist/handlers/sdlc-create-story-handler.d.ts +97 -0
- package/dist/handlers/sdlc-create-story-handler.d.ts.map +1 -0
- package/dist/handlers/sdlc-create-story-handler.js +91 -0
- package/dist/handlers/sdlc-create-story-handler.js.map +1 -0
- package/dist/handlers/sdlc-dev-story-handler.d.ts +121 -0
- package/dist/handlers/sdlc-dev-story-handler.d.ts.map +1 -0
- package/dist/handlers/sdlc-dev-story-handler.js +288 -0
- package/dist/handlers/sdlc-dev-story-handler.js.map +1 -0
- package/dist/handlers/sdlc-phase-handler.d.ts +32 -0
- package/dist/handlers/sdlc-phase-handler.d.ts.map +1 -0
- package/dist/handlers/sdlc-phase-handler.js +166 -0
- package/dist/handlers/sdlc-phase-handler.js.map +1 -0
- package/dist/handlers/types.d.ts +132 -0
- package/dist/handlers/types.d.ts.map +1 -0
- package/dist/handlers/types.js +10 -0
- package/dist/handlers/types.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/learning/failure-classifier.d.ts +23 -0
- package/dist/learning/failure-classifier.d.ts.map +1 -0
- package/dist/learning/failure-classifier.js +75 -0
- package/dist/learning/failure-classifier.js.map +1 -0
- package/dist/learning/finding-classifier.d.ts +25 -0
- package/dist/learning/finding-classifier.d.ts.map +1 -0
- package/dist/learning/finding-classifier.js +37 -0
- package/dist/learning/finding-classifier.js.map +1 -0
- package/dist/learning/finding-lifecycle.d.ts +69 -0
- package/dist/learning/finding-lifecycle.d.ts.map +1 -0
- package/dist/learning/finding-lifecycle.js +162 -0
- package/dist/learning/finding-lifecycle.js.map +1 -0
- package/dist/learning/finding-store.d.ts +16 -0
- package/dist/learning/finding-store.d.ts.map +1 -0
- package/dist/learning/finding-store.js +26 -0
- package/dist/learning/finding-store.js.map +1 -0
- package/dist/learning/findings-injector.d.ts +34 -0
- package/dist/learning/findings-injector.d.ts.map +1 -0
- package/dist/learning/findings-injector.js +140 -0
- package/dist/learning/findings-injector.js.map +1 -0
- package/dist/learning/index.d.ts +8 -0
- package/dist/learning/index.d.ts.map +1 -0
- package/dist/learning/index.js +10 -0
- package/dist/learning/index.js.map +1 -0
- package/dist/learning/relevance-scorer.d.ts +25 -0
- package/dist/learning/relevance-scorer.d.ts.map +1 -0
- package/dist/learning/relevance-scorer.js +49 -0
- package/dist/learning/relevance-scorer.js.map +1 -0
- package/dist/learning/types.d.ts +55 -0
- package/dist/learning/types.d.ts.map +1 -0
- package/dist/learning/types.js +36 -0
- package/dist/learning/types.js.map +1 -0
- package/dist/orchestrator/graph-orchestrator.d.ts +208 -0
- package/dist/orchestrator/graph-orchestrator.d.ts.map +1 -0
- package/dist/orchestrator/graph-orchestrator.js +213 -0
- package/dist/orchestrator/graph-orchestrator.js.map +1 -0
- package/dist/run-manifest/cli-flags.d.ts +11 -0
- package/dist/run-manifest/cli-flags.d.ts.map +1 -0
- package/dist/run-manifest/cli-flags.js +10 -0
- package/dist/run-manifest/cli-flags.js.map +1 -0
- package/dist/run-manifest/index.d.ts +10 -0
- package/dist/run-manifest/index.d.ts.map +1 -0
- package/dist/run-manifest/index.js +10 -0
- package/dist/run-manifest/index.js.map +1 -0
- package/dist/run-model/cli-flags.d.ts +27 -0
- package/dist/run-model/cli-flags.d.ts.map +1 -0
- package/dist/run-model/cli-flags.js +31 -0
- package/dist/run-model/cli-flags.js.map +1 -0
- package/dist/run-model/index.d.ts +21 -0
- package/dist/run-model/index.d.ts.map +1 -0
- package/dist/run-model/index.js +19 -0
- package/dist/run-model/index.js.map +1 -0
- package/dist/run-model/per-story-state.d.ts +62 -0
- package/dist/run-model/per-story-state.d.ts.map +1 -0
- package/dist/run-model/per-story-state.js +70 -0
- package/dist/run-model/per-story-state.js.map +1 -0
- package/dist/run-model/recovery-history.d.ts +56 -0
- package/dist/run-model/recovery-history.d.ts.map +1 -0
- package/dist/run-model/recovery-history.js +83 -0
- package/dist/run-model/recovery-history.js.map +1 -0
- package/dist/run-model/run-manifest.d.ts +146 -0
- package/dist/run-model/run-manifest.d.ts.map +1 -0
- package/dist/run-model/run-manifest.js +481 -0
- package/dist/run-model/run-manifest.js.map +1 -0
- package/dist/run-model/schemas.d.ts +117 -0
- package/dist/run-model/schemas.d.ts.map +1 -0
- package/dist/run-model/schemas.js +83 -0
- package/dist/run-model/schemas.js.map +1 -0
- package/dist/run-model/supervisor-lock.d.ts +104 -0
- package/dist/run-model/supervisor-lock.d.ts.map +1 -0
- package/dist/run-model/supervisor-lock.js +284 -0
- package/dist/run-model/supervisor-lock.js.map +1 -0
- package/dist/run-model/types.d.ts +74 -0
- package/dist/run-model/types.d.ts.map +1 -0
- package/dist/run-model/types.js +8 -0
- package/dist/run-model/types.js.map +1 -0
- package/dist/run-model/verification-result.d.ts +60 -0
- package/dist/run-model/verification-result.d.ts.map +1 -0
- package/dist/run-model/verification-result.js +55 -0
- package/dist/run-model/verification-result.js.map +1 -0
- package/dist/verification/checks/acceptance-criteria-evidence-check.d.ts +21 -0
- package/dist/verification/checks/acceptance-criteria-evidence-check.d.ts.map +1 -0
- package/dist/verification/checks/acceptance-criteria-evidence-check.js +159 -0
- package/dist/verification/checks/acceptance-criteria-evidence-check.js.map +1 -0
- package/dist/verification/checks/build-check.d.ts +52 -0
- package/dist/verification/checks/build-check.d.ts.map +1 -0
- package/dist/verification/checks/build-check.js +160 -0
- package/dist/verification/checks/build-check.js.map +1 -0
- package/dist/verification/checks/index.d.ts +15 -0
- package/dist/verification/checks/index.d.ts.map +1 -0
- package/dist/verification/checks/index.js +15 -0
- package/dist/verification/checks/index.js.map +1 -0
- package/dist/verification/checks/phantom-review-check.d.ts +29 -0
- package/dist/verification/checks/phantom-review-check.d.ts.map +1 -0
- package/dist/verification/checks/phantom-review-check.js +70 -0
- package/dist/verification/checks/phantom-review-check.js.map +1 -0
- package/dist/verification/checks/trivial-output-check.d.ts +47 -0
- package/dist/verification/checks/trivial-output-check.d.ts.map +1 -0
- package/dist/verification/checks/trivial-output-check.js +72 -0
- package/dist/verification/checks/trivial-output-check.js.map +1 -0
- package/dist/verification/index.d.ts +13 -0
- package/dist/verification/index.d.ts.map +1 -0
- package/dist/verification/index.js +13 -0
- package/dist/verification/index.js.map +1 -0
- package/dist/verification/types.d.ts +149 -0
- package/dist/verification/types.d.ts.map +1 -0
- package/dist/verification/types.js +12 -0
- package/dist/verification/types.js.map +1 -0
- package/dist/verification/verification-pipeline.d.ts +65 -0
- package/dist/verification/verification-pipeline.d.ts.map +1 -0
- package/dist/verification/verification-pipeline.js +149 -0
- package/dist/verification/verification-pipeline.js.map +1 -0
- package/graphs/sdlc-pipeline.dot +42 -0
- package/package.json +22 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FindingsInjector — relevance-scored learning findings injector.
|
|
3
|
+
*
|
|
4
|
+
* Story 53-6: Findings Injector with Relevance Scoring
|
|
5
|
+
*
|
|
6
|
+
* Queries structured findings from the decisions table, scores each finding
|
|
7
|
+
* against an injection context, applies threshold/saturation guards, and
|
|
8
|
+
* serializes the top-ranked findings with budget enforcement.
|
|
9
|
+
*/
|
|
10
|
+
import { getDecisionsByCategory, LEARNING_FINDING } from '@substrate-ai/core';
|
|
11
|
+
import { FindingSchema } from './types.js';
|
|
12
|
+
import { scoreRelevance } from './relevance-scorer.js';
|
|
13
|
+
import { FindingLifecycleManager } from './finding-lifecycle.js';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// FindingsInjector
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
export class FindingsInjector {
|
|
18
|
+
/**
|
|
19
|
+
* Query relevance-scored findings from the decisions table and serialize
|
|
20
|
+
* them as a prompt-injection string within the given character budget.
|
|
21
|
+
*
|
|
22
|
+
* Returns '' if no findings survive filtering or on any DB error.
|
|
23
|
+
*/
|
|
24
|
+
static async inject(db, context, config) {
|
|
25
|
+
// Resolve config defaults
|
|
26
|
+
const threshold = config?.threshold ?? 0.3;
|
|
27
|
+
const maxChars = config?.maxChars ?? 2000;
|
|
28
|
+
const saturationLimit = config?.saturationLimit ?? 10;
|
|
29
|
+
// Query decisions table for LEARNING_FINDING rows
|
|
30
|
+
let rows;
|
|
31
|
+
try {
|
|
32
|
+
rows = await getDecisionsByCategory(db, LEARNING_FINDING);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
// Parse valid findings; skip malformed rows silently
|
|
38
|
+
const validFindings = [];
|
|
39
|
+
for (const row of rows) {
|
|
40
|
+
try {
|
|
41
|
+
const parsed = JSON.parse(row.value);
|
|
42
|
+
const result = FindingSchema.safeParse(parsed);
|
|
43
|
+
if (!result.success)
|
|
44
|
+
continue;
|
|
45
|
+
validFindings.push(result.data);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Malformed JSON — skip this row
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// === Story 53-7: Lifecycle preprocessing ===
|
|
53
|
+
// Step 3a: Deduplicate by root_cause + files fingerprint
|
|
54
|
+
let candidates = FindingLifecycleManager.deduplicate(validFindings);
|
|
55
|
+
// Step 3b: Exclude tombstoned (contradicted/archived) findings
|
|
56
|
+
candidates = candidates.filter((f) => f.contradicted_by === undefined);
|
|
57
|
+
// Step 3c: File existence validation (demote if missing)
|
|
58
|
+
const projectRoot = process.cwd();
|
|
59
|
+
candidates = candidates.map((f) => {
|
|
60
|
+
try {
|
|
61
|
+
return FindingLifecycleManager.validateFiles(f, projectRoot);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return f;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
// Step 3d: Expiry check — archive and exclude expired findings
|
|
68
|
+
const survivingCandidates = [];
|
|
69
|
+
for (const f of candidates) {
|
|
70
|
+
try {
|
|
71
|
+
const runCount = await FindingLifecycleManager.countRunsSinceCreation(f, db);
|
|
72
|
+
if (FindingLifecycleManager.isExpired(f, runCount)) {
|
|
73
|
+
await FindingLifecycleManager.archiveFinding(f, context.runId, db);
|
|
74
|
+
continue; // excluded from injection
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Non-fatal: include the finding
|
|
79
|
+
}
|
|
80
|
+
survivingCandidates.push(f);
|
|
81
|
+
}
|
|
82
|
+
const scoredInput = survivingCandidates;
|
|
83
|
+
// === End lifecycle preprocessing ===
|
|
84
|
+
// Score surviving candidates
|
|
85
|
+
const scored = scoredInput.map((f) => ({
|
|
86
|
+
finding: f,
|
|
87
|
+
score: scoreRelevance(f, context),
|
|
88
|
+
}));
|
|
89
|
+
// Initial threshold filter
|
|
90
|
+
let dynamicThreshold = threshold;
|
|
91
|
+
let filtered = scored.filter(({ score }) => score >= dynamicThreshold);
|
|
92
|
+
// Saturation guard: raise threshold in 0.1 increments until ≤ saturationLimit remain
|
|
93
|
+
while (filtered.length > saturationLimit && dynamicThreshold <= 1.0) {
|
|
94
|
+
dynamicThreshold = Math.round((dynamicThreshold + 0.1) * 10) / 10;
|
|
95
|
+
filtered = scored.filter(({ score }) => score >= dynamicThreshold);
|
|
96
|
+
}
|
|
97
|
+
// If still over limit after threshold > 1.0, take top saturationLimit by score
|
|
98
|
+
if (filtered.length > saturationLimit) {
|
|
99
|
+
filtered = filtered.sort((a, b) => b.score - a.score).slice(0, saturationLimit);
|
|
100
|
+
}
|
|
101
|
+
// Sort by score descending
|
|
102
|
+
filtered.sort((a, b) => b.score - a.score);
|
|
103
|
+
// Serialize with maxChars budget enforcement
|
|
104
|
+
const prefix = 'Prior run findings (most relevant first):\n\n';
|
|
105
|
+
const lines = [];
|
|
106
|
+
let usedChars = prefix.length;
|
|
107
|
+
for (const { finding } of filtered) {
|
|
108
|
+
const line = finding.confidence === 'high'
|
|
109
|
+
? `[${finding.root_cause}] Directive: ${finding.description}`
|
|
110
|
+
: `[${finding.root_cause}] Note (low confidence): ${finding.description}`;
|
|
111
|
+
// Separator: '\n' between lines (not before the first)
|
|
112
|
+
const addedLen = lines.length === 0 ? line.length : 1 + line.length;
|
|
113
|
+
if (usedChars + addedLen > maxChars)
|
|
114
|
+
break;
|
|
115
|
+
lines.push(line);
|
|
116
|
+
usedChars += addedLen;
|
|
117
|
+
}
|
|
118
|
+
if (lines.length === 0)
|
|
119
|
+
return '';
|
|
120
|
+
return prefix + lines.join('\n');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// extractTargetFilesFromStoryContent
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
/**
|
|
127
|
+
* Extract file paths referenced in a story document for use as targetFiles
|
|
128
|
+
* in relevance scoring.
|
|
129
|
+
*
|
|
130
|
+
* Matches paths starting with `packages/` or `src/` with common code extensions.
|
|
131
|
+
* Returns up to 30 unique paths.
|
|
132
|
+
*/
|
|
133
|
+
export function extractTargetFilesFromStoryContent(storyContent) {
|
|
134
|
+
// Note: 'json' must appear before 'js' to prevent '.js' from matching '.json' files
|
|
135
|
+
const pattern = /(?:packages\/|src\/)[\w/.~-]+\.(?:ts|json|js|md)/g;
|
|
136
|
+
const matches = storyContent.match(pattern) ?? [];
|
|
137
|
+
const unique = [...new Set(matches)];
|
|
138
|
+
return unique.slice(0, 30);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=findings-injector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findings-injector.js","sourceRoot":"","sources":["../../src/learning/findings-injector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export * from './failure-classifier.js';
|
|
3
|
+
export * from './finding-store.js';
|
|
4
|
+
export * from './finding-classifier.js';
|
|
5
|
+
export * from './relevance-scorer.js';
|
|
6
|
+
export * from './findings-injector.js';
|
|
7
|
+
export * from './finding-lifecycle.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/learning/index.ts"],"names":[],"mappings":"AACA,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AAEtC,cAAc,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Story 53-5: Learning loop — root cause taxonomy and failure classification
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
export * from './failure-classifier.js';
|
|
4
|
+
export * from './finding-store.js';
|
|
5
|
+
export * from './finding-classifier.js';
|
|
6
|
+
export * from './relevance-scorer.js';
|
|
7
|
+
export * from './findings-injector.js';
|
|
8
|
+
// Story 53-7: Finding lifecycle — validation, deduplication, expiry, retirement
|
|
9
|
+
export * from './finding-lifecycle.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/learning/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,cAAc,oBAAoB,CAAA;AAClC,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,gFAAgF;AAChF,cAAc,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RelevanceScorer — deterministic relevance scoring for learning findings.
|
|
3
|
+
*
|
|
4
|
+
* Story 53-6: Findings Injector with Relevance Scoring
|
|
5
|
+
*
|
|
6
|
+
* Computes a [0, 1] relevance score for a Finding relative to an injection
|
|
7
|
+
* context using a three-component weighted formula:
|
|
8
|
+
* 0.5 * jaccardFileOverlap + 0.3 * packageMatch + 0.2 * rootCauseMatch
|
|
9
|
+
*/
|
|
10
|
+
import type { Finding, RootCauseCategory } from './types.js';
|
|
11
|
+
export interface InjectionContext {
|
|
12
|
+
storyKey: string;
|
|
13
|
+
runId: string;
|
|
14
|
+
targetFiles?: string[];
|
|
15
|
+
packageName?: string;
|
|
16
|
+
riskProfile?: RootCauseCategory[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Score the relevance of a Finding to the given InjectionContext.
|
|
20
|
+
*
|
|
21
|
+
* @returns A number in [0, 1] computed as:
|
|
22
|
+
* 0.5 * jaccardFileOverlap + 0.3 * packageMatch + 0.2 * rootCauseMatch
|
|
23
|
+
*/
|
|
24
|
+
export declare function scoreRelevance(finding: Finding, context: InjectionContext): number;
|
|
25
|
+
//# sourceMappingURL=relevance-scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relevance-scorer.d.ts","sourceRoot":"","sources":["../../src/learning/relevance-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAM5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAClC;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAmClF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RelevanceScorer — deterministic relevance scoring for learning findings.
|
|
3
|
+
*
|
|
4
|
+
* Story 53-6: Findings Injector with Relevance Scoring
|
|
5
|
+
*
|
|
6
|
+
* Computes a [0, 1] relevance score for a Finding relative to an injection
|
|
7
|
+
* context using a three-component weighted formula:
|
|
8
|
+
* 0.5 * jaccardFileOverlap + 0.3 * packageMatch + 0.2 * rootCauseMatch
|
|
9
|
+
*/
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
// scoreRelevance — pure synchronous relevance scoring
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
/**
|
|
14
|
+
* Score the relevance of a Finding to the given InjectionContext.
|
|
15
|
+
*
|
|
16
|
+
* @returns A number in [0, 1] computed as:
|
|
17
|
+
* 0.5 * jaccardFileOverlap + 0.3 * packageMatch + 0.2 * rootCauseMatch
|
|
18
|
+
*/
|
|
19
|
+
export function scoreRelevance(finding, context) {
|
|
20
|
+
// --- Jaccard file overlap ---
|
|
21
|
+
// Cap target files to the 20 shortest paths (sorted ascending by length)
|
|
22
|
+
const cappedTargets = (context.targetFiles ?? [])
|
|
23
|
+
.sort((a, b) => a.length - b.length)
|
|
24
|
+
.slice(0, 20);
|
|
25
|
+
const targetSet = new Set(cappedTargets);
|
|
26
|
+
const intersectionCount = finding.affected_files.filter((f) => targetSet.has(f)).length;
|
|
27
|
+
const jaccardFileOverlap = cappedTargets.length === 0 || finding.affected_files.length === 0
|
|
28
|
+
? 0
|
|
29
|
+
: intersectionCount / Math.min(finding.affected_files.length, cappedTargets.length);
|
|
30
|
+
// --- Package match ---
|
|
31
|
+
// Extract package name from each path in affected_files via packages/<name>/
|
|
32
|
+
const pkgRegex = /packages\/([^/]+)\//;
|
|
33
|
+
const inferredPackages = finding.affected_files
|
|
34
|
+
.map((f) => pkgRegex.exec(f)?.[1])
|
|
35
|
+
.filter((p) => p !== undefined);
|
|
36
|
+
const packageMatch = context.packageName === undefined || inferredPackages.length === 0
|
|
37
|
+
? 0.5
|
|
38
|
+
: inferredPackages.includes(context.packageName)
|
|
39
|
+
? 1.0
|
|
40
|
+
: 0.0;
|
|
41
|
+
// --- Root cause match ---
|
|
42
|
+
const rootCauseMatch = !context.riskProfile || context.riskProfile.length === 0
|
|
43
|
+
? 0.5
|
|
44
|
+
: context.riskProfile.includes(finding.root_cause)
|
|
45
|
+
? 1.0
|
|
46
|
+
: 0.0;
|
|
47
|
+
return Math.min(1, Math.max(0, 0.5 * jaccardFileOverlap + 0.3 * packageMatch + 0.2 * rootCauseMatch));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=relevance-scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relevance-scorer.js","sourceRoot":"","sources":["../../src/learning/relevance-scorer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAgBH,8EAA8E;AAC9E,sDAAsD;AACtD,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,OAAyB;IACxE,+BAA+B;IAC/B,yEAAyE;IACzE,MAAM,aAAa,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC;SAC9C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;SACnC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACf,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAA;IACxC,MAAM,iBAAiB,GAAG,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAA;IACvF,MAAM,kBAAkB,GACtB,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC;QAC/D,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAEvF,wBAAwB;IACxB,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,qBAAqB,CAAA;IACtC,MAAM,gBAAgB,GAAG,OAAO,CAAC,cAAc;SAC5C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SACjC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAA;IAC9C,MAAM,YAAY,GAChB,OAAO,CAAC,WAAW,KAAK,SAAS,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC;QAChE,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,CAAC;YAC9C,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,GAAG,CAAA;IAEX,2BAA2B;IAC3B,MAAM,cAAc,GAClB,CAAC,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC;QACtD,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC;YAChD,CAAC,CAAC,GAAG;YACL,CAAC,CAAC,GAAG,CAAA;IAEX,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,kBAAkB,GAAG,GAAG,GAAG,YAAY,GAAG,GAAG,GAAG,cAAc,CAAC,CAAC,CAAA;AACvG,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning loop — root cause taxonomy types.
|
|
3
|
+
*
|
|
4
|
+
* Story 53-5: Root Cause Taxonomy and Failure Classification
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
export declare const RootCauseCategorySchema: z.ZodEnum<{
|
|
8
|
+
"namespace-collision": "namespace-collision";
|
|
9
|
+
"dependency-ordering": "dependency-ordering";
|
|
10
|
+
"spec-staleness": "spec-staleness";
|
|
11
|
+
"adapter-format": "adapter-format";
|
|
12
|
+
"build-failure": "build-failure";
|
|
13
|
+
"test-failure": "test-failure";
|
|
14
|
+
"resource-exhaustion": "resource-exhaustion";
|
|
15
|
+
infrastructure: "infrastructure";
|
|
16
|
+
unclassified: "unclassified";
|
|
17
|
+
}>;
|
|
18
|
+
export type RootCauseCategory = z.infer<typeof RootCauseCategorySchema>;
|
|
19
|
+
export declare const FindingSchema: z.ZodObject<{
|
|
20
|
+
id: z.ZodString;
|
|
21
|
+
run_id: z.ZodString;
|
|
22
|
+
story_key: z.ZodString;
|
|
23
|
+
root_cause: z.ZodEnum<{
|
|
24
|
+
"namespace-collision": "namespace-collision";
|
|
25
|
+
"dependency-ordering": "dependency-ordering";
|
|
26
|
+
"spec-staleness": "spec-staleness";
|
|
27
|
+
"adapter-format": "adapter-format";
|
|
28
|
+
"build-failure": "build-failure";
|
|
29
|
+
"test-failure": "test-failure";
|
|
30
|
+
"resource-exhaustion": "resource-exhaustion";
|
|
31
|
+
infrastructure: "infrastructure";
|
|
32
|
+
unclassified: "unclassified";
|
|
33
|
+
}>;
|
|
34
|
+
affected_files: z.ZodArray<z.ZodString>;
|
|
35
|
+
description: z.ZodString;
|
|
36
|
+
confidence: z.ZodEnum<{
|
|
37
|
+
high: "high";
|
|
38
|
+
low: "low";
|
|
39
|
+
}>;
|
|
40
|
+
created_at: z.ZodString;
|
|
41
|
+
expires_after_runs: z.ZodDefault<z.ZodNumber>;
|
|
42
|
+
contradicted_by: z.ZodOptional<z.ZodString>;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
export type Finding = z.infer<typeof FindingSchema>;
|
|
45
|
+
export interface StoryFailureContext {
|
|
46
|
+
storyKey: string;
|
|
47
|
+
runId: string;
|
|
48
|
+
error?: string;
|
|
49
|
+
outputTokens?: number;
|
|
50
|
+
buildFailed?: boolean;
|
|
51
|
+
testsFailed?: boolean;
|
|
52
|
+
adapterError?: boolean;
|
|
53
|
+
affectedFiles?: string[];
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/learning/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB,eAAO,MAAM,uBAAuB;;;;;;;;;;EAUlC,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAA;AAMvE,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;iBAWxB,CAAA;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAA;AAOnD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CACzB"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Learning loop — root cause taxonomy types.
|
|
3
|
+
*
|
|
4
|
+
* Story 53-5: Root Cause Taxonomy and Failure Classification
|
|
5
|
+
*/
|
|
6
|
+
import { z } from 'zod';
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
// Root cause category enum
|
|
9
|
+
// ---------------------------------------------------------------------------
|
|
10
|
+
export const RootCauseCategorySchema = z.enum([
|
|
11
|
+
'namespace-collision',
|
|
12
|
+
'dependency-ordering',
|
|
13
|
+
'spec-staleness',
|
|
14
|
+
'adapter-format',
|
|
15
|
+
'build-failure',
|
|
16
|
+
'test-failure',
|
|
17
|
+
'resource-exhaustion',
|
|
18
|
+
'infrastructure',
|
|
19
|
+
'unclassified',
|
|
20
|
+
]);
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Finding schema
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
export const FindingSchema = z.object({
|
|
25
|
+
id: z.string().uuid(),
|
|
26
|
+
run_id: z.string(),
|
|
27
|
+
story_key: z.string(),
|
|
28
|
+
root_cause: RootCauseCategorySchema,
|
|
29
|
+
affected_files: z.array(z.string()),
|
|
30
|
+
description: z.string(),
|
|
31
|
+
confidence: z.enum(['high', 'low']),
|
|
32
|
+
created_at: z.string(),
|
|
33
|
+
expires_after_runs: z.number().int().positive().default(5),
|
|
34
|
+
contradicted_by: z.string().optional(),
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/learning/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,8EAA8E;AAC9E,2BAA2B;AAC3B,8EAA8E;AAE9E,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,IAAI,CAAC;IAC5C,qBAAqB;IACrB,qBAAqB;IACrB,gBAAgB;IAChB,gBAAgB;IAChB,eAAe;IACf,cAAc;IACd,qBAAqB;IACrB,gBAAgB;IAChB,cAAc;CACf,CAAC,CAAA;AAIF,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC;IACpC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;IACrB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;IACrB,UAAU,EAAE,uBAAuB;IACnC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IACnC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACnC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE;IACtB,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACvC,CAAC,CAAA"}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphOrchestrator — drives the SDLC pipeline as a factory graph.
|
|
3
|
+
*
|
|
4
|
+
* Story 43-7: GraphOrchestrator multi-story orchestration.
|
|
5
|
+
* Story 43-8: applyConfigToGraph config-to-graph mapping (duck-typed, ADR-003 compliant).
|
|
6
|
+
* Story 43-10: resolveGraphPath helper; eventBus/pipelineRunId/maxReviewCycles in config;
|
|
7
|
+
* per-story outcome tracking in GraphRunSummary.
|
|
8
|
+
*
|
|
9
|
+
* ADR-003: NO imports from @substrate-ai/factory in this file.
|
|
10
|
+
* All factory-side types are accepted via locally-defined duck-typed
|
|
11
|
+
* interfaces injected through GraphOrchestratorConfig.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Returns the absolute path to the bundled SDLC pipeline DOT file.
|
|
15
|
+
*
|
|
16
|
+
* Resolution order:
|
|
17
|
+
* 1. Relative to __dirname (works in source/unbundled: __dirname = packages/sdlc/src/orchestrator/)
|
|
18
|
+
* 2. Via createRequire to locate @substrate-ai/sdlc package.json, then graphs/ relative to it
|
|
19
|
+
* (works when bundled: __dirname points to dist/ but createRequire finds the real package)
|
|
20
|
+
*
|
|
21
|
+
* @throws {Error} if the DOT file cannot be found by any method.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveGraphPath(): string;
|
|
24
|
+
/**
|
|
25
|
+
* Minimal structural interface for a factory graph object.
|
|
26
|
+
* Duck-typed from `@substrate-ai/factory`'s `Graph` — no direct import.
|
|
27
|
+
*/
|
|
28
|
+
export interface GraphShape {
|
|
29
|
+
nodes: Array<{
|
|
30
|
+
id: string;
|
|
31
|
+
type: string;
|
|
32
|
+
label: string;
|
|
33
|
+
prompt: string;
|
|
34
|
+
}>;
|
|
35
|
+
edges: Array<{
|
|
36
|
+
from: string;
|
|
37
|
+
to: string;
|
|
38
|
+
label?: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Configuration passed to the executor for a single graph run.
|
|
43
|
+
* Duck-typed from `@substrate-ai/factory`'s `GraphExecutorConfig`.
|
|
44
|
+
*/
|
|
45
|
+
export interface GraphRunConfig {
|
|
46
|
+
runId: string;
|
|
47
|
+
logsRoot: string;
|
|
48
|
+
handlerRegistry: unknown;
|
|
49
|
+
initialContext?: Record<string, unknown>;
|
|
50
|
+
eventBus?: unknown;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Result returned by the executor for a single graph run.
|
|
54
|
+
* Duck-typed from `@substrate-ai/factory`'s `Outcome`.
|
|
55
|
+
* Maps StageStatus: 'SUCCESS' | 'FAIL' | 'PARTIAL_SUCCESS' | 'RETRY' | 'SKIPPED'
|
|
56
|
+
*/
|
|
57
|
+
export interface GraphRunResult {
|
|
58
|
+
status: 'SUCCESS' | 'FAIL' | 'PARTIAL_SUCCESS' | 'RETRY' | 'SKIPPED' | string;
|
|
59
|
+
failureReason?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Duck-typed executor contract — structurally compatible with `GraphExecutor` from factory.
|
|
63
|
+
*/
|
|
64
|
+
export interface IGraphExecutorLocal {
|
|
65
|
+
run(graph: GraphShape, config: GraphRunConfig): Promise<GraphRunResult>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Batched conflict groups: outer = batches (sequential), middle = groups
|
|
69
|
+
* (sequential within batch), inner = story keys (sequential within group).
|
|
70
|
+
*/
|
|
71
|
+
export type ConflictGroupBatches = string[][][];
|
|
72
|
+
/**
|
|
73
|
+
* Function that partitions story keys into ordered batches of conflict groups.
|
|
74
|
+
* Injected by the CLI composition root (story 43-10).
|
|
75
|
+
*/
|
|
76
|
+
export type ConflictGrouperFn = (storyKeys: string[]) => ConflictGroupBatches;
|
|
77
|
+
/**
|
|
78
|
+
* Configuration for `createGraphOrchestrator`.
|
|
79
|
+
*
|
|
80
|
+
* All factory-side objects (`graph`, `executor`, `handlerRegistry`) are injected
|
|
81
|
+
* here — the orchestrator never imports `@substrate-ai/factory` directly (ADR-003).
|
|
82
|
+
*/
|
|
83
|
+
export interface GraphOrchestratorConfig {
|
|
84
|
+
/** Pre-parsed graph object (structurally compatible with factory's Graph). */
|
|
85
|
+
graph: GraphShape;
|
|
86
|
+
/** Executor that runs a single story graph instance. */
|
|
87
|
+
executor: IGraphExecutorLocal;
|
|
88
|
+
/** Handler registry passed through to executor config. */
|
|
89
|
+
handlerRegistry: unknown;
|
|
90
|
+
/** Absolute path to the project root. */
|
|
91
|
+
projectRoot: string;
|
|
92
|
+
/** Methodology pack identifier passed to each story graph instance. */
|
|
93
|
+
methodologyPack: string;
|
|
94
|
+
/** Maximum number of concurrent story graph executor instances. */
|
|
95
|
+
maxConcurrency: number;
|
|
96
|
+
/** Directory under which per-story run logs are written. */
|
|
97
|
+
logsRoot: string;
|
|
98
|
+
/** Unique identifier for this orchestration run. */
|
|
99
|
+
runId: string;
|
|
100
|
+
/**
|
|
101
|
+
* Optional conflict group partitioner. If omitted, each story runs in its own
|
|
102
|
+
* single-item group within a single batch (fully parallel up to maxConcurrency).
|
|
103
|
+
*/
|
|
104
|
+
conflictGrouper?: ConflictGrouperFn;
|
|
105
|
+
/**
|
|
106
|
+
* Milliseconds to pause between stories within the same conflict group.
|
|
107
|
+
* Reduces memory pressure during long runs. Defaults to 2000.
|
|
108
|
+
*/
|
|
109
|
+
gcPauseMs?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Optional SDLC event bus that receives translated orchestrator events via the
|
|
112
|
+
* SDLC event bridge (story 43-9). When provided, graph executor lifecycle events
|
|
113
|
+
* are translated into `orchestrator:story-phase-*` events for downstream consumers.
|
|
114
|
+
* (story 43-10: wired by CLI composition root)
|
|
115
|
+
*/
|
|
116
|
+
eventBus?: unknown;
|
|
117
|
+
/**
|
|
118
|
+
* Optional pipeline run ID forwarded to SDLC event bridge payloads.
|
|
119
|
+
* Included as `pipelineRunId` in `orchestrator:story-phase-start/complete` events.
|
|
120
|
+
* (story 43-10)
|
|
121
|
+
*/
|
|
122
|
+
pipelineRunId?: string;
|
|
123
|
+
/**
|
|
124
|
+
* Maximum number of code-review + fix cycles per story.
|
|
125
|
+
* Forwarded to the graph via `applyConfigToGraph` before execution and
|
|
126
|
+
* stored here for observability / testing (AC7, story 43-10).
|
|
127
|
+
*/
|
|
128
|
+
maxReviewCycles?: number;
|
|
129
|
+
/**
|
|
130
|
+
* Per-story maximum retry attempts before mandatory escalation (Story 53-4).
|
|
131
|
+
* Default: 2. Reserved for future graph-engine budget gate implementation.
|
|
132
|
+
*/
|
|
133
|
+
retryBudget?: number;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Per-story outcome detail in `GraphRunSummary`.
|
|
137
|
+
* Story 43-10: added for normalisation by the CLI composition root.
|
|
138
|
+
*/
|
|
139
|
+
export interface GraphStoryOutcome {
|
|
140
|
+
outcome: 'SUCCESS' | 'FAILED' | 'ESCALATED';
|
|
141
|
+
error?: string;
|
|
142
|
+
}
|
|
143
|
+
/** Summary returned by `GraphOrchestrator.run()` after all stories complete. */
|
|
144
|
+
export interface GraphRunSummary {
|
|
145
|
+
successCount: number;
|
|
146
|
+
failureCount: number;
|
|
147
|
+
totalStories: number;
|
|
148
|
+
/**
|
|
149
|
+
* Per-story outcome map.
|
|
150
|
+
* Key = story key passed to `run()`; value = outcome detail.
|
|
151
|
+
* Added in story 43-10 so the CLI composition root can map results to the
|
|
152
|
+
* linear orchestrator's `{ stories: Record<string, { phase: string }> }` shape.
|
|
153
|
+
*/
|
|
154
|
+
stories: Record<string, GraphStoryOutcome>;
|
|
155
|
+
}
|
|
156
|
+
/** Multi-story graph orchestrator interface (story 43-7). */
|
|
157
|
+
export interface GraphOrchestrator {
|
|
158
|
+
run(storyKeys: string[]): Promise<GraphRunSummary>;
|
|
159
|
+
}
|
|
160
|
+
/** Thrown by `createGraphOrchestrator` when the supplied graph is structurally invalid. */
|
|
161
|
+
export declare class GraphOrchestratorInitError extends Error {
|
|
162
|
+
constructor(message: string);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Creates a `GraphOrchestrator` that runs one graph executor instance per
|
|
166
|
+
* concurrent story slot, with conflict-group serialization and bounded concurrency.
|
|
167
|
+
*
|
|
168
|
+
* When `config.eventBus` is provided, a per-story SDLC event bridge is created
|
|
169
|
+
* to translate factory `graph:*` events into `orchestrator:story-*` events (AC4,
|
|
170
|
+
* story 43-10).
|
|
171
|
+
*
|
|
172
|
+
* @throws {GraphOrchestratorInitError} if `config.graph` is missing `nodes` or `edges`.
|
|
173
|
+
*/
|
|
174
|
+
export declare function createGraphOrchestrator(config: GraphOrchestratorConfig): GraphOrchestrator;
|
|
175
|
+
/**
|
|
176
|
+
* Duck-typed graph interface for config patching.
|
|
177
|
+
* Structurally compatible with `@substrate-ai/factory`'s `Graph` (Map-based nodes)
|
|
178
|
+
* without requiring a direct import (ADR-003 compliant).
|
|
179
|
+
*/
|
|
180
|
+
interface PatchableGraph {
|
|
181
|
+
nodes: {
|
|
182
|
+
get(id: string): {
|
|
183
|
+
maxRetries?: number;
|
|
184
|
+
} | undefined;
|
|
185
|
+
};
|
|
186
|
+
defaultMaxRetries?: number;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Options accepted by `applyConfigToGraph`.
|
|
190
|
+
*/
|
|
191
|
+
export interface ApplyConfigOptions {
|
|
192
|
+
maxReviewCycles: number;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Patches the loaded SDLC pipeline graph to reflect runtime configuration.
|
|
196
|
+
*
|
|
197
|
+
* Currently maps `maxReviewCycles` → `dev_story.maxRetries` (1:1 mapping).
|
|
198
|
+
* Both values represent the number of *additional* retry attempts (not total).
|
|
199
|
+
*
|
|
200
|
+
* Must be called after parseGraph() and before any story graph instance runs.
|
|
201
|
+
*
|
|
202
|
+
* @param graph A factory Graph (Map-based nodes) duck-typed as PatchableGraph.
|
|
203
|
+
* @param options Runtime configuration to apply.
|
|
204
|
+
* @throws {Error} if the graph does not contain a `dev_story` node.
|
|
205
|
+
*/
|
|
206
|
+
export declare function applyConfigToGraph(graph: PatchableGraph, options: ApplyConfigOptions): void;
|
|
207
|
+
export {};
|
|
208
|
+
//# sourceMappingURL=graph-orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graph-orchestrator.d.ts","sourceRoot":"","sources":["../../src/orchestrator/graph-orchestrator.ts"],"names":[],"mappings":"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"}
|