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.
@@ -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.resolveSelection)({ role: 'implementer', requestedProfile: next.profile, policy: policy.state === 'approved' ? policy.policy : undefined, capabilities: capabilities.state === 'current' ? capabilities.receipt : undefined, runtime, now: new Date() });
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 reserved = (0, journal_1.reserveRoutingAttempt)(s, { obligationId: p.obligationId, lineageId: p.lineageId, envelope: p.envelope, fingerprint: p.fingerprint }, p.at ?? now());
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
- if (input.envelope.effectiveProfile !== expected.profile || actualEffort !== expected.effort)
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
- return { profile: initial, effort: 'medium' };
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 envelope = { schema: 'routing-envelope/v1', runtime: { target: 'codex', kind: 'native', version: '1', accountScopeDigest: '0'.repeat(64) }, role: 'implementer', sliceId: 'S1', requestedProfile: 'mechanical', effectiveProfile: 'mechanical', resolved: { selector: { kind: 'model', id: 'model-private' }, effort: { kind: 'explicit', value: 'medium' } }, outcome: 'native', unavailableEvidence: [], policyDigest: 'a'.repeat(64), capabilityDigest: 'b'.repeat(64), planDigest: 'c'.repeat(64), executionDigest: 'd'.repeat(64) };
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 reserved = (0, journal_1.reserveRoutingAttempt)(state, { obligationId: 'obligation', lineageId: 'lineage', envelope, fingerprint: 'e'.repeat(64) }, '2026-09-17T00:00:00.000Z');
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 envelope = { schema: 'routing-envelope/v1', runtime: { target: 'codex', kind: 'native', version: '1', accountScopeDigest: '0'.repeat(64) }, role: 'implementer', sliceId: 'S1', requestedProfile: 'mechanical', effectiveProfile: 'mechanical', resolved: { selector: { kind: 'model', id: 'm' }, effort: { kind: 'explicit', value: 'medium' } }, outcome: 'native', unavailableEvidence: [], policyDigest: 'a'.repeat(64), capabilityDigest: 'b'.repeat(64), planDigest: 'c'.repeat(64), executionDigest: 'd'.repeat(64) };
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: 'medium' } };
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 envelope = { schema: 'routing-envelope/v1', runtime: { target: 'codex', kind: 'native', version: '1', accountScopeDigest: '0'.repeat(64) }, role: 'implementer', sliceId: 'S1', requestedProfile: 'mechanical', effectiveProfile: 'mechanical', resolved: { selector: { kind: 'model', id: 'm' }, effort: { kind: 'explicit', value: 'medium' } }, outcome: 'native', unavailableEvidence: [], policyDigest: 'a'.repeat(64), capabilityDigest: 'b'.repeat(64), planDigest: 'c'.repeat(64), executionDigest: 'd'.repeat(64) };
199
- (0, requests_1.emitRequest)(repo, 'rama', { kind: 'routing-reserve', generationToken: 'g1', idempotencyKey: 'routing-1', payload: { obligationId: 'o1', lineageId: 'l1', envelope, fingerprint: 'e'.repeat(64) } });
200
- (0, apply_1.consumePendingRequests)(repo, 'rama', 'g1');
201
- const attempt = (0, store_1.readJournal)(repo, 'rama').state.routingAttempts[0];
202
- (0, requests_1.emitRequest)(repo, 'rama', { kind: 'routing-observe', generationToken: 'g1', idempotencyKey: 'routing-2', payload: { attemptId: attempt.id, nativeAgentId: 'native-1' } });
203
- (0, apply_1.consumePendingRequests)(repo, 'rama', 'g1');
204
- expect((0, store_1.readJournal)(repo, 'rama').state.routingAttempts[0]).toMatchObject({ state: 'active', nativeAgentId: 'native-1' });
205
- (0, requests_1.emitRequest)(repo, 'rama', { kind: 'routing-reserve', generationToken: 'old', idempotencyKey: 'routing-old', payload: { obligationId: 'o1', lineageId: 'l2', envelope, fingerprint: 'f'.repeat(64) } });
206
- expect((0, apply_1.consumePendingRequests)(repo, 'rama', 'g1').rejectedStale).toBe(1);
207
- expect((0, store_1.readJournal)(repo, 'rama').state.routingAttempts).toHaveLength(1);
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 envelope = { schema: 'routing-envelope/v1', runtime: { target: 'codex', kind: 'native', version: '1', accountScopeDigest: '0'.repeat(64) }, role: 'implementer', sliceId: 'S1', requestedProfile: 'mechanical', effectiveProfile: 'mechanical', resolved: { selector: { kind: 'model', id: 'm' }, effort: { kind: 'explicit', value: 'medium' } }, outcome: 'native', unavailableEvidence: [], policyDigest: 'a'.repeat(64), capabilityDigest: 'b'.repeat(64), planDigest: 'c'.repeat(64), executionDigest: 'd'.repeat(64) };
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: { ...envelope, effectiveProfile: profile }, fingerprint: `${'a'.repeat(63)}${index}` }, '2026-09-17T00:00:00.000Z').state;
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: { ...envelope, effectiveProfile: 'integration' }, state: 'blocked', verdict: 'fail' });
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: { ...envelope, effectiveProfile: 'judgment', resolved: { selector: { kind: 'model', id: 'm' }, effort: { kind: 'explicit', value: 'medium' } } }, state: 'blocked', verdict: 'fail' });
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)({ ...envelope, role: 'attacker-key' })).toBe(false);
44
- expect((0, types_1.isRoutingEnvelope)({ ...envelope, unavailableEvidence: ['secret=leak'] })).toBe(false);
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 = fs_1.default.readFileSync(path_1.default.join(REPO_ROOT, '.github', 'workflows', name), 'utf8');
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 = fs_1.default.readFileSync(path_1.default.join(REPO_ROOT, '.github', 'workflows', 'release.yml'), 'utf8');
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 = fs_1.default.readFileSync(path_1.default.join(REPO_ROOT, '.github', 'workflows', name), 'utf8');
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-workflow-manager",
3
- "version": "9.11.10",
3
+ "version": "9.11.12",
4
4
  "main": "dist/src/index.js",
5
5
  "bin": {
6
6
  "awm": "./dist/src/index.js"
Binary file
Binary file