arkgate 2.13.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +53 -36
  3. package/bin/ark-check.mjs +72 -6
  4. package/bin/ark-mcp.mjs +108 -1
  5. package/bin/ark-shared.mjs +204 -149
  6. package/bin/ark.mjs +90 -25
  7. package/bin/lib/adapter-contract.mjs +93 -0
  8. package/bin/lib/agent-gates.mjs +1 -0
  9. package/bin/lib/analysis-engine.mjs +1171 -0
  10. package/bin/lib/architecture-scan.mjs +84 -135
  11. package/bin/lib/ci-and-commands.mjs +51 -15
  12. package/bin/lib/config-warnings.mjs +7 -205
  13. package/bin/lib/design-smells.mjs +434 -0
  14. package/bin/lib/doctor-plan.mjs +149 -16
  15. package/bin/lib/field-install.mjs +67 -10
  16. package/bin/lib/gate-files.mjs +42 -3
  17. package/bin/lib/graph-cycles.mjs +4 -54
  18. package/bin/lib/hook-templates.mjs +33 -1
  19. package/bin/lib/host-support-matrix.mjs +7 -1
  20. package/bin/lib/install-migrate.mjs +54 -16
  21. package/bin/lib/presets.mjs +42 -2
  22. package/bin/lib/safety-diagnostics.mjs +18 -17
  23. package/bin/lib/scan-files.mjs +12 -1
  24. package/bin/lib/skill-install.mjs +8 -1
  25. package/bin/lib/source-policy.mjs +36 -0
  26. package/bin/lib/start-preview.mjs +271 -0
  27. package/bin/lib/ts-resolve.mjs +11 -2
  28. package/bin/lib/write-path-capabilities.mjs +4 -0
  29. package/compat/nestjs.cjs +2 -0
  30. package/compat/nestjs.d.ts +2 -0
  31. package/compat/nestjs.js +1 -0
  32. package/compat/runtime.cjs +2 -0
  33. package/compat/runtime.d.ts +2 -0
  34. package/compat/runtime.js +1 -0
  35. package/dist/configContract-BxSIwVRo.d.cts +259 -0
  36. package/dist/configContract-BxSIwVRo.d.ts +259 -0
  37. package/dist/eslint/index.cjs +125 -48
  38. package/dist/eslint/index.d.cts +7 -1
  39. package/dist/eslint/index.d.ts +7 -1
  40. package/dist/eslint/index.js +125 -48
  41. package/dist/index.cjs +1248 -3302
  42. package/dist/index.d.cts +359 -483
  43. package/dist/index.d.ts +359 -483
  44. package/dist/index.js +1231 -3248
  45. package/docs/agent-guide.md +34 -16
  46. package/docs/ai-gates.md +30 -7
  47. package/docs/brownfield-adoption.md +52 -1
  48. package/docs/migrate-from-ark-runtime-kernel.md +2 -3
  49. package/docs/package-surface.md +10 -13
  50. package/docs/production-hardening.md +17 -4
  51. package/docs/typescript-support.md +27 -0
  52. package/package.json +33 -11
  53. package/schemas/ark.analysis-result.schema.json +91 -0
  54. package/server.json +2 -2
  55. package/templates/skills/ark-adopt.md +26 -3
  56. package/templates/skills/ark-architect.md +10 -2
  57. package/templates/skills/ark-autopilot.md +37 -20
  58. package/templates/skills/ark-contract.md +7 -0
  59. package/templates/skills/ark-coverage.md +44 -45
  60. package/templates/skills/ark-explain.md +8 -0
  61. package/templates/skills/ark-explore.md +117 -47
  62. package/templates/skills/ark-fix.md +22 -0
  63. package/templates/skills/ark-loop.md +15 -1
  64. package/templates/skills/ark-place.md +7 -0
  65. package/templates/skills/ark-think.md +24 -20
  66. package/dist/configContract-iBLxx5Tz.d.cts +0 -53
  67. package/dist/configContract-iBLxx5Tz.d.ts +0 -53
  68. package/dist/eslint/index.cjs.map +0 -1
  69. package/dist/eslint/index.js.map +0 -1
  70. package/dist/index.cjs.map +0 -1
  71. package/dist/index.js.map +0 -1
  72. package/dist/nestjs/index.cjs +0 -2606
  73. package/dist/nestjs/index.cjs.map +0 -1
  74. package/dist/nestjs/index.d.cts +0 -23
  75. package/dist/nestjs/index.d.ts +0 -23
  76. package/dist/nestjs/index.js +0 -2582
  77. package/dist/nestjs/index.js.map +0 -1
  78. package/dist/runtime/index.cjs +0 -4014
  79. package/dist/runtime/index.cjs.map +0 -1
  80. package/dist/runtime/index.d.cts +0 -3
  81. package/dist/runtime/index.d.ts +0 -3
  82. package/dist/runtime/index.js +0 -3925
  83. package/dist/runtime/index.js.map +0 -1
  84. package/dist/types-BxBwnBpC.d.cts +0 -1041
  85. package/dist/types-Wcs_l1_J.d.ts +0 -1041
