arkgate 4.8.19 → 4.8.20
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 +101 -0
- package/README.md +4 -4
- package/bin/ark-check-runtime.mjs +23 -0
- package/bin/ark-layer-match.mjs +141 -9
- package/bin/ark.mjs +6 -2
- package/bin/lib/analysis-engine.mjs +6 -6
- package/bin/lib/config-contract.mjs +1 -0
- package/bin/lib/doctor-advisories.mjs +2 -1
- package/bin/lib/doctor-plan.mjs +2 -0
- package/bin/lib/enforcement-honesty.mjs +30 -2
- package/bin/lib/html-report-depth.mjs +5 -1
- package/bin/lib/invariant-coverage.mjs +44 -13
- package/bin/lib/package-manager.mjs +5 -2
- package/bin/lib/physical-cohesion.mjs +68 -51
- package/bin/lib/reshape-decisions.mjs +2 -2
- package/bin/lib/rules-under-contract.mjs +40 -4
- package/bin/lib/start-install-recovery.mjs +156 -0
- package/bin/lib/start-preview.mjs +0 -54
- package/dist/{configTypes-VD0qcubY.d.ts → configTypes-VVknqcTJ.d.ts} +2 -0
- package/dist/{diagnosticCatalog-D2v0ASN2.d.ts → diagnosticCatalog-BPYWNyJR.d.ts} +9 -3
- package/dist/eslint/index.cjs +4 -4
- package/dist/eslint/index.d.ts +12 -4
- package/dist/eslint/index.js +4 -4
- package/dist/index.cjs +18 -18
- package/dist/index.d.ts +8 -4
- package/dist/index.js +20 -20
- package/dist/nestjs/index.cjs +5 -5
- package/dist/nestjs/index.d.ts +3 -3
- package/dist/nestjs/index.js +5 -5
- package/dist/runtime/index.cjs +10 -10
- package/dist/runtime/index.d.ts +6 -6
- package/dist/runtime/index.js +10 -10
- package/dist/{types-BSzRy2X1.d.ts → types-Cs-46DRu.d.ts} +1 -1
- package/dist/{types-D5GT5ZT8.d.ts → types-p_fCp6P-.d.ts} +1 -1
- package/docs/README.md +1 -1
- package/docs/configuration.md +20 -5
- package/docs/develop.md +1 -1
- package/docs/package-surface.md +2 -2
- package/docs/use.md +1 -1
- package/package.json +3 -3
- package/schemas/ark.config.schema.json +6 -0
- package/server.json +2 -2
- package/templates/agent-skills/README.md +1 -1
- package/templates/agent-skills/ark-adopt/SKILL.md +15 -1
- package/templates/agent-skills/ark-autopilot/SKILL.md +2 -0
- package/templates/agent-skills/ark-coverage/SKILL.md +1 -1
- package/templates/agent-skills/ark-explain/SKILL.md +1 -1
- package/templates/agent-skills/ark-explore/SKILL.md +13 -1
- package/templates/agent-skills/ark-upgrade/SKILL.md +5 -3
- package/templates/skills/ark-adopt.md +15 -1
- package/templates/skills/ark-autopilot.md +2 -0
- package/templates/skills/ark-coverage.md +1 -1
- package/templates/skills/ark-explain.md +1 -1
- package/templates/skills/ark-explore.md +13 -1
- package/templates/skills/ark-upgrade.md +5 -3
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classified next steps when start / start --apply package install fails.
|
|
3
|
+
*
|
|
4
|
+
* Callers render `formatStartPackageInstallFailure`. Classification, Age window,
|
|
5
|
+
* pin-aware npx, and AgeExclude-must-be-in-config stay behind this module.
|
|
6
|
+
*/
|
|
7
|
+
import { spawnSync } from 'node:child_process';
|
|
8
|
+
import { arkPackageRecoveryCommand } from './package-manager.mjs';
|
|
9
|
+
|
|
10
|
+
const AGE_MARK = /ERR_PNPM_NO_MATURE_MATCHING_VERSION|minimumReleaseAge/i;
|
|
11
|
+
const AGE_EXCLUDE_LINE =
|
|
12
|
+
'To add it locally later: put arkgate on minimumReleaseAgeExclude in pnpm config or pnpm-workspace.yaml (a CLI flag is not enough), or wait until the release is old enough.';
|
|
13
|
+
const BIN_NOTE =
|
|
14
|
+
'`arkgate-check` is a command in the arkgate package — not its own npm package.';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {unknown} hostOutput
|
|
18
|
+
* @returns {string[]}
|
|
19
|
+
*/
|
|
20
|
+
function hostOutputTail(hostOutput) {
|
|
21
|
+
if (!hostOutput || !String(hostOutput).trim()) return [];
|
|
22
|
+
return String(hostOutput)
|
|
23
|
+
.split('\n')
|
|
24
|
+
.map((line) => line.trimEnd())
|
|
25
|
+
.filter((line) => line.trim())
|
|
26
|
+
.slice(-6);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Exact npm version for `npx --package=arkgate@<pin>` when Age blocked add.
|
|
31
|
+
* @param {string|undefined} packageVersion
|
|
32
|
+
* @param {string|undefined} installCommand
|
|
33
|
+
* @returns {string|null}
|
|
34
|
+
*/
|
|
35
|
+
export function resolveStartInstallPackagePin(packageVersion, installCommand) {
|
|
36
|
+
const fromArg = String(packageVersion ?? '')
|
|
37
|
+
.trim()
|
|
38
|
+
.replace(/^arkgate@/i, '')
|
|
39
|
+
.replace(/^\^/, '')
|
|
40
|
+
.replace(/^v/i, '');
|
|
41
|
+
if (/^\d+\.\d+\.\d+/.test(fromArg)) return fromArg.match(/^\d+\.\d+\.\d+/)?.[0] ?? null;
|
|
42
|
+
const fromCmd = String(installCommand ?? '').match(/arkgate@\^?v?(\d+\.\d+\.\d+)/i);
|
|
43
|
+
return fromCmd?.[1] ?? null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef {{ kind: 'pnpm-age', ageWindow: string, headline: string }} PnpmAgeInstallFailure
|
|
48
|
+
* @typedef {{ kind: 'generic', hostTail: string[] }} GenericInstallFailure
|
|
49
|
+
* @typedef {PnpmAgeInstallFailure | GenericInstallFailure} ClassifiedStartInstallFailure
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Classify captured package-manager stdout+stderr. Age is one class.
|
|
54
|
+
* @param {unknown} hostOutput
|
|
55
|
+
* @returns {ClassifiedStartInstallFailure}
|
|
56
|
+
*/
|
|
57
|
+
export function classifyStartInstallFailure(hostOutput) {
|
|
58
|
+
const text = String(hostOutput ?? '');
|
|
59
|
+
if (AGE_MARK.test(text)) {
|
|
60
|
+
const days = text.match(/(\d+)\s*days?/i)?.[1];
|
|
61
|
+
const ageWindow = days ? `${days} days` : 'a cooling-off window';
|
|
62
|
+
const headline = days
|
|
63
|
+
? `This repo waits before trusting new npm packages (pnpm Age — ${days} days).`
|
|
64
|
+
: 'This repo waits before trusting new npm packages (pnpm Age).';
|
|
65
|
+
return { kind: 'pnpm-age', ageWindow, headline };
|
|
66
|
+
}
|
|
67
|
+
return { kind: 'generic', hostTail: hostOutputTail(text) };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Plain Age headline, or null. Kept for the #268 one-liner tests.
|
|
72
|
+
* @param {unknown} hostOutput
|
|
73
|
+
* @returns {string|null}
|
|
74
|
+
*/
|
|
75
|
+
export function explainPnpmMaturityBlock(hostOutput) {
|
|
76
|
+
const classified = classifyStartInstallFailure(hostOutput);
|
|
77
|
+
return classified.kind === 'pnpm-age' ? classified.headline : null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* @typedef {{
|
|
82
|
+
* kind: 'pnpm-age' | 'generic',
|
|
83
|
+
* ageWindow?: string,
|
|
84
|
+
* primaryCommand: string,
|
|
85
|
+
* replayInstallCommand: string | null,
|
|
86
|
+
* lines: string[],
|
|
87
|
+
* }} StartInstallRecovery
|
|
88
|
+
*/
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Typed next-step for a failed start package install.
|
|
92
|
+
* Age never replays the doomed add; generic still names the exact command.
|
|
93
|
+
* @param {{
|
|
94
|
+
* exitStatus: number,
|
|
95
|
+
* installCommand: string,
|
|
96
|
+
* hostOutput?: string,
|
|
97
|
+
* packageVersion?: string,
|
|
98
|
+
* }} input
|
|
99
|
+
* @returns {StartInstallRecovery}
|
|
100
|
+
*/
|
|
101
|
+
export function startInstallRecovery(input) {
|
|
102
|
+
const exitStatus = input?.exitStatus ?? 1;
|
|
103
|
+
const installCommand = input?.installCommand ?? '';
|
|
104
|
+
const classified = classifyStartInstallFailure(input?.hostOutput);
|
|
105
|
+
const pin = resolveStartInstallPackagePin(input?.packageVersion, installCommand);
|
|
106
|
+
const honesty = `Package install failed (exit ${exitStatus}). Setup files are written; the local command is not installed yet.`;
|
|
107
|
+
if (classified.kind === 'pnpm-age') {
|
|
108
|
+
const doctor = arkPackageRecoveryCommand(
|
|
109
|
+
'arkgate-check',
|
|
110
|
+
'--doctor',
|
|
111
|
+
pin ? `arkgate@${pin}` : undefined
|
|
112
|
+
);
|
|
113
|
+
return {
|
|
114
|
+
kind: 'pnpm-age',
|
|
115
|
+
ageWindow: classified.ageWindow,
|
|
116
|
+
primaryCommand: doctor,
|
|
117
|
+
replayInstallCommand: null,
|
|
118
|
+
lines: [classified.headline, honesty, ` ${doctor}`, BIN_NOTE, AGE_EXCLUDE_LINE],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const doctor = arkPackageRecoveryCommand('arkgate-check', '--doctor');
|
|
122
|
+
return {
|
|
123
|
+
kind: 'generic',
|
|
124
|
+
primaryCommand: installCommand,
|
|
125
|
+
replayInstallCommand: installCommand,
|
|
126
|
+
lines: [...classified.hostTail, honesty, ` ${installCommand}`, ` ${doctor}`, BIN_NOTE],
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Red next-step when post-apply package install fails.
|
|
132
|
+
* Host files may already be written; local bins may be missing.
|
|
133
|
+
* @param {{
|
|
134
|
+
* exitStatus: number,
|
|
135
|
+
* installCommand: string,
|
|
136
|
+
* hostOutput?: string,
|
|
137
|
+
* packageVersion?: string,
|
|
138
|
+
* }} input
|
|
139
|
+
*/
|
|
140
|
+
export function formatStartPackageInstallFailure(input) {
|
|
141
|
+
return startInstallRecovery(input).lines.join('\n');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** Pipe the package manager so recovery can hide maturity internals. */
|
|
145
|
+
export function runStartPackageInstall(command, commandArgs, cwd) {
|
|
146
|
+
const result = spawnSync(command, commandArgs, {
|
|
147
|
+
cwd,
|
|
148
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
149
|
+
encoding: 'utf8',
|
|
150
|
+
});
|
|
151
|
+
return {
|
|
152
|
+
status: result.status ?? 1,
|
|
153
|
+
stdout: result.stdout ?? '',
|
|
154
|
+
stderr: result.stderr ?? '',
|
|
155
|
+
};
|
|
156
|
+
}
|
|
@@ -5,7 +5,6 @@ import os from 'node:os';
|
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import {
|
|
7
7
|
arkCommand,
|
|
8
|
-
arkPackageRecoveryCommand,
|
|
9
8
|
buildArchitectureRecommendation,
|
|
10
9
|
START_APPLY_REFUSE_FOOTER,
|
|
11
10
|
} from '../ark-shared.mjs';
|
|
@@ -218,59 +217,6 @@ function commands(root, args, helpers) {
|
|
|
218
217
|
return result;
|
|
219
218
|
}
|
|
220
219
|
|
|
221
|
-
/**
|
|
222
|
-
* Plain one-liner for pnpm minimumReleaseAge / ERR_PNPM_NO_MATURE_MATCHING_VERSION.
|
|
223
|
-
* Host dumps stay out of the recovery — stranger needs one next step.
|
|
224
|
-
*/
|
|
225
|
-
export function explainPnpmMaturityBlock(hostOutput) {
|
|
226
|
-
const text = String(hostOutput ?? '');
|
|
227
|
-
if (!/ERR_PNPM_NO_MATURE_MATCHING_VERSION|minimumReleaseAge/i.test(text)) return null;
|
|
228
|
-
const days = text.match(/(\d+)\s*days?/i)?.[1];
|
|
229
|
-
const window = days ? `${days} days` : 'a cooling-off window';
|
|
230
|
-
return `This repo blocks packages younger than ${window} — pin an older release or exclude arkgate temporarily.`;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
/** Pipe the package manager so recovery can hide maturity internals. */
|
|
234
|
-
export function runStartPackageInstall(command, commandArgs, cwd) {
|
|
235
|
-
const result = spawnSync(command, commandArgs, {
|
|
236
|
-
cwd,
|
|
237
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
238
|
-
encoding: 'utf8',
|
|
239
|
-
});
|
|
240
|
-
return {
|
|
241
|
-
status: result.status ?? 1,
|
|
242
|
-
stdout: result.stdout ?? '',
|
|
243
|
-
stderr: result.stderr ?? '',
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
/**
|
|
248
|
-
* Red next-step when post-apply package install fails.
|
|
249
|
-
* Host files may already be written; local bins may be missing.
|
|
250
|
-
*/
|
|
251
|
-
export function formatStartPackageInstallFailure({ exitStatus, installCommand, hostOutput }) {
|
|
252
|
-
const doctor = arkPackageRecoveryCommand('arkgate-check', '--doctor');
|
|
253
|
-
const maturity = explainPnpmMaturityBlock(hostOutput);
|
|
254
|
-
const lines = [];
|
|
255
|
-
if (maturity) {
|
|
256
|
-
lines.push(maturity);
|
|
257
|
-
} else if (hostOutput && String(hostOutput).trim()) {
|
|
258
|
-
const tail = String(hostOutput)
|
|
259
|
-
.split('\n')
|
|
260
|
-
.map((line) => line.trimEnd())
|
|
261
|
-
.filter((line) => line.trim())
|
|
262
|
-
.slice(-6);
|
|
263
|
-
if (tail.length) lines.push(...tail);
|
|
264
|
-
}
|
|
265
|
-
lines.push(
|
|
266
|
-
`Package install failed (exit ${exitStatus}). Setup files are written; the local command is not installed yet.`,
|
|
267
|
-
` ${installCommand}`,
|
|
268
|
-
` ${doctor}`,
|
|
269
|
-
'`arkgate-check` is a command in the arkgate package — not its own npm package.'
|
|
270
|
-
);
|
|
271
|
-
return lines.join('\n');
|
|
272
|
-
}
|
|
273
|
-
|
|
274
220
|
/**
|
|
275
221
|
* @param {object} preview
|
|
276
222
|
* @param {{ applying?: boolean }} [options] when applying=true, do not claim “no files were changed”
|
|
@@ -60,6 +60,8 @@ type ArkConfigRule = {
|
|
|
60
60
|
sharedRoots?: string[];
|
|
61
61
|
/** Directed slice→slice edges the repo declares on purpose. */
|
|
62
62
|
allowedCrossSlice?: ArkConfigCrossSliceEdge[];
|
|
63
|
+
/** When `"deny"`, a declared shared root may not import a slice. */
|
|
64
|
+
sharedImportsSlice?: 'deny';
|
|
63
65
|
};
|
|
64
66
|
type ArkConfigCrossSliceEdge = {
|
|
65
67
|
from: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
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-
|
|
2
|
-
import { A as ArkConfig, c as ArkConfigLoadResult } from './configTypes-
|
|
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-p_fCp6P-.js';
|
|
2
|
+
import { A as ArkConfig, c as ArkConfigLoadResult } from './configTypes-VVknqcTJ.js';
|
|
3
3
|
|
|
4
4
|
/** Versioned public result contract types + JSON Schema (adapter envelope). */
|
|
5
5
|
/**
|
|
@@ -392,7 +392,7 @@ declare function createAdapterResult(input: {
|
|
|
392
392
|
}): CurrentAdapterResult;
|
|
393
393
|
|
|
394
394
|
/** ArkGate library version — single source of truth. */
|
|
395
|
-
declare const version = "4.8.
|
|
395
|
+
declare const version = "4.8.20";
|
|
396
396
|
|
|
397
397
|
/**
|
|
398
398
|
* AI Code Gate (basic).
|
|
@@ -1738,6 +1738,12 @@ type InvariantCoverageEvidence = {
|
|
|
1738
1738
|
description: string;
|
|
1739
1739
|
/** Test file that supplied the `test-title` evidence, when there was one. */
|
|
1740
1740
|
testEvidenceFile?: string;
|
|
1741
|
+
/**
|
|
1742
|
+
* Non-test file that declares `coverage.symbol`. Absent when the name only
|
|
1743
|
+
* appears in an import or a call. ArkGate never runs tests; this path is the
|
|
1744
|
+
* declaration text, not a passing suite.
|
|
1745
|
+
*/
|
|
1746
|
+
symbolEvidenceFile?: string;
|
|
1741
1747
|
/**
|
|
1742
1748
|
* The only covering test found sits outside `coverage.coverageRoots` — the
|
|
1743
1749
|
* places the project declares its runner executes. ArkGate never runs tests,
|