arkgate 4.4.0 → 4.5.5
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.
- package/CHANGELOG.md +71 -2
- package/README.md +7 -4
- package/bin/ark-check-runtime.mjs +38 -13
- package/bin/ark-layer-match.mjs +25 -12
- package/bin/lib/adapter-contract.mjs +5 -5
- package/bin/lib/analysis-engine.mjs +5 -5
- package/bin/lib/ci-and-commands.mjs +5 -0
- package/bin/lib/deep-module-coach.mjs +177 -0
- package/bin/lib/deepening-coach.mjs +177 -0
- package/bin/lib/doctor-plan.mjs +14 -0
- package/bin/lib/html-report-advisories.mjs +33 -0
- package/bin/lib/html-report-depth.mjs +9 -0
- package/bin/lib/html-report.mjs +8 -1
- package/bin/lib/improvement-compass-map.mjs +507 -0
- package/bin/lib/improvement-compass-types.mjs +85 -0
- package/bin/lib/improvement-compass.mjs +10 -561
- package/bin/lib/managed-upgrade-honesty.mjs +201 -0
- package/bin/lib/managed-upgrade.mjs +54 -4
- package/bin/lib/remediation.mjs +5 -5
- package/bin/lib/status-command.mjs +127 -2
- package/bin/lib/status-manifest.mjs +163 -14
- package/bin/lib/upgrade-whats-new.mjs +110 -0
- package/dist/eslint/index.cjs +2 -2
- package/dist/eslint/index.js +2 -2
- package/dist/index.cjs +28 -28
- package/dist/index.d.ts +126 -21
- package/dist/index.js +28 -28
- package/docs/README.md +5 -5
- package/docs/agent-guide.md +50 -8
- package/docs/brownfield-adoption.md +12 -0
- package/docs/develop.md +3 -1
- package/docs/package-surface.md +8 -6
- package/docs/product-voice.md +25 -1
- package/docs/use.md +33 -0
- package/package.json +1 -1
- package/schemas/ark.status-manifest.schema.json +28 -1
- package/server.json +2 -2
- package/templates/agent-skills/README.md +2 -2
- package/templates/agent-skills/ark-adopt/SKILL.md +13 -0
- package/templates/agent-skills/ark-explore/SKILL.md +21 -0
- package/templates/agent-skills/ark-fix/SKILL.md +7 -0
- package/templates/agent-skills/ark-loop/SKILL.md +7 -0
- package/templates/agent-skills/ark-place/SKILL.md +7 -0
- package/templates/agent-skills/ark-think/SKILL.md +7 -0
- package/templates/agent-skills/ark-upgrade/SKILL.md +14 -0
- package/templates/skills/ark-adopt.md +13 -0
- package/templates/skills/ark-explore.md +21 -0
- package/templates/skills/ark-fix.md +7 -0
- package/templates/skills/ark-loop.md +7 -0
- package/templates/skills/ark-place.md +7 -0
- package/templates/skills/ark-think.md +7 -0
- package/templates/skills/ark-upgrade.md +14 -0
|
@@ -10,6 +10,25 @@
|
|
|
10
10
|
|
|
11
11
|
export const ARK_STATUS_MANIFEST_SCHEMA_VERSION = '1.0';
|
|
12
12
|
export const ARK_STATUS_MANIFEST_SCHEMA_URL = 'https://unpkg.com/arkgate@4/schemas/ark.status-manifest.schema.json';
|
|
13
|
+
/**
|
|
14
|
+
* Honesty mode for status improvementCompass (DF02).
|
|
15
|
+
* - full: residual projected from doctor-equivalent facts (residual ⊆ doctor)
|
|
16
|
+
* - subset: incomplete facts; residual may omit doctor residual; never invent green
|
|
17
|
+
* - unavailable: no usable facts; empty residual + reason (never silent ok)
|
|
18
|
+
*/
|
|
19
|
+
export const STATUS_COMPASS_MODES = ['full', 'subset', 'unavailable'];
|
|
20
|
+
/** Provenance for status compass residual (same-tree intent). */
|
|
21
|
+
export const STATUS_COMPASS_FACTS_SOURCES = [
|
|
22
|
+
'doctor-facts',
|
|
23
|
+
'report-snapshot',
|
|
24
|
+
'none',
|
|
25
|
+
];
|
|
26
|
+
/** Stable reason codes when mode is not full. */
|
|
27
|
+
export const STATUS_COMPASS_REASON_CODES = {
|
|
28
|
+
FACTS_UNAVAILABLE: 'FACTS_UNAVAILABLE',
|
|
29
|
+
FACTS_PARTIAL: 'FACTS_PARTIAL',
|
|
30
|
+
NO_SESSION_SNAPSHOT: 'NO_SESSION_SNAPSHOT',
|
|
31
|
+
};
|
|
13
32
|
const PROJECT_ID_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
14
33
|
/**
|
|
15
34
|
* Evaluate project binding for status without filesystem.
|
|
@@ -294,23 +313,148 @@ export function buildStatusManifest(facts) {
|
|
|
294
313
|
status.improvementCompass = compass;
|
|
295
314
|
return status;
|
|
296
315
|
}
|
|
297
|
-
|
|
316
|
+
const STATUS_COMPASS_MODE_SET = new Set(STATUS_COMPASS_MODES);
|
|
317
|
+
const STATUS_COMPASS_SOURCE_SET = new Set(STATUS_COMPASS_FACTS_SOURCES);
|
|
318
|
+
/**
|
|
319
|
+
* Project a thin status improvementCompass with explicit honesty mode (DF02).
|
|
320
|
+
*
|
|
321
|
+
* Rules:
|
|
322
|
+
* - always notAScore: true
|
|
323
|
+
* - mode full | subset | unavailable (invalid mode → unavailable)
|
|
324
|
+
* - unavailable: topResidual forced empty (never invent residual or silent green)
|
|
325
|
+
* - full/subset: residual ids from input only (never fabricate ok lenses)
|
|
326
|
+
* - never carries valid / goal.met / score fields
|
|
327
|
+
*/
|
|
328
|
+
export function projectStatusImprovementCompass(input) {
|
|
329
|
+
const mode = STATUS_COMPASS_MODE_SET.has(input.mode)
|
|
330
|
+
? input.mode
|
|
331
|
+
: 'unavailable';
|
|
332
|
+
const factsSource = input.factsSource != null && STATUS_COMPASS_SOURCE_SET.has(input.factsSource)
|
|
333
|
+
? input.factsSource
|
|
334
|
+
: mode === 'unavailable'
|
|
335
|
+
? 'none'
|
|
336
|
+
: undefined;
|
|
337
|
+
const contractHash = typeof input.contractHash === 'string' && input.contractHash.length > 0
|
|
338
|
+
? input.contractHash
|
|
339
|
+
: undefined;
|
|
340
|
+
if (mode === 'unavailable') {
|
|
341
|
+
const out = {
|
|
342
|
+
schemaVersion: '1.0',
|
|
343
|
+
notAScore: true,
|
|
344
|
+
mode: 'unavailable',
|
|
345
|
+
topResidual: [],
|
|
346
|
+
reasonCode: typeof input.reasonCode === 'string' && input.reasonCode.length > 0
|
|
347
|
+
? input.reasonCode
|
|
348
|
+
: STATUS_COMPASS_REASON_CODES.FACTS_UNAVAILABLE,
|
|
349
|
+
reason: typeof input.reason === 'string' && input.reason.length > 0
|
|
350
|
+
? input.reason
|
|
351
|
+
: 'Improvement compass facts are unavailable — run ark-check --doctor for residual lenses. Status never invents green.',
|
|
352
|
+
factsSource: factsSource ?? 'none',
|
|
353
|
+
};
|
|
354
|
+
if (contractHash)
|
|
355
|
+
out.contractHash = contractHash;
|
|
356
|
+
return out;
|
|
357
|
+
}
|
|
358
|
+
const topResidual = Array.isArray(input.topResidual)
|
|
359
|
+
? input.topResidual
|
|
360
|
+
.filter((id) => typeof id === 'string' && id.length > 0)
|
|
361
|
+
.slice(0, 15)
|
|
362
|
+
: [];
|
|
363
|
+
const out = {
|
|
364
|
+
schemaVersion: '1.0',
|
|
365
|
+
notAScore: true,
|
|
366
|
+
mode,
|
|
367
|
+
topResidual,
|
|
368
|
+
};
|
|
369
|
+
if (mode === 'subset') {
|
|
370
|
+
out.reasonCode =
|
|
371
|
+
typeof input.reasonCode === 'string' && input.reasonCode.length > 0
|
|
372
|
+
? input.reasonCode
|
|
373
|
+
: STATUS_COMPASS_REASON_CODES.FACTS_PARTIAL;
|
|
374
|
+
out.reason =
|
|
375
|
+
typeof input.reason === 'string' && input.reason.length > 0
|
|
376
|
+
? input.reason
|
|
377
|
+
: 'Status compass is a subset of doctor residual — incomplete session facts; run doctor for full.';
|
|
378
|
+
}
|
|
379
|
+
else if (typeof input.reasonCode === 'string' && input.reasonCode.length > 0) {
|
|
380
|
+
out.reasonCode = input.reasonCode;
|
|
381
|
+
}
|
|
382
|
+
if (typeof input.reason === 'string' && input.reason.length > 0 && mode === 'full') {
|
|
383
|
+
out.reason = input.reason;
|
|
384
|
+
}
|
|
385
|
+
if (factsSource)
|
|
386
|
+
out.factsSource = factsSource;
|
|
387
|
+
if (contractHash)
|
|
388
|
+
out.contractHash = contractHash;
|
|
389
|
+
return out;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Unavailable compass when Tooling has no doctor/report residual facts.
|
|
393
|
+
* Empty residual + mode label — never a green / ok claim.
|
|
394
|
+
*/
|
|
395
|
+
export function unavailableStatusImprovementCompass(input = {}) {
|
|
396
|
+
return projectStatusImprovementCompass({
|
|
397
|
+
mode: 'unavailable',
|
|
398
|
+
topResidual: [],
|
|
399
|
+
reasonCode: input.reasonCode ?? STATUS_COMPASS_REASON_CODES.NO_SESSION_SNAPSHOT,
|
|
400
|
+
reason: input.reason ??
|
|
401
|
+
'No session compass facts yet — run ark-check --doctor or --report for residual lenses. Status never invents green.',
|
|
402
|
+
factsSource: 'none',
|
|
403
|
+
contractHash: input.contractHash,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Normalize an incoming status compass slice (Tooling pass-through / snapshot).
|
|
408
|
+
* Rejects score-like shapes; coerces missing mode to subset (never silent full).
|
|
409
|
+
* Unavailable always clears residual.
|
|
410
|
+
*/
|
|
411
|
+
export function normalizeStatusImprovementCompass(value) {
|
|
298
412
|
if (value == null || typeof value !== 'object')
|
|
299
413
|
return null;
|
|
300
|
-
|
|
414
|
+
const record = value;
|
|
415
|
+
if (record.notAScore !== true)
|
|
301
416
|
return null;
|
|
302
|
-
if (
|
|
417
|
+
if (record.schemaVersion !== '1.0')
|
|
303
418
|
return null;
|
|
304
|
-
|
|
419
|
+
// Score-like fields never allowed on status compass.
|
|
420
|
+
if ('score' in record || 'valid' in record || 'goal' in record)
|
|
305
421
|
return null;
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
}
|
|
422
|
+
let mode;
|
|
423
|
+
if (typeof record.mode === 'string' && STATUS_COMPASS_MODE_SET.has(record.mode)) {
|
|
424
|
+
mode = record.mode;
|
|
425
|
+
}
|
|
426
|
+
else if (Array.isArray(record.topResidual)) {
|
|
427
|
+
// Legacy thin slice without mode → subset honesty (never silent full).
|
|
428
|
+
mode = 'subset';
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
mode = 'unavailable';
|
|
432
|
+
}
|
|
433
|
+
return projectStatusImprovementCompass({
|
|
434
|
+
mode,
|
|
435
|
+
topResidual: Array.isArray(record.topResidual)
|
|
436
|
+
? record.topResidual
|
|
437
|
+
: [],
|
|
438
|
+
reasonCode: typeof record.reasonCode === 'string' ? record.reasonCode : null,
|
|
439
|
+
reason: typeof record.reason === 'string' ? record.reason : null,
|
|
440
|
+
factsSource: typeof record.factsSource === 'string' ? record.factsSource : null,
|
|
441
|
+
contractHash: typeof record.contractHash === 'string' ? record.contractHash : null,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Residual-id subset check for status ⊆ doctor parity fixtures (DF02).
|
|
446
|
+
* Returns true when every status residual id appears in doctor residual ids.
|
|
447
|
+
*/
|
|
448
|
+
export function statusCompassResidualIsSubsetOfDoctor(statusResidual, doctorResidual) {
|
|
449
|
+
const status = Array.isArray(statusResidual) ? statusResidual : [];
|
|
450
|
+
const doctor = new Set(Array.isArray(doctorResidual) ? doctorResidual : []);
|
|
451
|
+
for (const id of status) {
|
|
452
|
+
if (typeof id !== 'string' || id.length === 0)
|
|
453
|
+
continue;
|
|
454
|
+
if (!doctor.has(id))
|
|
455
|
+
return false;
|
|
456
|
+
}
|
|
457
|
+
return true;
|
|
314
458
|
}
|
|
315
459
|
function numberOrNull(value) {
|
|
316
460
|
if (value == null)
|
|
@@ -414,17 +558,22 @@ export const ARK_STATUS_MANIFEST_SCHEMA = {
|
|
|
414
558
|
},
|
|
415
559
|
improvementCompass: {
|
|
416
560
|
type: 'object',
|
|
417
|
-
description: '
|
|
561
|
+
description: 'Thin improvement-compass residual ids with honesty mode (notAScore). full | subset | unavailable. Never a gate input; full lenses on doctor JSON. When full, residual ids ⊆ doctor residual for the same facts. unavailable never invents green residual.',
|
|
418
562
|
additionalProperties: false,
|
|
419
|
-
required: ['schemaVersion', 'notAScore', 'topResidual'],
|
|
563
|
+
required: ['schemaVersion', 'notAScore', 'mode', 'topResidual'],
|
|
420
564
|
properties: {
|
|
421
565
|
schemaVersion: { const: '1.0' },
|
|
422
566
|
notAScore: { const: true },
|
|
567
|
+
mode: { enum: ['full', 'subset', 'unavailable'] },
|
|
423
568
|
topResidual: {
|
|
424
569
|
type: 'array',
|
|
425
570
|
items: { type: 'string', minLength: 1 },
|
|
426
571
|
maxItems: 15,
|
|
427
572
|
},
|
|
573
|
+
reasonCode: { type: 'string', minLength: 1 },
|
|
574
|
+
reason: { type: 'string', minLength: 1 },
|
|
575
|
+
factsSource: { enum: ['doctor-facts', 'report-snapshot', 'none'] },
|
|
576
|
+
contractHash: { type: 'string', minLength: 1 },
|
|
428
577
|
},
|
|
429
578
|
},
|
|
430
579
|
},
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggested improvements / what’s new after `ark upgrade` (advisory).
|
|
3
|
+
*
|
|
4
|
+
* Product capability list so consumers know what to try or inspect after
|
|
5
|
+
* installing this package line. Always notAScore / never a gate input.
|
|
6
|
+
* Pure constants — no git, no LLM, no invented residual.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const UPGRADE_WHATS_NEW_SCHEMA_VERSION = '1.0';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Closed list of post-upgrade suggestions for this product line.
|
|
13
|
+
* Ids are stable for agents; titles/try/inspect are human-facing.
|
|
14
|
+
*
|
|
15
|
+
* @returns {{
|
|
16
|
+
* schemaVersion: typeof UPGRADE_WHATS_NEW_SCHEMA_VERSION,
|
|
17
|
+
* notAScore: true,
|
|
18
|
+
* neverGateInput: true,
|
|
19
|
+
* title: string,
|
|
20
|
+
* items: Array<{
|
|
21
|
+
* id: string,
|
|
22
|
+
* title: string,
|
|
23
|
+
* try: string,
|
|
24
|
+
* inspect: string,
|
|
25
|
+
* why: string,
|
|
26
|
+
* }>,
|
|
27
|
+
* }}
|
|
28
|
+
*/
|
|
29
|
+
export function buildUpgradeWhatsNewSuggestions() {
|
|
30
|
+
return {
|
|
31
|
+
schemaVersion: UPGRADE_WHATS_NEW_SCHEMA_VERSION,
|
|
32
|
+
notAScore: true,
|
|
33
|
+
neverGateInput: true,
|
|
34
|
+
title: 'Suggested improvements — try or inspect after this package',
|
|
35
|
+
items: [
|
|
36
|
+
{
|
|
37
|
+
id: 'deep-module-coach',
|
|
38
|
+
title: 'Deep-module coach (hot paths + deepening)',
|
|
39
|
+
try: 'npx arkgate-check --doctor',
|
|
40
|
+
inspect:
|
|
41
|
+
'doctor.deepModuleCoach (JSON) or HTML data-advisory="deepModuleCoach"',
|
|
42
|
+
why:
|
|
43
|
+
'See recent-churn hot paths and deepening candidates projected only from existing residual. Always notAScore; never invents paths; never flips the gate.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'improvement-compass',
|
|
47
|
+
title: 'Improvement compass (residual lenses)',
|
|
48
|
+
try: 'npx arkgate-check --doctor',
|
|
49
|
+
inspect: 'doctor.improvementCompass or HTML data-advisory="improvementCompass"',
|
|
50
|
+
why:
|
|
51
|
+
'Named residual architecture lenses (SoC, DIP, domain, …) from evidence you already have — not a score; never flips valid / strict-merge / goal.met.',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: 'session-status-honesty',
|
|
55
|
+
title: 'Session recipe + status honesty',
|
|
56
|
+
try: 'npx arkgate status --json',
|
|
57
|
+
inspect: 'status.improvementCompass.mode (full | subset | unavailable)',
|
|
58
|
+
why:
|
|
59
|
+
'Bind identity → status → act. Incomplete facts never invent green residual; when mode is not full, run doctor for the full residual map.',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'two-axis-done',
|
|
63
|
+
title: 'Two-axis done (Enforce green ≠ feature done)',
|
|
64
|
+
try: 'Read docs/agent-guide.md “Two-axis done” and your ticket/spec',
|
|
65
|
+
inspect: 'Architecture residual (doctor/compass) vs feature residual (your acceptance)',
|
|
66
|
+
why:
|
|
67
|
+
'Gate green only clears architecture residual. Feature/ticket acceptance stays outside the package — no package LLM verdict for “done.”',
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
id: 'upgrade-self-service',
|
|
71
|
+
title: 'Upgrade self-service honesty',
|
|
72
|
+
try: 'npx arkgate upgrade --json',
|
|
73
|
+
inspect: 'selfService (write-path labels + customized preserve)',
|
|
74
|
+
why:
|
|
75
|
+
'After managed upgrade, learn write-path hard|advisory|unavailable per host and whether customized content was preserved — without a maintainer ticket. Soft hosts never claim hard.',
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Human lines for upgrade preview/apply stdout.
|
|
83
|
+
* @param {ReturnType<typeof buildUpgradeWhatsNewSuggestions>} [whatsNew]
|
|
84
|
+
* @returns {string[]}
|
|
85
|
+
*/
|
|
86
|
+
export function formatUpgradeWhatsNewSuggestions(whatsNew) {
|
|
87
|
+
const payload = whatsNew && typeof whatsNew === 'object' ? whatsNew : buildUpgradeWhatsNewSuggestions();
|
|
88
|
+
const items = Array.isArray(payload.items) ? payload.items : [];
|
|
89
|
+
if (items.length === 0) return [];
|
|
90
|
+
const lines = [
|
|
91
|
+
payload.title || 'Suggested improvements — try or inspect after this package',
|
|
92
|
+
' (advisory only — not a score; never changes gate verdicts)',
|
|
93
|
+
];
|
|
94
|
+
for (const item of items) {
|
|
95
|
+
if (!item || typeof item !== 'object') continue;
|
|
96
|
+
const title = typeof item.title === 'string' ? item.title.trim() : '';
|
|
97
|
+
if (!title) continue;
|
|
98
|
+
lines.push(` • ${title}`);
|
|
99
|
+
if (typeof item.try === 'string' && item.try.trim()) {
|
|
100
|
+
lines.push(` try: ${item.try.trim()}`);
|
|
101
|
+
}
|
|
102
|
+
if (typeof item.inspect === 'string' && item.inspect.trim()) {
|
|
103
|
+
lines.push(` inspect: ${item.inspect.trim()}`);
|
|
104
|
+
}
|
|
105
|
+
if (typeof item.why === 'string' && item.why.trim()) {
|
|
106
|
+
lines.push(` why: ${item.why.trim()}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return lines;
|
|
110
|
+
}
|
package/dist/eslint/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var Oe=Object.create;var N=Object.defineProperty;var _e=Object.getOwnPropertyDescriptor;var Pe=Object.getOwnPropertyNames;var $e=Object.getPrototypeOf,ve=Object.prototype.hasOwnProperty;var Te=(e,t)=>{for(var n in t)N(e,n,{get:t[n],enumerable:!0})},Q=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Pe(t))!ve.call(e,s)&&s!==n&&N(e,s,{get:()=>t[s],enumerable:!(r=_e(t,s))||r.enumerable});return e};var ee=(e,t,n)=>(n=e!=null?Oe($e(e)):{},Q(t||!e||!e.__esModule?N(n,"default",{value:e,enumerable:!0}):n,e)),je=e=>Q(N({},"__esModule",{value:!0}),e);var
|
|
1
|
+
"use strict";var Oe=Object.create;var N=Object.defineProperty;var _e=Object.getOwnPropertyDescriptor;var Pe=Object.getOwnPropertyNames;var $e=Object.getPrototypeOf,ve=Object.prototype.hasOwnProperty;var Te=(e,t)=>{for(var n in t)N(e,n,{get:t[n],enumerable:!0})},Q=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of Pe(t))!ve.call(e,s)&&s!==n&&N(e,s,{get:()=>t[s],enumerable:!(r=_e(t,s))||r.enumerable});return e};var ee=(e,t,n)=>(n=e!=null?Oe($e(e)):{},Q(t||!e||!e.__esModule?N(n,"default",{value:e,enumerable:!0}):n,e)),je=e=>Q(N({},"__esModule",{value:!0}),e);var ut={};Te(ut,{default:()=>pt,findConfigPath:()=>T,globToRegExp:()=>E,isEdgeDenied:()=>F,layerForRelativePath:()=>R,loadArkConfig:()=>j,noDeniedCapabilities:()=>Ne,noDomainInfraImports:()=>we,noForbiddenGlobals:()=>Le,noRawEventPublish:()=>Ee,patternSpecificity:()=>M,plugin:()=>v,readTsconfigPathAliases:()=>be,requirePublishSource:()=>Ce,resolveImportSpecifier:()=>Se,resolveRelativeImport:()=>Ae});module.exports=je(ut);var k=ee(require("fs"),1),p=ee(require("path"),1);var te=new Map;function ne(e){return/[.*+?^${}()|[\]\\]/.test(e)?`\\${e}`:e}function O(e){let t="";for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"&&n+1<e.length){let s=e[n+1];if("*?{}[],".includes(s)||s==="\\"){t+="\\"+s,n+=1;continue}t+="/";continue}t+=r}return t}function De(e){let t=0;for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="\\"){n+=1;continue}if(r==="{")t+=1;else if(r==="}"&&(t-=1,t<0))return!1}return t===0}function E(e){let t=te.get(e);if(t)return t;let n=O(e),r=De(n),s="",i=0;for(let c=0;c<n.length;c+=1){let g=n[c];g==="\\"&&c+1<n.length?(s+=ne(n[c+1]),c+=1):g==="*"?n[c+1]==="*"?n[c+2]==="/"?(s+="(?:.*/)?",c+=2):(s+=".*",c+=1):s+="[^/]*":g==="?"?s+="[^/]":g==="{"&&r?(s+="(?:",i+=1):g==="}"&&r&&i>0?(s+=")",i-=1):g===","&&r&&i>0?s+="|":s+=ne(g)}let a=new RegExp(`^${s}$`);return te.set(e,a),a}function Me(e){return O(String(e)).split("/").filter(Boolean).filter(n=>n!=="**"&&n!=="*"&&!n.includes("*")&&!n.includes("?")&&!n.includes("{")&&!n.includes("["))}function M(e,t){let n=O(String(e)),r=Me(n),s=n.replace(/\*/g,"").length,i=r.length*1e4+s;if(t==null||t==="")return i;let a=String(t).split(/[/\\]/).filter(Boolean);if(r.length===0)return s;let c=0,g=-1;for(let f of r){let d=-1;for(let o=c;o<a.length;o+=1)if(a[o]===f){d=o;break}if(d<0)return i;g=d,c=d+1}return(g+1)*1e6+r.length*1e4+s}function R(e,t){let n=String(e).split(/[/\\]/).join("/"),r,s=-1;for(let i of t??[])if(!(i.exclude??[]).some(a=>E(a).test(n))){for(let a of i.patterns??[])if(E(a).test(n)){let c=M(a,n);c>s&&(s=c,r=i.name)}}return r}function re(e,t){if(!t?.length)return;let n=String(e).split(/[/\\]/).filter(Boolean),r=new Set(t.map(s=>String(s).toLowerCase()));for(let s=0;s<n.length-1;s+=1)if(r.has(n[s].toLowerCase()))return`${n[s].toLowerCase()}/${n[s+1].toLowerCase()}`}function Ve(e){let t=new Set;for(let n of e??[]){let s=O(String(n)).split("/").filter(Boolean);for(let i=0;i<s.length;i+=1){let a=s[i];if((a==="**"||a==="*")&&i>0){let c=s[i-1];c&&!c.includes("*")&&!c.includes("{")&&!c.includes("}")&&t.add(c)}}}return[...t]}function Fe(e,t,n){if(Array.isArray(e.sliceFolders)&&e.sliceFolders.length>0)return e.sliceFolders.filter(s=>typeof s=="string"&&s.length>0);let r=(n??[]).find(s=>s.name===t);return Ve(r?.patterns)}function Ke(e){return!e.fromPath||!e.toPath||e.folderCount<=0||!e.fromSlice||!e.toSlice?!0:e.fromSlice!==e.toSlice}function V(e,t,n,r){for(let s of e??[])if(!(s.from!==t||s.to!==n)&&s.allowed===!1){if(s.peerIsolation){let i=r?.fromPath,a=r?.toPath,c=Fe(s,t,r?.layers),g=i&&a?re(i,c):void 0,f=i&&a?re(a,c):void 0;if(Ke({fromPath:i,toPath:a,folderCount:c.length,fromSlice:g,toSlice:f}))return s;continue}if(t!==n)return s}}function F(e,t,n,r){return V(e,t,n,r)!==void 0}var He=["**/*.gen.ts","**/*.gen.tsx","**/*.generated.ts","**/*.generated.tsx"];function Ge(e){let t=Array.isArray(e?.exclude)?e.exclude.filter(r=>typeof r=="string"):[];return[...e?.excludeGenerated===!1?[]:He,...t]}function se(e,t){let n=String(e).split(/[/\\]/).join("/");return Ge(t).some(r=>E(r).test(n))}var oe=Object.freeze(["network","filesystem","clock","randomness","environment","process","persistence"]),Be=Object.freeze({fetch:"network",XMLHttpRequest:"network",Date:"clock","Date.now":"clock","Math.random":"randomness","process.env":"environment",process:"process"}),mt=Object.freeze(Object.keys(Be).sort()),K=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"}),Ue=Object.freeze({process:Object.freeze(["process","node:process"])});function ie(e){if(!e||e.startsWith(".")||e.startsWith("/"))return null;let t=K[e];if(t)return t;let n=e.indexOf("/");if(n<0)return null;let r=e.slice(0,n),s=K[r];if(s)return s;let i=e.indexOf("/",n+1);return i<0?null:K[e.slice(0,i)]??null}function H(e,t){for(let n of t)if(Ue[n]?.includes(e))return n;return null}function ae(e){if(e?.pure===!0)return[...oe].sort();let n=(e?.capabilities?.deny??[]).filter(r=>oe.includes(r));return[...new Set(n)].sort()}var G="https://unpkg.com/arkgate@2/schemas/ark.config.schema.json",le=["DomainModel","ApplicationOrchestration","PersistenceAdapters","IntegrationAdapters","WorkflowSagaEngine","BackgroundJobsScheduling","PresentationAdapters","ReportingReadModels","ExtensibilityMetadata","SecurityAuditObservability","Kernel"],qe=new Set(["PresentationAdapters->ApplicationOrchestration","ApplicationOrchestration->DomainModel","WorkflowSagaEngine->ApplicationOrchestration","WorkflowSagaEngine->DomainModel","BackgroundJobsScheduling->ApplicationOrchestration"]);function We(){let e=[];for(let t of le)for(let n of le)t===n||qe.has(`${t}->${n}`)||e.push({from:t,to:n,allowed:!1});return e}var de=We(),B=[{from:"unversioned",to:"1.0"},{from:"1.0",to:"1.1"}],I={type:"array",items:{type:"string",minLength:1},uniqueItems:!0},ce={$schema:"https://json-schema.org/draft/2020-12/schema",$id:G,title:"ArkGate architecture contract",description:"Versioned contract consumed identically by ArkGate CLI, MCP, and ESLint surfaces.",type:"object",additionalProperties:!1,required:["$schema","schemaVersion","include","layers","rules"],properties:{$schema:{type:"string",minLength:1,default:G,description:"Editor-facing URL or local path for this JSON Schema."},schemaVersion:{type:"string",const:"1.1",default:"1.1"},name:{type:"string",minLength:1},include:{...I,minItems:1,default:["src"]},exclude:{...I,default:[]},excludeGenerated:{type:"boolean",default:!0},frameworkOverlay:{type:"string",minLength:1},layers:{type:"array",default:[],items:{$ref:"#/$defs/layer"}},rules:{type:"array",default:de,items:{$ref:"#/$defs/rule"}},cyclePolicy:{type:"string",enum:["strict","soft","framework-soft","off"],default:"strict"},dynamicImportAllowlist:{...I,default:[]},safety:{$ref:"#/$defs/safety",default:{maxTsSuppressions:0,maxAnyCasts:0,allowInMemory:!1,allowDisabledPeerIsolation:!1}},arkRules:{type:"object",additionalProperties:{type:"string",minLength:1},default:{}}},$defs:{layer:{type:"object",additionalProperties:!1,required:["name","patterns"],properties:{name:{type:"string",minLength:1},patterns:{...I,minItems:1},exclude:I,intentPrefixes:I,description:{type:"string",minLength:1},forbiddenGlobals:I,capabilities:{type:"object",additionalProperties:!1,properties:{deny:{type:"array",uniqueItems:!0,items:{type:"string",enum:["network","filesystem","clock","randomness","environment","process","persistence"]}}}},pure:{type:"boolean"},mayImportInfrastructure:{type:"boolean"},optional:{type:"boolean"}}},rule:{type:"object",additionalProperties:!1,required:["from","to","allowed"],properties:{from:{type:"string",minLength:1},to:{type:"string",minLength:1},allowed:{type:"boolean"},message:{type:"string",minLength:1},peerIsolation:{type:"boolean"},sliceFolders:{...I,minItems:1}}},safety:{type:"object",additionalProperties:!1,properties:{maxTsSuppressions:{type:"integer",minimum:0,default:0},maxAnyCasts:{type:"integer",minimum:0,default:0},allowInMemory:{type:"boolean",default:!1},allowDisabledPeerIsolation:{type:"boolean",default:!1}}}}},S=class extends Error{issues;source;constructor(t,n){super(`Invalid ArkGate config (${t}):
|
|
2
2
|
${n.map(r=>`- ${r.path}: ${r.message}`).join(`
|
|
3
|
-
`)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function pe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function _(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function x(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function We(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function C(e,t,n,r,s){if(t.$ref){let i=We(t.$ref,r);if(!i){s.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}C(e,i,n,r,s);return}if(t.const!==void 0&&!Object.is(e,t.const)){s.push({path:n,message:`must equal ${JSON.stringify(t.const)}`});return}if(t.enum&&!t.enum.some(i=>Object.is(i,e))){s.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!pe(e)){s.push({path:n,message:`must be an object; received ${x(e)}`});return}let i=t.properties??{};for(let a of t.required??[])e[a]===void 0&&s.push({path:_(n,a),message:"is required"});if(t.additionalProperties===!1)for(let a of Object.keys(e))a in i||s.push({path:_(n,a),message:"unknown field"});else if(t.additionalProperties!==void 0&&t.additionalProperties!==!0&&typeof t.additionalProperties=="object"){let a=t.additionalProperties;for(let c of Object.keys(e))c in i||C(e[c],a,_(n,c),r,s)}for(let[a,c]of Object.entries(i))e[a]!==void 0&&C(e[a],c,_(n,a),r,s);return}if(t.type==="array"){if(!Array.isArray(e)){s.push({path:n,message:`must be an array; received ${x(e)}`});return}if(t.minItems!==void 0&&e.length<t.minItems&&s.push({path:n,message:`must contain at least ${t.minItems} item(s)`}),t.uniqueItems){let i=e.map(a=>JSON.stringify(a));new Set(i).size!==i.length&&s.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((i,a)=>C(i,t.items,`${n}[${a}]`,r,s));return}if(t.type==="string"){if(typeof e!="string"){s.push({path:n,message:`must be a string; received ${x(e)}`});return}t.minLength!==void 0&&e.length<t.minLength&&s.push({path:n,message:`must contain at least ${t.minLength} character(s)`});return}if(t.type==="boolean"){typeof e!="boolean"&&s.push({path:n,message:`must be a boolean; received ${x(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){s.push({path:n,message:`must be an integer; received ${x(e)}`});return}t.minimum!==void 0&&e<t.minimum&&s.push({path:n,message:`must be at least ${t.minimum}`})}}function Ye(e){return{...e,$schema:e.$schema===void 0?G:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.1":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?de.map(t=>({...t})):e.rules}}function Je(){let e=new Set(["1.1"]);for(let t of B)t.from!=="unversioned"&&e.add(t.from),e.add(t.to);return e}function ze(e,t="ark.config.json"){if(!pe(e))throw new S(t,[{path:"$",message:`must be an object; received ${x(e)}`}]);let n=Je(),r=e.schemaVersion===void 0?"unversioned":typeof e.schemaVersion=="string"?e.schemaVersion:null;if(r===null)throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.1`}]);if(r!=="unversioned"&&!n.has(r))throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);let s=r,i={...e},a=0;for(;s!=="1.1"&&a<B.length+1;){a+=1;let g=B.find(f=>f.from===s);if(!g)throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);s=g.to,i.schemaVersion=s}if(s!=="1.1")throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);let c=r==="unversioned"?"unversioned":r==="1.0"?"1.0":null;return{candidate:Ye(i),migratedFrom:c}}function Ze(e,t="ark.config.json"){let{candidate:n,migratedFrom:r}=ze(e,t),s=[];if(C(n,ce,"$",ce,s),s.length>0)throw new S(t,s);return{config:n,migratedFrom:r}}function ue(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(r){throw new S(t,[{path:"$",message:`invalid JSON: ${r instanceof Error?r.message:String(r)}`}])}return Ze(n,t)}var Xe="docs/diagnostics.md";function b(e){return typeof e=="string"&&e.length>0?e:void 0}function fe(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function Qe(e){let t=typeof e.ruleId=="string"?e.ruleId:typeof e.code=="string"?e.code:void 0,n=typeof e.file=="string"?e.file:void 0,r=typeof e.fromLayer=="string"?e.fromLayer:void 0,s=typeof e.toLayer=="string"?e.toLayer:void 0,i=typeof e.target=="string"?e.target:void 0;return[t,n,r??"",s??"",i??""].join("|")}function et(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return`fnv1a-${(t>>>0).toString(16).padStart(8,"0")}`}function tt(e){return`${Xe}#${e}`}function nt(e,t,n){if(e==="LAYER_IMPORT_VIOLATION")return t.typeOnly||n.targetTypeOnlyExports===!0||n.namedBindingsTypeOnly===!0?"Move the referenced type to a mutually allowed layer, use `import type`, then preflight again.":n.peerIsolation===!0?"Extract the shared dependency to a shared layer, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${b(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, then preflight again.";if(e==="RAW_EVENT_PUBLISH")return"Publish through a registered intent creator, then run Ark again.";if(e==="PUBLISH_MISSING_SOURCE")return"Add metadata.source to the publish call, then run Ark again.";if(e==="ARKRULE_STRUCTURE"||e==="ARKRULE_INVARIANT"||e==="INVARIANT_UNCOVERED"||e.startsWith("ARKRULE_")){let r=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${r}), then preflight again. Do not demote the rule without a hash-bound policy acknowledgement.`}return`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function ge(e,t="error",n){let r=b(e.ruleId)??b(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"||e.failsStrict===!1||e.typeOnly===!0&&e.peerIsolation!==!0?"warning":t,i={...b(e.target)?{target:b(e.target)}:{},...b(e.fromLayer)?{fromLayer:b(e.fromLayer)}:{},...b(e.toLayer)?{toLayer:b(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{},...typeof e.targetTypeOnlyExports=="boolean"?{targetTypeOnlyExports:e.targetTypeOnlyExports}:{},...typeof e.sourcePureTypeModule=="boolean"?{sourcePureTypeModule:e.sourcePureTypeModule}:{},...typeof e.namedBindingsTypeOnly=="boolean"?{namedBindingsTypeOnly:e.namedBindingsTypeOnly}:{},...typeof e.portProofEligible=="boolean"?{portProofEligible:e.portProofEligible}:{},...typeof e.peerIsolation=="boolean"?{peerIsolation:e.peerIsolation}:{},...b(e.capability)?{capability:b(e.capability)}:{},...b(e.edgeKind)?{edgeKind:b(e.edgeKind)}:{},...b(e.arkruleId)?{arkruleId:b(e.arkruleId)}:{},...b(e.arkruleSource)?{arkruleSource:b(e.arkruleSource)}:{}},a=n??Qe(e),c=et(a);return{ruleId:r,severity:s,message:b(e.message)??r,location:{file:b(e.file)??"<unknown>",line:fe(e.line,1),column:fe(e.column,1)},evidence:i,nextAction:b(e.nextAction)??nt(r,i,e),findingRef:c,targetKey:a,docsCodePath:tt(r)}}var me={RAW_EVENT_PUBLISH:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts and tooling.",PUBLISH_MISSING_SOURCE:"Strict Ark publish calls must include metadata.source."},ht=Object.freeze([{layer:"DomainModel",prefixes:["Domain."]},{layer:"ApplicationOrchestration",prefixes:["Application."]},{layer:"PersistenceAdapters",prefixes:["Adapter.Persistence.","Adapter.Repository."]},{layer:"IntegrationAdapters",prefixes:["Adapter.Integration.","Adapter.External."]},{layer:"WorkflowSagaEngine",prefixes:["Workflow."]},{layer:"BackgroundJobsScheduling",prefixes:["Job."]},{layer:"PresentationAdapters",prefixes:["Presentation.","Adapter.Presentation.","Adapter.Api."]},{layer:"ReportingReadModels",prefixes:["Reporting."]},{layer:"ExtensibilityMetadata",prefixes:["Metadata."]},{layer:"SecurityAuditObservability",prefixes:["Security.","Audit.","Observability."]},{layer:"Kernel",prefixes:["Kernel."]}]);function rt(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function U(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&rt(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:me.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:me.PUBLISH_MISSING_SOURCE}),t}function L(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,r,s){let i=ge({...r,line:r.line??t.loc?.start?.line,column:r.column??(typeof t.loc?.start?.column=="number"?t.loc.start.column+1:void 0)});return e.report({node:t,messageId:n,...s?{data:s}:{},diagnostic:i}),i}function T(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=p.default.dirname(p.default.resolve(e));for(;;){let n=p.default.join(t,"ark.config.json");if(k.default.existsSync(n))return n;let r=p.default.dirname(t);if(r===t)return null;t=r}}var ye=new Map;function j(e){if(!k.default.existsSync(e))return null;let t=k.default.readFileSync(e,"utf8"),n=ye.get(e);if(n?.source===t)return n.config;let r=ue(t,e).config;return ye.set(e,{source:t,config:r}),r}function W(e,t){return(e.include??[]).some(r=>{let s=String(r).replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/$/,"");return s==="."||t===s||t.startsWith(`${s}/`)})&&!se(t,e)}function be(e){let t=[e,`${e}.ts`,`${e}.tsx`,`${e}.mts`,`${e}.cts`,`${e}.js`,`${e}.jsx`,p.default.join(e,"index.ts"),p.default.join(e,"index.tsx"),p.default.join(e,"index.js")];for(let n of t)try{if(k.default.existsSync(n)&&k.default.statSync(n).isFile())return n}catch{}return null}function he(e){let t=p.default.resolve(e),n=null;for(;;){let f=p.default.join(t,"tsconfig.json");if(k.default.existsSync(f)){n=f;break}let d=p.default.dirname(t);if(d===t)break;t=d}if(!n)return{baseUrl:e,aliases:[]};let r=f=>{try{let d=k.default.readFileSync(f,"utf8");return d=d.replace(/\/\*[\s\S]*?\*\//g,"").replace(/(^|[^:])\/\/.*$/gm,"$1"),JSON.parse(d)}catch{return null}},s=(f,d)=>{if(d>4)return{};let o=r(f);if(!o)return{};let l=o.compilerOptions??{},u=l.baseUrl,m=l.paths,y=o.extends;if(typeof y=="string"&&!y.startsWith("@")){let h=p.default.resolve(p.default.dirname(f),y.endsWith(".json")?y:`${y}.json`);if(k.default.existsSync(h)){let A=s(h,d+1);u=u??A.baseUrl,m={...A.paths??{},...m??{}}}}return{baseUrl:u,paths:m}},i=s(n,0),a=p.default.dirname(n),c=p.default.resolve(a,i.baseUrl||"."),g=[];for(let[f,d]of Object.entries(i.paths||{})){if(!Array.isArray(d)||d.length===0)continue;let o=f.replace(/\*$/,"");o&&g.push({from:o,to:String(d[0]).replace(/\*$/,"")})}return g.sort((f,d)=>d.from.length-f.from.length),{baseUrl:c,aliases:g}}function Ae(e,t){if(!t.startsWith("."))return null;let n=p.default.resolve(p.default.dirname(e),t);return be(n)}function Se(e,t,n){if(!t)return null;if(t.startsWith("."))return Ae(e,t);let r=n||p.default.dirname(e),{baseUrl:s,aliases:i}=he(r),a=i.find(g=>t.startsWith(g.from));if(!a)return null;let c=p.default.resolve(s,`${a.to}${t.slice(a.from.length)}`);return be(c)}function D(e){return typeof e?.value=="string"?e.value:void 0}function Y(e){return e?.name??D(e)}function J(e){return e.sourceCode??e.getSourceCode?.()}function ke(e,t){let n=J(e)?.getScope?.(t);for(;n;){let r=n.references?.find(s=>s.identifier===t);if(r)return r;n=n.upper??void 0}}function P(e,t,n){let r=ke(e,t);if(r?.resolved)return(r.resolved.defs?.length??0)>0;let s=J(e)?.getScope?.(t);for(;s;){let i=s.set?.get(n);if(i)return(i.defs?.length??0)>0;s=s.upper??void 0}return!1}function st(e,t){let n=ke(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function Ie(e){if(e?.type==="Identifier"&&e.name)return{root:e,segments:[e.name]};if(!e||!(e.type==="MemberExpression"||!!(e.object&&e.property))||e.computed===!0)return;let n=Ie(e.object),r=Y(e.property);if(!(!n||!r))return{root:n.root,segments:[...n.segments,r]}}function ot(e){return Y(e.callee?.property)}function Re(e,t){return e?.properties?.find(n=>Y(n.key)===t)}function $(e,t){return Re(e,t)!==void 0}function it(e){let t=Re(e,"metadata")?.value;return $(t,"source")}function xe(e){return ot(e)==="publish"}function q(e){if(e.importKind==="type"||e.exportKind==="type")return!0;let t=e.specifiers??[];return t.length===0?!1:t.every(n=>n.type==="ImportSpecifier")?t.every(n=>n.importKind==="type"):t.every(n=>n.exportKind==="type")}function at(e){let t=e;for(;t?.parent;)t=t.parent;return t?.type==="Program"?t:void 0}function lt(e){let t=at(e)?.body;if(!t)return!1;let n=!1;for(let r of t){if(r.type==="ImportDeclaration"){if(!q(r))return!1;continue}if(!(r.type==="TSInterfaceDeclaration"||r.type==="TSTypeAliasDeclaration")){if(r.type==="ExportNamedDeclaration"){if(r.declaration){if(r.declaration.type!=="TSInterfaceDeclaration"&&r.declaration.type!=="TSTypeAliasDeclaration")return!1}else if(!q(r))return!1;n=!0;continue}return!1}}return n}var we={meta:{type:"problem",docs:{description:"Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check)."},messages:{forbiddenImport:"Architecture: {{fromLayer}} must not import {{toLayer}} (ark.config.json). Specifier: {{specifier}}",forbiddenImportHeuristic:"Domain code must not import infrastructure, adapters, repositories, or database modules."},schema:[]},create(e){let t=L(e),n=T(t),r=n?j(n):null,s=n?p.default.dirname(n):null,i=a=>{let c=D(a.source);if(c&&r&&s&&t){let g=p.default.isAbsolute(t)?t:p.default.resolve(t),f=p.default.relative(s,g).split(p.default.sep).join("/");if(!W(r,f))return;let d=R(f,r.layers);if(!d)return;let o=Se(g,c,s);if(!o)return;let l=p.default.relative(s,o).split(p.default.sep).join("/");if(l.startsWith(".."))return;let u=R(l,r.layers);if(!u)return;let m={fromPath:f,toPath:l,layers:r.layers},y=V(r.rules,d,u,m);if(y||F(r.rules,d,u,m)){let h=a.type?.startsWith("Export")?"export":"import",A=q(a),z=!!y?.peerIsolation,Z=A&&!z,X=y?.message??`${d} must not ${h} ${u}.`;w(e,a,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:f,fromLayer:d,toLayer:u,target:l,edgeKind:h,...z?{peerIsolation:!0}:{},...A?{typeOnly:!0}:{},...Z?{severity:"warning"}:{},...lt(a)?{sourcePureTypeModule:!0}:{},message:Z?`${X} (type-only \u2014 type placement debt; prefer SharedTypes / owning layer; not runtime coupling)`:X},{fromLayer:d,toLayer:u,specifier:c})}return}};return{ImportDeclaration:i,ExportNamedDeclaration:i,ExportAllDeclaration:i}}},Ee={meta:{type:"problem",docs:{description:"Require event bus publish calls to use registered intent creators instead of raw event objects or intent strings."},messages:{rawPublish:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],r=D(n),s=U({publishCall:xe(t),rawIntentName:r,objectHasIntent:$(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(s.some(i=>i.ruleId==="RAW_EVENT_PUBLISH")){let i=s.find(a=>a.ruleId==="RAW_EVENT_PUBLISH");w(e,t,"rawPublish",{...i,file:L(e)})}}}}},Ce={meta:{type:"problem",docs:{description:"Require event bus publish calls to include source metadata."},messages:{missingSource:"Strict Ark publish calls must include metadata.source."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],r=t.arguments?.[2],i=U({publishCall:xe(t),rawIntentName:D(n),objectHasIntent:$(n,"intent"),arkPublishCandidate:!0,hasSource:it(n)||$(r,"source")}).find(a=>a.ruleId==="PUBLISH_MISSING_SOURCE");i&&w(e,t,"missingSource",{...i,file:L(e)})}}}},Le={meta:{type:"problem",docs:{description:"Disallow ambient globals from the layer\u2019s forbiddenGlobals in ark.config.json (same purity surface as ark-check). Option `globals` is a standalone fallback when no project config applies."},messages:{forbiddenGlobal:'Ambient global "{{name}}" is forbidden in {{layer}} (ark.config.json); inject the capability through a port instead.',forbiddenGlobalDefault:'Ambient global "{{name}}" is forbidden here; inject the capability through a port instead.',forbiddenModule:'{{layer}} must not use module "{{specifier}}" because it is the import form of forbidden global "{{name}}".'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=L(e),n=e.options?.[0],r=T(t),s=r?j(r):null,i=r?p.default.dirname(r):null,a=null,c="this layer";if(s&&i&&t){let o=p.default.isAbsolute(t)?t:p.default.resolve(t),l=p.default.relative(i,o).split(p.default.sep).join("/");if(!W(s,l))return{};let u=s.layers?.find(m=>m.name===R(l,s.layers));u?.forbiddenGlobals?.length?(a=new Set(u.forbiddenGlobals),c=u.name):a=null}else n?.globals&&(a=new Set(n.globals));if(!a)return{};let g=typeof J(e)?.getScope=="function",f=(o,l)=>{let u=p.default.isAbsolute(t)?t:p.default.resolve(t),m=i?p.default.relative(i,u).split(p.default.sep).join("/"):t;w(e,o,s?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:m,fromLayer:c,target:l,message:`${c} must not use the ambient global "${l}".`},{name:l,layer:c})},d=(o,l,u,m)=>{if(u||typeof l!="string")return;let y=H(l,a);if(!y)return;let h=p.default.isAbsolute(t)?t:p.default.resolve(t),A=i?p.default.relative(i,h).split(p.default.sep).join("/"):t;w(e,o,"forbiddenModule",{ruleId:"FORBIDDEN_GLOBAL",file:A,fromLayer:c,target:l,edgeKind:m,message:`${c} must not use module "${l}" because it is the import form of forbidden global "${y}".`},{layer:c,name:y,specifier:l,importKind:m})};return{MemberExpression(o){if(o.parent?.type==="MemberExpression"&&o.parent.object===o)return;let l=Ie(o);if(!l||P(e,l.root,l.segments[0]))return;let u=l.segments[0]==="globalThis",m=u?l.segments.slice(1):l.segments,y;for(let h=m.length;h>=(u?1:2);h-=1){let A=m.slice(0,h).join(".");if(a.has(A)){y=A;break}}y?f(o,y):!g&&a.has(l.segments[0])&&f(o,l.segments[0])},CallExpression(o){let l=o;if(l.callee?.type==="Identifier"&&l.callee.name==="require"&&l.arguments?.[0]?.type==="Literal"&&!P(e,o,"require")&&d(o,l.arguments[0].value,!1,"require"),g)return;let u=l.callee?.type==="Identifier"?l.callee.name:void 0;u&&a.has(u)&&f(o,u)},ImportDeclaration(o){let l=o,u=(l.specifiers??[]).filter(y=>y.type==="ImportSpecifier"),m=u.length>0&&u.length===(l.specifiers??[]).length&&u.every(y=>y.importKind==="type");d(o,l.source?.value,l.importKind==="type"||m,"import")},ImportExpression(o){let l=o;l.source?.type==="Literal"&&d(o,l.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(o){let l=o;d(o,l.moduleReference?.expression?.value,l.importKind==="type"||l.isTypeOnly===!0,"require")},ExportNamedDeclaration(o){let l=o;if(!l.source)return;let u=l.specifiers??[],m=u.length>0&&u.every(y=>y.exportKind==="type");d(o,l.source.value,l.exportKind==="type"||m,"export")},ExportAllDeclaration(o){let l=o;d(o,l.source?.value,l.exportKind==="type","export")},NewExpression(o){if(g)return;let l=o.callee?.type==="Identifier"?o.callee.name:void 0;l&&a.has(l)&&f(o,l)},Identifier(o){!g||!o.name||!a.has(o.name)||!st(e,o)||P(e,o,o.name)||f(o,o.name)}}}},Ne={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=L(e),n=T(t),r=n?j(n):null,s=n?p.default.dirname(n):null;if(!r||!s||!t)return{};let i=p.default.isAbsolute(t)?t:p.default.resolve(t),a=p.default.relative(s,i).split(p.default.sep).join("/");if(!W(r,a))return{};let c=r.layers?.find(d=>d.name===R(a,r.layers));if(!c)return{};let g=new Set(ae(c));if(g.size===0)return{};let f=(d,o,l,u)=>{if(l||typeof o!="string"||H(o,c.forbiddenGlobals??[]))return;let m=ie(o);!m||!g.has(m)||w(e,d,"deniedCapability",{ruleId:"CAPABILITY_VIOLATION",file:a,fromLayer:c.name,target:o,capability:m,edgeKind:u,message:`${c.name} denies the ${m} capability; found import of "${o}".`},{layer:c.name,capability:m,specifier:o})};return{ImportDeclaration(d){let o=d,l=(o.specifiers??[]).filter(m=>m.type==="ImportSpecifier"),u=l.length>0&&l.length===(o.specifiers??[]).length&&l.every(m=>m.importKind==="type");f(d,o.source?.value,o.importKind==="type"||u,"import")},ImportExpression(d){let o=d;o.source?.type==="Literal"&&f(d,o.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(d){let o=d;f(d,o.moduleReference?.expression?.value,o.importKind==="type"||o.isTypeOnly===!0,"require")},ExportNamedDeclaration(d){let o=d;if(!o.source)return;let l=o.specifiers??[],u=l.length>0&&l.every(m=>m.exportKind==="type");f(d,o.source.value,o.exportKind==="type"||u,"export")},ExportAllDeclaration(d){let o=d;f(d,o.source?.value,o.exportKind==="type","export")},CallExpression(d){let o=d;o.callee?.type==="Identifier"&&o.callee.name==="require"&&o.arguments?.[0]?.type==="Literal"&&!P(e,d,"require")&&f(d,o.arguments[0].value,!1,"require")}}}},ct={"no-domain-infra-imports":we,"no-raw-event-publish":Ee,"require-publish-source":Ce,"no-forbidden-globals":Le,"no-denied-capabilities":Ne},v={rules:ct};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 dt=v;0&&(module.exports={findConfigPath,globToRegExp,isEdgeDenied,layerForRelativePath,loadArkConfig,noDeniedCapabilities,noDomainInfraImports,noForbiddenGlobals,noRawEventPublish,patternSpecificity,plugin,readTsconfigPathAliases,requirePublishSource,resolveImportSpecifier,resolveRelativeImport});
|
|
3
|
+
`)}`),this.name="ArkConfigValidationError",this.source=t,this.issues=n}};function pe(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function _(e,t){return/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(t)?`${e}.${t}`:`${e}[${JSON.stringify(t)}]`}function x(e){return e===null?"null":Array.isArray(e)?"array":typeof e}function Ye(e,t){let n="#/$defs/";if(e.startsWith(n))return t.$defs[e.slice(n.length)]}function C(e,t,n,r,s){if(t.$ref){let i=Ye(t.$ref,r);if(!i){s.push({path:n,message:`schema reference ${t.$ref} cannot be resolved`});return}C(e,i,n,r,s);return}if(t.const!==void 0&&!Object.is(e,t.const)){s.push({path:n,message:`must equal ${JSON.stringify(t.const)}`});return}if(t.enum&&!t.enum.some(i=>Object.is(i,e))){s.push({path:n,message:`must be one of ${t.enum.map(String).join(", ")}`});return}if(t.type==="object"){if(!pe(e)){s.push({path:n,message:`must be an object; received ${x(e)}`});return}let i=t.properties??{};for(let a of t.required??[])e[a]===void 0&&s.push({path:_(n,a),message:"is required"});if(t.additionalProperties===!1)for(let a of Object.keys(e))a in i||s.push({path:_(n,a),message:"unknown field"});else if(t.additionalProperties!==void 0&&t.additionalProperties!==!0&&typeof t.additionalProperties=="object"){let a=t.additionalProperties;for(let c of Object.keys(e))c in i||C(e[c],a,_(n,c),r,s)}for(let[a,c]of Object.entries(i))e[a]!==void 0&&C(e[a],c,_(n,a),r,s);return}if(t.type==="array"){if(!Array.isArray(e)){s.push({path:n,message:`must be an array; received ${x(e)}`});return}if(t.minItems!==void 0&&e.length<t.minItems&&s.push({path:n,message:`must contain at least ${t.minItems} item(s)`}),t.uniqueItems){let i=e.map(a=>JSON.stringify(a));new Set(i).size!==i.length&&s.push({path:n,message:"must not contain duplicate items"})}t.items&&e.forEach((i,a)=>C(i,t.items,`${n}[${a}]`,r,s));return}if(t.type==="string"){if(typeof e!="string"){s.push({path:n,message:`must be a string; received ${x(e)}`});return}t.minLength!==void 0&&e.length<t.minLength&&s.push({path:n,message:`must contain at least ${t.minLength} character(s)`});return}if(t.type==="boolean"){typeof e!="boolean"&&s.push({path:n,message:`must be a boolean; received ${x(e)}`});return}if(t.type==="integer"){if(!Number.isInteger(e)){s.push({path:n,message:`must be an integer; received ${x(e)}`});return}t.minimum!==void 0&&e<t.minimum&&s.push({path:n,message:`must be at least ${t.minimum}`})}}function Je(e){return{...e,$schema:e.$schema===void 0?G:e.$schema,schemaVersion:e.schemaVersion===void 0?"1.1":e.schemaVersion,include:e.include===void 0?["src"]:e.include,layers:e.layers===void 0?[]:e.layers,rules:e.rules===void 0?de.map(t=>({...t})):e.rules}}function ze(){let e=new Set(["1.1"]);for(let t of B)t.from!=="unversioned"&&e.add(t.from),e.add(t.to);return e}function Ze(e,t="ark.config.json"){if(!pe(e))throw new S(t,[{path:"$",message:`must be an object; received ${x(e)}`}]);let n=ze(),r=e.schemaVersion===void 0?"unversioned":typeof e.schemaVersion=="string"?e.schemaVersion:null;if(r===null)throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(e.schemaVersion)}; expected 1.1`}]);if(r!=="unversioned"&&!n.has(r))throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);let s=r,i={...e},a=0;for(;s!=="1.1"&&a<B.length+1;){a+=1;let g=B.find(f=>f.from===s);if(!g)throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(s)}; expected 1.1`}]);s=g.to,i.schemaVersion=s}if(s!=="1.1")throw new S(t,[{path:"$.schemaVersion",message:`unsupported version ${JSON.stringify(r)}; expected 1.1`}]);let c=r==="unversioned"?"unversioned":r==="1.0"?"1.0":null;return{candidate:Je(i),migratedFrom:c}}function Xe(e,t="ark.config.json"){let{candidate:n,migratedFrom:r}=Ze(e,t),s=[];if(C(n,ce,"$",ce,s),s.length>0)throw new S(t,s);return{config:n,migratedFrom:r}}function ue(e,t="ark.config.json"){let n;try{n=JSON.parse(e)}catch(r){throw new S(t,[{path:"$",message:`invalid JSON: ${r instanceof Error?r.message:String(r)}`}])}return Xe(n,t)}var Qe="docs/diagnostics.md";function h(e){return typeof e=="string"&&e.length>0?e:void 0}function fe(e,t){return Number.isInteger(e)&&Number(e)>0?Number(e):t}function et(e){let t=typeof e.ruleId=="string"?e.ruleId:typeof e.code=="string"?e.code:void 0,n=typeof e.file=="string"?e.file:void 0,r=typeof e.fromLayer=="string"?e.fromLayer:void 0,s=typeof e.toLayer=="string"?e.toLayer:void 0,i=typeof e.target=="string"?e.target:void 0;return[t,n,r??"",s??"",i??""].join("|")}function tt(e){let t=2166136261;for(let n=0;n<e.length;n+=1)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return`fnv1a-${(t>>>0).toString(16).padStart(8,"0")}`}function nt(e){return`${Qe}#${e}`}function rt(e,t,n){if(e==="LAYER_IMPORT_VIOLATION")return t.typeOnly||n.targetTypeOnlyExports===!0||n.namedBindingsTypeOnly===!0?"Move the referenced type to a mutually allowed layer, use `import type`, then preflight again.":n.peerIsolation===!0?"Extract the shared dependency to a shared layer, test at the public interface, then preflight again.":`Define a port in ${t.fromLayer??"the source layer"}, inject the ${t.toLayer??"outer-layer"} implementation, test at the public interface, then preflight again.`;if(e==="FORBIDDEN_GLOBAL")return`Inject ${t.target??"the capability"} through a port, test at the public interface, then preflight again.`;if(e==="CAPABILITY_VIOLATION")return`Define a ${h(n.capability)??"capability"} port in ${t.fromLayer??"the walled layer"}, bind the implementation outside it, test at the public interface, then preflight again.`;if(e==="CIRCULAR_DEPENDENCY")return"Extract the shared dependency into a third module, test at the public interface, then preflight again.";if(e==="RAW_EVENT_PUBLISH")return"Publish through a registered intent creator, then run Ark again.";if(e==="PUBLISH_MISSING_SOURCE")return"Add metadata.source to the publish call, then run Ark again.";if(e==="ARKRULE_STRUCTURE"||e==="ARKRULE_INVARIANT"||e==="INVARIANT_UNCOVERED"||e.startsWith("ARKRULE_")){let r=t.arkruleSource??"arkrules/<Layer>.json";return`Fix the structure or invariant for ${t.arkruleId??"the ArkRule"} (declared in ${r}), then preflight again. Do not demote the rule without a hash-bound policy acknowledgement.`}return`Resolve ${e} without weakening ark.config.json, then run Ark again.`}function ge(e,t="error",n){let r=h(e.ruleId)??h(e.code)??"ARK_UNKNOWN",s=e.severity==="warning"||e.failsStrict===!1||e.typeOnly===!0&&e.peerIsolation!==!0?"warning":t,i={...h(e.target)?{target:h(e.target)}:{},...h(e.fromLayer)?{fromLayer:h(e.fromLayer)}:{},...h(e.toLayer)?{toLayer:h(e.toLayer)}:{},...typeof e.typeOnly=="boolean"?{typeOnly:e.typeOnly}:{},...typeof e.targetTypeOnlyExports=="boolean"?{targetTypeOnlyExports:e.targetTypeOnlyExports}:{},...typeof e.sourcePureTypeModule=="boolean"?{sourcePureTypeModule:e.sourcePureTypeModule}:{},...typeof e.namedBindingsTypeOnly=="boolean"?{namedBindingsTypeOnly:e.namedBindingsTypeOnly}:{},...typeof e.portProofEligible=="boolean"?{portProofEligible:e.portProofEligible}:{},...typeof e.peerIsolation=="boolean"?{peerIsolation:e.peerIsolation}:{},...h(e.capability)?{capability:h(e.capability)}:{},...h(e.edgeKind)?{edgeKind:h(e.edgeKind)}:{},...h(e.arkruleId)?{arkruleId:h(e.arkruleId)}:{},...h(e.arkruleSource)?{arkruleSource:h(e.arkruleSource)}:{}},a=n??et(e),c=tt(a);return{ruleId:r,severity:s,message:h(e.message)??r,location:{file:h(e.file)??"<unknown>",line:fe(e.line,1),column:fe(e.column,1)},evidence:i,nextAction:h(e.nextAction)??rt(r,i,e),findingRef:c,targetKey:a,docsCodePath:nt(r)}}var me={RAW_EVENT_PUBLISH:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts and tooling.",PUBLISH_MISSING_SOURCE:"Strict Ark publish calls must include metadata.source."},At=Object.freeze([{layer:"DomainModel",prefixes:["Domain."]},{layer:"ApplicationOrchestration",prefixes:["Application."]},{layer:"PersistenceAdapters",prefixes:["Adapter.Persistence.","Adapter.Repository."]},{layer:"IntegrationAdapters",prefixes:["Adapter.Integration.","Adapter.External."]},{layer:"WorkflowSagaEngine",prefixes:["Workflow."]},{layer:"BackgroundJobsScheduling",prefixes:["Job."]},{layer:"PresentationAdapters",prefixes:["Presentation.","Adapter.Presentation.","Adapter.Api."]},{layer:"ReportingReadModels",prefixes:["Reporting."]},{layer:"ExtensibilityMetadata",prefixes:["Metadata."]},{layer:"SecurityAuditObservability",prefixes:["Security.","Audit.","Observability."]},{layer:"Kernel",prefixes:["Kernel."]}]);function st(e){return/^(Domain|Application|Adapter|Workflow|Job|Presentation|Reporting|Metadata|Security|Audit|Observability|Kernel)\.[A-Za-z0-9_.]+$/.test(e)}function U(e){if(!e.publishCall)return[];let t=[];return(e.rawIntentName!==void 0&&st(e.rawIntentName)||e.objectHasIntent)&&t.push({ruleId:"RAW_EVENT_PUBLISH",message:me.RAW_EVENT_PUBLISH}),e.arkPublishCandidate&&!e.hasSource&&t.push({ruleId:"PUBLISH_MISSING_SOURCE",message:me.PUBLISH_MISSING_SOURCE}),t}function L(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,r,s){let i=ge({...r,line:r.line??t.loc?.start?.line,column:r.column??(typeof t.loc?.start?.column=="number"?t.loc.start.column+1:void 0)});return e.report({node:t,messageId:n,...s?{data:s}:{},diagnostic:i}),i}function T(e){if(!e||e==="<input>"||e.startsWith("stdin"))return null;let t=p.default.dirname(p.default.resolve(e));for(;;){let n=p.default.join(t,"ark.config.json");if(k.default.existsSync(n))return n;let r=p.default.dirname(t);if(r===t)return null;t=r}}var ye=new Map;function j(e){if(!k.default.existsSync(e))return null;let t=k.default.readFileSync(e,"utf8"),n=ye.get(e);if(n?.source===t)return n.config;let r=ue(t,e).config;return ye.set(e,{source:t,config:r}),r}function W(e,t){return(e.include??[]).some(r=>{let s=String(r).replace(/\\/g,"/").replace(/^\.\//,"").replace(/\/$/,"");return s==="."||t===s||t.startsWith(`${s}/`)})&&!se(t,e)}function he(e){let t=[e,`${e}.ts`,`${e}.tsx`,`${e}.mts`,`${e}.cts`,`${e}.js`,`${e}.jsx`,p.default.join(e,"index.ts"),p.default.join(e,"index.tsx"),p.default.join(e,"index.js")];for(let n of t)try{if(k.default.existsSync(n)&&k.default.statSync(n).isFile())return n}catch{}return null}function be(e){let t=p.default.resolve(e),n=null;for(;;){let f=p.default.join(t,"tsconfig.json");if(k.default.existsSync(f)){n=f;break}let d=p.default.dirname(t);if(d===t)break;t=d}if(!n)return{baseUrl:e,aliases:[]};let r=f=>{try{let d=k.default.readFileSync(f,"utf8");return d=d.replace(/\/\*[\s\S]*?\*\//g,"").replace(/(^|[^:])\/\/.*$/gm,"$1"),JSON.parse(d)}catch{return null}},s=(f,d)=>{if(d>4)return{};let o=r(f);if(!o)return{};let l=o.compilerOptions??{},u=l.baseUrl,m=l.paths,y=o.extends;if(typeof y=="string"&&!y.startsWith("@")){let b=p.default.resolve(p.default.dirname(f),y.endsWith(".json")?y:`${y}.json`);if(k.default.existsSync(b)){let A=s(b,d+1);u=u??A.baseUrl,m={...A.paths??{},...m??{}}}}return{baseUrl:u,paths:m}},i=s(n,0),a=p.default.dirname(n),c=p.default.resolve(a,i.baseUrl||"."),g=[];for(let[f,d]of Object.entries(i.paths||{})){if(!Array.isArray(d)||d.length===0)continue;let o=f.replace(/\*$/,"");o&&g.push({from:o,to:String(d[0]).replace(/\*$/,"")})}return g.sort((f,d)=>d.from.length-f.from.length),{baseUrl:c,aliases:g}}function Ae(e,t){if(!t.startsWith("."))return null;let n=p.default.resolve(p.default.dirname(e),t);return he(n)}function Se(e,t,n){if(!t)return null;if(t.startsWith("."))return Ae(e,t);let r=n||p.default.dirname(e),{baseUrl:s,aliases:i}=be(r),a=i.find(g=>t.startsWith(g.from));if(!a)return null;let c=p.default.resolve(s,`${a.to}${t.slice(a.from.length)}`);return he(c)}function D(e){return typeof e?.value=="string"?e.value:void 0}function Y(e){return e?.name??D(e)}function J(e){return e.sourceCode??e.getSourceCode?.()}function ke(e,t){let n=J(e)?.getScope?.(t);for(;n;){let r=n.references?.find(s=>s.identifier===t);if(r)return r;n=n.upper??void 0}}function P(e,t,n){let r=ke(e,t);if(r?.resolved)return(r.resolved.defs?.length??0)>0;let s=J(e)?.getScope?.(t);for(;s;){let i=s.set?.get(n);if(i)return(i.defs?.length??0)>0;s=s.upper??void 0}return!1}function ot(e,t){let n=ke(e,t);return n?n.isValueReference!==!1:t.parent?.type==="VariableDeclarator"&&t.parent.init===t}function Ie(e){if(e?.type==="Identifier"&&e.name)return{root:e,segments:[e.name]};if(!e||!(e.type==="MemberExpression"||!!(e.object&&e.property))||e.computed===!0)return;let n=Ie(e.object),r=Y(e.property);if(!(!n||!r))return{root:n.root,segments:[...n.segments,r]}}function it(e){return Y(e.callee?.property)}function Re(e,t){return e?.properties?.find(n=>Y(n.key)===t)}function $(e,t){return Re(e,t)!==void 0}function at(e){let t=Re(e,"metadata")?.value;return $(t,"source")}function xe(e){return it(e)==="publish"}function q(e){if(e.importKind==="type"||e.exportKind==="type")return!0;let t=e.specifiers??[];return t.length===0?!1:t.every(n=>n.type==="ImportSpecifier")?t.every(n=>n.importKind==="type"):t.every(n=>n.exportKind==="type")}function lt(e){let t=e;for(;t?.parent;)t=t.parent;return t?.type==="Program"?t:void 0}function ct(e){let t=lt(e)?.body;if(!t)return!1;let n=!1;for(let r of t){if(r.type==="ImportDeclaration"){if(!q(r))return!1;continue}if(!(r.type==="TSInterfaceDeclaration"||r.type==="TSTypeAliasDeclaration")){if(r.type==="ExportNamedDeclaration"){if(r.declaration){if(r.declaration.type!=="TSInterfaceDeclaration"&&r.declaration.type!=="TSTypeAliasDeclaration")return!1}else if(!q(r))return!1;n=!0;continue}return!1}}return n}var we={meta:{type:"problem",docs:{description:"Disallow imports that violate ark.config.json layer rules (same contract as arkgate-check)."},messages:{forbiddenImport:"Architecture: {{fromLayer}} must not import {{toLayer}} (ark.config.json). Specifier: {{specifier}}",forbiddenImportHeuristic:"Domain code must not import infrastructure, adapters, repositories, or database modules."},schema:[]},create(e){let t=L(e),n=T(t),r=n?j(n):null,s=n?p.default.dirname(n):null,i=a=>{let c=D(a.source);if(c&&r&&s&&t){let g=p.default.isAbsolute(t)?t:p.default.resolve(t),f=p.default.relative(s,g).split(p.default.sep).join("/");if(!W(r,f))return;let d=R(f,r.layers);if(!d)return;let o=Se(g,c,s);if(!o)return;let l=p.default.relative(s,o).split(p.default.sep).join("/");if(l.startsWith(".."))return;let u=R(l,r.layers);if(!u)return;let m={fromPath:f,toPath:l,layers:r.layers},y=V(r.rules,d,u,m);if(y||F(r.rules,d,u,m)){let b=a.type?.startsWith("Export")?"export":"import",A=q(a),z=!!y?.peerIsolation,Z=A&&!z,X=y?.message??`${d} must not ${b} ${u}.`;w(e,a,"forbiddenImport",{ruleId:"LAYER_IMPORT_VIOLATION",file:f,fromLayer:d,toLayer:u,target:l,edgeKind:b,...z?{peerIsolation:!0}:{},...A?{typeOnly:!0}:{},...Z?{severity:"warning"}:{},...ct(a)?{sourcePureTypeModule:!0}:{},message:Z?`${X} (type-only \u2014 type placement debt; prefer SharedTypes / owning layer; not runtime coupling)`:X},{fromLayer:d,toLayer:u,specifier:c})}return}};return{ImportDeclaration:i,ExportNamedDeclaration:i,ExportAllDeclaration:i}}},Ee={meta:{type:"problem",docs:{description:"Require event bus publish calls to use registered intent creators instead of raw event objects or intent strings."},messages:{rawPublish:"Publish through a registered intent creator; raw event objects or intent strings bypass Ark contracts."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],r=D(n),s=U({publishCall:xe(t),rawIntentName:r,objectHasIntent:$(n,"intent"),arkPublishCandidate:!1,hasSource:!0});if(s.some(i=>i.ruleId==="RAW_EVENT_PUBLISH")){let i=s.find(a=>a.ruleId==="RAW_EVENT_PUBLISH");w(e,t,"rawPublish",{...i,file:L(e)})}}}}},Ce={meta:{type:"problem",docs:{description:"Require event bus publish calls to include source metadata."},messages:{missingSource:"Strict Ark publish calls must include metadata.source."},schema:[]},create(e){return{CallExpression(t){let n=t.arguments?.[0],r=t.arguments?.[2],i=U({publishCall:xe(t),rawIntentName:D(n),objectHasIntent:$(n,"intent"),arkPublishCandidate:!0,hasSource:at(n)||$(r,"source")}).find(a=>a.ruleId==="PUBLISH_MISSING_SOURCE");i&&w(e,t,"missingSource",{...i,file:L(e)})}}}},Le={meta:{type:"problem",docs:{description:"Disallow ambient globals from the layer\u2019s forbiddenGlobals in ark.config.json (same purity surface as ark-check). Option `globals` is a standalone fallback when no project config applies."},messages:{forbiddenGlobal:'Ambient global "{{name}}" is forbidden in {{layer}} (ark.config.json); inject the capability through a port instead.',forbiddenGlobalDefault:'Ambient global "{{name}}" is forbidden here; inject the capability through a port instead.',forbiddenModule:'{{layer}} must not use module "{{specifier}}" because it is the import form of forbidden global "{{name}}".'},schema:[{type:"object",properties:{globals:{type:"array",items:{type:"string"}}},additionalProperties:!1}]},create(e){let t=L(e),n=e.options?.[0],r=T(t),s=r?j(r):null,i=r?p.default.dirname(r):null,a=null,c="this layer";if(s&&i&&t){let o=p.default.isAbsolute(t)?t:p.default.resolve(t),l=p.default.relative(i,o).split(p.default.sep).join("/");if(!W(s,l))return{};let u=s.layers?.find(m=>m.name===R(l,s.layers));u?.forbiddenGlobals?.length?(a=new Set(u.forbiddenGlobals),c=u.name):a=null}else n?.globals&&(a=new Set(n.globals));if(!a)return{};let g=typeof J(e)?.getScope=="function",f=(o,l)=>{let u=p.default.isAbsolute(t)?t:p.default.resolve(t),m=i?p.default.relative(i,u).split(p.default.sep).join("/"):t;w(e,o,s?"forbiddenGlobal":"forbiddenGlobalDefault",{ruleId:"FORBIDDEN_GLOBAL",file:m,fromLayer:c,target:l,message:`${c} must not use the ambient global "${l}".`},{name:l,layer:c})},d=(o,l,u,m)=>{if(u||typeof l!="string")return;let y=H(l,a);if(!y)return;let b=p.default.isAbsolute(t)?t:p.default.resolve(t),A=i?p.default.relative(i,b).split(p.default.sep).join("/"):t;w(e,o,"forbiddenModule",{ruleId:"FORBIDDEN_GLOBAL",file:A,fromLayer:c,target:l,edgeKind:m,message:`${c} must not use module "${l}" because it is the import form of forbidden global "${y}".`},{layer:c,name:y,specifier:l,importKind:m})};return{MemberExpression(o){if(o.parent?.type==="MemberExpression"&&o.parent.object===o)return;let l=Ie(o);if(!l||P(e,l.root,l.segments[0]))return;let u=l.segments[0]==="globalThis",m=u?l.segments.slice(1):l.segments,y;for(let b=m.length;b>=(u?1:2);b-=1){let A=m.slice(0,b).join(".");if(a.has(A)){y=A;break}}y?f(o,y):!g&&a.has(l.segments[0])&&f(o,l.segments[0])},CallExpression(o){let l=o;if(l.callee?.type==="Identifier"&&l.callee.name==="require"&&l.arguments?.[0]?.type==="Literal"&&!P(e,o,"require")&&d(o,l.arguments[0].value,!1,"require"),g)return;let u=l.callee?.type==="Identifier"?l.callee.name:void 0;u&&a.has(u)&&f(o,u)},ImportDeclaration(o){let l=o,u=(l.specifiers??[]).filter(y=>y.type==="ImportSpecifier"),m=u.length>0&&u.length===(l.specifiers??[]).length&&u.every(y=>y.importKind==="type");d(o,l.source?.value,l.importKind==="type"||m,"import")},ImportExpression(o){let l=o;l.source?.type==="Literal"&&d(o,l.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(o){let l=o;d(o,l.moduleReference?.expression?.value,l.importKind==="type"||l.isTypeOnly===!0,"require")},ExportNamedDeclaration(o){let l=o;if(!l.source)return;let u=l.specifiers??[],m=u.length>0&&u.every(y=>y.exportKind==="type");d(o,l.source.value,l.exportKind==="type"||m,"export")},ExportAllDeclaration(o){let l=o;d(o,l.source?.value,l.exportKind==="type","export")},NewExpression(o){if(g)return;let l=o.callee?.type==="Identifier"?o.callee.name:void 0;l&&a.has(l)&&f(o,l)},Identifier(o){!g||!o.name||!a.has(o.name)||!ot(e,o)||P(e,o,o.name)||f(o,o.name)}}}},Ne={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=L(e),n=T(t),r=n?j(n):null,s=n?p.default.dirname(n):null;if(!r||!s||!t)return{};let i=p.default.isAbsolute(t)?t:p.default.resolve(t),a=p.default.relative(s,i).split(p.default.sep).join("/");if(!W(r,a))return{};let c=r.layers?.find(d=>d.name===R(a,r.layers));if(!c)return{};let g=new Set(ae(c));if(g.size===0)return{};let f=(d,o,l,u)=>{if(l||typeof o!="string"||H(o,c.forbiddenGlobals??[]))return;let m=ie(o);!m||!g.has(m)||w(e,d,"deniedCapability",{ruleId:"CAPABILITY_VIOLATION",file:a,fromLayer:c.name,target:o,capability:m,edgeKind:u,message:`${c.name} denies the ${m} capability; found import of "${o}".`},{layer:c.name,capability:m,specifier:o})};return{ImportDeclaration(d){let o=d,l=(o.specifiers??[]).filter(m=>m.type==="ImportSpecifier"),u=l.length>0&&l.length===(o.specifiers??[]).length&&l.every(m=>m.importKind==="type");f(d,o.source?.value,o.importKind==="type"||u,"import")},ImportExpression(d){let o=d;o.source?.type==="Literal"&&f(d,o.source.value,!1,"dynamic-import")},TSImportEqualsDeclaration(d){let o=d;f(d,o.moduleReference?.expression?.value,o.importKind==="type"||o.isTypeOnly===!0,"require")},ExportNamedDeclaration(d){let o=d;if(!o.source)return;let l=o.specifiers??[],u=l.length>0&&l.every(m=>m.exportKind==="type");f(d,o.source.value,o.exportKind==="type"||u,"export")},ExportAllDeclaration(d){let o=d;f(d,o.source?.value,o.exportKind==="type","export")},CallExpression(d){let o=d;o.callee?.type==="Identifier"&&o.callee.name==="require"&&o.arguments?.[0]?.type==="Literal"&&!P(e,d,"require")&&f(d,o.arguments[0].value,!1,"require")}}}},dt={"no-domain-infra-imports":we,"no-raw-event-publish":Ee,"require-publish-source":Ce,"no-forbidden-globals":Le,"no-denied-capabilities":Ne},v={rules:dt};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 pt=v;0&&(module.exports={findConfigPath,globToRegExp,isEdgeDenied,layerForRelativePath,loadArkConfig,noDeniedCapabilities,noDomainInfraImports,noForbiddenGlobals,noRawEventPublish,patternSpecificity,plugin,readTsconfigPathAliases,requirePublishSource,resolveImportSpecifier,resolveRelativeImport});
|