@@ -0,0 +1,259 @@
1
+ /**
2
+ * Canonical, pure contract for ark.config.json.
3
+ *
4
+ * Tooling adapters own filesystem I/O; this module owns JSON parsing, deterministic
5
+ * migration, defaults, validation, diagnostics, and the published JSON Schema.
6
+ * The standalone CLI artifact is generated into bin/lib/config-contract.mjs.
7
+ */
8
+ declare const ARK_CONFIG_SCHEMA_VERSION: "1.0";
9
+ type ArkConfigCyclePolicy = 'strict' | 'soft' | 'framework-soft' | 'off';
10
+ type ArkConfigLayer = {
11
+ name: string;
12
+ patterns: string[];
13
+ exclude?: string[];
14
+ intentPrefixes?: string[];
15
+ description?: string;
16
+ forbiddenGlobals?: string[];
17
+ mayImportInfrastructure?: boolean;
18
+ optional?: boolean;
19
+ };
20
+ type ArkConfigRule = {
21
+ from: string;
22
+ to: string;
23
+ allowed: boolean;
24
+ message?: string;
25
+ peerIsolation?: boolean;
26
+ sliceFolders?: string[];
27
+ };
28
+ type ArkConfigSafety = {
29
+ maxTsSuppressions?: number;
30
+ maxAnyCasts?: number;
31
+ allowInMemory?: boolean;
32
+ allowDisabledPeerIsolation?: boolean;
33
+ };
34
+ type ArkConfig = {
35
+ $schema: string;
36
+ schemaVersion: typeof ARK_CONFIG_SCHEMA_VERSION;
37
+ name?: string;
38
+ include: string[];
39
+ exclude?: string[];
40
+ excludeGenerated?: boolean;
41
+ frameworkOverlay?: string;
42
+ layers: ArkConfigLayer[];
43
+ rules: ArkConfigRule[];
44
+ cyclePolicy?: ArkConfigCyclePolicy;
45
+ dynamicImportAllowlist?: string[];
46
+ safety?: ArkConfigSafety;
47
+ };
48
+ declare const ARK_CONFIG_SCHEMA: {
49
+ readonly $schema: "https://json-schema.org/draft/2020-12/schema";
50
+ readonly $id: "https://unpkg.com/arkgate@2/schemas/ark.config.schema.json";
51
+ readonly title: "ArkGate architecture contract";
52
+ readonly description: "Versioned contract consumed identically by ArkGate CLI, MCP, and ESLint surfaces.";
53
+ readonly type: "object";
54
+ readonly additionalProperties: false;
55
+ readonly required: readonly ["$schema", "schemaVersion", "include", "layers", "rules"];
56
+ readonly properties: {
57
+ readonly $schema: {
58
+ readonly type: "string";
59
+ readonly minLength: 1;
60
+ readonly default: "https://unpkg.com/arkgate@2/schemas/ark.config.schema.json";
61
+ readonly description: "Editor-facing URL or local path for this JSON Schema.";
62
+ };
63
+ readonly schemaVersion: {
64
+ readonly type: "string";
65
+ readonly const: "1.0";
66
+ readonly default: "1.0";
67
+ };
68
+ readonly name: {
69
+ readonly type: "string";
70
+ readonly minLength: 1;
71
+ };
72
+ readonly include: {
73
+ readonly minItems: 1;
74
+ readonly default: readonly ["src"];
75
+ readonly type: "array";
76
+ readonly items: {
77
+ readonly type: "string";
78
+ readonly minLength: 1;
79
+ };
80
+ readonly uniqueItems: true;
81
+ };
82
+ readonly exclude: {
83
+ readonly default: readonly [];
84
+ readonly type: "array";
85
+ readonly items: {
86
+ readonly type: "string";
87
+ readonly minLength: 1;
88
+ };
89
+ readonly uniqueItems: true;
90
+ };
91
+ readonly excludeGenerated: {
92
+ readonly type: "boolean";
93
+ readonly default: true;
94
+ };
95
+ readonly frameworkOverlay: {
96
+ readonly type: "string";
97
+ readonly minLength: 1;
98
+ };
99
+ readonly layers: {
100
+ readonly type: "array";
101
+ readonly default: readonly [];
102
+ readonly items: {
103
+ readonly $ref: "#/$defs/layer";
104
+ };
105
+ };
106
+ readonly rules: {
107
+ readonly type: "array";
108
+ readonly default: ArkConfigRule[];
109
+ readonly items: {
110
+ readonly $ref: "#/$defs/rule";
111
+ };
112
+ };
113
+ readonly cyclePolicy: {
114
+ readonly type: "string";
115
+ readonly enum: readonly ["strict", "soft", "framework-soft", "off"];
116
+ readonly default: "strict";
117
+ };
118
+ readonly dynamicImportAllowlist: {
119
+ readonly default: readonly [];
120
+ readonly type: "array";
121
+ readonly items: {
122
+ readonly type: "string";
123
+ readonly minLength: 1;
124
+ };
125
+ readonly uniqueItems: true;
126
+ };
127
+ readonly safety: {
128
+ readonly $ref: "#/$defs/safety";
129
+ readonly default: {
130
+ readonly maxTsSuppressions: 0;
131
+ readonly maxAnyCasts: 0;
132
+ readonly allowInMemory: false;
133
+ readonly allowDisabledPeerIsolation: false;
134
+ };
135
+ };
136
+ };
137
+ readonly $defs: {
138
+ readonly layer: {
139
+ readonly type: "object";
140
+ readonly additionalProperties: false;
141
+ readonly required: readonly ["name", "patterns"];
142
+ readonly properties: {
143
+ readonly name: {
144
+ readonly type: "string";
145
+ readonly minLength: 1;
146
+ };
147
+ readonly patterns: {
148
+ readonly minItems: 1;
149
+ readonly type: "array";
150
+ readonly items: {
151
+ readonly type: "string";
152
+ readonly minLength: 1;
153
+ };
154
+ readonly uniqueItems: true;
155
+ };
156
+ readonly exclude: {
157
+ readonly type: "array";
158
+ readonly items: {
159
+ readonly type: "string";
160
+ readonly minLength: 1;
161
+ };
162
+ readonly uniqueItems: true;
163
+ };
164
+ readonly intentPrefixes: {
165
+ readonly type: "array";
166
+ readonly items: {
167
+ readonly type: "string";
168
+ readonly minLength: 1;
169
+ };
170
+ readonly uniqueItems: true;
171
+ };
172
+ readonly description: {
173
+ readonly type: "string";
174
+ readonly minLength: 1;
175
+ };
176
+ readonly forbiddenGlobals: {
177
+ readonly type: "array";
178
+ readonly items: {
179
+ readonly type: "string";
180
+ readonly minLength: 1;
181
+ };
182
+ readonly uniqueItems: true;
183
+ };
184
+ readonly mayImportInfrastructure: {
185
+ readonly type: "boolean";
186
+ };
187
+ readonly optional: {
188
+ readonly type: "boolean";
189
+ };
190
+ };
191
+ };
192
+ readonly rule: {
193
+ readonly type: "object";
194
+ readonly additionalProperties: false;
195
+ readonly required: readonly ["from", "to", "allowed"];
196
+ readonly properties: {
197
+ readonly from: {
198
+ readonly type: "string";
199
+ readonly minLength: 1;
200
+ };
201
+ readonly to: {
202
+ readonly type: "string";
203
+ readonly minLength: 1;
204
+ };
205
+ readonly allowed: {
206
+ readonly type: "boolean";
207
+ };
208
+ readonly message: {
209
+ readonly type: "string";
210
+ readonly minLength: 1;
211
+ };
212
+ readonly peerIsolation: {
213
+ readonly type: "boolean";
214
+ };
215
+ readonly sliceFolders: {
216
+ readonly minItems: 1;
217
+ readonly type: "array";
218
+ readonly items: {
219
+ readonly type: "string";
220
+ readonly minLength: 1;
221
+ };
222
+ readonly uniqueItems: true;
223
+ };
224
+ };
225
+ };
226
+ readonly safety: {
227
+ readonly type: "object";
228
+ readonly additionalProperties: false;
229
+ readonly properties: {
230
+ readonly maxTsSuppressions: {
231
+ readonly type: "integer";
232
+ readonly minimum: 0;
233
+ readonly default: 0;
234
+ };
235
+ readonly maxAnyCasts: {
236
+ readonly type: "integer";
237
+ readonly minimum: 0;
238
+ readonly default: 0;
239
+ };
240
+ readonly allowInMemory: {
241
+ readonly type: "boolean";
242
+ readonly default: false;
243
+ };
244
+ readonly allowDisabledPeerIsolation: {
245
+ readonly type: "boolean";
246
+ readonly default: false;
247
+ };
248
+ };
249
+ };
250
+ };
251
+ };
252
+ type ArkConfigLoadResult = {
253
+ config: ArkConfig;
254
+ migratedFrom: 'unversioned' | null;
255
+ };
256
+ declare function loadArkConfigContract(input: unknown, source?: string): ArkConfigLoadResult;
257
+ declare function parseArkConfigJson(json: string, source?: string): ArkConfigLoadResult;
258
+
259
+ export { type ArkConfig as A, type ArkConfigRule as a, type ArkConfigLayer as b, type ArkConfigLoadResult as c, ARK_CONFIG_SCHEMA as d, ARK_CONFIG_SCHEMA_VERSION as e, loadArkConfigContract as l, parseArkConfigJson as p };
@@ -521,6 +521,63 @@ function parseArkConfigJson(json, source = "ark.config.json") {
521
521
  return loadArkConfigContract(input, source);
522
522
  }
