agentic-workflow-manager 9.7.0 → 9.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/src/commands/doctor.js +4 -2
- package/dist/src/commands/export.js +3 -0
- package/dist/src/commands/init.js +10 -2
- package/dist/src/commands/job/exec-wrapper.js +53 -3
- package/dist/src/commands/plan/index.js +124 -6
- package/dist/src/commands/registry/add.js +2 -2
- package/dist/src/commands/registry/index.js +7 -5
- package/dist/src/commands/registry/install-bundles.js +4 -4
- package/dist/src/commands/registry/status.js +4 -4
- package/dist/src/commands/sensors/bootstrap.js +36 -5
- package/dist/src/commands/sensors/compatibility/contract.js +19 -4
- package/dist/src/commands/sensors/compatibility/discovery.js +23 -3
- package/dist/src/commands/sensors/compatibility/live.js +18 -1
- package/dist/src/commands/sensors/compatibility/probe.js +8 -2
- package/dist/src/commands/sensors/compatibility/resolve.js +5 -2
- package/dist/src/commands/sensors/coverage/evidence.js +19 -10
- package/dist/src/commands/sensors/coverage/index.js +11 -2
- package/dist/src/commands/sensors/coverage/resolve.js +10 -0
- package/dist/src/commands/sensors/exec.js +16 -1
- package/dist/src/commands/sensors/migrate.js +62 -2
- package/dist/src/commands/sensors/prepare.js +2 -0
- package/dist/src/commands/sensors/result.js +2 -0
- package/dist/src/commands/sensors/run.js +64 -1
- package/dist/src/commands/sensors/status.js +6 -4
- package/dist/src/commands/sync.js +2 -1
- package/dist/src/commands/update.js +3 -1
- package/dist/src/commands/watch/archive-unused.js +138 -0
- package/dist/src/commands/watch/generations.js +32 -9
- package/dist/src/commands/watch/index.js +108 -2
- package/dist/src/commands/watch/init.js +149 -18
- package/dist/src/commands/watch/supervisor.js +167 -13
- package/dist/src/commands/watch/teardown-driver.js +13 -13
- package/dist/src/commands/watch/track-state.js +59 -0
- package/dist/src/commands/watch/tracks.js +38 -102
- package/dist/src/core/admission/index.js +181 -0
- package/dist/src/core/admission/registry-contracts.js +290 -0
- package/dist/src/core/bundle-install.js +2 -2
- package/dist/src/core/bundles.js +92 -19
- package/dist/src/core/diagnostics/context.js +1 -1
- package/dist/src/core/export/index.js +1 -1
- package/dist/src/core/export/resolve.js +2 -2
- package/dist/src/core/journal/fingerprint.js +35 -1
- package/dist/src/core/journal/paths.js +11 -0
- package/dist/src/core/journal/store.js +146 -4
- package/dist/src/core/journal/types.js +35 -1
- package/dist/src/core/migration/historical-provenance.js +18 -0
- package/dist/src/core/migration/index.js +322 -0
- package/dist/src/core/plan/identity.js +75 -0
- package/dist/src/core/plan/validate.js +178 -64
- package/dist/src/core/reconciliation.js +1 -1
- package/dist/src/index.js +46 -39
- package/dist/src/utils/grouping.js +1 -1
- package/dist/src/utils/registry-view.js +1 -1
- package/dist/tests/commands/bundle-diagnostics.test.js +145 -0
- package/dist/tests/commands/export.test.js +28 -2
- package/dist/tests/commands/job/exec-wrapper.test.js +16 -0
- package/dist/tests/commands/job/gate-reconcile.test.js +24 -10
- package/dist/tests/commands/multi-agent-targeting.test.js +1 -1
- package/dist/tests/commands/pin.test.js +23 -23
- package/dist/tests/commands/plan/index.test.js +630 -14
- package/dist/tests/commands/sensors/bootstrap.test.js +57 -4
- package/dist/tests/commands/sensors/compatibility/contract.test.js +21 -0
- package/dist/tests/commands/sensors/compatibility/discovery.test.js +19 -0
- package/dist/tests/commands/sensors/compatibility/probe.test.js +14 -1
- package/dist/tests/commands/sensors/compatibility/resolve.test.js +17 -0
- package/dist/tests/commands/sensors/coverage/evidence.test.js +51 -27
- package/dist/tests/commands/sensors/coverage/resolve.test.js +51 -0
- package/dist/tests/commands/sensors/exec.test.js +112 -0
- package/dist/tests/commands/sensors/run-changed.test.js +11 -0
- package/dist/tests/commands/sensors/run.test.js +15 -2
- package/dist/tests/commands/sensors/status.test.js +3 -3
- package/dist/tests/commands/watch/e2e-crash.test.js +126 -11
- package/dist/tests/commands/watch/generations.test.js +113 -4
- package/dist/tests/commands/watch/plan-lifecycle.test.js +263 -0
- package/dist/tests/commands/watch/supervisor-loop.test.js +247 -49
- package/dist/tests/commands/watch/track-finalize.test.js +20 -3
- package/dist/tests/commands/watch/track-freeze.test.js +43 -30
- package/dist/tests/commands/watch/track-state-dependency.test.js +15 -0
- package/dist/tests/commands/watch/watch-init.test.js +244 -0
- package/dist/tests/core/admission/index.test.js +87 -0
- package/dist/tests/core/bundle-install.test.js +36 -0
- package/dist/tests/core/bundles-multiroot.test.js +24 -2
- package/dist/tests/core/bundles-overrides.test.js +10 -7
- package/dist/tests/core/bundles.test.js +75 -6
- package/dist/tests/core/diagnostics/context.test.js +2 -2
- package/dist/tests/core/export/engine.test.js +1 -1
- package/dist/tests/core/export/resolve.test.js +1 -1
- package/dist/tests/core/init/mutation-targets.test.js +1 -1
- package/dist/tests/core/init/orchestrator.test.js +1 -1
- package/dist/tests/core/init/steps.test.js +1 -1
- package/dist/tests/core/journal/fingerprint.test.js +22 -0
- package/dist/tests/core/journal/store.test.js +53 -0
- package/dist/tests/core/journal/types.test.js +7 -0
- package/dist/tests/core/migration/facts.test.js +289 -0
- package/dist/tests/core/migration/historical-provenance.test.js +25 -0
- package/dist/tests/core/plan/validate.test.js +320 -6
- package/dist/tests/core/reconciliation.test.js +1 -1
- package/dist/tests/core/sync-profile-atomicity.test.js +1 -1
- package/dist/tests/integration/pack-e2e.test.js +4 -1
- package/dist/tests/integration/preflight-json-pipe.e2e.test.js +7 -3
- package/dist/tests/integration/sensor-bootstrap.e2e.test.js +37 -0
- package/dist/tests/integration/sensor-structured-run.e2e.test.js +12 -10
- package/dist/tests/providers/injection-config.test.js +14 -6
- package/dist/tests/structural/bundle-skill-reference-contract.test.js +56 -0
- package/dist/tests/structural/jest-environment-is-isolated.test.js +29 -24
- package/dist/tests/structural/native-release-artifacts.test.js +16 -0
- package/dist/tests/utils/grouping.test.js +2 -2
- package/dist/tests/utils/registry-view.test.js +7 -7
- package/package.json +2 -2
- package/prebuilds/darwin-arm64/secure_fs.node +0 -0
- package/prebuilds/darwin-x64/secure_fs.node +0 -0
- package/prebuilds/win32-arm64/secure_fs.node +0 -0
- package/prebuilds/win32-x64/secure_fs.node +0 -0
|
@@ -1,4 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
@@ -17,7 +50,14 @@ const store_1 = require("../../../src/core/journal/store");
|
|
|
17
50
|
const paths_1 = require("../../../src/core/journal/paths");
|
|
18
51
|
const process_1 = require("../../../src/core/journal/process");
|
|
19
52
|
const fingerprint_1 = require("../../../src/core/journal/fingerprint");
|
|
53
|
+
const fingerprint = __importStar(require("../../../src/core/journal/fingerprint"));
|
|
20
54
|
const tracks_1 = require("../../../src/commands/watch/tracks");
|
|
55
|
+
const validate_1 = require("../../../src/core/plan/validate");
|
|
56
|
+
const registryInventory = __importStar(require("../../../src/core/registries"));
|
|
57
|
+
const currentnessCheck = __importStar(require("../../../src/core/currentness/check"));
|
|
58
|
+
const sensorCommands = __importStar(require("../../../src/commands/sensors/run"));
|
|
59
|
+
const preferencesConfig = __importStar(require("../../../src/utils/config"));
|
|
60
|
+
const providers_1 = require("../../../src/providers");
|
|
21
61
|
jest.setTimeout(60000);
|
|
22
62
|
// runSupervisorLoop's full external-controller lifecycle (spawn stub codex ->
|
|
23
63
|
// identity captured by the wrapper -> adopted via collectControllerGeneration's
|
|
@@ -49,6 +89,28 @@ function setupRepo() {
|
|
|
49
89
|
fs_1.default.writeFileSync(path_1.default.join(repo, '.awm', 'sensors.json'), '{}');
|
|
50
90
|
return repo;
|
|
51
91
|
}
|
|
92
|
+
const admitted = async () => ({
|
|
93
|
+
state: 'admitted', planState: 'valid', executionMode: 'desatendido',
|
|
94
|
+
journal: 'current', currentness: 'current', sensors: 'pass', diagnostics: [],
|
|
95
|
+
});
|
|
96
|
+
/** Legacy fixtures predate compact-only admission; make their execution contract explicit. */
|
|
97
|
+
function initUnattendedFixture(repo) {
|
|
98
|
+
(0, init_1.initWatch)(repo, 'main');
|
|
99
|
+
const planPath = path_1.default.join(repo, 'plans', 'fixture.md');
|
|
100
|
+
fs_1.default.mkdirSync(path_1.default.dirname(planPath), { recursive: true });
|
|
101
|
+
fs_1.default.writeFileSync(planPath, fs_1.default.readFileSync(path_1.default.join(__dirname, '../../core/plan/fixtures/compact-slices-v1/valid.md'), 'utf8'));
|
|
102
|
+
fs_1.default.writeFileSync(path_1.default.join(repo, 'source.md'), '## Canonical source\nfixture source\n');
|
|
103
|
+
const plan = (0, validate_1.validatePlanFile)('plans/fixture.md', repo);
|
|
104
|
+
if (plan.state !== 'valid')
|
|
105
|
+
throw new Error('compact fixture must validate');
|
|
106
|
+
const state = (0, store_1.readJournal)(repo, 'main').state;
|
|
107
|
+
state.schema = 2;
|
|
108
|
+
state.planBinding = {
|
|
109
|
+
path: 'plans/fixture.md', digest: plan.planDigest, schema: plan.schema,
|
|
110
|
+
executionMode: 'desatendido', boundAt: new Date().toISOString(),
|
|
111
|
+
};
|
|
112
|
+
(0, store_1.writeJournal)(repo, 'main', state);
|
|
113
|
+
}
|
|
52
114
|
function emitVerdict(repo, token, obligationId, verdictId) {
|
|
53
115
|
const argv = ['awm-review', obligationId];
|
|
54
116
|
const fp = (0, fingerprint_1.computeFingerprint)(repo, argv, [], '.').fingerprint;
|
|
@@ -160,43 +222,70 @@ describe('supervisor loop', () => {
|
|
|
160
222
|
process.env.PATH = `${stubBin}${path_1.default.delimiter}${process.env.PATH}`;
|
|
161
223
|
});
|
|
162
224
|
afterEach(() => {
|
|
225
|
+
jest.restoreAllMocks();
|
|
163
226
|
process.env.PATH = oldPath;
|
|
164
227
|
fs_1.default.rmSync(repo, { recursive: true, force: true });
|
|
165
228
|
fs_1.default.rmSync(stubBin, { recursive: true, force: true });
|
|
166
229
|
});
|
|
167
230
|
test('ticks drenan y declaran COMPLETE solo con gate verde + cero vivos (R4.5)', async () => {
|
|
168
|
-
(
|
|
231
|
+
initUnattendedFixture(repo);
|
|
169
232
|
const cfg = { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, provider: 'codex', tickMs: 50, reconcileGraceMs: 10000 };
|
|
170
|
-
|
|
233
|
+
// Recovery classification has its own unit suite. This lifecycle test
|
|
234
|
+
// owns draining/COMPLETE, so pin the recovered schema-2 fixture green
|
|
235
|
+
// and do not leak the external controller stub merely to test wrappers.
|
|
236
|
+
const recovery = jest.spyOn(fingerprint, 'reconcileUnattendedRecovery').mockReturnValue({
|
|
237
|
+
state: 'ready', nextAction: 'select-work', activeJobIds: [], diagnostics: [],
|
|
238
|
+
});
|
|
239
|
+
let controllerSpawnAttempts = 0;
|
|
240
|
+
const lifecycleSpawner = (job, nonce, logsRoot, repoRoot) => {
|
|
241
|
+
if (job.argv[0] === 'codex') {
|
|
242
|
+
controllerSpawnAttempts++;
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
fakeSpawner(job, nonce, logsRoot, repoRoot);
|
|
246
|
+
};
|
|
247
|
+
const sup = new supervisor_1.Supervisor(repo, 'main', cfg, lifecycleSpawner, undefined, admitted);
|
|
248
|
+
// The schema-2 recovery path only consumes requests authorized by the
|
|
249
|
+
// active generation. Establish it before issuing the scenario facts;
|
|
250
|
+
// the legacy fixture's hard-coded `g0` was never consumed and left the
|
|
251
|
+
// fake controller running forever in `select-work`.
|
|
252
|
+
const generation = (0, generations_1.beginGeneration)(repo, 'main');
|
|
171
253
|
// el controlador (aqui: el test) registra plan de ciclo + task + jobs enlazados
|
|
172
|
-
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken:
|
|
254
|
+
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken: generation.token, idempotencyKey: 'e1',
|
|
173
255
|
payload: { entity: 'task', taskId: 'T1', title: 't', verificationPlan: [{ id: 'v1', kind: 'test' }, { id: 'v-sensors', kind: 'sensors' }], reviewObligations: [{ id: 'o-spec', kind: 'spec' }, { id: 'o-quality', kind: 'quality' }] } });
|
|
174
|
-
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken:
|
|
256
|
+
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken: generation.token, idempotencyKey: 'e2',
|
|
175
257
|
payload: { entity: 'cycle-plan', items: [{ id: 'cv1', kind: 'qa' }, { id: 'cv-interlock', kind: 'interlock' }] } });
|
|
176
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
177
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
178
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
179
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
180
|
-
emitVerdict(repo,
|
|
181
|
-
emitVerdict(repo,
|
|
182
|
-
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken:
|
|
258
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'setTimeout(()=>process.exit(0), 400)'], [], '.', { satisfies: 'v1' });
|
|
259
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'process.exit(0)'], [], '.', { satisfies: 'v-sensors' });
|
|
260
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'process.exit(0)'], [], '.', { satisfies: 'cv1' });
|
|
261
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'process.exit(0)'], [], '.', { satisfies: 'cv-interlock' });
|
|
262
|
+
emitVerdict(repo, generation.token, 'o-spec', 'verd-spec');
|
|
263
|
+
emitVerdict(repo, generation.token, 'o-quality', 'verd-quality');
|
|
264
|
+
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken: generation.token, idempotencyKey: 'e3',
|
|
183
265
|
payload: { entity: 'task-status', taskId: 'T1', status: 'done' } });
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
266
|
+
try {
|
|
267
|
+
let sawContinueWithLiveJob = false;
|
|
268
|
+
let outcome = 'continue';
|
|
269
|
+
for (let i = 0; i < 400 && outcome !== 'complete'; i++) {
|
|
270
|
+
outcome = await sup.tick();
|
|
271
|
+
const s = (0, store_1.readJournal)(repo, 'main').state;
|
|
272
|
+
const live = Object.values(s.jobs).some((j) => ['received', 'spawn-intent', 'claimed', 'running'].includes(j.executionState));
|
|
273
|
+
if (outcome === 'continue' && live)
|
|
274
|
+
sawContinueWithLiveJob = true; // drenaje ANTES de COMPLETE
|
|
275
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
276
|
+
}
|
|
277
|
+
expect(outcome).toBe('complete');
|
|
278
|
+
expect(sawContinueWithLiveJob).toBe(true);
|
|
279
|
+
const final = (0, store_1.readJournal)(repo, 'main').state;
|
|
280
|
+
expect(final.cycle.status).toBe('COMPLETE');
|
|
281
|
+
expect(typeof final.cycle.completedAt).toBe('string');
|
|
282
|
+
expect(Object.values(final.jobs).every((j) => j.executionState === 'exited' && j.verdict === 'pass')).toBe(true);
|
|
283
|
+
expect(final.generations.every((entry) => entry.state === 'terminated' && entry.processRef === undefined)).toBe(true);
|
|
284
|
+
expect(controllerSpawnAttempts).toBeGreaterThan(0);
|
|
285
|
+
}
|
|
286
|
+
finally {
|
|
287
|
+
recovery.mockRestore();
|
|
193
288
|
}
|
|
194
|
-
expect(outcome).toBe('complete');
|
|
195
|
-
expect(sawContinueWithLiveJob).toBe(true);
|
|
196
|
-
const final = (0, store_1.readJournal)(repo, 'main').state;
|
|
197
|
-
expect(final.cycle.status).toBe('COMPLETE');
|
|
198
|
-
expect(typeof final.cycle.completedAt).toBe('string');
|
|
199
|
-
expect(Object.values(final.jobs).every((j) => j.executionState === 'exited' && j.verdict === 'pass')).toBe(true);
|
|
200
289
|
});
|
|
201
290
|
// Regresion (post-review #2, Task 12/R7 — Finding 2 de la segunda ronda
|
|
202
291
|
// de re-review): la version anterior de esta prueba armaba el escenario
|
|
@@ -215,7 +304,7 @@ describe('supervisor loop', () => {
|
|
|
215
304
|
// vivos) y confirma que `cycle.status` llega a COMPLETE por ese camino
|
|
216
305
|
// generico, exactamente como lo haria un plan sin tracks en absoluto.
|
|
217
306
|
test('una cohorte que cayo a fallback SERIAL via el reducer real no cuelga el ciclo: COMPLETE llega igual por el camino generico (regresion post-review R7, ronda 2)', async () => {
|
|
218
|
-
(
|
|
307
|
+
initUnattendedFixture(repo);
|
|
219
308
|
const tracksRoot = fs_1.default.mkdtempSync(path_1.default.join(os_1.default.tmpdir(), 'awm-loop-tracks-'));
|
|
220
309
|
try {
|
|
221
310
|
const baseSha = (0, child_process_1.execFileSync)('git', ['rev-parse', 'HEAD'], { cwd: repo, encoding: 'utf8' }).trim();
|
|
@@ -240,20 +329,32 @@ describe('supervisor loop', () => {
|
|
|
240
329
|
// --- Fase 2: sobre ESE MISMO journal, completar el ciclo por el
|
|
241
330
|
// camino generico (task done + qa/interlock satisfechos + cero
|
|
242
331
|
// jobs vivos) — la misma receta que la prueba R4.5 de arriba.
|
|
243
|
-
(0,
|
|
332
|
+
const generation = (0, generations_1.beginGeneration)(repo, 'main');
|
|
333
|
+
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken: generation.token, idempotencyKey: 'e1',
|
|
244
334
|
payload: { entity: 'task', taskId: 'T1', title: 't', verificationPlan: [{ id: 'v1', kind: 'test' }, { id: 'v-sensors', kind: 'sensors' }], reviewObligations: [{ id: 'o-spec', kind: 'spec' }, { id: 'o-quality', kind: 'quality' }] } });
|
|
245
|
-
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken:
|
|
335
|
+
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken: generation.token, idempotencyKey: 'e2',
|
|
246
336
|
payload: { entity: 'cycle-plan', items: [{ id: 'cv1', kind: 'qa' }, { id: 'cv-interlock', kind: 'interlock' }] } });
|
|
247
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
248
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
249
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
250
|
-
(0, request_1.requestJob)(repo, 'main',
|
|
251
|
-
emitVerdict(repo,
|
|
252
|
-
emitVerdict(repo,
|
|
253
|
-
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken:
|
|
337
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'process.exit(0)'], [], '.', { satisfies: 'v1' });
|
|
338
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'process.exit(0)'], [], '.', { satisfies: 'v-sensors' });
|
|
339
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'process.exit(0)'], [], '.', { satisfies: 'cv1' });
|
|
340
|
+
(0, request_1.requestJob)(repo, 'main', generation.token, ['node', '-e', 'process.exit(0)'], [], '.', { satisfies: 'cv-interlock' });
|
|
341
|
+
emitVerdict(repo, generation.token, 'o-spec', 'verd-spec');
|
|
342
|
+
emitVerdict(repo, generation.token, 'o-quality', 'verd-quality');
|
|
343
|
+
(0, requests_1.emitRequest)(repo, 'main', { kind: 'register-entity', generationToken: generation.token, idempotencyKey: 'e3',
|
|
254
344
|
payload: { entity: 'task-status', taskId: 'T1', status: 'done' } });
|
|
255
345
|
const cfg = { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, provider: 'codex', tickMs: 50, reconcileGraceMs: 10000 };
|
|
256
|
-
|
|
346
|
+
// The compact recovery reducer is verified independently. This test
|
|
347
|
+
// exercises the fallback SERIAL completion path, so avoid an
|
|
348
|
+
// external controller process while keeping real job wrappers.
|
|
349
|
+
jest.spyOn(fingerprint, 'reconcileUnattendedRecovery').mockReturnValue({
|
|
350
|
+
state: 'ready', nextAction: 'select-work', activeJobIds: [], diagnostics: [],
|
|
351
|
+
});
|
|
352
|
+
const lifecycleSpawner = (job, nonce, logsRoot, repoRoot) => {
|
|
353
|
+
if (job.argv[0] === 'codex')
|
|
354
|
+
return;
|
|
355
|
+
fakeSpawner(job, nonce, logsRoot, repoRoot);
|
|
356
|
+
};
|
|
357
|
+
const sup = new supervisor_1.Supervisor(repo, 'main', cfg, lifecycleSpawner, undefined, admitted);
|
|
257
358
|
let outcome = 'continue';
|
|
258
359
|
for (let i = 0; i < 400 && outcome !== 'complete'; i++) {
|
|
259
360
|
outcome = await sup.tick();
|
|
@@ -265,34 +366,120 @@ describe('supervisor loop', () => {
|
|
|
265
366
|
expect(final.cohortPhase).toBe('SERIAL'); // nunca inventa una transicion SERIAL -> COMPLETE
|
|
266
367
|
for (const t of final.tracks)
|
|
267
368
|
expect(['REMOVED', 'DECLARED']).toContain(t.phase);
|
|
369
|
+
const { refIsAlive } = require('../../../src/core/journal/process');
|
|
370
|
+
expect(final.generations.every((entry) => entry.state === 'terminated' && (entry.processRef === undefined || !refIsAlive(entry.processRef)))).toBe(true);
|
|
268
371
|
}
|
|
269
372
|
finally {
|
|
270
373
|
fs_1.default.rmSync(tracksRoot, { recursive: true, force: true });
|
|
271
374
|
}
|
|
272
375
|
});
|
|
273
376
|
test('tick verifica branch antes del launch y un ciclo COMPLETE no lanza otro controller', async () => {
|
|
274
|
-
(
|
|
377
|
+
initUnattendedFixture(repo);
|
|
275
378
|
let calls = 0;
|
|
276
379
|
const spy = () => { calls++; };
|
|
277
380
|
const cfg = { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, tickMs: 10 };
|
|
278
381
|
const s = (0, store_1.readJournal)(repo, 'main').state;
|
|
279
382
|
s.cycle.status = 'COMPLETE';
|
|
280
383
|
(0, store_1.writeJournal)(repo, 'main', s);
|
|
281
|
-
expect(await new supervisor_1.Supervisor(repo, 'main', cfg, spy).tick()).toBe('complete');
|
|
384
|
+
expect(await new supervisor_1.Supervisor(repo, 'main', cfg, spy, undefined, admitted).tick()).toBe('complete');
|
|
282
385
|
expect(calls).toBe(0);
|
|
283
386
|
const reset = (0, store_1.readJournal)(repo, 'main').state;
|
|
284
387
|
reset.cycle.status = 'IN_PROGRESS';
|
|
285
388
|
(0, store_1.writeJournal)(repo, 'main', reset);
|
|
286
389
|
git(repo, 'checkout', '-qb', 'otra');
|
|
287
|
-
await expect(new supervisor_1.Supervisor(repo, 'main', cfg, spy).tick()).rejects.toThrow(/rama|branch/i);
|
|
390
|
+
await expect(new supervisor_1.Supervisor(repo, 'main', cfg, spy, undefined, admitted).tick()).rejects.toThrow(/rama|branch/i);
|
|
288
391
|
expect(calls).toBe(0);
|
|
289
392
|
});
|
|
393
|
+
test('una admisión compacta bloqueada no lanza controlador ni wrappers', async () => {
|
|
394
|
+
initUnattendedFixture(repo);
|
|
395
|
+
const state = (0, store_1.readJournal)(repo, 'main').state;
|
|
396
|
+
state.schema = 2;
|
|
397
|
+
state.planBinding = { path: 'plans/exact.md', digest: 'a'.repeat(64), schema: 'compact-slices/v1', executionMode: 'desatendido', boundAt: new Date().toISOString() };
|
|
398
|
+
(0, store_1.writeJournal)(repo, 'main', state);
|
|
399
|
+
(0, request_1.requestJob)(repo, 'main', 'g0', ['node', '-e', 'process.exit(0)'], [], '.');
|
|
400
|
+
let spawns = 0;
|
|
401
|
+
const blocked = async () => ({ state: 'blocked', planState: 'valid', journal: 'current', currentness: 'stale', sensors: 'not-required', diagnostics: [{ code: 'ADMISSION_CURRENTNESS_BLOCKED', message: 'stale' }] });
|
|
402
|
+
const outcome = await new supervisor_1.Supervisor(repo, 'main', supervisor_1.DEFAULT_SUPERVISOR_CONFIG, () => { spawns++; }, undefined, blocked).tick();
|
|
403
|
+
expect(outcome).toBe('custody');
|
|
404
|
+
expect(spawns).toBe(0);
|
|
405
|
+
expect((0, store_1.readJournal)(repo, 'main').state.cycle.status).toBe('BLOCKED');
|
|
406
|
+
});
|
|
407
|
+
test('native default admission blocks an actual incompatible runtime supplier on a project-only plan before sensors or dispatch', async () => {
|
|
408
|
+
initUnattendedFixture(repo);
|
|
409
|
+
const oldHome = process.env.HOME;
|
|
410
|
+
process.env.HOME = path_1.default.join(repo, 'isolated-home');
|
|
411
|
+
const registryRoot = path_1.default.join(repo, 'supplier-registry');
|
|
412
|
+
const skillSource = path_1.default.join(registryRoot, 'skills', 'using-awm');
|
|
413
|
+
fs_1.default.mkdirSync(skillSource, { recursive: true });
|
|
414
|
+
fs_1.default.writeFileSync(path_1.default.join(skillSource, 'SKILL.md'), 'runtime contract');
|
|
415
|
+
fs_1.default.writeFileSync(path_1.default.join(registryRoot, 'awm-registry.json'), '{"minCliVersion":"999.0.0"}');
|
|
416
|
+
const installed = (0, providers_1.providerFor)('codex').skill.global;
|
|
417
|
+
fs_1.default.mkdirSync(installed, { recursive: true });
|
|
418
|
+
fs_1.default.symlinkSync(skillSource, path_1.default.join(installed, 'using-awm'), process.platform === 'win32' ? 'junction' : 'dir');
|
|
419
|
+
const inventory = jest.spyOn(registryInventory, 'listRegistries').mockReturnValue([{ name: 'supplier', remote: 'https://example.invalid/supplier.git', contentRoot: registryRoot }]);
|
|
420
|
+
const preferences = jest.spyOn(preferencesConfig, 'readPreferences').mockReturnValue({ defaultAgent: 'codex', enabledAgents: ['codex'], installMethod: 'symlink', defaultScope: 'local' });
|
|
421
|
+
const currentness = jest.spyOn(currentnessCheck, 'checkCurrentness').mockResolvedValue({ checkedAt: 'x', compatibility: { status: 'not-checked' }, components: ['cli', 'registry:supplier'].map(component => ({ component, installed: '1.0.0', latest: '1.0.0', channel: 'stable', source: 'fixture', checkedAt: 'x', status: 'current', detail: 'ok', remedy: 'none' })) });
|
|
422
|
+
const sensors = jest.spyOn(sensorCommands, 'runSensors').mockResolvedValue({ overall: 'pass', sensors: [] });
|
|
423
|
+
let dispatches = 0;
|
|
424
|
+
try {
|
|
425
|
+
const outcome = await new supervisor_1.Supervisor(repo, 'main', supervisor_1.DEFAULT_SUPERVISOR_CONFIG, () => { dispatches++; }).tick();
|
|
426
|
+
expect(outcome).toBe('custody');
|
|
427
|
+
expect(sensors).not.toHaveBeenCalled();
|
|
428
|
+
expect(dispatches).toBe(0);
|
|
429
|
+
expect((0, store_1.readJournal)(repo, 'main').state.cycle.status).toBe('BLOCKED');
|
|
430
|
+
expect((0, store_1.readJournal)(repo, 'main').state.cycle.blockedReason).toContain('ADMISSION_REGISTRY_CLI_INCOMPATIBLE');
|
|
431
|
+
expect((0, store_1.readJournal)(repo, 'main').state.cycle.blockedReason).toContain('999.0.0');
|
|
432
|
+
}
|
|
433
|
+
finally {
|
|
434
|
+
inventory.mockRestore();
|
|
435
|
+
preferences.mockRestore();
|
|
436
|
+
currentness.mockRestore();
|
|
437
|
+
sensors.mockRestore();
|
|
438
|
+
if (oldHome === undefined)
|
|
439
|
+
delete process.env.HOME;
|
|
440
|
+
else
|
|
441
|
+
process.env.HOME = oldHome;
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
test.each([
|
|
445
|
+
['cycle BLOCKED', (s) => { s.cycle.status = 'BLOCKED'; }],
|
|
446
|
+
['request problem durable', (s) => { s.requestProblems.push({ file: 'x.request.json', kind: 'rejected', detail: 'x', at: new Date().toISOString() }); }],
|
|
447
|
+
['verificador requerido ausente tras tasks completadas', (s) => {
|
|
448
|
+
s.tasks.push({ id: 'T1', title: 'terminada', status: 'done', attempts: 1, verificationPlan: [], reviewObligations: [] });
|
|
449
|
+
s.requiredVerifiers = ['test'];
|
|
450
|
+
}],
|
|
451
|
+
])('recovery fail-closed: %s entra en custodia sin controller ni dispatch', async (_name, mutate) => {
|
|
452
|
+
initUnattendedFixture(repo);
|
|
453
|
+
const state = (0, store_1.readJournal)(repo, 'main').state;
|
|
454
|
+
mutate(state);
|
|
455
|
+
(0, store_1.writeJournal)(repo, 'main', state);
|
|
456
|
+
let spawns = 0;
|
|
457
|
+
const outcome = await new supervisor_1.Supervisor(repo, 'main', supervisor_1.DEFAULT_SUPERVISOR_CONFIG, () => { spawns++; }, undefined, admitted).tick();
|
|
458
|
+
expect(outcome).toBe('custody');
|
|
459
|
+
expect(spawns).toBe(0);
|
|
460
|
+
expect((0, store_1.readJournal)(repo, 'main').state.cycle.status).toBe('BLOCKED');
|
|
461
|
+
});
|
|
462
|
+
test('un journal schema-1 legacy no despacha controller ni jobs aunque contenga trabajo pendiente', async () => {
|
|
463
|
+
(0, store_1.initJournal)(repo, 'main');
|
|
464
|
+
const legacy = (0, store_1.readJournal)(repo, 'main').state;
|
|
465
|
+
legacy.jobs.pending = {
|
|
466
|
+
id: 'pending', fingerprint: '', commandDigest: '', argv: ['node', '-e', 'process.exit(0)'], cwd: '.', paths: [], expandedPaths: [],
|
|
467
|
+
executionState: 'received', observationState: 'progressing', phaseTimestamps: {},
|
|
468
|
+
};
|
|
469
|
+
(0, store_1.writeJournal)(repo, 'main', legacy);
|
|
470
|
+
let spawns = 0;
|
|
471
|
+
const outcome = await new supervisor_1.Supervisor(repo, 'main', supervisor_1.DEFAULT_SUPERVISOR_CONFIG, () => { spawns++; }).tick();
|
|
472
|
+
expect(outcome).toBe('custody');
|
|
473
|
+
expect(spawns).toBe(0);
|
|
474
|
+
expect((0, store_1.readJournal)(repo, 'main').state.generations).toEqual([]);
|
|
475
|
+
expect((0, store_1.readJournal)(repo, 'main').state.jobs.pending.executionState).toBe('received');
|
|
476
|
+
});
|
|
290
477
|
test('fallo de launch queda durable y entra en backoff sin tumbar el supervisor (R4.3)', async () => {
|
|
291
|
-
(
|
|
478
|
+
initUnattendedFixture(repo);
|
|
292
479
|
(0, generations_1.beginGeneration)(repo, 'main');
|
|
293
480
|
let calls = 0;
|
|
294
481
|
const failing = () => { calls++; throw new Error('provider unavailable'); };
|
|
295
|
-
const sup = new supervisor_1.Supervisor(repo, 'main', { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, tickMs: 10 }, failing);
|
|
482
|
+
const sup = new supervisor_1.Supervisor(repo, 'main', { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, tickMs: 10 }, failing, undefined, admitted);
|
|
296
483
|
await expect(sup.tick()).resolves.toBe('continue');
|
|
297
484
|
expect(calls).toBe(1);
|
|
298
485
|
const intent = (0, generations_1.activeGeneration)((0, store_1.readJournal)(repo, 'main').state);
|
|
@@ -302,7 +489,7 @@ describe('supervisor loop', () => {
|
|
|
302
489
|
expect(calls).toBe(1); // primer backoff es 60 s: no hace hot-loop
|
|
303
490
|
});
|
|
304
491
|
test('custodia: doble senial + indeterminate => tick custody, lock retenido, proceso intacto (R4.2b/R4.5)', async () => {
|
|
305
|
-
(
|
|
492
|
+
initUnattendedFixture(repo);
|
|
306
493
|
(0, generations_1.beginGeneration)(repo, 'main');
|
|
307
494
|
const { child, ref } = (0, process_1.spawnStructured)(['node', '-e', 'setTimeout(()=>{}, 20000)'], process.cwd(), 'nCtl');
|
|
308
495
|
let s = (0, store_1.readJournal)(repo, 'main').state;
|
|
@@ -312,7 +499,7 @@ describe('supervisor loop', () => {
|
|
|
312
499
|
fs_1.default.mkdirSync(path_1.default.dirname((0, paths_1.supervisorLockPath)(repo)), { recursive: true });
|
|
313
500
|
fs_1.default.writeFileSync((0, paths_1.supervisorLockPath)(repo), 'lock-del-loop'); // el loop lo tendria: NO debe borrarse
|
|
314
501
|
const cfg = { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, provider: 'codex', heartbeatTimeoutMs: 1, activityWindowMs: 50, tickMs: 20 };
|
|
315
|
-
const sup = new supervisor_1.Supervisor(repo, 'main', cfg, fakeSpawner);
|
|
502
|
+
const sup = new supervisor_1.Supervisor(repo, 'main', cfg, fakeSpawner, undefined, admitted);
|
|
316
503
|
await sup.tick(); // primer tick: arranca el tracking de actividad
|
|
317
504
|
await new Promise((r) => setTimeout(r, 150)); // actividad congelada > ventana
|
|
318
505
|
const out = await sup.tick();
|
|
@@ -324,9 +511,12 @@ describe('supervisor loop', () => {
|
|
|
324
511
|
child.kill('SIGKILL');
|
|
325
512
|
});
|
|
326
513
|
itPosix('runSupervisorLoop: bootstrap gen-1 con stub codex, COMPLETE => libera lock y termina su generacion (R4.1/R4.5/R2.4)', async () => {
|
|
327
|
-
(
|
|
514
|
+
initUnattendedFixture(repo);
|
|
515
|
+
jest.spyOn(fingerprint, 'reconcileUnattendedRecovery').mockReturnValue({
|
|
516
|
+
state: 'ready', nextAction: 'select-work', activeJobIds: [], diagnostics: [],
|
|
517
|
+
});
|
|
328
518
|
const cfg = { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, provider: 'codex', tickMs: 50, termGraceMs: 300, killGraceMs: 300 };
|
|
329
|
-
const loop = (0, supervisor_1.runSupervisorLoop)(repo, 'main', cfg, fakeSpawner);
|
|
519
|
+
const loop = (0, supervisor_1.runSupervisorLoop)(repo, 'main', cfg, fakeSpawner, undefined, admitted);
|
|
330
520
|
await until(() => {
|
|
331
521
|
const r = (0, store_1.readJournal)(repo, 'main');
|
|
332
522
|
return r.state !== null && (0, generations_1.activeGeneration)(r.state) !== undefined && fs_1.default.existsSync((0, paths_1.supervisorLockPath)(repo));
|
|
@@ -346,13 +536,17 @@ describe('supervisor loop', () => {
|
|
|
346
536
|
// generacion propia terminada: cero procesos codex huerfanos (R2.4)
|
|
347
537
|
const { refIsAlive } = require('../../../src/core/journal/process');
|
|
348
538
|
expect(gen.processRef === undefined || !refIsAlive(gen.processRef)).toBe(true);
|
|
539
|
+
expect(gen.state).toBe('terminated');
|
|
349
540
|
});
|
|
350
541
|
itPosix('reinicio tras crash entre beginGeneration y spawn recupera la misma generacion sin quedar wedged', async () => {
|
|
351
|
-
(
|
|
542
|
+
initUnattendedFixture(repo);
|
|
543
|
+
jest.spyOn(fingerprint, 'reconcileUnattendedRecovery').mockReturnValue({
|
|
544
|
+
state: 'ready', nextAction: 'select-work', activeJobIds: [], diagnostics: [],
|
|
545
|
+
});
|
|
352
546
|
const begun = (0, generations_1.beginGeneration)(repo, 'main'); // crash simulado: intent durable, sin ProcessRef
|
|
353
547
|
const cfg = { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, provider: 'codex', tickMs: 25, reconcileGraceMs: 300,
|
|
354
548
|
termGraceMs: 300, killGraceMs: 300 };
|
|
355
|
-
const loop = (0, supervisor_1.runSupervisorLoop)(repo, 'main', cfg, fakeSpawner);
|
|
549
|
+
const loop = (0, supervisor_1.runSupervisorLoop)(repo, 'main', cfg, fakeSpawner, undefined, admitted);
|
|
356
550
|
let recovered = false;
|
|
357
551
|
try {
|
|
358
552
|
await until(() => {
|
|
@@ -369,6 +563,10 @@ describe('supervisor loop', () => {
|
|
|
369
563
|
}
|
|
370
564
|
await loop;
|
|
371
565
|
expect(recovered).toBe(true);
|
|
372
|
-
|
|
566
|
+
const final = (0, store_1.readJournal)(repo, 'main').state;
|
|
567
|
+
expect(final.generations).toHaveLength(1);
|
|
568
|
+
expect(final.generations[0].state).toBe('terminated');
|
|
569
|
+
const { refIsAlive } = require('../../../src/core/journal/process');
|
|
570
|
+
expect(final.generations[0].processRef === undefined || !refIsAlive(final.generations[0].processRef)).toBe(true);
|
|
373
571
|
});
|
|
374
572
|
});
|
|
@@ -26,6 +26,7 @@ const supervisor_1 = require("../../../src/commands/watch/supervisor");
|
|
|
26
26
|
const tracks_1 = require("../../../src/commands/watch/tracks");
|
|
27
27
|
const exec_wrapper_1 = require("../../../src/commands/job/exec-wrapper");
|
|
28
28
|
const init_1 = require("../../../src/commands/watch/init");
|
|
29
|
+
const validate_1 = require("../../../src/core/plan/validate");
|
|
29
30
|
const requests_1 = require("../../../src/core/journal/requests");
|
|
30
31
|
const apply_1 = require("../../../src/commands/watch/apply");
|
|
31
32
|
const generations_1 = require("../../../src/commands/watch/generations");
|
|
@@ -35,6 +36,22 @@ const fingerprint_1 = require("../../../src/core/journal/fingerprint");
|
|
|
35
36
|
const paths_1 = require("../../../src/core/journal/paths");
|
|
36
37
|
const types_1 = require("../../../src/core/journal/types");
|
|
37
38
|
const git_fixture_1 = require("../../helpers/git-fixture");
|
|
39
|
+
const admitted = async () => ({
|
|
40
|
+
state: 'admitted', planState: 'valid', executionMode: 'desatendido',
|
|
41
|
+
journal: 'current', currentness: 'current', sensors: 'pass', diagnostics: [],
|
|
42
|
+
});
|
|
43
|
+
function initCompactWatch(repoRoot, branch) {
|
|
44
|
+
const planPath = path_1.default.join(repoRoot, 'plans', 'fixture.md');
|
|
45
|
+
fs_1.default.mkdirSync(path_1.default.dirname(planPath), { recursive: true });
|
|
46
|
+
fs_1.default.writeFileSync(planPath, fs_1.default.readFileSync(path_1.default.join(__dirname, '../../core/plan/fixtures/compact-slices-v1/valid.md'), 'utf8'));
|
|
47
|
+
fs_1.default.writeFileSync(path_1.default.join(repoRoot, 'source.md'), '## Canonical source\nfixture source\n');
|
|
48
|
+
git(repoRoot, 'add', 'plans/fixture.md', 'source.md');
|
|
49
|
+
git(repoRoot, 'commit', '-qm', 'compact plan fixture');
|
|
50
|
+
const report = (0, validate_1.validatePlanFile)('plans/fixture.md', repoRoot);
|
|
51
|
+
if (report.state !== 'valid')
|
|
52
|
+
throw new Error(`compact fixture must validate: ${JSON.stringify(report)}`);
|
|
53
|
+
(0, init_1.initWatch)(repoRoot, branch, { path: 'plans/fixture.md', report });
|
|
54
|
+
}
|
|
38
55
|
function git(cwd, ...args) {
|
|
39
56
|
(0, child_process_1.execFileSync)('git', ['-c', 'user.email=t@t.t', '-c', 'user.name=t', '-c', 'commit.gpgsign=false', ...args], { cwd, stdio: 'pipe' });
|
|
40
57
|
}
|
|
@@ -242,7 +259,7 @@ function finalizerHarness(trackIds) {
|
|
|
242
259
|
git(repo, 'commit', '-qm', 'seed');
|
|
243
260
|
fs_1.default.mkdirSync(path_1.default.join(repo, '.awm'), { recursive: true });
|
|
244
261
|
fs_1.default.writeFileSync(path_1.default.join(repo, '.awm', 'sensors.json'), '{}');
|
|
245
|
-
(
|
|
262
|
+
initCompactWatch(repo, 'main'); // gitignora .awm, detecta requiredVerifiers (test+sensors, R3.6)
|
|
246
263
|
git(repo, 'add', '.gitignore');
|
|
247
264
|
git(repo, 'commit', '-qm', 'gitignore .awm');
|
|
248
265
|
const baseSha = (0, child_process_1.execFileSync)('git', ['rev-parse', 'HEAD'], { cwd: repo, encoding: 'utf8' }).trim();
|
|
@@ -282,7 +299,7 @@ function finalizerHarness(trackIds) {
|
|
|
282
299
|
payload: { entity: 'track-integration', argv: INTEGRATION_ARGV, paths: INTEGRATION_PATHS, planDigest: 'plan-1' },
|
|
283
300
|
});
|
|
284
301
|
const cfg = { ...supervisor_1.DEFAULT_SUPERVISOR_CONFIG, tickMs: 10, provider: 'codex' };
|
|
285
|
-
let sup = new supervisor_1.Supervisor(repo, 'main', cfg, spawner);
|
|
302
|
+
let sup = new supervisor_1.Supervisor(repo, 'main', cfg, spawner, undefined, admitted);
|
|
286
303
|
const realFingerprintNow = (argv, paths, cwd) => {
|
|
287
304
|
try {
|
|
288
305
|
return (0, fingerprint_1.computeFingerprint)(repo, argv, paths, cwd).fingerprint;
|
|
@@ -360,7 +377,7 @@ function finalizerHarness(trackIds) {
|
|
|
360
377
|
.map((j) => ({ argv: j.argv, paths: j.paths, cwd: j.cwd, satisfies: [...(j.satisfies ?? [])].sort() }));
|
|
361
378
|
},
|
|
362
379
|
integrationWrapperCalls() { return integrationCalls; },
|
|
363
|
-
crashAndRestart() { sup = new supervisor_1.Supervisor(repo, 'main', cfg, spawner); },
|
|
380
|
+
crashAndRestart() { sup = new supervisor_1.Supervisor(repo, 'main', cfg, spawner, undefined, admitted); },
|
|
364
381
|
interlock() {
|
|
365
382
|
const s = (0, store_1.readJournal)(repo, 'main').state;
|
|
366
383
|
return (0, gate_1.computeGate)(s, false, realFingerprintNow);
|