@ankhorage/doctor 0.2.1 → 0.3.0
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 +6 -0
- package/README.md +12 -4
- package/dist/analysis.d.ts +18 -1
- package/dist/analysis.d.ts.map +1 -1
- package/dist/analysis.js +786 -57
- package/dist/analysis.js.map +1 -1
- package/dist/commands.d.ts +2 -2
- package/dist/commands.d.ts.map +1 -1
- package/dist/commands.js +19 -4
- package/dist/commands.js.map +1 -1
- package/dist/diagnostics.d.ts +5 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/readme-usage.js +11 -3
- package/dist/readme-usage.js.map +1 -1
- package/package.json +1 -1
- package/src/analysis.ts +1082 -145
- package/src/commands.ts +22 -5
- package/src/diagnostics.ts +67 -10
- package/src/index.ts +5 -0
- package/src/readme-usage.ts +11 -3
package/src/commands.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AnkhCapabilityId, AnkhCommandDescriptor } from '@ankhorage/contracts/cli';
|
|
2
2
|
|
|
3
|
-
import type { DoctorAnalysisResult, DoctorTargetMode } from './analysis.js';
|
|
3
|
+
import type { DoctorAnalysisResult, DoctorPlannedChange, DoctorTargetMode } from './analysis.js';
|
|
4
4
|
import { analyzeDoctorTarget } from './analysis.js';
|
|
5
5
|
import type { DoctorCommandContext, DoctorCommandRunResult } from './commandContext.js';
|
|
6
6
|
import {
|
|
@@ -64,7 +64,7 @@ export const DOCTOR_COMMANDS = [
|
|
|
64
64
|
path: ['validate'],
|
|
65
65
|
capability: COMMAND_CAPABILITIES.validate,
|
|
66
66
|
mode: 'validate',
|
|
67
|
-
summary: 'Auto-detect
|
|
67
|
+
summary: 'Auto-detect the applicable doctor policy profile and validate a local path.',
|
|
68
68
|
run: runValidateCommand,
|
|
69
69
|
},
|
|
70
70
|
{
|
|
@@ -72,7 +72,7 @@ export const DOCTOR_COMMANDS = [
|
|
|
72
72
|
path: ['fix'],
|
|
73
73
|
capability: COMMAND_CAPABILITIES.fix,
|
|
74
74
|
mode: 'fix',
|
|
75
|
-
summary: '
|
|
75
|
+
summary: 'Build a non-mutating fix plan for deterministic doctor policy violations.',
|
|
76
76
|
run: runFixCommand,
|
|
77
77
|
},
|
|
78
78
|
{
|
|
@@ -226,7 +226,6 @@ async function runFixCommand(
|
|
|
226
226
|
});
|
|
227
227
|
|
|
228
228
|
request.context.writeStdout(renderAnalysisReport('fix', result));
|
|
229
|
-
request.context.writeStdout('No automatic fixes available.\n');
|
|
230
229
|
|
|
231
230
|
return {
|
|
232
231
|
exitCode: countErrorDiagnostics(result.diagnostics) > 0 ? 1 : 0,
|
|
@@ -274,6 +273,7 @@ function renderAnalysisReport(
|
|
|
274
273
|
const lines = [
|
|
275
274
|
`doctor ${commandName}`,
|
|
276
275
|
`target: ${result.targetPath}`,
|
|
276
|
+
`profile: ${result.profile}`,
|
|
277
277
|
`checks: ${result.appliedChecks.length > 0 ? result.appliedChecks.join(', ') : 'none'}`,
|
|
278
278
|
`repoMarkers: ${result.repoMarkers.length > 0 ? result.repoMarkers.join(', ') : 'none'}`,
|
|
279
279
|
'',
|
|
@@ -288,6 +288,19 @@ function renderAnalysisReport(
|
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
|
|
291
|
+
if (commandName === 'fix') {
|
|
292
|
+
lines.push('');
|
|
293
|
+
lines.push('Planned changes:');
|
|
294
|
+
|
|
295
|
+
if (result.plannedChanges.length === 0) {
|
|
296
|
+
lines.push(' none');
|
|
297
|
+
} else {
|
|
298
|
+
for (const change of result.plannedChanges) {
|
|
299
|
+
lines.push(renderPlannedChangeLine(change));
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
291
304
|
const errorCount = countErrorDiagnostics(result.diagnostics);
|
|
292
305
|
const warningCount = countWarningDiagnostics(result.diagnostics);
|
|
293
306
|
|
|
@@ -299,7 +312,11 @@ function renderAnalysisReport(
|
|
|
299
312
|
}
|
|
300
313
|
|
|
301
314
|
function renderDiagnosticLine(diagnostic: DoctorDiagnostic): string {
|
|
302
|
-
return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.code}: ${diagnostic.message}`;
|
|
315
|
+
return ` - ${diagnostic.severity.toUpperCase()} ${diagnostic.ruleId} (${diagnostic.code}): ${diagnostic.message}`;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function renderPlannedChangeLine(change: DoctorPlannedChange): string {
|
|
319
|
+
return ` - ${change.ruleId} [${change.kind}]: ${change.description}`;
|
|
303
320
|
}
|
|
304
321
|
|
|
305
322
|
function renderCommandFailure(commandName: DoctorCommandName, error: unknown): string {
|
package/src/diagnostics.ts
CHANGED
|
@@ -1,26 +1,83 @@
|
|
|
1
1
|
export type DoctorDiagnosticCode =
|
|
2
|
+
| 'field-invalid'
|
|
3
|
+
| 'field-missing'
|
|
2
4
|
| 'invalid-ankh-metadata'
|
|
3
5
|
| 'invalid-package-json'
|
|
4
|
-
| 'missing-
|
|
5
|
-
| 'missing-
|
|
6
|
-
| 'missing-
|
|
7
|
-
| '
|
|
8
|
-
| '
|
|
9
|
-
| 'package-json-missing'
|
|
10
|
-
| 'package-name-missing'
|
|
11
|
-
| 'package-type-missing'
|
|
12
|
-
| 'package-version-missing'
|
|
13
|
-
| 'repo-markers-missing'
|
|
6
|
+
| 'missing-dependency'
|
|
7
|
+
| 'missing-path'
|
|
8
|
+
| 'missing-script'
|
|
9
|
+
| 'provider-source-import-failed'
|
|
10
|
+
| 'provider-source-missing'
|
|
14
11
|
| 'target-not-directory'
|
|
15
12
|
| 'target-not-found'
|
|
16
13
|
| 'unsupported-target';
|
|
17
14
|
|
|
18
15
|
export type DoctorDiagnosticSeverity = 'error' | 'warning';
|
|
16
|
+
export type DoctorPolicyProfile = 'integration-monorepo' | 'public-package' | 'unknown';
|
|
17
|
+
export type DoctorRuleId =
|
|
18
|
+
| 'integration.package.ankh.disallowed'
|
|
19
|
+
| 'integration.package.private.required'
|
|
20
|
+
| 'integration.package.workspaces.required'
|
|
21
|
+
| 'package.ankh.capabilities.match-provider'
|
|
22
|
+
| 'package.ankh.present.valid-shape'
|
|
23
|
+
| 'package.ankh.provider-path.required'
|
|
24
|
+
| 'package.ankh.required-for-provider'
|
|
25
|
+
| 'package.dependencies.changesets.required'
|
|
26
|
+
| 'package.dependencies.devtools.required'
|
|
27
|
+
| 'package.dependencies.paradox.required'
|
|
28
|
+
| 'package.dependencies.types-bun.required'
|
|
29
|
+
| 'package.dependencies.types-node.required'
|
|
30
|
+
| 'package.dependencies.typescript.required'
|
|
31
|
+
| 'package.json.bugs.required'
|
|
32
|
+
| 'package.json.description.required'
|
|
33
|
+
| 'package.json.exports.required'
|
|
34
|
+
| 'package.json.files.required'
|
|
35
|
+
| 'package.json.homepage.required'
|
|
36
|
+
| 'package.json.keywords.required'
|
|
37
|
+
| 'package.json.license.required'
|
|
38
|
+
| 'package.json.name.required'
|
|
39
|
+
| 'package.json.package-manager.bun'
|
|
40
|
+
| 'package.json.package-manager.required'
|
|
41
|
+
| 'package.json.private.public-package-disallowed'
|
|
42
|
+
| 'package.json.publish-config.public'
|
|
43
|
+
| 'package.json.publish-config.required'
|
|
44
|
+
| 'package.json.repository.required'
|
|
45
|
+
| 'package.json.type.module'
|
|
46
|
+
| 'package.json.type.required'
|
|
47
|
+
| 'package.json.version.required'
|
|
48
|
+
| 'package.scripts.build.required'
|
|
49
|
+
| 'package.scripts.changeset-status.required'
|
|
50
|
+
| 'package.scripts.changeset.required'
|
|
51
|
+
| 'package.scripts.docs.required'
|
|
52
|
+
| 'package.scripts.format-check.required'
|
|
53
|
+
| 'package.scripts.format.required'
|
|
54
|
+
| 'package.scripts.knip.required'
|
|
55
|
+
| 'package.scripts.lint-fix.required'
|
|
56
|
+
| 'package.scripts.lint.required'
|
|
57
|
+
| 'package.scripts.test.required'
|
|
58
|
+
| 'package.scripts.typecheck.required'
|
|
59
|
+
| 'package.scripts.version-packages.required'
|
|
60
|
+
| 'provider.commands.match-capabilities'
|
|
61
|
+
| 'provider.commands.match-handlers'
|
|
62
|
+
| 'provider.source.importable'
|
|
63
|
+
| 'provider.source.required'
|
|
64
|
+
| 'repo.changelog.required'
|
|
65
|
+
| 'repo.changeset.required'
|
|
66
|
+
| 'repo.license.required'
|
|
67
|
+
| 'repo.readme.required'
|
|
68
|
+
| 'repo.workflows.required'
|
|
69
|
+
| 'target.package-json.required'
|
|
70
|
+
| 'target.path.directory'
|
|
71
|
+
| 'target.path.exists'
|
|
72
|
+
| 'target.profile.supported'
|
|
73
|
+
| 'target.repo-markers.required';
|
|
19
74
|
|
|
20
75
|
export interface DoctorDiagnostic {
|
|
21
76
|
readonly code: DoctorDiagnosticCode;
|
|
22
77
|
readonly message: string;
|
|
23
78
|
readonly path: string;
|
|
79
|
+
readonly profile: DoctorPolicyProfile;
|
|
80
|
+
readonly ruleId: DoctorRuleId;
|
|
24
81
|
readonly severity: DoctorDiagnosticSeverity;
|
|
25
82
|
}
|
|
26
83
|
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export type {
|
|
2
2
|
DoctorAnalysisRequest,
|
|
3
3
|
DoctorAnalysisResult,
|
|
4
|
+
DoctorFixPlan,
|
|
5
|
+
DoctorPlannedChange,
|
|
6
|
+
DoctorPlannedChangeKind,
|
|
4
7
|
DoctorTargetCheck,
|
|
5
8
|
DoctorTargetMode,
|
|
6
9
|
} from './analysis.js';
|
|
@@ -16,6 +19,8 @@ export type {
|
|
|
16
19
|
DoctorDiagnostic,
|
|
17
20
|
DoctorDiagnosticCode,
|
|
18
21
|
DoctorDiagnosticSeverity,
|
|
22
|
+
DoctorPolicyProfile,
|
|
23
|
+
DoctorRuleId,
|
|
19
24
|
} from './diagnostics.js';
|
|
20
25
|
export {
|
|
21
26
|
DOCTOR_CAPABILITIES,
|
package/src/readme-usage.ts
CHANGED
|
@@ -17,10 +17,18 @@ import { runCli } from './cli.js';
|
|
|
17
17
|
* - `repo`
|
|
18
18
|
* - `package`
|
|
19
19
|
*
|
|
20
|
-
* `doctor#
|
|
20
|
+
* `doctor#2` adds a profile-based policy engine:
|
|
21
21
|
*
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
22
|
+
* - strict `public-package` validation for extracted public package repos
|
|
23
|
+
* - light recognized `integration-monorepo` validation for `ankhorage4`
|
|
24
|
+
* - non-mutating `fix` plans for deterministic mechanical changes only
|
|
25
|
+
*
|
|
26
|
+
* Still deferred:
|
|
27
|
+
*
|
|
28
|
+
* - GitHub checks
|
|
29
|
+
* - CI checks
|
|
30
|
+
* - on-disk `fix --apply`
|
|
31
|
+
* - deeper cross-repo policy enforcement
|
|
24
32
|
*
|
|
25
33
|
* Path handling:
|
|
26
34
|
*
|