523
523
 
524
+ // src/domain/adapterContract.ts
525
+ function text(value) {
526
+ return typeof value === "string" && value.length > 0 ? value : void 0;
527
+ }
528
+ function positiveInteger(value, fallback) {
529
+ return Number.isInteger(value) && Number(value) > 0 ? Number(value) : fallback;
530
+ }
531
+ function toAdapterDiagnostic(violation, fallbackSeverity = "error") {
532
+ const ruleId = text(violation.ruleId) ?? text(violation.code) ?? "ARK_UNKNOWN";
533
+ const severity = violation.severity === "warning" ? "warning" : fallbackSeverity;
534
+ const evidence = {
535
+ ...text(violation.target) ? { target: text(violation.target) } : {},
536
+ ...text(violation.fromLayer) ? { fromLayer: text(violation.fromLayer) } : {},
537
+ ...text(violation.toLayer) ? { toLayer: text(violation.toLayer) } : {},
538
+ ...typeof violation.typeOnly === "boolean" ? { typeOnly: violation.typeOnly } : {}
539
+ };
540
+ return {
541
+ ruleId,
542
+ severity,
543
+ message: text(violation.message) ?? ruleId,
544
+ location: {
545
+ file: text(violation.file) ?? "<unknown>",
546
+ line: positiveInteger(violation.line, 1),
547
+ column: positiveInteger(violation.column, 1)
548
+ },
549
+ evidence
550
+ };
551
+ }
552
+
553
+ // src/domain/sourcePolicy.ts
554
+ var SOURCE_POLICY_MESSAGES = {
555
+ RAW_EVENT_PUBLISH: "Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts and tooling.",
556
+ PUBLISH_MISSING_SOURCE: "Strict Ark publish calls must include metadata.source."
557
+ };
558
+ function looksLikeArkIntent(value) {
559
+ return /^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(
560
+ value
561
+ );
562
+ }
563
+ function classifyPublishFacts(facts) {
564
+ if (!facts.publishCall) return [];
565
+ const findings = [];
566
+ if (facts.rawIntentName !== void 0 && looksLikeArkIntent(facts.rawIntentName) || facts.objectHasIntent) {
567
+ findings.push({
568
+ ruleId: "RAW_EVENT_PUBLISH",
569
+ message: SOURCE_POLICY_MESSAGES.RAW_EVENT_PUBLISH
570
+ });
571
+ }
572
+ if (facts.arkPublishCandidate && !facts.hasSource) {
573
+ findings.push({
574
+ ruleId: "PUBLISH_MISSING_SOURCE",
575
+ message: SOURCE_POLICY_MESSAGES.PUBLISH_MISSING_SOURCE
576
+ });
577
+ }
578
+ return findings;
579
+ }
580
+
524
581
  // src/eslint/index.ts
