mandrel 1.69.0 → 1.70.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.agents/README.md +1 -1
  2. package/.agents/docs/workflows.md +1 -1
  3. package/.agents/scripts/agents-update-preflight.js +235 -0
  4. package/.agents/scripts/apply-quality-bootstrap.js +79 -0
  5. package/.agents/scripts/audit-labels-bootstrap.js +52 -30
  6. package/.agents/scripts/audit-to-stories.js +54 -0
  7. package/.agents/scripts/bootstrap.js +13 -3
  8. package/.agents/scripts/generate-config-docs.js +189 -94
  9. package/.agents/scripts/lib/audit-suite/findings.js +0 -4
  10. package/.agents/scripts/lib/audit-to-stories/audit-lenses.js +99 -0
  11. package/.agents/scripts/lib/audit-to-stories/build-story-body.js +13 -5
  12. package/.agents/scripts/lib/baseline-snapshot.js +163 -4
  13. package/.agents/scripts/lib/baselines/refresh-service.js +0 -4
  14. package/.agents/scripts/lib/config/baselines.js +0 -20
  15. package/.agents/scripts/lib/config/temp-paths.js +0 -31
  16. package/.agents/scripts/lib/crap-utils.js +281 -0
  17. package/.agents/scripts/lib/orchestration/dispatch-engine.js +0 -2
  18. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/composition.js +0 -84
  19. package/.agents/scripts/lib/orchestration/epic-runner/progress-reporter/signals.js +3 -4
  20. package/.agents/scripts/lib/orchestration/lifecycle/trace-logger.js +0 -4
  21. package/.agents/scripts/lib/orchestration/retro/phases/compose-body.js +101 -70
  22. package/.agents/scripts/lib/orchestration/spec-renderer.js +42 -14
  23. package/.agents/scripts/lib/orchestration/ticket-lease.js +3 -0
  24. package/.agents/scripts/lib/story-body/story-body.js +110 -65
  25. package/.agents/scripts/lib/test-tiers.js +13 -7
  26. package/.agents/scripts/lib/wave-runner/tick.js +177 -53
  27. package/.agents/scripts/lib/workers/combined-mi-crap-worker.js +226 -0
  28. package/.agents/scripts/providers/github/issues.js +48 -0
  29. package/.agents/scripts/providers/github.js +1 -0
  30. package/.agents/workflows/agents-update.md +205 -28
  31. package/README.md +20 -0
  32. package/docs/CHANGELOG.md +32 -0
  33. package/lib/cli/registry.js +49 -6
  34. package/lib/cli/update.js +335 -332
  35. package/package.json +16 -11
