arkgate 2.13.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -0
- package/README.md +53 -36
- package/bin/ark-check.mjs +72 -6
- package/bin/ark-mcp.mjs +108 -1
- package/bin/ark-shared.mjs +204 -149
- package/bin/ark.mjs +90 -25
- package/bin/lib/adapter-contract.mjs +93 -0
- package/bin/lib/agent-gates.mjs +1 -0
- package/bin/lib/analysis-engine.mjs +1171 -0
- package/bin/lib/architecture-scan.mjs +84 -135
- package/bin/lib/ci-and-commands.mjs +51 -15
- package/bin/lib/config-warnings.mjs +7 -205
- package/bin/lib/design-smells.mjs +434 -0
- package/bin/lib/doctor-plan.mjs +149 -16
- package/bin/lib/field-install.mjs +67 -10
- package/bin/lib/gate-files.mjs +42 -3
- package/bin/lib/graph-cycles.mjs +4 -54
- package/bin/lib/hook-templates.mjs +33 -1
- package/bin/lib/host-support-matrix.mjs +7 -1
- package/bin/lib/install-migrate.mjs +54 -16
- package/bin/lib/presets.mjs +42 -2
- package/bin/lib/safety-diagnostics.mjs +18 -17
- package/bin/lib/scan-files.mjs +12 -1
- package/bin/lib/skill-install.mjs +8 -1
- package/bin/lib/source-policy.mjs +36 -0
- package/bin/lib/start-preview.mjs +271 -0
- package/bin/lib/ts-resolve.mjs +11 -2
- package/bin/lib/write-path-capabilities.mjs +4 -0
- package/compat/nestjs.cjs +2 -0
- package/compat/nestjs.d.ts +2 -0
- package/compat/nestjs.js +1 -0
- package/compat/runtime.cjs +2 -0
- package/compat/runtime.d.ts +2 -0
- package/compat/runtime.js +1 -0
- package/dist/configContract-BxSIwVRo.d.cts +259 -0
- package/dist/configContract-BxSIwVRo.d.ts +259 -0
- package/dist/eslint/index.cjs +125 -48
- package/dist/eslint/index.d.cts +7 -1
- package/dist/eslint/index.d.ts +7 -1
- package/dist/eslint/index.js +125 -48
- package/dist/index.cjs +1248 -3302
- package/dist/index.d.cts +359 -483
- package/dist/index.d.ts +359 -483
- package/dist/index.js +1231 -3248
- package/docs/agent-guide.md +34 -16
- package/docs/ai-gates.md +30 -7
- package/docs/brownfield-adoption.md +52 -1
- package/docs/migrate-from-ark-runtime-kernel.md +2 -3
- package/docs/package-surface.md +10 -13
- package/docs/production-hardening.md +17 -4
- package/docs/typescript-support.md +27 -0
- package/package.json +33 -11
- package/schemas/ark.analysis-result.schema.json +91 -0
- package/server.json +2 -2
- package/templates/skills/ark-adopt.md +26 -3
- package/templates/skills/ark-architect.md +10 -2
- package/templates/skills/ark-autopilot.md +37 -20
- package/templates/skills/ark-contract.md +7 -0
- package/templates/skills/ark-coverage.md +44 -45
- package/templates/skills/ark-explain.md +8 -0
- package/templates/skills/ark-explore.md +117 -47
- package/templates/skills/ark-fix.md +22 -0
- package/templates/skills/ark-loop.md +15 -1
- package/templates/skills/ark-place.md +7 -0
- package/templates/skills/ark-think.md +24 -20
- package/dist/configContract-iBLxx5Tz.d.cts +0 -53
- package/dist/configContract-iBLxx5Tz.d.ts +0 -53
- package/dist/eslint/index.cjs.map +0 -1
- package/dist/eslint/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/nestjs/index.cjs +0 -2606
- package/dist/nestjs/index.cjs.map +0 -1
- package/dist/nestjs/index.d.cts +0 -23
- package/dist/nestjs/index.d.ts +0 -23
- package/dist/nestjs/index.js +0 -2582
- package/dist/nestjs/index.js.map +0 -1
- package/dist/runtime/index.cjs +0 -4014
- package/dist/runtime/index.cjs.map +0 -1
- package/dist/runtime/index.d.cts +0 -3
- package/dist/runtime/index.d.ts +0 -3
- package/dist/runtime/index.js +0 -3925
- package/dist/runtime/index.js.map +0 -1
- package/dist/types-BxBwnBpC.d.cts +0 -1041
- package/dist/types-Wcs_l1_J.d.ts +0 -1041
package/bin/ark.mjs
CHANGED
|
@@ -20,6 +20,8 @@ import {
|
|
|
20
20
|
} from './ark-shared.mjs';
|
|
21
21
|
import { pinArkgateDevDependency, FALSE_GREEN_GAP_ID } from './lib/field-install.mjs';
|
|
22
22
|
import { validateHardWriteRequest } from './lib/enforcement-profiles.mjs';
|
|
23
|
+
import { applyStartPreview, planStart, renderStartPreview } from './lib/start-preview.mjs';
|
|
24
|
+
import { detectActiveAgentHost } from './lib/skill-install.mjs';
|
|
23
25
|
|
|
24
26
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
25
27
|
const arkCheck = path.join(here, 'ark-check.mjs');
|
|
@@ -58,6 +60,12 @@ function parseArgs(argv) {
|
|
|
58
60
|
force: false,
|
|
59
61
|
strict: true,
|
|
60
62
|
install: true,
|
|
63
|
+
installExplicit: false,
|
|
64
|
+
apply: false,
|
|
65
|
+
json: false,
|
|
66
|
+
internalApply: false,
|
|
67
|
+
skipPackageManager: false,
|
|
68
|
+
removeHost: undefined,
|
|
61
69
|
requireWriteHook: undefined,
|
|
62
70
|
help: false,
|
|
63
71
|
version: false,
|
|
@@ -79,7 +87,19 @@ function parseArgs(argv) {
|
|
|
79
87
|
else if (arg === '--yes' || arg === '-y') args.yes = true;
|
|
80
88
|
else if (arg === '--force') args.force = true;
|
|
81
89
|
else if (arg === '--no-strict') args.strict = false;
|
|
82
|
-
else if (arg === '--
|
|
90
|
+
else if (arg === '--install') {
|
|
91
|
+
args.install = true;
|
|
92
|
+
args.installExplicit = true;
|
|
93
|
+
}
|
|
94
|
+
else if (arg === '--no-install') {
|
|
95
|
+
args.install = false;
|
|
96
|
+
args.installExplicit = true;
|
|
97
|
+
}
|
|
98
|
+
else if (arg === '--apply') args.apply = true;
|
|
99
|
+
else if (arg === '--json') args.json = true;
|
|
100
|
+
else if (arg === '--internal-apply') args.internalApply = true;
|
|
101
|
+
else if (arg === '--skip-package-manager') args.skipPackageManager = true;
|
|
102
|
+
else if (arg === '--remove-host') args.removeHost = requireValue(arg, i++).trim().toLowerCase();
|
|
83
103
|
else if (arg === '--preset') args.preset = requireValue(arg, i++);
|
|
84
104
|
else if (arg === '--archetype') args.archetype = requireValue(arg, i++);
|
|
85
105
|
else if (arg === '--tools') args.tools = requireValue(arg, i++);
|
|
@@ -97,14 +117,13 @@ function parseArgs(argv) {
|
|
|
97
117
|
|
|
98
118
|
function usage() {
|
|
99
119
|
return `Usage:
|
|
100
|
-
ark start [--root <project>] [--tools <
|
|
120
|
+
ark start [--root <project>] [--tools <host>] [--require-write-hook <host>] [--install] [--apply] [--json]
|
|
101
121
|
ark init [--root <project>] [--preset hexagonal|layered|feature-sliced|monorepo|ui-surface|vertical-slice|ddd-bounded-contexts|clean-architecture|onion-architecture]
|
|
102
122
|
[--archetype <playbook-id>] [--tools <list>] [--require-write-hook <host>] [--yes] [--force] [--no-strict]
|
|
103
123
|
ark upgrade [--root <project>] [--no-install] [--no-strict]
|
|
104
124
|
|
|
105
125
|
Commands:
|
|
106
|
-
start New here?
|
|
107
|
-
plain language, sets up the guardrails, and shows a plan — no code changed.
|
|
126
|
+
start New here? Analyze and preview the complete setup. Read-only unless --apply.
|
|
108
127
|
init Configure Ark project enforcement with explicit prompts.
|
|
109
128
|
upgrade One command to update Ark: bump the package to @latest, refresh gate
|
|
110
129
|
templates + /ark-* skills (and Codex home prompts), migrate command
|
|
@@ -116,14 +135,19 @@ Options:
|
|
|
116
135
|
(Also the implicit default when stdin/stdout are not a TTY — agents never hang on prompts.)
|
|
117
136
|
--force Allow generated files to overwrite existing files.
|
|
118
137
|
--no-strict Skip the final strict ark-check run.
|
|
138
|
+
--install Add arkgate to package.json explicitly before applying a start plan.
|
|
119
139
|
--no-install Skip adding/installing arkgate as a project devDependency (start/upgrade).
|
|
140
|
+
--apply Apply the mutations shown by the start preview.
|
|
141
|
+
--json Emit the start preview as deterministic machine-readable JSON.
|
|
120
142
|
--preset Start from a named architecture preset instead of detection.
|
|
121
143
|
--archetype Application shape from templates/architecture-playbook.json (maps to the matching preset).
|
|
122
144
|
Valid ids: crud-product, api-backend, frontend-surface, library-sdk, cli-utility,
|
|
123
145
|
worker-pipeline, event-coordinator, integration-bridge, multi-app-workspace, prototype-spike,
|
|
124
146
|
vertical-slice-product, ddd-bounded-contexts.
|
|
125
|
-
--tools
|
|
126
|
-
Omit to
|
|
147
|
+
--tools One active agent host for start (claude,cursor,codex,grok,windsurf,cline,copilot,kiro,roo,continue,gemini).
|
|
148
|
+
Omit to use the active host; an unknown host creates only the shared compact router.
|
|
149
|
+
--remove-host <host>
|
|
150
|
+
Preview or apply removal of that compact host integration; re-add it with --tools <host>.
|
|
127
151
|
--require-write-hook <host>
|
|
128
152
|
Require and verify a hard local write hook for Claude or Grok. Cursor/Codex are
|
|
129
153
|
advisory-write plus hard CI merge only; impossible requests fail before any write.
|
|
@@ -229,6 +253,25 @@ function isInteractiveTty() {
|
|
|
229
253
|
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
230
254
|
}
|
|
231
255
|
|
|
256
|
+
async function resolveStartHost(args) {
|
|
257
|
+
if (args.tools || args.removeHost) return args.tools;
|
|
258
|
+
const active = detectActiveAgentHost();
|
|
259
|
+
if (!isInteractiveTty() || args.yes) return active ?? undefined;
|
|
260
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
261
|
+
try {
|
|
262
|
+
const answer = (
|
|
263
|
+
await rl.question(
|
|
264
|
+
`Which agent should receive Ark's compact router? [${active ?? 'skip for now'}] `
|
|
265
|
+
)
|
|
266
|
+
)
|
|
267
|
+
.trim()
|
|
268
|
+
.toLowerCase();
|
|
269
|
+
return answer || active || undefined;
|
|
270
|
+
} finally {
|
|
271
|
+
rl.close();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
232
275
|
/**
|
|
233
276
|
* True when prompts should be skipped and guided defaults applied.
|
|
234
277
|
* Agents typically have no TTY — never call readline on a null interface.
|
|
@@ -410,9 +453,24 @@ async function init(args) {
|
|
|
410
453
|
|
|
411
454
|
// `ark start` — the guided entry point (co-pilot Phase G). One command takes a newcomer from
|
|
412
455
|
// "I have a project" to "governed, with a plan" in plain language, without knowing any skill
|
|
413
|
-
// names: look at the code → suggest a shape → set up
|
|
456
|
+
// names: look at the code → suggest a shape → set up one compact host router → show the plan. It only
|
|
414
457
|
// orchestrates existing steps (recommend → init → --plan) and frames each in outcome terms.
|
|
415
458
|
async function start(args) {
|
|
459
|
+
if (!args.internalApply) {
|
|
460
|
+
args.tools = await resolveStartHost(args);
|
|
461
|
+
const preview = await planStart(args, {
|
|
462
|
+
arkCheck,
|
|
463
|
+
cliPath: fileURLToPath(import.meta.url),
|
|
464
|
+
cliVersion,
|
|
465
|
+
packageInstallArgv,
|
|
466
|
+
});
|
|
467
|
+
if (args.json) console.log(JSON.stringify(preview, null, 2));
|
|
468
|
+
else renderStartPreview(preview);
|
|
469
|
+
if (!args.apply) return 0;
|
|
470
|
+
applyStartPreview(args.root, preview);
|
|
471
|
+
if (!args.json) console.log(`Applied ${preview.changes.length} previewed mutation(s).`);
|
|
472
|
+
return 0;
|
|
473
|
+
}
|
|
416
474
|
const root = args.root;
|
|
417
475
|
const nonInteractive = shouldUseNonInteractiveDefaults(args);
|
|
418
476
|
const interactive = !nonInteractive;
|
|
@@ -423,10 +481,10 @@ async function start(args) {
|
|
|
423
481
|
try {
|
|
424
482
|
console.log("Let's set up Ark for your project.");
|
|
425
483
|
console.log(
|
|
426
|
-
"I'll walk the tree,
|
|
484
|
+
"I'll walk the tree, create a compact host-specific guardrail setup, then show a plan."
|
|
427
485
|
);
|
|
428
486
|
console.log(
|
|
429
|
-
'Nothing in your product code is changed — only Ark config,
|
|
487
|
+
'Nothing in your product code is changed — only Ark config, one active-host router, and a CI template.'
|
|
430
488
|
);
|
|
431
489
|
if (nonInteractive && !args.yes) {
|
|
432
490
|
console.log(
|
|
@@ -465,10 +523,10 @@ async function start(args) {
|
|
|
465
523
|
}
|
|
466
524
|
|
|
467
525
|
// 2b) Pin arkgate as a project devDependency so CI/npx do not depend on a stale global.
|
|
468
|
-
if (args.
|
|
526
|
+
if (args.installExplicit && args.install && fs.existsSync(path.join(root, 'package.json'))) {
|
|
469
527
|
const { pinned, installStatus } = ensureProjectArkgateDependency(root, {
|
|
470
528
|
install: true,
|
|
471
|
-
runPackageManager:
|
|
529
|
+
runPackageManager: !args.skipPackageManager,
|
|
472
530
|
});
|
|
473
531
|
if (pinned.changed) {
|
|
474
532
|
console.log(` Pinned arkgate@${pinned.version} in package.json devDependencies.`);
|
|
@@ -480,7 +538,7 @@ async function start(args) {
|
|
|
480
538
|
} else if (pinned.reason === 'already-present') {
|
|
481
539
|
console.log(` arkgate already in package.json (${pinned.version}).`);
|
|
482
540
|
}
|
|
483
|
-
} else if (args.install === false) {
|
|
541
|
+
} else if (args.installExplicit && args.install === false) {
|
|
484
542
|
console.log(' Skipping arkgate package pin (--no-install).');
|
|
485
543
|
}
|
|
486
544
|
|
|
@@ -494,10 +552,11 @@ async function start(args) {
|
|
|
494
552
|
const preset = archetype ? resolveArchetypePreset(archetype).preset : undefined;
|
|
495
553
|
const includeRoots = resolveIncludeRoots(root);
|
|
496
554
|
const tsPackages = detectTsPackageRoots(root);
|
|
555
|
+
const nestedTsPackages = tsPackages.filter((entry) => entry !== '.');
|
|
497
556
|
const workspaces = detectWorkspaces(root);
|
|
498
557
|
const looksLikeMonorepo =
|
|
499
558
|
includeRoots.length > 0 ||
|
|
500
|
-
|
|
559
|
+
nestedTsPackages.length > 0 ||
|
|
501
560
|
workspaces.length > 0 ||
|
|
502
561
|
fs.existsSync(path.join(root, 'rush.json')) ||
|
|
503
562
|
fs.existsSync(path.join(root, 'pnpm-workspace.yaml')) ||
|
|
@@ -510,9 +569,9 @@ async function start(args) {
|
|
|
510
569
|
const useUi =
|
|
511
570
|
rec?.preset === 'feature-sliced' ||
|
|
512
571
|
rec?.archetype === 'frontend-surface' ||
|
|
513
|
-
(
|
|
514
|
-
initArgs.push('--preset', useUi &&
|
|
515
|
-
const shown = includeRoots.length > 0 ? includeRoots :
|
|
572
|
+
(nestedTsPackages.length > 0 && includeRoots.length === 0 && !rec?.mature);
|
|
573
|
+
initArgs.push('--preset', useUi && nestedTsPackages.length <= 3 ? 'ui-surface' : 'monorepo');
|
|
574
|
+
const shown = includeRoots.length > 0 ? includeRoots : nestedTsPackages;
|
|
516
575
|
console.log(
|
|
517
576
|
shown.length > 0
|
|
518
577
|
? ` Multi-package / TS package layout detected — profile include: ${shown.join(', ')}.`
|
|
@@ -527,16 +586,16 @@ async function start(args) {
|
|
|
527
586
|
console.log(' Found an existing ark.config.json — keeping it.');
|
|
528
587
|
}
|
|
529
588
|
|
|
530
|
-
// 4)
|
|
531
|
-
//
|
|
589
|
+
// 4) Compact start deliberately avoids reports/history and copied skills. A report can
|
|
590
|
+
// be requested later, after the small host-specific setup is accepted.
|
|
532
591
|
console.log('');
|
|
533
|
-
|
|
592
|
+
console.log('Skipping day-zero report archive in compact start (run ark-check --report later if wanted).');
|
|
534
593
|
|
|
535
|
-
// 5) Agent + CI gate templates
|
|
594
|
+
// 5) Agent + CI gate templates for exactly one active host.
|
|
536
595
|
console.log('');
|
|
537
596
|
console.log('Installing agent and CI gate templates…');
|
|
538
597
|
{
|
|
539
|
-
const gateArgs = ['--root', root, '--install-agent-gates'];
|
|
598
|
+
const gateArgs = ['--root', root, '--install-agent-gates', '--compact'];
|
|
540
599
|
if (args.tools) gateArgs.push('--tools', args.tools);
|
|
541
600
|
if (args.requireWriteHook) {
|
|
542
601
|
gateArgs.push('--require-write-hook', args.requireWriteHook);
|
|
@@ -687,7 +746,7 @@ async function start(args) {
|
|
|
687
746
|
);
|
|
688
747
|
}
|
|
689
748
|
console.log('');
|
|
690
|
-
console.log('
|
|
749
|
+
console.log('Optional later: ark-check --report ark-report.html (captures a day-zero/evolution report).');
|
|
691
750
|
console.log('Optional later: --plan · --coverage · /ark-explore · /ark-fix · /ark-place · ark upgrade');
|
|
692
751
|
return 0;
|
|
693
752
|
} finally {
|
|
@@ -764,9 +823,15 @@ async function main() {
|
|
|
764
823
|
}
|
|
765
824
|
|
|
766
825
|
// Only run when executed as the CLI entry (not when imported by unit tests).
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
826
|
+
function entryPath(file) {
|
|
827
|
+
try {
|
|
828
|
+
return fs.realpathSync(file);
|
|
829
|
+
} catch {
|
|
830
|
+
return path.resolve(file);
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const isMain = Boolean(process.argv[1]) && entryPath(process.argv[1]) === entryPath(fileURLToPath(import.meta.url));
|
|
770
835
|
if (isMain) {
|
|
771
836
|
process.exitCode = await main();
|
|
772
837
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GENERATED FILE — do not edit by hand.
|
|
3
|
+
*
|
|
4
|
+
* Canonical algorithm: src/domain/adapterContract.ts
|
|
5
|
+
* Regenerate: node scripts/generate-cli-pure.mjs
|
|
6
|
+
* Drift check: node scripts/generate-cli-pure.mjs --check
|
|
7
|
+
*
|
|
8
|
+
* Pure CLI helper (bin/lib/adapter-contract.mjs). Zero Node I/O.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const ARK_ANALYSIS_RESULT_SCHEMA_VERSION = '1.0';
|
|
12
|
+
function text(value) {
|
|
13
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
14
|
+
}
|
|
15
|
+
function positiveInteger(value, fallback) {
|
|
16
|
+
return Number.isInteger(value) && Number(value) > 0 ? Number(value) : fallback;
|
|
17
|
+
}
|
|
18
|
+
export function toAdapterDiagnostic(violation, fallbackSeverity = 'error') {
|
|
19
|
+
const ruleId = text(violation.ruleId) ?? text(violation.code) ?? 'ARK_UNKNOWN';
|
|
20
|
+
const severity = violation.severity === 'warning' ? 'warning' : fallbackSeverity;
|
|
21
|
+
const evidence = {
|
|
22
|
+
...(text(violation.target) ? { target: text(violation.target) } : {}),
|
|
23
|
+
...(text(violation.fromLayer) ? { fromLayer: text(violation.fromLayer) } : {}),
|
|
24
|
+
...(text(violation.toLayer) ? { toLayer: text(violation.toLayer) } : {}),
|
|
25
|
+
...(typeof violation.typeOnly === 'boolean' ? { typeOnly: violation.typeOnly } : {}),
|
|
26
|
+
};
|
|
27
|
+
return {
|
|
28
|
+
ruleId,
|
|
29
|
+
severity,
|
|
30
|
+
message: text(violation.message) ?? ruleId,
|
|
31
|
+
location: {
|
|
32
|
+
file: text(violation.file) ?? '<unknown>',
|
|
33
|
+
line: positiveInteger(violation.line, 1),
|
|
34
|
+
column: positiveInteger(violation.column, 1),
|
|
35
|
+
},
|
|
36
|
+
evidence,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function createAdapterResult(input) {
|
|
40
|
+
return {
|
|
41
|
+
schemaVersion: ARK_ANALYSIS_RESULT_SCHEMA_VERSION,
|
|
42
|
+
valid: input.valid,
|
|
43
|
+
diagnostics: [
|
|
44
|
+
...(input.violations ?? []).map((item) => toAdapterDiagnostic(item, 'error')),
|
|
45
|
+
...(input.warnings ?? []).map((item) => toAdapterDiagnostic(item, 'warning')),
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export const ARK_ANALYSIS_RESULT_SCHEMA = {
|
|
50
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
51
|
+
$id: 'https://unpkg.com/arkgate@2/schemas/ark.analysis-result.schema.json',
|
|
52
|
+
title: 'ArkGate analysis result',
|
|
53
|
+
type: 'object',
|
|
54
|
+
additionalProperties: false,
|
|
55
|
+
required: ['schemaVersion', 'valid', 'diagnostics'],
|
|
56
|
+
properties: {
|
|
57
|
+
schemaVersion: { const: ARK_ANALYSIS_RESULT_SCHEMA_VERSION },
|
|
58
|
+
valid: { type: 'boolean' },
|
|
59
|
+
diagnostics: {
|
|
60
|
+
type: 'array',
|
|
61
|
+
items: {
|
|
62
|
+
type: 'object',
|
|
63
|
+
additionalProperties: false,
|
|
64
|
+
required: ['ruleId', 'severity', 'message', 'location', 'evidence'],
|
|
65
|
+
properties: {
|
|
66
|
+
ruleId: { type: 'string', minLength: 1 },
|
|
67
|
+
severity: { enum: ['error', 'warning'] },
|
|
68
|
+
message: { type: 'string', minLength: 1 },
|
|
69
|
+
location: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
additionalProperties: false,
|
|
72
|
+
required: ['file', 'line', 'column'],
|
|
73
|
+
properties: {
|
|
74
|
+
file: { type: 'string', minLength: 1 },
|
|
75
|
+
line: { type: 'integer', minimum: 1 },
|
|
76
|
+
column: { type: 'integer', minimum: 1 },
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
evidence: {
|
|
80
|
+
type: 'object',
|
|
81
|
+
additionalProperties: false,
|
|
82
|
+
properties: {
|
|
83
|
+
target: { type: 'string' },
|
|
84
|
+
fromLayer: { type: 'string' },
|
|
85
|
+
toLayer: { type: 'string' },
|
|
86
|
+
typeOnly: { type: 'boolean' },
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|