@substrate-ai/sdlc 0.20.4 → 0.20.5
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/verification/checks/index.d.ts +4 -1
- package/dist/verification/checks/index.d.ts.map +1 -1
- package/dist/verification/checks/index.js +3 -1
- package/dist/verification/checks/index.js.map +1 -1
- package/dist/verification/checks/runtime-probe-check.d.ts +43 -0
- package/dist/verification/checks/runtime-probe-check.d.ts.map +1 -0
- package/dist/verification/checks/runtime-probe-check.js +152 -0
- package/dist/verification/checks/runtime-probe-check.js.map +1 -0
- package/dist/verification/index.d.ts +4 -0
- package/dist/verification/index.d.ts.map +1 -1
- package/dist/verification/index.js +3 -0
- package/dist/verification/index.js.map +1 -1
- package/dist/verification/probes/executor.d.ts +39 -0
- package/dist/verification/probes/executor.d.ts.map +1 -0
- package/dist/verification/probes/executor.js +109 -0
- package/dist/verification/probes/executor.js.map +1 -0
- package/dist/verification/probes/index.d.ts +14 -0
- package/dist/verification/probes/index.d.ts.map +1 -0
- package/dist/verification/probes/index.js +12 -0
- package/dist/verification/probes/index.js.map +1 -0
- package/dist/verification/probes/parser.d.ts +26 -0
- package/dist/verification/probes/parser.d.ts.map +1 -0
- package/dist/verification/probes/parser.js +134 -0
- package/dist/verification/probes/parser.js.map +1 -0
- package/dist/verification/probes/types.d.ts +122 -0
- package/dist/verification/probes/types.d.ts.map +1 -0
- package/dist/verification/probes/types.js +68 -0
- package/dist/verification/probes/types.js.map +1 -0
- package/dist/verification/verification-pipeline.d.ts +3 -1
- package/dist/verification/verification-pipeline.d.ts.map +1 -1
- package/dist/verification/verification-pipeline.js +20 -2
- package/dist/verification/verification-pipeline.js.map +1 -1
- package/package.json +6 -3
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
* Barrel export for VerificationCheck implementations.
|
|
3
3
|
*
|
|
4
4
|
* Check registration order (Tier A before Tier B, and within Tier A in
|
|
5
|
-
* pipeline sequence order
|
|
5
|
+
* pipeline sequence order):
|
|
6
6
|
* 1. PhantomReviewCheck — story 51-2
|
|
7
7
|
* 2. TrivialOutputCheck — story 51-3
|
|
8
8
|
* 3. AcceptanceCriteriaEvidenceCheck
|
|
9
9
|
* 4. BuildCheck — story 51-4
|
|
10
|
+
* 5. RuntimeProbeCheck — Epic 55 Phase 2
|
|
10
11
|
*/
|
|
11
12
|
export { PhantomReviewCheck } from './phantom-review-check.js';
|
|
12
13
|
export { TrivialOutputCheck, DEFAULT_TRIVIAL_OUTPUT_THRESHOLD } from './trivial-output-check.js';
|
|
13
14
|
export { AcceptanceCriteriaEvidenceCheck, extractAcceptanceCriteriaIds } from './acceptance-criteria-evidence-check.js';
|
|
14
15
|
export { BuildCheck, BUILD_CHECK_TIMEOUT_MS, detectBuildCommand } from './build-check.js';
|
|
16
|
+
export { RuntimeProbeCheck } from './runtime-probe-check.js';
|
|
17
|
+
export type { RuntimeProbeExecutors } from './runtime-probe-check.js';
|
|
15
18
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/verification/checks/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/verification/checks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAA;AAChG,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAA;AACvH,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,YAAY,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAA"}
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
* Barrel export for VerificationCheck implementations.
|
|
3
3
|
*
|
|
4
4
|
* Check registration order (Tier A before Tier B, and within Tier A in
|
|
5
|
-
* pipeline sequence order
|
|
5
|
+
* pipeline sequence order):
|
|
6
6
|
* 1. PhantomReviewCheck — story 51-2
|
|
7
7
|
* 2. TrivialOutputCheck — story 51-3
|
|
8
8
|
* 3. AcceptanceCriteriaEvidenceCheck
|
|
9
9
|
* 4. BuildCheck — story 51-4
|
|
10
|
+
* 5. RuntimeProbeCheck — Epic 55 Phase 2
|
|
10
11
|
*/
|
|
11
12
|
export { PhantomReviewCheck } from './phantom-review-check.js';
|
|
12
13
|
export { TrivialOutputCheck, DEFAULT_TRIVIAL_OUTPUT_THRESHOLD } from './trivial-output-check.js';
|
|
13
14
|
export { AcceptanceCriteriaEvidenceCheck, extractAcceptanceCriteriaIds } from './acceptance-criteria-evidence-check.js';
|
|
14
15
|
export { BuildCheck, BUILD_CHECK_TIMEOUT_MS, detectBuildCommand } from './build-check.js';
|
|
16
|
+
export { RuntimeProbeCheck } from './runtime-probe-check.js';
|
|
15
17
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/verification/checks/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/verification/checks/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,2BAA2B,CAAA;AAChG,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAA;AACvH,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACzF,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuntimeProbeCheck — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Tier A verification check that parses and executes the author-declared
|
|
5
|
+
* runtime probes in a story's `## Runtime Probes` section. Each probe's
|
|
6
|
+
* outcome becomes a structured VerificationFinding, leveraging the
|
|
7
|
+
* Phase 1 persistence surface to flow through retry prompts, the run
|
|
8
|
+
* manifest, and post-run analysis without string-parsing.
|
|
9
|
+
*
|
|
10
|
+
* Architecture / scoring contract:
|
|
11
|
+
*
|
|
12
|
+
* - No probes declared → pass (skip note finding array is empty)
|
|
13
|
+
* - Probes declared, YAML invalid → fail (one finding per parse error)
|
|
14
|
+
* - Probe `sandbox: twin` → warn (deferred until Phase 3)
|
|
15
|
+
* - Probe `sandbox: host`, exit 0 → pass; no finding emitted for that probe
|
|
16
|
+
* - Probe `sandbox: host`, exit ≠ 0 → fail (exit code + stdout/stderr tails)
|
|
17
|
+
* - Probe `sandbox: host`, timed out → fail (runtime-probe-timeout category)
|
|
18
|
+
* - No storyContent on context → warn (cannot verify without story text)
|
|
19
|
+
*
|
|
20
|
+
* Registered last in the canonical Tier A pipeline, after BuildCheck,
|
|
21
|
+
* because probes may depend on a successful build's output.
|
|
22
|
+
*/
|
|
23
|
+
import type { VerificationCheck, VerificationContext, VerificationResult } from '../types.js';
|
|
24
|
+
import { type ProbeResult, type RuntimeProbe } from '../probes/index.js';
|
|
25
|
+
/**
|
|
26
|
+
* Per-sandbox executors, injected via constructor so tests (and future
|
|
27
|
+
* twin integration in Phase 3) can swap implementations without touching
|
|
28
|
+
* the check's dispatch logic.
|
|
29
|
+
*/
|
|
30
|
+
export interface RuntimeProbeExecutors {
|
|
31
|
+
host: (probe: RuntimeProbe) => Promise<ProbeResult>;
|
|
32
|
+
/** Twin execution is deferred; the default returns undefined so the check
|
|
33
|
+
* emits a `probe-deferred` warn finding. Phase 3 replaces this. */
|
|
34
|
+
twin?: (probe: RuntimeProbe) => Promise<ProbeResult> | undefined;
|
|
35
|
+
}
|
|
36
|
+
export declare class RuntimeProbeCheck implements VerificationCheck {
|
|
37
|
+
readonly name = "runtime-probes";
|
|
38
|
+
readonly tier: "A";
|
|
39
|
+
private readonly _executors;
|
|
40
|
+
constructor(executors?: Partial<RuntimeProbeExecutors>);
|
|
41
|
+
run(context: VerificationContext): Promise<VerificationResult>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=runtime-probe-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-probe-check.d.ts","sourceRoot":"","sources":["../../../src/verification/checks/runtime-probe-check.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EAEnB,kBAAkB,EACnB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAA;AAgB3B;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,CAAA;IACnD;wEACoE;IACpE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,WAAW,CAAC,GAAG,SAAS,CAAA;CACjE;AAWD,qBAAa,iBAAkB,YAAW,iBAAiB;IACzD,QAAQ,CAAC,IAAI,oBAAmB;IAChC,QAAQ,CAAC,IAAI,EAAG,GAAG,CAAS;IAE5B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuB;gBAEtC,SAAS,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC;IAOhD,GAAG,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAmHrE"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuntimeProbeCheck — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Tier A verification check that parses and executes the author-declared
|
|
5
|
+
* runtime probes in a story's `## Runtime Probes` section. Each probe's
|
|
6
|
+
* outcome becomes a structured VerificationFinding, leveraging the
|
|
7
|
+
* Phase 1 persistence surface to flow through retry prompts, the run
|
|
8
|
+
* manifest, and post-run analysis without string-parsing.
|
|
9
|
+
*
|
|
10
|
+
* Architecture / scoring contract:
|
|
11
|
+
*
|
|
12
|
+
* - No probes declared → pass (skip note finding array is empty)
|
|
13
|
+
* - Probes declared, YAML invalid → fail (one finding per parse error)
|
|
14
|
+
* - Probe `sandbox: twin` → warn (deferred until Phase 3)
|
|
15
|
+
* - Probe `sandbox: host`, exit 0 → pass; no finding emitted for that probe
|
|
16
|
+
* - Probe `sandbox: host`, exit ≠ 0 → fail (exit code + stdout/stderr tails)
|
|
17
|
+
* - Probe `sandbox: host`, timed out → fail (runtime-probe-timeout category)
|
|
18
|
+
* - No storyContent on context → warn (cannot verify without story text)
|
|
19
|
+
*
|
|
20
|
+
* Registered last in the canonical Tier A pipeline, after BuildCheck,
|
|
21
|
+
* because probes may depend on a successful build's output.
|
|
22
|
+
*/
|
|
23
|
+
import { renderFindings } from '../findings.js';
|
|
24
|
+
import { parseRuntimeProbes, executeProbeOnHost, } from '../probes/index.js';
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Finding categories
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
const CATEGORY_PARSE = 'runtime-probe-parse-error';
|
|
29
|
+
const CATEGORY_SKIP = 'runtime-probe-skip';
|
|
30
|
+
const CATEGORY_DEFERRED = 'runtime-probe-deferred';
|
|
31
|
+
const CATEGORY_FAIL = 'runtime-probe-fail';
|
|
32
|
+
const CATEGORY_TIMEOUT = 'runtime-probe-timeout';
|
|
33
|
+
const defaultExecutors = {
|
|
34
|
+
host: (probe) => executeProbeOnHost(probe, { cwd: process.cwd() }),
|
|
35
|
+
// twin intentionally omitted → RuntimeProbeCheck emits a warn finding
|
|
36
|
+
};
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
// RuntimeProbeCheck
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
export class RuntimeProbeCheck {
|
|
41
|
+
name = 'runtime-probes';
|
|
42
|
+
tier = 'A';
|
|
43
|
+
_executors;
|
|
44
|
+
constructor(executors) {
|
|
45
|
+
this._executors = {
|
|
46
|
+
...defaultExecutors,
|
|
47
|
+
...(executors ?? {}),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
async run(context) {
|
|
51
|
+
const start = Date.now();
|
|
52
|
+
// Story content is required to locate the `## Runtime Probes` section.
|
|
53
|
+
// Absence is treated as a warn so reviewers know the check could not
|
|
54
|
+
// make a decision, distinct from "present but no probes declared".
|
|
55
|
+
if (context.storyContent === undefined) {
|
|
56
|
+
const findings = [
|
|
57
|
+
{
|
|
58
|
+
category: CATEGORY_SKIP,
|
|
59
|
+
severity: 'warn',
|
|
60
|
+
message: 'story content unavailable — skipping runtime probe check',
|
|
61
|
+
},
|
|
62
|
+
];
|
|
63
|
+
return {
|
|
64
|
+
status: 'warn',
|
|
65
|
+
details: renderFindings(findings),
|
|
66
|
+
duration_ms: Date.now() - start,
|
|
67
|
+
findings,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const parsed = parseRuntimeProbes(context.storyContent);
|
|
71
|
+
if (parsed.kind === 'absent') {
|
|
72
|
+
return {
|
|
73
|
+
status: 'pass',
|
|
74
|
+
details: 'runtime-probes: no ## Runtime Probes section declared — skipping',
|
|
75
|
+
duration_ms: Date.now() - start,
|
|
76
|
+
findings: [],
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (parsed.kind === 'invalid') {
|
|
80
|
+
const findings = [
|
|
81
|
+
{
|
|
82
|
+
category: CATEGORY_PARSE,
|
|
83
|
+
severity: 'error',
|
|
84
|
+
message: parsed.error,
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
return {
|
|
88
|
+
status: 'fail',
|
|
89
|
+
details: renderFindings(findings),
|
|
90
|
+
duration_ms: Date.now() - start,
|
|
91
|
+
findings,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// kind === 'parsed'. Empty list is a valid author-declared state
|
|
95
|
+
// (e.g. they declared the section but intentionally zero probes yet);
|
|
96
|
+
// treat identically to `absent` for the verdict.
|
|
97
|
+
if (parsed.probes.length === 0) {
|
|
98
|
+
return {
|
|
99
|
+
status: 'pass',
|
|
100
|
+
details: 'runtime-probes: 0 probes declared — skipping',
|
|
101
|
+
duration_ms: Date.now() - start,
|
|
102
|
+
findings: [],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const findings = [];
|
|
106
|
+
for (const probe of parsed.probes) {
|
|
107
|
+
if (probe.sandbox === 'twin') {
|
|
108
|
+
findings.push({
|
|
109
|
+
category: CATEGORY_DEFERRED,
|
|
110
|
+
severity: 'warn',
|
|
111
|
+
message: `probe "${probe.name}" uses sandbox=twin which is deferred until ` +
|
|
112
|
+
`Phase 3 (Digital Twin integration); skipping`,
|
|
113
|
+
});
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
// sandbox === 'host'
|
|
117
|
+
const result = await this._executors.host(probe);
|
|
118
|
+
if (result.outcome === 'pass') {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const category = result.outcome === 'timeout' ? CATEGORY_TIMEOUT : CATEGORY_FAIL;
|
|
122
|
+
const descriptor = probe.description ? ` (${probe.description})` : '';
|
|
123
|
+
const message = result.outcome === 'timeout'
|
|
124
|
+
? `probe "${probe.name}"${descriptor} timed out after ${result.durationMs}ms`
|
|
125
|
+
: `probe "${probe.name}"${descriptor} failed with exit ${result.exitCode ?? 'unknown'}`;
|
|
126
|
+
findings.push({
|
|
127
|
+
category,
|
|
128
|
+
severity: 'error',
|
|
129
|
+
message,
|
|
130
|
+
command: result.command,
|
|
131
|
+
...(result.exitCode !== undefined ? { exitCode: result.exitCode } : {}),
|
|
132
|
+
stdoutTail: result.stdoutTail,
|
|
133
|
+
stderrTail: result.stderrTail,
|
|
134
|
+
durationMs: result.durationMs,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const status = findings.some((f) => f.severity === 'error')
|
|
138
|
+
? 'fail'
|
|
139
|
+
: findings.some((f) => f.severity === 'warn')
|
|
140
|
+
? 'warn'
|
|
141
|
+
: 'pass';
|
|
142
|
+
return {
|
|
143
|
+
status,
|
|
144
|
+
details: findings.length > 0
|
|
145
|
+
? renderFindings(findings)
|
|
146
|
+
: `runtime-probes: ${parsed.probes.length} probe(s) passed`,
|
|
147
|
+
duration_ms: Date.now() - start,
|
|
148
|
+
findings,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=runtime-probe-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime-probe-check.js","sourceRoot":"","sources":["../../../src/verification/checks/runtime-probe-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
export { VerificationPipeline, createDefaultVerificationPipeline } from './verification-pipeline.js';
|
|
8
8
|
export type { VerificationCheck, VerificationContext, VerificationResult, VerificationCheckResult, VerificationSummary, ReviewSignals, DevStorySignals, VerificationFinding, VerificationFindingSeverity, } from './types.js';
|
|
9
9
|
export { renderFindings } from './findings.js';
|
|
10
|
+
export { RuntimeProbeCheck } from './checks/runtime-probe-check.js';
|
|
11
|
+
export type { RuntimeProbeExecutors } from './checks/runtime-probe-check.js';
|
|
12
|
+
export { DEFAULT_PROBE_TIMEOUT_MS, PROBE_TAIL_BYTES, RuntimeProbeListSchema, RuntimeProbeSandboxSchema, RuntimeProbeSchema, parseRuntimeProbes, executeProbeOnHost, } from './probes/index.js';
|
|
13
|
+
export type { HostExecuteOptions, ProbeResult, RuntimeProbe, RuntimeProbeParseResult, RuntimeProbeSandbox, } from './probes/index.js';
|
|
10
14
|
export { PhantomReviewCheck } from './checks/index.js';
|
|
11
15
|
export { TrivialOutputCheck, DEFAULT_TRIVIAL_OUTPUT_THRESHOLD } from './checks/index.js';
|
|
12
16
|
export { AcceptanceCriteriaEvidenceCheck, extractAcceptanceCriteriaIds } from './checks/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AACpG,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AACpG,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,2BAA2B,GAC5B,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAG9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAA;AACxF,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
export { VerificationPipeline, createDefaultVerificationPipeline } from './verification-pipeline.js';
|
|
8
8
|
export { renderFindings } from './findings.js';
|
|
9
|
+
// Epic 55 Phase 2 — Runtime probe support.
|
|
10
|
+
export { RuntimeProbeCheck } from './checks/runtime-probe-check.js';
|
|
11
|
+
export { DEFAULT_PROBE_TIMEOUT_MS, PROBE_TAIL_BYTES, RuntimeProbeListSchema, RuntimeProbeSandboxSchema, RuntimeProbeSchema, parseRuntimeProbes, executeProbeOnHost, } from './probes/index.js';
|
|
9
12
|
// Concrete check implementations (story 51-2+)
|
|
10
13
|
export { PhantomReviewCheck } from './checks/index.js';
|
|
11
14
|
export { TrivialOutputCheck, DEFAULT_TRIVIAL_OUTPUT_THRESHOLD } from './checks/index.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AAYpG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/verification/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,oBAAoB,EAAE,iCAAiC,EAAE,MAAM,4BAA4B,CAAA;AAYpG,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAE9C,2CAA2C;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAEnE,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,mBAAmB,CAAA;AAQ1B,+CAA+C;AAC/C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,gCAAgC,EAAE,MAAM,mBAAmB,CAAA;AACxF,OAAO,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAA;AACjG,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-sandbox probe executor — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Runs one runtime probe directly on the operator machine via a detached
|
|
5
|
+
* shell process, with stream-separated capture and a hard timeout that
|
|
6
|
+
* terminates the entire process group. Same safety posture as BuildCheck —
|
|
7
|
+
* specifically the detached-process-group + SIGKILL-on-timeout pattern —
|
|
8
|
+
* so probe execution cannot orphan long-running descendants.
|
|
9
|
+
*
|
|
10
|
+
* Twin-sandbox execution is **deferred to Phase 3** (Digital Twin
|
|
11
|
+
* integration). RuntimeProbeCheck handles the `sandbox: twin` case itself
|
|
12
|
+
* without routing through this module.
|
|
13
|
+
*/
|
|
14
|
+
import { type ProbeResult, type RuntimeProbe } from './types.js';
|
|
15
|
+
/** Options for host execution. Injected primarily to make tests deterministic. */
|
|
16
|
+
export interface HostExecuteOptions {
|
|
17
|
+
/** Working directory for the spawned shell. Defaults to process.cwd(). */
|
|
18
|
+
cwd?: string;
|
|
19
|
+
/** Environment override. Defaults to the parent process's env. */
|
|
20
|
+
env?: NodeJS.ProcessEnv;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Execute one probe on the host and return a structured ProbeResult.
|
|
24
|
+
*
|
|
25
|
+
* Behavior notes:
|
|
26
|
+
* - The shell used is `/bin/sh -c '<probe.command>'` inside a detached
|
|
27
|
+
* process group (so the entire tree is killed on timeout).
|
|
28
|
+
* - stdout and stderr are captured independently; each is returned
|
|
29
|
+
* tailed to PROBE_TAIL_BYTES (≤ 4 KiB) so published tarballs of the
|
|
30
|
+
* run manifest stay small.
|
|
31
|
+
* - Timeout defaults to `probe.timeout_ms ?? DEFAULT_PROBE_TIMEOUT_MS`
|
|
32
|
+
* (60 s). When the timeout fires, the process group is SIGKILL'd and
|
|
33
|
+
* the returned result has `outcome: 'timeout'`, `exitCode` undefined.
|
|
34
|
+
* - Never throws. Spawn errors (e.g. exec format error) are returned as
|
|
35
|
+
* `outcome: 'fail'` with exitCode -1 and the error message captured on
|
|
36
|
+
* stderrTail, so the caller can emit a deterministic finding.
|
|
37
|
+
*/
|
|
38
|
+
export declare function executeProbeOnHost(probe: RuntimeProbe, options?: HostExecuteOptions): Promise<ProbeResult>;
|
|
39
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/verification/probes/executor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,YAAY,CAAA;AAenB,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC,0EAA0E;IAC1E,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;CACxB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,WAAW,CAAC,CA0EtB"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-sandbox probe executor — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Runs one runtime probe directly on the operator machine via a detached
|
|
5
|
+
* shell process, with stream-separated capture and a hard timeout that
|
|
6
|
+
* terminates the entire process group. Same safety posture as BuildCheck —
|
|
7
|
+
* specifically the detached-process-group + SIGKILL-on-timeout pattern —
|
|
8
|
+
* so probe execution cannot orphan long-running descendants.
|
|
9
|
+
*
|
|
10
|
+
* Twin-sandbox execution is **deferred to Phase 3** (Digital Twin
|
|
11
|
+
* integration). RuntimeProbeCheck handles the `sandbox: twin` case itself
|
|
12
|
+
* without routing through this module.
|
|
13
|
+
*/
|
|
14
|
+
import { spawn } from 'node:child_process';
|
|
15
|
+
import { DEFAULT_PROBE_TIMEOUT_MS, PROBE_TAIL_BYTES, } from './types.js';
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Helpers
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
/** Return the last N bytes of a UTF-8 string (sliced by length for simplicity). */
|
|
20
|
+
function tail(text, bytes = PROBE_TAIL_BYTES) {
|
|
21
|
+
return text.length <= bytes ? text : text.slice(text.length - bytes);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Execute one probe on the host and return a structured ProbeResult.
|
|
25
|
+
*
|
|
26
|
+
* Behavior notes:
|
|
27
|
+
* - The shell used is `/bin/sh -c '<probe.command>'` inside a detached
|
|
28
|
+
* process group (so the entire tree is killed on timeout).
|
|
29
|
+
* - stdout and stderr are captured independently; each is returned
|
|
30
|
+
* tailed to PROBE_TAIL_BYTES (≤ 4 KiB) so published tarballs of the
|
|
31
|
+
* run manifest stay small.
|
|
32
|
+
* - Timeout defaults to `probe.timeout_ms ?? DEFAULT_PROBE_TIMEOUT_MS`
|
|
33
|
+
* (60 s). When the timeout fires, the process group is SIGKILL'd and
|
|
34
|
+
* the returned result has `outcome: 'timeout'`, `exitCode` undefined.
|
|
35
|
+
* - Never throws. Spawn errors (e.g. exec format error) are returned as
|
|
36
|
+
* `outcome: 'fail'` with exitCode -1 and the error message captured on
|
|
37
|
+
* stderrTail, so the caller can emit a deterministic finding.
|
|
38
|
+
*/
|
|
39
|
+
export function executeProbeOnHost(probe, options = {}) {
|
|
40
|
+
const timeoutMs = probe.timeout_ms ?? DEFAULT_PROBE_TIMEOUT_MS;
|
|
41
|
+
const cwd = options.cwd ?? process.cwd();
|
|
42
|
+
const env = options.env ?? process.env;
|
|
43
|
+
const start = Date.now();
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
let stdout = '';
|
|
46
|
+
let stderr = '';
|
|
47
|
+
let settled = false;
|
|
48
|
+
const child = spawn(probe.command, [], {
|
|
49
|
+
cwd,
|
|
50
|
+
env,
|
|
51
|
+
detached: true,
|
|
52
|
+
shell: true,
|
|
53
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
54
|
+
});
|
|
55
|
+
const finalize = (result) => {
|
|
56
|
+
if (settled)
|
|
57
|
+
return;
|
|
58
|
+
settled = true;
|
|
59
|
+
resolve(result);
|
|
60
|
+
};
|
|
61
|
+
child.on('error', (err) => {
|
|
62
|
+
// spawn error (ENOENT, EACCES, EMFILE, etc.) — never reach 'close'.
|
|
63
|
+
finalize({
|
|
64
|
+
outcome: 'fail',
|
|
65
|
+
command: probe.command,
|
|
66
|
+
exitCode: -1,
|
|
67
|
+
stdoutTail: tail(stdout),
|
|
68
|
+
stderrTail: tail(stderr + (stderr.length > 0 && !stderr.endsWith('\n') ? '\n' : '') + `spawn error: ${err.message}\n`),
|
|
69
|
+
durationMs: Date.now() - start,
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
child.stdout?.on('data', (chunk) => {
|
|
73
|
+
stdout += chunk.toString();
|
|
74
|
+
});
|
|
75
|
+
child.stderr?.on('data', (chunk) => {
|
|
76
|
+
stderr += chunk.toString();
|
|
77
|
+
});
|
|
78
|
+
const timeoutHandle = setTimeout(() => {
|
|
79
|
+
try {
|
|
80
|
+
if (child.pid !== undefined) {
|
|
81
|
+
process.kill(-child.pid, 'SIGKILL');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// Process already exited between timeout fire and kill call.
|
|
86
|
+
}
|
|
87
|
+
finalize({
|
|
88
|
+
outcome: 'timeout',
|
|
89
|
+
command: probe.command,
|
|
90
|
+
stdoutTail: tail(stdout),
|
|
91
|
+
stderrTail: tail(stderr),
|
|
92
|
+
durationMs: Date.now() - start,
|
|
93
|
+
});
|
|
94
|
+
}, timeoutMs);
|
|
95
|
+
child.on('close', (code) => {
|
|
96
|
+
clearTimeout(timeoutHandle);
|
|
97
|
+
const duration = Date.now() - start;
|
|
98
|
+
finalize({
|
|
99
|
+
outcome: code === 0 ? 'pass' : 'fail',
|
|
100
|
+
command: probe.command,
|
|
101
|
+
...(code !== null ? { exitCode: code } : {}),
|
|
102
|
+
stdoutTail: tail(stdout),
|
|
103
|
+
stderrTail: tail(stderr),
|
|
104
|
+
durationMs: duration,
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../../src/verification/probes/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime probe public surface — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the parser, executor, and supporting types. The actual
|
|
5
|
+
* VerificationCheck implementation lives in ../checks/runtime-probe-check.ts
|
|
6
|
+
* to keep the existing `checks/` directory as the canonical location for
|
|
7
|
+
* all VerificationCheck subclasses.
|
|
8
|
+
*/
|
|
9
|
+
export { DEFAULT_PROBE_TIMEOUT_MS, PROBE_TAIL_BYTES, RuntimeProbeListSchema, RuntimeProbeSandboxSchema, RuntimeProbeSchema, } from './types.js';
|
|
10
|
+
export type { ProbeResult, RuntimeProbe, RuntimeProbeParseResult, RuntimeProbeSandbox, } from './types.js';
|
|
11
|
+
export { parseRuntimeProbes } from './parser.js';
|
|
12
|
+
export { executeProbeOnHost } from './executor.js';
|
|
13
|
+
export type { HostExecuteOptions } from './executor.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/verification/probes/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AACnB,YAAY,EACV,WAAW,EACX,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime probe public surface — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the parser, executor, and supporting types. The actual
|
|
5
|
+
* VerificationCheck implementation lives in ../checks/runtime-probe-check.ts
|
|
6
|
+
* to keep the existing `checks/` directory as the canonical location for
|
|
7
|
+
* all VerificationCheck subclasses.
|
|
8
|
+
*/
|
|
9
|
+
export { DEFAULT_PROBE_TIMEOUT_MS, PROBE_TAIL_BYTES, RuntimeProbeListSchema, RuntimeProbeSandboxSchema, RuntimeProbeSchema, } from './types.js';
|
|
10
|
+
export { parseRuntimeProbes } from './parser.js';
|
|
11
|
+
export { executeProbeOnHost } from './executor.js';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/verification/probes/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,sBAAsB,EACtB,yBAAyB,EACzB,kBAAkB,GACnB,MAAM,YAAY,CAAA;AAQnB,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime probe parser — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Locates the `## Runtime Probes` section in a story's markdown content and
|
|
5
|
+
* extracts any probe declarations contained in a `yaml` code fence inside
|
|
6
|
+
* it. Never throws: every failure mode is returned as a RuntimeProbeParseResult
|
|
7
|
+
* variant so the VerificationCheck can emit a structured finding rather than
|
|
8
|
+
* crash the verification pipeline.
|
|
9
|
+
*/
|
|
10
|
+
import { type RuntimeProbeParseResult } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Parse the `## Runtime Probes` section of a story's markdown content.
|
|
13
|
+
*
|
|
14
|
+
* Outcomes:
|
|
15
|
+
* - section missing → { kind: 'absent' }
|
|
16
|
+
* - section present, no yaml fence → { kind: 'invalid' }
|
|
17
|
+
* - section present, yaml fence malformed → { kind: 'invalid' }
|
|
18
|
+
* - section present, yaml root is not a list → { kind: 'invalid' }
|
|
19
|
+
* - section present, entry fails RuntimeProbeSchema → { kind: 'invalid' }
|
|
20
|
+
* - section present, yaml valid, all entries valid → { kind: 'parsed' }
|
|
21
|
+
*
|
|
22
|
+
* Duplicate names within a single story are surfaced as `invalid` so that
|
|
23
|
+
* finding messages can unambiguously reference a probe by name.
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseRuntimeProbes(storyContent: string): RuntimeProbeParseResult;
|
|
26
|
+
//# sourceMappingURL=parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../src/verification/probes/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAGL,KAAK,uBAAuB,EAC7B,MAAM,YAAY,CAAA;AAmEnB;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,uBAAuB,CAsDhF"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime probe parser — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* Locates the `## Runtime Probes` section in a story's markdown content and
|
|
5
|
+
* extracts any probe declarations contained in a `yaml` code fence inside
|
|
6
|
+
* it. Never throws: every failure mode is returned as a RuntimeProbeParseResult
|
|
7
|
+
* variant so the VerificationCheck can emit a structured finding rather than
|
|
8
|
+
* crash the verification pipeline.
|
|
9
|
+
*/
|
|
10
|
+
import { load as yamlLoad, YAMLException } from 'js-yaml';
|
|
11
|
+
import { RuntimeProbeListSchema, } from './types.js';
|
|
12
|
+
// ---------------------------------------------------------------------------
|
|
13
|
+
// Section extraction
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
const SECTION_HEADING = /^##\s+Runtime\s+Probes\s*$/i;
|
|
16
|
+
/**
|
|
17
|
+
* Return the raw text of the story's `## Runtime Probes` section (excluding
|
|
18
|
+
* the heading line itself), or `undefined` if the section is not present.
|
|
19
|
+
*
|
|
20
|
+
* The section ends at the next `##` heading or end-of-file. Sub-headings
|
|
21
|
+
* (`###`, `####`) remain part of the section body.
|
|
22
|
+
*/
|
|
23
|
+
function extractRuntimeProbesSection(storyContent) {
|
|
24
|
+
const lines = storyContent.split(/\r?\n/);
|
|
25
|
+
const start = lines.findIndex((line) => SECTION_HEADING.test(line.trim()));
|
|
26
|
+
if (start === -1)
|
|
27
|
+
return undefined;
|
|
28
|
+
let end = lines.length;
|
|
29
|
+
for (let i = start + 1; i < lines.length; i += 1) {
|
|
30
|
+
if (/^##\s+\S/.test(lines[i] ?? '')) {
|
|
31
|
+
end = i;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return lines.slice(start + 1, end).join('\n');
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Extract the body of the first ```yaml (or ```yml) fenced block in the
|
|
39
|
+
* given section text. Returns `undefined` if no yaml fence is present.
|
|
40
|
+
*
|
|
41
|
+
* The opening fence is recognized case-insensitively and may carry an
|
|
42
|
+
* arbitrary trailing info string (e.g. ```yaml title=...). The closing
|
|
43
|
+
* fence is any line whose first non-whitespace run is exactly three
|
|
44
|
+
* backticks.
|
|
45
|
+
*/
|
|
46
|
+
function extractYamlFence(section) {
|
|
47
|
+
const lines = section.split(/\r?\n/);
|
|
48
|
+
let inside = false;
|
|
49
|
+
let collected;
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
if (!inside) {
|
|
52
|
+
if (/^\s*```\s*(yaml|yml)\b/i.test(line)) {
|
|
53
|
+
inside = true;
|
|
54
|
+
collected = [];
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// inside a yaml fence
|
|
59
|
+
if (/^\s*```\s*$/.test(line)) {
|
|
60
|
+
return (collected ?? []).join('\n');
|
|
61
|
+
}
|
|
62
|
+
collected?.push(line);
|
|
63
|
+
}
|
|
64
|
+
// Unterminated fence → treat as missing; the caller surfaces this as an
|
|
65
|
+
// `invalid` parse result with a clear message.
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// parseRuntimeProbes — public entry point
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
/**
|
|
72
|
+
* Parse the `## Runtime Probes` section of a story's markdown content.
|
|
73
|
+
*
|
|
74
|
+
* Outcomes:
|
|
75
|
+
* - section missing → { kind: 'absent' }
|
|
76
|
+
* - section present, no yaml fence → { kind: 'invalid' }
|
|
77
|
+
* - section present, yaml fence malformed → { kind: 'invalid' }
|
|
78
|
+
* - section present, yaml root is not a list → { kind: 'invalid' }
|
|
79
|
+
* - section present, entry fails RuntimeProbeSchema → { kind: 'invalid' }
|
|
80
|
+
* - section present, yaml valid, all entries valid → { kind: 'parsed' }
|
|
81
|
+
*
|
|
82
|
+
* Duplicate names within a single story are surfaced as `invalid` so that
|
|
83
|
+
* finding messages can unambiguously reference a probe by name.
|
|
84
|
+
*/
|
|
85
|
+
export function parseRuntimeProbes(storyContent) {
|
|
86
|
+
const section = extractRuntimeProbesSection(storyContent);
|
|
87
|
+
if (section === undefined) {
|
|
88
|
+
return { kind: 'absent' };
|
|
89
|
+
}
|
|
90
|
+
const yamlBody = extractYamlFence(section);
|
|
91
|
+
if (yamlBody === undefined) {
|
|
92
|
+
return {
|
|
93
|
+
kind: 'invalid',
|
|
94
|
+
error: '## Runtime Probes section is present but contains no terminated ```yaml fenced block',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
let parsed;
|
|
98
|
+
try {
|
|
99
|
+
parsed = yamlLoad(yamlBody) ?? [];
|
|
100
|
+
}
|
|
101
|
+
catch (err) {
|
|
102
|
+
const detail = err instanceof YAMLException ? err.message : String(err);
|
|
103
|
+
return { kind: 'invalid', error: `YAML parse error: ${detail}` };
|
|
104
|
+
}
|
|
105
|
+
if (!Array.isArray(parsed)) {
|
|
106
|
+
return {
|
|
107
|
+
kind: 'invalid',
|
|
108
|
+
error: `probe block root must be a YAML list; got ${typeof parsed}`,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const validation = RuntimeProbeListSchema.safeParse(parsed);
|
|
112
|
+
if (!validation.success) {
|
|
113
|
+
const first = validation.error.issues[0];
|
|
114
|
+
const path = first?.path.join('.') ?? '';
|
|
115
|
+
const message = first?.message ?? 'schema validation failed';
|
|
116
|
+
return {
|
|
117
|
+
kind: 'invalid',
|
|
118
|
+
error: `probe list is malformed at ${path || '<root>'}: ${message}`,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const probes = validation.data;
|
|
122
|
+
const seen = new Set();
|
|
123
|
+
for (const probe of probes) {
|
|
124
|
+
if (seen.has(probe.name)) {
|
|
125
|
+
return {
|
|
126
|
+
kind: 'invalid',
|
|
127
|
+
error: `duplicate probe name: ${probe.name}`,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
seen.add(probe.name);
|
|
131
|
+
}
|
|
132
|
+
return { kind: 'parsed', probes };
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../src/verification/probes/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime probe types — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* A "runtime probe" is an author-declared executable command that the
|
|
5
|
+
* verification pipeline runs against a real or ephemeral target environment
|
|
6
|
+
* to answer the question "does the artifact this story produced actually
|
|
7
|
+
* work?". Runtime probes exist specifically to catch the class of bugs that
|
|
8
|
+
* static shape-gates (phantom-review, trivial-output, ac-evidence, build)
|
|
9
|
+
* cannot — runtime misconfiguration, wrong image paths, systemd semantics,
|
|
10
|
+
* credential issues, and so on.
|
|
11
|
+
*
|
|
12
|
+
* This file defines the data shape; parsing lives in ./parser.ts, execution
|
|
13
|
+
* lives in ./executor.ts, and the VerificationCheck implementation lives in
|
|
14
|
+
* ../checks/runtime-probe-check.ts.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
/**
|
|
18
|
+
* Execution sandbox for a runtime probe.
|
|
19
|
+
*
|
|
20
|
+
* - `host`: probe runs directly on the operator's machine. Explicit opt-in.
|
|
21
|
+
* Cheapest; most dangerous. Authors choosing `host` acknowledge the probe
|
|
22
|
+
* may touch host state (ports, systemd units, filesystem) and take
|
|
23
|
+
* responsibility for cleanup.
|
|
24
|
+
* - `twin`: probe runs inside an ephemeral sandbox brokered by the Digital
|
|
25
|
+
* Twin subsystem (Epic 47). Twin integration is **deferred to Phase 3** —
|
|
26
|
+
* probes with `sandbox: twin` currently emit a `probe-deferred` warn
|
|
27
|
+
* finding rather than executing. Authors can declare twin-scoped probes
|
|
28
|
+
* today and they will execute transparently once Phase 3 lands.
|
|
29
|
+
*/
|
|
30
|
+
export declare const RuntimeProbeSandboxSchema: z.ZodEnum<{
|
|
31
|
+
host: "host";
|
|
32
|
+
twin: "twin";
|
|
33
|
+
}>;
|
|
34
|
+
export type RuntimeProbeSandbox = z.infer<typeof RuntimeProbeSandboxSchema>;
|
|
35
|
+
/**
|
|
36
|
+
* Default per-probe timeout in milliseconds. Matches the existing
|
|
37
|
+
* BuildCheck ceiling (60 s) — deliberate, so probe timeouts are bounded
|
|
38
|
+
* by the same policy the pipeline already uses for long-running checks.
|
|
39
|
+
*/
|
|
40
|
+
export declare const DEFAULT_PROBE_TIMEOUT_MS = 60000;
|
|
41
|
+
/** Hard upper bound on per-probe stdout/stderr retention (≤ 4 KiB — the
|
|
42
|
+
* same convention as VerificationFinding.{stdoutTail,stderrTail}). */
|
|
43
|
+
export declare const PROBE_TAIL_BYTES: number;
|
|
44
|
+
/**
|
|
45
|
+
* Zod schema for one runtime probe declared in a story's
|
|
46
|
+
* `## Runtime Probes` section.
|
|
47
|
+
*
|
|
48
|
+
* Required fields (`name`, `sandbox`, `command`) force authors to make
|
|
49
|
+
* intent explicit — no silent defaults that could mask a miswritten probe.
|
|
50
|
+
* Optional fields cover operational knobs with sensible fallbacks.
|
|
51
|
+
*/
|
|
52
|
+
export declare const RuntimeProbeSchema: z.ZodObject<{
|
|
53
|
+
name: z.ZodString;
|
|
54
|
+
sandbox: z.ZodEnum<{
|
|
55
|
+
host: "host";
|
|
56
|
+
twin: "twin";
|
|
57
|
+
}>;
|
|
58
|
+
command: z.ZodString;
|
|
59
|
+
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
60
|
+
description: z.ZodOptional<z.ZodString>;
|
|
61
|
+
}, z.core.$strip>;
|
|
62
|
+
export type RuntimeProbe = z.infer<typeof RuntimeProbeSchema>;
|
|
63
|
+
/** Zod schema for the full list (wrapping the per-probe schema). */
|
|
64
|
+
export declare const RuntimeProbeListSchema: z.ZodArray<z.ZodObject<{
|
|
65
|
+
name: z.ZodString;
|
|
66
|
+
sandbox: z.ZodEnum<{
|
|
67
|
+
host: "host";
|
|
68
|
+
twin: "twin";
|
|
69
|
+
}>;
|
|
70
|
+
command: z.ZodString;
|
|
71
|
+
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
72
|
+
description: z.ZodOptional<z.ZodString>;
|
|
73
|
+
}, z.core.$strip>>;
|
|
74
|
+
/**
|
|
75
|
+
* Result of parsing the `## Runtime Probes` section from story markdown.
|
|
76
|
+
*
|
|
77
|
+
* Parsing never throws — instead it returns one of three variants so the
|
|
78
|
+
* VerificationCheck can distinguish and emit appropriate findings:
|
|
79
|
+
*
|
|
80
|
+
* - `absent`: section missing entirely. Treat as "no probes declared" →
|
|
81
|
+
* check emits pass with skip note. Backward compat for every
|
|
82
|
+
* story authored before Phase 2.
|
|
83
|
+
* - `parsed`: section present, YAML valid, all entries match
|
|
84
|
+
* RuntimeProbeSchema. `probes` is the parsed array (may be
|
|
85
|
+
* empty if the YAML list was intentionally `[]`).
|
|
86
|
+
* - `invalid`: section present but YAML is malformed, the root value is
|
|
87
|
+
* not a list, or at least one entry fails schema validation.
|
|
88
|
+
* The check surfaces `invalid` as a fail finding with the
|
|
89
|
+
* original parse error so authors see the exact problem.
|
|
90
|
+
*/
|
|
91
|
+
export type RuntimeProbeParseResult = {
|
|
92
|
+
kind: 'absent';
|
|
93
|
+
} | {
|
|
94
|
+
kind: 'parsed';
|
|
95
|
+
probes: RuntimeProbe[];
|
|
96
|
+
} | {
|
|
97
|
+
kind: 'invalid';
|
|
98
|
+
error: string;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Outcome of one probe execution.
|
|
102
|
+
*
|
|
103
|
+
* Mirrors the optional `{command, exitCode, stdoutTail, stderrTail,
|
|
104
|
+
* durationMs}` surface on VerificationFinding so the RuntimeProbeCheck can
|
|
105
|
+
* lift ProbeResult fields into a finding with minimal translation.
|
|
106
|
+
*
|
|
107
|
+
* `outcome` disambiguates the three terminal states the check cares about:
|
|
108
|
+
*
|
|
109
|
+
* - `pass`: command exited 0 within its timeout.
|
|
110
|
+
* - `fail`: command exited non-zero within its timeout.
|
|
111
|
+
* - `timeout`: probe exceeded its timeout and was killed. `exitCode` is
|
|
112
|
+
* undefined (the process never reported one).
|
|
113
|
+
*/
|
|
114
|
+
export interface ProbeResult {
|
|
115
|
+
outcome: 'pass' | 'fail' | 'timeout';
|
|
116
|
+
command: string;
|
|
117
|
+
exitCode?: number;
|
|
118
|
+
stdoutTail: string;
|
|
119
|
+
stderrTail: string;
|
|
120
|
+
durationMs: number;
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/verification/probes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAMvB;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB;;;EAA2B,CAAA;AACjE,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAM3E;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,QAAS,CAAA;AAE9C;uEACuE;AACvE,eAAO,MAAM,gBAAgB,QAAW,CAAA;AAExC;;;;;;;GAOG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;iBAW7B,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAA;AAE7D,oEAAoE;AACpE,eAAO,MAAM,sBAAsB;;;;;;;;;kBAA8B,CAAA;AAMjE;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,uBAAuB,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,YAAY,EAAE,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAA;AAMtC;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;CACnB"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime probe types — Epic 55 / Phase 2.
|
|
3
|
+
*
|
|
4
|
+
* A "runtime probe" is an author-declared executable command that the
|
|
5
|
+
* verification pipeline runs against a real or ephemeral target environment
|
|
6
|
+
* to answer the question "does the artifact this story produced actually
|
|
7
|
+
* work?". Runtime probes exist specifically to catch the class of bugs that
|
|
8
|
+
* static shape-gates (phantom-review, trivial-output, ac-evidence, build)
|
|
9
|
+
* cannot — runtime misconfiguration, wrong image paths, systemd semantics,
|
|
10
|
+
* credential issues, and so on.
|
|
11
|
+
*
|
|
12
|
+
* This file defines the data shape; parsing lives in ./parser.ts, execution
|
|
13
|
+
* lives in ./executor.ts, and the VerificationCheck implementation lives in
|
|
14
|
+
* ../checks/runtime-probe-check.ts.
|
|
15
|
+
*/
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
// Sandbox — where the probe runs
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
/**
|
|
21
|
+
* Execution sandbox for a runtime probe.
|
|
22
|
+
*
|
|
23
|
+
* - `host`: probe runs directly on the operator's machine. Explicit opt-in.
|
|
24
|
+
* Cheapest; most dangerous. Authors choosing `host` acknowledge the probe
|
|
25
|
+
* may touch host state (ports, systemd units, filesystem) and take
|
|
26
|
+
* responsibility for cleanup.
|
|
27
|
+
* - `twin`: probe runs inside an ephemeral sandbox brokered by the Digital
|
|
28
|
+
* Twin subsystem (Epic 47). Twin integration is **deferred to Phase 3** —
|
|
29
|
+
* probes with `sandbox: twin` currently emit a `probe-deferred` warn
|
|
30
|
+
* finding rather than executing. Authors can declare twin-scoped probes
|
|
31
|
+
* today and they will execute transparently once Phase 3 lands.
|
|
32
|
+
*/
|
|
33
|
+
export const RuntimeProbeSandboxSchema = z.enum(['host', 'twin']);
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// RuntimeProbe — one author-declared probe
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
/**
|
|
38
|
+
* Default per-probe timeout in milliseconds. Matches the existing
|
|
39
|
+
* BuildCheck ceiling (60 s) — deliberate, so probe timeouts are bounded
|
|
40
|
+
* by the same policy the pipeline already uses for long-running checks.
|
|
41
|
+
*/
|
|
42
|
+
export const DEFAULT_PROBE_TIMEOUT_MS = 60_000;
|
|
43
|
+
/** Hard upper bound on per-probe stdout/stderr retention (≤ 4 KiB — the
|
|
44
|
+
* same convention as VerificationFinding.{stdoutTail,stderrTail}). */
|
|
45
|
+
export const PROBE_TAIL_BYTES = 4 * 1024;
|
|
46
|
+
/**
|
|
47
|
+
* Zod schema for one runtime probe declared in a story's
|
|
48
|
+
* `## Runtime Probes` section.
|
|
49
|
+
*
|
|
50
|
+
* Required fields (`name`, `sandbox`, `command`) force authors to make
|
|
51
|
+
* intent explicit — no silent defaults that could mask a miswritten probe.
|
|
52
|
+
* Optional fields cover operational knobs with sensible fallbacks.
|
|
53
|
+
*/
|
|
54
|
+
export const RuntimeProbeSchema = z.object({
|
|
55
|
+
/** Stable, unique-within-story identifier used in finding messages and logs. */
|
|
56
|
+
name: z.string().min(1, 'probe name is required'),
|
|
57
|
+
/** Where the probe runs. See RuntimeProbeSandboxSchema. */
|
|
58
|
+
sandbox: RuntimeProbeSandboxSchema,
|
|
59
|
+
/** Shell command line(s). Passed to a detached `sh -c` wrapper on host execution. */
|
|
60
|
+
command: z.string().min(1, 'probe command is required'),
|
|
61
|
+
/** Optional per-probe timeout in ms. Defaults to DEFAULT_PROBE_TIMEOUT_MS. */
|
|
62
|
+
timeout_ms: z.number().int().positive().optional(),
|
|
63
|
+
/** Optional human-readable description. Surfaced in finding messages. */
|
|
64
|
+
description: z.string().optional(),
|
|
65
|
+
});
|
|
66
|
+
/** Zod schema for the full list (wrapping the per-probe schema). */
|
|
67
|
+
export const RuntimeProbeListSchema = z.array(RuntimeProbeSchema);
|
|
68
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/verification/probes/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,8EAA8E;AAC9E,iCAAiC;AACjC,8EAA8E;AAE9E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;AAGjE,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAA;AAE9C;uEACuE;AACvE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAG,IAAI,CAAA;AAExC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,gFAAgF;IAChF,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;IACjD,2DAA2D;IAC3D,OAAO,EAAE,yBAAyB;IAClC,qFAAqF;IACrF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,2BAA2B,CAAC;IACvD,8EAA8E;IAC9E,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IAClD,yEAAyE;IACzE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACnC,CAAC,CAAA;AAIF,oEAAoE;AACpE,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAA"}
|
|
@@ -52,11 +52,13 @@ export declare class VerificationPipeline {
|
|
|
52
52
|
/**
|
|
53
53
|
* Create a VerificationPipeline pre-loaded with the canonical check set.
|
|
54
54
|
*
|
|
55
|
-
* Canonical Tier A check order
|
|
55
|
+
* Canonical Tier A check order:
|
|
56
56
|
* 1. PhantomReviewCheck — story 51-2 (runs first: unreviewed stories skipped)
|
|
57
57
|
* 2. TrivialOutputCheck — story 51-3
|
|
58
58
|
* 3. AcceptanceCriteriaEvidenceCheck
|
|
59
59
|
* 4. BuildCheck — story 51-4
|
|
60
|
+
* 5. RuntimeProbeCheck — Epic 55 Phase 2: runtime behavior gate; runs last
|
|
61
|
+
* in Tier A because probes may depend on built artifacts
|
|
60
62
|
*
|
|
61
63
|
* @param bus Typed event bus for verification events.
|
|
62
64
|
* @param config Optional config (used to forward threshold to TrivialOutputCheck).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification-pipeline.d.ts","sourceRoot":"","sources":["../../src/verification/verification-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EAEnB,mBAAmB,EACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAA;
|
|
1
|
+
{"version":3,"file":"verification-pipeline.d.ts","sourceRoot":"","sources":["../../src/verification/verification-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC9C,OAAO,KAAK,EACV,iBAAiB,EACjB,mBAAmB,EAEnB,mBAAmB,EACpB,MAAM,YAAY,CAAA;AAGnB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAA;AA4BhF;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAElD;;;OAGG;gBACS,GAAG,EAAE,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAE,iBAAiB,EAAO;IAO5E;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAIxC;;;;;;;;;;OAUG;IACG,GAAG,CAAC,OAAO,EAAE,mBAAmB,EAAE,IAAI,GAAE,GAAG,GAAG,GAAS,GAAG,OAAO,CAAC,mBAAmB,CAAC;CAqE7F;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iCAAiC,CAC/C,GAAG,EAAE,aAAa,CAAC,UAAU,CAAC,EAC9B,MAAM,CAAC,EAAE,wBAAwB,GAChC,oBAAoB,CAStB"}
|
|
@@ -14,6 +14,7 @@ import { PhantomReviewCheck } from './checks/phantom-review-check.js';
|
|
|
14
14
|
import { TrivialOutputCheck } from './checks/trivial-output-check.js';
|
|
15
15
|
import { AcceptanceCriteriaEvidenceCheck } from './checks/acceptance-criteria-evidence-check.js';
|
|
16
16
|
import { BuildCheck } from './checks/build-check.js';
|
|
17
|
+
import { RuntimeProbeCheck } from './checks/runtime-probe-check.js';
|
|
17
18
|
// ---------------------------------------------------------------------------
|
|
18
19
|
// Helpers
|
|
19
20
|
// ---------------------------------------------------------------------------
|
|
@@ -88,17 +89,31 @@ export class VerificationPipeline {
|
|
|
88
89
|
status: runResult.status,
|
|
89
90
|
details: runResult.details,
|
|
90
91
|
duration_ms: runResult.duration_ms,
|
|
92
|
+
// Story 55-1/55-2: preserve the structured findings array so
|
|
93
|
+
// downstream consumers (retry prompts, run manifest, post-run
|
|
94
|
+
// analysis) see each issue as its own addressable record.
|
|
95
|
+
...(runResult.findings !== undefined ? { findings: runResult.findings } : {}),
|
|
91
96
|
};
|
|
92
97
|
}
|
|
93
98
|
catch (err) {
|
|
94
99
|
const elapsed = Date.now() - checkStart;
|
|
95
100
|
const message = err instanceof Error ? err.message : String(err);
|
|
96
101
|
process.stderr.write(`[verification-pipeline] check "${check.name}" threw an unhandled exception: ${message}\n`);
|
|
102
|
+
// Synthesize a structured finding for the thrown error so the
|
|
103
|
+
// retry-prompt injector has something to render. Matches the
|
|
104
|
+
// behavior of the check-level migrations in story 55-2.
|
|
97
105
|
result = {
|
|
98
106
|
checkName: check.name,
|
|
99
107
|
status: 'warn',
|
|
100
108
|
details: message,
|
|
101
109
|
duration_ms: elapsed,
|
|
110
|
+
findings: [
|
|
111
|
+
{
|
|
112
|
+
category: 'check-exception',
|
|
113
|
+
severity: 'warn',
|
|
114
|
+
message,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
102
117
|
};
|
|
103
118
|
}
|
|
104
119
|
checkResults.push(result);
|
|
@@ -128,11 +143,13 @@ export class VerificationPipeline {
|
|
|
128
143
|
/**
|
|
129
144
|
* Create a VerificationPipeline pre-loaded with the canonical check set.
|
|
130
145
|
*
|
|
131
|
-
* Canonical Tier A check order
|
|
146
|
+
* Canonical Tier A check order:
|
|
132
147
|
* 1. PhantomReviewCheck — story 51-2 (runs first: unreviewed stories skipped)
|
|
133
148
|
* 2. TrivialOutputCheck — story 51-3
|
|
134
149
|
* 3. AcceptanceCriteriaEvidenceCheck
|
|
135
150
|
* 4. BuildCheck — story 51-4
|
|
151
|
+
* 5. RuntimeProbeCheck — Epic 55 Phase 2: runtime behavior gate; runs last
|
|
152
|
+
* in Tier A because probes may depend on built artifacts
|
|
136
153
|
*
|
|
137
154
|
* @param bus Typed event bus for verification events.
|
|
138
155
|
* @param config Optional config (used to forward threshold to TrivialOutputCheck).
|
|
@@ -142,7 +159,8 @@ export function createDefaultVerificationPipeline(bus, config) {
|
|
|
142
159
|
new PhantomReviewCheck(),
|
|
143
160
|
new TrivialOutputCheck(config),
|
|
144
161
|
new AcceptanceCriteriaEvidenceCheck(),
|
|
145
|
-
new BuildCheck(), // story 51-4: runs
|
|
162
|
+
new BuildCheck(), // story 51-4: runs late in Tier A (expensive, 60s worst-case)
|
|
163
|
+
new RuntimeProbeCheck(), // Epic 55 Phase 2: runtime behavior verification
|
|
146
164
|
];
|
|
147
165
|
return new VerificationPipeline(bus, checks);
|
|
148
166
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"verification-pipeline.js","sourceRoot":"","sources":["../../src/verification/verification-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AAErE,OAAO,EAAE,+BAA+B,EAAE,MAAM,gDAAgD,CAAA;AAChG,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"verification-pipeline.js","sourceRoot":"","sources":["../../src/verification/verification-pipeline.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@substrate-ai/sdlc",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,8 +24,11 @@
|
|
|
24
24
|
"node": ">=22.0.0"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@substrate-ai/core": "0.20.
|
|
27
|
+
"@substrate-ai/core": "0.20.5",
|
|
28
|
+
"js-yaml": "^4.1.1",
|
|
28
29
|
"zod": "^4.3.6"
|
|
29
30
|
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/js-yaml": "^4.0.9"
|
|
33
|
+
}
|
|
31
34
|
}
|