arkgate 4.0.1 → 4.1.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 (52) hide show
  1. package/CHANGELOG.md +90 -0
  2. package/README.md +6 -5
  3. package/bin/ark-check-runtime.mjs +244 -25
  4. package/bin/ark-check.mjs +10 -1
  5. package/bin/ark-layer-match.mjs +80 -5
  6. package/bin/ark-shared.mjs +170 -9
  7. package/bin/ark.mjs +52 -5
  8. package/bin/lib/adapter-contract.mjs +7 -1
  9. package/bin/lib/agent-gates.mjs +2 -0
  10. package/bin/lib/analysis-engine.mjs +6 -6
  11. package/bin/lib/arkrules-sensors.mjs +63 -22
  12. package/bin/lib/ci-and-commands.mjs +148 -8
  13. package/bin/lib/core-ratchet.mjs +9 -4
  14. package/bin/lib/doctor-advisories.mjs +8 -1
  15. package/bin/lib/doctor-plan.mjs +277 -59
  16. package/bin/lib/enforcement-honesty.mjs +351 -26
  17. package/bin/lib/enforcement-state.mjs +1 -1
  18. package/bin/lib/field-install.mjs +35 -2
  19. package/bin/lib/html-report-depth.mjs +167 -3
  20. package/bin/lib/html-report.mjs +12 -5
  21. package/bin/lib/install-migrate.mjs +109 -6
  22. package/bin/lib/managed-upgrade.mjs +99 -0
  23. package/bin/lib/presets.mjs +314 -46
  24. package/bin/lib/project-root.mjs +268 -0
  25. package/bin/lib/remediation.mjs +12 -11
  26. package/bin/lib/rules-inventory.mjs +71 -29
  27. package/bin/lib/rules-under-contract.mjs +134 -4
  28. package/bin/lib/start-preview.mjs +48 -14
  29. package/bin/lib/suggestions.mjs +118 -3
  30. package/bin/lib/unavailable-analysis.mjs +2 -0
  31. package/bin/lib/write-path-capabilities.mjs +38 -9
  32. package/dist/eslint/index.cjs +2 -2
  33. package/dist/eslint/index.d.ts +27 -2
  34. package/dist/eslint/index.js +2 -2
  35. package/dist/index.cjs +16 -14
  36. package/dist/index.d.ts +3 -1
  37. package/dist/index.js +16 -14
  38. package/docs/README.md +3 -3
  39. package/docs/ai-gates.md +15 -11
  40. package/docs/brownfield-adoption.md +36 -0
  41. package/docs/configuration.md +36 -0
  42. package/docs/package-surface.md +3 -3
  43. package/docs/product-voice.md +7 -0
  44. package/docs/typescript-support.md +9 -5
  45. package/package.json +3 -1
  46. package/server.json +3 -3
  47. package/templates/architecture-playbook.json +3 -0
  48. package/templates/layers/shared-types.starter.json +29 -0
  49. package/templates/skills/ark-adopt.md +2 -0
  50. package/templates/skills/ark-explain.md +5 -0
  51. package/templates/skills/ark-explore.md +21 -1
  52. package/templates/skills/ark-fix.md +16 -5
@@ -122,8 +122,21 @@ function commands(root, args, helpers) {
122
122
  return result;
123
123
  }
124
124
 
