@telora/daemon 0.19.74 → 0.19.82
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/build-info.json +5 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +23 -0
- package/dist/config.js.map +1 -1
- package/dist/focus-executor.d.ts.map +1 -1
- package/dist/focus-executor.js +40 -5
- package/dist/focus-executor.js.map +1 -1
- package/dist/focus-merge.js +3 -3
- package/dist/focus-merge.js.map +1 -1
- package/dist/focus-prompt-builder.d.ts.map +1 -1
- package/dist/focus-prompt-builder.js +4 -1
- package/dist/focus-prompt-builder.js.map +1 -1
- package/dist/prompt-contradictions.d.ts +55 -0
- package/dist/prompt-contradictions.d.ts.map +1 -0
- package/dist/prompt-contradictions.js +114 -0
- package/dist/prompt-contradictions.js.map +1 -0
- package/dist/prompt-listing.d.ts +19 -0
- package/dist/prompt-listing.d.ts.map +1 -1
- package/dist/prompt-listing.js +49 -0
- package/dist/prompt-listing.js.map +1 -1
- package/dist/prompt-sections/execution-sections.d.ts +3 -2
- package/dist/prompt-sections/execution-sections.d.ts.map +1 -1
- package/dist/prompt-sections/execution-sections.js +70 -97
- package/dist/prompt-sections/execution-sections.js.map +1 -1
- package/dist/prompt-sections/role-sections.js +2 -2
- package/dist/prompt-sections/role-sections.js.map +1 -1
- package/dist/queries/context-assembly.d.ts +14 -4
- package/dist/queries/context-assembly.d.ts.map +1 -1
- package/dist/queries/context-assembly.js +14 -4
- package/dist/queries/context-assembly.js.map +1 -1
- package/dist/queries/deliveries.d.ts +30 -0
- package/dist/queries/deliveries.d.ts.map +1 -1
- package/dist/queries/deliveries.js.map +1 -1
- package/dist/queries/focuses.d.ts +0 -7
- package/dist/queries/focuses.d.ts.map +1 -1
- package/dist/queries/focuses.js +0 -9
- package/dist/queries/focuses.js.map +1 -1
- package/dist/queries/index.d.ts +1 -1
- package/dist/queries/index.d.ts.map +1 -1
- package/dist/queries/index.js +1 -1
- package/dist/queries/index.js.map +1 -1
- package/dist/resolvers/escalation-answers.d.ts +40 -0
- package/dist/resolvers/escalation-answers.d.ts.map +1 -1
- package/dist/resolvers/escalation-answers.js +54 -35
- package/dist/resolvers/escalation-answers.js.map +1 -1
- package/dist/resolvers/shared/wiki.d.ts +27 -0
- package/dist/resolvers/shared/wiki.d.ts.map +1 -1
- package/dist/resolvers/shared/wiki.js +39 -0
- package/dist/resolvers/shared/wiki.js.map +1 -1
- package/dist/spawn/delivered-manifest.d.ts +42 -0
- package/dist/spawn/delivered-manifest.d.ts.map +1 -0
- package/dist/spawn/delivered-manifest.js +64 -0
- package/dist/spawn/delivered-manifest.js.map +1 -0
- package/dist/spawn/process-spawn.d.ts +9 -0
- package/dist/spawn/process-spawn.d.ts.map +1 -1
- package/dist/spawn/process-spawn.js +8 -1
- package/dist/spawn/process-spawn.js.map +1 -1
- package/dist/spawn/prompt-assembly.d.ts +28 -1
- package/dist/spawn/prompt-assembly.d.ts.map +1 -1
- package/dist/spawn/prompt-assembly.js +16 -7
- package/dist/spawn/prompt-assembly.js.map +1 -1
- package/dist/spawn/shared.d.ts +27 -3
- package/dist/spawn/shared.d.ts.map +1 -1
- package/dist/spawn/spawn-decision.d.ts +50 -0
- package/dist/spawn/spawn-decision.d.ts.map +1 -1
- package/dist/spawn/spawn-decision.js +114 -38
- package/dist/spawn/spawn-decision.js.map +1 -1
- package/dist/spawner/lifecycle.js +3 -3
- package/dist/spawner/lifecycle.js.map +1 -1
- package/dist/spawner/resolution.js +3 -3
- package/dist/spawner/resolution.js.map +1 -1
- package/dist/types/config.d.ts +44 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/verification-baseline.d.ts +112 -0
- package/dist/verification-baseline.d.ts.map +1 -0
- package/dist/verification-baseline.js +264 -0
- package/dist/verification-baseline.js.map +1 -0
- package/dist/verification-config.d.ts +53 -0
- package/dist/verification-config.d.ts.map +1 -0
- package/dist/verification-config.js +72 -0
- package/dist/verification-config.js.map +1 -0
- package/dist/verification-default-on.d.ts +87 -0
- package/dist/verification-default-on.d.ts.map +1 -0
- package/dist/verification-default-on.js +186 -0
- package/dist/verification-default-on.js.map +1 -0
- package/dist/verification-deterministic.d.ts +56 -0
- package/dist/verification-deterministic.d.ts.map +1 -0
- package/dist/verification-deterministic.js +123 -0
- package/dist/verification-deterministic.js.map +1 -0
- package/dist/verification-engine.d.ts +22 -15
- package/dist/verification-engine.d.ts.map +1 -1
- package/dist/verification-engine.js +79 -65
- package/dist/verification-engine.js.map +1 -1
- package/dist/verification-failure-parser.d.ts +48 -0
- package/dist/verification-failure-parser.d.ts.map +1 -0
- package/dist/verification-failure-parser.js +102 -0
- package/dist/verification-failure-parser.js.map +1 -0
- package/dist/verification-feedback.d.ts +58 -0
- package/dist/verification-feedback.d.ts.map +1 -0
- package/dist/verification-feedback.js +110 -0
- package/dist/verification-feedback.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Baseline-diff attribution keyed by the focus-base SHA.
|
|
3
|
+
*
|
|
4
|
+
* Replaces per-delivery LLM failure attribution with an exact mechanical diff:
|
|
5
|
+
* run the verification command ONCE against the focus base (the merge-base of
|
|
6
|
+
* the focus branch and integration), cache the parsed failing-test set per
|
|
7
|
+
* (product, base SHA), then classify each delivery-HEAD failure as NEW (in HEAD
|
|
8
|
+
* not baseline -> gates) or PRE-EXISTING (in both -> recorded, non-blocking).
|
|
9
|
+
* The differential gate then measures only the delta the focus introduced.
|
|
10
|
+
*
|
|
11
|
+
* Correctness note: the HEAD run must execute in the FOCUS WORKTREE (HEAD of the
|
|
12
|
+
* focus branch), and the baseline in a detached worktree at the merge-base --
|
|
13
|
+
* otherwise the two sides are not comparable. verification-engine resolves the
|
|
14
|
+
* focus-worktree cwd for the HEAD run; this module owns the base side.
|
|
15
|
+
*
|
|
16
|
+
* @module verification-baseline
|
|
17
|
+
*/
|
|
18
|
+
import { spawn } from 'node:child_process';
|
|
19
|
+
import { mkdirSync, readFileSync, writeFileSync, existsSync, rmSync } from 'node:fs';
|
|
20
|
+
import { resolve } from 'node:path';
|
|
21
|
+
import { resolveGlobalStateDir } from './daemon-process.js';
|
|
22
|
+
import { parseFailingTests } from './verification-failure-parser.js';
|
|
23
|
+
import { runGitSync } from './git.js';
|
|
24
|
+
import { configForProduct } from './config.js';
|
|
25
|
+
import { getFocusWorktree } from './focus-worktree-state.js';
|
|
26
|
+
/** Default timeout for a baseline run when the verification config sets none: 30 min. */
|
|
27
|
+
const DEFAULT_BASELINE_TIMEOUT_MS = 30 * 60 * 1000;
|
|
28
|
+
/**
|
|
29
|
+
* Partition a HEAD failing-test set against the baseline failing-test set. Pure.
|
|
30
|
+
* Sorted for stable output / comparison.
|
|
31
|
+
*/
|
|
32
|
+
export function classifyFailures(headFailing, baselineFailing) {
|
|
33
|
+
const newFailures = [];
|
|
34
|
+
const preExisting = [];
|
|
35
|
+
for (const id of headFailing) {
|
|
36
|
+
if (baselineFailing.has(id))
|
|
37
|
+
preExisting.push(id);
|
|
38
|
+
else
|
|
39
|
+
newFailures.push(id);
|
|
40
|
+
}
|
|
41
|
+
return { newFailures: newFailures.sort(), preExisting: preExisting.sort() };
|
|
42
|
+
}
|
|
43
|
+
// ---------------------------------------------------------------------------
|
|
44
|
+
// SHA-keyed baseline cache (under the global state dir)
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
function baselineCacheDir() {
|
|
47
|
+
return resolve(resolveGlobalStateDir(), 'verification-baseline');
|
|
48
|
+
}
|
|
49
|
+
/** Cache file path for a (product, base SHA). Exported for tests. */
|
|
50
|
+
export function baselineCachePath(productId, baseSha) {
|
|
51
|
+
// Sanitize: productId is a uuid and baseSha a hex sha, both filename-safe, but
|
|
52
|
+
// guard against separators defensively.
|
|
53
|
+
const safe = `${productId}-${baseSha}`.replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
54
|
+
return resolve(baselineCacheDir(), `${safe}.json`);
|
|
55
|
+
}
|
|
56
|
+
/** Read the cached baseline failing-test set, or null on miss / unreadable. */
|
|
57
|
+
export function readBaselineCache(productId, baseSha) {
|
|
58
|
+
const path = baselineCachePath(productId, baseSha);
|
|
59
|
+
if (!existsSync(path))
|
|
60
|
+
return null;
|
|
61
|
+
try {
|
|
62
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
63
|
+
if (!Array.isArray(parsed.failingTests))
|
|
64
|
+
return null;
|
|
65
|
+
return parsed.failingTests.filter((t) => typeof t === 'string');
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** Write the baseline failing-test set for a (product, base SHA). Best-effort. */
|
|
72
|
+
export function writeBaselineCache(productId, baseSha, failingTests) {
|
|
73
|
+
try {
|
|
74
|
+
mkdirSync(baselineCacheDir(), { recursive: true });
|
|
75
|
+
writeFileSync(baselineCachePath(productId, baseSha), JSON.stringify({ productId, baseSha, failingTests }, null, 2), { mode: 0o600 });
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.warn(`[verification] failed to write baseline cache for ${productId}@${baseSha.slice(0, 8)}:`, err.message);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Resolve the baseline failing-test set for a (product, base SHA): a cache hit
|
|
83
|
+
* short-circuits (an unchanged SHA never re-runs the suite); a miss runs the
|
|
84
|
+
* baseline once, parses, and caches.
|
|
85
|
+
*/
|
|
86
|
+
export async function getBaselineFailingSet(productId, baseSha, deps) {
|
|
87
|
+
const cached = deps.readCache(productId, baseSha);
|
|
88
|
+
if (cached)
|
|
89
|
+
return new Set(cached);
|
|
90
|
+
const output = await deps.runBaseline(baseSha);
|
|
91
|
+
const failing = [...parseFailingTests(output)];
|
|
92
|
+
deps.writeCache(productId, baseSha, failing);
|
|
93
|
+
return new Set(failing);
|
|
94
|
+
}
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
// git + shell helpers for the default baseline runner
|
|
97
|
+
// ---------------------------------------------------------------------------
|
|
98
|
+
/** Resolve the focus base = merge-base(integrationBranch, HEAD) in a worktree. Null on failure. */
|
|
99
|
+
export function resolveFocusBaseSha(worktreePath, integrationBranch) {
|
|
100
|
+
const result = runGitSync(['merge-base', integrationBranch, 'HEAD'], worktreePath);
|
|
101
|
+
if (!result.success || result.output.trim().length === 0)
|
|
102
|
+
return null;
|
|
103
|
+
return result.output.trim();
|
|
104
|
+
}
|
|
105
|
+
/** Spawn `sh -c command` in cwd and capture the FULL combined stdout+stderr. */
|
|
106
|
+
function runShellCapture(command, cwd, timeoutMs) {
|
|
107
|
+
return new Promise((resolvePromise) => {
|
|
108
|
+
const child = spawn('sh', ['-c', command], { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
109
|
+
let out = '';
|
|
110
|
+
child.stdout?.on('data', (c) => { out += c.toString('utf8'); });
|
|
111
|
+
child.stderr?.on('data', (c) => { out += c.toString('utf8'); });
|
|
112
|
+
const timer = setTimeout(() => { try {
|
|
113
|
+
child.kill('SIGKILL');
|
|
114
|
+
}
|
|
115
|
+
catch { /* ignore */ } }, timeoutMs);
|
|
116
|
+
child.on('error', () => { clearTimeout(timer); resolvePromise(out); });
|
|
117
|
+
child.on('close', () => { clearTimeout(timer); resolvePromise(out); });
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Default baseline runner: create a detached worktree at the base SHA off the
|
|
122
|
+
* product's main repo, run the command there, capture output, and remove the
|
|
123
|
+
* worktree. Best-effort -- on any git failure returns '' (no baseline -> the
|
|
124
|
+
* caller treats all HEAD failures as new, i.e. the pre-attribution gate).
|
|
125
|
+
*/
|
|
126
|
+
export function buildDefaultRunBaseline(config, productId, command, timeoutMs) {
|
|
127
|
+
return async (baseSha) => {
|
|
128
|
+
const product = config.products.find(p => p.id === productId);
|
|
129
|
+
const repoPath = product ? configForProduct(config, product).repoPath : config.repoPath;
|
|
130
|
+
const wtDir = resolve(resolveGlobalStateDir(), 'verification-baseline-wt');
|
|
131
|
+
const wtPath = resolve(wtDir, `${productId}-${baseSha.slice(0, 12)}`.replace(/[^a-zA-Z0-9._-]/g, '_'));
|
|
132
|
+
try {
|
|
133
|
+
mkdirSync(wtDir, { recursive: true });
|
|
134
|
+
runGitSync(['worktree', 'prune'], repoPath);
|
|
135
|
+
if (existsSync(wtPath)) {
|
|
136
|
+
runGitSync(['worktree', 'remove', '--force', wtPath], repoPath);
|
|
137
|
+
rmSync(wtPath, { recursive: true, force: true });
|
|
138
|
+
}
|
|
139
|
+
const add = runGitSync(['worktree', 'add', '--detach', wtPath, baseSha], repoPath);
|
|
140
|
+
if (!add.success) {
|
|
141
|
+
console.warn(`[verification] baseline worktree add failed at ${baseSha.slice(0, 8)}: ${add.error}`);
|
|
142
|
+
return '';
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
console.warn(`[verification] baseline worktree setup failed:`, err.message);
|
|
147
|
+
return '';
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
return await runShellCapture(command, wtPath, timeoutMs);
|
|
151
|
+
}
|
|
152
|
+
finally {
|
|
153
|
+
try {
|
|
154
|
+
runGitSync(['worktree', 'remove', '--force', wtPath], repoPath);
|
|
155
|
+
rmSync(wtPath, { recursive: true, force: true });
|
|
156
|
+
runGitSync(['worktree', 'prune'], repoPath);
|
|
157
|
+
}
|
|
158
|
+
catch { /* best-effort cleanup */ }
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Classify a failed HEAD run against the focus base. Returns null when no
|
|
164
|
+
* baseline could be resolved (no worktree / no merge-base) -- the caller then
|
|
165
|
+
* treats all HEAD failures as new (fail-closed toward gating, the behavior
|
|
166
|
+
* before attribution existed).
|
|
167
|
+
*/
|
|
168
|
+
export async function attributeFailures(v, result, deps) {
|
|
169
|
+
const worktreePath = deps.resolveWorktreePath(v);
|
|
170
|
+
if (!worktreePath)
|
|
171
|
+
return null;
|
|
172
|
+
const baseSha = resolveFocusBaseSha(worktreePath, deps.integrationBranch);
|
|
173
|
+
if (!baseSha || !v.productId)
|
|
174
|
+
return null;
|
|
175
|
+
const headFailing = parseFailingTests(deps.readHeadOutput(result));
|
|
176
|
+
const baselineFailing = await deps.getBaselineFailingSet(v.productId, baseSha);
|
|
177
|
+
return classifyFailures(headFailing, baselineFailing);
|
|
178
|
+
}
|
|
179
|
+
/** Default HEAD-output reader: full log file when present, else the tails. */
|
|
180
|
+
export function readHeadOutputDefault(result) {
|
|
181
|
+
if (result.logPath && existsSync(result.logPath)) {
|
|
182
|
+
try {
|
|
183
|
+
return readFileSync(result.logPath, 'utf8');
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
// fall through to tails
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return `${result.stdoutTail ?? ''}\n${result.stderrTail ?? ''}`;
|
|
190
|
+
}
|
|
191
|
+
// ---------------------------------------------------------------------------
|
|
192
|
+
// Default wiring consumed by verification-engine (kept here to keep that file
|
|
193
|
+
// under the daemon 800-line limit).
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
/**
|
|
196
|
+
* Build the default `attributeFailures` closure: reads the focus-worktree cwd,
|
|
197
|
+
* resolves the merge-base, runs (or reuses a cached) baseline at that SHA in a
|
|
198
|
+
* detached worktree, and classifies HEAD failures against it. Returns null when
|
|
199
|
+
* no baseline is resolvable (caller gates all failures).
|
|
200
|
+
*/
|
|
201
|
+
export function buildDefaultAttributeFailures(config) {
|
|
202
|
+
return (v, result) => {
|
|
203
|
+
const cfg = v.verificationConfig ?? {};
|
|
204
|
+
const command = typeof cfg.command === 'string' ? cfg.command : '';
|
|
205
|
+
const timeoutMs = typeof cfg.timeoutMs === 'number' && cfg.timeoutMs > 0
|
|
206
|
+
? cfg.timeoutMs
|
|
207
|
+
: DEFAULT_BASELINE_TIMEOUT_MS;
|
|
208
|
+
const runBaseline = buildDefaultRunBaseline(config, v.productId ?? config.productId, command, timeoutMs);
|
|
209
|
+
return attributeFailures(v, result, {
|
|
210
|
+
resolveWorktreePath: (pv) => (pv.focusId ? getFocusWorktree(pv.focusId)?.worktreePath ?? null : null),
|
|
211
|
+
integrationBranch: config.integrationBranch,
|
|
212
|
+
getBaselineFailingSet: (productId, baseSha) => getBaselineFailingSet(productId, baseSha, {
|
|
213
|
+
readCache: readBaselineCache,
|
|
214
|
+
writeCache: writeBaselineCache,
|
|
215
|
+
runBaseline,
|
|
216
|
+
}),
|
|
217
|
+
readHeadOutput: readHeadOutputDefault,
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Build the default `resolveVerificationCwd`: the focus worktree (HEAD of the
|
|
223
|
+
* focus branch) so the deterministic run measures the focus's changes, falling
|
|
224
|
+
* back to the product repo path when no focus worktree exists.
|
|
225
|
+
*/
|
|
226
|
+
export function buildResolveVerificationCwd(resolveCwd) {
|
|
227
|
+
return (v) => {
|
|
228
|
+
if (v.focusId) {
|
|
229
|
+
const wt = getFocusWorktree(v.focusId);
|
|
230
|
+
if (wt?.worktreePath)
|
|
231
|
+
return wt.worktreePath;
|
|
232
|
+
}
|
|
233
|
+
return resolveCwd(v.productId);
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Decide the attributed outcome for a failed deterministic run: all-pre-existing
|
|
238
|
+
* demotes to 'passed' (the focus introduced no regression); any new failure keeps
|
|
239
|
+
* it 'failed'. Pure -- exported for testing.
|
|
240
|
+
*/
|
|
241
|
+
export function applyAttribution(deliveryId, classification) {
|
|
242
|
+
const { newFailures, preExisting } = classification;
|
|
243
|
+
if (newFailures.length === 0) {
|
|
244
|
+
return {
|
|
245
|
+
outcome: 'passed',
|
|
246
|
+
rationale: `deterministic check exited non-zero but all ${preExisting.length} failure(s) ` +
|
|
247
|
+
`pre-exist on the focus base -- no new regression (differential pass)`,
|
|
248
|
+
newFailures,
|
|
249
|
+
preExisting,
|
|
250
|
+
log: preExisting.length > 0
|
|
251
|
+
? `[verification] delivery ${deliveryId}: ${preExisting.length} pre-existing base failure(s) recorded, non-blocking (differential pass)`
|
|
252
|
+
: null,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
outcome: 'failed',
|
|
257
|
+
rationale: `deterministic check failed: ${newFailures.length} NEW failure(s) vs focus base` +
|
|
258
|
+
(preExisting.length > 0 ? `, ${preExisting.length} pre-existing (recorded, non-blocking)` : ''),
|
|
259
|
+
newFailures,
|
|
260
|
+
preExisting,
|
|
261
|
+
log: null,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=verification-baseline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-baseline.js","sourceRoot":"","sources":["../src/verification-baseline.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the default-on deterministic verification config.
|
|
3
|
+
*
|
|
4
|
+
* The deterministic verification method used to be opt-in (a delivery only ran
|
|
5
|
+
* a check when it carried an explicit verification_method). This module makes
|
|
6
|
+
* it the DEFAULT for every delivery entering verify, using a config-default
|
|
7
|
+
* command run daemon-side at the coding->verify edge.
|
|
8
|
+
*
|
|
9
|
+
* Resolution precedence (env > file > typed default), mirroring how
|
|
10
|
+
* resolveTelemetryConfig / resolveLacunaConfig work in the daemon:
|
|
11
|
+
* - command: TELORA_DEFAULT_VERIFY_COMMAND > config.defaultVerification.command > '' (disabled)
|
|
12
|
+
* - timeoutMs: TELORA_DEFAULT_VERIFY_TIMEOUT_MS > config.defaultVerification.timeoutMs > 30 min
|
|
13
|
+
* - maxConcurrent:TELORA_DEFAULT_VERIFY_MAX_CONCURRENT > config.defaultVerification.maxConcurrent > 1
|
|
14
|
+
*
|
|
15
|
+
* The env knobs are read directly from `process.env` here rather than through
|
|
16
|
+
* daemon-core's env-config Zod index: daemon-core is a registry-installed
|
|
17
|
+
* dependency (not a workspace symlink), so an env-config edit there would not
|
|
18
|
+
* take effect at runtime for this daemon. Reading process.env directly is the
|
|
19
|
+
* same pattern buildEngineRuntimeConfig uses for telemetry/lacuna.
|
|
20
|
+
*
|
|
21
|
+
* @module verification-config
|
|
22
|
+
*/
|
|
23
|
+
import type { DaemonConfig } from './types.js';
|
|
24
|
+
/** Default timeout for the default-on deterministic run: 30 min (full build+test sweep). */
|
|
25
|
+
export declare const DEFAULT_VERIFY_TIMEOUT_MS: number;
|
|
26
|
+
/** Default max concurrent daemon-side verification runs. */
|
|
27
|
+
export declare const DEFAULT_VERIFY_MAX_CONCURRENT = 1;
|
|
28
|
+
/** Env var names for the default-on verification knobs. */
|
|
29
|
+
export declare const VERIFY_ENV: {
|
|
30
|
+
readonly COMMAND: "TELORA_DEFAULT_VERIFY_COMMAND";
|
|
31
|
+
readonly TIMEOUT_MS: "TELORA_DEFAULT_VERIFY_TIMEOUT_MS";
|
|
32
|
+
readonly MAX_CONCURRENT: "TELORA_DEFAULT_VERIFY_MAX_CONCURRENT";
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Fully-resolved default-on verification settings. `enabled` is a convenience
|
|
36
|
+
* flag: true iff a non-empty command is configured (the default-on path only
|
|
37
|
+
* runs for deliveries with no explicit method WHEN enabled).
|
|
38
|
+
*/
|
|
39
|
+
export interface ResolvedDefaultVerification {
|
|
40
|
+
command: string;
|
|
41
|
+
timeoutMs: number;
|
|
42
|
+
maxConcurrent: number;
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Resolve the default-on verification config from env > file(config) > default.
|
|
47
|
+
*
|
|
48
|
+
* Pure w.r.t. its inputs (env is injectable for tests). Never throws: an
|
|
49
|
+
* invalid numeric env value degrades to the next precedence source rather than
|
|
50
|
+
* failing the tick.
|
|
51
|
+
*/
|
|
52
|
+
export declare function resolveDefaultVerification(config: Pick<DaemonConfig, 'defaultVerification'>, env?: NodeJS.ProcessEnv): ResolvedDefaultVerification;
|
|
53
|
+
//# sourceMappingURL=verification-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-config.d.ts","sourceRoot":"","sources":["../src/verification-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C,4FAA4F;AAC5F,eAAO,MAAM,yBAAyB,QAAiB,CAAC;AAExD,4DAA4D;AAC5D,eAAO,MAAM,6BAA6B,IAAI,CAAC;AAE/C,2DAA2D;AAC3D,eAAO,MAAM,UAAU;;;;CAIb,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CAClB;AAcD;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,qBAAqB,CAAC,EACjD,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,2BAA2B,CAyB7B"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the default-on deterministic verification config.
|
|
3
|
+
*
|
|
4
|
+
* The deterministic verification method used to be opt-in (a delivery only ran
|
|
5
|
+
* a check when it carried an explicit verification_method). This module makes
|
|
6
|
+
* it the DEFAULT for every delivery entering verify, using a config-default
|
|
7
|
+
* command run daemon-side at the coding->verify edge.
|
|
8
|
+
*
|
|
9
|
+
* Resolution precedence (env > file > typed default), mirroring how
|
|
10
|
+
* resolveTelemetryConfig / resolveLacunaConfig work in the daemon:
|
|
11
|
+
* - command: TELORA_DEFAULT_VERIFY_COMMAND > config.defaultVerification.command > '' (disabled)
|
|
12
|
+
* - timeoutMs: TELORA_DEFAULT_VERIFY_TIMEOUT_MS > config.defaultVerification.timeoutMs > 30 min
|
|
13
|
+
* - maxConcurrent:TELORA_DEFAULT_VERIFY_MAX_CONCURRENT > config.defaultVerification.maxConcurrent > 1
|
|
14
|
+
*
|
|
15
|
+
* The env knobs are read directly from `process.env` here rather than through
|
|
16
|
+
* daemon-core's env-config Zod index: daemon-core is a registry-installed
|
|
17
|
+
* dependency (not a workspace symlink), so an env-config edit there would not
|
|
18
|
+
* take effect at runtime for this daemon. Reading process.env directly is the
|
|
19
|
+
* same pattern buildEngineRuntimeConfig uses for telemetry/lacuna.
|
|
20
|
+
*
|
|
21
|
+
* @module verification-config
|
|
22
|
+
*/
|
|
23
|
+
/** Default timeout for the default-on deterministic run: 30 min (full build+test sweep). */
|
|
24
|
+
export const DEFAULT_VERIFY_TIMEOUT_MS = 30 * 60 * 1000;
|
|
25
|
+
/** Default max concurrent daemon-side verification runs. */
|
|
26
|
+
export const DEFAULT_VERIFY_MAX_CONCURRENT = 1;
|
|
27
|
+
/** Env var names for the default-on verification knobs. */
|
|
28
|
+
export const VERIFY_ENV = {
|
|
29
|
+
COMMAND: 'TELORA_DEFAULT_VERIFY_COMMAND',
|
|
30
|
+
TIMEOUT_MS: 'TELORA_DEFAULT_VERIFY_TIMEOUT_MS',
|
|
31
|
+
MAX_CONCURRENT: 'TELORA_DEFAULT_VERIFY_MAX_CONCURRENT',
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Parse a positive integer from an env string. Returns undefined for an unset,
|
|
35
|
+
* empty, non-numeric, or non-positive value so the caller falls through to the
|
|
36
|
+
* next precedence source (never NaN, never a silently-wrong 0).
|
|
37
|
+
*/
|
|
38
|
+
function positiveIntEnv(raw) {
|
|
39
|
+
if (raw === undefined || raw.trim() === '')
|
|
40
|
+
return undefined;
|
|
41
|
+
const n = Number(raw);
|
|
42
|
+
if (!Number.isFinite(n) || !Number.isInteger(n) || n <= 0)
|
|
43
|
+
return undefined;
|
|
44
|
+
return n;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Resolve the default-on verification config from env > file(config) > default.
|
|
48
|
+
*
|
|
49
|
+
* Pure w.r.t. its inputs (env is injectable for tests). Never throws: an
|
|
50
|
+
* invalid numeric env value degrades to the next precedence source rather than
|
|
51
|
+
* failing the tick.
|
|
52
|
+
*/
|
|
53
|
+
export function resolveDefaultVerification(config, env = process.env) {
|
|
54
|
+
const file = config.defaultVerification;
|
|
55
|
+
const envCommand = env[VERIFY_ENV.COMMAND];
|
|
56
|
+
const command = envCommand !== undefined && envCommand.trim() !== ''
|
|
57
|
+
? envCommand
|
|
58
|
+
: (typeof file?.command === 'string' ? file.command : '');
|
|
59
|
+
const timeoutMs = positiveIntEnv(env[VERIFY_ENV.TIMEOUT_MS])
|
|
60
|
+
?? (typeof file?.timeoutMs === 'number' && file.timeoutMs > 0 ? file.timeoutMs : undefined)
|
|
61
|
+
?? DEFAULT_VERIFY_TIMEOUT_MS;
|
|
62
|
+
const maxConcurrent = positiveIntEnv(env[VERIFY_ENV.MAX_CONCURRENT])
|
|
63
|
+
?? (typeof file?.maxConcurrent === 'number' && file.maxConcurrent > 0 ? file.maxConcurrent : undefined)
|
|
64
|
+
?? DEFAULT_VERIFY_MAX_CONCURRENT;
|
|
65
|
+
return {
|
|
66
|
+
command,
|
|
67
|
+
timeoutMs,
|
|
68
|
+
maxConcurrent,
|
|
69
|
+
enabled: command.trim().length > 0,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=verification-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-config.js","sourceRoot":"","sources":["../src/verification-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,4FAA4F;AAC5F,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAExD,4DAA4D;AAC5D,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAE/C,2DAA2D;AAC3D,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,OAAO,EAAE,+BAA+B;IACxC,UAAU,EAAE,kCAAkC;IAC9C,cAAc,EAAE,sCAAsC;CAC9C,CAAC;AAcX;;;;GAIG;AACH,SAAS,cAAc,CAAC,GAAuB;IAC7C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IAC7D,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5E,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAAiD,EACjD,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,IAAI,GAAG,MAAM,CAAC,mBAAmB,CAAC;IAExC,MAAM,UAAU,GAAG,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,OAAO,GACX,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE;QAClD,CAAC,CAAC,UAAU;QACZ,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAE9D,MAAM,SAAS,GACb,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;WACvC,CAAC,OAAO,IAAI,EAAE,SAAS,KAAK,QAAQ,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;WACxF,yBAAyB,CAAC;IAE/B,MAAM,aAAa,GACjB,cAAc,CAAC,GAAG,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;WAC3C,CAAC,OAAO,IAAI,EAAE,aAAa,KAAK,QAAQ,IAAI,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;WACpG,6BAA6B,CAAC;IAEnC,OAAO;QACL,OAAO;QACP,SAAS;QACT,aAAa;QACb,OAAO,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;KACnC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default-on deterministic verification: selection + concurrency cap.
|
|
3
|
+
*
|
|
4
|
+
* The deterministic verification method used to be opt-in (a delivery only ran
|
|
5
|
+
* a check when it carried an explicit verification_method). This module makes
|
|
6
|
+
* it the DEFAULT for every delivery entering verify: it discovers verify-status
|
|
7
|
+
* deliveries with no explicit method and synthesizes a `deterministic`
|
|
8
|
+
* PendingVerification carrying the config-default command, and it caps
|
|
9
|
+
* concurrent daemon-side runs so a burst cannot spawn N whole-repo suites.
|
|
10
|
+
*
|
|
11
|
+
* Extracted from verification-engine.ts to keep that file under the daemon
|
|
12
|
+
* 800-line limit. The dispatch (runVerificationForDelivery / runVerificationTick)
|
|
13
|
+
* stays in verification-engine.ts and imports from here.
|
|
14
|
+
*
|
|
15
|
+
* @module verification-default-on
|
|
16
|
+
*/
|
|
17
|
+
import type { DaemonConfig } from './types.js';
|
|
18
|
+
import type { PendingVerification } from './queries/verification.js';
|
|
19
|
+
import type { ResolvedDefaultVerification } from './verification-config.js';
|
|
20
|
+
import type { getActiveFocuses, getFocusDeliveries } from './supabase.js';
|
|
21
|
+
/**
|
|
22
|
+
* The subset of verification dependencies the default-on scan needs. Kept as a
|
|
23
|
+
* narrow structural type (rather than importing the full VerificationDeps) so
|
|
24
|
+
* there is no runtime import cycle with verification-engine.ts.
|
|
25
|
+
*/
|
|
26
|
+
export interface DefaultOnScanDeps {
|
|
27
|
+
getActiveFocuses: typeof getActiveFocuses;
|
|
28
|
+
getFocusDeliveries: typeof getFocusDeliveries;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Counting semaphore capping concurrent daemon-side verification runs.
|
|
32
|
+
*
|
|
33
|
+
* A default-on deterministic run is a full build+test sweep (minutes), while
|
|
34
|
+
* the verification loop ticks every 60s and `safeInterval` has NO re-entry
|
|
35
|
+
* guard -- so without a cap, overlapping ticks (and multiple products in one
|
|
36
|
+
* tick) could spawn N whole-repo suites at once and thrash the host. The
|
|
37
|
+
* module-level singleton below is shared across every tick invocation, so the
|
|
38
|
+
* cap holds across overlapping ticks, not just within one.
|
|
39
|
+
*
|
|
40
|
+
* A dedicated semaphore (rather than the shared ResourceGovernor) because the
|
|
41
|
+
* governor's per-engine slots model agent-team spawns and are wired through
|
|
42
|
+
* the governor-construction path; runVerificationTick is invoked with only
|
|
43
|
+
* `config` and has no governor handle. The cap value comes from
|
|
44
|
+
* resolveDefaultVerification (maxConcurrent).
|
|
45
|
+
*/
|
|
46
|
+
export declare class VerificationSemaphore {
|
|
47
|
+
private permits;
|
|
48
|
+
private limit;
|
|
49
|
+
private readonly waiters;
|
|
50
|
+
constructor(limit: number);
|
|
51
|
+
/** Adjust the cap (config change between ticks). Only frees waiters on a raise. */
|
|
52
|
+
setLimit(limit: number): void;
|
|
53
|
+
acquire(): Promise<void>;
|
|
54
|
+
release(): void;
|
|
55
|
+
/** Test-only: how many permits are currently available. */
|
|
56
|
+
availablePermits(): number;
|
|
57
|
+
}
|
|
58
|
+
/** Shared cap across all tick invocations. Sized from config at each tick. */
|
|
59
|
+
export declare const verificationSemaphore: VerificationSemaphore;
|
|
60
|
+
/** Test-only: inspect the concurrency semaphore. */
|
|
61
|
+
export declare function __getVerificationSemaphoreForTests(): {
|
|
62
|
+
availablePermits(): number;
|
|
63
|
+
setLimit(n: number): void;
|
|
64
|
+
};
|
|
65
|
+
/** Test-only: reset the default-on re-run guard. */
|
|
66
|
+
export declare function __resetDefaultOnGuardForTests(): void;
|
|
67
|
+
/** Test-only: snapshot of the default-on re-run guard. */
|
|
68
|
+
export declare function __getDefaultOnGuardForTests(): ReadonlySet<string>;
|
|
69
|
+
/** Mark a delivery as already run this verify-entry (dispatch-time bookkeeping). */
|
|
70
|
+
export declare function markDefaultOnRan(deliveryId: string): void;
|
|
71
|
+
/** Test-only alias for markDefaultOnRan. */
|
|
72
|
+
export declare function __markDefaultOnRanForTests(deliveryId: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* Discover deliveries that should receive a DEFAULT-ON deterministic run: in
|
|
75
|
+
* `verify` status, anchored to an injection, with no explicit verification
|
|
76
|
+
* method (so not already returned by getPendingVerifications), not in a
|
|
77
|
+
* read-only audit focus (those are discovery-only and never run a suite), and
|
|
78
|
+
* not already run this verify-entry (steady-state guard).
|
|
79
|
+
*
|
|
80
|
+
* Synthesizes a `deterministic` PendingVerification carrying the resolved
|
|
81
|
+
* config-default command + timeout. Returns [] when the default-on path is
|
|
82
|
+
* disabled (no command configured) so the feature is inert until opted in.
|
|
83
|
+
*
|
|
84
|
+
* `config` must be product-scoped (config.productId identifies the product).
|
|
85
|
+
*/
|
|
86
|
+
export declare function collectDefaultOnVerifications(config: DaemonConfig, resolved: ResolvedDefaultVerification, explicitDeliveryIds: ReadonlySet<string>, deps: DefaultOnScanDeps): Promise<PendingVerification[]>;
|
|
87
|
+
//# sourceMappingURL=verification-default-on.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-default-on.d.ts","sourceRoot":"","sources":["../src/verification-default-on.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAC5E,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAE1E;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,OAAO,gBAAgB,CAAC;IAC1C,kBAAkB,EAAE,OAAO,kBAAkB,CAAC;CAC/C;AAMD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;gBAErC,KAAK,EAAE,MAAM;IAKzB,mFAAmF;IACnF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAavB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ9B,OAAO,IAAI,IAAI;IASf,2DAA2D;IAC3D,gBAAgB,IAAI,MAAM;CAG3B;AAED,8EAA8E;AAC9E,eAAO,MAAM,qBAAqB,uBAA+B,CAAC;AAElE,oDAAoD;AACpD,wBAAgB,kCAAkC,IAAI;IAAE,gBAAgB,IAAI,MAAM,CAAC;IAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAE9G;AAmBD,oDAAoD;AACpD,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD;AAED,0DAA0D;AAC1D,wBAAgB,2BAA2B,IAAI,WAAW,CAAC,MAAM,CAAC,CAEjE;AAED,oFAAoF;AACpF,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEzD;AAED,4CAA4C;AAC5C,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAEnE;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAsB,6BAA6B,CACjD,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,2BAA2B,EACrC,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,EACxC,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAuDhC"}
|