agentic-workflow-manager 9.11.10 → 9.11.12
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/src/commands/plan/index.js +1 -4
- package/dist/src/commands/watch/apply.js +9 -1
- package/dist/src/core/model-policy/journal.js +17 -3
- package/dist/src/core/model-policy/resolve.js +24 -0
- package/dist/tests/commands/job/routing-report-cli.test.js +8 -2
- package/dist/tests/commands/job/routing.test.js +2 -2
- package/dist/tests/commands/plan/index.test.js +2 -2
- package/dist/tests/commands/watch/apply.test.js +32 -10
- package/dist/tests/core/model-policy/journal.test.js +53 -11
- package/dist/tests/core/model-policy/resolve.test.js +17 -0
- package/dist/tests/helpers/routing-approval.js +14 -0
- package/dist/tests/structural/native-release-artifacts.test.js +73 -4
- package/package.json +1 -1
- 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
|
@@ -209,12 +209,9 @@ function registerPlanCommand(program, deps = { validatePlanFile: validate_1.vali
|
|
|
209
209
|
const state = journalObservation(cwd).journalState;
|
|
210
210
|
const lineage = state.implementationLineages.find(candidate => candidate.id === options.lineage);
|
|
211
211
|
const next = (0, journal_1.resolveLineageEscalation)(state, options.lineage, lineage.initialProfile);
|
|
212
|
-
const resolved = (0, resolve_1.
|
|
212
|
+
const resolved = (0, resolve_1.resolveEscalatedSelection)({ role: 'implementer', requestedProfile: next.profile, expectedEffort: next.effort, policy: policy.state === 'approved' ? policy.policy : undefined, capabilities: capabilities.state === 'current' ? capabilities.receipt : undefined, runtime, now: new Date() });
|
|
213
213
|
if (resolved.state === 'blocked')
|
|
214
214
|
return resolved;
|
|
215
|
-
const highRequiresFull = next.effort !== 'high' || (policy.state === 'approved' && (() => { const full = policy.policy.content.mappings.find(row => row.target === runtime.target && row.runtimeKind === runtime.kind)?.fullCapability; return full?.selector.kind === resolved.selection.selector.kind && full.selector.id === resolved.selection.selector.id && full.effort.kind === 'explicit' && full.effort.value === 'high'; })());
|
|
216
|
-
if (resolved.selection.effort.kind !== 'explicit' || resolved.selection.effort.value !== next.effort || !highRequiresFull)
|
|
217
|
-
return { state: 'blocked', diagnostics: [{ code: 'ROUTING_ESCALATION_EFFORT_UNAVAILABLE', message: 'The approved selected effort does not match the next lineage escalation.' }] };
|
|
218
215
|
return { ...resolved, envelope: { schema: 'routing-envelope/v1', runtime, role: 'implementer', planDigest: report.planDigest, executionDigest: report.executionDigest, sliceId: lineage.sliceId, requestedProfile: lineage.initialProfile, effectiveProfile: next.profile, resolved: resolved.selection, policyDigest: resolved.policyDigest, capabilityDigest: resolved.capabilityDigest, outcome: resolved.outcome, unavailableEvidence: resolved.unavailableEvidence }, custodyHandoff: { kind: 'routing-reserve', obligationId: lineage.obligationId, lineageId: lineage.id } };
|
|
219
216
|
})();
|
|
220
217
|
process.stdout.write(options.json ? `${JSON.stringify(result)}\n` : `Plan routing: ${result.state}\n`);
|
|
@@ -20,6 +20,8 @@ const redact_1 = require("../../core/journal/redact");
|
|
|
20
20
|
const git_1 = require("../../core/tracks/git");
|
|
21
21
|
const types_1 = require("../../core/journal/types");
|
|
22
22
|
const journal_1 = require("../../core/model-policy/journal");
|
|
23
|
+
const store_2 = require("../../core/model-policy/store");
|
|
24
|
+
const capabilities_1 = require("../../core/model-policy/capabilities");
|
|
23
25
|
function now() { return new Date().toISOString(); }
|
|
24
26
|
const VERIFICATION_KINDS = ['test', 'lint', 'sensors', 'review', 'qa', 'interlock', 'track-integration'];
|
|
25
27
|
function verificationItems(value, field) {
|
|
@@ -116,7 +118,13 @@ function applyRequestToState(s, env, digest, repoRoot) {
|
|
|
116
118
|
const p = env.payload;
|
|
117
119
|
if (typeof p.obligationId !== 'string' || typeof p.lineageId !== 'string' || !(0, types_1.isRoutingEnvelope)(p.envelope) || typeof p.fingerprint !== 'string' || (p.at !== undefined && typeof p.at !== 'string'))
|
|
118
120
|
throw new Error('routing-reserve requiere payload estricto');
|
|
119
|
-
const
|
|
121
|
+
const envelope = p.envelope;
|
|
122
|
+
const reserved = (0, journal_1.reserveRoutingAttempt)(s, { obligationId: p.obligationId, lineageId: p.lineageId, envelope, fingerprint: p.fingerprint, approval: () => {
|
|
123
|
+
const checkedAt = new Date();
|
|
124
|
+
const policy = (0, store_2.readEffectivePolicy)(repoRoot);
|
|
125
|
+
const capabilities = (0, capabilities_1.readCapabilities)((0, capabilities_1.validateRuntimeKey)(envelope.runtime), checkedAt);
|
|
126
|
+
return { checkedAt, policy: policy.state === 'approved' ? policy.policy : undefined, capabilities: capabilities.state === 'current' ? capabilities.receipt : undefined };
|
|
127
|
+
} }, p.at ?? now());
|
|
120
128
|
Object.assign(s, reserved.state);
|
|
121
129
|
(0, requests_1.applyOutcome)(s, { ...base, outcome: 'applied', resultRef: reserved.attemptId });
|
|
122
130
|
return;
|
|
@@ -9,6 +9,8 @@ exports.resolveLineageEscalation = resolveLineageEscalation;
|
|
|
9
9
|
exports.routingReport = routingReport;
|
|
10
10
|
const crypto_1 = __importDefault(require("crypto"));
|
|
11
11
|
const types_1 = require("../journal/types");
|
|
12
|
+
const resolve_1 = require("./resolve");
|
|
13
|
+
const capabilities_1 = require("./capabilities");
|
|
12
14
|
function assertTimestamp(value) { if (typeof value !== 'string' || !Number.isFinite(Date.parse(value)))
|
|
13
15
|
throw new Error('routing timestamp is invalid'); }
|
|
14
16
|
function canonical(value) { if (Array.isArray(value))
|
|
@@ -45,9 +47,19 @@ function reserveRoutingAttempt(state, input, now) {
|
|
|
45
47
|
throw new Error('routing implementer profile is invalid');
|
|
46
48
|
const expected = resolveLineageEscalation(next, input.lineageId, initial);
|
|
47
49
|
const actualEffort = input.envelope.resolved.effort.kind === 'explicit' ? input.envelope.resolved.effort.value : 'runtime-default';
|
|
48
|
-
|
|
50
|
+
const judgmentHighAfterIntegration = expected.profile === 'judgment' && expected.effort === 'medium' && actualEffort === 'high' && attempts.length > 0 && attempts[attempts.length - 1].envelope.effectiveProfile === 'integration';
|
|
51
|
+
if (input.envelope.effectiveProfile !== expected.profile || (actualEffort !== expected.effort && !judgmentHighAfterIntegration))
|
|
49
52
|
throw new Error('routing effective escalation mismatch');
|
|
50
53
|
}
|
|
54
|
+
const approval = input.approval?.();
|
|
55
|
+
if (!approval)
|
|
56
|
+
throw new Error('routing reservation requires current approval');
|
|
57
|
+
const selectionInput = { role: input.envelope.role, requestedProfile: input.envelope.role === 'implementer' ? input.envelope.effectiveProfile : 'full', runtime: (0, capabilities_1.validateRuntimeKey)(input.envelope.runtime), policy: approval.policy, capabilities: approval.capabilities, now: approval.checkedAt };
|
|
58
|
+
const resolved = input.envelope.role === 'implementer' && input.envelope.effectiveProfile === 'judgment' && input.envelope.resolved.effort.kind === 'explicit' && input.envelope.resolved.effort.value === 'high'
|
|
59
|
+
? (0, resolve_1.resolveEscalatedSelection)({ ...selectionInput, role: 'implementer', requestedProfile: 'judgment', expectedEffort: 'high' })
|
|
60
|
+
: (0, resolve_1.resolveSelection)(selectionInput);
|
|
61
|
+
if (resolved.state !== 'resolved' || resolved.effectiveProfile !== input.envelope.effectiveProfile || canonical(resolved.selection) !== canonical(input.envelope.resolved) || resolved.policyDigest !== input.envelope.policyDigest || resolved.capabilityDigest !== input.envelope.capabilityDigest || resolved.outcome !== input.envelope.outcome || canonical(resolved.unavailableEvidence) !== canonical(input.envelope.unavailableEvidence))
|
|
62
|
+
throw new Error('routing reservation approval mismatch');
|
|
51
63
|
const attempt = attempts.length + 1;
|
|
52
64
|
const id = `route-${crypto_1.default.createHash('sha256').update(`${input.lineageId}\0${attempt}\0${envelopeDigest}\0${input.fingerprint}`).digest('hex').slice(0, 24)}`;
|
|
53
65
|
next.routingAttempts.push({ schema: 'routing-attempt/v1', id, obligationId: input.obligationId, lineageId: input.lineageId, attempt, envelope: structuredClone(input.envelope), envelopeDigest, fingerprint: input.fingerprint, state: 'reserved' });
|
|
@@ -88,8 +100,10 @@ function resolveLineageEscalation(state, lineageId, initial) {
|
|
|
88
100
|
const attempts = (state.routingAttempts ?? []).filter((attempt) => attempt.lineageId === lineageId && attempt.envelope.role === 'implementer').sort((left, right) => left.attempt - right.attempt);
|
|
89
101
|
if (attempts.some((attempt) => ['reserved', 'active', 'unknown'].includes(attempt.state)))
|
|
90
102
|
throw new Error('routing lineage has a live or unknown attempt');
|
|
91
|
-
if (attempts.length === 0)
|
|
92
|
-
|
|
103
|
+
if (attempts.length === 0) {
|
|
104
|
+
const lineage = state.implementationLineages?.find(candidate => candidate.id === lineageId);
|
|
105
|
+
return { profile: initial, effort: lineage?.initialEffort ?? 'medium' };
|
|
106
|
+
}
|
|
93
107
|
const last = attempts[attempts.length - 1];
|
|
94
108
|
if (last.verdict !== 'fail')
|
|
95
109
|
throw new Error('routing lineage advances only after a terminal failed verdict');
|
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveEscalatedSelection = resolveEscalatedSelection;
|
|
3
4
|
exports.resolveDispatch = resolveDispatch;
|
|
4
5
|
exports.resolveV1Dispatch = resolveV1Dispatch;
|
|
5
6
|
exports.resolveSelection = resolveSelection;
|
|
6
7
|
const capabilities_1 = require("./capabilities");
|
|
7
8
|
const validate_1 = require("./validate");
|
|
8
9
|
const validate_2 = require("../plan/validate");
|
|
10
|
+
function resolveEscalatedSelection(input) {
|
|
11
|
+
if (!input || input.role !== 'implementer' || !['medium', 'high'].includes(input.expectedEffort))
|
|
12
|
+
throw new Error('escalated selection requires an implementer and a supported effort');
|
|
13
|
+
const selected = resolveSelection(input);
|
|
14
|
+
if (selected.state === 'blocked')
|
|
15
|
+
return selected;
|
|
16
|
+
const effort = selected.selection.effort;
|
|
17
|
+
if (input.requestedProfile !== 'judgment')
|
|
18
|
+
return effort.kind === 'explicit' && effort.value === input.expectedEffort ? selected : blocked('ROUTING_ESCALATION_EFFORT_UNAVAILABLE', 'The approved selected effort does not match the next lineage escalation.');
|
|
19
|
+
if (effort.kind === 'explicit' && effort.value === 'medium' && input.expectedEffort === 'medium')
|
|
20
|
+
return selected;
|
|
21
|
+
const full = resolveSelection({ ...input, role: 'code-quality-reviewer', requestedProfile: 'full' });
|
|
22
|
+
if (full.state === 'blocked')
|
|
23
|
+
return full;
|
|
24
|
+
const sameModel = full.selection.selector.kind === selected.selection.selector.kind && full.selection.selector.id === selected.selection.selector.id;
|
|
25
|
+
if (!sameModel || full.selection.effort.kind !== 'explicit' || full.selection.effort.value !== 'high')
|
|
26
|
+
return blocked('ROUTING_ESCALATION_EFFORT_UNAVAILABLE', 'Judgment high requires the same approved full-capability model at explicit high effort.');
|
|
27
|
+
if (effort.kind === 'explicit' && effort.value === 'high')
|
|
28
|
+
return selected;
|
|
29
|
+
if (effort.kind === 'explicit' && effort.value === 'medium' && input.expectedEffort === 'high')
|
|
30
|
+
return { ...full, effectiveProfile: 'judgment' };
|
|
31
|
+
return blocked('ROUTING_ESCALATION_EFFORT_UNAVAILABLE', 'The approved selected effort does not match the next lineage escalation.');
|
|
32
|
+
}
|
|
9
33
|
/** Resolve only from the immutable validator report; a reopened plan may never
|
|
10
34
|
* provide a routing profile after validation. */
|
|
11
35
|
function resolveDispatch(input) {
|
|
@@ -11,7 +11,8 @@ const commander_1 = require("commander");
|
|
|
11
11
|
const job_1 = require("../../../src/commands/job");
|
|
12
12
|
const store_1 = require("../../../src/core/journal/store");
|
|
13
13
|
const journal_1 = require("../../../src/core/model-policy/journal");
|
|
14
|
-
const
|
|
14
|
+
const capabilities_1 = require("../../../src/core/model-policy/capabilities");
|
|
15
|
+
const routing_approval_1 = require("../../helpers/routing-approval");
|
|
15
16
|
function gitInit(repo) {
|
|
16
17
|
(0, child_process_1.execFileSync)('git', ['-c', 'user.email=t@t.t', '-c', 'user.name=t', 'init', '-q', '-b', 'main'], { cwd: repo });
|
|
17
18
|
fs_1.default.writeFileSync(path_1.default.join(repo, 'fixture'), 'x');
|
|
@@ -24,7 +25,12 @@ test('`job routing-report --json` emits only aggregate routing evidence', async
|
|
|
24
25
|
gitInit(repo);
|
|
25
26
|
(0, store_1.initJournal)(repo, 'main');
|
|
26
27
|
const state = (0, store_1.readJournal)(repo, 'main').state;
|
|
27
|
-
const
|
|
28
|
+
const approved = (0, routing_approval_1.routingApproval)();
|
|
29
|
+
const privateSelection = { ...routing_approval_1.routingEnvelope.resolved, selector: { kind: 'model', id: 'model-private' } };
|
|
30
|
+
approved.policy.content.mappings[0].profiles.mechanical = privateSelection;
|
|
31
|
+
approved.capabilities.availableSelections.push(privateSelection);
|
|
32
|
+
const envelope = { ...routing_approval_1.routingEnvelope, resolved: privateSelection, capabilityDigest: (0, capabilities_1.capabilityReceiptDigest)(approved.capabilities) };
|
|
33
|
+
const reserved = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'obligation', lineageId: 'lineage', envelope, fingerprint: 'e'.repeat(64), approval: () => approved }, '2026-09-17T00:00:00.000Z');
|
|
28
34
|
(0, store_1.writeJournal)(repo, 'main', (0, journal_1.observeRoutingAttempt)(reserved.state, { attemptId: reserved.attemptId, nativeAgentId: 'native-private' }, '2026-09-17T00:01:00.000Z'));
|
|
29
35
|
const program = new commander_1.Command();
|
|
30
36
|
program.exitOverride();
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const types_1 = require("../../../src/core/journal/types");
|
|
4
4
|
const journal_1 = require("../../../src/core/model-policy/journal");
|
|
5
|
-
const
|
|
5
|
+
const routing_approval_1 = require("../../helpers/routing-approval");
|
|
6
6
|
test('routing report remains read-only across an observed attempt', () => {
|
|
7
|
-
const reserved = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'o1', lineageId: 'l1', envelope, fingerprint: 'e'.repeat(64) }, '2026-09-17T00:00:00.000Z');
|
|
7
|
+
const reserved = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'o1', lineageId: 'l1', envelope: routing_approval_1.routingEnvelope, fingerprint: 'e'.repeat(64), approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z');
|
|
8
8
|
const observed = (0, journal_1.observeRoutingAttempt)(reserved.state, { attemptId: reserved.attemptId, nativeAgentId: 'native-id' }, '2026-09-17T00:01:00.000Z');
|
|
9
9
|
expect((0, journal_1.routingReport)(observed)).toMatchObject({ attempts: 1, byState: { active: 1 } });
|
|
10
10
|
expect(observed.routingAttempts[0].nativeAgentId).toBe('native-id');
|
|
@@ -84,7 +84,7 @@ describe('plan validate Commander wiring', () => {
|
|
|
84
84
|
// not come out of validatePlanFile, so a spread-and-relabel fixture
|
|
85
85
|
// cannot reach this path at all.
|
|
86
86
|
const sliceId = 'S1';
|
|
87
|
-
const sel = { selector: { kind: 'model', id: 'gpt-5.6-luna' }, effort: { kind: 'explicit', value: '
|
|
87
|
+
const sel = { selector: { kind: 'model', id: 'gpt-5.6-luna' }, effort: { kind: 'explicit', value: 'high' } };
|
|
88
88
|
const full = { selector: { kind: 'model', id: 'gpt-5.6-sol' }, effort: { kind: 'explicit', value: 'high' } };
|
|
89
89
|
const sha = 'a'.repeat(64);
|
|
90
90
|
const content = { schema: 'model-policy/v1', mappings: [{ target: 'codex', runtimeKind: 'native', profiles: { mechanical: sel, integration: sel, judgment: sel }, fullCapability: full, degradation: { allowMissingModelOverride: false, allowMissingEffortOverride: false, allowMissingObservedIdentity: false } }], implementationBudget: { maxAttempts: 3, escalation: ['mechanical', 'integration', 'judgment'], judgmentEfforts: ['medium', 'high'] } };
|
|
@@ -115,7 +115,7 @@ describe('plan validate Commander wiring', () => {
|
|
|
115
115
|
expect(emitted.envelope.executionDigest).toBe(v2Valid.executionDigest);
|
|
116
116
|
// The point of the whole thing: that envelope reserves a first attempt,
|
|
117
117
|
// which is what creates the lineage the escalation path later needs.
|
|
118
|
-
const reserved = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'o1', lineageId: 'l1', envelope: emitted.envelope, fingerprint: 'e'.repeat(64) }, '2026-09-19T00:00:00.000Z');
|
|
118
|
+
const reserved = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'o1', lineageId: 'l1', envelope: emitted.envelope, fingerprint: 'e'.repeat(64), approval: () => ({ policy: readEffectivePolicy().policy, capabilities: receipt, checkedAt: new Date() }) }, '2026-09-19T00:00:00.000Z');
|
|
119
119
|
expect(reserved.attemptId).toEqual(expect.any(String));
|
|
120
120
|
expect(reserved.state.implementationLineages).toEqual([expect.objectContaining({ id: 'l1', sliceId, initialProfile: 'mechanical' })]);
|
|
121
121
|
});
|
|
@@ -47,6 +47,9 @@ const store_1 = require("../../../src/core/journal/store");
|
|
|
47
47
|
const paths_1 = require("../../../src/core/journal/paths");
|
|
48
48
|
const atomicFile = __importStar(require("../../../src/core/atomic-file"));
|
|
49
49
|
const gate_1 = require("../../../src/commands/job/gate");
|
|
50
|
+
const canonical_1 = require("../../../src/core/model-policy/canonical");
|
|
51
|
+
const capabilities_1 = require("../../../src/core/model-policy/capabilities");
|
|
52
|
+
const routing_approval_1 = require("../../helpers/routing-approval");
|
|
50
53
|
function jobPayload(argv) {
|
|
51
54
|
return { argv, paths: [], cwd: '.', fingerprint: 'fp-1', commandDigest: 'cd-1', expandedPaths: [] };
|
|
52
55
|
}
|
|
@@ -195,16 +198,35 @@ describe('aplicacion transaccional de requests', () => {
|
|
|
195
198
|
expect(s.controllerHeartbeatAt).toBeUndefined();
|
|
196
199
|
});
|
|
197
200
|
test('routing reserve/observe es supervisado, idempotente y una generacion vieja no muta intentos', () => {
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
const priorHome = process.env.AWM_HOME;
|
|
202
|
+
process.env.AWM_HOME = path_1.default.join(repo, 'operator');
|
|
203
|
+
try {
|
|
204
|
+
const approved = (0, routing_approval_1.routingApproval)();
|
|
205
|
+
approved.policy.contentDigest = (0, canonical_1.canonicalPolicyDigest)(approved.policy.content);
|
|
206
|
+
approved.capabilities.recordedAt = new Date(Date.now() - 60_000).toISOString();
|
|
207
|
+
approved.capabilities.expiresAt = new Date(Date.now() + 3_600_000).toISOString();
|
|
208
|
+
const envelope = { ...routing_approval_1.routingEnvelope, policyDigest: approved.policy.contentDigest, capabilityDigest: (0, capabilities_1.capabilityReceiptDigest)(approved.capabilities) };
|
|
209
|
+
fs_1.default.mkdirSync(path_1.default.join(repo, '.awm'), { recursive: true });
|
|
210
|
+
fs_1.default.writeFileSync(path_1.default.join(repo, '.awm', 'model-policy.json'), JSON.stringify(approved.policy));
|
|
211
|
+
const receiptPath = path_1.default.join(process.env.AWM_HOME, 'routing-capabilities', 'codex', 'native.json');
|
|
212
|
+
fs_1.default.mkdirSync(path_1.default.dirname(receiptPath), { recursive: true });
|
|
213
|
+
fs_1.default.writeFileSync(receiptPath, JSON.stringify(approved.capabilities));
|
|
214
|
+
(0, requests_1.emitRequest)(repo, 'rama', { kind: 'routing-reserve', generationToken: 'g1', idempotencyKey: 'routing-1', payload: { obligationId: 'o1', lineageId: 'l1', envelope, fingerprint: 'e'.repeat(64) } });
|
|
215
|
+
expect((0, apply_1.consumePendingRequests)(repo, 'rama', 'g1').applied).toBe(1);
|
|
216
|
+
const attempt = (0, store_1.readJournal)(repo, 'rama').state.routingAttempts[0];
|
|
217
|
+
(0, requests_1.emitRequest)(repo, 'rama', { kind: 'routing-observe', generationToken: 'g1', idempotencyKey: 'routing-2', payload: { attemptId: attempt.id, nativeAgentId: 'native-1' } });
|
|
218
|
+
(0, apply_1.consumePendingRequests)(repo, 'rama', 'g1');
|
|
219
|
+
expect((0, store_1.readJournal)(repo, 'rama').state.routingAttempts[0]).toMatchObject({ state: 'active', nativeAgentId: 'native-1' });
|
|
220
|
+
(0, requests_1.emitRequest)(repo, 'rama', { kind: 'routing-reserve', generationToken: 'old', idempotencyKey: 'routing-old', payload: { obligationId: 'o1', lineageId: 'l2', envelope, fingerprint: 'f'.repeat(64) } });
|
|
221
|
+
expect((0, apply_1.consumePendingRequests)(repo, 'rama', 'g1').rejectedStale).toBe(1);
|
|
222
|
+
expect((0, store_1.readJournal)(repo, 'rama').state.routingAttempts).toHaveLength(1);
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
if (priorHome === undefined)
|
|
226
|
+
delete process.env.AWM_HOME;
|
|
227
|
+
else
|
|
228
|
+
process.env.AWM_HOME = priorHome;
|
|
229
|
+
}
|
|
208
230
|
});
|
|
209
231
|
test('request corrupta se aparta VISIBLE como .corrupt, jamas se descarta (R1.6)', () => {
|
|
210
232
|
fs_1.default.writeFileSync(path_1.default.join((0, paths_1.requestsDir)(repo, 'rama'), 'req-roto.json'), '{no-json');
|
|
@@ -2,45 +2,87 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const types_1 = require("../../../src/core/journal/types");
|
|
4
4
|
const journal_1 = require("../../../src/core/model-policy/journal");
|
|
5
|
-
const
|
|
5
|
+
const capabilities_1 = require("../../../src/core/model-policy/capabilities");
|
|
6
|
+
const routing_approval_1 = require("../../helpers/routing-approval");
|
|
6
7
|
describe('routing journal helpers', () => {
|
|
7
8
|
it('reserves one idempotent attempt and records native observation', () => {
|
|
8
9
|
const state = (0, types_1.emptyState)('main');
|
|
9
|
-
const reserved = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope, fingerprint: 'e'.repeat(64) }, '2026-09-17T00:00:00.000Z');
|
|
10
|
-
const replay = (0, journal_1.reserveRoutingAttempt)(reserved.state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope, fingerprint: 'e'.repeat(64) }, '2026-09-17T00:01:00.000Z');
|
|
10
|
+
const reserved = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: routing_approval_1.routingEnvelope, fingerprint: 'e'.repeat(64), approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z');
|
|
11
|
+
const replay = (0, journal_1.reserveRoutingAttempt)(reserved.state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: routing_approval_1.routingEnvelope, fingerprint: 'e'.repeat(64) }, '2026-09-17T00:01:00.000Z');
|
|
11
12
|
expect(replay.attemptId).toBe(reserved.attemptId);
|
|
12
13
|
const observed = (0, journal_1.observeRoutingAttempt)(replay.state, { attemptId: reserved.attemptId, nativeAgentId: 'native-1' }, '2026-09-17T00:02:00.000Z');
|
|
13
14
|
expect(observed.routingAttempts?.[0]).toMatchObject({ state: 'active', nativeAgentId: 'native-1' });
|
|
14
15
|
});
|
|
16
|
+
it('reserves an initial mechanical attempt at its approved explicit high effort', () => {
|
|
17
|
+
const high = { ...routing_approval_1.routingEnvelope, resolved: { ...routing_approval_1.routingEnvelope.resolved, effort: { kind: 'explicit', value: 'high' } } };
|
|
18
|
+
expect(() => (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: high, fingerprint: 'e'.repeat(64) }, '2026-09-17T00:00:00.000Z')).toThrow(/approval/i);
|
|
19
|
+
const approved = (0, routing_approval_1.routingApproval)();
|
|
20
|
+
approved.policy.content.mappings[0].profiles.mechanical = (0, routing_approval_1.routingSelection)('high');
|
|
21
|
+
const reserved = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: high, fingerprint: 'e'.repeat(64), approval: () => approved }, '2026-09-17T00:00:00.000Z');
|
|
22
|
+
expect(reserved.state.implementationLineages?.[0].initialEffort).toBe('high');
|
|
23
|
+
});
|
|
24
|
+
it('reserves the approved high-effort judgment profile after a failed integration attempt', () => {
|
|
25
|
+
const integration = { ...routing_approval_1.routingEnvelope, requestedProfile: 'integration', effectiveProfile: 'integration' };
|
|
26
|
+
const first = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: integration, fingerprint: 'e'.repeat(64), approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z').state;
|
|
27
|
+
first.routingAttempts[0].state = 'blocked';
|
|
28
|
+
first.routingAttempts[0].verdict = 'fail';
|
|
29
|
+
const judgment = { ...integration, effectiveProfile: 'judgment', resolved: { ...integration.resolved, effort: { kind: 'explicit', value: 'high' } } };
|
|
30
|
+
const approved = (0, routing_approval_1.routingApproval)();
|
|
31
|
+
const second = (0, journal_1.reserveRoutingAttempt)(first, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: { ...judgment, capabilityDigest: (0, capabilities_1.capabilityReceiptDigest)(approved.capabilities) }, fingerprint: 'f'.repeat(64), approval: () => approved }, '2026-09-17T00:01:00.000Z').state;
|
|
32
|
+
expect(second.routingAttempts?.[1].envelope.resolved).toEqual(judgment.resolved);
|
|
33
|
+
});
|
|
34
|
+
it('rejects judgment high without current matching approval at reservation', () => {
|
|
35
|
+
const integration = { ...routing_approval_1.routingEnvelope, requestedProfile: 'integration', effectiveProfile: 'integration' };
|
|
36
|
+
const first = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: integration, fingerprint: 'e'.repeat(64), approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z').state;
|
|
37
|
+
first.routingAttempts[0].state = 'blocked';
|
|
38
|
+
first.routingAttempts[0].verdict = 'fail';
|
|
39
|
+
const high = { ...integration, effectiveProfile: 'judgment', resolved: (0, routing_approval_1.routingSelection)('high') };
|
|
40
|
+
const input = { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: high, fingerprint: 'f'.repeat(64) };
|
|
41
|
+
expect(() => (0, journal_1.reserveRoutingAttempt)(first, input, '2026-09-17T00:01:00.000Z')).toThrow(/approval/i);
|
|
42
|
+
const approved = (0, routing_approval_1.routingApproval)();
|
|
43
|
+
expect(() => (0, journal_1.reserveRoutingAttempt)(first, { ...input, envelope: { ...high, capabilityDigest: 'b'.repeat(64) }, approval: () => approved }, '2026-09-17T00:01:00.000Z')).toThrow(/approval/i);
|
|
44
|
+
const stale = { ...approved, checkedAt: new Date('2026-09-19T00:00:00.000Z') };
|
|
45
|
+
expect(() => (0, journal_1.reserveRoutingAttempt)(first, { ...input, envelope: { ...high, capabilityDigest: (0, capabilities_1.capabilityReceiptDigest)(approved.capabilities) }, approval: () => stale }, '2026-09-17T00:01:00.000Z')).toThrow(/approval/i);
|
|
46
|
+
});
|
|
47
|
+
it('reserves judgment high after a failed judgment medium attempt without resetting the lineage', () => {
|
|
48
|
+
const judgment = { ...routing_approval_1.routingEnvelope, requestedProfile: 'judgment', effectiveProfile: 'judgment' };
|
|
49
|
+
const first = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: judgment, fingerprint: 'e'.repeat(64), approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z').state;
|
|
50
|
+
first.routingAttempts[0].state = 'blocked';
|
|
51
|
+
first.routingAttempts[0].verdict = 'fail';
|
|
52
|
+
const high = { ...judgment, resolved: { ...judgment.resolved, effort: { kind: 'explicit', value: 'high' } } };
|
|
53
|
+
const approved = (0, routing_approval_1.routingApproval)();
|
|
54
|
+
const second = (0, journal_1.reserveRoutingAttempt)(first, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: { ...high, capabilityDigest: (0, capabilities_1.capabilityReceiptDigest)(approved.capabilities) }, fingerprint: 'f'.repeat(64), approval: () => approved }, '2026-09-17T00:01:00.000Z').state;
|
|
55
|
+
expect(second.routingAttempts?.[1]).toMatchObject({ attempt: 2, envelope: { effectiveProfile: 'judgment', resolved: high.resolved } });
|
|
56
|
+
});
|
|
15
57
|
it('rejects a fourth implementer attempt in one lineage', () => {
|
|
16
58
|
let state = (0, types_1.emptyState)('main');
|
|
17
59
|
for (const [index, profile] of ['mechanical', 'integration', 'judgment'].entries()) {
|
|
18
|
-
state = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: { ...
|
|
60
|
+
state = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: { ...routing_approval_1.routingEnvelope, effectiveProfile: profile }, fingerprint: `${'a'.repeat(63)}${index}`, approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z').state;
|
|
19
61
|
state.routingAttempts[state.routingAttempts.length - 1].state = 'blocked';
|
|
20
62
|
state.routingAttempts[state.routingAttempts.length - 1].verdict = 'fail';
|
|
21
63
|
}
|
|
22
|
-
expect(() => (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope, fingerprint: 'f'.repeat(64) }, '2026-09-17T00:00:00.000Z')).toThrow(/budget/i);
|
|
64
|
+
expect(() => (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: routing_approval_1.routingEnvelope, fingerprint: 'f'.repeat(64) }, '2026-09-17T00:00:00.000Z')).toThrow(/budget/i);
|
|
23
65
|
});
|
|
24
66
|
it('reports routing attempts without envelope bodies or native identities', () => {
|
|
25
|
-
const state = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope, fingerprint: 'e'.repeat(64) }, '2026-09-17T00:00:00.000Z').state;
|
|
67
|
+
const state = (0, journal_1.reserveRoutingAttempt)((0, types_1.emptyState)('main'), { obligationId: 'impl:S1', lineageId: 'lineage:S1', envelope: routing_approval_1.routingEnvelope, fingerprint: 'e'.repeat(64), approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z').state;
|
|
26
68
|
expect((0, journal_1.routingReport)(state)).toEqual({ schema: 'routing-report/v1', attempts: 1, plannedByRole: { implementer: 1 }, actualByRole: {}, byState: { reserved: 1 }, retries: 0, fallbacks: 0, unavailable: {}, verdicts: {}, administrativeRepairs: 0 });
|
|
27
69
|
});
|
|
28
70
|
it('uses the exact deterministic implementation escalation sequence', () => {
|
|
29
71
|
let state = (0, types_1.emptyState)('main');
|
|
30
72
|
expect((0, journal_1.resolveLineageEscalation)(state, 'l1', 'mechanical')).toEqual({ profile: 'mechanical', effort: 'medium' });
|
|
31
|
-
state = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'l1', envelope, fingerprint: '1'.repeat(64) }, '2026-09-17T00:00:00.000Z').state;
|
|
73
|
+
state = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'impl:S1', lineageId: 'l1', envelope: routing_approval_1.routingEnvelope, fingerprint: '1'.repeat(64), approval: routing_approval_1.routingApproval }, '2026-09-17T00:00:00.000Z').state;
|
|
32
74
|
state.routingAttempts[0].state = 'blocked';
|
|
33
75
|
state.routingAttempts[0].verdict = 'fail';
|
|
34
76
|
expect((0, journal_1.resolveLineageEscalation)(state, 'l1', 'mechanical')).toEqual({ profile: 'integration', effort: 'medium' });
|
|
35
|
-
state.routingAttempts.push({ ...state.routingAttempts[0], id: 'route-2', attempt: 2, envelope: { ...
|
|
77
|
+
state.routingAttempts.push({ ...state.routingAttempts[0], id: 'route-2', attempt: 2, envelope: { ...routing_approval_1.routingEnvelope, effectiveProfile: 'integration' }, state: 'blocked', verdict: 'fail' });
|
|
36
78
|
expect((0, journal_1.resolveLineageEscalation)(state, 'l1', 'mechanical')).toEqual({ profile: 'judgment', effort: 'medium' });
|
|
37
|
-
state.routingAttempts.push({ ...state.routingAttempts[0], id: 'route-3', attempt: 3, envelope: { ...
|
|
79
|
+
state.routingAttempts.push({ ...state.routingAttempts[0], id: 'route-3', attempt: 3, envelope: { ...routing_approval_1.routingEnvelope, effectiveProfile: 'judgment', resolved: { selector: { kind: 'model', id: 'm' }, effort: { kind: 'explicit', value: 'medium' } } }, state: 'blocked', verdict: 'fail' });
|
|
38
80
|
expect((0, journal_1.resolveLineageEscalation)(state, 'l1', 'mechanical')).toEqual({ profile: 'judgment', effort: 'high' });
|
|
39
81
|
state.routingAttempts[2].envelope = { ...state.routingAttempts[2].envelope, resolved: { selector: { kind: 'model', id: 'm' }, effort: { kind: 'explicit', value: 'high' } } };
|
|
40
82
|
expect(() => (0, journal_1.resolveLineageEscalation)(state, 'l1', 'mechanical')).toThrow(/exhausted/i);
|
|
41
83
|
});
|
|
42
84
|
it('rejects hostile roles and unavailable provenance before it can reach a report', () => {
|
|
43
|
-
expect((0, types_1.isRoutingEnvelope)({ ...
|
|
44
|
-
expect((0, types_1.isRoutingEnvelope)({ ...
|
|
85
|
+
expect((0, types_1.isRoutingEnvelope)({ ...routing_approval_1.routingEnvelope, role: 'attacker-key' })).toBe(false);
|
|
86
|
+
expect((0, types_1.isRoutingEnvelope)({ ...routing_approval_1.routingEnvelope, unavailableEvidence: ['secret=leak'] })).toBe(false);
|
|
45
87
|
});
|
|
46
88
|
});
|
|
@@ -183,3 +183,20 @@ describe('resolveSelection', () => {
|
|
|
183
183
|
expect((0, resolve_1.resolveSelection)(value)).toMatchObject({ state: 'resolved', outcome: 'degraded', selection: runtimeDefaultSelection('full'), unavailableEvidence: ['modelOverride'] });
|
|
184
184
|
});
|
|
185
185
|
});
|
|
186
|
+
describe('resolveEscalatedSelection', () => {
|
|
187
|
+
it('accepts the approved judgment high profile after integration when full capability matches', () => {
|
|
188
|
+
const value = input();
|
|
189
|
+
value.policy.content.mappings[0].profiles.judgment = selection('full', 'high');
|
|
190
|
+
expect((0, resolve_1.resolveEscalatedSelection)({ ...value, requestedProfile: 'judgment', expectedEffort: 'medium' })).toMatchObject({ state: 'resolved', effectiveProfile: 'judgment', selection: selection('full', 'high') });
|
|
191
|
+
});
|
|
192
|
+
it('promotes judgment medium to the attested full high selection on its last correction', () => {
|
|
193
|
+
const value = input();
|
|
194
|
+
value.policy.content.mappings[0].profiles.judgment = selection('full', 'medium');
|
|
195
|
+
value.capabilities.availableSelections.push(selection('full', 'medium'));
|
|
196
|
+
expect((0, resolve_1.resolveEscalatedSelection)({ ...value, requestedProfile: 'judgment', expectedEffort: 'high' })).toMatchObject({ state: 'resolved', effectiveProfile: 'judgment', selection: selection('full', 'high') });
|
|
197
|
+
});
|
|
198
|
+
it('blocks judgment high escalation when the full selection uses another model', () => {
|
|
199
|
+
const value = input();
|
|
200
|
+
expect((0, resolve_1.resolveEscalatedSelection)({ ...value, requestedProfile: 'judgment', expectedEffort: 'high' })).toMatchObject({ state: 'blocked', diagnostics: [{ code: 'ROUTING_ESCALATION_EFFORT_UNAVAILABLE' }] });
|
|
201
|
+
});
|
|
202
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.routingEnvelope = exports.routingSelection = exports.routingRuntime = void 0;
|
|
4
|
+
exports.routingApproval = routingApproval;
|
|
5
|
+
const capabilities_1 = require("../../src/core/model-policy/capabilities");
|
|
6
|
+
exports.routingRuntime = { target: 'codex', kind: 'native', version: '1.0.0', accountScopeDigest: '0'.repeat(64) };
|
|
7
|
+
const routingSelection = (value) => ({ selector: { kind: 'model', id: 'm' }, effort: { kind: 'explicit', value } });
|
|
8
|
+
exports.routingSelection = routingSelection;
|
|
9
|
+
function routingApproval() {
|
|
10
|
+
const policy = { schema: 'approved-model-policy/v1', content: { schema: 'model-policy/v1', mappings: [{ target: 'codex', runtimeKind: 'native', profiles: { mechanical: (0, exports.routingSelection)('medium'), integration: (0, exports.routingSelection)('medium'), judgment: (0, exports.routingSelection)('medium') }, fullCapability: (0, exports.routingSelection)('high'), degradation: { allowMissingModelOverride: false, allowMissingEffortOverride: false, allowMissingObservedIdentity: false } }], implementationBudget: { maxAttempts: 3, escalation: ['mechanical', 'integration', 'judgment'], judgmentEfforts: ['medium', 'high'] } }, contentDigest: 'a'.repeat(64), approval: { approvedAt: '2026-09-17T00:00:00.000Z', approvalId: 'approval-1' }, lineage: { previousDigest: null } };
|
|
11
|
+
const capabilities = { schema: 'routing-capabilities/v1', runtime: exports.routingRuntime, recordedAt: '2026-09-17T00:00:00.000Z', expiresAt: '2026-09-18T00:00:00.000Z', capabilities: { artifactDelivery: 'unverified', interactiveExecution: 'supported', unattendedController: 'supported', nativeSubagents: 'unverified', modelOverride: 'supported', effortOverride: 'supported', observedModelEvidence: 'supported', durableResume: 'unverified' }, availableSelections: [(0, exports.routingSelection)('medium'), (0, exports.routingSelection)('high')], evidence: ['interactiveExecution', 'unattendedController', 'modelOverride', 'effortOverride', 'observedModelEvidence'].map(capability => ({ capability, kind: 'native-control', receiptDigest: 'a'.repeat(64) })), approval: { approvalId: 'approval-1', snapshotDigest: 'a'.repeat(64) } };
|
|
12
|
+
return { policy, capabilities, checkedAt: new Date('2026-09-17T12:00:00.000Z') };
|
|
13
|
+
}
|
|
14
|
+
exports.routingEnvelope = { schema: 'routing-envelope/v1', runtime: exports.routingRuntime, role: 'implementer', sliceId: 'S1', requestedProfile: 'mechanical', effectiveProfile: 'mechanical', resolved: (0, exports.routingSelection)('medium'), outcome: 'native', unavailableEvidence: [], policyDigest: 'a'.repeat(64), capabilityDigest: (0, capabilities_1.capabilityReceiptDigest)(routingApproval().capabilities), planDigest: 'c'.repeat(64), executionDigest: 'd'.repeat(64) };
|
|
@@ -8,21 +8,90 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const CLI_ROOT = path_1.default.resolve(__dirname, '..', '..');
|
|
10
10
|
const REPO_ROOT = path_1.default.resolve(CLI_ROOT, '..');
|
|
11
|
+
function readWorkflow(name) {
|
|
12
|
+
return fs_1.default.readFileSync(path_1.default.join(REPO_ROOT, '.github', 'workflows', name), 'utf8').replace(/\r\n/g, '\n');
|
|
13
|
+
}
|
|
14
|
+
function assertArmPartition(source) {
|
|
15
|
+
const workflow = source.replace(/\r\n/g, '\n');
|
|
16
|
+
expect(workflow.match(/^ windows-arm-hot:\s*$/gm)).toHaveLength(1);
|
|
17
|
+
const [matrixJob, rest] = workflow.split(/^ windows-arm-hot:\s*$/m);
|
|
18
|
+
expect(rest).toBeDefined();
|
|
19
|
+
const hotJob = rest.split(/^ [a-z][\w-]*:\s*$/m)[0];
|
|
20
|
+
expect(matrixJob).toMatch(/- name: Tests?\n if: matrix\.target != 'win32-arm64'\n working-directory: cli\n run: npx jest --runInBand --bail\n/);
|
|
21
|
+
const remainder = matrixJob.match(/- name: Tests? \(Windows ARM remainder\)\n if: matrix\.target == 'win32-arm64'\n working-directory: cli\n run: ([^\n]+)/)?.[1];
|
|
22
|
+
expect(remainder).toMatch(/^npx jest --runInBand --bail --testPathIgnorePatterns='[^']+'$/);
|
|
23
|
+
const ignorePattern = remainder?.match(/--testPathIgnorePatterns='([^']+)'/)?.[1];
|
|
24
|
+
expect(ignorePattern).toBe(String.raw `node_modules|[/\\]cli[/\\]tests[/\\]commands[/\\]watch[/\\]track-(finalize|freeze)\.test\.ts$`);
|
|
25
|
+
const ignored = new RegExp(ignorePattern);
|
|
26
|
+
for (const separator of ['/', '\\']) {
|
|
27
|
+
const root = ['repo', 'cli', 'tests'].join(separator);
|
|
28
|
+
for (const suite of ['track-finalize', 'track-freeze']) {
|
|
29
|
+
expect(ignored.test([root, 'commands', 'watch', `${suite}.test.ts`].join(separator))).toBe(true);
|
|
30
|
+
expect(ignored.test([root, 'other', `${suite}.test.ts`].join(separator))).toBe(false);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const remainderStep = matrixJob.split(/- name: Tests? \(Windows ARM remainder\)\n/)[1]?.split(/^ - name:/m)[0];
|
|
34
|
+
expect(remainderStep).toBeDefined();
|
|
35
|
+
expect(remainderStep).not.toContain('continue-on-error: true');
|
|
36
|
+
expect(matrixJob.match(/uses: actions\/upload-artifact@v4/g)).toHaveLength(1);
|
|
37
|
+
expect(hotJob).toContain('runs-on: windows-11-arm');
|
|
38
|
+
expect(hotJob).toContain('run: npm run native:build');
|
|
39
|
+
expect(hotJob).toContain('run: npm run native:test-build');
|
|
40
|
+
expect(hotJob.split('\n')).toContain(' run: npx jest --runTestsByPath tests/commands/watch/track-finalize.test.ts tests/commands/watch/track-freeze.test.ts --runInBand --bail');
|
|
41
|
+
expect(hotJob).not.toContain('upload-artifact@v4');
|
|
42
|
+
expect(hotJob).not.toContain('secure-fs-win32-arm64');
|
|
43
|
+
expect(hotJob).not.toMatch(/^\s*if:/m);
|
|
44
|
+
expect(hotJob).not.toContain('continue-on-error: true');
|
|
45
|
+
}
|
|
11
46
|
describe('native release artifacts', () => {
|
|
12
47
|
it('runs each platform suite once without weakening publication', () => {
|
|
13
48
|
for (const name of ['ci.yml', 'release.yml']) {
|
|
14
|
-
const workflow =
|
|
49
|
+
const workflow = readWorkflow(name);
|
|
15
50
|
expect(workflow).not.toContain('- name: Windows admission smoke');
|
|
16
51
|
expect(workflow).not.toContain('run: npx jest tests/commands/plan/index.test.ts --runInBand --bail');
|
|
17
52
|
expect(workflow).toContain('run: npx jest --runInBand --bail');
|
|
18
53
|
}
|
|
19
|
-
const release =
|
|
20
|
-
expect(release).toMatch(/release:\s*\n\s*needs: test/);
|
|
54
|
+
const release = readWorkflow('release.yml');
|
|
55
|
+
expect(release).toMatch(/release:\s*\n\s*needs: \[test, windows-arm-hot\]/);
|
|
21
56
|
for (const target of ['linux-x64', 'linux-arm64', 'darwin-x64', 'darwin-arm64', 'win32-x64', 'win32-arm64']) {
|
|
22
57
|
expect(release).toContain(`target: ${target}`);
|
|
23
58
|
}
|
|
24
59
|
expect(release).toContain('cancel-in-progress: false');
|
|
25
60
|
});
|
|
61
|
+
it('partitions the two hot ARM suites without duplicating the native artifact', () => {
|
|
62
|
+
for (const name of ['ci.yml', 'release.yml']) {
|
|
63
|
+
const workflow = readWorkflow(name);
|
|
64
|
+
assertArmPartition(workflow);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
it('checks the same partition after a Windows CRLF checkout', () => {
|
|
68
|
+
for (const name of ['ci.yml', 'release.yml']) {
|
|
69
|
+
const workflow = readWorkflow(name);
|
|
70
|
+
assertArmPartition(workflow.replace(/\n/g, '\r\n'));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it('rejects swapped matrix guards, non-gating hot tests and duplicate artifacts', () => {
|
|
74
|
+
for (const name of ['ci.yml', 'release.yml']) {
|
|
75
|
+
const workflow = readWorkflow(name);
|
|
76
|
+
const swapped = workflow.replace(/if: matrix\.target (?:!=|==) 'win32-arm64'/g, (guard) => guard.includes('!=') ? "if: matrix.target == 'win32-arm64'" : "if: matrix.target != 'win32-arm64'");
|
|
77
|
+
const nonGating = workflow.replace(' windows-arm-hot:\n', ' windows-arm-hot:\n continue-on-error: true\n');
|
|
78
|
+
const duplicateArtifact = workflow.replace('uses: actions/upload-artifact@v4', 'uses: actions/upload-artifact@v4\n - uses: actions/upload-artifact@v4');
|
|
79
|
+
const broadIgnore = workflow.replace(/(--testPathIgnorePatterns='[^']+)(?=')/, '$1|runner\\.test\\.ts$');
|
|
80
|
+
const skippedHot = workflow.replace(' - name: Test hot Windows ARM suites\n', ' - name: Test hot Windows ARM suites\n if: false\n');
|
|
81
|
+
const nonGatingRemainder = workflow.replace(/(run: npx jest --runInBand --bail --testPathIgnorePatterns='[^']+'\n)/, '$1 continue-on-error: true\n');
|
|
82
|
+
const maskedHot = workflow.replace(/(run: npx jest --runTestsByPath [^\n]+ --runInBand --bail)(?=\n)/, '$1; exit 0');
|
|
83
|
+
for (const mutated of [swapped, nonGating, duplicateArtifact, broadIgnore, skippedHot, nonGatingRemainder, maskedHot]) {
|
|
84
|
+
expect(mutated).not.toBe(workflow);
|
|
85
|
+
}
|
|
86
|
+
expect(() => assertArmPartition(swapped)).toThrow();
|
|
87
|
+
expect(() => assertArmPartition(nonGating)).toThrow();
|
|
88
|
+
expect(() => assertArmPartition(duplicateArtifact)).toThrow();
|
|
89
|
+
expect(() => assertArmPartition(broadIgnore)).toThrow();
|
|
90
|
+
expect(() => assertArmPartition(skippedHot)).toThrow();
|
|
91
|
+
expect(() => assertArmPartition(nonGatingRemainder)).toThrow();
|
|
92
|
+
expect(() => assertArmPartition(maskedHot)).toThrow();
|
|
93
|
+
}
|
|
94
|
+
});
|
|
26
95
|
it('keeps native prebuilds generated instead of versioned source', () => {
|
|
27
96
|
const gitignore = fs_1.default.readFileSync(path_1.default.join(REPO_ROOT, '.gitignore'), 'utf8');
|
|
28
97
|
const tracked = (0, child_process_1.execFileSync)('git', ['ls-files', '--', 'cli/prebuilds'], {
|
|
@@ -37,7 +106,7 @@ describe('native release artifacts', () => {
|
|
|
37
106
|
const pkg = JSON.parse(fs_1.default.readFileSync(path_1.default.join(CLI_ROOT, 'package.json'), 'utf8'));
|
|
38
107
|
expect(pkg.scripts['native:test-build']).toContain('secure_fs_test');
|
|
39
108
|
for (const name of ['ci.yml', 'release.yml']) {
|
|
40
|
-
const workflow =
|
|
109
|
+
const workflow = readWorkflow(name);
|
|
41
110
|
const testBuild = workflow.indexOf('run: npm run native:test-build');
|
|
42
111
|
const jest = workflow.indexOf('run: npx jest --runInBand --bail');
|
|
43
112
|
expect(testBuild).toBeGreaterThanOrEqual(0);
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|