125
- export function renderStartPreview(preview) {
126
- console.log('Ark start preview no files were changed.');
125
+ /**
126
+ * @param {object} preview
127
+ * @param {{ applying?: boolean }} [options] when applying=true, do not claim “no files were changed”
128
+ */
129
+ export function renderStartPreview(preview, options = {}) {
130
+ const applying = options.applying === true;
131
+ if (applying) {
132
+ console.log(
133
+ preview.changes.length === 0
134
+ ? 'Ark start apply — reviewing plan (no mutations pending).'
135
+ : `Ark start apply — writing ${preview.changes.length} planned mutation(s).`
136
+ );
137
+ } else {
138
+ console.log('Ark start preview — no files were changed.');
139
+ }
127
140
  if (preview.analysis) {
128
141
  console.log(`Your project looks like: ${preview.analysis.label} (${preview.analysis.archetype}, confidence ${preview.analysis.confidence}).`);
129
142
  }
@@ -135,20 +148,24 @@ export function renderStartPreview(preview) {
135
148
  console.log(
136
149
  `Compact setup budget: ${gateCount}/${budget.maxFiles} gate files${arkrulesNote}, ${budget.bytes}/${budget.maxBytes} bytes${budget.ok ? '' : ' (exceeded)'}.`
137
150
  );
138
- console.log('Files to create/edit/delete:');
151
+ console.log(applying ? 'Files create/edit/delete:' : 'Files to create/edit/delete:');
139
152
  if (preview.changes.length === 0) console.log(' (none)');
140
153
  for (const change of preview.changes) {
141
154
  console.log(` ${change.action.padEnd(6)} ${change.path} ${change.afterHash ?? '(deleted)'}`);
142
155
  }
143
- console.log('Commands in the approved setup plan:');
144
- for (const command of preview.commands) console.log(` ${command}`);
156
+ if (!applying) {
157
+ console.log('Commands in the approved setup plan:');
158
+ for (const command of preview.commands) console.log(` ${command}`);
159
+ }
145
160
  console.log('Host guarantees:');
146
161
  for (const guarantee of preview.hostGuarantees) console.log(` ${guarantee}`);
147
162
  if (preview.unresolvedDecisions.length > 0) {
148
163
  console.log('Unresolved decisions:');
149
164
  for (const decision of preview.unresolvedDecisions) console.log(` ${decision}`);
150
165
  }
151
- console.log('Review complete file contents with --json. Apply this plan with: ark start --apply');
166
+ if (!applying) {
167
+ console.log('Review complete file contents with --json. Apply this plan with: ark start --apply');
168
+ }
152
169
  }
153
170
 
154
171
  export function applyStartPreview(root, preview) {
@@ -224,16 +241,30 @@ export async function planStart(args, helpers) {
224
241
  const root = args.root;
225
242
  const before = treeFiles(root);
226
243
  let recommendation = null;
227
- try {
228
- const rec = buildArchitectureRecommendation(root);
244
+ // Wire --archetype / --preset into the plan so apply locks the chosen shape (not just recommend).
245
+ if (args.archetype || args.preset) {
229
246
  recommendation = {
230
- archetype: rec.archetype,
231
- label: rec.label,
232
- confidence: rec.confidence,
233
- mature: rec.mature,
247
+ archetype: args.archetype || args.preset,
248
+ label: args.archetype
249
+ ? `explicit archetype ${args.archetype}`
250
+ : `explicit preset ${args.preset}`,
251
+ confidence: 1,
252
+ mature: false,
253
+ explicitShape: true,
254
+ preset: args.preset || null,
234
255
  };
235
- } catch {
236
- recommendation = null;
256
+ } else {
257
+ try {
258
+ const rec = buildArchitectureRecommendation(root);
259
+ recommendation = {
260
+ archetype: rec.archetype,
261
+ label: rec.label,
262
+ confidence: rec.confidence,
263
+ mature: rec.mature,
264
+ };
265
+ } catch {
266
+ recommendation = null;
267
+ }
237
268
  }
238
269
  const shadowRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'ark-start-preview-'));
239
270
  try {
@@ -253,6 +284,9 @@ export async function planStart(args, helpers) {
253
284
  else childArgs.push('--install');
254
285
  if (args.tools) childArgs.push('--tools', args.tools);
255
286
  if (args.requireWriteHook) childArgs.push('--require-write-hook', args.requireWriteHook);
287
+ // Lock archetype/preset into the shadow apply so the plan matches the gate bypass.
288
+ if (args.archetype) childArgs.push('--archetype', args.archetype);
289
+ if (args.preset) childArgs.push('--preset', args.preset);
256
290
  const planned = spawnSync(process.execPath, [helpers.cliPath, ...childArgs], {
257
291
  cwd: shadowRoot,
258
292
  encoding: 'utf8',
@@ -15,6 +15,68 @@ export function dirSegmentsFromGlob(pattern) {
15
15
  .filter((segment) => segment && !segment.includes('*'));
16
16
  }
17
17
 
18
+ /**
19
+ * Basename / path tokens that score as Persistence (data clients, auth, CRM).
20
+ * Used so adopt never maps lib/turso → Presentation (NEW-ADOPT-LIB-AS-PRESENTATION).
21
+ */
22
+ export const PERSISTENCE_PATH_TOKENS = Object.freeze([
23
+ 'turso',
24
+ 'prisma',
25
+ 'supabase',
26
+ 'airtable',
27
+ 'drizzle',
28
+ 'kysely',
29
+ 'mongoose',
30
+ 'mongodb',
31
+ 'firebase',
32
+ 'firestore',
33
+ 'planetscale',
34
+ 'neon',
35
+ 'pipedrive',
36
+ 'repository',
37
+ 'repositories',
38
+ 'persistence',
39
+ 'infrastructure',
40
+ 'infra',
41
+ 'db',
42
+ 'auth',
43
+ 'session',
44
+ ]);
45
+
46
+ /** True when a path/basename looks like a data or auth client (not UI). */
47
+ export function isPersistenceClientPath(relPath) {
48
+ const posix = String(relPath || '')
49
+ .split(/[/\\]/)
50
+ .filter(Boolean)
51
+ .join('/');
52
+ if (!posix) return false;
53
+ const lower = posix.toLowerCase();
54
+ const base = path.posix.basename(lower).replace(/\.(ts|tsx|js|jsx|mjs|cjs)$/i, '');
55
+ for (const token of PERSISTENCE_PATH_TOKENS) {
56
+ if (base === token || base.startsWith(`${token}.`) || base.startsWith(`${token}-`) || base.startsWith(`${token}_`)) {
57
+ return true;
58
+ }
59
+ if (lower.includes(`/${token}/`) || lower.endsWith(`/${token}`) || lower.startsWith(`${token}/`)) {
60
+ return true;
61
+ }
62
+ }
63
+ return false;
64
+ }
65
+
66
+ /** True when a path looks like pure domain folders. */
67
+ export function isDomainPath(relPath) {
68
+ const posix = String(relPath || '')
69
+ .split(/[/\\]/)
70
+ .filter(Boolean)
71
+ .join('/')
72
+ .toLowerCase();
73
+ return (
74
+ /(?:^|\/)domain(?:\/|$)/.test(posix) ||
75
+ /(?:^|\/)entities(?:\/|$)/.test(posix) ||
76
+ /(?:^|\/)kernel\/domain(?:\/|$)/.test(posix)
77
+ );
78
+ }
79
+
18
80
  let _layerByDir;
19
81
  // Map<dirBasename, string[] layers>. A basename mapping to >1 layer (e.g. `app` — Application
20
82
  // orchestration in the 11-layer defaults, but Presentation in the monorepo/Next preset) is
@@ -58,11 +120,64 @@ export function suggestLayerForDir(name) {
58
120
 
59
121
  // Suggest a layer for a directory PATH by finding the deepest segment Ark recognizes, so
60
122
  // `src/lib/repositories` proposes PersistenceAdapters even though `lib` itself is unknown.
123
+ // Next App Router / Pages API shells (`…/app/api`, `…/pages/api`) are Application, not Presentation.
124
+ // Never map bare `lib` alone to Presentation (NEW-ADOPT-LIB-AS-PRESENTATION).
61
125
  export function suggestLayerForPath(relDir) {
62
- const segments = relDir.split('/').filter(Boolean);
126
+ const posix = String(relDir || '')
127
+ .split(/[/\\]/)
128
+ .filter(Boolean)
129
+ .join('/');
130
+ // Prefer the API orchestration shell over a bare `app` / `pages` Presentation match.
131
+ // Direct api/ and route-group shells: app/(marketing)/api/**
132
+ if (
133
+ /(?:^|\/)(?:src\/)?app(?:\/[^/]+)*\/api(?:\/|$)/.test(posix) ||
134
+ /(?:^|\/)(?:src\/)?pages(?:\/[^/]+)*\/api(?:\/|$)/.test(posix)
135
+ ) {
136
+ return {
137
+ layer: 'ApplicationOrchestration',
138
+ alternatives: [],
139
+ matchedDir: posix.includes('pages') && posix.includes('/api') ? 'pages/…/api' : 'app/…/api',
140
+ };
141
+ }
142
+ // Root / Vercel serverless api handlers (SPA layout).
143
+ if (/(?:^|\/)api(?:\/|$)/.test(posix) && !/(?:^|\/)app(?:\/|$)/.test(posix)) {
144
+ return {
145
+ layer: 'ApplicationOrchestration',
146
+ alternatives: [],
147
+ matchedDir: 'api',
148
+ };
149
+ }
150
+ if (isDomainPath(posix)) {
151
+ return { layer: 'DomainModel', alternatives: [], matchedDir: 'domain' };
152
+ }
153
+ if (isPersistenceClientPath(posix)) {
154
+ return {
155
+ layer: 'PersistenceAdapters',
156
+ alternatives: [],
157
+ matchedDir: path.posix.basename(posix) || 'persistence',
158
+ };
159
+ }
160
+ const segments = posix.split('/').filter(Boolean);
63
161
  for (let i = segments.length - 1; i >= 0; i -= 1) {
64
- const hit = suggestLayerForDir(segments[i]);
65
- if (hit) return { ...hit, matchedDir: segments[i] };
162
+ const seg = segments[i];
163
+ // Bare `lib` is not Presentation leave unrecognized so agents classify children.
164
+ if (seg === 'lib' || seg === 'src') continue;
165
+ const hit = suggestLayerForDir(seg);
166
+ if (hit) {
167
+ // Never promote Presentation solely because a parent was `lib`.
168
+ if (hit.layer === 'PresentationAdapters' && segments.includes('lib')) {
169
+ // Prefer Persistence when any sibling token smells like data; else skip.
170
+ if (isPersistenceClientPath(posix)) {
171
+ return {
172
+ layer: 'PersistenceAdapters',
173
+ alternatives: [],
174
+ matchedDir: seg,
175
+ };
176
+ }
177
+ continue;
178
+ }
179
+ return { ...hit, matchedDir: seg };
180
+ }
66
181
  }
67
182
  return null;
68
183
  }
@@ -41,6 +41,8 @@ export function reportUnavailableAnalysis({
41
41
  runDoctor(root, config, files, rules, [], args.json, {
42
42
  configPath,
43
43
  configMissing: !fs.existsSync(configPath),
44
+ configRoot: args.configRoot ?? root,
45
+ configWalkedUp: args.configWalkedUp === true,
44
46
  parseHealth,
45
47
  completeness,
46
48
  });
@@ -19,7 +19,7 @@ import {
19
19
  } from './host-support-matrix.mjs';
20
20
  import { detectActiveAgentHost } from './skill-install.mjs';
21
21
  import { detectCiEnforcement } from './weakest-link.mjs';
22
- import { buildEnforcementState } from './enforcement-state.mjs';
22
+ import { buildEnforcementState, packageInstallation } from './enforcement-state.mjs';
23
23
 
24
24
  export const WRITE_CAPABILITY_NAMES = [
25
25
  'hard-write',
@@ -46,29 +46,47 @@ function operationCovered(profile, operation) {
46
46
  return profile.hookOperations.some((candidate) => candidate.toLowerCase() === normalized);
47
47
  }
48
48
 
49
- function buildEnforcementLadder(activeHost, support, evidence, attempt) {
50
- const localInstalled = evidence['hard-write'].length > 0;
49
+ /**
50
+ * Local write ladder. Hook assets alone never prove hard without package install.
51
+ * @param {string} activeHost
52
+ * @param {object|null} support
53
+ * @param {Record<string, string[]>} evidence
54
+ * @param {object|undefined} attempt
55
+ * @param {{ packageInstalled?: boolean }} [opts]
56
+ */
57
+ function buildEnforcementLadder(activeHost, support, evidence, attempt, opts = {}) {
58
+ const hookConfigured = evidence['hard-write'].length > 0;
59
+ const packageInstalled = opts.packageInstalled !== false;
51
60
  const observedPreTool = attempt?.boundary === 'pre-tool';
52
61
  const covered = observedPreTool && operationCovered(support, attempt.operation);
62
+ // P0B-PIN-ABSENT-WRITEPATH: never hard:true without pin+node_modules (packageInstalled).
63
+ // Hook config / observed coverage can still be active or operationCovered without hard.
53
64
  const hard = Boolean(
54
- support?.capabilities['hard-write'] && (localInstalled || observedPreTool) && covered
65
+ support?.capabilities['hard-write'] &&
66
+ packageInstalled &&
67
+ (hookConfigured || observedPreTool) &&
68
+ covered
55
69
  );
56
- const inferredActive = (installed) => (installed ? 'unverified' : false);
70
+ // Configured assets active "unverified" even when package is absent (hard stays false).
71
+ const inferredActive = (configured) => (configured ? 'unverified' : false);
57
72
  return {
58
73
  schemaVersion: '1.0',
59
74
  activeHost,
60
75
  localWrite: boundaryState({
61
76
  supported: Boolean(support?.capabilities['hard-write']),
62
77
  evidence: evidence['hard-write'],
63
- active: observedPreTool ? covered : inferredActive(localInstalled),
78
+ active: observedPreTool ? Boolean(covered) : inferredActive(hookConfigured),
64
79
  bypassable: !hard,
65
80
  hard,
66
81
  extra: {
67
- installed: localInstalled || observedPreTool,
82
+ // Ladder "installed" here means hook assets; package install lives in enforcementState.
83
+ installed: hookConfigured || observedPreTool,
84
+ packageInstalled,
85
+ // completePatch describes op scope (coverage), not package install.
68
86
  completePatch: Boolean(covered && attempt?.completePatch),
69
87
  coverage: covered && attempt?.completePatch ? 'complete-patch' : support?.hookSurface ?? null,
70
88
  ...(observedPreTool
71
- ? { operation: attempt.operation, operationCovered: covered }
89
+ ? { operation: attempt.operation, operationCovered: Boolean(covered) }
72
90
  : { operationCovered: 'unverified' }),
73
91
  },
74
92
  }),
@@ -441,20 +459,31 @@ export function buildWritePathCapabilityModel(root, explicitHost, attempt) {
441
459
  'merge-gate': [...inventory.evidence['merge-gate']],
442
460
  };
443
461
 
462
+ const pkg = packageInstallation(root);
444
463
  const model = {
445
464
  activeHost,
446
465
  support: getHostSupportProfile(activeHost),
447
466
  capabilities: capabilityMap(capabilityEvidence),
448
467
  capabilityEvidence,
468
+ packageInstallation: pkg,
449
469
  enforcementLadder: buildEnforcementLadder(
450
470
  activeHost,
451
471
  getHostSupportProfile(activeHost),
452
472
  capabilityEvidence,
453
- attempt
473
+ attempt,
474
+ { packageInstalled: pkg.installed === true }
454
475
  ),
455
476
  inventory,
456
477
  };
457
478
  model.enforcementState = buildEnforcementState(root, { ...model, ci });
458
479
  model.enforcementLadder.ciMerge.requiredStatus = model.enforcementState.ciMerge.required;
480
+ // Ladder/state agreement stamp for pin-absent consumers (configured ≠ installed).
481
+ if (pkg.installed !== true) {
482
+ model.packagePinHonesty = {
483
+ code: 'PACKAGE_PIN_ABSENT',
484
+ hard: false,
485
+ note: 'arkgate not resolved from project — ladder and enforcementState hard stay false (configured hooks ≠ installed).',
486
+ };
487
+ }
459
488
  return model;
460
489
  }
@@ -1,3 +1,3 @@
1
- "use strict";var Re=Object.create;var L=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var we=Object.getOwnPropertyNames;var Ee=Object.getPrototypeOf,Ce=Object.prototype.hasOwnProperty;var Ne=(e,t)=>{for(var n in t)L(e,n,{get:t[n],enumerable:!0})},z=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of we(t))!Ce.call(e,r)&&r!==n&&L(e,r,{get:()=>t[r],enumerable:!(s=xe(t,r))||s.enumerable});return e};var J=(e,t,n)=>(n=e!=null?Re(Ee(e)):{},z(t||!e||!e.__esModule?L(n,"default",{value:e,enumerable:!0}):n,e)),Le=e=>z(L({},"__esModule",{value:!0}),e);var et={};Ne(et,{default:()=>Qe,findConfigPath:()=>$,globToRegExp:()=>w,isEdgeDenied:()=>V,layerForRelativePath:()=>k,loadArkConfig:()=>T,noDeniedCapabilities:()=>Ie,noDomainInfraImports:()=>he,noForbiddenGlobals:()=>Se,noRawEventPublish:()=>Ae,patternSpecificity:()=>M,plugin:()=>P,requirePublishSource:()=>ke,resolveRelativeImport:()=>fe});module.exports=Le(et);var I=J(require("fs"),1),p=J(require("path"),1);var Z=new Map;function X(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function D(e){let t="";for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=s}return t}function Oe(e){let t=0;for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"){n+=1;continue}if(s==="{")t+=1;else if(s==="}"&&(t-=1,t<0))return!1}return t===0}function w(e){let t=Z.get(e);if(t)return t;let n=D(e),s=Oe(n),r="",a=0;for(let c=0;c<n.length;c+=1){let g=n[c];g==="\\"&&c+1<n.length?(r+=X(n[c+1]),c+=1):g==="*"?n[c+1]==="*"?n[c+2]==="/"?(r+="(?:.*/)?",c+=2):(r+=".*",c+=1):r+="[^/]*":g==="?"?r+="[^/]":g==="{"&&s?(r+="(?:",a+=1):g==="}"&&s&&a>0?(r+=")",a-=1):g===","&&s&&a>0?r+="|":r+=X(g)}let l=new RegExp(`^${r}$`);return Z.set(e,l),l}function M(e){let t=D(String(e)),s=t.split("*")[0].split("/").filter(Boolean).length,r=t.replace(/\*/g,"").length;return s*1e4+r}function k(e,t){let n=String(e).split(/[/\\]/).join("/"),s,r=-1;for(let a of t??[])if(!(a.exclude??[]).some(l=>w(l).test(n))){for(let l of a.patterns??[])if(w(l).test(n)){let c=M(l);c>r&&(r=c,s=a.name)}}return s}function Q(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),s=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(s.has(n[r].toLowerCase()))return`${n[r].toLowerCase()}/${n[r+1].toLowerCase()}`}function _e(e){let t=new Set;for(let n of e??[]){let r=D(String(n)).split("/").filter(Boolean);for(let a=0;a<r.length;a+=1){let l=r[a];if((l==="**"||l==="*")&&a>0){let c=r[a-1];c&&!c.includes("*")&&!c.includes("{")&&!c.includes("}")&&t.add(c)}}}return[...t]}function ve(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let s=(n??[]).find(r=>r.name===t);return _e(s?.patterns)}function Pe(e,t,n,s){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let a=s?.fromPath,l=s?.toPath;if(!a||!l)return r;let c=ve(r,t,s?.layers);if(c.length===0)return r;let g=Q(a,c),m=Q(l,c);if(!g||!m||g!==m)return r;continue}if(t!==n)return r}}function V(e,t,n,s){return Pe(e,t,n,s)!==void 0}var $e=["**/*.gen.ts","**/*.gen.tsx","**/*.generated.ts","**/*.generated.tsx"];function Te(e){let t=Array.isArray(e?.exclude)?e.exclude.filter(s=>typeof s=="string"):[];return[...e?.excludeGenerated===!1?[]:$e,...t]}function ee(e,t){let n=String(e).split(/[/\\]/).join("/");return Te(t).some(s=>w(s).test(n))}var te=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),je=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),rt=Object.freeze(Object.keys(je).sort()),F=Object.freeze({fs:"filesystem","node:fs":"filesystem","fs/promises":"filesystem","node:fs/promises":"filesystem","fs-extra":"filesystem","graceful-fs":"filesystem",memfs:"filesystem",chokidar:"filesystem",http:"network",https:"network",http2:"network",net:"network",tls:"network",dgram:"network",dns:"network","node:http":"network","node:https":"network","node:http2":"network","node:net":"network","node:tls":"network","node:dgram":"network","node:dns":"network",axios:"network",undici:"network","node-fetch":"network",got:"network",ky:"network",superagent:"network",ws:"network",process:"process","node:process":"process",child_process:"process","node:child_process":"process","@prisma/client":"persistence",prisma:"persistence",pg:"persistence",mysql:"persistence",mysql2:"persistence",mongodb:"persistence",mongoose:"persistence",sqlite3:"persistence","better-sqlite3":"persistence",redis:"persistence",ioredis:"persistence",typeorm:"persistence",knex:"persistence","drizzle-orm":"persistence",sequelize:"persistence",kysely:"persistence","@supabase/supabase-js":"persistence"}),De=Object.freeze({process:Object.freeze(["process","node:process"])});function ne(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=F[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let s=e.slice(0,n),r=F[s];if(r)return r;let a=e.indexOf("/",n+1);return a<0?null:F[e.slice(0,a)]??null}function K(e,t){for(let n of t)if(De[n]?.includes(e))return n;return null}function re(e){if(e?.pure===!0)return[...te].sort();let n=(e?.capabilities?.deny??[]).filter(s=>te.includes(s));return[...new Set(n)].sort()}var H="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",se=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],Me=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function Ve(){let e=[];for(let t of se)for(let n of se)t===n||Me.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var oe=Ve(),G=[{from:"unversioned",to:"1.0"},{from:"1.0",to:"1.1"}],A={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},ie={$schema:"https://json-schema.org/draft/2020-12/schema",$id:H,title:"ArkGate architecture contract",description:"Versioned contract consumed identically by ArkGate CLI, MCP, and ESLint surfaces.",type:"object",additionalProperties:!1,required:["$schema","schemaVersion","include","layers","rules"],properties:{$schema:{type:"string",minLength:1,default:H,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.1",default:"1.1"},name:{type:"string",minLength:1},include:{...A,minItems:1,default:["src"]},exclude:{...A,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:oe,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...A,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}},arkRules:{type:"object",additionalProperties:{type:"string",minLength:1},default:{}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...A,minItems:1},exclude:A,intentPrefixes:A,description:{type:"string",minLength:1},forbiddenGlobals:A,capabilities:{type:"object",additionalProperties:!1,properties:{deny:{type:"array",uniqueItems:!0,items:{type:"string",enum:["network","filesystem","clock","randomness","environment","process","persistence"]}}}},pure:{type:"boolean"},mayImportInfrastructure:{type:"boolean"},optional:{type:"boolean"}}},rule:{type:"object",additionalProperties:!1,required:["from","to","allowed"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},allowed:{type:"boolean"},message:{type:"string",minLength:1},peerIsolation:{type:"boolean"},sliceFolders:{...A,minItems:1}}},safety:{type:"object",additionalProperties:!1,properties:{maxTsSuppressions:{type:"integer",minimum:0,default:0},maxAnyCasts:{type:"integer",minimum:0,default:0},allowInMemory:{type:"boolean",default:!1},allowDisabledPeerIsolation:{type:"boolean",default:!1}}}}},h=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
1
+ "use strict";var Oe=Object.create;var L=Object.defineProperty;var _e=Object.getOwnPropertyDescriptor;var ve=Object.getOwnPropertyNames;var Pe=Object.getPrototypeOf,$e=Object.prototype.hasOwnProperty;var Te=(e,t)=>{for(var n in t)L(e,n,{get:t[n],enumerable:!0})},Q=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ve(t))!$e.call(e,r)&&r!==n&&L(e,r,{get:()=>t[r],enumerable:!(s=_e(t,r))||s.enumerable});return e};var ee=(e,t,n)=>(n=e!=null?Oe(Pe(e)):{},Q(t||!e||!e.__esModule?L(n,"default",{value:e,enumerable:!0}):n,e)),je=e=>Q(L({},"__esModule",{value:!0}),e);var at={};Te(at,{default:()=>it,findConfigPath:()=>T,globToRegExp:()=>E,isEdgeDenied:()=>F,layerForRelativePath:()=>R,loadArkConfig:()=>j,noDeniedCapabilities:()=>Le,noDomainInfraImports:()=>we,noForbiddenGlobals:()=>Ne,noRawEventPublish:()=>Ee,patternSpecificity:()=>D,plugin:()=>$,readTsconfigPathAliases:()=>he,requirePublishSource:()=>Ce,resolveImportSpecifier:()=>ke,resolveRelativeImport:()=>Ae});module.exports=je(at);var S=ee(require("fs"),1),d=ee(require("path"),1);var te=new Map;function ne(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function O(e){let t="";for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=s}return t}function Me(e){let t=0;for(let n=0;n<e.length;n+=1){let s=e[n];if(s==="\\"){n+=1;continue}if(s==="{")t+=1;else if(s==="}"&&(t-=1,t<0))return!1}return t===0}function E(e){let t=te.get(e);if(t)return t;let n=O(e),s=Me(n),r="",i=0;for(let c=0;c<n.length;c+=1){let g=n[c];g==="\\"&&c+1<n.length?(r+=ne(n[c+1]),c+=1):g==="*"?n[c+1]==="*"?n[c+2]==="/"?(r+="(?:.*/)?",c+=2):(r+=".*",c+=1):r+="[^/]*":g==="?"?r+="[^/]":g==="{"&&s?(r+="(?:",i+=1):g==="}"&&s&&i>0?(r+=")",i-=1):g===","&&s&&i>0?r+="|":r+=ne(g)}let l=new RegExp(`^${r}$`);return te.set(e,l),l}function De(e){return O(String(e)).split("/").filter(Boolean).filter(n=>n!=="**"&&n!=="*"&&!n.includes("*")&&!n.includes("?")&&!n.includes("{")&&!n.includes("["))}function D(e,t){let n=O(String(e)),s=De(n),r=n.replace(/\*/g,"").length,i=s.length*1e4+r;if(t==null||t==="")return i;let l=String(t).split(/[/\\]/).filter(Boolean);if(s.length===0)return r;let c=0,g=-1;for(let f of s){let p=-1;for(let o=c;o<l.length;o+=1)if(l[o]===f){p=o;break}if(p<0)return i;g=p,c=p+1}return(g+1)*1e6+s.length*1e4+r}function R(e,t){let n=String(e).split(/[/\\]/).join("/"),s,r=-1;for(let i of t??[])if(!(i.exclude??[]).some(l=>E(l).test(n))){for(let l of i.patterns??[])if(E(l).test(n)){let c=D(l,n);c>r&&(r=c,s=i.name)}}return s}function re(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),s=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(s.has(n[r].toLowerCase()))return`${n[r].toLowerCase()}/${n[r+1].toLowerCase()}`}function Ve(e){let t=new Set;for(let n of e??[]){let r=O(String(n)).split("/").filter(Boolean);for(let i=0;i<r.length;i+=1){let l=r[i];if((l==="**"||l==="*")&&i>0){let c=r[i-1];c&&!c.includes("*")&&!c.includes("{")&&!c.includes("}")&&t.add(c)}}}return[...t]}function Fe(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let s=(n??[]).find(r=>r.name===t);return Ve(s?.patterns)}function V(e,t,n,s){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let i=s?.fromPath,l=s?.toPath;if(!i||!l)return r;let c=Fe(r,t,s?.layers);if(c.length===0)return r;let g=re(i,c),f=re(l,c);if(!g||!f||g!==f)return r;continue}if(t!==n)return r}}function F(e,t,n,s){return V(e,t,n,s)!==void 0}var He=["**/*.gen.ts","**/*.gen.tsx","**/*.generated.ts","**/*.generated.tsx"];function Ke(e){let t=Array.isArray(e?.exclude)?e.exclude.filter(s=>typeof s=="string"):[];return[...e?.excludeGenerated===!1?[]:He,...t]}function se(e,t){let n=String(e).split(/[/\\]/).join("/");return Ke(t).some(s=>E(s).test(n))}var oe=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),Ge=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),pt=Object.freeze(Object.keys(Ge).sort()),H=Object.freeze({fs:"filesystem","node:fs":"filesystem","fs/promises":"filesystem","node:fs/promises":"filesystem","fs-extra":"filesystem","graceful-fs":"filesystem",memfs:"filesystem",chokidar:"filesystem",http:"network",https:"network",http2:"network",net:"network",tls:"network",dgram:"network",dns:"network","node:http":"network","node:https":"network","node:http2":"network","node:net":"network","node:tls":"network","node:dgram":"network","node:dns":"network",axios:"network",undici:"network","node-fetch":"network",got:"network",ky:"network",superagent:"network",ws:"network",process:"process","node:process":"process",child_process:"process","node:child_process":"process","@prisma/client":"persistence",prisma:"persistence",pg:"persistence",mysql:"persistence",mysql2:"persistence",mongodb:"persistence",mongoose:"persistence",sqlite3:"persistence","better-sqlite3":"persistence",redis:"persistence",ioredis:"persistence",typeorm:"persistence",knex:"persistence","drizzle-orm":"persistence",sequelize:"persistence",kysely:"persistence","@supabase/supabase-js":"persistence"}),Be=Object.freeze({process:Object.freeze(["process","node:process"])});function ie(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=H[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let s=e.slice(0,n),r=H[s];if(r)return r;let i=e.indexOf("/",n+1);return i<0?null:H[e.slice(0,i)]??null}function K(e,t){for(let n of t)if(Be[n]?.includes(e))return n;return null}function ae(e){if(e?.pure===!0)return[...oe].sort();let n=(e?.capabilities?.deny??[]).filter(s=>oe.includes(s));return[...new Set(n)].sort()}var G="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",le=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],Ue=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function qe(){let e=[];for(let t of le)for(let n of le)t===n||Ue.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var pe=qe(),B=[{from:"unversioned",to:"1.0"},{from:"1.0",to:"1.1"}],I={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},ce={$schema:"https://json-schema.org/draft/2020-12/schema",$id:G,title:"ArkGate architecture contract",description:"Versioned contract consumed identically by ArkGate CLI, MCP, and ESLint surfaces.",type:"object",additionalProperties:!1,required:["$schema","schemaVersion","include","layers","rules"],properties:{$schema:{type:"string",minLength:1,default:G,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.1",default:"1.1"},name:{type:"string",minLength:1},include:{...I,minItems:1,default:["src"]},exclude:{...I,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:pe,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...I,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}},arkRules:{type:"object",additionalProperties:{type:"string",minLength:1},default:{}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...I,minItems:1},exclude:I,intentPrefixes:I,description:{type:"string",minLength:1},forbiddenGlobals:I,capabilities:{type:"object",additionalProperties:!1,properties:{deny:{type:"array",uniqueItems:!0,items:{type:"string",enum:["network","filesystem","clock","randomness","environment","process","persistence"]}}}},pure:{type:"boolean"},mayImportInfrastructure:{type:"boolean"},optional:{type:"boolean"}}},rule:{type:"object",additionalProperties:!1,required:["from","to","allowed"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},allowed:{type:"boolean"},message:{type:"string",minLength:1},peerIsolation:{type:"boolean"},sliceFolders:{...I,minItems:1}}},safety:{type:"object",additionalProperties:!1,properties:{maxTsSuppressions:{type:"integer",minimum:0,default:0},maxAnyCasts:{type:"integer",minimum:0,default:0},allowInMemory:{type:"boolean",default:!1},allowDisabledPeerIsolation:{type:"boolean",default:!1}}}}},k=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
2
2
  ${n.map(s=>`- ${s.path}: ${s.message}`).join(`
3
- `)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function ae(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function O(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function S(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function Fe(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function E(e,t,n,s,r){if(t.$ref){let a=Fe(t.$ref,s);if(!a){r.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}E(e,a,n,s,r);return}if(t.const!==void 0&&!Object.is(e,t.const)){r.push({path:n,message:`must equal ${JSON.stringify(t.const)}`});return}if(t.enum&&!t.enum.some(a=>Object.is(a,e))){r.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!ae(e)){r.push({path:n,message:`must be an object; received ${S(e)}`});return}let a=t.properties??{};for(let l of t.required??[])e[l]===void 0&&r.push({path:O(n,l),message:"is required"});if(t.additionalProperties===!1)for(let l of Object.keys(e))l in a||r.push({path:O(n,l),message:"unknown field"});else if(t.additionalProperties!==void 0&&t.additionalProperties!==!0&&typeof t.additionalProperties=="object"){let l=t.additionalProperties;for(let c of Object.keys(e))c in a||E(e[c],l,O(n,c),s,r)}for(let[l,c]of Object.entries(a))e[l]!==void 0&&E(e[l],c,O(n,l),s,r);return}if(t.type==="array"){if(!Array.isArray(e)){r.push({path:n,message:`must be an array; received ${S(e)}`});return}if(t.minItems!==void 0&&e.length<t.minItems&&r.push({path:n,message:`must contain at least ${t.minItems} item(s)`}),t.uniqueItems){let a=e.map(l=>JSON.stringify(l));new Set(a).size!==a.length&&r.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((a,l)=>E(a,t.items,`${n}[${l}]`,s,r));return}if(t.type==="string"){if(typeof e!="string"){r.push({path:n,message:`must be a string; received ${S(e)}`});return}t.minLength!==void 0&&e.length<t.minLength&&r.push({path:n,message:`must contain at least ${t.minLength} character(s)`});return}if(t.type==="boolean"){typeof e!="boolean"&&r.push({path:n,message:`must be a boolean; received ${S(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){r.push({path:n,message:`must be an integer; received ${S(e)}`});return}t.minimum!==void 0&&e<t.minimum&&r.push({path:n,message:`must be at least ${t.minimum}`})}}function Ke(e){return{...e,$schema:e.$schema===void 0?H:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.1":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?oe.map(t=>({...t})):e.rules}}function He(){let e=new Set(["1.1"]);for(let t of G)t.from!=="unversioned"&&e.add(t.from),e.add(t.to);return e}function Ge(e,t="ark.config.json"){if(!ae(e))throw new h(t,[{path:"$",message:`must be an object; received ${S(e)}`}]);let n=He(),s=e.schemaVersion===void 0?"unversioned":typeof e.schemaVersion=="string"?e.schemaVersion:null;if(s===null)throw new h(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.1`}]);if(s!=="unversioned"&&!n.has(s))throw new h(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);let r=s,a={...e},l=0;for(;r!=="1.1"&&l<G.length+1;){l+=1;let g=G.find(m=>m.from===r);if(!g)throw new h(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);r=g.to,a.schemaVersion=r}if(r!=="1.1")throw new h(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);let c=s==="unversioned"?"unversioned":s==="1.0"?"1.0":null;return{candidate:Ke(a),migratedFrom:c}}function Be(e,t="ark.config.json"){let{candidate:n,migratedFrom:s}=Ge(e,t),r=[];if(E(n,ie,"$",ie,r),r.length>0)throw new h(t,r);return{config:n,migratedFrom:s}}function le(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(s){throw new h(t,[{path:"$",message:`invalid JSON: ${s instanceof Error?s.message:String(s)}`}])}return Be(n,t)}function y(e){return typeof e=="string"&&e.length>0?e:void 0}function ce(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Ue(e,t,n){if(e==="LAYER_IMPORT_VIOLATION")return t.typeOnly||n.targetTypeOnlyExports===!0||n.namedBindingsTypeOnly===!0?"Move the referenced type to a mutually allowed layer, use `import type`, then preflight again.":n.peerIsolation===!0?"Extract the shared dependency to a shared layer, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${y(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, then preflight again.";if(e==="RAW_EVENT_PUBLISH")return"Publish through a registered intent creator, then run Ark again.";if(e==="PUBLISH_MISSING_SOURCE")return"Add metadata.source to the publish call, then run Ark again.";if(e==="ARKRULE_STRUCTURE"||e==="ARKRULE_INVARIANT"||e==="INVARIANT_UNCOVERED"||e.startsWith("ARKRULE_")){let s=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${s}), then preflight again. Do not demote the rule without a hash-bound policy acknowledgement.`}return`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function de(e,t="error"){let n=y(e.ruleId)??y(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"?"warning":t,r={...y(e.target)?{target:y(e.target)}:{},...y(e.fromLayer)?{fromLayer:y(e.fromLayer)}:{},...y(e.toLayer)?{toLayer:y(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{},...typeof e.targetTypeOnlyExports=="boolean"?{targetTypeOnlyExports:e.targetTypeOnlyExports}:{},...typeof e.sourcePureTypeModule=="boolean"?{sourcePureTypeModule:e.sourcePureTypeModule}:{},...typeof e.namedBindingsTypeOnly=="boolean"?{namedBindingsTypeOnly:e.namedBindingsTypeOnly}:{},...typeof e.portProofEligible=="boolean"?{portProofEligible:e.portProofEligible}:{},...typeof e.peerIsolation=="boolean"?{peerIsolation:e.peerIsolation}:{},...y(e.capability)?{capability:y(e.capability)}:{},...y(e.edgeKind)?{edgeKind:y(e.edgeKind)}:{},...y(e.arkruleId)?{arkruleId:y(e.arkruleId)}:{},...y(e.arkruleSource)?{arkruleSource:y(e.arkruleSource)}:{}};return{ruleId:n,severity:s,message:y(e.message)??n,location:{file:y(e.file)??"<unknown>",line:ce(e.line,1),column:ce(e.column,1)},evidence:r,nextAction:y(e.nextAction)??Ue(n,r,e)}}var pe={RAW_EVENT_PUBLISH:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts and tooling.",PUBLISH_MISSING_SOURCE:"Strict Ark publish calls must include metadata.source."},at=Object.freeze([{layer:"DomainModel",prefixes:["Domain."]},{layer:"ApplicationOrchestration",prefixes:["Application."]},{layer:"PersistenceAdapters",prefixes:["Adapter.Persistence.","Adapter.Repository."]},{layer:"IntegrationAdapters",prefixes:["Adapter.Integration.","Adapter.External."]},{layer:"WorkflowSagaEngine",prefixes:["Workflow."]},{layer:"BackgroundJobsScheduling",prefixes:["Job."]},{layer:"PresentationAdapters",prefixes:["Presentation.","Adapter.Presentation.","Adapter.Api."]},{layer:"ReportingReadModels",prefixes:["Reporting."]},{layer:"ExtensibilityMetadata",prefixes:["Metadata."]},{layer:"SecurityAuditObservability",prefixes:["Security.","Audit.","Observability."]},{layer:"Kernel",prefixes:["Kernel."]}]);function qe(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function B(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&qe(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:pe.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:pe.PUBLISH_MISSING_SOURCE}),t}function C(e){if(typeof e.physicalFilename=="string"&&e.physicalFilename.length>0)return e.physicalFilename;if(typeof e.filename=="string"&&e.filename.length>0)return e.filename;if(typeof e.getFilename=="function")try{let t=e.getFilename();if(typeof t=="string"&&t.length>0)return t}catch{}return""}function R(e,t,n,s,r){let a=de({...s,line:s.line??t.loc?.start?.line,column:s.column??(typeof t.loc?.start?.column=="number"?t.loc.start.column+1:void 0)});return e.report({node:t,messageId:n,...r?{data:r}:{},diagnostic:a}),a}function $(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=p.default.dirname(p.default.resolve(e));for(;;){let n=p.default.join(t,"ark.config.json");if(I.default.existsSync(n))return n;let s=p.default.dirname(t);if(s===t)return null;t=s}}var ue=new Map;function T(e){if(!I.default.existsSync(e))return null;let t=I.default.readFileSync(e,"utf8"),n=ue.get(e);if(n?.source===t)return n.config;let s=le(t,e).config;return ue.set(e,{source:t,config:s}),s}function q(e,t){return(e.include??[]).some(s=>{let r=String(s).replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/$/,"");return r==="."||t===r||t.startsWith(`${r}/`)})&&!ee(t,e)}function fe(e,t){if(!t.startsWith("."))return null;let n=p.default.resolve(p.default.dirname(e),t),s=[n,`${n}.ts`,`${n}.tsx`,`${n}.mts`,`${n}.cts`,`${n}.js`,`${n}.jsx`,p.default.join(n,"index.ts"),p.default.join(n,"index.tsx"),p.default.join(n,"index.js")];for(let r of s)try{if(I.default.existsSync(r)&&I.default.statSync(r).isFile())return r}catch{}return null}function j(e){return typeof e?.value=="string"?e.value:void 0}function W(e){return e?.name??j(e)}function Y(e){return e.sourceCode??e.getSourceCode?.()}function ge(e,t){let n=Y(e)?.getScope?.(t);for(;n;){let s=n.references?.find(r=>r.identifier===t);if(s)return s;n=n.upper??void 0}}function _(e,t,n){let s=ge(e,t);if(s?.resolved)return(s.resolved.defs?.length??0)>0;let r=Y(e)?.getScope?.(t);for(;r;){let a=r.set?.get(n);if(a)return(a.defs?.length??0)>0;r=r.upper??void 0}return!1}function We(e,t){let n=ge(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function me(e){if(e?.type==="Identifier"&&e.name)return{root:e,segments:[e.name]};if(!e||!(e.type==="MemberExpression"||!!(e.object&&e.property))||e.computed===!0)return;let n=me(e.object),s=W(e.property);if(!(!n||!s))return{root:n.root,segments:[...n.segments,s]}}function Ye(e){return W(e.callee?.property)}function ye(e,t){return e?.properties?.find(n=>W(n.key)===t)}function v(e,t){return ye(e,t)!==void 0}function ze(e){let t=ye(e,"metadata")?.value;return v(t,"source")}function be(e){return Ye(e)==="publish"}function U(e){if(e.importKind==="type"||e.exportKind==="type")return!0;let t=e.specifiers??[];return t.length===0?!1:t.every(n=>n.type==="ImportSpecifier")?t.every(n=>n.importKind==="type"):t.every(n=>n.exportKind==="type")}function Je(e){let t=e;for(;t?.parent;)t=t.parent;return t?.type==="Program"?t:void 0}function Ze(e){let t=Je(e)?.body;if(!t)return!1;let n=!1;for(let s of t){if(s.type==="ImportDeclaration"){if(!U(s))return!1;continue}if(!(s.type==="TSInterfaceDeclaration"||s.type==="TSTypeAliasDeclaration")){if(s.type==="ExportNamedDeclaration"){if(s.declaration){if(s.declaration.type!=="TSInterfaceDeclaration"&&s.declaration.type!=="TSTypeAliasDeclaration")return!1}else if(!U(s))return!1;n=!0;continue}return!1}}return n}var he={meta:{type:"problem",docs:{description:"Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check)."},messages:{forbiddenImport:"Architecture: {{fromLayer}} must not import {{toLayer}} (ark.config.json). Specifier: {{specifier}}",forbiddenImportHeuristic:"Domain code must not import infrastructure, adapters, repositories, or database modules."},schema:[]},create(e){let t=C(e),n=$(t),s=n?T(n):null,r=n?p.default.dirname(n):null,a=l=>{let c=j(l.source);if(c&&s&&r&&t){let g=p.default.isAbsolute(t)?t:p.default.resolve(t),m=p.default.relative(r,g).split(p.default.sep).join("/");if(!q(s,m))return;let d=k(m,s.layers);if(!d)return;let i=fe(g,c);if(!i)return;let o=p.default.relative(r,i).split(p.default.sep).join("/");if(o.startsWith(".."))return;let u=k(o,s.layers);if(!u)return;if(V(s.rules,d,u,{fromPath:m,toPath:o,layers:s.layers})){let f=l.type?.startsWith("Export")?"export":"import";R(e,l,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:m,fromLayer:d,toLayer:u,target:o,edgeKind:f,...U(l)?{typeOnly:!0}:{},...Ze(l)?{sourcePureTypeModule:!0}:{},message:`${d} must not ${f} ${u}.`},{fromLayer:d,toLayer:u,specifier:c})}return}};return{ImportDeclaration:a,ExportNamedDeclaration:a,ExportAllDeclaration:a}}},Ae={meta:{type:"problem",docs:{description:"Require event bus publish calls to use registered intent creators instead of raw event objects or intent strings."},messages:{rawPublish:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],s=j(n),r=B({publishCall:be(t),rawIntentName:s,objectHasIntent:v(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(r.some(a=>a.ruleId==="RAW_EVENT_PUBLISH")){let a=r.find(l=>l.ruleId==="RAW_EVENT_PUBLISH");R(e,t,"rawPublish",{...a,file:C(e)})}}}}},ke={meta:{type:"problem",docs:{description:"Require event bus publish calls to include source metadata."},messages:{missingSource:"Strict Ark publish calls must include metadata.source."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],s=t.arguments?.[2],a=B({publishCall:be(t),rawIntentName:j(n),objectHasIntent:v(n,"intent"),arkPublishCandidate:!0,hasSource:ze(n)||v(s,"source")}).find(l=>l.ruleId==="PUBLISH_MISSING_SOURCE");a&&R(e,t,"missingSource",{...a,file:C(e)})}}}},Se={meta:{type:"problem",docs:{description:"Disallow ambient globals from the layer\u2019s forbiddenGlobals in ark.config.json (same purity surface as ark-check). Option `globals` is a standalone fallback when no project config applies."},messages:{forbiddenGlobal:'Ambient global "{{name}}" is forbidden in {{layer}} (ark.config.json); inject the capability through a port instead.',forbiddenGlobalDefault:'Ambient global "{{name}}" is forbidden here; inject the capability through a port instead.',forbiddenModule:'{{layer}} must not use module "{{specifier}}" because it is the import form of forbidden global "{{name}}".'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=C(e),n=e.options?.[0],s=$(t),r=s?T(s):null,a=s?p.default.dirname(s):null,l=null,c="this layer";if(r&&a&&t){let i=p.default.isAbsolute(t)?t:p.default.resolve(t),o=p.default.relative(a,i).split(p.default.sep).join("/");if(!q(r,o))return{};let u=r.layers?.find(f=>f.name===k(o,r.layers));u?.forbiddenGlobals?.length?(l=new Set(u.forbiddenGlobals),c=u.name):l=null}else n?.globals&&(l=new Set(n.globals));if(!l)return{};let g=typeof Y(e)?.getScope=="function",m=(i,o)=>{let u=p.default.isAbsolute(t)?t:p.default.resolve(t),f=a?p.default.relative(a,u).split(p.default.sep).join("/"):t;R(e,i,r?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:f,fromLayer:c,target:o,message:`${c} must not use the ambient global "${o}".`},{name:o,layer:c})},d=(i,o,u,f)=>{if(u||typeof o!="string")return;let b=K(o,l);if(!b)return;let x=p.default.isAbsolute(t)?t:p.default.resolve(t),N=a?p.default.relative(a,x).split(p.default.sep).join("/"):t;R(e,i,"forbiddenModule",{ruleId:"FORBIDDEN_GLOBAL",file:N,fromLayer:c,target:o,edgeKind:f,message:`${c} must not use module "${o}" because it is the import form of forbidden global "${b}".`},{layer:c,name:b,specifier:o,importKind:f})};return{MemberExpression(i){if(i.parent?.type==="MemberExpression"&&i.parent.object===i)return;let o=me(i);if(!o||_(e,o.root,o.segments[0]))return;let u=o.segments[0]==="globalThis",f=u?o.segments.slice(1):o.segments,b;for(let x=f.length;x>=(u?1:2);x-=1){let N=f.slice(0,x).join(".");if(l.has(N)){b=N;break}}b?m(i,b):!g&&l.has(o.segments[0])&&m(i,o.segments[0])},CallExpression(i){let o=i;if(o.callee?.type==="Identifier"&&o.callee.name==="require"&&o.arguments?.[0]?.type==="Literal"&&!_(e,i,"require")&&d(i,o.arguments[0].value,!1,"require"),g)return;let u=o.callee?.type==="Identifier"?o.callee.name:void 0;u&&l.has(u)&&m(i,u)},ImportDeclaration(i){let o=i,u=(o.specifiers??[]).filter(b=>b.type==="ImportSpecifier"),f=u.length>0&&u.length===(o.specifiers??[]).length&&u.every(b=>b.importKind==="type");d(i,o.source?.value,o.importKind==="type"||f,"import")},ImportExpression(i){let o=i;o.source?.type==="Literal"&&d(i,o.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(i){let o=i;d(i,o.moduleReference?.expression?.value,o.importKind==="type"||o.isTypeOnly===!0,"require")},ExportNamedDeclaration(i){let o=i;if(!o.source)return;let u=o.specifiers??[],f=u.length>0&&u.every(b=>b.exportKind==="type");d(i,o.source.value,o.exportKind==="type"||f,"export")},ExportAllDeclaration(i){let o=i;d(i,o.source?.value,o.exportKind==="type","export")},NewExpression(i){if(g)return;let o=i.callee?.type==="Identifier"?i.callee.name:void 0;o&&l.has(o)&&m(i,o)},Identifier(i){!g||!i.name||!l.has(i.name)||!We(e,i)||_(e,i,i.name)||m(i,i.name)}}}},Ie={meta:{type:"problem",docs:{description:"Disallow importing modules whose effect capability the layer denies (ark.config.json capabilities.deny / pure \u2014 same wall surface as ark-check). Import dimension only: ambient globals stay with no-forbidden-globals and the CLI/hook symbol path."},messages:{deniedCapability:'{{layer}} denies the {{capability}} capability (ark.config.json); "{{specifier}}" imports it. Define a port and bind the implementation in an adapter layer.'},schema:[]},create(e){let t=C(e),n=$(t),s=n?T(n):null,r=n?p.default.dirname(n):null;if(!s||!r||!t)return{};let a=p.default.isAbsolute(t)?t:p.default.resolve(t),l=p.default.relative(r,a).split(p.default.sep).join("/");if(!q(s,l))return{};let c=s.layers?.find(d=>d.name===k(l,s.layers));if(!c)return{};let g=new Set(re(c));if(g.size===0)return{};let m=(d,i,o,u)=>{if(o||typeof i!="string"||K(i,c.forbiddenGlobals??[]))return;let f=ne(i);!f||!g.has(f)||R(e,d,"deniedCapability",{ruleId:"CAPABILITY_VIOLATION",file:l,fromLayer:c.name,target:i,capability:f,edgeKind:u,message:`${c.name} denies the ${f} capability; found import of "${i}".`},{layer:c.name,capability:f,specifier:i})};return{ImportDeclaration(d){let i=d,o=(i.specifiers??[]).filter(f=>f.type==="ImportSpecifier"),u=o.length>0&&o.length===(i.specifiers??[]).length&&o.every(f=>f.importKind==="type");m(d,i.source?.value,i.importKind==="type"||u,"import")},ImportExpression(d){let i=d;i.source?.type==="Literal"&&m(d,i.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(d){let i=d;m(d,i.moduleReference?.expression?.value,i.importKind==="type"||i.isTypeOnly===!0,"require")},ExportNamedDeclaration(d){let i=d;if(!i.source)return;let o=i.specifiers??[],u=o.length>0&&o.every(f=>f.exportKind==="type");m(d,i.source.value,i.exportKind==="type"||u,"export")},ExportAllDeclaration(d){let i=d;m(d,i.source?.value,i.exportKind==="type","export")},CallExpression(d){let i=d;i.callee?.type==="Identifier"&&i.callee.name==="require"&&i.arguments?.[0]?.type==="Literal"&&!_(e,d,"require")&&m(d,i.arguments[0].value,!1,"require")}}}},Xe={"no-domain-infra-imports":he,"no-raw-event-publish":Ae,"require-publish-source":ke,"no-forbidden-globals":Se,"no-denied-capabilities":Ie},P={rules:Xe};P.configs={recommended:{plugins:{ark:P},rules:{"ark/no-domain-infra-imports":"error","ark/no-raw-event-publish":"error","ark/require-publish-source":"error","ark/no-forbidden-globals":"error","ark/no-denied-capabilities":"error"}}};var Qe=P;0&&(module.exports={findConfigPath,globToRegExp,isEdgeDenied,layerForRelativePath,loadArkConfig,noDeniedCapabilities,noDomainInfraImports,noForbiddenGlobals,noRawEventPublish,patternSpecificity,plugin,requirePublishSource,resolveRelativeImport});
3
+ `)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function de(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function _(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function x(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function We(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function C(e,t,n,s,r){if(t.$ref){let i=We(t.$ref,s);if(!i){r.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}C(e,i,n,s,r);return}if(t.const!==void 0&&!Object.is(e,t.const)){r.push({path:n,message:`must equal ${JSON.stringify(t.const)}`});return}if(t.enum&&!t.enum.some(i=>Object.is(i,e))){r.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!de(e)){r.push({path:n,message:`must be an object; received ${x(e)}`});return}let i=t.properties??{};for(let l of t.required??[])e[l]===void 0&&r.push({path:_(n,l),message:"is required"});if(t.additionalProperties===!1)for(let l of Object.keys(e))l in i||r.push({path:_(n,l),message:"unknown field"});else if(t.additionalProperties!==void 0&&t.additionalProperties!==!0&&typeof t.additionalProperties=="object"){let l=t.additionalProperties;for(let c of Object.keys(e))c in i||C(e[c],l,_(n,c),s,r)}for(let[l,c]of Object.entries(i))e[l]!==void 0&&C(e[l],c,_(n,l),s,r);return}if(t.type==="array"){if(!Array.isArray(e)){r.push({path:n,message:`must be an array; received ${x(e)}`});return}if(t.minItems!==void 0&&e.length<t.minItems&&r.push({path:n,message:`must contain at least ${t.minItems} item(s)`}),t.uniqueItems){let i=e.map(l=>JSON.stringify(l));new Set(i).size!==i.length&&r.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((i,l)=>C(i,t.items,`${n}[${l}]`,s,r));return}if(t.type==="string"){if(typeof e!="string"){r.push({path:n,message:`must be a string; received ${x(e)}`});return}t.minLength!==void 0&&e.length<t.minLength&&r.push({path:n,message:`must contain at least ${t.minLength} character(s)`});return}if(t.type==="boolean"){typeof e!="boolean"&&r.push({path:n,message:`must be a boolean; received ${x(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){r.push({path:n,message:`must be an integer; received ${x(e)}`});return}t.minimum!==void 0&&e<t.minimum&&r.push({path:n,message:`must be at least ${t.minimum}`})}}function Ye(e){return{...e,$schema:e.$schema===void 0?G:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.1":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?pe.map(t=>({...t})):e.rules}}function Je(){let e=new Set(["1.1"]);for(let t of B)t.from!=="unversioned"&&e.add(t.from),e.add(t.to);return e}function ze(e,t="ark.config.json"){if(!de(e))throw new k(t,[{path:"$",message:`must be an object; received ${x(e)}`}]);let n=Je(),s=e.schemaVersion===void 0?"unversioned":typeof e.schemaVersion=="string"?e.schemaVersion:null;if(s===null)throw new k(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.1`}]);if(s!=="unversioned"&&!n.has(s))throw new k(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);let r=s,i={...e},l=0;for(;r!=="1.1"&&l<B.length+1;){l+=1;let g=B.find(f=>f.from===r);if(!g)throw new k(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);r=g.to,i.schemaVersion=r}if(r!=="1.1")throw new k(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);let c=s==="unversioned"?"unversioned":s==="1.0"?"1.0":null;return{candidate:Ye(i),migratedFrom:c}}function Ze(e,t="ark.config.json"){let{candidate:n,migratedFrom:s}=ze(e,t),r=[];if(C(n,ce,"$",ce,r),r.length>0)throw new k(t,r);return{config:n,migratedFrom:s}}function ue(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(s){throw new k(t,[{path:"$",message:`invalid JSON: ${s instanceof Error?s.message:String(s)}`}])}return Ze(n,t)}function b(e){return typeof e=="string"&&e.length>0?e:void 0}function fe(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Xe(e,t,n){if(e==="LAYER_IMPORT_VIOLATION")return t.typeOnly||n.targetTypeOnlyExports===!0||n.namedBindingsTypeOnly===!0?"Move the referenced type to a mutually allowed layer, use `import type`, then preflight again.":n.peerIsolation===!0?"Extract the shared dependency to a shared layer, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${b(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, then preflight again.";if(e==="RAW_EVENT_PUBLISH")return"Publish through a registered intent creator, then run Ark again.";if(e==="PUBLISH_MISSING_SOURCE")return"Add metadata.source to the publish call, then run Ark again.";if(e==="ARKRULE_STRUCTURE"||e==="ARKRULE_INVARIANT"||e==="INVARIANT_UNCOVERED"||e.startsWith("ARKRULE_")){let s=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${s}), then preflight again. Do not demote the rule without a hash-bound policy acknowledgement.`}return`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function ge(e,t="error"){let n=b(e.ruleId)??b(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"||e.failsStrict===!1||e.typeOnly===!0&&e.peerIsolation!==!0?"warning":t,r={...b(e.target)?{target:b(e.target)}:{},...b(e.fromLayer)?{fromLayer:b(e.fromLayer)}:{},...b(e.toLayer)?{toLayer:b(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{},...typeof e.targetTypeOnlyExports=="boolean"?{targetTypeOnlyExports:e.targetTypeOnlyExports}:{},...typeof e.sourcePureTypeModule=="boolean"?{sourcePureTypeModule:e.sourcePureTypeModule}:{},...typeof e.namedBindingsTypeOnly=="boolean"?{namedBindingsTypeOnly:e.namedBindingsTypeOnly}:{},...typeof e.portProofEligible=="boolean"?{portProofEligible:e.portProofEligible}:{},...typeof e.peerIsolation=="boolean"?{peerIsolation:e.peerIsolation}:{},...b(e.capability)?{capability:b(e.capability)}:{},...b(e.edgeKind)?{edgeKind:b(e.edgeKind)}:{},...b(e.arkruleId)?{arkruleId:b(e.arkruleId)}:{},...b(e.arkruleSource)?{arkruleSource:b(e.arkruleSource)}:{}};return{ruleId:n,severity:s,message:b(e.message)??n,location:{file:b(e.file)??"<unknown>",line:fe(e.line,1),column:fe(e.column,1)},evidence:r,nextAction:b(e.nextAction)??Xe(n,r,e)}}var me={RAW_EVENT_PUBLISH:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts and tooling.",PUBLISH_MISSING_SOURCE:"Strict Ark publish calls must include metadata.source."},gt=Object.freeze([{layer:"DomainModel",prefixes:["Domain."]},{layer:"ApplicationOrchestration",prefixes:["Application."]},{layer:"PersistenceAdapters",prefixes:["Adapter.Persistence.","Adapter.Repository."]},{layer:"IntegrationAdapters",prefixes:["Adapter.Integration.","Adapter.External."]},{layer:"WorkflowSagaEngine",prefixes:["Workflow."]},{layer:"BackgroundJobsScheduling",prefixes:["Job."]},{layer:"PresentationAdapters",prefixes:["Presentation.","Adapter.Presentation.","Adapter.Api."]},{layer:"ReportingReadModels",prefixes:["Reporting."]},{layer:"ExtensibilityMetadata",prefixes:["Metadata."]},{layer:"SecurityAuditObservability",prefixes:["Security.","Audit.","Observability."]},{layer:"Kernel",prefixes:["Kernel."]}]);function Qe(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function U(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&Qe(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:me.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:me.PUBLISH_MISSING_SOURCE}),t}function N(e){if(typeof e.physicalFilename=="string"&&e.physicalFilename.length>0)return e.physicalFilename;if(typeof e.filename=="string"&&e.filename.length>0)return e.filename;if(typeof e.getFilename=="function")try{let t=e.getFilename();if(typeof t=="string"&&t.length>0)return t}catch{}return""}function w(e,t,n,s,r){let i=ge({...s,line:s.line??t.loc?.start?.line,column:s.column??(typeof t.loc?.start?.column=="number"?t.loc.start.column+1:void 0)});return e.report({node:t,messageId:n,...r?{data:r}:{},diagnostic:i}),i}function T(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=d.default.dirname(d.default.resolve(e));for(;;){let n=d.default.join(t,"ark.config.json");if(S.default.existsSync(n))return n;let s=d.default.dirname(t);if(s===t)return null;t=s}}var ye=new Map;function j(e){if(!S.default.existsSync(e))return null;let t=S.default.readFileSync(e,"utf8"),n=ye.get(e);if(n?.source===t)return n.config;let s=ue(t,e).config;return ye.set(e,{source:t,config:s}),s}function W(e,t){return(e.include??[]).some(s=>{let r=String(s).replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/$/,"");return r==="."||t===r||t.startsWith(`${r}/`)})&&!se(t,e)}function be(e){let t=[e,`${e}.ts`,`${e}.tsx`,`${e}.mts`,`${e}.cts`,`${e}.js`,`${e}.jsx`,d.default.join(e,"index.ts"),d.default.join(e,"index.tsx"),d.default.join(e,"index.js")];for(let n of t)try{if(S.default.existsSync(n)&&S.default.statSync(n).isFile())return n}catch{}return null}function he(e){let t=d.default.resolve(e),n=null;for(;;){let f=d.default.join(t,"tsconfig.json");if(S.default.existsSync(f)){n=f;break}let p=d.default.dirname(t);if(p===t)break;t=p}if(!n)return{baseUrl:e,aliases:[]};let s=f=>{try{let p=S.default.readFileSync(f,"utf8");return p=p.replace(/\/\*[\s\S]*?\*\//g,"").replace(/(^|[^:])\/\/.*$/gm,"$1"),JSON.parse(p)}catch{return null}},r=(f,p)=>{if(p>4)return{};let o=s(f);if(!o)return{};let a=o.compilerOptions??{},u=a.baseUrl,m=a.paths,y=o.extends;if(typeof y=="string"&&!y.startsWith("@")){let h=d.default.resolve(d.default.dirname(f),y.endsWith(".json")?y:`${y}.json`);if(S.default.existsSync(h)){let A=r(h,p+1);u=u??A.baseUrl,m={...A.paths??{},...m??{}}}}return{baseUrl:u,paths:m}},i=r(n,0),l=d.default.dirname(n),c=d.default.resolve(l,i.baseUrl||"."),g=[];for(let[f,p]of Object.entries(i.paths||{})){if(!Array.isArray(p)||p.length===0)continue;let o=f.replace(/\*$/,"");o&&g.push({from:o,to:String(p[0]).replace(/\*$/,"")})}return g.sort((f,p)=>p.from.length-f.from.length),{baseUrl:c,aliases:g}}function Ae(e,t){if(!t.startsWith("."))return null;let n=d.default.resolve(d.default.dirname(e),t);return be(n)}function ke(e,t,n){if(!t)return null;if(t.startsWith("."))return Ae(e,t);let s=n||d.default.dirname(e),{baseUrl:r,aliases:i}=he(s),l=i.find(g=>t.startsWith(g.from));if(!l)return null;let c=d.default.resolve(r,`${l.to}${t.slice(l.from.length)}`);return be(c)}function M(e){return typeof e?.value=="string"?e.value:void 0}function Y(e){return e?.name??M(e)}function J(e){return e.sourceCode??e.getSourceCode?.()}function Se(e,t){let n=J(e)?.getScope?.(t);for(;n;){let s=n.references?.find(r=>r.identifier===t);if(s)return s;n=n.upper??void 0}}function v(e,t,n){let s=Se(e,t);if(s?.resolved)return(s.resolved.defs?.length??0)>0;let r=J(e)?.getScope?.(t);for(;r;){let i=r.set?.get(n);if(i)return(i.defs?.length??0)>0;r=r.upper??void 0}return!1}function et(e,t){let n=Se(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function Ie(e){if(e?.type==="Identifier"&&e.name)return{root:e,segments:[e.name]};if(!e||!(e.type==="MemberExpression"||!!(e.object&&e.property))||e.computed===!0)return;let n=Ie(e.object),s=Y(e.property);if(!(!n||!s))return{root:n.root,segments:[...n.segments,s]}}function tt(e){return Y(e.callee?.property)}function Re(e,t){return e?.properties?.find(n=>Y(n.key)===t)}function P(e,t){return Re(e,t)!==void 0}function nt(e){let t=Re(e,"metadata")?.value;return P(t,"source")}function xe(e){return tt(e)==="publish"}function q(e){if(e.importKind==="type"||e.exportKind==="type")return!0;let t=e.specifiers??[];return t.length===0?!1:t.every(n=>n.type==="ImportSpecifier")?t.every(n=>n.importKind==="type"):t.every(n=>n.exportKind==="type")}function rt(e){let t=e;for(;t?.parent;)t=t.parent;return t?.type==="Program"?t:void 0}function st(e){let t=rt(e)?.body;if(!t)return!1;let n=!1;for(let s of t){if(s.type==="ImportDeclaration"){if(!q(s))return!1;continue}if(!(s.type==="TSInterfaceDeclaration"||s.type==="TSTypeAliasDeclaration")){if(s.type==="ExportNamedDeclaration"){if(s.declaration){if(s.declaration.type!=="TSInterfaceDeclaration"&&s.declaration.type!=="TSTypeAliasDeclaration")return!1}else if(!q(s))return!1;n=!0;continue}return!1}}return n}var we={meta:{type:"problem",docs:{description:"Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check)."},messages:{forbiddenImport:"Architecture: {{fromLayer}} must not import {{toLayer}} (ark.config.json). Specifier: {{specifier}}",forbiddenImportHeuristic:"Domain code must not import infrastructure, adapters, repositories, or database modules."},schema:[]},create(e){let t=N(e),n=T(t),s=n?j(n):null,r=n?d.default.dirname(n):null,i=l=>{let c=M(l.source);if(c&&s&&r&&t){let g=d.default.isAbsolute(t)?t:d.default.resolve(t),f=d.default.relative(r,g).split(d.default.sep).join("/");if(!W(s,f))return;let p=R(f,s.layers);if(!p)return;let o=ke(g,c,r);if(!o)return;let a=d.default.relative(r,o).split(d.default.sep).join("/");if(a.startsWith(".."))return;let u=R(a,s.layers);if(!u)return;let m={fromPath:f,toPath:a,layers:s.layers},y=V(s.rules,p,u,m);if(y||F(s.rules,p,u,m)){let h=l.type?.startsWith("Export")?"export":"import",A=q(l),z=!!y?.peerIsolation,Z=A&&!z,X=y?.message??`${p} must not ${h} ${u}.`;w(e,l,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:f,fromLayer:p,toLayer:u,target:a,edgeKind:h,...z?{peerIsolation:!0}:{},...A?{typeOnly:!0}:{},...Z?{severity:"warning"}:{},...st(l)?{sourcePureTypeModule:!0}:{},message:Z?`${X} (type-only \u2014 type placement debt; prefer SharedTypes / owning layer; not runtime coupling)`:X},{fromLayer:p,toLayer:u,specifier:c})}return}};return{ImportDeclaration:i,ExportNamedDeclaration:i,ExportAllDeclaration:i}}},Ee={meta:{type:"problem",docs:{description:"Require event bus publish calls to use registered intent creators instead of raw event objects or intent strings."},messages:{rawPublish:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],s=M(n),r=U({publishCall:xe(t),rawIntentName:s,objectHasIntent:P(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(r.some(i=>i.ruleId==="RAW_EVENT_PUBLISH")){let i=r.find(l=>l.ruleId==="RAW_EVENT_PUBLISH");w(e,t,"rawPublish",{...i,file:N(e)})}}}}},Ce={meta:{type:"problem",docs:{description:"Require event bus publish calls to include source metadata."},messages:{missingSource:"Strict Ark publish calls must include metadata.source."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],s=t.arguments?.[2],i=U({publishCall:xe(t),rawIntentName:M(n),objectHasIntent:P(n,"intent"),arkPublishCandidate:!0,hasSource:nt(n)||P(s,"source")}).find(l=>l.ruleId==="PUBLISH_MISSING_SOURCE");i&&w(e,t,"missingSource",{...i,file:N(e)})}}}},Ne={meta:{type:"problem",docs:{description:"Disallow ambient globals from the layer\u2019s forbiddenGlobals in ark.config.json (same purity surface as ark-check). Option `globals` is a standalone fallback when no project config applies."},messages:{forbiddenGlobal:'Ambient global "{{name}}" is forbidden in {{layer}} (ark.config.json); inject the capability through a port instead.',forbiddenGlobalDefault:'Ambient global "{{name}}" is forbidden here; inject the capability through a port instead.',forbiddenModule:'{{layer}} must not use module "{{specifier}}" because it is the import form of forbidden global "{{name}}".'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=N(e),n=e.options?.[0],s=T(t),r=s?j(s):null,i=s?d.default.dirname(s):null,l=null,c="this layer";if(r&&i&&t){let o=d.default.isAbsolute(t)?t:d.default.resolve(t),a=d.default.relative(i,o).split(d.default.sep).join("/");if(!W(r,a))return{};let u=r.layers?.find(m=>m.name===R(a,r.layers));u?.forbiddenGlobals?.length?(l=new Set(u.forbiddenGlobals),c=u.name):l=null}else n?.globals&&(l=new Set(n.globals));if(!l)return{};let g=typeof J(e)?.getScope=="function",f=(o,a)=>{let u=d.default.isAbsolute(t)?t:d.default.resolve(t),m=i?d.default.relative(i,u).split(d.default.sep).join("/"):t;w(e,o,r?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:m,fromLayer:c,target:a,message:`${c} must not use the ambient global "${a}".`},{name:a,layer:c})},p=(o,a,u,m)=>{if(u||typeof a!="string")return;let y=K(a,l);if(!y)return;let h=d.default.isAbsolute(t)?t:d.default.resolve(t),A=i?d.default.relative(i,h).split(d.default.sep).join("/"):t;w(e,o,"forbiddenModule",{ruleId:"FORBIDDEN_GLOBAL",file:A,fromLayer:c,target:a,edgeKind:m,message:`${c} must not use module "${a}" because it is the import form of forbidden global "${y}".`},{layer:c,name:y,specifier:a,importKind:m})};return{MemberExpression(o){if(o.parent?.type==="MemberExpression"&&o.parent.object===o)return;let a=Ie(o);if(!a||v(e,a.root,a.segments[0]))return;let u=a.segments[0]==="globalThis",m=u?a.segments.slice(1):a.segments,y;for(let h=m.length;h>=(u?1:2);h-=1){let A=m.slice(0,h).join(".");if(l.has(A)){y=A;break}}y?f(o,y):!g&&l.has(a.segments[0])&&f(o,a.segments[0])},CallExpression(o){let a=o;if(a.callee?.type==="Identifier"&&a.callee.name==="require"&&a.arguments?.[0]?.type==="Literal"&&!v(e,o,"require")&&p(o,a.arguments[0].value,!1,"require"),g)return;let u=a.callee?.type==="Identifier"?a.callee.name:void 0;u&&l.has(u)&&f(o,u)},ImportDeclaration(o){let a=o,u=(a.specifiers??[]).filter(y=>y.type==="ImportSpecifier"),m=u.length>0&&u.length===(a.specifiers??[]).length&&u.every(y=>y.importKind==="type");p(o,a.source?.value,a.importKind==="type"||m,"import")},ImportExpression(o){let a=o;a.source?.type==="Literal"&&p(o,a.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(o){let a=o;p(o,a.moduleReference?.expression?.value,a.importKind==="type"||a.isTypeOnly===!0,"require")},ExportNamedDeclaration(o){let a=o;if(!a.source)return;let u=a.specifiers??[],m=u.length>0&&u.every(y=>y.exportKind==="type");p(o,a.source.value,a.exportKind==="type"||m,"export")},ExportAllDeclaration(o){let a=o;p(o,a.source?.value,a.exportKind==="type","export")},NewExpression(o){if(g)return;let a=o.callee?.type==="Identifier"?o.callee.name:void 0;a&&l.has(a)&&f(o,a)},Identifier(o){!g||!o.name||!l.has(o.name)||!et(e,o)||v(e,o,o.name)||f(o,o.name)}}}},Le={meta:{type:"problem",docs:{description:"Disallow importing modules whose effect capability the layer denies (ark.config.json capabilities.deny / pure \u2014 same wall surface as ark-check). Import dimension only: ambient globals stay with no-forbidden-globals and the CLI/hook symbol path."},messages:{deniedCapability:'{{layer}} denies the {{capability}} capability (ark.config.json); "{{specifier}}" imports it. Define a port and bind the implementation in an adapter layer.'},schema:[]},create(e){let t=N(e),n=T(t),s=n?j(n):null,r=n?d.default.dirname(n):null;if(!s||!r||!t)return{};let i=d.default.isAbsolute(t)?t:d.default.resolve(t),l=d.default.relative(r,i).split(d.default.sep).join("/");if(!W(s,l))return{};let c=s.layers?.find(p=>p.name===R(l,s.layers));if(!c)return{};let g=new Set(ae(c));if(g.size===0)return{};let f=(p,o,a,u)=>{if(a||typeof o!="string"||K(o,c.forbiddenGlobals??[]))return;let m=ie(o);!m||!g.has(m)||w(e,p,"deniedCapability",{ruleId:"CAPABILITY_VIOLATION",file:l,fromLayer:c.name,target:o,capability:m,edgeKind:u,message:`${c.name} denies the ${m} capability; found import of "${o}".`},{layer:c.name,capability:m,specifier:o})};return{ImportDeclaration(p){let o=p,a=(o.specifiers??[]).filter(m=>m.type==="ImportSpecifier"),u=a.length>0&&a.length===(o.specifiers??[]).length&&a.every(m=>m.importKind==="type");f(p,o.source?.value,o.importKind==="type"||u,"import")},ImportExpression(p){let o=p;o.source?.type==="Literal"&&f(p,o.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(p){let o=p;f(p,o.moduleReference?.expression?.value,o.importKind==="type"||o.isTypeOnly===!0,"require")},ExportNamedDeclaration(p){let o=p;if(!o.source)return;let a=o.specifiers??[],u=a.length>0&&a.every(m=>m.exportKind==="type");f(p,o.source.value,o.exportKind==="type"||u,"export")},ExportAllDeclaration(p){let o=p;f(p,o.source?.value,o.exportKind==="type","export")},CallExpression(p){let o=p;o.callee?.type==="Identifier"&&o.callee.name==="require"&&o.arguments?.[0]?.type==="Literal"&&!v(e,p,"require")&&f(p,o.arguments[0].value,!1,"require")}}}},ot={"no-domain-infra-imports":we,"no-raw-event-publish":Ee,"require-publish-source":Ce,"no-forbidden-globals":Ne,"no-denied-capabilities":Le},$={rules:ot};$.configs={recommended:{plugins:{ark:$},rules:{"ark/no-domain-infra-imports":"error","ark/no-raw-event-publish":"error","ark/require-publish-source":"error","ark/no-forbidden-globals":"error","ark/no-denied-capabilities":"error"}}};var it=$;0&&(module.exports={findConfigPath,globToRegExp,isEdgeDenied,layerForRelativePath,loadArkConfig,noDeniedCapabilities,noDomainInfraImports,noForbiddenGlobals,noRawEventPublish,patternSpecificity,plugin,readTsconfigPathAliases,requirePublishSource,resolveImportSpecifier,resolveRelativeImport});
@@ -52,7 +52,15 @@ type EdgeCheckOptions = {
52
52
  layers?: LayerConfig[];
53
53
  };
54
54
  declare function globToRegExp(pattern: string): RegExp;
55
- declare function patternSpecificity(pattern: string): number;
55
+ /**
56
+ * Rank competing layer globs.
57
+ *
58
+ * Without a path: concrete-segment count + literal length (historical shape).
59
+ * With a path: last matched concrete segment depth dominates so interior
60
+ * domain/persistence folders beat Application/Presentation scatter bags
61
+ * (DL-DOMAIN-SPECIFICITY / NEW-APP-VACUUM-LIB).
62
+ */
63
+ declare function patternSpecificity(pattern: string, relPath?: string): number;
56
64
  declare function layerForRelativePath(relPath: string, layers: LayerConfig[] | undefined): string | undefined;
57
65
  declare function isEdgeDenied(rules: EdgeRule[] | undefined, from: string, to: string, options?: EdgeCheckOptions): boolean;
58
66
 
@@ -130,8 +138,25 @@ type ArkEslintPlugin = {
130
138
  };
131
139
  declare function findConfigPath(startFile: string): string | null;
132
140
  declare function loadArkConfig(configPath: string): ArkConfig | null;
141
+ /**
142
+ * Read tsconfig paths/baseUrl for ESLint alias parity (P0-C).
143
+ * JSONC-tolerant strip of // and /* comments; supports simple extends of a relative JSON.
144
+ * Does not claim full TypeScript resolution (project refs, complex multi-target, wildcards beyond trailing *).
145
+ */
146
+ declare function readTsconfigPathAliases(startDir: string): {
147
+ baseUrl: string;
148
+ aliases: Array<{
149
+ from: string;
150
+ to: string;
151
+ }>;
152
+ };
133
153
  /** Resolve relative import specifier to an absolute path candidate (TS-oriented). */
134
154
  declare function resolveRelativeImport(fromFile: string, specifier: string): string | null;
155
+ /**
156
+ * Resolve relative or tsconfig path-alias import to an on-disk file.
157
+ * Bare packages (no matching alias) return null — CI/TS remain source of truth there.
158
+ */
159
+ declare function resolveImportSpecifier(fromFile: string, specifier: string, projectRoot?: string | null): string | null;
135
160
  /**
136
161
  * Config-driven layer import boundary (primary editor gate).
137
162
  * Replaces path-token domain/infra heuristics when ark.config.json is present.
@@ -144,4 +169,4 @@ declare const noForbiddenGlobals: ArkRule;
144
169
  declare const noDeniedCapabilities: ArkRule;
145
170
  declare const plugin: ArkEslintPlugin;
146
171
 
147
- export { plugin as default, findConfigPath, globToRegExp, isEdgeDenied, layerForRelativePath, loadArkConfig, noDeniedCapabilities, noDomainInfraImports, noForbiddenGlobals, noRawEventPublish, patternSpecificity, plugin, requirePublishSource, resolveRelativeImport };
172
+ export { plugin as default, findConfigPath, globToRegExp, isEdgeDenied, layerForRelativePath, loadArkConfig, noDeniedCapabilities, noDomainInfraImports, noForbiddenGlobals, noRawEventPublish, patternSpecificity, plugin, readTsconfigPathAliases, requirePublishSource, resolveImportSpecifier, resolveRelativeImport };