arkgate 2.6.0 → 2.7.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 (57) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +98 -70
  3. package/bin/ark-check.mjs +240 -1001
  4. package/bin/ark-layer-match.mjs +153 -147
  5. package/bin/ark-mcp.mjs +102 -5
  6. package/bin/ark-shared.mjs +304 -165
  7. package/bin/ark.mjs +44 -34
  8. package/bin/lib/agent-gates.mjs +448 -15
  9. package/bin/lib/architecture-scan.mjs +279 -0
  10. package/bin/lib/ast-scan.mjs +199 -0
  11. package/bin/lib/baseline-key.mjs +23 -0
  12. package/bin/lib/config-warnings.mjs +228 -0
  13. package/bin/lib/doctor-plan.mjs +11 -4
  14. package/bin/lib/graph-cycles.mjs +56 -0
  15. package/bin/lib/presets.mjs +75 -4
  16. package/bin/lib/remediation.mjs +150 -0
  17. package/bin/lib/scan-files.mjs +69 -0
  18. package/bin/lib/ts-resolve.mjs +215 -0
  19. package/bin/lib/violations.mjs +3 -9
  20. package/dist/eslint/index.cjs +21 -3
  21. package/dist/eslint/index.cjs.map +1 -1
  22. package/dist/eslint/index.d.cts +5 -3
  23. package/dist/eslint/index.d.ts +5 -3
  24. package/dist/eslint/index.js +21 -3
  25. package/dist/eslint/index.js.map +1 -1
  26. package/dist/index.cjs +1 -1
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.d.cts +3 -3
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +1 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/nestjs/index.cjs +1 -1
  33. package/dist/nestjs/index.cjs.map +1 -1
  34. package/dist/nestjs/index.d.cts +1 -1
  35. package/dist/nestjs/index.d.ts +1 -1
  36. package/dist/nestjs/index.js +1 -1
  37. package/dist/nestjs/index.js.map +1 -1
  38. package/dist/runtime/index.cjs +3080 -0
  39. package/dist/runtime/index.cjs.map +1 -0
  40. package/dist/runtime/index.d.cts +2 -0
  41. package/dist/runtime/index.d.ts +2 -0
  42. package/dist/runtime/index.js +2998 -0
  43. package/dist/runtime/index.js.map +1 -0
  44. package/dist/{types-DpdVN7Lm.d.cts → types-CP3KkwZt.d.cts} +1 -1
  45. package/dist/{types-DpdVN7Lm.d.ts → types-CP3KkwZt.d.ts} +1 -1
  46. package/docs/agent-guide.md +67 -1
  47. package/docs/migrate-from-ark-runtime-kernel.md +4 -2
  48. package/docs/package-surface.md +72 -0
  49. package/docs/production-hardening.md +3 -0
  50. package/package.json +11 -1
  51. package/server.json +2 -2
  52. package/templates/skills/ark-adopt.md +43 -87
  53. package/templates/skills/ark-autopilot.md +39 -77
  54. package/templates/skills/ark-contract.md +43 -84
  55. package/templates/skills/ark-coverage.md +62 -83
  56. package/templates/skills/ark-fix.md +45 -90
  57. package/templates/skills/ark-loop.md +44 -66