@@ -371,7 +371,14 @@ function runRuntimeDeps({
371
371
  return {
372
372
  ok: false,
373
373
  detail: `missing: ${missing.join(', ')}`,
374
- remedy: `Run \`npm install\` in the repository root to install missing packages: ${missing.join(', ')}`,
374
+ remedy:
375
+ 'The framework runtime deps are not resolvable from the consumer root, ' +
376
+ 'where the materialized .agents/scripts/*.js run. npm and yarn hoist ' +
377
+ "them automatically — run the installer if you haven't. pnpm's default " +
378
+ 'isolated layout does NOT hoist transitive deps to the top level: add ' +
379
+ '`shamefully-hoist=true` (or a scoped `public-hoist-pattern[]` for ' +
380
+ 'each dep) to your `.npmrc` and reinstall. ' +
381
+ `Missing: ${missing.join(', ')}`,
375
382
  };
376
383
  }
377
384
 
@@ -457,6 +464,39 @@ function runAgentsMaterialized({ cwd, existsSync, resolvePackage } = {}) {
457
464
  // from sync.js) are imported from `lib/cli/sync.js` at the top of this file
458
465
  // (Story #4048 B3 — no mirror copies).
459
466
 
467
+ /**
468
+ * Decide whether a single materialized payload file has drifted from its
469
+ * package-payload source.
470
+ *
471
+ * Size short-circuit (Story #4193): when the injected `fsImpl` exposes
472
+ * `statSync`, a `statSync(src).size !== statSync(dest).size` mismatch is
473
+ * sufficient proof of drift, so it returns `true` on two `stat` syscalls
474
+ * **without reading either file's contents** — the overwhelmingly common
475
+ * drift shape after a stale `sync` is a size change. Equal sizes do not
476
+ * guarantee equal content, so an equal-size pair falls through to the
477
+ * `readFileSync` + `Buffer.equals` byte comparison. The short-circuit is
478
+ * opt-in on `statSync` being present; a seam that omits it (e.g. a legacy
479
+ * test double) transparently uses the byte-read path, preserving the prior
480
+ * behaviour exactly.
481
+ *
482
+ * Security: returns only a boolean — it never surfaces file contents to the
483
+ * caller (security baseline §5 — Data Leakage & Logging).
484
+ *
485
+ * @param {string} src - absolute path to the package-payload file
486
+ * @param {string} dest - absolute path to the materialized file
487
+ * @param {{ readFileSync: Function, statSync?: Function }} fsImpl
488
+ * @returns {boolean} `true` when the files differ
489
+ */
490
+ function payloadFileDrifted(src, dest, fsImpl) {
491
+ if (
492
+ typeof fsImpl.statSync === 'function' &&
493
+ fsImpl.statSync(src).size !== fsImpl.statSync(dest).size
494
+ ) {
495
+ return true;
496
+ }
497
+ return !fsImpl.readFileSync(src).equals(fsImpl.readFileSync(dest));
498
+ }
499
+
460
500
  /**
461
501
  * Compare the consumer's materialized `./.agents/<f>` bytes against the
462
502
  * installed package payload (`node_modules/mandrel/.agents/<f>`),
@@ -469,16 +509,21 @@ function runAgentsMaterialized({ cwd, existsSync, resolvePackage } = {}) {
469
509
  * §5 — Data Leakage & Logging). The comparison is short-circuiting and never
470
510
  * accumulates file contents.
471
511
  *
512
+ * Performance: per-file drift is decided by `payloadFileDrifted`, which gates
513
+ * the byte read behind a cheap `statSync` size comparison (Story #4193) so a
514
+ * size-changed file — the common drift shape after a stale `sync` — reports
515
+ * without reading either file's contents.
516
+ *
472
517
  * Injectable seams (used by tests so no real filesystem or package is needed):
473
518
  * - `cwd()` — replaces `process.cwd`.
474
519
  * - `fsImpl` — replaces the `node:fs` surface (`existsSync`, `readdirSync`,
475
- * `readFileSync`).
520
+ * `readFileSync`, and optionally `statSync` for the size short-circuit).
476
521
  * - `resolvePackageRoot(fromDir)` — replaces `mandrel` resolution;
477
522
  * throws when the package is not installed.
478
523
  *
479
524
  * @param {{
480
525
  * cwd?: () => string,
481
- * fsImpl?: { existsSync: (p: string) => boolean, readdirSync: Function, readFileSync: Function },
526
+ * fsImpl?: { existsSync: (p: string) => boolean, readdirSync: Function, readFileSync: Function, statSync?: Function },
482
527
  * resolvePackageRoot?: (fromDir: string) => string,
483
528
  * }} [opts]
484
529
  * @returns {{ ok: boolean, detail: string, remedy?: string }}
@@ -534,10 +579,8 @@ export function runAgentsDrift({ cwd, fsImpl = fs, resolvePackageRoot } = {}) {
534
579
  };
535
580
  }
536
581
 
537
- const srcBytes = fsImpl.readFileSync(src);
538
- const destBytes = fsImpl.readFileSync(dest);
539
582
  comparedCount += 1;
540
- if (!srcBytes.equals(destBytes)) {
583
+ if (payloadFileDrifted(src, dest, fsImpl)) {
541
584
  return {
542
585
  ok: false,
543
586
  detail: `${relLabel} differs from the installed package payload`,