arkgate 4.8.9 → 4.8.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +111 -3
  2. package/README.md +5 -4
  3. package/bin/ark-check-runtime.mjs +8 -2
  4. package/bin/ark-check.mjs +3 -0
  5. package/bin/ark.mjs +18 -10
  6. package/bin/lib/adapter-contract-types.mjs +137 -0
  7. package/bin/lib/adapter-contract.mjs +4 -180
  8. package/bin/lib/adapter-finding-refs.mjs +63 -0
  9. package/bin/lib/agent-projection-formatters.mjs +151 -0
  10. package/bin/lib/agent-projection-merge.mjs +148 -0
  11. package/bin/lib/agent-projection-types.mjs +42 -0
  12. package/bin/lib/agent-projection.mjs +3 -309
  13. package/bin/lib/analysis-engine.mjs +6 -6
  14. package/bin/lib/architecture-scan.mjs +91 -4
  15. package/bin/lib/ark-order-facts.mjs +11 -4
  16. package/bin/lib/arkrule-file-hints.mjs +255 -20
  17. package/bin/lib/arkrules-sensors.mjs +364 -68
  18. package/bin/lib/baseline-key.mjs +45 -1
  19. package/bin/lib/config-contract.mjs +9 -3
  20. package/bin/lib/diagnostic-catalog.mjs +1 -0
  21. package/bin/lib/doctor-human.mjs +3 -3
  22. package/bin/lib/doctor-next-actions.mjs +3 -1
  23. package/bin/lib/field-install.mjs +23 -2
  24. package/bin/lib/first-run-help.mjs +69 -5
  25. package/bin/lib/project-root.mjs +70 -4
  26. package/bin/lib/resolved-candidate-facts.mjs +82 -1
  27. package/bin/lib/rules-inventory.mjs +7 -3
  28. package/bin/lib/upstream-report.mjs +330 -0
  29. package/bin/lib/violations.mjs +51 -15
  30. package/dist/{diagnosticCatalog-BrkOiwCk.d.ts → diagnosticCatalog-DiflIock.d.ts} +30 -41
  31. package/dist/eslint/index.cjs +4 -7
  32. package/dist/eslint/index.js +4 -7
  33. package/dist/index.cjs +28 -31
  34. package/dist/index.d.ts +52 -13
  35. package/dist/index.js +28 -31
  36. package/dist/nestjs/index.cjs +1 -1
  37. package/dist/nestjs/index.js +1 -1
  38. package/dist/runtime/index.cjs +11 -11
  39. package/dist/runtime/index.d.ts +1 -1
  40. package/dist/runtime/index.js +11 -11
  41. package/docs/README.md +3 -3
  42. package/docs/agent-guide.md +25 -1
  43. package/docs/ai-gates.md +8 -0
  44. package/docs/brownfield-adoption.md +30 -0
  45. package/docs/configuration.md +14 -1
  46. package/docs/diagnostics.md +10 -0
  47. package/docs/package-surface.md +5 -3
  48. package/docs/use.md +11 -0
  49. package/package.json +3 -2
  50. package/schemas/ark.config.schema.json +3 -2
  51. package/server.json +2 -2
  52. package/templates/agent-skills/ark-explore/SKILL.md +22 -1
  53. package/templates/skills/ark-explore.md +22 -1
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Upstream GitHub issue draft for ArkGate itself (`arkgate report` / `ark report`).
3
+ * Target is this package's package.json bugs.url (pedroknigge/arkgate), never the consumer repo.
4
+ */
5
+ import { spawnSync } from 'node:child_process';
6
+ import fs from 'node:fs';
7
+ import path from 'node:path';
8
+ import readline from 'node:readline/promises';
9
+
10
+ import { __packageRoot } from './gate-files.mjs';
11
+
12
+ export const UPSTREAM_OWNER_REPO = 'pedroknigge/arkgate';
13
+ export const SUBMIT_PROMPT = 'Type submit to send';
14
+
15
+ export function ownerRepoFromGithubUrl(url) {
16
+ if (typeof url !== 'string' || url.trim() === '') return null;
17
+ const match = url.trim().match(/github\.com[:/]+([^/]+)\/([^/#?\s]+)/i);
18
+ if (!match) return null;
19
+ const owner = match[1];
20
+ const repo = match[2].replace(/\.git$/i, '');
21
+ if (!owner || !repo) return null;
22
+ return `${owner}/${repo}`;
23
+ }
24
+
25
+ export function resolveUpstreamRepo(pkg) {
26
+ const fromBugs = ownerRepoFromGithubUrl(pkg?.bugs?.url);
27
+ if (fromBugs) return fromBugs;
28
+ const repository = pkg?.repository;
29
+ const repoUrl = typeof repository === 'string' ? repository : repository?.url;
30
+ const fromRepo = ownerRepoFromGithubUrl(repoUrl);
31
+ if (fromRepo) return fromRepo;
32
+ return UPSTREAM_OWNER_REPO;
33
+ }
34
+
35
+ export function posixSingleQuote(value) {
36
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
37
+ }
38
+
39
+ export function formatGhIssueCreateCommand({ repo, title, body }) {
40
+ return `gh issue create --repo ${posixSingleQuote(repo)} --title ${posixSingleQuote(title)} --body ${posixSingleQuote(body)}`;
41
+ }
42
+
43
+ export function reportUsage() {
44
+ return `arkgate report (alias ark report) — draft an upstream GitHub issue for ArkGate.
45
+
46
+ Target: pedroknigge/arkgate (this package's package.json bugs.url). Never the consumer repo.
47
+
48
+ Usage:
49
+ arkgate report [--root <project>] [--json] [--title <text>] [--finding <ref>]
50
+ arkgate report --submit --i-confirm-submit
51
+ arkgate report --submit # TTY: type submit to send
52
+
53
+ Default prints a draft (arkgate version + last-check snippet). Nothing is created.
54
+ Create only with --submit AND (--i-confirm-submit after the human said yes, or TTY
55
+ "${SUBMIT_PROMPT}"). --yes does not submit.
56
+
57
+ If gh is missing or not logged in: prints the draft and the exact
58
+ gh issue create --repo pedroknigge/arkgate command, then exits 2.
59
+ `;
60
+ }
61
+
62
+ export function lastCheckSnippet(latest) {
63
+ if (!latest || typeof latest !== 'object') return null;
64
+ const at =
65
+ typeof latest.generatedAt === 'string'
66
+ ? latest.generatedAt
67
+ : typeof latest.at === 'string'
68
+ ? latest.at
69
+ : null;
70
+ const active =
71
+ typeof latest.activeViolations === 'number'
72
+ ? latest.activeViolations
73
+ : typeof latest.violations?.active === 'number'
74
+ ? latest.violations.active
75
+ : null;
76
+ let verdict = null;
77
+ if (latest.ok === true && (active == null || active === 0)) verdict = 'pass';
78
+ else if (latest.ok === false || (typeof active === 'number' && active > 0)) verdict = 'fail';
79
+ else if (latest.completeness === 'partial' || latest.completeness === 'unavailable') {
80
+ verdict = 'incomplete';
81
+ } else if (latest.ok === true) verdict = 'pass';
82
+ if (at == null && verdict == null && active == null) return null;
83
+ return { at, verdict, activeViolations: active };
84
+ }
85
+
86
+ export function readLastCheckSnapshot(root) {
87
+ const latestPath = path.join(root, '.ark', 'reports', 'latest.json');
88
+ try {
89
+ return JSON.parse(fs.readFileSync(latestPath, 'utf8'));
90
+ } catch {
91
+ return null;
92
+ }
93
+ }
94
+
95
+ export function buildIssueDraft({ repo, arkgateVersion, lastCheck, finding, title }) {
96
+ const resolvedTitle =
97
+ typeof title === 'string' && title.trim()
98
+ ? title.trim()
99
+ : finding
100
+ ? `ArkGate finding ${finding}`
101
+ : 'ArkGate field report';
102
+ const lines = [`## ArkGate version`, String(arkgateVersion ?? 'unknown'), ''];
103
+ if (finding) {
104
+ lines.push('## Finding', String(finding), '');
105
+ }
106
+ if (lastCheck) {
107
+ lines.push('## Last check');
108
+ lines.push(`- at: ${lastCheck.at ?? 'none'}`);
109
+ lines.push(`- verdict: ${lastCheck.verdict ?? 'none'}`);
110
+ lines.push(`- activeViolations: ${lastCheck.activeViolations ?? 'unknown'}`);
111
+ lines.push('');
112
+ } else {
113
+ lines.push('## Last check', 'No last-check snapshot under .ark/reports/latest.json.', '');
114
+ }
115
+ lines.push(
116
+ '## Repro',
117
+ '```bash',
118
+ 'npx arkgate-check --doctor',
119
+ 'npx arkgate status --json',
120
+ '```',
121
+ '',
122
+ '## What happened',
123
+ '(ArkGate bug, false green, false red, missing doc, or improvable behavior in ArkGate itself — not leftover design in the consumer app.)',
124
+ '',
125
+ `Prepared with \`arkgate report\` against upstream ${repo}. Not the consumer repo.`
126
+ );
127
+ return { repo, title: resolvedTitle, body: lines.join('\n') };
128
+ }
129
+
130
+ export function defaultRunGh(argv, options = {}) {
131
+ const env = { ...(options.env ?? process.env) };
132
+ delete env.GH_REPO;
133
+ const result = spawnSync('gh', argv, {
134
+ encoding: 'utf8',
135
+ env,
136
+ stdio: ['ignore', 'pipe', 'pipe'],
137
+ });
138
+ if (result.error && (result.error.code === 'ENOENT' || result.error.code === 'EACCES')) {
139
+ return { missing: true, status: 127, stdout: '', stderr: result.error.message };
140
+ }
141
+ return {
142
+ missing: false,
143
+ status: result.status ?? 1,
144
+ stdout: result.stdout ?? '',
145
+ stderr: result.stderr ?? '',
146
+ };
147
+ }
148
+
149
+ function loadArkgatePackageJson(explicit) {
150
+ if (explicit && typeof explicit === 'object') return explicit;
151
+ try {
152
+ return JSON.parse(fs.readFileSync(path.join(__packageRoot, 'package.json'), 'utf8'));
153
+ } catch {
154
+ return { bugs: { url: `https://github.com/${UPSTREAM_OWNER_REPO}/issues` } };
155
+ }
156
+ }
157
+
158
+ function packageVersion(pkg, fallback) {
159
+ if (typeof fallback === 'string' && fallback.trim()) return fallback;
160
+ return typeof pkg?.version === 'string' ? pkg.version : 'unknown';
161
+ }
162
+
163
+ function renderHumanDraft(draft, arkgateVersion) {
164
+ return [
165
+ `Upstream: ${draft.repo}`,
166
+ '(never the consumer repo)',
167
+ '',
168
+ `ArkGate version: ${arkgateVersion}`,
169
+ '',
170
+ `Title: ${draft.title}`,
171
+ '',
172
+ draft.body,
173
+ ].join('\n');
174
+ }
175
+
176
+ async function defaultPromptSubmit(stdin, stdout) {
177
+ const rl = readline.createInterface({ input: stdin, output: stdout });
178
+ try {
179
+ return await rl.question(`${SUBMIT_PROMPT}\n`);
180
+ } finally {
181
+ rl.close();
182
+ }
183
+ }
184
+
185
+ export function parseReportArgv(argv = []) {
186
+ const out = {
187
+ submit: false,
188
+ iConfirmSubmit: false,
189
+ json: false,
190
+ yes: false,
191
+ help: false,
192
+ finding: undefined,
193
+ title: undefined,
194
+ root: undefined,
195
+ };
196
+ for (let i = 0; i < argv.length; i += 1) {
197
+ const arg = argv[i];
198
+ const next = () => {
199
+ const value = argv[i + 1];
200
+ if (value === undefined || String(value).startsWith('-')) {
201
+ throw new Error(`Missing value for ${arg}. Run arkgate report --help for usage.`);
202
+ }
203
+ i += 1;
204
+ return value;
205
+ };
206
+ if (arg === '--submit') out.submit = true;
207
+ else if (arg === '--i-confirm-submit') out.iConfirmSubmit = true;
208
+ else if (arg === '--json') out.json = true;
209
+ else if (arg === '--yes' || arg === '-y') out.yes = true;
210
+ else if (arg === '--help' || arg === '-h' || arg === 'help') out.help = true;
211
+ else if (arg === '--finding') out.finding = next();
212
+ else if (arg === '--title') out.title = next();
213
+ else if (arg === '--root') out.root = path.resolve(next());
214
+ else throw new Error(`Unknown argument: ${arg}. Run arkgate report --help for usage.`);
215
+ }
216
+ return out;
217
+ }
218
+
219
+ /**
220
+ * @param {object} options
221
+ * @returns {Promise<number>} process exit code
222
+ */
223
+ export async function runUpstreamReportCommand(options = {}) {
224
+ const fromArgv = Array.isArray(options.argv) ? parseReportArgv(options.argv) : {};
225
+ if (fromArgv.help) {
226
+ const writeOut = options.writeOut ?? ((text) => console.log(text));
227
+ writeOut(reportUsage());
228
+ return 0;
229
+ }
230
+ const root = path.resolve(fromArgv.root ?? options.root ?? process.cwd());
231
+ const json = Boolean(fromArgv.json || options.json);
232
+ const submit = Boolean(fromArgv.submit || options.submit);
233
+ const iConfirmSubmit = Boolean(fromArgv.iConfirmSubmit || options.iConfirmSubmit);
234
+ const yes = Boolean(fromArgv.yes || options.yes);
235
+ const finding = fromArgv.finding ?? options.finding;
236
+ const title = fromArgv.title ?? options.title;
237
+ const stdin = options.stdin ?? process.stdin;
238
+ const stdout = options.stdout ?? process.stdout;
239
+ const stdinIsTTY = options.stdinIsTTY ?? Boolean(stdin.isTTY);
240
+ const env = options.env ?? process.env;
241
+ const runGh = options.runGh ?? ((argv) => defaultRunGh(argv, { env }));
242
+ const writeOut = options.writeOut ?? ((text) => console.log(text));
243
+ const writeErr = options.writeErr ?? ((text) => console.error(text));
244
+
245
+ const pkg = loadArkgatePackageJson(options.arkgatePackageJson);
246
+ const repo = resolveUpstreamRepo(pkg);
247
+ const arkgateVersion = packageVersion(pkg, options.arkgateVersion);
248
+ const lastCheck = lastCheckSnippet(options.latestSnapshot ?? readLastCheckSnapshot(root));
249
+ const draft = buildIssueDraft({
250
+ repo,
251
+ arkgateVersion,
252
+ lastCheck,
253
+ finding,
254
+ title,
255
+ });
256
+ const ghCommand = formatGhIssueCreateCommand(draft);
257
+ const human = renderHumanDraft(draft, arkgateVersion);
258
+
259
+ const payload = {
260
+ schemaVersion: '1.0',
261
+ command: 'report',
262
+ created: false,
263
+ submitted: false,
264
+ repo: draft.repo,
265
+ title: draft.title,
266
+ body: draft.body,
267
+ arkgateVersion,
268
+ lastCheck,
269
+ ghCommand,
270
+ yesDoesNotSubmit: true,
271
+ };
272
+
273
+ const emit = (extraHuman, extraPayload) => {
274
+ if (json) writeOut(JSON.stringify({ ...payload, ...extraPayload }, null, 2));
275
+ else writeOut(extraHuman ? `${human}\n\n${extraHuman}` : human);
276
+ };
277
+
278
+ if (!submit) {
279
+ emit('Draft only. Nothing was created.\nAfter a human confirms: arkgate report --submit --i-confirm-submit\n--yes does not submit.');
280
+ return 0;
281
+ }
282
+
283
+ // --yes never confirms. Confirm is --i-confirm-submit or TTY "submit".
284
+ let confirmed = iConfirmSubmit;
285
+ if (!confirmed && stdinIsTTY) {
286
+ const typed = options.promptSubmit
287
+ ? await options.promptSubmit()
288
+ : await defaultPromptSubmit(stdin, stdout);
289
+ confirmed = /^\s*submit\s*$/i.test(String(typed ?? ''));
290
+ }
291
+
292
+ if (!confirmed) {
293
+ const refused =
294
+ 'Refused: --submit requires --i-confirm-submit or typing submit on a TTY. --yes does not submit.';
295
+ if (json) {
296
+ writeOut(JSON.stringify({ ...payload, error: 'submit-confirm-required', yesDoesNotSubmit: true }, null, 2));
297
+ } else {
298
+ writeOut(`${human}\n\nDraft only. ${refused}`);
299
+ }
300
+ writeErr(refused);
301
+ return 2;
302
+ }
303
+
304
+ const auth = runGh(['auth', 'status']);
305
+ const ghUnavailable = Boolean(auth?.missing) || auth?.status !== 0;
306
+ if (ghUnavailable) {
307
+ const missing =
308
+ 'Not filed: gh is missing or not logged in.\nExact command:\n' + ghCommand;
309
+ emit(missing, { created: false, submitted: false, error: 'gh-unavailable', ghCommand });
310
+ if (!json) writeErr('Not filed: gh is missing or not logged in.');
311
+ return 2;
312
+ }
313
+
314
+ const created = runGh(['issue', 'create', '--repo', repo, '--title', draft.title, '--body', draft.body]);
315
+ if (created?.missing || created?.status !== 0) {
316
+ const missing =
317
+ 'Not filed: gh is missing or not logged in.\nExact command:\n' + ghCommand;
318
+ emit(missing, { created: false, submitted: false, error: 'gh-unavailable', ghCommand });
319
+ if (!json) writeErr('Not filed: gh is missing or not logged in.');
320
+ return 2;
321
+ }
322
+
323
+ const url = String(created.stdout ?? '').trim();
324
+ emit(url ? `Created: ${url}` : 'Created.', {
325
+ created: true,
326
+ submitted: true,
327
+ url: url || null,
328
+ });
329
+ return 0;
330
+ }
@@ -16,8 +16,12 @@ import { baselineKeysFromDocument, baselineRecordsDocument } from './team-parlia
16
16
  import { toAdapterDiagnostic } from './adapter-contract.mjs';
17
17
  export { baselineKey, baselineOccurrenceKeys };
18
18
 
19
- const BASELINE_NOTE =
20
- 'Frozen ark-check violations (one record per edge). Only NEW keys vs the merge-base fail --against / --baseline. Regenerate with: ark-check --update-baseline';
19
+ /** Real regenerate flags: freeze-refuse needs --force; law PR needs --contract-session; stewards[] needs --author. */
20
+ export const REGENERATE_BASELINE_COMMAND =
21
+ 'ark-check --update-baseline --force --contract-session --author <steward>';
22
+
23
+ export const BASELINE_NOTE =
24
+ `Frozen ark-check violations (one record per edge). Only NEW keys vs the merge-base fail --against / --baseline. Regenerate with: ${REGENERATE_BASELINE_COMMAND} (--author when stewards[] is set)`;
21
25
 
22
26
  export function readBaseline(root, baselinePath) {
23
27
  const fullPath = path.isAbsolute(baselinePath) ? baselinePath : path.join(root, baselinePath);
@@ -76,13 +80,34 @@ export function printViolation(violation) {
76
80
  export const CONCENTRATION_MIN_VIOLATIONS = 10;
77
81
  export const CONCENTRATION_SHARE = 0.9;
78
82
 
83
+ /** Sensor id for STRUCTURE findings. Orchestration-only is code debt, not a missing toLayer. */
84
+ export function violationSensorId(violation) {
85
+ if (typeof violation?.sensor === 'string' && violation.sensor.trim()) return violation.sensor.trim();
86
+ if (typeof violation?.arkruleId === 'string' && violation.arkruleId.trim()) return violation.arkruleId.trim();
87
+ return undefined;
88
+ }
89
+
79
90
  export function violationEdge(violation) {
80
91
  if (violation.ruleId === 'CIRCULAR_DEPENDENCY') return 'circular dependency';
81
92
  if (violation.ruleId === 'FORBIDDEN_GLOBAL') return `${violation.fromLayer ?? '?'} → ambient global`;
82
93
  if (violation.fromLayer && violation.toLayer) return `${violation.fromLayer} → ${violation.toLayer}`;
94
+ const sensor = violationSensorId(violation);
95
+ if (sensor) return sensor;
83
96
  return violation.ruleId;
84
97
  }
85
98
 
99
+ /** Layer-import arrows can mean a contract bug. Structural-sensor blobs are code debt. */
100
+ export function isContractConcentrationEdge(edge) {
101
+ return typeof edge === 'string' && edge.includes(' → ');
102
+ }
103
+
104
+ export function isContractStyleViolation(violation) {
105
+ if (violationSensorId(violation)) return false;
106
+ if (violation.ruleId === 'CIRCULAR_DEPENDENCY') return true;
107
+ if (violation.ruleId === 'FORBIDDEN_GLOBAL') return true;
108
+ return Boolean(violation.fromLayer && violation.toLayer);
109
+ }
110
+
86
111
  // The directory the offending import lands in — the signal for "where does this edge go?".
87
112
  // For a LAYER_IMPORT_VIOLATION the target is a resolved file path; cluster by its dir prefix
88
113
  // so `kernel/internal/x` and `kernel/internal/y` collapse to one "into kernel/internal/".
@@ -100,27 +125,35 @@ export function summarizeViolations(violations) {
100
125
  for (const violation of violations) {
101
126
  if (violation.typeOnly) typeOnly += 1;
102
127
  const key = violationEdge(violation);
103
- const entry = byEdge.get(key) ?? { edge: key, count: 0, typeOnly: 0, targets: new Map() };
128
+ const entry = byEdge.get(key) ?? {
129
+ edge: key,
130
+ count: 0,
131
+ typeOnly: 0,
132
+ targets: new Map(),
133
+ contractStyle: true,
134
+ };
104
135
  entry.count += 1;
105
136
  if (violation.typeOnly) entry.typeOnly += 1;
137
+ if (!isContractStyleViolation(violation)) entry.contractStyle = false;
106
138
  const subtree = violationTargetSubtree(violation);
107
139
  if (subtree) entry.targets.set(subtree, (entry.targets.get(subtree) ?? 0) + 1);
108
140
  byEdge.set(key, entry);
109
141
  }
110
- const edges = [...byEdge.values()]
111
- .map((entry) => ({
112
- edge: entry.edge,
113
- count: entry.count,
114
- typeOnly: entry.typeOnly,
115
- topTargets: [...entry.targets.entries()]
116
- .sort((a, b) => b[1] - a[1])
117
- .slice(0, 4)
118
- .map(([dir, count]) => ({ dir, count })),
119
- }))
120
- .sort((a, b) => b.count - a.count);
142
+ const ranked = [...byEdge.values()].sort((a, b) => b.count - a.count);
143
+ const edges = ranked.map((entry) => ({
144
+ edge: entry.edge,
145
+ count: entry.count,
146
+ typeOnly: entry.typeOnly,
147
+ topTargets: [...entry.targets.entries()]
148
+ .sort((a, b) => b[1] - a[1])
149
+ .slice(0, 4)
150
+ .map(([dir, count]) => ({ dir, count })),
151
+ }));
121
152
  const total = violations.length;
122
153
  const dominant = edges[0];
123
154
  const dominantShare = total > 0 && dominant ? dominant.count / total : 0;
155
+ const contractConcentration =
156
+ Boolean(ranked[0]?.contractStyle) && isContractConcentrationEdge(ranked[0]?.edge);
124
157
  return {
125
158
  total,
126
159
  // Value edges are real runtime coupling; type-only edges (erased at compile time) are
@@ -130,7 +163,10 @@ export function summarizeViolations(violations) {
130
163
  edges,
131
164
  dominant: dominant ? dominant.edge : undefined,
132
165
  dominantShare,
133
- concentrated: total >= CONCENTRATION_MIN_VIOLATIONS && dominantShare >= CONCENTRATION_SHARE,
166
+ concentrated:
167
+ total >= CONCENTRATION_MIN_VIOLATIONS &&
168
+ dominantShare >= CONCENTRATION_SHARE &&
169
+ contractConcentration,
134
170
  };
135
171
  }
136
172
 
@@ -1,7 +1,7 @@
1
1
  import { e as CreateArchitectureProfileOptions, b as ArchitectureProfile, d as ArkCheckConfig, C as CreateArchitectureProfileFromArkConfigOptions, f as CreateElevenLayerArkConfigOptions, i as Policy, j as IntentCreator, I as IntentName } from './types-Djbs3KjE.js';
2
2
  import { A as ArkConfig, c as ArkConfigLoadResult } from './configTypes-j7so8B4O.js';
3
3
 
4
- /** Versioned public result contract shared by every ArkGate enforcement adapter. */
4
+ /** Versioned public result contract types + JSON Schema (adapter envelope). */
5
5
  /**
6
6
  * 1.5 adds stable finding refs on every factory-emitted diagnostic (ACS06):
7
7
  * `findingRef`, `targetKey` (baseline-compatible), `docsCodePath`.
@@ -144,42 +144,6 @@ type CurrentAdapterResult = (CurrentAdapterResultBase & Partial<ResolvedAdapterE
144
144
  completeness: 'unavailable';
145
145
  });
146
146
  type AdapterResult = LegacyAdapterResult | Version12AdapterResult | CurrentAdapterResult;
147
- /**
148
- * Baseline-compatible target key for a violation input.
149
- * Field order and empty-string fallbacks **must** match `baselineKey` in
150
- * `baselineKey.ts` — parity tests guard this so finding refs never orphan freezes.
151
- *
152
- * Note: uses raw ruleId/file strings (including empty) the same way baseline does;
153
- * display `ruleId` / `location.file` may still normalize to ARK_UNKNOWN / `<unknown>`.
154
- */
155
- declare function adapterFindingTargetKey(violation: AdapterViolationInput): string;
156
- /**
157
- * Occurrence-aware target keys for a violation list (parity with baselineOccurrenceKeys).
158
- * First occurrence keeps the historical base key; duplicates get `#N`.
159
- */
160
- declare function adapterFindingOccurrenceTargetKeys(violations: readonly AdapterViolationInput[]): string[];
161
- /** FNV-1a finding ref from a baseline-compatible targetKey (not a security hash). */
162
- declare function adapterFindingRefFromTargetKey(targetKey: string): string;
163
- /** Package-relative docs path with fragment for a public ruleId. */
164
- declare function adapterDocsCodePath(ruleId: string): string;
165
- declare function toAdapterDiagnostic(violation: AdapterViolationInput, fallbackSeverity?: AdapterSeverity,
166
- /**
167
- * Optional precomputed baseline-compatible targetKey (e.g. occurrence-aware from
168
- * `adapterFindingOccurrenceTargetKeys`). When omitted, uses the first-occurrence key.
169
- */
170
- targetKeyOverride?: string): AdapterDiagnostic;
171
- declare function createAdapterResult(input: {
172
- valid: boolean;
173
- completeness?: AnalysisCompleteness;
174
- mode?: AnalysisMode;
175
- policyHash?: unknown;
176
- resolverIdentity?: unknown;
177
- factsHash?: unknown;
178
- candidateTreeHash?: unknown;
179
- completenessReasons?: readonly AdapterCompletenessReason[];
180
- violations?: readonly AdapterViolationInput[];
181
- warnings?: readonly AdapterViolationInput[];
182
- }): CurrentAdapterResult;
183
147
  declare const ARK_ANALYSIS_RESULT_SCHEMA: {
184
148
  readonly $schema: "https://json-schema.org/draft/2020-12/schema";
185
149
  readonly $id: "https://unpkg.com/arkgate@3/schemas/ark.analysis-result.schema.json";
@@ -408,8 +372,27 @@ declare const ARK_ANALYSIS_RESULT_SCHEMA: {
408
372
  };
409
373
  };
410
374
 
375
+ declare function toAdapterDiagnostic(violation: AdapterViolationInput, fallbackSeverity?: AdapterSeverity,
376
+ /**
377
+ * Optional precomputed baseline-compatible targetKey (e.g. occurrence-aware from
378
+ * `adapterFindingOccurrenceTargetKeys`). When omitted, uses the first-occurrence key.
379
+ */
380
+ targetKeyOverride?: string): AdapterDiagnostic;
381
+ declare function createAdapterResult(input: {
382
+ valid: boolean;
383
+ completeness?: AnalysisCompleteness;
384
+ mode?: AnalysisMode;
385
+ policyHash?: unknown;
386
+ resolverIdentity?: unknown;
387
+ factsHash?: unknown;
388
+ candidateTreeHash?: unknown;
389
+ completenessReasons?: readonly AdapterCompletenessReason[];
390
+ violations?: readonly AdapterViolationInput[];
391
+ warnings?: readonly AdapterViolationInput[];
392
+ }): CurrentAdapterResult;
393
+
411
394
  /** ArkGate library version — single source of truth. */
412
- declare const version = "4.8.9";
395
+ declare const version = "4.8.11";
413
396
 
414
397
  /**
415
398
  * AI Code Gate (basic).
@@ -1924,12 +1907,18 @@ declare function evaluateArkRuleSensors(input: EvaluateArkRuleSensorsInput): Ark
1924
1907
  * Rules without appliesTo (whole-layer) never emit this signal.
1925
1908
  */
1926
1909
  declare function collectEmptyAppliesToFindings(arkRules: EffectiveArkRules, files: readonly string[]): ArkRuleSensorViolation[];
1910
+ /** Optional resolved-import facts when the collector already classified the specifier. */
1911
+ type ResolvedPersistenceImportFact = {
1912
+ specifier?: string;
1913
+ resolvedFile?: string;
1914
+ layer?: string | null;
1915
+ };
1927
1916
  /**
1928
1917
  * Pure Tooling/Domain heuristic for orchestration-only / thin-adapter fileHints.
1929
1918
  * Prefers false negatives over false positives (ADR 0013 discipline).
1930
1919
  * Returns null when neither flag is set (callers may omit the path).
1931
1920
  */
1932
- declare function deriveArkRuleFileHints(_file: string, content: string): {
1921
+ declare function deriveArkRuleFileHints(_file: string, content: string, resolvedImports?: readonly ResolvedPersistenceImportFact[]): {
1933
1922
  orchestrationHeavy?: boolean;
1934
1923
  adapterThick?: boolean;
1935
1924
  persistenceWrite?: boolean;
@@ -1937,7 +1926,7 @@ declare function deriveArkRuleFileHints(_file: string, content: string): {
1937
1926
  /**
1938
1927
  * Build fileHints map from path→content. Omits paths with no flags (sparse map).
1939
1928
  */
1940
- declare function buildArkRuleFileHints(fileContents: Readonly<Record<string, string>>): Record<string, {
1929
+ declare function buildArkRuleFileHints(fileContents: Readonly<Record<string, string>>, resolvedImportsByFile?: Readonly<Record<string, readonly ResolvedPersistenceImportFact[]>>): Record<string, {
1941
1930
  orchestrationHeavy?: boolean;
1942
1931
  adapterThick?: boolean;
1943
1932
  persistenceWrite?: boolean;
@@ -2468,4 +2457,4 @@ declare function catalogFixForRuleId(ruleId: string | null | undefined): string
2468
2457
  */
2469
2458
  declare function catalogWhyForRuleId(ruleId: string | null | undefined): string | undefined;
2470
2459
 
2471
- export { type ArchitectureChangeMapFile as $, type ArkRulesFile as A, type AdapterSeverity as B, type AdapterViolationInput as C, type AnalysisCapabilityUse as D, type EffectiveArkRules as E, type AnalysisCompilerOptions as F, type AnalysisCompleteness as G, type AnalysisContract as H, type AnalysisEvidence as I, type AnalysisFile as J, type AnalysisFileChange as K, type AnalysisFileInput as L, type AnalysisImportEdge as M, type AnalysisIr as N, type AnalysisMode as O, type AnalysisResult as P, type AnalysisViolation as Q, type ResolvedArkRunKernelCallKind as R, type AnalyzeArchitectureConvergenceInput as S, type AnalyzeChangeInput as T, type AnalyzePolicyDeltaInput as U, type AnalyzeProjectInput as V, type AnalyzeResolvedProjectInput as W, type ArchitectureActualChange as X, type ArchitectureChangeMap as Y, type ArchitectureChangeMapContract as Z, type ArchitectureChangeMapDependency as _, type ResolvedArkRunDeclarationFact as a, type SemanticDependencyKind as a$, type ArchitectureChangeOperation as a0, type ArchitectureConvergenceClassification as a1, type ArchitectureConvergenceFinding as a2, type ArchitectureConvergenceResult as a3, type ArchitectureDependency as a4, type ArchitectureEngineEdge as a5, type ArchitectureEngineResult as a6, type ArchitectureEngineViolation as a7, type ArkDesignDeltaResult as a8, type ArkEnforcementHost as a9, type PolicyDeltaAcknowledgement as aA, type PolicyDeltaAnalysis as aB, type PolicyDeltaClassification as aC, type PolicyDeltaFinding as aD, type PreflightResolvedChangeInput as aE, type PreparedChangeFile as aF, RESOLVED_CANDIDATE_FACTS_SCHEMA as aG, RESOLVED_CANDIDATE_FACTS_SCHEMA_VERSION as aH, type ResolvedAmbientFact as aI, type ResolvedAnalysisFile as aJ, type ResolvedAnalysisIr as aK, type ResolvedAnalysisResult as aL, type ResolvedCandidateFacts as aM, type ResolvedCandidateFactsInput as aN, type ResolvedCapability as aO, type ResolvedCapabilityFact as aP, type ResolvedChangePreflightResult as aQ, type ResolvedDependencyKind as aR, type ResolvedDependencyState as aS, type ResolvedFactsCompleteness as aT, type ResolvedFileFact as aU, type ResolvedIntentReferenceFact as aV, type ResolvedPublishFact as aW, type ResolvedSafetyFact as aX, type ResolvedSafetyKind as aY, type ResolvedSafetyReport as aZ, type SemanticDependency as a_, type ArkEnforcementState as aa, type ArkRuleSensorViolation as ab, type ChangePreflightResult as ac, type ClassShapeFact as ad, type CollectAnalysisConfigWarningsInput as ae, DIAGNOSTIC_CATALOG as af, DIAGNOSTIC_CATALOG_SCHEMA_VERSION as ag, DIAGNOSTIC_DOCS_RELATIVE_PATH as ah, DIAGNOSTIC_RULE_IDS as ai, type DesignDeltaChange as aj, type DesignDeltaEnforcementScope as ak, type DesignDeltaIdentity as al, type DesignSmellEvidence as am, type DesignSmellFinding as an, type DesignSmellId as ao, type DiagnosticCatalogEntry as ap, type DiagnosticCategory as aq, type EnforcementBoundaryState as ar, type EnforcementEvidence as as, type EnforcementEvidenceField as at, type EnforcementVerification as au, type EvaluateArchitectureGraphInput as av, type ForbiddenCapabilityUse as aw, type InvariantCoverageEvidence as ax, POLICY_DELTA_SCHEMA_VERSION as ay, type PolicyDelta as az, type ResolvedArkRunKernelCallFact as b, adapterDocsCodePath as b0, adapterFindingOccurrenceTargetKeys as b1, adapterFindingRefFromTargetKey as b2, adapterFindingTargetKey as b3, analyzeArchitectureConvergence as b4, analyzeChange as b5, analyzePolicyDelta as b6, analyzeProject as b7, analyzeResolvedProject as b8, buildArkRuleFileHints as b9, isCataloguedOrArkRuleFamily as bA, isKnownDiagnosticCode as bB, loadContract as bC, loadResolvedCandidateFacts as bD, policyDeltaAcknowledgementMatches as bE, preflightChange as bF, preflightResolvedChange as bG, resolvedFactsEvidenceRequirementsHash as bH, serializeDiagnosticCatalog as bI, stableSerialize as bJ, toAdapterDiagnostic as bK, version as bL, canPromoteInvariant as ba, catalogFixForRuleId as bb, catalogWhyForRuleId as bc, classifyArkPolicyDelta as bd, collectAnalysisConfigWarnings as be, collectEmptyAppliesToFindings as bf, collectForbiddenCapabilityUses as bg, createAICodeGate as bh, createAdapterResult as bi, createArchitectureProfile as bj, createArchitectureProfileFromArkConfig as bk, createElevenLayerArkConfig as bl, createResolvedCandidateFacts as bm, deriveArkRuleFileHints as bn, detectArchitectureCycles as bo, deterministicHash as bp, diagnosticDocsFragment as bq, diagnosticDocsPath as br, elevenLayerProfile as bs, evaluateArchitectureGraph as bt, evaluateArkRuleSensors as bu, evaluateInvariantCoverage as bv, explainViolation as bw, extractClassShapesFromSource as bx, extractSemanticDependencies as by, getDiagnosticCatalogEntry as bz, type ResolvedArkRunManagedNewFact as c, type ResolvedDependencyFact as d, type ResolvedArkRunCompositionRootHitFact as e, type ResolvedFactsReason as f, type ResolvedArkOrderPlaneCallFact as g, type ResolvedArkOrderGenericUpdateFact as h, type ResolvedArkOrderRootHitFact as i, type ResolvedArkOrderXiFieldWriteFact as j, type ResolvedArkOrderIngestWriteFact as k, ADAPTER_DIAGNOSTIC_DOCS_RELATIVE_PATH as l, type AICodeGate as m, type AICodeGateContext as n, type AICodeGateOptions as o, type AICodeGateResult as p, type AICodeGateViolation as q, type AIGateExtension as r, ANALYSIS_IR_SCHEMA_VERSION as s, ARK_ANALYSIS_RESULT_SCHEMA as t, ARK_ANALYSIS_RESULT_SCHEMA_VERSION as u, ARK_DESIGN_DELTA_SCHEMA_VERSION as v, ARK_ENFORCEMENT_STATE_SCHEMA_VERSION as w, type AdapterCompletenessReason as x, type AdapterDiagnostic as y, type AdapterResult as z };
2460
+ export { type ArchitectureChangeMapFile as $, type AdapterViolationInput as A, type AdapterResult as B, type AdapterSeverity as C, type AnalysisCapabilityUse as D, type EffectiveArkRules as E, type AnalysisCompilerOptions as F, type AnalysisCompleteness as G, type AnalysisContract as H, type AnalysisEvidence as I, type AnalysisFile as J, type AnalysisFileChange as K, type AnalysisFileInput as L, type AnalysisImportEdge as M, type AnalysisIr as N, type AnalysisMode as O, type AnalysisResult as P, type AnalysisViolation as Q, type ResolvedArkRunKernelCallKind as R, type AnalyzeArchitectureConvergenceInput as S, type AnalyzeChangeInput as T, type AnalyzePolicyDeltaInput as U, type AnalyzeProjectInput as V, type AnalyzeResolvedProjectInput as W, type ArchitectureActualChange as X, type ArchitectureChangeMap as Y, type ArchitectureChangeMapContract as Z, type ArchitectureChangeMapDependency as _, type ArkRulesFile as a, type SemanticDependencyKind as a$, type ArchitectureChangeOperation as a0, type ArchitectureConvergenceClassification as a1, type ArchitectureConvergenceFinding as a2, type ArchitectureConvergenceResult as a3, type ArchitectureDependency as a4, type ArchitectureEngineEdge as a5, type ArchitectureEngineResult as a6, type ArchitectureEngineViolation as a7, type ArkDesignDeltaResult as a8, type ArkEnforcementHost as a9, type PolicyDeltaAcknowledgement as aA, type PolicyDeltaAnalysis as aB, type PolicyDeltaClassification as aC, type PolicyDeltaFinding as aD, type PreflightResolvedChangeInput as aE, type PreparedChangeFile as aF, RESOLVED_CANDIDATE_FACTS_SCHEMA as aG, RESOLVED_CANDIDATE_FACTS_SCHEMA_VERSION as aH, type ResolvedAmbientFact as aI, type ResolvedAnalysisFile as aJ, type ResolvedAnalysisIr as aK, type ResolvedAnalysisResult as aL, type ResolvedCandidateFacts as aM, type ResolvedCandidateFactsInput as aN, type ResolvedCapability as aO, type ResolvedCapabilityFact as aP, type ResolvedChangePreflightResult as aQ, type ResolvedDependencyKind as aR, type ResolvedDependencyState as aS, type ResolvedFactsCompleteness as aT, type ResolvedFileFact as aU, type ResolvedIntentReferenceFact as aV, type ResolvedPublishFact as aW, type ResolvedSafetyFact as aX, type ResolvedSafetyKind as aY, type ResolvedSafetyReport as aZ, type SemanticDependency as a_, type ArkEnforcementState as aa, type ArkRuleSensorViolation as ab, type ChangePreflightResult as ac, type ClassShapeFact as ad, type CollectAnalysisConfigWarningsInput as ae, DIAGNOSTIC_CATALOG as af, DIAGNOSTIC_CATALOG_SCHEMA_VERSION as ag, DIAGNOSTIC_DOCS_RELATIVE_PATH as ah, DIAGNOSTIC_RULE_IDS as ai, type DesignDeltaChange as aj, type DesignDeltaEnforcementScope as ak, type DesignDeltaIdentity as al, type DesignSmellEvidence as am, type DesignSmellFinding as an, type DesignSmellId as ao, type DiagnosticCatalogEntry as ap, type DiagnosticCategory as aq, type EnforcementBoundaryState as ar, type EnforcementEvidence as as, type EnforcementEvidenceField as at, type EnforcementVerification as au, type EvaluateArchitectureGraphInput as av, type ForbiddenCapabilityUse as aw, type InvariantCoverageEvidence as ax, POLICY_DELTA_SCHEMA_VERSION as ay, type PolicyDelta as az, type ResolvedArkRunDeclarationFact as b, analyzeArchitectureConvergence as b0, analyzeChange as b1, analyzePolicyDelta as b2, analyzeProject as b3, analyzeResolvedProject as b4, buildArkRuleFileHints as b5, canPromoteInvariant as b6, catalogFixForRuleId as b7, catalogWhyForRuleId as b8, classifyArkPolicyDelta as b9, policyDeltaAcknowledgementMatches as bA, preflightChange as bB, preflightResolvedChange as bC, resolvedFactsEvidenceRequirementsHash as bD, serializeDiagnosticCatalog as bE, stableSerialize as bF, toAdapterDiagnostic as bG, version as bH, collectAnalysisConfigWarnings as ba, collectEmptyAppliesToFindings as bb, collectForbiddenCapabilityUses as bc, createAICodeGate as bd, createAdapterResult as be, createArchitectureProfile as bf, createArchitectureProfileFromArkConfig as bg, createElevenLayerArkConfig as bh, createResolvedCandidateFacts as bi, deriveArkRuleFileHints as bj, detectArchitectureCycles as bk, deterministicHash as bl, diagnosticDocsFragment as bm, diagnosticDocsPath as bn, elevenLayerProfile as bo, evaluateArchitectureGraph as bp, evaluateArkRuleSensors as bq, evaluateInvariantCoverage as br, explainViolation as bs, extractClassShapesFromSource as bt, extractSemanticDependencies as bu, getDiagnosticCatalogEntry as bv, isCataloguedOrArkRuleFamily as bw, isKnownDiagnosticCode as bx, loadContract as by, loadResolvedCandidateFacts as bz, type ResolvedArkRunKernelCallFact as c, type ResolvedArkRunManagedNewFact as d, type ResolvedDependencyFact as e, type ResolvedArkRunCompositionRootHitFact as f, type ResolvedFactsReason as g, type ResolvedArkOrderPlaneCallFact as h, type ResolvedArkOrderGenericUpdateFact as i, type ResolvedArkOrderRootHitFact as j, type ResolvedArkOrderXiFieldWriteFact as k, type ResolvedArkOrderIngestWriteFact as l, ADAPTER_DIAGNOSTIC_DOCS_RELATIVE_PATH as m, type AICodeGate as n, type AICodeGateContext as o, type AICodeGateOptions as p, type AICodeGateResult as q, type AICodeGateViolation as r, type AIGateExtension as s, ANALYSIS_IR_SCHEMA_VERSION as t, ARK_ANALYSIS_RESULT_SCHEMA as u, ARK_ANALYSIS_RESULT_SCHEMA_VERSION as v, ARK_DESIGN_DELTA_SCHEMA_VERSION as w, ARK_ENFORCEMENT_STATE_SCHEMA_VERSION as x, type AdapterCompletenessReason as y, type AdapterDiagnostic as z };