arkgate 2.8.3 → 2.9.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 (53) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +2 -1
  3. package/bin/ark-check.mjs +2 -2
  4. package/bin/ark-layer-match.mjs +88 -5
  5. package/bin/ark-mcp.mjs +7 -70
  6. package/bin/ark-shared.mjs +88 -8
  7. package/bin/ark.mjs +3 -2
  8. package/bin/lib/architecture-scan.mjs +16 -4
  9. package/bin/lib/config-warnings.mjs +11 -2
  10. package/bin/lib/doctor-plan.mjs +20 -0
  11. package/bin/lib/import-resolve.mjs +133 -0
  12. package/bin/lib/presets.mjs +207 -11
  13. package/bin/lib/remediation.mjs +15 -0
  14. package/bin/lib/suggestions.mjs +8 -3
  15. package/dist/eslint/index.cjs +63 -5
  16. package/dist/eslint/index.cjs.map +1 -1
  17. package/dist/eslint/index.d.cts +33 -1
  18. package/dist/eslint/index.d.ts +33 -1
  19. package/dist/eslint/index.js +63 -5
  20. package/dist/eslint/index.js.map +1 -1
  21. package/dist/index.cjs +103 -14
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +21 -9
  24. package/dist/index.d.ts +21 -9
  25. package/dist/index.js +103 -14
  26. package/dist/index.js.map +1 -1
  27. package/dist/nestjs/index.cjs +78 -4
  28. package/dist/nestjs/index.cjs.map +1 -1
  29. package/dist/nestjs/index.d.cts +1 -1
  30. package/dist/nestjs/index.d.ts +1 -1
  31. package/dist/nestjs/index.js +78 -4
  32. package/dist/nestjs/index.js.map +1 -1
  33. package/dist/runtime/index.cjs +103 -14
  34. package/dist/runtime/index.cjs.map +1 -1
  35. package/dist/runtime/index.d.cts +1 -1
  36. package/dist/runtime/index.d.ts +1 -1
  37. package/dist/runtime/index.js +103 -14
  38. package/dist/runtime/index.js.map +1 -1
  39. package/dist/{types-CSJhEOk2.d.cts → types-D6Q8WHes.d.cts} +7 -0
  40. package/dist/{types-CSJhEOk2.d.ts → types-D6Q8WHes.d.ts} +7 -0
  41. package/docs/agent-guide.md +55 -4
  42. package/package.json +3 -1
  43. package/server.json +2 -2
  44. package/templates/architecture-playbook.json +65 -1
  45. package/templates/policy-packs/enthusiast-ddd-bounded-contexts.json +19 -0
  46. package/templates/policy-packs/enthusiast-ui-surface.json +18 -0
  47. package/templates/policy-packs/enthusiast-vertical-slice.json +18 -0
  48. package/templates/skills/ark-adopt.md +4 -0
  49. package/templates/skills/ark-architect.md +5 -1
  50. package/templates/skills/ark-autopilot.md +3 -1
  51. package/templates/skills/ark-fix.md +3 -0
  52. package/templates/skills/ark-place.md +7 -0
  53. package/templates/skills/ark-think.md +43 -0
@@ -600,6 +600,82 @@ async function recordInterceptorError(interceptor, event, error, deps) {
600
600
  });
601
601
  }
602
602
 
