arkgate 3.3.0 → 3.5.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.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Doctor's advisory sensors, aggregated (W01 contract health + U05 ambient
3
+ * state). Advisory only: nothing here feeds a verdict, designFitness, or an
4
+ * exit code. One seam keeps doctor-plan.mjs inside its module budget as new
5
+ * advisory surfaces land.
6
+ */
7
+ import { computeAmbientState, printAmbientStateSection } from './ambient-state.mjs';
8
+ import { computeContractHealth, printContractHealthSection } from './contract-smells.mjs';
9
+
10
+ export function computeDoctorAdvisories(root, config, cov, rules, files, ts) {
11
+ return {
12
+ contractHealth: computeContractHealth(root, config, cov, rules),
13
+ ambientState: computeAmbientState(ts, root, config, files),
14
+ };
15
+ }
16
+
17
+ export function printDoctorAdvisories(advisories, io) {
18
+ printContractHealthSection(advisories.contractHealth, io);
19
+ printAmbientStateSection(advisories.ambientState, io);
20
+ }
@@ -40,7 +40,7 @@ import {
40
40
  } from './post-green-path.mjs';
41
41
  import { loadGoldenPattern, summarizeGoldenPattern } from './golden-pattern.mjs';
42
42
  import { summarizePilotLoop } from './pilot-loop.mjs';
43
- import { computeContractHealth, printContractHealthSection } from './contract-smells.mjs';
43
+ import { computeDoctorAdvisories, printDoctorAdvisories } from './doctor-advisories.mjs';
44
44
 
45
45
  const color = {
46
46
  green: (s) => `\x1b[32m${s}\x1b[0m`,
@@ -425,8 +425,7 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
425
425
  patternBets: patternBetsForLoop,
426
426
  designSmells,
427
427
  });
428
- // W01 contract meta-lint over the rules in force. Advisory; never feeds any verdict.
429
- const contractHealth = computeContractHealth(root, config, cov, rules);
428
+ const { contractHealth, ambientState } = computeDoctorAdvisories(root, config, cov, rules, files, options.ts); // W01+U05 advisories — never a verdict
430
429
 
431
430
  if (asJson) {
432
431
  console.log(
@@ -465,6 +464,8 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
465
464
  pilotLoop,
466
465
  // W01: contract-health meta-lint (advisory; verdict unchanged).
467
466
  contractHealth,
467
+ // U05: ambient-state sensor (advisory; opt-in; verdict unchanged).
468
+ ambientState,
468
469
  governed: cov.governed,
469
470
  emptyLayers: cov.emptyLayers,
470
471
  layersWithoutRules: cov.layersWithoutRules,
@@ -646,8 +647,7 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
646
647
  );
647
648
  }
648
649
 
649
- // W01 contract health (advisory; verdict unchanged).
650
- printContractHealthSection(contractHealth, { line, warn, color });
650
+ printDoctorAdvisories({ contractHealth, ambientState }, { line, warn, color }); // advisory sections
651
651
 
652
652
  console.log('');
653
653
  console.log(color.bold('Coverage'));
@@ -0,0 +1,149 @@
1
+ /**
2
+ * X01 — advisory sections for the HTML report (report parity with doctor).
3
+ *
4
+ * The report is a RENDERING of doctor truth: every advisory surface the doctor
5
+ * emits must have a section here, marked with `data-advisory="<key>"`. The
6
+ * parity guard (reportParity.test.ts) enumerates the doctor's advisory keys
7
+ * and fails when one has no section — that is the standing rule that keeps
8
+ * this report from falling behind the product again.
9
+ */
10
+ import { effectiveCapabilityDeny } from './analysis-engine.mjs';
11
+
12
+ // htmlEscape is injected by the caller (html-report.mjs) — importing it back
13
+ // would be a dependency cycle, and the repo's own gate blocks that. The
14
+ // fallback still escapes so a caller that forgets to inject cannot ship XSS.
15
+ let esc = (v) =>
16
+ String(v).replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
17
+
18
+ /** Layer badges for the layers table: purity walls next to forbidden globals. */
19
+ export function capabilityBadgesFor(layer, escape = esc) {
20
+ const previous = esc;
21
+ esc = escape;
22
+ try {
23
+ return badgesInner(layer);
24
+ } finally {
25
+ esc = previous;
26
+ }
27
+ }
28
+
29
+ function badgesInner(layer) {
30
+ const deny = effectiveCapabilityDeny(layer ?? {});
31
+ if (deny.length === 0) return '';
32
+ if (layer?.pure === true) {
33
+ return '<span class="tag warn" title="pure: true — all seven effect capabilities denied (ADR 0009)">pure</span>';
34
+ }
35
+ return `<span class="tag warn" title="capabilities.deny (ADR 0009)">walls: ${deny.map(esc).join(', ')}</span>`;
36
+ }
37
+
38
+ function governanceWeightHtml(gw) {
39
+ if (!gw || gw.weight === 'unknown') {
40
+ return '<p class="muted">Governance weight: unknown (no governed files or layers).</p>';
41
+ }
42
+ const label = `${gw.weight} — ${gw.declaredLayers} layer(s), ${gw.rules} rule(s), ${gw.governedFiles} governed file(s)` +
43
+ (gw.filesPerLayer != null ? ` (${gw.filesPerLayer} files/layer · ${gw.rulesPerLayer} rules/layer)` : '');
44
+ return `
45
+ <div data-advisory="governanceWeight">
46
+ <p><b>Governance weight:</b> <span class="tag ${gw.weight === 'typical' ? 'ok' : 'warn'}">${esc(String(gw.weight))}</span> ${esc(label)}</p>
47
+ <p class="muted">${esc(gw.note ?? '')} Facts, never a score or gate input (<code>notAScore</code>).</p>
48
+ </div>`;
49
+ }
50
+
51
+ function ackLifecycleHtml(lc) {
52
+ if (!lc) return '';
53
+ const rows = [];
54
+ if ((lc.expiredCount ?? 0) > 0) {
55
+ const edges = (lc.expired ?? [])
56
+ .map((e) => `<code>${esc(e.edge)}</code> (review-by ${esc(e.reviewBy)})`)
57
+ .join(' · ');
58
+ rows.push(
59
+ `<p><span class="tag warn">expired</span> ${lc.expiredCount} acknowledgment(s) past review-by — no longer applied, the smell is active again: ${edges}</p>`
60
+ );
61
+ }
62
+ if ((lc.malformed ?? 0) > 0) {
63
+ rows.push(
64
+ `<p><span class="tag warn">malformed</span> ${lc.malformed} acknowledgment(s) have a malformed review-by (expected YYYY-MM-DD) — ignored, not silently applied.</p>`
65
+ );
66
+ }
67
+ if ((lc.undated ?? 0) > 0) {
68
+ rows.push(
69
+ `<p class="muted">${lc.undated} applied acknowledgment(s) have no review-by date — add one so migration acks cannot fossilize.</p>`
70
+ );
71
+ }
72
+ return rows.join('\n');
73
+ }
74
+
75
+ function contractHealthHtml(health) {
76
+ if (!health) return '';
77
+ const smells = Array.isArray(health.smells) ? health.smells : [];
78
+ const acked = health.acknowledged ?? 0;
79
+ const ackNote = acked > 0
80
+ ? `<p class="muted">Acknowledged edges applied: <b>${acked}</b> (${esc(health.ackFile?.path ?? '.ark/contract-smell-acks.json')}) — deliberate loops recorded with a reason; review them when their migrations finish.</p>`
81
+ : '';
82
+ const invalid = health.ackFile?.invalid
83
+ ? `<p class="tag warn">Acknowledgment sidecar present but invalid — acks are ignored, never silently applied.</p>`
84
+ : '';
85
+ const body = smells.length === 0
86
+ ? `<p class="muted">No contract smells detected — no explicitly bidirectional allows, peripheral-into-core allows, lateral adapter allows, or dead rules beyond what is acknowledged.</p>`
87
+ : smells
88
+ .map(
89
+ (s) => `
90
+ <div class="finding">
91
+ <p><span class="tag warn">${esc(s.id)}</span> ${esc(s.outcome ?? s.message ?? '')}</p>
92
+ <p class="muted">${esc(s.message ?? '')}</p>
93
+ <p class="muted">evidence: <code>${(s.evidence ?? []).slice(0, 6).map(esc).join('</code> · <code>')}</code></p>
94
+ <p class="muted">fix: ${esc(s.fix ?? '')}</p>
95
+ </div>`
96
+ )
97
+ .join('\n');
98
+ return `
99
+ <section data-advisory="contractHealth">
100
+ <h2>Contract health <span class="muted">(advisory — meta-lint of the contract itself; never changes the verdict)</span></h2>
101
+ ${invalid}
102
+ ${body}
103
+ ${ackNote}
104
+ ${ackLifecycleHtml(health.ackLifecycle)}
105
+ ${governanceWeightHtml(health.governanceWeight)}
106
+ </section>`;
107
+ }
108
+
109
+ function ambientStateHtml(state) {
110
+ if (!state) return '';
111
+ if (state.available === false) {
112
+ return `
113
+ <section data-advisory="ambientState">
114
+ <h2>Ambient state <span class="muted">(advisory)</span></h2>
115
+ <p class="muted">${esc(state.note ?? 'Sensor unavailable in this run.')}</p>
116
+ </section>`;
117
+ }
118
+ const findings = Array.isArray(state.findings) ? state.findings : [];
119
+ const body = !state.active
120
+ ? '<p class="muted">Idle — no <code>pure: true</code> layer opted in. Declare a pure layer to scan module-scope mutable state.</p>'
121
+ : findings.length === 0
122
+ ? '<p class="muted">Active and clean — no module-scope <code>let</code>/<code>var</code> in pure layers.</p>'
123
+ : `<ul>${findings
124
+ .slice(0, 10)
125
+ .map(
126
+ (f) => `<li><code>${esc(f.file)}:${f.line}</code> — <b>${esc(f.name)}</b> <span class="tag warn">${esc(f.kind)}</span></li>`
127
+ )
128
+ .join('')}</ul>` +
129
+ (state.findingCount > 10 ? `<p class="muted">…(+${state.findingCount - 10} more in doctor JSON)</p>` : '') +
130
+ (state.acknowledged > 0 ? `<p class="muted">acknowledged module state: ${state.acknowledged}</p>` : '');
131
+ return `
132
+ <section data-advisory="ambientState">
133
+ <h2>Ambient state <span class="muted">(advisory — opt-in via pure layers; no strict mode exists)</span></h2>
134
+ ${body}
135
+ </section>`;
136
+ }
137
+
138
+ /**
139
+ * Render every doctor advisory as report sections. Keys must cover everything
140
+ * `computeDoctorAdvisories` returns — the parity guard enforces it.
141
+ * @param escape injected HTML escaper (dependency points html-report → here only)
142
+ */
143
+ export function renderAdvisorySections(advisories, escape) {
144
+ if (!advisories || typeof advisories !== 'object') return '';
145
+ if (typeof escape === 'function') esc = escape;
146
+ return [contractHealthHtml(advisories.contractHealth), ambientStateHtml(advisories.ambientState)]
147
+ .filter(Boolean)
148
+ .join('\n');
149
+ }
@@ -19,6 +19,7 @@ import {
19
19
  renderWritePathAdoptionBlock,
20
20
  } from './html-report-depth.mjs';