package/bin/ark.mjs CHANGED
@@ -10,6 +10,8 @@ import {
10
10
  buildArchitectureRecommendation,
11
11
  detectPackageManager,
12
12
  detectWorkspaces,
13
+ resolveIncludeRoots,
14
+ detectTsPackageRoots,
13
15
  INIT_WIZARD_CHOICES,
14
16
  isValidArchetypeId,
15
17
  mapWizardChoiceToArchetype,
@@ -345,16 +347,32 @@ async function start(args) {
345
347
  if (!fs.existsSync(configPath)) {
346
348
  const initArgs = ['--root', root, '--init'];
347
349
  const preset = archetype ? resolveArchetypePreset(archetype).preset : undefined;
350
+ const includeRoots = resolveIncludeRoots(root);
351
+ const tsPackages = detectTsPackageRoots(root);
348
352
  const workspaces = detectWorkspaces(root);
349
353
  const looksLikeMonorepo =
354
+ includeRoots.length > 0 ||
355
+ tsPackages.length > 0 ||
350
356
  workspaces.length > 0 ||
357
+ fs.existsSync(path.join(root, 'rush.json')) ||
358
+ fs.existsSync(path.join(root, 'pnpm-workspace.yaml')) ||
359
+ fs.existsSync(path.join(root, 'lerna.json')) ||
351
360
  fs.existsSync(path.join(root, 'apps')) ||
352
361
  fs.existsSync(path.join(root, 'packages'));
353
- // Mature multi-package trees must NOT get a thin src/** starter (0 files → false green).
354
- // Prefer the monorepo preset so include roots match apps/packages/tooling.
355
- if (looksLikeMonorepo && (rec?.mature || workspaces.length > 0)) {
356
- initArgs.push('--preset', 'monorepo');
357
- console.log(' Multi-package layout detected — using monorepo profile.');
362
+ // Mature multi-package / nested-TS trees must NOT get a thin src/** starter (0 files).
363
+ if (looksLikeMonorepo && (rec?.mature || includeRoots.length > 0 || tsPackages.length > 0)) {
364
+ // UI-heavy TS packages (Remotion/Vite) prefer ui-surface patterns when recommend says so.
365
+ const useUi =
366
+ rec?.preset === 'feature-sliced' ||
367
+ rec?.archetype === 'frontend-surface' ||
368
+ (tsPackages.length > 0 && includeRoots.length === 0 && !rec?.mature);
369
+ initArgs.push('--preset', useUi && tsPackages.length <= 3 ? 'ui-surface' : 'monorepo');
370
+ const shown = includeRoots.length > 0 ? includeRoots : tsPackages;
371
+ console.log(
372
+ shown.length > 0
373
+ ? ` Multi-package / TS package layout detected — profile include: ${shown.join(', ')}.`
374
+ : ' Multi-package layout detected — using monorepo profile.'
375
+ );
358
376
  } else if (!rec?.mature && preset) {
359
377
  initArgs.push('--preset', preset);
360
378
  }
@@ -363,7 +381,12 @@ async function start(args) {
363
381
  } else {
364
382
  console.log(' Found an existing ark.config.json — keeping it.');
365
383
  }
366
- runArkCheck(['--root', root, '--install-agent-gates'], { cwd: root });
384
+ {
385
+ const gateArgs = ['--root', root, '--install-agent-gates'];
386
+ if (args.tools) gateArgs.push('--tools', args.tools);
387
+ if (args.force) gateArgs.push('--force');
388
+ runArkCheck(gateArgs, { cwd: root });
389
+ }
367
390
 
368
391
  // 4) Show the plan: what's safe to auto-fix vs what needs a decision.
369
392
  console.log('');
@@ -406,49 +429,36 @@ async function start(args) {
406
429
  planOk = false;
407
430
  }
408
431
 
409
- // 5) Plain-language wrap-up — three operating modes, one contract.
410
- // suggest = greenfield shape proposal; adapt = match real layout / raise coverage;
411
- // enforce = contract actually governs code and gates stay on.
432
+ // 5) Plain-language wrap-up — one next step, status light only.
433
+ // Modes are detected (Suggest/Adapt/Enforce), not user-picked settings.
412
434
  console.log('');
413
435
  if (mode === 'enforce' && planOk) {
414
- console.log('Done — Ark is in ENFORCE mode: your contract governs the code and the gates stay on.');
436
+ console.log('Done — status: ENFORCE (gates can honestly protect you).');
415
437
  console.log('What happens now:');
416
438
  console.log(' • Every edit is checked (in CI and, if wired, at write time).');
417
- console.log(' • Carry out remaining plan steps with /ark-autopilot (safe auto + your approvals).');
418
439
  } else if (mode === 'suggest') {
419
- console.log('Done — Ark is in SUGGEST mode: a starting shape is installed; enforcement grows as you add layers.');
440
+ console.log('Done — status: SUGGEST (starting shape installed; expand as you grow).');
420
441
  console.log('What happens now:');
421
- console.log(' • Gates are on for whatever the contract already matches.');
422
- console.log(' • Expand coverage as you create real layer folders (see the plan above).');
423
442
  if (governedPercent != null) {
424
- console.log(` • Right now Ark governs ~${governedPercent}% of in-scope files — low is normal on a fresh scaffold.`);
443
+ console.log(` • Ark governs ~${governedPercent}% of in-scope files — low is normal on a fresh scaffold.`);
425
444
  }
426
- console.log(' • When you want the agent to drive the plan: /ark-autopilot');
427
445
  } else {
428
- console.log('Done — Ark is in ADAPT mode: config is in place, but the contract still needs to match your real layout.');
446
+ console.log('Done — status: ADAPT (contract still aligning with your real layout).');
429
447
  console.log('What happens now:');
430
448
  if (governedPercent != null) {
431
449
  console.log(
432
- ` • Governed coverage is ~${governedPercent}% — a "clean" plan with low coverage checks almost nothing.`
450
+ ` • Governed ~${governedPercent}% — a "clean" plan with low coverage checks almost nothing.`
433
451
  );
434
452
  }
435
- console.log(` • See what is unmatched: ${arkCommand(root, 'ark-check', '--coverage')}`);
436
- console.log(' • On a mature repo, prefer /ark-adopt over forcing a starter preset.');
437
- console.log(' • Drive fixes with /ark-autopilot once the contract matches; until then ENFORCE is not honest.');
438
- }
439
- console.log(` • Re-run the plan anytime: ${arkCommand(root, 'ark-check', '--plan')}`);
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')}`);
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
453
  }
454
+ console.log('');
455
+ console.log('Next (the only flow you need):');
456
+ console.log(' 1. In your agent: /ark-autopilot');
457
+ console.log(' → origin report, adoption, plan, safe fixes, leave gates on.');
458
+ console.log(` 2. Status anytime: ${arkCommand(root, 'ark-check', '--doctor')}`);
459
+ console.log(` 3. After edits: ${arkCommand(root, 'ark-check', '--root . --config ark.config.json --strict-config')}`);
460
+ console.log('');
461
+ console.log('Optional later: --plan · --coverage · /ark-fix · /ark-place · ark upgrade');
452
462
 
453
463
  // 6) First architecture report — freezes an origin snapshot under .ark/reports/
454
464
  // so later --report runs can show evolution. Idempotent: origin is written only once.