603
+ // src/domain/layerMatch.ts
604
+ function normalizeGlobSeparators(pattern) {
605
+ let out = "";
606
+ for (let i = 0; i < pattern.length; i += 1) {
607
+ const c = pattern[i];
608
+ if (c === "\\" && i + 1 < pattern.length) {
609
+ const next = pattern[i + 1];
610
+ if ("*?{}[],".includes(next) || next === "\\") {
611
+ out += "\\" + next;
612
+ i += 1;
613
+ continue;
614
+ }
615
+ out += "/";
616
+ continue;
617
+ }
618
+ out += c;
619
+ }
620
+ return out;
621
+ }
622
+ function sliceIdForPath(relPath, sliceFolders) {
623
+ if (!sliceFolders?.length) return void 0;
624
+ const parts = String(relPath).split(/[/\\]/).filter(Boolean);
625
+ const folders = new Set(sliceFolders.map((s) => String(s).toLowerCase()));
626
+ for (let i = 0; i < parts.length - 1; i += 1) {
627
+ if (folders.has(parts[i].toLowerCase())) {
628
+ return `${parts[i]}/${parts[i + 1]}`;
629
+ }
630
+ }
631
+ return void 0;
632
+ }
633
+ function inferSliceFoldersFromPatterns(patterns) {
634
+ const out = /* @__PURE__ */ new Set();
635
+ for (const pattern of patterns ?? []) {
636
+ const glob = normalizeGlobSeparators(String(pattern));
637
+ const parts = glob.split("/").filter(Boolean);
638
+ for (let i = 0; i < parts.length; i += 1) {
639
+ const part = parts[i];
640
+ if ((part === "**" || part === "*") && i > 0) {
641
+ const prev = parts[i - 1];
642
+ if (prev && !prev.includes("*") && !prev.includes("{") && !prev.includes("}")) {
643
+ out.add(prev);
644
+ }
645
+ }
646
+ }
647
+ }
648
+ return [...out];
649
+ }
650
+ function resolveSliceFolders(rule, layerName, layers) {
651
+ if (Array.isArray(rule.sliceFolders) && rule.sliceFolders.length > 0) {
652
+ return rule.sliceFolders.filter((s) => typeof s === "string" && s.length > 0);
653
+ }
654
+ const layer = (layers ?? []).find((l) => l.name === layerName);
655
+ return inferSliceFoldersFromPatterns(layer?.patterns);
656
+ }
657
+ function findDeniedEdgeRule(rules, from, to, options) {
658
+ for (const rule of rules ?? []) {
659
+ if (rule.from !== from || rule.to !== to) continue;
660
+ if (rule.allowed !== false) continue;
661
+ if (rule.peerIsolation) {
662
+ const fromPath = options?.fromPath;
663
+ const toPath = options?.toPath;
664
+ if (!fromPath || !toPath) continue;
665
+ const folders = resolveSliceFolders(rule, from, options?.layers);
666
+ if (folders.length === 0) continue;
667
+ const fromSlice = sliceIdForPath(fromPath, folders);
668
+ const toSlice = sliceIdForPath(toPath, folders);
669
+ if (!fromSlice || !toSlice) continue;
670
+ if (fromSlice !== toSlice) return rule;
671
+ continue;
672
+ }
673
+ if (from === to) continue;
674
+ return rule;
675
+ }
676
+ return void 0;
677
+ }
678
+
603
679
  // src/kernel/event-bus/observedLayerFlow.ts
604
680
  async function assertObservedLayerFlowAllowed(event, deps) {
605
681
  if (deps.mode === "off" || !deps.architectureProfile) {
@@ -611,9 +687,7 @@ async function assertObservedLayerFlowAllowed(event, deps) {
611
687
  const fromLayer = profile.resolveLayer(source);
612
688
  const toLayer = profile.resolveLayer(event.intent);
613
689
  if (!fromLayer || !toLayer) return;
614
- const blocked = profile.rules.find(
615
- (rule) => !rule.allowed && rule.from === fromLayer && rule.to === toLayer
616
- );
690
+ const blocked = findDeniedEdgeRule(profile.rules, fromLayer, toLayer);
617
691
  if (!blocked) return;
618
692
  const severity = deps.mode;
619
693
  const message = blocked.message ?? `Observed layer violation: "${source}" (${fromLayer}) must not produce "${event.intent}" (${toLayer}).`;
@@ -1727,7 +1801,7 @@ var elevenLayerProfile = createArchitectureProfile({
1727
1801
  var MANIFEST_SCHEMA_VERSION = "1.0";
1728
1802
 
1729
1803
  // src/version.ts
1730
- var version = "2.8.3";
1804
+ var version = "2.9.0";
1731
1805
 
1732
1806
  // src/kernel/manifest/createArkManifest.ts
1733
1807
  function policyId(name) {