arkgate 2.3.0 → 2.4.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 (39) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +26 -16
  3. package/SECURITY.md +9 -8
  4. package/bin/ark-check.mjs +599 -53
  5. package/bin/ark-shared.mjs +53 -0
  6. package/bin/ark.mjs +20 -5
  7. package/dist/index.cjs +1 -1
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/nestjs/index.cjs +1 -1
  14. package/dist/nestjs/index.cjs.map +1 -1
  15. package/dist/nestjs/index.js +1 -1
  16. package/dist/nestjs/index.js.map +1 -1
  17. package/docs/agent-guide.md +11 -5
  18. package/docs/ai-gates.md +11 -7
  19. package/docs/brownfield-adoption.md +14 -13
  20. package/docs/demos/03-copilot-autopilot.md +5 -3
  21. package/docs/enthusiast/README.md +4 -3
  22. package/docs/enthusiast/how-to-agent-gates.md +14 -6
  23. package/docs/enthusiast/reference-commands.md +23 -8
  24. package/docs/migrate-from-ark-runtime-kernel.md +18 -0
  25. package/docs/typescript-support.md +142 -0
  26. package/package.json +12 -3
  27. package/server.json +2 -2
  28. package/templates/skills/ark-autopilot.md +6 -4
  29. package/templates/skills/ark-explain.md +7 -2
  30. package/templates/skills/ark-fix.md +16 -12
  31. package/templates/skills/ark-loop.md +14 -4
  32. package/templates/skills/ark-upgrade.md +26 -1
  33. package/templates/tests/ark-adoption-gaps.test.ts +68 -0
  34. package/tests/fixtures/ts-consumer/ark.config.json +11 -0
  35. package/tests/fixtures/ts-consumer/src/app/types.ts +1 -0
  36. package/tests/fixtures/ts-consumer/src/domain/bad.ts +1 -0
  37. package/tests/fixtures/ts-consumer/src/domain/ok.ts +1 -0
  38. package/tests/fixtures/ts-consumer/src/domain/user.ts +1 -0
  39. package/tests/fixtures/ts-consumer/tsconfig.json +16 -0
@@ -630,6 +630,59 @@ export function classifyRemediation(violation) {
630
630
  };
631
631
  }
632
632
 
633
+ /**
634
+ * Normalize a required/imported TypeScript module for ark-check's host.
635
+ * TS 5/6 expose `sys` on the root export. Early TS 7 / some ESM interop shapes
636
+ * may nest under `.default` or omit `sys` — those are unusable for resolve/scan
637
+ * and must fall through to a JS-API-compatible TypeScript (Ark's own or 5/6).
638
+ *
639
+ * @param {unknown} mod
640
+ * @returns {object | null} usable typescript namespace, or null
641
+ */
642
+ export function usableTypescript(mod) {
643
+ if (!mod || typeof mod !== 'object') return null;
644
+ // Prefer root; if root has no sys but default does (CJS/ESM interop), use default.
645
+ const candidates = [mod];
646
+ if (mod.default && typeof mod.default === 'object') candidates.push(mod.default);
647
+ for (const ts of candidates) {
648
+ if (
649
+ ts &&
650
+ typeof ts === 'object' &&
651
+ ts.sys &&
652
+ typeof ts.sys.fileExists === 'function' &&
653
+ typeof ts.createSourceFile === 'function' &&
654
+ typeof ts.resolveModuleName === 'function'
655
+ ) {
656
+ return ts;
657
+ }
658
+ }
659
+ return null;
660
+ }
661
+
662
+ /**
663
+ * Human-readable reason a typescript package module is unusable for the gate.
664
+ * @param {unknown} mod
665
+ */
666
+ export function typescriptUsabilityHint(mod) {
667
+ if (!mod) return 'module is null/undefined';
668
+ const ts = mod.default && mod.sys == null ? mod.default : mod;
669
+ if (!ts || typeof ts !== 'object') return 'not an object export';
670
+ // TS 7.0.x main export is only { version, versionMajorMinor }; classic JS host is not there.
671
+ if (
672
+ typeof ts.version === 'string' &&
673
+ !ts.sys &&
674
+ typeof ts.createSourceFile !== 'function' &&
675
+ typeof ts.resolveModuleName !== 'function'
676
+ ) {
677
+ return `version-only export (${ts.version}) — TypeScript 7 main entry no longer ships the classic JS host (sys/AST/resolve); gate falls back to a JS-API TypeScript`;
678
+ }
679
+ if (!ts.sys) return 'missing ts.sys (common with early TypeScript 7 native builds without a full JS host)';
680
+ if (typeof ts.sys.fileExists !== 'function') return 'ts.sys.fileExists is not a function';
681
+ if (typeof ts.createSourceFile !== 'function') return 'missing createSourceFile (AST API)';
682
+ if (typeof ts.resolveModuleName !== 'function') return 'missing resolveModuleName';
683
+ return 'unknown shape incompatibility';
684
+ }
685
+
633
686
  /** The three package managers Ark emits commands for. */
