agentic-workflow-manager 9.22.0 → 9.22.1

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.
Files changed (53) hide show
  1. package/dist/src/commands/change/index.js +2 -2
  2. package/dist/src/commands/init.js +8 -4
  3. package/dist/src/commands/registry/add.js +9 -3
  4. package/dist/src/commands/sync.js +11 -5
  5. package/dist/src/commands/update.js +23 -12
  6. package/dist/src/core/changes/derive.js +6 -3
  7. package/dist/src/core/changes/git.js +1 -2
  8. package/dist/src/core/changes/worktree.js +15 -3
  9. package/dist/src/core/init/steps.js +3 -8
  10. package/dist/src/core/registries.js +20 -15
  11. package/dist/src/core/registry-git-errors.js +107 -0
  12. package/dist/src/core/registry-git.js +93 -0
  13. package/dist/src/core/registry-sync-report.js +74 -0
  14. package/dist/src/core/versioning.js +3 -6
  15. package/dist/src/index.js +5 -8
  16. package/dist/tests/commands/change/new.test.js +103 -57
  17. package/dist/tests/commands/change/validate.test.js +164 -108
  18. package/dist/tests/commands/changes/list.test.js +41 -22
  19. package/dist/tests/commands/job/gate-reconcile.test.js +13 -2
  20. package/dist/tests/commands/registry-sync-honesty.test.js +175 -0
  21. package/dist/tests/commands/sensors/exec.test.js +3 -1
  22. package/dist/tests/commands/update.test.js +8 -8
  23. package/dist/tests/commands/watch/supervisor-loop.test.js +21 -5
  24. package/dist/tests/core/changes/helpers.js +15 -3
  25. package/dist/tests/core/changes/list-paging.test.js +131 -110
  26. package/dist/tests/core/changes/list.test.js +133 -83
  27. package/dist/tests/core/changes/receipt.test.js +18 -6
  28. package/dist/tests/core/diagnostics/provider-checks.test.js +3 -0
  29. package/dist/tests/core/init/steps-registry-sync.test.js +6 -8
  30. package/dist/tests/core/registry-git.test.js +153 -0
  31. package/dist/tests/helpers/commit-seeded-registry.js +18 -0
  32. package/dist/tests/integration/codex-provider-isolated.test.js +7 -2
  33. package/dist/tests/integration/copilot-init-isolated.test.js +7 -4
  34. package/dist/tests/structural/active-documentation.test.js +0 -41
  35. package/dist/tests/structural/bundle-skill-reference-contract.test.js +0 -12
  36. package/dist/tests/structural/cli-reference-matches-commander.test.js +94 -0
  37. package/dist/tests/structural/native-release-artifacts.test.js +116 -107
  38. package/dist/tests/structural/sensor-documentation-contract.test.js +0 -47
  39. package/dist/tests/structural/sensor-portability-contract.test.js +0 -7
  40. package/dist/tests/structural/simple-git-v4-pin.test.js +49 -0
  41. package/package.json +2 -2
  42. package/prebuilds/darwin-arm64/secure_fs.node +0 -0
  43. package/prebuilds/darwin-x64/secure_fs.node +0 -0
  44. package/prebuilds/win32-arm64/secure_fs.node +0 -0
  45. package/prebuilds/win32-x64/secure_fs.node +0 -0
  46. package/dist/tests/structural/cloud-admission-docs-contract.test.js +0 -54
  47. package/dist/tests/structural/documentation-phase-is-mechanized.test.js +0 -29
  48. package/dist/tests/structural/operator-environments-docs-contract.test.js +0 -70
  49. package/dist/tests/structural/process-model-description-contract.test.js +0 -34
  50. package/dist/tests/structural/project-declared-sensors-docs-contract.test.js +0 -104
  51. package/dist/tests/structural/r4-plan-currentness-docs.test.js +0 -37
  52. package/dist/tests/structural/sensor-execution-optimization-docs-contract.test.js +0 -102
  53. package/dist/tests/structural/sensor-slice-decision-contract.test.js +0 -63
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.normalizePin = normalizePin;
7
4
  exports.resolveTargetRef = resolveTargetRef;
@@ -12,7 +9,7 @@ exports.compareSemver = compareSemver;
12
9
  //
13
10
  // Resolver de versiones por tags semver — WS-3. Sin estado propio: git es la