21
21
  import { FIX_HINTS } from './violations.mjs';
22
+ import { capabilityBadgesFor, renderAdvisorySections } from './html-report-advisories.mjs';
22
23
 
23
24
  export function detectEnforcement(root) {
24
25
  const has = (rel) => fs.existsSync(path.join(root, rel));
@@ -455,6 +456,8 @@ export function renderHtmlReport({
455
456
  adoption = null,
456
457
  /** Optional design-depth (doctor parity): designFitness, designSmells, pilotLoop, postGreenPath, goldenPattern */
457
458
  designDepth = null,
459
+ /** Doctor advisory parity (X01): contractHealth (+governanceWeight), ambientState — guarded by reportParity.test.ts */
460
+ advisories = null,
458
461
  }) {
459
462
  const layers = Array.isArray(config.layers) ? config.layers : [];
460
463
  const rules = Array.isArray(config.rules) ? config.rules : [];
@@ -710,6 +713,7 @@ export function renderHtmlReport({
710
713
  Array.isArray(layer.forbiddenGlobals) && layer.forbiddenGlobals.length
711
714
  ? `<span class="tag warn">no ${layer.forbiddenGlobals.map(esc).join(', ')}</span>`
712
715
  : '',
716
+ capabilityBadgesFor(layer, esc),
713
717
  layer.mayImportInfrastructure ? '<span class="tag">may import infra</span>' : '',
714
718
  Array.isArray(layer.intentPrefixes) && layer.intentPrefixes.length
715
719
  ? `<span class="tag">${layer.intentPrefixes.map(esc).join(' ')}</span>`
@@ -1187,6 +1191,8 @@ export function renderHtmlReport({
1187
1191
  ${violationBlocks}
1188
1192
  </div>
1189
1193
 
1194
+ ${renderAdvisorySections(advisories, esc)}
1195
+
1190
1196
  <div class="section card">
1191
1197
  <h2>Enforcement points</h2>
1192
1198
  <p class="dim" style="margin:.15rem 0 .85rem;font-size:.88rem">Write-time · merge-time · editor · ratchet. Same contract everywhere.</p>
@@ -54,6 +54,8 @@ export function deterministicNextAction(violation) {
54
54
  return `Define a port in ${violation.fromLayer ?? 'the source layer'}, inject the ${violation.toLayer ?? 'outer-layer'} implementation, then preflight again.`;
55
55
  case 'FORBIDDEN_GLOBAL':
56
56
  return `Inject ${violation.target ?? 'the capability'} through a port, then preflight again.`;
57
+ case 'CAPABILITY_VIOLATION':
58
+ return `Define a ${String(violation.capability ?? 'capability')} port in ${violation.fromLayer ?? 'the walled layer'}, bind the implementation outside it, then preflight again.`;
57
59
  case 'CIRCULAR_DEPENDENCY':
58
60
  return 'Extract the shared dependency into a third module, then preflight again.';
59
61
  case 'RAW_EVENT_PUBLISH':
@@ -148,6 +150,13 @@ export function classifyRemediation(violation) {
148
150
  rationale: 'Ambient global in a pure layer: inject the capability through a port (Clock, Config, Http). Introducing the port is a design decision.',
149
151
  };
150
152
  }
153
+ if (ruleId === 'CAPABILITY_VIOLATION') {
154
+ return {
155
+ class: 'judgment',
156
+ confidence: 0.8,
157
+ rationale: 'A denied effect capability (clock/network/persistence/…) reached a walled layer: define a port and bind the implementation outside it. Never mechanical-safe — the port shape is a design decision.',
158
+ };
159
+ }
151
160
  if (ruleId === 'CIRCULAR_DEPENDENCY') {
152
161
  return {
153
162
  class: 'judgment',
@@ -201,6 +210,11 @@ export function enrichViolationWithFixClass(violation) {
201
210
  enriched.effort = 'small';
202
211
  enriched.enthusiastHint = `Do not call "${violation.target ?? 'that global'}" here. Pass the capability in through a small interface (for example a Clock, HttpPort, or Config provider).`;
203
212
  break;
213
+ case 'CAPABILITY_VIOLATION':
214
+ enriched.fixClass = 'inject-port';
215
+ enriched.effort = 'medium';
216
+ enriched.enthusiastHint = `This layer denies the ${String(violation.capability ?? 'effect')} capability. Define a small port (for example ClockPort, HttpPort, StoragePort) and inject the implementation from an adapter layer instead of using "${violation.target ?? 'the capability'}" directly.`;
217
+ break;
204
218
  case 'RAW_EVENT_PUBLISH':
205
219
  enriched.fixClass = 'registered-intent';
206
220
  enriched.effort = 'small';
@@ -129,9 +129,10 @@ export function scanCacheKey(root, args) {
129
129
  // v3: per-file exportsOnlyTypes. v4: typeOnlyExportNames + namedBindings.
130
130
  // v5: hasTopLevelSideEffects. v6: non-exported impure inits + non-export class statics.
131
131
  // v7: scope-aware forbidden globals + import-equals dependency edges.
132
+ // v8: opted-in capability walls (U04) — stale caches must not miss wall verdicts.
132
133
  return crypto
133
134
  .createHash('sha1')
134
- .update(`ark-check-cache-v7\0${read(configPath)}\0${manifestPath ? read(manifestPath) : ''}`)
135
+ .update(`ark-check-cache-v8\0${read(configPath)}\0${manifestPath ? read(manifestPath) : ''}`)
135
136
  .digest('hex');
136
137
  }
137
138
 
@@ -45,6 +45,8 @@ export const FIX_HINTS = {
45
45
  'Use a source intent that belongs to the same layer as the publishing file, or move the file.',
46
46
  FORBIDDEN_GLOBAL:
47
47
  'Inject the capability through a port (e.g. a Clock, IdGenerator, or HttpPort) instead of reaching for the ambient global.',
48
+ CAPABILITY_VIOLATION:
49
+ 'This layer denies that effect. Define a small port (ClockPort, HttpPort, StoragePort) and bind the implementation in an adapter layer.',
48
50
  CIRCULAR_DEPENDENCY:
49
51
  'Break the cycle: extract the shared code into a module both sides import, invert one edge behind a port/interface, or merge the files if they are really one unit.',
50
52
  };
@@ -8,6 +8,9 @@
8
8
  */
9
9
  type ArkConfigSchemaVersion = '1.0';
10
10
  type ArkConfigCyclePolicy = 'strict' | 'soft' | 'framework-soft' | 'off';
11
+ type ArkConfigLayerCapabilities = {
12
+ deny?: string[];
13
+ };
11
14
  type ArkConfigLayer = {
12
15
  name: string;
13
16
  patterns: string[];
@@ -15,6 +18,10 @@ type ArkConfigLayer = {
15
18
  intentPrefixes?: string[];
16
19
  description?: string;
17
20
  forbiddenGlobals?: string[];
21
+ /** ADR 0009 D2 — opt-in effect-capability walls; absence changes no verdict. */
22
+ capabilities?: ArkConfigLayerCapabilities;
23
+ /** Dual-depth sugar: `pure: true` denies all seven capabilities. */
24
+ pure?: boolean;
18
25
  mayImportInfrastructure?: boolean;
19
26
  optional?: boolean;
20
27
  };
@@ -8,6 +8,9 @@
8
8
  */
9
9
  type ArkConfigSchemaVersion = '1.0';
10
10
  type ArkConfigCyclePolicy = 'strict' | 'soft' | 'framework-soft' | 'off';
11
+ type ArkConfigLayerCapabilities = {
12
+ deny?: string[];
13
+ };
11
14
  type ArkConfigLayer = {
12
15
  name: string;
13
16
  patterns: string[];
@@ -15,6 +18,10 @@ type ArkConfigLayer = {
15
18
  intentPrefixes?: string[];
16
19
  description?: string;
17
20
  forbiddenGlobals?: string[];
21
+ /** ADR 0009 D2 — opt-in effect-capability walls; absence changes no verdict. */
22
+ capabilities?: ArkConfigLayerCapabilities;
23
+ /** Dual-depth sugar: `pure: true` denies all seven capabilities. */
24
+ pure?: boolean;
18
25
  mayImportInfrastructure?: boolean;
19
26
  optional?: boolean;
20
27
  };
@@ -1,3 +1,3 @@
1
- "use strict";var de=Object.create;var k=Object.defineProperty;var ge=Object.getOwnPropertyDescriptor;var pe=Object.getOwnPropertyNames;var me=Object.getPrototypeOf,ye=Object.prototype.hasOwnProperty;var he=(e,t)=>{for(var n in t)k(e,n,{get:t[n],enumerable:!0})},v=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of pe(t))!ye.call(e,r)&&r!==n&&k(e,r,{get:()=>t[r],enumerable:!(i=ge(t,r))||i.enumerable});return e};var B=(e,t,n)=>(n=e!=null?de(me(e)):{},v(t||!e||!e.__esModule?k(n,"default",{value:e,enumerable:!0}):n,e)),Ae=e=>v(k({},"__esModule",{value:!0}),e);var Fe={};he(Fe,{default:()=>Ve,findConfigPath:()=>D,globToRegExp:()=>R,isEdgeDenied:()=>P,layerForRelativePath:()=>S,loadArkConfig:()=>G,noDomainInfraImports:()=>le,noForbiddenGlobals:()=>fe,noRawEventPublish:()=>ce,patternSpecificity:()=>$,plugin:()=>E,requirePublishSource:()=>ue,resolveRelativeImport:()=>re});module.exports=Ae(Fe);var b=B(require("fs"),1),c=B(require("path"),1);var K=new Map;function W(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function O(e){let t="";for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=i}return t}function be(e){let t=0;for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"){n+=1;continue}if(i==="{")t+=1;else if(i==="}"&&(t-=1,t<0))return!1}return t===0}function R(e){let t=K.get(e);if(t)return t;let n=O(e),i=be(n),r="",o=0;for(let a=0;a<n.length;a+=1){let f=n[a];f==="\\"&&a+1<n.length?(r+=W(n[a+1]),a+=1):f==="*"?n[a+1]==="*"?n[a+2]==="/"?(r+="(?:.*/)?",a+=2):(r+=".*",a+=1):r+="[^/]*":f==="?"?r+="[^/]":f==="{"&&i?(r+="(?:",o+=1):f==="}"&&i&&o>0?(r+=")",o-=1):f===","&&i&&o>0?r+="|":r+=W(f)}let s=new RegExp(`^${r}$`);return K.set(e,s),s}function $(e){let t=O(String(e)),i=t.split("*")[0].split("/").filter(Boolean).length,r=t.replace(/\*/g,"").length;return i*1e4+r}function S(e,t){let n=String(e).split(/[/\\]/).join("/"),i,r=-1;for(let o of t??[])if(!(o.exclude??[]).some(s=>R(s).test(n))){for(let s of o.patterns??[])if(R(s).test(n)){let a=$(s);a>r&&(r=a,i=o.name)}}return i}function q(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),i=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(i.has(n[r].toLowerCase()))return`${n[r]}/${n[r+1]}`}function Se(e){let t=new Set;for(let n of e??[]){let r=O(String(n)).split("/").filter(Boolean);for(let o=0;o<r.length;o+=1){let s=r[o];if((s==="**"||s==="*")&&o>0){let a=r[o-1];a&&!a.includes("*")&&!a.includes("{")&&!a.includes("}")&&t.add(a)}}}return[...t]}function ke(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let i=(n??[]).find(r=>r.name===t);return Se(i?.patterns)}function Re(e,t,n,i){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let o=i?.fromPath,s=i?.toPath;if(!o||!s)continue;let a=ke(r,t,i?.layers);if(a.length===0)continue;let f=q(o,a),g=q(s,a);if(!f||!g)continue;if(f!==g)return r;continue}if(t!==n)return r}}function P(e,t,n,i){return Re(e,t,n,i)!==void 0}var V="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",J=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],Ie=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function Ce(){let e=[];for(let t of J)for(let n of J)t===n||Ie.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var z=Ce();var y={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},Y={$schema:"https://json-schema.org/draft/2020-12/schema",$id:V,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:V,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.0",default:"1.0"},name:{type:"string",minLength:1},include:{...y,minItems:1,default:["src"]},exclude:{...y,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:z,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...y,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...y,minItems:1},exclude:y,intentPrefixes:y,description:{type:"string",minLength:1},forbiddenGlobals:y,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:{...y,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}}}}},A=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
1
+ "use strict";var be=Object.create;var C=Object.defineProperty;var he=Object.getOwnPropertyDescriptor;var Ae=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var Ie=(e,t)=>{for(var n in t)C(e,n,{get:t[n],enumerable:!0})},U=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Ae(t))!Se.call(e,r)&&r!==n&&C(e,r,{get:()=>t[r],enumerable:!(i=he(t,r))||i.enumerable});return e};var q=(e,t,n)=>(n=e!=null?be(ke(e)):{},U(t||!e||!e.__esModule?C(n,"default",{value:e,enumerable:!0}):n,e)),we=e=>U(C({},"__esModule",{value:!0}),e);var Be={};Ie(Be,{default:()=>Ge,findConfigPath:()=>L,globToRegExp:()=>R,isEdgeDenied:()=>F,layerForRelativePath:()=>h,loadArkConfig:()=>_,noDeniedCapabilities:()=>ye,noDomainInfraImports:()=>fe,noForbiddenGlobals:()=>me,noRawEventPublish:()=>pe,patternSpecificity:()=>j,plugin:()=>N,requirePublishSource:()=>ge,resolveRelativeImport:()=>ae});module.exports=we(Be);var S=q(require("fs"),1),u=q(require("path"),1);var W=new Map;function Y(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function P(e){let t="";for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=i}return t}function Ce(e){let t=0;for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"){n+=1;continue}if(i==="{")t+=1;else if(i==="}"&&(t-=1,t<0))return!1}return t===0}function R(e){let t=W.get(e);if(t)return t;let n=P(e),i=Ce(n),r="",s=0;for(let c=0;c<n.length;c+=1){let p=n[c];p==="\\"&&c+1<n.length?(r+=Y(n[c+1]),c+=1):p==="*"?n[c+1]==="*"?n[c+2]==="/"?(r+="(?:.*/)?",c+=2):(r+=".*",c+=1):r+="[^/]*":p==="?"?r+="[^/]":p==="{"&&i?(r+="(?:",s+=1):p==="}"&&i&&s>0?(r+=")",s-=1):p===","&&i&&s>0?r+="|":r+=Y(p)}let l=new RegExp(`^${r}$`);return W.set(e,l),l}function j(e){let t=P(String(e)),i=t.split("*")[0].split("/").filter(Boolean).length,r=t.replace(/\*/g,"").length;return i*1e4+r}function h(e,t){let n=String(e).split(/[/\\]/).join("/"),i,r=-1;for(let s of t??[])if(!(s.exclude??[]).some(l=>R(l).test(n))){for(let l of s.patterns??[])if(R(l).test(n)){let c=j(l);c>r&&(r=c,i=s.name)}}return i}function z(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),i=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(i.has(n[r].toLowerCase()))return`${n[r]}/${n[r+1]}`}function Re(e){let t=new Set;for(let n of e??[]){let r=P(String(n)).split("/").filter(Boolean);for(let s=0;s<r.length;s+=1){let l=r[s];if((l==="**"||l==="*")&&s>0){let c=r[s-1];c&&!c.includes("*")&&!c.includes("{")&&!c.includes("}")&&t.add(c)}}}return[...t]}function xe(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let i=(n??[]).find(r=>r.name===t);return Re(i?.patterns)}function Ee(e,t,n,i){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let s=i?.fromPath,l=i?.toPath;if(!s||!l)continue;let c=xe(r,t,i?.layers);if(c.length===0)continue;let p=z(s,c),g=z(l,c);if(!p||!g)continue;if(p!==g)return r;continue}if(t!==n)return r}}function F(e,t,n,i){return Ee(e,t,n,i)!==void 0}var J=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),Ne=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),Ue=Object.freeze(Object.keys(Ne).sort()),V=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"});function Z(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=V[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let i=e.slice(0,n),r=V[i];if(r)return r;let s=e.indexOf("/",n+1);return s<0?null:V[e.slice(0,s)]??null}function X(e){if(e?.pure===!0)return[...J].sort();let n=(e?.capabilities?.deny??[]).filter(i=>J.includes(i));return[...new Set(n)].sort()}var M="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",Q=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],Le=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function _e(){let e=[];for(let t of Q)for(let n of Q)t===n||Le.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var te=_e();var b={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},ee={$schema:"https://json-schema.org/draft/2020-12/schema",$id:M,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:M,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.0",default:"1.0"},name:{type:"string",minLength:1},include:{...b,minItems:1,default:["src"]},exclude:{...b,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:te,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...b,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...b,minItems:1},exclude:b,intentPrefixes:b,description:{type:"string",minLength:1},forbiddenGlobals:b,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:{...b,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(i=>`- ${i.path}: ${i.message}`).join(`
3
- `)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function Z(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function j(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function h(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function Ee(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function I(e,t,n,i,r){if(t.$ref){let o=Ee(t.$ref,i);if(!o){r.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}I(e,o,n,i,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(o=>Object.is(o,e))){r.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!Z(e)){r.push({path:n,message:`must be an object; received ${h(e)}`});return}let o=t.properties??{};for(let s of t.required??[])e[s]===void 0&&r.push({path:j(n,s),message:"is required"});if(t.additionalProperties===!1)for(let s of Object.keys(e))s in o||r.push({path:j(n,s),message:"unknown field"});for(let[s,a]of Object.entries(o))e[s]!==void 0&&I(e[s],a,j(n,s),i,r);return}if(t.type==="array"){if(!Array.isArray(e)){r.push({path:n,message:`must be an array; received ${h(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 o=e.map(s=>JSON.stringify(s));new Set(o).size!==o.length&&r.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((o,s)=>I(o,t.items,`${n}[${s}]`,i,r));return}if(t.type==="string"){if(typeof e!="string"){r.push({path:n,message:`must be a string; received ${h(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 ${h(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){r.push({path:n,message:`must be an integer; received ${h(e)}`});return}t.minimum!==void 0&&e<t.minimum&&r.push({path:n,message:`must be at least ${t.minimum}`})}}function Ne(e){return{...e,$schema:e.$schema===void 0?V:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.0":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?z.map(t=>({...t})):e.rules}}function xe(e,t="ark.config.json"){if(!Z(e))throw new A(t,[{path:"$",message:`must be an object; received ${h(e)}`}]);let n=e.schemaVersion===void 0?"unversioned":null;if(e.schemaVersion!==void 0&&e.schemaVersion!=="1.0")throw new A(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.0`}]);return{candidate:Ne(e),migratedFrom:n}}function we(e,t="ark.config.json"){let{candidate:n,migratedFrom:i}=xe(e,t),r=[];if(I(n,Y,"$",Y,r),r.length>0)throw new A(t,r);return{config:n,migratedFrom:i}}function Q(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(i){throw new A(t,[{path:"$",message:`invalid JSON: ${i instanceof Error?i.message:String(i)}`}])}return we(n,t)}function m(e){return typeof e=="string"&&e.length>0?e:void 0}function X(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Le(e,t,n){return e==="LAYER_IMPORT_VIOLATION"?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.`:e==="FORBIDDEN_GLOBAL"?`Inject ${t.target??"the capability"} through a port, then preflight again.`:e==="CIRCULAR_DEPENDENCY"?"Extract the shared dependency into a third module, then preflight again.":e==="RAW_EVENT_PUBLISH"?"Publish through a registered intent creator, then run Ark again.":e==="PUBLISH_MISSING_SOURCE"?"Add metadata.source to the publish call, then run Ark again.":`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function ee(e,t="error"){let n=m(e.ruleId)??m(e.code)??"ARK_UNKNOWN",i=e.severity==="warning"?"warning":t,r={...m(e.target)?{target:m(e.target)}:{},...m(e.fromLayer)?{fromLayer:m(e.fromLayer)}:{},...m(e.toLayer)?{toLayer:m(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{}};return{ruleId:n,severity:i,message:m(e.message)??n,location:{file:m(e.file)??"<unknown>",line:X(e.line,1),column:X(e.column,1)},evidence:r,nextAction:m(e.nextAction)??Le(n,r,e)}}var te={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."};function _e(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function F(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&_e(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:te.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:te.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 x(e,t,n,i,r){let o=ee({...i,line:i.line??t.loc?.start?.line,column:i.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:o}),o}function D(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=c.default.dirname(c.default.resolve(e));for(;;){let n=c.default.join(t,"ark.config.json");if(b.default.existsSync(n))return n;let i=c.default.dirname(t);if(i===t)return null;t=i}}var M=new Map;function G(e){if(M.has(e))return M.get(e)??null;if(!b.default.existsSync(e))return null;let t=Q(b.default.readFileSync(e,"utf8"),e).config;return M.set(e,t),t}function re(e,t){if(!t.startsWith("."))return null;let n=c.default.resolve(c.default.dirname(e),t),i=[n,`${n}.ts`,`${n}.tsx`,`${n}.mts`,`${n}.cts`,`${n}.js`,`${n}.jsx`,c.default.join(n,"index.ts"),c.default.join(n,"index.tsx"),c.default.join(n,"index.js")];for(let r of i)try{if(b.default.existsSync(r)&&b.default.statSync(r).isFile())return r}catch{}return`${n}.ts`}function w(e){return typeof e?.value=="string"?e.value:void 0}function T(e){return e?.name??w(e)}function H(e){return e.sourceCode??e.getSourceCode?.()}function ie(e,t){let n=H(e)?.getScope?.(t);for(;n;){let i=n.references?.find(r=>r.identifier===t);if(i)return i;n=n.upper??void 0}}function ne(e,t,n){let i=ie(e,t);if(i?.resolved)return(i.resolved.defs?.length??0)>0;let r=H(e)?.getScope?.(t);for(;r;){let o=r.set?.get(n);if(o)return(o.defs?.length??0)>0;r=r.upper??void 0}return!1}function Oe(e,t){let n=ie(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function oe(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=oe(e.object),i=T(e.property);if(!(!n||!i))return{root:n.root,segments:[...n.segments,i]}}function $e(e){return T(e.callee?.property)}function se(e,t){return e?.properties?.find(n=>T(n.key)===t)}function C(e,t){return se(e,t)!==void 0}function Pe(e){let t=se(e,"metadata")?.value;return C(t,"source")}function ae(e){return $e(e)==="publish"}var le={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=D(t),i=n?G(n):null,r=n?c.default.dirname(n):null,o=s=>{let a=w(s.source);if(a&&i&&r&&t){let f=c.default.isAbsolute(t)?t:c.default.resolve(t),g=c.default.relative(r,f).split(c.default.sep).join("/"),l=S(g,i.layers);if(!l)return;let u=re(f,a);if(!u)return;let d=c.default.relative(r,u).split(c.default.sep).join("/");if(d.startsWith(".."))return;let p=S(d,i.layers);if(!p)return;P(i.rules,l,p,{fromPath:g,toPath:d,layers:i.layers})&&x(e,s,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:g,fromLayer:l,toLayer:p,target:d,...s.importKind==="type"?{typeOnly:!0}:{},message:`${l} must not import ${p}.`},{fromLayer:l,toLayer:p,specifier:a});return}};return{ImportDeclaration:o,ExportNamedDeclaration:o,ExportAllDeclaration:o}}},ce={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],i=w(n),r=F({publishCall:ae(t),rawIntentName:i,objectHasIntent:C(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(r.some(o=>o.ruleId==="RAW_EVENT_PUBLISH")){let o=r.find(s=>s.ruleId==="RAW_EVENT_PUBLISH");x(e,t,"rawPublish",{...o,file:N(e)})}}}}},ue={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],i=t.arguments?.[2],o=F({publishCall:ae(t),rawIntentName:w(n),objectHasIntent:C(n,"intent"),arkPublishCandidate:!0,hasSource:Pe(n)||C(i,"source")}).find(s=>s.ruleId==="PUBLISH_MISSING_SOURCE");o&&x(e,t,"missingSource",{...o,file:N(e)})}}}},fe={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` explicitly overrides."},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.'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=N(e),n=e.options?.[0],i=D(t),r=i?G(i):null,o=i?c.default.dirname(i):null,s=null,a="this layer";if(n?.globals)s=new Set(n.globals);else if(r&&o&&t){let l=c.default.isAbsolute(t)?t:c.default.resolve(t),u=c.default.relative(o,l).split(c.default.sep).join("/"),d=r.layers?.find(p=>p.name===S(u,r.layers));d?.forbiddenGlobals?.length?(s=new Set(d.forbiddenGlobals),a=d.name):s=null}if(!s)return{};let f=typeof H(e)?.getScope=="function",g=(l,u)=>{let d=c.default.isAbsolute(t)?t:c.default.resolve(t),p=o?c.default.relative(o,d).split(c.default.sep).join("/"):t;x(e,l,r?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:p,fromLayer:a,target:u,message:`${a} must not use the ambient global "${u}".`},{name:u,layer:a})};return{MemberExpression(l){if(l.parent?.type==="MemberExpression"&&l.parent.object===l)return;let u=oe(l);if(!u||ne(e,u.root,u.segments[0]))return;let d=u.segments[0]==="globalThis",p=d?u.segments.slice(1):u.segments,L;for(let _=p.length;_>=(d?1:2);_-=1){let U=p.slice(0,_).join(".");if(s.has(U)){L=U;break}}L?g(l,L):!f&&s.has(u.segments[0])&&g(l,u.segments[0])},CallExpression(l){if(f)return;let u=l.callee?.type==="Identifier"?l.callee.name:void 0;u&&s.has(u)&&g(l,u)},NewExpression(l){if(f)return;let u=l.callee?.type==="Identifier"?l.callee.name:void 0;u&&s.has(u)&&g(l,u)},Identifier(l){!f||!l.name||!s.has(l.name)||!Oe(e,l)||ne(e,l,l.name)||g(l,l.name)}}}},je={"no-domain-infra-imports":le,"no-raw-event-publish":ce,"require-publish-source":ue,"no-forbidden-globals":fe},E={rules:je};E.configs={recommended:{plugins:{ark:E},rules:{"ark/no-domain-infra-imports":"error","ark/no-raw-event-publish":"error","ark/require-publish-source":"error","ark/no-forbidden-globals":"error"}}};var Ve=E;0&&(module.exports={findConfigPath,globToRegExp,isEdgeDenied,layerForRelativePath,loadArkConfig,noDomainInfraImports,noForbiddenGlobals,noRawEventPublish,patternSpecificity,plugin,requirePublishSource,resolveRelativeImport});
3
+ `)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function ne(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function D(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function A(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function Oe(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function x(e,t,n,i,r){if(t.$ref){let s=Oe(t.$ref,i);if(!s){r.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}x(e,s,n,i,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(s=>Object.is(s,e))){r.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!ne(e)){r.push({path:n,message:`must be an object; received ${A(e)}`});return}let s=t.properties??{};for(let l of t.required??[])e[l]===void 0&&r.push({path:D(n,l),message:"is required"});if(t.additionalProperties===!1)for(let l of Object.keys(e))l in s||r.push({path:D(n,l),message:"unknown field"});for(let[l,c]of Object.entries(s))e[l]!==void 0&&x(e[l],c,D(n,l),i,r);return}if(t.type==="array"){if(!Array.isArray(e)){r.push({path:n,message:`must be an array; received ${A(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 s=e.map(l=>JSON.stringify(l));new Set(s).size!==s.length&&r.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((s,l)=>x(s,t.items,`${n}[${l}]`,i,r));return}if(t.type==="string"){if(typeof e!="string"){r.push({path:n,message:`must be a string; received ${A(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 ${A(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){r.push({path:n,message:`must be an integer; received ${A(e)}`});return}t.minimum!==void 0&&e<t.minimum&&r.push({path:n,message:`must be at least ${t.minimum}`})}}function $e(e){return{...e,$schema:e.$schema===void 0?M:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.0":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?te.map(t=>({...t})):e.rules}}function Pe(e,t="ark.config.json"){if(!ne(e))throw new k(t,[{path:"$",message:`must be an object; received ${A(e)}`}]);let n=e.schemaVersion===void 0?"unversioned":null;if(e.schemaVersion!==void 0&&e.schemaVersion!=="1.0")throw new k(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.0`}]);return{candidate:$e(e),migratedFrom:n}}function je(e,t="ark.config.json"){let{candidate:n,migratedFrom:i}=Pe(e,t),r=[];if(x(n,ee,"$",ee,r),r.length>0)throw new k(t,r);return{config:n,migratedFrom:i}}function re(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(i){throw new k(t,[{path:"$",message:`invalid JSON: ${i instanceof Error?i.message:String(i)}`}])}return je(n,t)}function m(e){return typeof e=="string"&&e.length>0?e:void 0}function ie(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Fe(e,t,n){return e==="LAYER_IMPORT_VIOLATION"?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.`:e==="FORBIDDEN_GLOBAL"?`Inject ${t.target??"the capability"} through a port, then preflight again.`:e==="CAPABILITY_VIOLATION"?`Define a ${m(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, then preflight again.`:e==="CIRCULAR_DEPENDENCY"?"Extract the shared dependency into a third module, then preflight again.":e==="RAW_EVENT_PUBLISH"?"Publish through a registered intent creator, then run Ark again.":e==="PUBLISH_MISSING_SOURCE"?"Add metadata.source to the publish call, then run Ark again.":`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function se(e,t="error"){let n=m(e.ruleId)??m(e.code)??"ARK_UNKNOWN",i=e.severity==="warning"?"warning":t,r={...m(e.target)?{target:m(e.target)}:{},...m(e.fromLayer)?{fromLayer:m(e.fromLayer)}:{},...m(e.toLayer)?{toLayer:m(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{}};return{ruleId:n,severity:i,message:m(e.message)??n,location:{file:m(e.file)??"<unknown>",line:ie(e.line,1),column:ie(e.column,1)},evidence:r,nextAction:m(e.nextAction)??Fe(n,r,e)}}var oe={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."};function Ve(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function T(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&Ve(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:oe.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:oe.PUBLISH_MISSING_SOURCE}),t}function I(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,i,r){let s=se({...i,line:i.line??t.loc?.start?.line,column:i.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:s}),s}function L(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=u.default.dirname(u.default.resolve(e));for(;;){let n=u.default.join(t,"ark.config.json");if(S.default.existsSync(n))return n;let i=u.default.dirname(t);if(i===t)return null;t=i}}var v=new Map;function _(e){if(v.has(e))return v.get(e)??null;if(!S.default.existsSync(e))return null;let t=re(S.default.readFileSync(e,"utf8"),e).config;return v.set(e,t),t}function ae(e,t){if(!t.startsWith("."))return null;let n=u.default.resolve(u.default.dirname(e),t),i=[n,`${n}.ts`,`${n}.tsx`,`${n}.mts`,`${n}.cts`,`${n}.js`,`${n}.jsx`,u.default.join(n,"index.ts"),u.default.join(n,"index.tsx"),u.default.join(n,"index.js")];for(let r of i)try{if(S.default.existsSync(r)&&S.default.statSync(r).isFile())return r}catch{}return`${n}.ts`}function O(e){return typeof e?.value=="string"?e.value:void 0}function B(e){return e?.name??O(e)}function H(e){return e.sourceCode??e.getSourceCode?.()}function le(e,t){let n=H(e)?.getScope?.(t);for(;n;){let i=n.references?.find(r=>r.identifier===t);if(i)return i;n=n.upper??void 0}}function G(e,t,n){let i=le(e,t);if(i?.resolved)return(i.resolved.defs?.length??0)>0;let r=H(e)?.getScope?.(t);for(;r;){let s=r.set?.get(n);if(s)return(s.defs?.length??0)>0;r=r.upper??void 0}return!1}function De(e,t){let n=le(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function ce(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=ce(e.object),i=B(e.property);if(!(!n||!i))return{root:n.root,segments:[...n.segments,i]}}function Me(e){return B(e.callee?.property)}function ue(e,t){return e?.properties?.find(n=>B(n.key)===t)}function E(e,t){return ue(e,t)!==void 0}function Te(e){let t=ue(e,"metadata")?.value;return E(t,"source")}function de(e){return Me(e)==="publish"}var fe={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=I(e),n=L(t),i=n?_(n):null,r=n?u.default.dirname(n):null,s=l=>{let c=O(l.source);if(c&&i&&r&&t){let p=u.default.isAbsolute(t)?t:u.default.resolve(t),g=u.default.relative(r,p).split(u.default.sep).join("/"),o=h(g,i.layers);if(!o)return;let a=ae(p,c);if(!a)return;let d=u.default.relative(r,a).split(u.default.sep).join("/");if(d.startsWith(".."))return;let f=h(d,i.layers);if(!f)return;F(i.rules,o,f,{fromPath:g,toPath:d,layers:i.layers})&&w(e,l,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:g,fromLayer:o,toLayer:f,target:d,...l.importKind==="type"?{typeOnly:!0}:{},message:`${o} must not import ${f}.`},{fromLayer:o,toLayer:f,specifier:c});return}};return{ImportDeclaration:s,ExportNamedDeclaration:s,ExportAllDeclaration:s}}},pe={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],i=O(n),r=T({publishCall:de(t),rawIntentName:i,objectHasIntent:E(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(r.some(s=>s.ruleId==="RAW_EVENT_PUBLISH")){let s=r.find(l=>l.ruleId==="RAW_EVENT_PUBLISH");w(e,t,"rawPublish",{...s,file:I(e)})}}}}},ge={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],i=t.arguments?.[2],s=T({publishCall:de(t),rawIntentName:O(n),objectHasIntent:E(n,"intent"),arkPublishCandidate:!0,hasSource:Te(n)||E(i,"source")}).find(l=>l.ruleId==="PUBLISH_MISSING_SOURCE");s&&w(e,t,"missingSource",{...s,file:I(e)})}}}},me={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` explicitly overrides."},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.'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=I(e),n=e.options?.[0],i=L(t),r=i?_(i):null,s=i?u.default.dirname(i):null,l=null,c="this layer";if(n?.globals)l=new Set(n.globals);else if(r&&s&&t){let o=u.default.isAbsolute(t)?t:u.default.resolve(t),a=u.default.relative(s,o).split(u.default.sep).join("/"),d=r.layers?.find(f=>f.name===h(a,r.layers));d?.forbiddenGlobals?.length?(l=new Set(d.forbiddenGlobals),c=d.name):l=null}if(!l)return{};let p=typeof H(e)?.getScope=="function",g=(o,a)=>{let d=u.default.isAbsolute(t)?t:u.default.resolve(t),f=s?u.default.relative(s,d).split(u.default.sep).join("/"):t;w(e,o,r?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:f,fromLayer:c,target:a,message:`${c} must not use the ambient global "${a}".`},{name:a,layer:c})};return{MemberExpression(o){if(o.parent?.type==="MemberExpression"&&o.parent.object===o)return;let a=ce(o);if(!a||G(e,a.root,a.segments[0]))return;let d=a.segments[0]==="globalThis",f=d?a.segments.slice(1):a.segments,y;for(let $=f.length;$>=(d?1:2);$-=1){let K=f.slice(0,$).join(".");if(l.has(K)){y=K;break}}y?g(o,y):!p&&l.has(a.segments[0])&&g(o,a.segments[0])},CallExpression(o){if(p)return;let a=o.callee?.type==="Identifier"?o.callee.name:void 0;a&&l.has(a)&&g(o,a)},NewExpression(o){if(p)return;let a=o.callee?.type==="Identifier"?o.callee.name:void 0;a&&l.has(a)&&g(o,a)},Identifier(o){!p||!o.name||!l.has(o.name)||!De(e,o)||G(e,o,o.name)||g(o,o.name)}}}},ye={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=I(e),n=L(t),i=n?_(n):null,r=n?u.default.dirname(n):null;if(!i||!r||!t)return{};let s=u.default.isAbsolute(t)?t:u.default.resolve(t),l=u.default.relative(r,s).split(u.default.sep).join("/"),c=i.layers?.find(o=>o.name===h(l,i.layers));if(!c)return{};let p=new Set(X(c));if(p.size===0)return{};let g=(o,a,d)=>{if(d||typeof a!="string")return;let f=Z(a);!f||!p.has(f)||w(e,o,"deniedCapability",{ruleId:"CAPABILITY_VIOLATION",file:l,fromLayer:c.name,target:a,capability:f,message:`${c.name} denies the ${f} capability; found import of "${a}".`},{layer:c.name,capability:f,specifier:a})};return{ImportDeclaration(o){let a=o,d=(a.specifiers??[]).filter(y=>y.type==="ImportSpecifier"),f=d.length>0&&d.length===(a.specifiers??[]).length&&d.every(y=>y.importKind==="type");g(o,a.source?.value,a.importKind==="type"||f)},ImportExpression(o){let a=o;a.source?.type==="Literal"&&g(o,a.source.value,!1)},ExportNamedDeclaration(o){let a=o;if(!a.source)return;let d=a.specifiers??[],f=d.length>0&&d.every(y=>y.exportKind==="type");g(o,a.source.value,a.exportKind==="type"||f)},ExportAllDeclaration(o){let a=o;g(o,a.source?.value,a.exportKind==="type")},CallExpression(o){let a=o;a.callee?.type==="Identifier"&&a.callee.name==="require"&&a.arguments?.[0]?.type==="Literal"&&!G(e,o,"require")&&g(o,a.arguments[0].value,!1)}}}},ve={"no-domain-infra-imports":fe,"no-raw-event-publish":pe,"require-publish-source":ge,"no-forbidden-globals":me,"no-denied-capabilities":ye},N={rules:ve};N.configs={recommended:{plugins:{ark:N},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 Ge=N;0&&(module.exports={findConfigPath,globToRegExp,isEdgeDenied,layerForRelativePath,loadArkConfig,noDeniedCapabilities,noDomainInfraImports,noForbiddenGlobals,noRawEventPublish,patternSpecificity,plugin,requirePublishSource,resolveRelativeImport});
@@ -1,4 +1,4 @@
1
- import { A as ArkConfig } from '../configTypes-CVWWhBoe.cjs';
1
+ import { A as ArkConfig } from '../configTypes-DAPvBqK6.cjs';
2
2
 
3
3
  /**
4
4
  * Pure layer-glob matching for ark.config.json.
@@ -138,8 +138,9 @@ declare const noDomainInfraImports: ArkRule;
138
138
  declare const noRawEventPublish: ArkRule;
139
139
  declare const requirePublishSource: ArkRule;
140
140
  declare const noForbiddenGlobals: ArkRule;
141
+ declare const noDeniedCapabilities: ArkRule;
141
142
  declare const plugin: ArkEslintPlugin;
142
143
 
143
144
  // @ts-ignore
144
145
  export = plugin;
145
- export { findConfigPath, globToRegExp, isEdgeDenied, layerForRelativePath, loadArkConfig, noDomainInfraImports, noForbiddenGlobals, noRawEventPublish, patternSpecificity, plugin, requirePublishSource, resolveRelativeImport };
146
+ export { findConfigPath, globToRegExp, isEdgeDenied, layerForRelativePath, loadArkConfig, noDeniedCapabilities, noDomainInfraImports, noForbiddenGlobals, noRawEventPublish, patternSpecificity, plugin, requirePublishSource, resolveRelativeImport };
@@ -1,4 +1,4 @@
1
- import { A as ArkConfig } from '../configTypes-CVWWhBoe.js';
1
+ import { A as ArkConfig } from '../configTypes-DAPvBqK6.js';
2
2
 
3
3
  /**
4
4
  * Pure layer-glob matching for ark.config.json.
@@ -138,6 +138,7 @@ declare const noDomainInfraImports: ArkRule;
138
138
  declare const noRawEventPublish: ArkRule;
139
139
  declare const requirePublishSource: ArkRule;
140
140
  declare const noForbiddenGlobals: ArkRule;
141
+ declare const noDeniedCapabilities: ArkRule;
141
142
  declare const plugin: ArkEslintPlugin;
142
143
 
143
- export { plugin as default, findConfigPath, globToRegExp, isEdgeDenied, layerForRelativePath, loadArkConfig, noDomainInfraImports, noForbiddenGlobals, noRawEventPublish, patternSpecificity, plugin, requirePublishSource, resolveRelativeImport };
144
+ export { plugin as default, findConfigPath, globToRegExp, isEdgeDenied, layerForRelativePath, loadArkConfig, noDeniedCapabilities, noDomainInfraImports, noForbiddenGlobals, noRawEventPublish, patternSpecificity, plugin, requirePublishSource, resolveRelativeImport };
@@ -1,3 +1,3 @@
1
- import b from"fs";import u from"path";var D=new Map;function G(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function L(e){let t="";for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=i}return t}function ie(e){let t=0;for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"){n+=1;continue}if(i==="{")t+=1;else if(i==="}"&&(t-=1,t<0))return!1}return t===0}function w(e){let t=D.get(e);if(t)return t;let n=L(e),i=ie(n),r="",o=0;for(let a=0;a<n.length;a+=1){let f=n[a];f==="\\"&&a+1<n.length?(r+=G(n[a+1]),a+=1):f==="*"?n[a+1]==="*"?n[a+2]==="/"?(r+="(?:.*/)?",a+=2):(r+=".*",a+=1):r+="[^/]*":f==="?"?r+="[^/]":f==="{"&&i?(r+="(?:",o+=1):f==="}"&&i&&o>0?(r+=")",o-=1):f===","&&i&&o>0?r+="|":r+=G(f)}let s=new RegExp(`^${r}$`);return D.set(e,s),s}function H(e){let t=L(String(e)),i=t.split("*")[0].split("/").filter(Boolean).length,r=t.replace(/\*/g,"").length;return i*1e4+r}function S(e,t){let n=String(e).split(/[/\\]/).join("/"),i,r=-1;for(let o of t??[])if(!(o.exclude??[]).some(s=>w(s).test(n))){for(let s of o.patterns??[])if(w(s).test(n)){let a=H(s);a>r&&(r=a,i=o.name)}}return i}function T(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),i=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(i.has(n[r].toLowerCase()))return`${n[r]}/${n[r+1]}`}function oe(e){let t=new Set;for(let n of e??[]){let r=L(String(n)).split("/").filter(Boolean);for(let o=0;o<r.length;o+=1){let s=r[o];if((s==="**"||s==="*")&&o>0){let a=r[o-1];a&&!a.includes("*")&&!a.includes("{")&&!a.includes("}")&&t.add(a)}}}return[...t]}function se(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let i=(n??[]).find(r=>r.name===t);return oe(i?.patterns)}function ae(e,t,n,i){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let o=i?.fromPath,s=i?.toPath;if(!o||!s)continue;let a=se(r,t,i?.layers);if(a.length===0)continue;let f=T(o,a),g=T(s,a);if(!f||!g)continue;if(f!==g)return r;continue}if(t!==n)return r}}function U(e,t,n,i){return ae(e,t,n,i)!==void 0}var O="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",v=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],le=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function ce(){let e=[];for(let t of v)for(let n of v)t===n||le.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var K=ce();var y={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},B={$schema:"https://json-schema.org/draft/2020-12/schema",$id:O,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:O,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.0",default:"1.0"},name:{type:"string",minLength:1},include:{...y,minItems:1,default:["src"]},exclude:{...y,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:K,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...y,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...y,minItems:1},exclude:y,intentPrefixes:y,description:{type:"string",minLength:1},forbiddenGlobals:y,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:{...y,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}}}}},A=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
1
+ import S from"fs";import u from"path";var B=new Map;function H(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function L(e){let t="";for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"&&n+1<e.length){let r=e[n+1];if("*?{}[],".includes(r)||r==="\\"){t+="\\"+r,n+=1;continue}t+="/";continue}t+=i}return t}function le(e){let t=0;for(let n=0;n<e.length;n+=1){let i=e[n];if(i==="\\"){n+=1;continue}if(i==="{")t+=1;else if(i==="}"&&(t-=1,t<0))return!1}return t===0}function N(e){let t=B.get(e);if(t)return t;let n=L(e),i=le(n),r="",s=0;for(let c=0;c<n.length;c+=1){let p=n[c];p==="\\"&&c+1<n.length?(r+=H(n[c+1]),c+=1):p==="*"?n[c+1]==="*"?n[c+2]==="/"?(r+="(?:.*/)?",c+=2):(r+=".*",c+=1):r+="[^/]*":p==="?"?r+="[^/]":p==="{"&&i?(r+="(?:",s+=1):p==="}"&&i&&s>0?(r+=")",s-=1):p===","&&i&&s>0?r+="|":r+=H(p)}let l=new RegExp(`^${r}$`);return B.set(e,l),l}function U(e){let t=L(String(e)),i=t.split("*")[0].split("/").filter(Boolean).length,r=t.replace(/\*/g,"").length;return i*1e4+r}function k(e,t){let n=String(e).split(/[/\\]/).join("/"),i,r=-1;for(let s of t??[])if(!(s.exclude??[]).some(l=>N(l).test(n))){for(let l of s.patterns??[])if(N(l).test(n)){let c=U(l);c>r&&(r=c,i=s.name)}}return i}function K(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),i=new Set(t.map(r=>String(r).toLowerCase()));for(let r=0;r<n.length-1;r+=1)if(i.has(n[r].toLowerCase()))return`${n[r]}/${n[r+1]}`}function ce(e){let t=new Set;for(let n of e??[]){let r=L(String(n)).split("/").filter(Boolean);for(let s=0;s<r.length;s+=1){let l=r[s];if((l==="**"||l==="*")&&s>0){let c=r[s-1];c&&!c.includes("*")&&!c.includes("{")&&!c.includes("}")&&t.add(c)}}}return[...t]}function ue(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(r=>typeof r=="string"&&r.length>0);let i=(n??[]).find(r=>r.name===t);return ce(i?.patterns)}function de(e,t,n,i){for(let r of e??[])if(!(r.from!==t||r.to!==n)&&r.allowed===!1){if(r.peerIsolation){let s=i?.fromPath,l=i?.toPath;if(!s||!l)continue;let c=ue(r,t,i?.layers);if(c.length===0)continue;let p=K(s,c),g=K(l,c);if(!p||!g)continue;if(p!==g)return r;continue}if(t!==n)return r}}function q(e,t,n,i){return de(e,t,n,i)!==void 0}var W=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),fe=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),$e=Object.freeze(Object.keys(fe).sort()),_=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"});function Y(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=_[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let i=e.slice(0,n),r=_[i];if(r)return r;let s=e.indexOf("/",n+1);return s<0?null:_[e.slice(0,s)]??null}function z(e){if(e?.pure===!0)return[...W].sort();let n=(e?.capabilities?.deny??[]).filter(i=>W.includes(i));return[...new Set(n)].sort()}var $="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",J=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],pe=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function ge(){let e=[];for(let t of J)for(let n of J)t===n||pe.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var X=ge();var b={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},Z={$schema:"https://json-schema.org/draft/2020-12/schema",$id:$,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:$,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.0",default:"1.0"},name:{type:"string",minLength:1},include:{...b,minItems:1,default:["src"]},exclude:{...b,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:X,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...b,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...b,minItems:1},exclude:b,intentPrefixes:b,description:{type:"string",minLength:1},forbiddenGlobals:b,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:{...b,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}}}}},A=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
2
2
  ${n.map(i=>`- ${i.path}: ${i.message}`).join(`
3
- `)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function W(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 h(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function ue(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function k(e,t,n,i,r){if(t.$ref){let o=ue(t.$ref,i);if(!o){r.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}k(e,o,n,i,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(o=>Object.is(o,e))){r.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!W(e)){r.push({path:n,message:`must be an object; received ${h(e)}`});return}let o=t.properties??{};for(let s of t.required??[])e[s]===void 0&&r.push({path:_(n,s),message:"is required"});if(t.additionalProperties===!1)for(let s of Object.keys(e))s in o||r.push({path:_(n,s),message:"unknown field"});for(let[s,a]of Object.entries(o))e[s]!==void 0&&k(e[s],a,_(n,s),i,r);return}if(t.type==="array"){if(!Array.isArray(e)){r.push({path:n,message:`must be an array; received ${h(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 o=e.map(s=>JSON.stringify(s));new Set(o).size!==o.length&&r.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((o,s)=>k(o,t.items,`${n}[${s}]`,i,r));return}if(t.type==="string"){if(typeof e!="string"){r.push({path:n,message:`must be a string; received ${h(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 ${h(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){r.push({path:n,message:`must be an integer; received ${h(e)}`});return}t.minimum!==void 0&&e<t.minimum&&r.push({path:n,message:`must be at least ${t.minimum}`})}}function fe(e){return{...e,$schema:e.$schema===void 0?O:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.0":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?K.map(t=>({...t})):e.rules}}function de(e,t="ark.config.json"){if(!W(e))throw new A(t,[{path:"$",message:`must be an object; received ${h(e)}`}]);let n=e.schemaVersion===void 0?"unversioned":null;if(e.schemaVersion!==void 0&&e.schemaVersion!=="1.0")throw new A(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.0`}]);return{candidate:fe(e),migratedFrom:n}}function ge(e,t="ark.config.json"){let{candidate:n,migratedFrom:i}=de(e,t),r=[];if(k(n,B,"$",B,r),r.length>0)throw new A(t,r);return{config:n,migratedFrom:i}}function q(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(i){throw new A(t,[{path:"$",message:`invalid JSON: ${i instanceof Error?i.message:String(i)}`}])}return ge(n,t)}function m(e){return typeof e=="string"&&e.length>0?e:void 0}function J(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function pe(e,t,n){return e==="LAYER_IMPORT_VIOLATION"?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.`:e==="FORBIDDEN_GLOBAL"?`Inject ${t.target??"the capability"} through a port, then preflight again.`:e==="CIRCULAR_DEPENDENCY"?"Extract the shared dependency into a third module, then preflight again.":e==="RAW_EVENT_PUBLISH"?"Publish through a registered intent creator, then run Ark again.":e==="PUBLISH_MISSING_SOURCE"?"Add metadata.source to the publish call, then run Ark again.":`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function Y(e,t="error"){let n=m(e.ruleId)??m(e.code)??"ARK_UNKNOWN",i=e.severity==="warning"?"warning":t,r={...m(e.target)?{target:m(e.target)}:{},...m(e.fromLayer)?{fromLayer:m(e.fromLayer)}:{},...m(e.toLayer)?{toLayer:m(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{}};return{ruleId:n,severity:i,message:m(e.message)??n,location:{file:m(e.file)??"<unknown>",line:J(e.line,1),column:J(e.column,1)},evidence:r,nextAction:m(e.nextAction)??pe(n,r,e)}}var z={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."};function me(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function $(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&me(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:z.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:z.PUBLISH_MISSING_SOURCE}),t}function I(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 C(e,t,n,i,r){let o=Y({...i,line:i.line??t.loc?.start?.line,column:i.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:o}),o}function Q(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=u.dirname(u.resolve(e));for(;;){let n=u.join(t,"ark.config.json");if(b.existsSync(n))return n;let i=u.dirname(t);if(i===t)return null;t=i}}var P=new Map;function X(e){if(P.has(e))return P.get(e)??null;if(!b.existsSync(e))return null;let t=q(b.readFileSync(e,"utf8"),e).config;return P.set(e,t),t}function ye(e,t){if(!t.startsWith("."))return null;let n=u.resolve(u.dirname(e),t),i=[n,`${n}.ts`,`${n}.tsx`,`${n}.mts`,`${n}.cts`,`${n}.js`,`${n}.jsx`,u.join(n,"index.ts"),u.join(n,"index.tsx"),u.join(n,"index.js")];for(let r of i)try{if(b.existsSync(r)&&b.statSync(r).isFile())return r}catch{}return`${n}.ts`}function E(e){return typeof e?.value=="string"?e.value:void 0}function V(e){return e?.name??E(e)}function F(e){return e.sourceCode??e.getSourceCode?.()}function ee(e,t){let n=F(e)?.getScope?.(t);for(;n;){let i=n.references?.find(r=>r.identifier===t);if(i)return i;n=n.upper??void 0}}function Z(e,t,n){let i=ee(e,t);if(i?.resolved)return(i.resolved.defs?.length??0)>0;let r=F(e)?.getScope?.(t);for(;r;){let o=r.set?.get(n);if(o)return(o.defs?.length??0)>0;r=r.upper??void 0}return!1}function he(e,t){let n=ee(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function te(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=te(e.object),i=V(e.property);if(!(!n||!i))return{root:n.root,segments:[...n.segments,i]}}function Ae(e){return V(e.callee?.property)}function ne(e,t){return e?.properties?.find(n=>V(n.key)===t)}function R(e,t){return ne(e,t)!==void 0}function be(e){let t=ne(e,"metadata")?.value;return R(t,"source")}function re(e){return Ae(e)==="publish"}var Se={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=I(e),n=Q(t),i=n?X(n):null,r=n?u.dirname(n):null,o=s=>{let a=E(s.source);if(a&&i&&r&&t){let f=u.isAbsolute(t)?t:u.resolve(t),g=u.relative(r,f).split(u.sep).join("/"),l=S(g,i.layers);if(!l)return;let c=ye(f,a);if(!c)return;let d=u.relative(r,c).split(u.sep).join("/");if(d.startsWith(".."))return;let p=S(d,i.layers);if(!p)return;U(i.rules,l,p,{fromPath:g,toPath:d,layers:i.layers})&&C(e,s,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:g,fromLayer:l,toLayer:p,target:d,...s.importKind==="type"?{typeOnly:!0}:{},message:`${l} must not import ${p}.`},{fromLayer:l,toLayer:p,specifier:a});return}};return{ImportDeclaration:o,ExportNamedDeclaration:o,ExportAllDeclaration:o}}},ke={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],i=E(n),r=$({publishCall:re(t),rawIntentName:i,objectHasIntent:R(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(r.some(o=>o.ruleId==="RAW_EVENT_PUBLISH")){let o=r.find(s=>s.ruleId==="RAW_EVENT_PUBLISH");C(e,t,"rawPublish",{...o,file:I(e)})}}}}},Re={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],i=t.arguments?.[2],o=$({publishCall:re(t),rawIntentName:E(n),objectHasIntent:R(n,"intent"),arkPublishCandidate:!0,hasSource:be(n)||R(i,"source")}).find(s=>s.ruleId==="PUBLISH_MISSING_SOURCE");o&&C(e,t,"missingSource",{...o,file:I(e)})}}}},Ie={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` explicitly overrides."},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.'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=I(e),n=e.options?.[0],i=Q(t),r=i?X(i):null,o=i?u.dirname(i):null,s=null,a="this layer";if(n?.globals)s=new Set(n.globals);else if(r&&o&&t){let l=u.isAbsolute(t)?t:u.resolve(t),c=u.relative(o,l).split(u.sep).join("/"),d=r.layers?.find(p=>p.name===S(c,r.layers));d?.forbiddenGlobals?.length?(s=new Set(d.forbiddenGlobals),a=d.name):s=null}if(!s)return{};let f=typeof F(e)?.getScope=="function",g=(l,c)=>{let d=u.isAbsolute(t)?t:u.resolve(t),p=o?u.relative(o,d).split(u.sep).join("/"):t;C(e,l,r?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:p,fromLayer:a,target:c,message:`${a} must not use the ambient global "${c}".`},{name:c,layer:a})};return{MemberExpression(l){if(l.parent?.type==="MemberExpression"&&l.parent.object===l)return;let c=te(l);if(!c||Z(e,c.root,c.segments[0]))return;let d=c.segments[0]==="globalThis",p=d?c.segments.slice(1):c.segments,N;for(let x=p.length;x>=(d?1:2);x-=1){let M=p.slice(0,x).join(".");if(s.has(M)){N=M;break}}N?g(l,N):!f&&s.has(c.segments[0])&&g(l,c.segments[0])},CallExpression(l){if(f)return;let c=l.callee?.type==="Identifier"?l.callee.name:void 0;c&&s.has(c)&&g(l,c)},NewExpression(l){if(f)return;let c=l.callee?.type==="Identifier"?l.callee.name:void 0;c&&s.has(c)&&g(l,c)},Identifier(l){!f||!l.name||!s.has(l.name)||!he(e,l)||Z(e,l,l.name)||g(l,l.name)}}}},Ce={"no-domain-infra-imports":Se,"no-raw-event-publish":ke,"require-publish-source":Re,"no-forbidden-globals":Ie},j={rules:Ce};j.configs={recommended:{plugins:{ark:j},rules:{"ark/no-domain-infra-imports":"error","ark/no-raw-event-publish":"error","ark/require-publish-source":"error","ark/no-forbidden-globals":"error"}}};var Ve=j;export{Ve as default,Q as findConfigPath,w as globToRegExp,U as isEdgeDenied,S as layerForRelativePath,X as loadArkConfig,Se as noDomainInfraImports,Ie as noForbiddenGlobals,ke as noRawEventPublish,H as patternSpecificity,j as plugin,Re as requirePublishSource,ye as resolveRelativeImport};
3
+ `)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function Q(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 h(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function me(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function C(e,t,n,i,r){if(t.$ref){let s=me(t.$ref,i);if(!s){r.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}C(e,s,n,i,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(s=>Object.is(s,e))){r.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!Q(e)){r.push({path:n,message:`must be an object; received ${h(e)}`});return}let s=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 s||r.push({path:O(n,l),message:"unknown field"});for(let[l,c]of Object.entries(s))e[l]!==void 0&&C(e[l],c,O(n,l),i,r);return}if(t.type==="array"){if(!Array.isArray(e)){r.push({path:n,message:`must be an array; received ${h(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 s=e.map(l=>JSON.stringify(l));new Set(s).size!==s.length&&r.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((s,l)=>C(s,t.items,`${n}[${l}]`,i,r));return}if(t.type==="string"){if(typeof e!="string"){r.push({path:n,message:`must be a string; received ${h(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 ${h(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){r.push({path:n,message:`must be an integer; received ${h(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?$:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.0":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?X.map(t=>({...t})):e.rules}}function be(e,t="ark.config.json"){if(!Q(e))throw new A(t,[{path:"$",message:`must be an object; received ${h(e)}`}]);let n=e.schemaVersion===void 0?"unversioned":null;if(e.schemaVersion!==void 0&&e.schemaVersion!=="1.0")throw new A(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.0`}]);return{candidate:ye(e),migratedFrom:n}}function he(e,t="ark.config.json"){let{candidate:n,migratedFrom:i}=be(e,t),r=[];if(C(n,Z,"$",Z,r),r.length>0)throw new A(t,r);return{config:n,migratedFrom:i}}function ee(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(i){throw new A(t,[{path:"$",message:`invalid JSON: ${i instanceof Error?i.message:String(i)}`}])}return he(n,t)}function m(e){return typeof e=="string"&&e.length>0?e:void 0}function te(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Ae(e,t,n){return e==="LAYER_IMPORT_VIOLATION"?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.`:e==="FORBIDDEN_GLOBAL"?`Inject ${t.target??"the capability"} through a port, then preflight again.`:e==="CAPABILITY_VIOLATION"?`Define a ${m(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, then preflight again.`:e==="CIRCULAR_DEPENDENCY"?"Extract the shared dependency into a third module, then preflight again.":e==="RAW_EVENT_PUBLISH"?"Publish through a registered intent creator, then run Ark again.":e==="PUBLISH_MISSING_SOURCE"?"Add metadata.source to the publish call, then run Ark again.":`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function ne(e,t="error"){let n=m(e.ruleId)??m(e.code)??"ARK_UNKNOWN",i=e.severity==="warning"?"warning":t,r={...m(e.target)?{target:m(e.target)}:{},...m(e.fromLayer)?{fromLayer:m(e.fromLayer)}:{},...m(e.toLayer)?{toLayer:m(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{}};return{ruleId:n,severity:i,message:m(e.message)??n,location:{file:m(e.file)??"<unknown>",line:te(e.line,1),column:te(e.column,1)},evidence:r,nextAction:m(e.nextAction)??Ae(n,r,e)}}var re={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."};function ke(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function P(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&ke(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:re.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:re.PUBLISH_MISSING_SOURCE}),t}function I(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,i,r){let s=ne({...i,line:i.line??t.loc?.start?.line,column:i.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:s}),s}function D(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=u.dirname(u.resolve(e));for(;;){let n=u.join(t,"ark.config.json");if(S.existsSync(n))return n;let i=u.dirname(t);if(i===t)return null;t=i}}var j=new Map;function M(e){if(j.has(e))return j.get(e)??null;if(!S.existsSync(e))return null;let t=ee(S.readFileSync(e,"utf8"),e).config;return j.set(e,t),t}function Se(e,t){if(!t.startsWith("."))return null;let n=u.resolve(u.dirname(e),t),i=[n,`${n}.ts`,`${n}.tsx`,`${n}.mts`,`${n}.cts`,`${n}.js`,`${n}.jsx`,u.join(n,"index.ts"),u.join(n,"index.tsx"),u.join(n,"index.js")];for(let r of i)try{if(S.existsSync(r)&&S.statSync(r).isFile())return r}catch{}return`${n}.ts`}function x(e){return typeof e?.value=="string"?e.value:void 0}function T(e){return e?.name??x(e)}function v(e){return e.sourceCode??e.getSourceCode?.()}function ie(e,t){let n=v(e)?.getScope?.(t);for(;n;){let i=n.references?.find(r=>r.identifier===t);if(i)return i;n=n.upper??void 0}}function F(e,t,n){let i=ie(e,t);if(i?.resolved)return(i.resolved.defs?.length??0)>0;let r=v(e)?.getScope?.(t);for(;r;){let s=r.set?.get(n);if(s)return(s.defs?.length??0)>0;r=r.upper??void 0}return!1}function Ie(e,t){let n=ie(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function se(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=se(e.object),i=T(e.property);if(!(!n||!i))return{root:n.root,segments:[...n.segments,i]}}function we(e){return T(e.callee?.property)}function oe(e,t){return e?.properties?.find(n=>T(n.key)===t)}function R(e,t){return oe(e,t)!==void 0}function Ce(e){let t=oe(e,"metadata")?.value;return R(t,"source")}function ae(e){return we(e)==="publish"}var Re={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=I(e),n=D(t),i=n?M(n):null,r=n?u.dirname(n):null,s=l=>{let c=x(l.source);if(c&&i&&r&&t){let p=u.isAbsolute(t)?t:u.resolve(t),g=u.relative(r,p).split(u.sep).join("/"),o=k(g,i.layers);if(!o)return;let a=Se(p,c);if(!a)return;let d=u.relative(r,a).split(u.sep).join("/");if(d.startsWith(".."))return;let f=k(d,i.layers);if(!f)return;q(i.rules,o,f,{fromPath:g,toPath:d,layers:i.layers})&&w(e,l,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:g,fromLayer:o,toLayer:f,target:d,...l.importKind==="type"?{typeOnly:!0}:{},message:`${o} must not import ${f}.`},{fromLayer:o,toLayer:f,specifier:c});return}};return{ImportDeclaration:s,ExportNamedDeclaration:s,ExportAllDeclaration:s}}},xe={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],i=x(n),r=P({publishCall:ae(t),rawIntentName:i,objectHasIntent:R(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(r.some(s=>s.ruleId==="RAW_EVENT_PUBLISH")){let s=r.find(l=>l.ruleId==="RAW_EVENT_PUBLISH");w(e,t,"rawPublish",{...s,file:I(e)})}}}}},Ee={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],i=t.arguments?.[2],s=P({publishCall:ae(t),rawIntentName:x(n),objectHasIntent:R(n,"intent"),arkPublishCandidate:!0,hasSource:Ce(n)||R(i,"source")}).find(l=>l.ruleId==="PUBLISH_MISSING_SOURCE");s&&w(e,t,"missingSource",{...s,file:I(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` explicitly overrides."},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.'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=I(e),n=e.options?.[0],i=D(t),r=i?M(i):null,s=i?u.dirname(i):null,l=null,c="this layer";if(n?.globals)l=new Set(n.globals);else if(r&&s&&t){let o=u.isAbsolute(t)?t:u.resolve(t),a=u.relative(s,o).split(u.sep).join("/"),d=r.layers?.find(f=>f.name===k(a,r.layers));d?.forbiddenGlobals?.length?(l=new Set(d.forbiddenGlobals),c=d.name):l=null}if(!l)return{};let p=typeof v(e)?.getScope=="function",g=(o,a)=>{let d=u.isAbsolute(t)?t:u.resolve(t),f=s?u.relative(s,d).split(u.sep).join("/"):t;w(e,o,r?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:f,fromLayer:c,target:a,message:`${c} must not use the ambient global "${a}".`},{name:a,layer:c})};return{MemberExpression(o){if(o.parent?.type==="MemberExpression"&&o.parent.object===o)return;let a=se(o);if(!a||F(e,a.root,a.segments[0]))return;let d=a.segments[0]==="globalThis",f=d?a.segments.slice(1):a.segments,y;for(let E=f.length;E>=(d?1:2);E-=1){let G=f.slice(0,E).join(".");if(l.has(G)){y=G;break}}y?g(o,y):!p&&l.has(a.segments[0])&&g(o,a.segments[0])},CallExpression(o){if(p)return;let a=o.callee?.type==="Identifier"?o.callee.name:void 0;a&&l.has(a)&&g(o,a)},NewExpression(o){if(p)return;let a=o.callee?.type==="Identifier"?o.callee.name:void 0;a&&l.has(a)&&g(o,a)},Identifier(o){!p||!o.name||!l.has(o.name)||!Ie(e,o)||F(e,o,o.name)||g(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=I(e),n=D(t),i=n?M(n):null,r=n?u.dirname(n):null;if(!i||!r||!t)return{};let s=u.isAbsolute(t)?t:u.resolve(t),l=u.relative(r,s).split(u.sep).join("/"),c=i.layers?.find(o=>o.name===k(l,i.layers));if(!c)return{};let p=new Set(z(c));if(p.size===0)return{};let g=(o,a,d)=>{if(d||typeof a!="string")return;let f=Y(a);!f||!p.has(f)||w(e,o,"deniedCapability",{ruleId:"CAPABILITY_VIOLATION",file:l,fromLayer:c.name,target:a,capability:f,message:`${c.name} denies the ${f} capability; found import of "${a}".`},{layer:c.name,capability:f,specifier:a})};return{ImportDeclaration(o){let a=o,d=(a.specifiers??[]).filter(y=>y.type==="ImportSpecifier"),f=d.length>0&&d.length===(a.specifiers??[]).length&&d.every(y=>y.importKind==="type");g(o,a.source?.value,a.importKind==="type"||f)},ImportExpression(o){let a=o;a.source?.type==="Literal"&&g(o,a.source.value,!1)},ExportNamedDeclaration(o){let a=o;if(!a.source)return;let d=a.specifiers??[],f=d.length>0&&d.every(y=>y.exportKind==="type");g(o,a.source.value,a.exportKind==="type"||f)},ExportAllDeclaration(o){let a=o;g(o,a.source?.value,a.exportKind==="type")},CallExpression(o){let a=o;a.callee?.type==="Identifier"&&a.callee.name==="require"&&a.arguments?.[0]?.type==="Literal"&&!F(e,o,"require")&&g(o,a.arguments[0].value,!1)}}}},_e={"no-domain-infra-imports":Re,"no-raw-event-publish":xe,"require-publish-source":Ee,"no-forbidden-globals":Ne,"no-denied-capabilities":Le},V={rules:_e};V.configs={recommended:{plugins:{ark:V},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 Ke=V;export{Ke as default,D as findConfigPath,N as globToRegExp,q as isEdgeDenied,k as layerForRelativePath,M as loadArkConfig,Le as noDeniedCapabilities,Re as noDomainInfraImports,Ne as noForbiddenGlobals,xe as noRawEventPublish,U as patternSpecificity,V as plugin,Ee as requirePublishSource,Se as resolveRelativeImport};