634
687
  const LOCKFILES = { pnpm: 'pnpm-lock.yaml', yarn: 'yarn.lock', npm: 'package-lock.json' };
635
688
 
package/bin/ark.mjs CHANGED
@@ -123,11 +123,12 @@ async function upgrade(args) {
123
123
  let status = runArkCheck(['--root', root, '--install-agent-gates'], { cwd: root });
124
124
  if (status !== 0) return status;
125
125
 
126
- // Codex loads slash-command prompts from ~/.codex/prompts, not the repo — refresh those too
127
- // when a Codex home exists, so nothing is left stale. Non-fatal: a permission error there
128
- // (e.g. a sandbox) shouldn't fail the whole upgrade.
129
- if (fs.existsSync(path.join(os.homedir(), '.codex'))) {
130
- console.log('\n Refreshing Codex home prompts (~/.codex)…');
126
+ // Codex loads slash-command prompts from $CODEX_HOME/prompts, not the repo — refresh those
127
+ // when a Codex home exists. --force rewrites temp/upgrade MCP roots to this project + arkgate-mcp.
128
+ // Non-fatal: a permission error (e.g. sandbox) shouldn't fail the whole upgrade.
129
+ const codexHomeBase = process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
130
+ if (fs.existsSync(codexHomeBase)) {
131
+ console.log(`\n Refreshing Codex home (${codexHomeBase})…`);
131
132
  runArkCheck(
132
133
  ['--root', root, '--install-agent-gates', '--skills-only', '--codex-home', '--force'],
133
134
  { cwd: root }
@@ -279,6 +280,10 @@ async function init(args) {
279
280
  if (archetype) {
280
281
  console.log(`Shape: ${archetype}. Plan: ${arkCommand(root, 'ark-check', '--recommend')}`);
281
282
  }
283
+ console.log(
284
+ `Freeze day-one architecture snapshot: ${arkCommand(root, 'ark-check', '--report ark-report.html')} (writes .ark/reports/origin.* once).`
285
+ );
286
+ console.log(`Adoption health: ${arkCommand(root, 'ark-check', '--doctor')}`);
282
287
  return 0;
283
288
  } finally {
284
289
  rl?.close();
@@ -433,7 +438,17 @@ async function start(args) {
433
438
  }
434
439
  console.log(` • Re-run the plan anytime: ${arkCommand(root, 'ark-check', '--plan')}`);
435
440
  console.log(` • Full project check: ${arkCommand(root, 'ark-check', '--root . --config ark.config.json --strict-config')}`);
441
+ console.log(` • Adoption health: ${arkCommand(root, 'ark-check', '--doctor')}`);
436
442
  console.log(` • Update Ark later: ${arkCommand(root, 'ark', 'upgrade')}`);
443
+ if (fs.existsSync(path.join(root, '.ark-baseline.json'))) {
444
+ console.log(
445
+ ' • Baseline file present — keep empty for ratchet-from-clean, or freeze debt with --update-baseline.'
446
+ );
447
+ } else {
448
+ console.log(
449
+ ' • No baseline yet (fine on clean trees). Adopting dirty code? freeze with --update-baseline.'
450
+ );
451
+ }
437
452
 
438
453
  // 6) First architecture report — freezes an origin snapshot under .ark/reports/
439
454
  // so later --report runs can show evolution. Idempotent: origin is written only once.
package/dist/index.cjs CHANGED
@@ -80,7 +80,7 @@ __export(index_exports, {
80
80
  module.exports = __toCommonJS(index_exports);
81
81
 
82
82
  // src/version.ts
83
- var version = "2.3.0";
83
+ var version = "2.4.0";
84
84
 
85
85
  // src/kernel/intent/IntentRegistry.ts
86
86
  var IntentRegistry = class {