525
582
  function lintedFilename(context) {
526
583
  if (typeof context.physicalFilename === "string" && context.physicalFilename.length > 0) {
@@ -538,6 +595,15 @@ function lintedFilename(context) {
538
595
  }
539
596
  return "";
540
597
  }
598
+ function reportAdapterDiagnostic(context, node, messageId, violation, data) {
599
+ const diagnostic = toAdapterDiagnostic({
600
+ ...violation,
601
+ line: violation.line ?? node.loc?.start?.line,
602
+ column: violation.column ?? (typeof node.loc?.start?.column === "number" ? node.loc.start.column + 1 : void 0)
603
+ });
604
+ context.report({ node, messageId, ...data ? { data } : {}, diagnostic });
605
+ return diagnostic;
606
+ }
541
607
  function findConfigPath(startFile) {
542
608
  if (!startFile || startFile === "<input>" || startFile.startsWith("stdin")) return null;
543
609
  let dir = import_node_path.default.dirname(import_node_path.default.resolve(startFile));
@@ -639,38 +705,14 @@ function objectHasMetadataSource(node) {
639
705
  const metadata = objectProperty(node, "metadata")?.value;
640
706
  return objectHasProperty(metadata, "source");
641
707
  }
642
- function looksLikeIntent(value) {
643
- return /^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(
644
- value
645
- );
646
- }
647
708
  function isPublishCall(node) {
648
709
  return calleePropertyName(node) === "publish";
649
710
  }
650
- function isDomainFileHeuristic(filename) {
651
- const normalized = filename.split("\\").join("/").toLowerCase();
652
- return normalized.includes("/domain/") || normalized.endsWith("/domain.ts");
653
- }
654
- function isInfraImportHeuristic(specifier) {
655
- const normalized = specifier.toLowerCase();
656
- return [
657
- "adapter",
658
- "adapters",
659
- "infrastructure",
660
- "persistence",
661
- "repository",
662
- "repositories",
663
- "integration",
664
- "database",
665
- "db"
666
- ].some((token) => normalized.includes(token));
667
- }
668
- var DEFAULT_FORBIDDEN_GLOBALS = ["fetch", "process", "Date.now", "Math.random"];
669
711
  var noDomainInfraImports = {
670
712
  meta: {
671
713
  type: "problem",
672
714
  docs: {
673
- description: "Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check). Falls back to domain\u2192infra path heuristics when no config is found."
715
+ description: "Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check)."
674
716
  },
675
717
  messages: {
676
718
  forbiddenImport: "Architecture: {{fromLayer}} must not import {{toLayer}} (ark.config.json). Specifier: {{specifier}}",
@@ -702,17 +744,24 @@ var noDomainInfraImports = {
702
744
  toPath: relTarget,
703
745
  layers: config.layers
704
746
  })) {
705
- context.report({
747
+ reportAdapterDiagnostic(
748
+ context,
706
749
  node,
707
- messageId: "forbiddenImport",
708
- data: { fromLayer, toLayer, specifier: source }
709
- });
750
+ "forbiddenImport",
751
+ {
752
+ ruleId: "LAYER_IMPORT_VIOLATION",
753
+ file: relFile,
754
+ fromLayer,
755
+ toLayer,
756
+ target: relTarget,
757
+ ...node.importKind === "type" ? { typeOnly: true } : {},
758
+ message: `${fromLayer} must not import ${toLayer}.`
759
+ },
760
+ { fromLayer, toLayer, specifier: source }
761
+ );
710
762
  }
711
763
  return;
712
764
  }
713
- if (isDomainFileHeuristic(filename) && isInfraImportHeuristic(source)) {
714
- context.report({ node, messageId: "forbiddenImportHeuristic" });
715
- }
716
765
  };
717
766
  return {
718
767
  ImportDeclaration: check,
@@ -735,11 +784,21 @@ var noRawEventPublish = {
735
784
  create(context) {
736
785
  return {
737
786
  CallExpression(node) {
738
- if (!isPublishCall(node)) return;
739
787
  const firstArg = node.arguments?.[0];
740
788
  const firstValue = stringValue(firstArg);
741
- if (firstValue && looksLikeIntent(firstValue) || objectHasProperty(firstArg, "intent")) {
742
- context.report({ node, messageId: "rawPublish" });
789
+ const findings = classifyPublishFacts({
790
+ publishCall: isPublishCall(node),
791
+ rawIntentName: firstValue,
792
+ objectHasIntent: objectHasProperty(firstArg, "intent"),
793
+ arkPublishCandidate: false,
794
+ hasSource: true
795
+ });
796
+ if (findings.some((finding) => finding.ruleId === "RAW_EVENT_PUBLISH")) {
797
+ const finding = findings.find((item) => item.ruleId === "RAW_EVENT_PUBLISH");
798
+ reportAdapterDiagnostic(context, node, "rawPublish", {
799
+ ...finding,
800
+ file: lintedFilename(context)
801
+ });
743
802
  }
744
803
  }
745
804
  };
@@ -759,13 +818,22 @@ var requirePublishSource = {
759
818
  create(context) {
760
819
  return {
761
820
  CallExpression(node) {
762
- if (!isPublishCall(node)) return;
763
821
  const firstArg = node.arguments?.[0];
764
822
  const metadataArg = node.arguments?.[2];
765
- if (objectHasMetadataSource(firstArg) || objectHasProperty(metadataArg, "source")) {
766
- return;
823
+ const findings = classifyPublishFacts({
824
+ publishCall: isPublishCall(node),
825
+ rawIntentName: stringValue(firstArg),
826
+ objectHasIntent: objectHasProperty(firstArg, "intent"),
827
+ arkPublishCandidate: true,
828
+ hasSource: objectHasMetadataSource(firstArg) || objectHasProperty(metadataArg, "source")
829
+ });
830
+ const finding = findings.find((item) => item.ruleId === "PUBLISH_MISSING_SOURCE");
831
+ if (finding) {
832
+ reportAdapterDiagnostic(context, node, "missingSource", {
833
+ ...finding,
834
+ file: lintedFilename(context)
835
+ });
767
836
  }
768
- context.report({ node, messageId: "missingSource" });
769
837
  }
770
838
  };
771
839
  }
@@ -774,7 +842,7 @@ var noForbiddenGlobals = {
774
842
  meta: {
775
843
  type: "problem",
776
844
  docs: {
777
- description: "Disallow ambient globals from the layer\u2019s forbiddenGlobals in ark.config.json (same purity surface as arkgate-check). Option `globals` overrides. Without config, defaults apply only on domain-like paths."
845
+ description: "Disallow ambient globals from the layer\u2019s forbiddenGlobals in ark.config.json (same purity surface as ark-check). Option `globals` explicitly overrides."
778
846
  },
779
847
  messages: {
780
848
  forbiddenGlobal: 'Ambient global "{{name}}" is forbidden in {{layer}} (ark.config.json); inject the capability through a port instead.',
@@ -812,18 +880,28 @@ var noForbiddenGlobals = {
812
880
  } else {
813
881
  globals = null;
814
882
  }
815
- } else if (isDomainFileHeuristic(filename)) {
816
- globals = new Set(DEFAULT_FORBIDDEN_GLOBALS);
817
883
  }
818
884
  if (!globals) {
819
885
  return {};
820
886
  }
821
887
  const scopeAware = typeof sourceCodeFor(context)?.getScope === "function";
822
- const report = (node, name) => context.report({
823
- node,
824
- messageId: config ? "forbiddenGlobal" : "forbiddenGlobalDefault",
825
- data: { name, layer: layerName }
826
- });
888
+ const report = (node, name) => {
889
+ const absFile = import_node_path.default.isAbsolute(filename) ? filename : import_node_path.default.resolve(filename);
890
+ const reportFile = root ? import_node_path.default.relative(root, absFile).split(import_node_path.default.sep).join("/") : filename;
891
+ reportAdapterDiagnostic(
892
+ context,
893
+ node,
894
+ config ? "forbiddenGlobal" : "forbiddenGlobalDefault",
895
+ {
896
+ ruleId: "FORBIDDEN_GLOBAL",
897
+ file: reportFile,
898
+ fromLayer: layerName,
899
+ target: name,
900
+ message: `${layerName} must not use the ambient global "${name}".`
901
+ },
902
+ { name, layer: layerName }
903
+ );
904
+ };
827
905
  return {
828
906
  MemberExpression(node) {
829
907
  if (node.parent?.type === "MemberExpression" && node.parent.object === node) return;
@@ -897,4 +975,3 @@ var eslint_default = plugin;
897
975
  requirePublishSource,
898
976
  resolveRelativeImport
899
977
  });
900
- //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- import { A as ArkConfig } from '../configContract-iBLxx5Tz.cjs';
1
+ import { A as ArkConfig } from '../configContract-BxSIwVRo.cjs';
2
2
 
3
3
  /**
4
4
  * Pure layer-glob matching for ark.config.json.
@@ -103,6 +103,12 @@ type AstNode = {
103
103
  parent?: AstNode;
104
104
  init?: AstNode;
105
105
  computed?: boolean;
106
+ loc?: {
107
+ start?: {
108
+ line?: number;
109
+ column?: number;
110
+ };
111
+ };
106
112
  };
107
113
  type ArkRule = {
108
114
  meta: {
@@ -1,4 +1,4 @@
1
- import { A as ArkConfig } from '../configContract-iBLxx5Tz.js';
1
+ import { A as ArkConfig } from '../configContract-BxSIwVRo.js';
2
2
 
3
3
  /**
4
4
  * Pure layer-glob matching for ark.config.json.
@@ -103,6 +103,12 @@ type AstNode = {
103
103
  parent?: AstNode;
104
104
  init?: AstNode;
105
105
  computed?: boolean;
106
+ loc?: {
107
+ start?: {
108
+ line?: number;
109
+ column?: number;
110
+ };
111
+ };
106
112
  };
107
113
  type ArkRule = {
108
114
  meta: {