14
11
  // única fuente de verdad (la versión vigente se deriva de `git describe`).
15
- const simple_git_1 = __importDefault(require("simple-git"));
12
+ const registry_git_1 = require("./registry-git");
16
13
  const config_1 = require("../utils/config");
17
14
  const TAG_RE = /^v(\d+)\.(\d+)\.(\d+)$/;
18
15
  function normalizePin(pin) {
@@ -59,7 +56,7 @@ async function fetchVersionTags(git) {
59
56
  * pin declarado > último tag semver (canal stable) > HEAD (canal dev o repo sin tags).
60
57
  */
61
58
  async function resolveTargetRef(repoDir, opts) {
62
- const git = (0, simple_git_1.default)(repoDir);
59
+ const git = (0, registry_git_1.createRegistryGit)(repoDir);
63
60
  const tags = await fetchVersionTags(git);
64
61
  if (opts.pin) {
65
62
  const want = `v${normalizePin(opts.pin)}`;
@@ -82,7 +79,7 @@ async function resolveTargetRef(repoDir, opts) {
82
79
  /** Versión checkouteada actual ("X.Y.Z") si HEAD coincide exactamente con un tag semver; null si sigue un branch. */
83
80
  async function currentVersion(repoDir) {
84
81
  try {
85
- const out = (await (0, simple_git_1.default)(repoDir).raw(['describe', '--tags', '--exact-match', 'HEAD'])).trim();
82
+ const out = (await (0, registry_git_1.createRegistryGit)(repoDir).raw(['describe', '--tags', '--exact-match', 'HEAD'])).trim();
86
83
  return TAG_RE.test(out) ? out.slice(1) : null;
87
84
  }
88
85
  catch {
package/dist/src/index.js CHANGED
@@ -19,6 +19,7 @@ const provider_preflight_1 = require("./ui/provider-preflight");
19
19
  const discovery_1 = require("./core/discovery");
20
20
  const bundles_1 = require("./core/bundles");
21
21
  const registries_1 = require("./core/registries");
22
+ const registry_sync_report_1 = require("./core/registry-sync-report");
22
23
  const install_planner_1 = require("./core/install-planner");
23
24
  const install_transaction_1 = require("./core/install-transaction");
24
25
  const profile_1 = require("./core/profile");
@@ -129,10 +130,8 @@ exports.program.command('add [name]')
129
130
  s.start('Syncing registries...');
130
131
  const results = await (0, registries_1.syncRegistries)();
131
132
  s.stop('Registries synced.');
132
- for (const r of results) {
133
- if (r.action === 'error')
134
- console.warn(picocolors_1.default.yellow(` ⚠ registry ${r.name}: ${r.error}`));
135
- }
133
+ // SG-7 soft path: usable cache may continue after stating cached version + SG-6 cause.
134
+ await (0, registry_sync_report_1.reportRegistrySyncSoftFailures)(results, (m) => console.warn(picocolors_1.default.yellow(m)));
136
135
  try {
137
136
  (0, registries_1.assertSyncedRegistriesUsable)(results);
138
137
  }
@@ -458,10 +457,8 @@ exports.program.command('list [package]')
458
457
  s.start('Syncing registries...');
459
458
  const listSyncResults = await (0, registries_1.syncRegistries)();
460
459
  s.stop('Registries synced.');
461
- for (const r of listSyncResults) {
462
- if (r.action === 'error')
463
- console.warn(picocolors_1.default.yellow(` ⚠ registry ${r.name}: ${r.error}`));
464
- }
460
+ // SG-7 soft path: usable cache may continue after stating cached version + SG-6 cause.
461
+ await (0, registry_sync_report_1.reportRegistrySyncSoftFailures)(listSyncResults, (m) => console.warn(picocolors_1.default.yellow(m)));
465
462
  try {
466
463
  (0, registries_1.assertSyncedRegistriesUsable)(listSyncResults);
467
464
  }
@@ -92,6 +92,37 @@ function sharedRepo() {
92
92
  beforeAll(() => { newRepo(); receiptForHead(); });
93
93
  afterAll(() => repo.cleanup());
94
94
  }
95
+ /**
96
+ * Prebuilt states: each is built once, lazily, in its own clone of the template (the git work happens there once), and every test
97
+ * that starts from it gets a private file copy (no git process) that it may change freely. `build` returns what the test needs
98
+ * of how the state was made (a command result, a text), handed back on every use.
99
+ */
100
+ const fixtures = new Map();
101
+ afterAll(() => { for (const f of fixtures.values())
102
+ f.state.cleanup(); });
103
+ function fromFixture(key, build) {
104
+ let built = fixtures.get(key);
105
+ if (built === undefined) {
106
+ const own = repo;
107
+ repo = (0, helpers_1.cloneRepo)(template);
108
+ try {
109
+ built = { state: repo, value: build() };
110
+ fixtures.set(key, built);
111
+ }
112
+ catch (error) {
113
+ repo.cleanup();
114
+ throw error;
115
+ }
116
+ finally {
117
+ repo = own;
118
+ }
119
+ }
120
+ repo.cleanup();
121
+ repo = (0, helpers_1.cloneRepo)(built.state);
122
+ return built.value;
123
+ }
124
+ /** The repository after `receiptForHead()` and `run('change-record')` (the record is created, not committed): that run's result. */
125
+ const created = () => fromFixture('created', () => { receiptForHead(); return run('change-record'); });
95
126
  // The command writes only into the throwaway repository: the real checkout is never touched.
96
127
  afterEach(() => expect(listReal()).toEqual(realBefore));
97
128
  afterAll(() => expect(listReal()).toEqual(realBefore));
@@ -181,20 +212,17 @@ describe('awm change new: receipt and clean tree (R3.6)', () => {
181
212
  describe('awm change new: skeleton (R3.7, R3.9)', () => {
182
213
  freshRepo();
183
214
  test('prints the created path and writes exactly that file', () => {
184
- receiptForHead();
185
- const r = run('change-record');
215
+ const r = created();
186
216
  expect(r).toEqual({ code: 0, stdout: 'Created docs/changes/2026-10-17-change-record.md\n', stderr: '' });
187
217
  expect(recordFiles()).toEqual(['2026-10-17-change-record.md']);
188
218
  });
189
219
  test('derives type, scope, semver, breaking and modules from the branch commits', () => {
190
- receiptForHead();
191
- run('change-record');
220
+ created();
192
221
  const fm = frontmatter(read());
193
222
  expect(fm).toMatchObject({ schema: 'awm.change-record/v1', id: '2026-10-17-change-record', type: 'feat', scope: 'changes', semver: 'minor', breaking: false, modules: ['cli/src'] });
194
223
  });
195
224
  test('copies commit, overall, sensors and the digest of the receipt into verification', () => {
196
- receiptForHead();
197
- run('change-record');
225
+ created();
198
226
  const expected = {
199
227
  commit: repo.git('rev-parse', 'HEAD'),
200
228
  overall: 'pass',
@@ -211,8 +239,7 @@ describe('awm change new: skeleton (R3.7, R3.9)', () => {
211
239
  expect(frontmatter(read()).verification.receipt_digest).toBe(digest);
212
240
  });
213
241
  test('every narrative field and every body section carries the pending marker', () => {
214
- receiptForHead();
215
- run('change-record');
242
+ created();
216
243
  const text = read();
217
244
  const fm = frontmatter(text);
218
245
  expect(fm.title).toBe(types_1.PENDING_MARKER);
@@ -225,8 +252,7 @@ describe('awm change new: skeleton (R3.7, R3.9)', () => {
225
252
  }
226
253
  });
227
254
  test('the skeleton fails validation only because of its pending markers', () => {
228
- receiptForHead();
229
- run('change-record');
255
+ created();
230
256
  const { diagnostics } = (0, validate_shape_1.validateRecordShape)('2026-10-17-change-record.md', read(), { root: repo.root });
231
257
  expect(diagnostics.map((d) => d.code)).toEqual(['pending-content']);
232
258
  });
@@ -246,13 +272,11 @@ describe('awm change new: skeleton (R3.7, R3.9)', () => {
246
272
  expect(frontmatter(read()).links).toEqual({ plan: 'docs/plans/p.md', issue: 'https://github.com/o/r/issues/217' });
247
273
  });
248
274
  test('without --plan and --issue there is no links key', () => {
249
- receiptForHead();
250
- run('change-record');
275
+ created();
251
276
  expect(frontmatter(read())).not.toHaveProperty('links');
252
277
  });
253
278
  test('the record ends with a newline and uses LF only', () => {
254
- receiptForHead();
255
- run('change-record');
279
+ created();
256
280
  const text = read();
257
281
  expect(text.endsWith('\n')).toBe(true);
258
282
  expect(text).not.toContain('\r');
@@ -310,8 +334,20 @@ describe('awm change new: the 65536-byte boundary of the record (R3.4, R1.8)', (
310
334
  ...Array.from({ length: fillers }, (_, i) => ({ name: `f${String(i).padStart(4, '0')}${'x'.repeat(95)}`, status: 'pass', errors: [] })),
311
335
  { name: `v${'x'.repeat(variable - 1)}`, status: 'pass', errors: [] },
312
336
  ];
313
- const setReceipt = (fillers, variable) => {
314
- (0, receipt_1.writeReceipt)(repo.root, (0, receipt_1.buildReceipt)({ commit: repo.git('rev-parse', 'HEAD'), ranAt: RECEIPT_TIME, cliVersion: '9.20.0', output: { overall: 'pass', sensors: sensorList(fillers, variable) } }));
337
+ /** The receipt for HEAD of (fillers, variable), not written. */
338
+ const receiptOf = (head, fillers, variable) => (0, receipt_1.buildReceipt)({ commit: head, ranAt: RECEIPT_TIME, cliVersion: '9.20.0', output: { overall: 'pass', sensors: sensorList(fillers, variable) } });
339
+ const setReceipt = (fillers, variable) => { (0, receipt_1.writeReceipt)(repo.root, receiptOf(repo.git('rev-parse', 'HEAD'), fillers, variable)); };
340
+ /** The verification block the command copies from a receipt. */
341
+ const verificationOf = (r) => ({ commit: r.commit, overall: r.overall, sensors: r.sensors, receipt_digest: r.digest });
342
+ /** The derived fields a record states. */
343
+ const fieldsOf = (text) => {
344
+ const fm = frontmatter(text);
345
+ return { type: fm.type, scope: fm.scope, semver: fm.semver, breaking: fm.breaking, modules: fm.modules };
346
+ };
347
+ const bytesOf = (text) => {
348
+ if (text === null)
349
+ throw new Error('the record could not be rendered');
350
+ return Buffer.byteLength(text, 'utf8');
315
351
  };
316
352
  /** Largest n in [lo, hi] for which `fits(n)` holds, `fits` being true up to a point and false after it. */
317
353
  const largest = (lo, hi, fits) => {
@@ -326,12 +362,17 @@ describe('awm change new: the 65536-byte boundary of the record (R3.4, R1.8)', (
326
362
  }
327
363
  return a;
328
364
  };
329
- /** Runs `attempt` for a receipt of (fillers, variable); `bytes` is the size of the file it wrote, null when it failed as too large. */
330
- function findBoundary(attempt) {
331
- const fits = (fillers, variable) => { setReceipt(fillers, variable); return attempt().bytes; };
332
- const fillers = largest(0, 700, (k) => fits(k, 1) !== null);
333
- const variable = largest(1, 128, (l) => fits(fillers, l) !== null);
334
- return { fillers, variable, atLimit: fits(fillers, variable), oneMore: variable < 128 ? fits(fillers, variable + 1) : -1 };
365
+ /**
366
+ * The receipt (fillers, variable) whose record is exactly at the limit is searched with `predict` (the size of the record the
367
+ * command would write for it: the pure renderer the command writes with, no git), then the command itself is run on that receipt
368
+ * and on the one a byte larger: `attempt` reports the size of the file it wrote, null when it failed as too large.
369
+ */
370
+ function findBoundary(predict, attempt) {
371
+ const fits = (fillers, variable) => predict(fillers, variable) <= types_1.MAX_RECORD_BYTES;
372
+ const fillers = largest(0, 700, (k) => fits(k, 1));
373
+ const variable = largest(1, 128, (l) => fits(fillers, l));
374
+ const real = (f, v) => { setReceipt(f, v); return attempt().bytes; };
375
+ return { fillers, variable, atLimit: real(fillers, variable), oneMore: variable < 128 ? real(fillers, variable + 1) : -1 };
335
376
  }
336
377
  test('change new: a record of exactly 65536 bytes is written, one of 65537 is record-too-large', () => {
337
378
  const attempt = () => {
@@ -344,7 +385,15 @@ describe('awm change new: the 65536-byte boundary of the record (R3.4, R1.8)', (
344
385
  expect(r.stderr).toContain('record-too-large');
345
386
  return { bytes: null };
346
387
  };
347
- const found = findBoundary(attempt);
388
+ const head = repo.git('rev-parse', 'HEAD');
389
+ setReceipt(0, 1);
390
+ expect(run('change-record').code).toBe(0);
391
+ const fields = fieldsOf(read());
392
+ const predict = (f, v) => bytesOf(renderModule.renderSkeleton({ id: '2026-10-17-change-record', fields, verification: verificationOf(receiptOf(head, f, v)), links: {}, provenance: {} }));
393
+ // The prediction is the command's own output: the record it just wrote, byte for byte.
394
+ expect(read()).toBe(renderModule.renderSkeleton({ id: '2026-10-17-change-record', fields, verification: verificationOf(receiptOf(head, 0, 1)), links: {}, provenance: {} }));
395
+ fs_1.default.rmSync(file());
396
+ const found = findBoundary(predict, attempt);
348
397
  expect(found.variable).toBeLessThan(128);
349
398
  expect(found.atLimit).toBe(65536);
350
399
  expect(found.oneMore).toBeNull();
@@ -366,7 +415,16 @@ describe('awm change new: the 65536-byte boundary of the record (R3.4, R1.8)', (
366
415
  expect(read()).toBe(original);
367
416
  return { bytes: null };
368
417
  };
369
- const found = findBoundary(attempt);
418
+ const head = repo.git('rev-parse', 'HEAD');
419
+ setReceipt(0, 1);
420
+ expect(run('change-record', { refresh: true }).code).toBe(0);
421
+ const refreshed = read();
422
+ const fields = fieldsOf(refreshed);
423
+ fs_1.default.writeFileSync(file(), original);
424
+ const predict = (f, v) => bytesOf(renderModule.refreshDerived(original, fields, verificationOf(receiptOf(head, f, v))));
425
+ // The prediction is the command's own output: the record it just refreshed, byte for byte.
426
+ expect(renderModule.refreshDerived(original, fields, verificationOf(receiptOf(head, 0, 1)))).toBe(refreshed);
427
+ const found = findBoundary(predict, attempt);
370
428
  expect(found.variable).toBeLessThan(128);
371
429
  expect(found.atLimit).toBe(65536);
372
430
  expect(found.oneMore).toBeNull();
@@ -389,8 +447,7 @@ describe('awm change new: HEAD moving while the command runs', () => {
389
447
  expect(recordFiles()).toEqual([]);
390
448
  });
391
449
  test('a HEAD that moves before a refresh is written is head-moved and the record is untouched', () => {
392
- receiptForHead();
393
- run('change-record');
450
+ created();
394
451
  repo.git('add', '-A');
395
452
  repo.git('commit', '-q', '-m', 'docs(changes): record');
396
453
  receiptForHead();
@@ -462,8 +519,7 @@ describe('awm change new: provenance (R3.8)', () => {
462
519
  return r.state;
463
520
  }
464
521
  test('omits the provenance key entirely when no source exists', () => {
465
- receiptForHead();
466
- run('change-record');
522
+ created();
467
523
  expect(frontmatter(read())).not.toHaveProperty('provenance');
468
524
  });
469
525
  test('model and session come only from flags', () => {
@@ -526,23 +582,20 @@ describe('awm change new: provenance (R3.8)', () => {
526
582
  describe('awm change new: no overwrite (R3.10)', () => {
527
583
  freshRepo();
528
584
  test('refuses to overwrite on the same date and leaves the file untouched', () => {
529
- receiptForHead();
530
- run('change-record');
585
+ created();
531
586
  fs_1.default.writeFileSync(file(), 'edited by hand');
532
587
  expectFailure(run('change-record'), 'record-exists', 'use --refresh to update derived fields');
533
588
  expect(read()).toBe('edited by hand');
534
589
  });
535
590
  test('refuses the same slug on another date', () => {
536
- receiptForHead();
537
- run('change-record');
591
+ created();
538
592
  const before = read();
539
593
  expectFailure(run('change-record', {}, { now: () => new Date('2026-10-20T12:00:00.000Z') }), 'record-exists', 'use --refresh to update derived fields');
540
594
  expect(recordFiles()).toEqual(['2026-10-17-change-record.md']);
541
595
  expect(read()).toBe(before);
542
596
  });
543
597
  test('a different slug is not blocked by an existing record', () => {
544
- receiptForHead();
545
- run('change-record');
598
+ created();
546
599
  expect(run('change-record-2').code).toBe(0);
547
600
  expect(recordFiles()).toEqual(['2026-10-17-change-record-2.md', '2026-10-17-change-record.md']);
548
601
  });
@@ -561,8 +614,7 @@ describe('awm change new: no overwrite (R3.10)', () => {
561
614
  expect(fs_1.default.readFileSync(outside, 'utf8')).toBe('precious');
562
615
  });
563
616
  test('a listing that misses an existing file still never overwrites it (exclusive create)', () => {
564
- receiptForHead();
565
- run('change-record');
617
+ created();
566
618
  fs_1.default.writeFileSync(file(), 'edited by hand');
567
619
  interceptFs('readdirSync', (a) => isRecordsDirArg(a[0]), () => []);
568
620
  expectFailure(run('change-record'), 'record-exists', 'use --refresh to update derived fields');
@@ -842,7 +894,7 @@ describe('awm change new: base and derivation diagnostics (R3.1, R3.2, R3.5)', (
842
894
  });
843
895
  describe('awm change new --refresh (R3.11)', () => {
844
896
  freshRepo();
845
- function recordCommitted(mutate = (t) => t) {
897
+ function buildRecordCommitted(mutate) {
846
898
  receiptForHead();
847
899
  run('change-record');
848
900
  const edited = mutate(read().split(types_1.PENDING_MARKER).join('written by agent'));
@@ -853,6 +905,10 @@ describe('awm change new --refresh (R3.11)', () => {
853
905
  receiptForHead();
854
906
  return edited;
855
907
  }
908
+ /** A filled record committed, a later fix(core) commit and a receipt for it. Without `mutate` the state is prebuilt (fromFixture). */
909
+ function recordCommitted(mutate) {
910
+ return mutate === undefined ? fromFixture('record committed', () => buildRecordCommitted((t) => t)) : buildRecordCommitted(mutate);
911
+ }
856
912
  const strip = (s) => s.replace(/^(type|scope|semver|breaking|modules|verification):[\s\S]*?(?=^[a-z_]+:|^---$)/gm, '');
857
913
  test('recomputes the derived fields and verification', () => {
858
914
  recordCommitted();
@@ -908,8 +964,7 @@ describe('awm change new --refresh (R3.11)', () => {
908
964
  expectFailure(run('change-record', { refresh: true }), 'record-missing', 'run awm change new change-record to create it');
909
965
  });
910
966
  test('two records with the same slug are record-ambiguous and neither is modified', () => {
911
- receiptForHead();
912
- run('change-record');
967
+ created();
913
968
  run('change-record', {}, { now });
914
969
  fs_1.default.copyFileSync(file(), path_1.default.join(recordsDir(), '2026-11-01-change-record.md'));
915
970
  const before = recordFiles().map((f) => fs_1.default.readFileSync(path_1.default.join(recordsDir(), f), 'utf8'));
@@ -927,8 +982,7 @@ describe('awm change new --refresh (R3.11)', () => {
927
982
  expect(read()).toBe('---\n: : :\n---\n');
928
983
  });
929
984
  test('a record missing a derived key is record-invalid and untouched', () => {
930
- receiptForHead();
931
- run('change-record');
985
+ created();
932
986
  const broken = read().replace(/^semver: .*\n/m, '');
933
987
  fs_1.default.writeFileSync(file(), broken);
934
988
  repo.git('add', '-A');
@@ -938,8 +992,7 @@ describe('awm change new --refresh (R3.11)', () => {
938
992
  expect(read()).toBe(broken);
939
993
  });
940
994
  test('R3.4 a refresh that would push the record over 64 KiB is record-too-large with a remedy, and the record is untouched', () => {
941
- receiptForHead();
942
- run('change-record');
995
+ created();
943
996
  repo.git('add', '-A');
944
997
  repo.git('commit', '-q', '-m', 'docs(changes): record');
945
998
  const files = Object.fromEntries(Array.from({ length: 4000 }, (_, i) => [`vendor/package-${String(i).padStart(5, '0')}/index.js`, '1']));
@@ -950,8 +1003,7 @@ describe('awm change new --refresh (R3.11)', () => {
950
1003
  expect(read()).toBe(before);
951
1004
  });
952
1005
  test('a record already over 64 KiB on disk is record-invalid and untouched (it cannot be read for a rewrite)', () => {
953
- receiptForHead();
954
- run('change-record');
1006
+ created();
955
1007
  fs_1.default.writeFileSync(file(), `${read()}\n${'x'.repeat(70 * 1024)}\n`);
956
1008
  repo.git('add', '-A');
957
1009
  repo.git('commit', '-q', '-m', 'docs(changes): huge');
@@ -961,8 +1013,7 @@ describe('awm change new --refresh (R3.11)', () => {
961
1013
  expect(read()).toBe(before);
962
1014
  });
963
1015
  test('a record that is not valid UTF-8 is record-invalid and untouched', () => {
964
- receiptForHead();
965
- run('change-record');
1016
+ created();
966
1017
  const bytes = Buffer.concat([fs_1.default.readFileSync(file()), Buffer.from([0xff, 0xfe, 0x0a])]);
967
1018
  fs_1.default.writeFileSync(file(), bytes);
968
1019
  repo.git('add', '-A');
@@ -972,8 +1023,7 @@ describe('awm change new --refresh (R3.11)', () => {
972
1023
  expect(fs_1.default.readFileSync(file()).equals(bytes)).toBe(true);
973
1024
  });
974
1025
  test('a record with a UTF-8 BOM is record-invalid and its bytes are untouched', () => {
975
- receiptForHead();
976
- run('change-record');
1026
+ created();
977
1027
  const bytes = Buffer.concat([Buffer.from([0xef, 0xbb, 0xbf]), fs_1.default.readFileSync(file())]);
978
1028
  fs_1.default.writeFileSync(file(), bytes);
979
1029
  repo.git('add', '-A');
@@ -983,8 +1033,7 @@ describe('awm change new --refresh (R3.11)', () => {
983
1033
  expect(fs_1.default.readFileSync(file()).equals(bytes)).toBe(true);
984
1034
  });
985
1035
  test('a record without a BOM but with non-ASCII text still refreshes and keeps those bytes', () => {
986
- receiptForHead();
987
- run('change-record');
1036
+ created();
988
1037
  fs_1.default.writeFileSync(file(), fs_1.default.readFileSync(file(), 'utf8').split(types_1.PENDING_MARKER).join('Qué se probó ñandú \u{1F600}'));
989
1038
  repo.git('add', '-A');
990
1039
  repo.git('commit', '-q', '-m', 'docs(changes): text');
@@ -995,8 +1044,7 @@ describe('awm change new --refresh (R3.11)', () => {
995
1044
  expect(read().charCodeAt(0)).toBe('-'.charCodeAt(0));
996
1045
  });
997
1046
  test('a record larger than the record limit is record-invalid', () => {
998
- receiptForHead();
999
- run('change-record');
1047
+ created();
1000
1048
  fs_1.default.appendFileSync(file(), 'x'.repeat(70 * 1024));
1001
1049
  repo.git('add', '-A');
1002
1050
  repo.git('commit', '-q', '-m', 'docs(changes): big');
@@ -1004,8 +1052,7 @@ describe('awm change new --refresh (R3.11)', () => {
1004
1052
  expectFailure(run('change-record', { refresh: true }), 'record-invalid');
1005
1053
  });
1006
1054
  test('a record whose derived keys are quoted is refreshed and still validates', () => {
1007
- receiptForHead();
1008
- run('change-record');
1055
+ created();
1009
1056
  const quoted = read().replace(/^(type|semver) *:/gm, '"$1" :');
1010
1057
  fs_1.default.writeFileSync(file(), quoted.split(types_1.PENDING_MARKER).join('written by agent'));
1011
1058
  repo.git('add', '-A');
@@ -1043,8 +1090,7 @@ describe('awm change new --refresh (R3.11)', () => {
1043
1090
  expect(run('change-record', { refresh: true, base: 'main' }).code).toBe(0);
1044
1091
  });
1045
1092
  test('a derived key spelled with a YAML escape is record-invalid and the bytes are untouched', () => {
1046
- receiptForHead();
1047
- run('change-record');
1093
+ created();
1048
1094
  const bytes = Buffer.from(read().replace(/^type: .*$/m, '"t\\x79pe": fix'));
1049
1095
  expect(bytes.toString('utf8')).toContain('"t\\x79pe": fix');
1050
1096
  fs_1.default.writeFileSync(file(), bytes);