@shrkcrft/inspector 0.1.0-alpha.28 → 0.1.0-alpha.30
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/dist/code-intelligence-doctor.d.ts +34 -0
- package/dist/code-intelligence-doctor.d.ts.map +1 -1
- package/dist/code-intelligence-doctor.js +68 -9
- package/dist/doc-references.d.ts +59 -0
- package/dist/doc-references.d.ts.map +1 -0
- package/dist/doc-references.js +190 -0
- package/dist/fuzzy-impact.d.ts.map +1 -1
- package/dist/fuzzy-impact.js +11 -20
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/knowledge-stale.d.ts.map +1 -1
- package/dist/knowledge-stale.js +18 -37
- package/dist/nearest-id.d.ts +30 -0
- package/dist/nearest-id.d.ts.map +1 -0
- package/dist/nearest-id.js +62 -0
- package/dist/policy-registry.d.ts +15 -0
- package/dist/policy-registry.d.ts.map +1 -0
- package/dist/policy-registry.js +64 -0
- package/dist/query-resolver.d.ts.map +1 -1
- package/dist/query-resolver.js +8 -8
- package/dist/reference-registry.d.ts +112 -0
- package/dist/reference-registry.d.ts.map +1 -0
- package/dist/reference-registry.js +239 -0
- package/dist/resolve-project-config.d.ts.map +1 -1
- package/dist/resolve-project-config.js +24 -6
- package/dist/self-config-doctor-v2.d.ts.map +1 -1
- package/dist/self-config-doctor-v2.js +37 -86
- package/dist/self-config-doctor.d.ts.map +1 -1
- package/dist/self-config-doctor.js +20 -37
- package/dist/sharkcraft-inspector.d.ts +13 -1
- package/dist/sharkcraft-inspector.d.ts.map +1 -1
- package/dist/sharkcraft-inspector.js +5 -3
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +10 -20
- package/package.json +17 -17
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { listConstructs, warmConstructCache } from "./construct-registry.js";
|
|
2
|
+
import { listConventions } from "./convention-registry.js";
|
|
3
|
+
import { loadAllContractTemplates } from "./contract-template-registry.js";
|
|
4
|
+
import { listDecisions } from "./decision-records.js";
|
|
5
|
+
import { HELPERS } from "./helper-registry.js";
|
|
6
|
+
import { listMigrationProfilesFromPacks } from "./migration-profile-registry.js";
|
|
7
|
+
import { listPackHelpers } from "./pack-helper-registry.js";
|
|
8
|
+
import { listPlaybooks, warmPlaybookCache } from "./playbook-registry.js";
|
|
9
|
+
import { listPolicyIds, warmPolicyCache } from "./policy-registry.js";
|
|
10
|
+
import { listRegistrationHints } from "./registration-hint-registry.js";
|
|
11
|
+
import { loadScaffoldPatternsFromInspection } from "./scaffold-patterns.js";
|
|
12
|
+
import { listTaskRoutingHints } from "./task-routing-hint-registry.js";
|
|
13
|
+
/**
|
|
14
|
+
* Every kind that resolves against a registry of ids.
|
|
15
|
+
*
|
|
16
|
+
* `command` is deliberately absent: the catalog lives in the CLI package,
|
|
17
|
+
* ABOVE this layer, so it resolves by shape instead of by list. `file` /
|
|
18
|
+
* `directory` / `symbol` / `package` / `url` are not id registries at all.
|
|
19
|
+
*/
|
|
20
|
+
export const ALL_ID_REFERENCE_KINDS = [
|
|
21
|
+
'template',
|
|
22
|
+
'pipeline',
|
|
23
|
+
'playbook',
|
|
24
|
+
'policy',
|
|
25
|
+
'construct',
|
|
26
|
+
'helper',
|
|
27
|
+
'boundary-rule',
|
|
28
|
+
'path-convention',
|
|
29
|
+
'knowledge',
|
|
30
|
+
'rule',
|
|
31
|
+
'decision',
|
|
32
|
+
'convention',
|
|
33
|
+
'contract-template',
|
|
34
|
+
'migration-profile',
|
|
35
|
+
'routing-hint',
|
|
36
|
+
'registration-hint',
|
|
37
|
+
'scaffold-pattern',
|
|
38
|
+
];
|
|
39
|
+
function listIds(reg) {
|
|
40
|
+
if (!reg || typeof reg.list !== 'function')
|
|
41
|
+
return [];
|
|
42
|
+
return (reg.list() ?? []).map((r) => r.id);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Kinds whose ids only exist after an ASYNC load.
|
|
46
|
+
*
|
|
47
|
+
* The resolver is synchronous — a doc linter walks lines, and a lookup set is
|
|
48
|
+
* built once — so these are read from a snapshot that {@link
|
|
49
|
+
* warmReferenceRegistries} fills. An unwarmed snapshot is empty, which reads as
|
|
50
|
+
* "no such id" for every id; {@link emptyReferenceKinds} is the safety net for
|
|
51
|
+
* when a caller forgets.
|
|
52
|
+
*/
|
|
53
|
+
const CACHE_BACKED_KINDS = [
|
|
54
|
+
'playbook',
|
|
55
|
+
'construct',
|
|
56
|
+
'policy',
|
|
57
|
+
'helper',
|
|
58
|
+
'convention',
|
|
59
|
+
'contract-template',
|
|
60
|
+
'migration-profile',
|
|
61
|
+
'routing-hint',
|
|
62
|
+
'registration-hint',
|
|
63
|
+
'scaffold-pattern',
|
|
64
|
+
];
|
|
65
|
+
/** Snapshot of the async-loaded kinds, per project root. */
|
|
66
|
+
const ASYNC_IDS = new Map();
|
|
67
|
+
async function safeIds(load) {
|
|
68
|
+
try {
|
|
69
|
+
return await load();
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// A registry that will not load is its OWN surface's problem to report.
|
|
73
|
+
// Resolution must degrade to "no candidates", never to a crash — but never
|
|
74
|
+
// silently to "your id is wrong" either, which is what the empty-kind guard
|
|
75
|
+
// is for.
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Populate the snapshot the synchronous accessors read.
|
|
81
|
+
*
|
|
82
|
+
* Call this once, from the async layer that owns the inspection, before
|
|
83
|
+
* resolving anything. Without it a correct playbook — or convention, or
|
|
84
|
+
* scaffold pattern — resolves to nothing, which is exactly how a correct id got
|
|
85
|
+
* reported as an error twice.
|
|
86
|
+
*/
|
|
87
|
+
export async function warmReferenceRegistries(inspection) {
|
|
88
|
+
await Promise.all([
|
|
89
|
+
warmPlaybookCache(inspection),
|
|
90
|
+
warmConstructCache(inspection),
|
|
91
|
+
warmPolicyCache(inspection),
|
|
92
|
+
]);
|
|
93
|
+
const [packHelpers, conventions, contractTemplates, migrationProfiles, routingHints, registrationHints, scaffoldPatterns,] = await Promise.all([
|
|
94
|
+
safeIds(async () => (await listPackHelpers(inspection)).map((e) => e.helper.id)),
|
|
95
|
+
safeIds(async () => (await listConventions(inspection)).map((e) => e.convention.id)),
|
|
96
|
+
safeIds(async () => (await loadAllContractTemplates(inspection)).entries.map((e) => e.template.id)),
|
|
97
|
+
safeIds(async () => (await listMigrationProfilesFromPacks(inspection)).map((p) => p.id)),
|
|
98
|
+
safeIds(async () => (await listTaskRoutingHints(inspection)).map((e) => e.hint.id)),
|
|
99
|
+
safeIds(async () => (await listRegistrationHints(inspection)).map((e) => e.hint.id)),
|
|
100
|
+
safeIds(async () => (await loadScaffoldPatternsFromInspection(inspection)).patterns.map((e) => e.pattern.id)),
|
|
101
|
+
]);
|
|
102
|
+
ASYNC_IDS.set(inspection.projectRoot, new Map([
|
|
103
|
+
// Built-in helpers need no load; pack-contributed ones do. The doc
|
|
104
|
+
// resolver used to see only the built-ins (an empty frozen array) while
|
|
105
|
+
// the doctor saw both — a live divergence between the two paths.
|
|
106
|
+
['helper', [...HELPERS.map((h) => h.id), ...packHelpers]],
|
|
107
|
+
['convention', conventions],
|
|
108
|
+
['contract-template', contractTemplates],
|
|
109
|
+
['migration-profile', migrationProfiles],
|
|
110
|
+
['routing-hint', routingHints],
|
|
111
|
+
['registration-hint', registrationHints],
|
|
112
|
+
['scaffold-pattern', scaffoldPatterns],
|
|
113
|
+
]));
|
|
114
|
+
}
|
|
115
|
+
function asyncIds(inspection, kind) {
|
|
116
|
+
return ASYNC_IDS.get(inspection.projectRoot)?.get(kind) ?? [];
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Every registered id of `kind`, for existence checks and for suggesting what
|
|
120
|
+
* an unresolved token might have meant.
|
|
121
|
+
*
|
|
122
|
+
* **The invariant:** each kind reads the SAME source its `list` verb reads.
|
|
123
|
+
* `template` goes through `templateRegistry` because that is what `shrk
|
|
124
|
+
* templates list` prints — not the `templates` array it happens to be built
|
|
125
|
+
* from today, which would agree only until someone filters one of them.
|
|
126
|
+
*/
|
|
127
|
+
export function referenceIdsFor(inspection, kind) {
|
|
128
|
+
switch (kind) {
|
|
129
|
+
case 'template':
|
|
130
|
+
return listIds(inspection.templateRegistry);
|
|
131
|
+
case 'pipeline':
|
|
132
|
+
return listIds(inspection.pipelineRegistry);
|
|
133
|
+
case 'rule':
|
|
134
|
+
return listIds(inspection.ruleService);
|
|
135
|
+
case 'boundary-rule':
|
|
136
|
+
return listIds(inspection.boundaryRegistry);
|
|
137
|
+
case 'path-convention':
|
|
138
|
+
return listIds(inspection.pathService);
|
|
139
|
+
case 'knowledge':
|
|
140
|
+
return inspection.knowledgeEntries.map((k) => k.id);
|
|
141
|
+
case 'decision':
|
|
142
|
+
try {
|
|
143
|
+
return listDecisions(inspection).map((d) => d.id);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
case 'playbook':
|
|
149
|
+
return listPlaybooks(inspection).map((p) => p.id);
|
|
150
|
+
case 'construct':
|
|
151
|
+
return listConstructs(inspection).map((c) => c.id);
|
|
152
|
+
case 'policy':
|
|
153
|
+
// Declarations only — `evaluatePolicy` is the one that RUNS them.
|
|
154
|
+
return listPolicyIds(inspection);
|
|
155
|
+
case 'helper':
|
|
156
|
+
case 'convention':
|
|
157
|
+
case 'contract-template':
|
|
158
|
+
case 'migration-profile':
|
|
159
|
+
case 'routing-hint':
|
|
160
|
+
case 'registration-hint':
|
|
161
|
+
case 'scaffold-pattern':
|
|
162
|
+
return asyncIds(inspection, kind);
|
|
163
|
+
case 'command':
|
|
164
|
+
// The command catalog lives in the CLI package, ABOVE this layer, so it
|
|
165
|
+
// cannot be imported here. `referenceIdExists` keeps the permissive
|
|
166
|
+
// shape check instead of pretending to a list it cannot see.
|
|
167
|
+
return [];
|
|
168
|
+
default:
|
|
169
|
+
// `file` / `directory` / `symbol` / `package` / `url` are not id
|
|
170
|
+
// registries; they resolve against the filesystem or not at all.
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Kinds among `kinds` whose registry is EMPTY in this repo.
|
|
176
|
+
*
|
|
177
|
+
* This is the generalisation of the bug that prompted it: resolving against an
|
|
178
|
+
* empty registry cannot succeed, so every id checked against it is reported
|
|
179
|
+
* wrong — a gate confidently flagging CORRECT usage, which is the fastest way
|
|
180
|
+
* to get a gate switched off. Emptiness is repo-dependent (a project may simply
|
|
181
|
+
* have no playbooks), so it cannot be a config-time error; the caller surfaces
|
|
182
|
+
* it as a loud refusal at run time instead.
|
|
183
|
+
*/
|
|
184
|
+
export function emptyReferenceKinds(inspection, kinds) {
|
|
185
|
+
return kinds.filter((kind) => kind !== 'command' && referenceIdsFor(inspection, kind).length === 0);
|
|
186
|
+
}
|
|
187
|
+
/** True when `kind`'s ids come from an async-populated cache. */
|
|
188
|
+
export function isCacheBackedKind(kind) {
|
|
189
|
+
return CACHE_BACKED_KINDS.includes(kind);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Whether `id` is registered under `kind`.
|
|
193
|
+
*
|
|
194
|
+
* `command` keeps its historical permissiveness: the catalog is not always
|
|
195
|
+
* populated, and a repo citing `shrk gen …` should not be told its own CLI
|
|
196
|
+
* does not exist because an optional catalog was absent.
|
|
197
|
+
*/
|
|
198
|
+
export function referenceIdExists(inspection, kind, id) {
|
|
199
|
+
if (kind === 'command') {
|
|
200
|
+
const catalog = inspection.commandCatalog;
|
|
201
|
+
if (Array.isArray(catalog) && catalog.some((c) => c.id === id))
|
|
202
|
+
return true;
|
|
203
|
+
return id.startsWith('shrk ') || id.startsWith('bun ');
|
|
204
|
+
}
|
|
205
|
+
return referenceIdsFor(inspection, kind).includes(id);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* The union of candidate ids across `kinds`, deduped and sorted.
|
|
209
|
+
*
|
|
210
|
+
* A doc token is checked against several registries at once (a `nge.foo` might
|
|
211
|
+
* be a template OR a playbook), so the suggester needs one pool rather than
|
|
212
|
+
* per-kind lists that would each propose their own nearest miss.
|
|
213
|
+
*/
|
|
214
|
+
export function referenceIdPool(inspection, kinds) {
|
|
215
|
+
const pool = new Set();
|
|
216
|
+
for (const kind of kinds) {
|
|
217
|
+
for (const id of referenceIdsFor(inspection, kind))
|
|
218
|
+
pool.add(id);
|
|
219
|
+
}
|
|
220
|
+
return [...pool].sort();
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Whether `id` is registered under ANY kind.
|
|
224
|
+
*
|
|
225
|
+
* For cross-references that do not name a kind — a search-tuning entry boosts
|
|
226
|
+
* "some id", a decision record relates to "some id". That union used to be
|
|
227
|
+
* hand-written as a chain of `lookups.x.has(id) || lookups.y.has(id) || …`,
|
|
228
|
+
* which is a list that silently goes stale: it omitted policies, decisions and
|
|
229
|
+
* scaffold patterns, so seven of shrk's own correctly-registered ids were
|
|
230
|
+
* reported unknown. Reading the kind list means adding a kind widens the union
|
|
231
|
+
* automatically.
|
|
232
|
+
*/
|
|
233
|
+
export function referenceIdExistsInAnyKind(inspection, id) {
|
|
234
|
+
return ALL_ID_REFERENCE_KINDS.some((kind) => referenceIdsFor(inspection, kind).includes(id));
|
|
235
|
+
}
|
|
236
|
+
/** The kind that accepted `id`, or `undefined` — for "resolved as what?" output. */
|
|
237
|
+
export function referenceKindOf(inspection, id) {
|
|
238
|
+
return ALL_ID_REFERENCE_KINDS.find((kind) => referenceIdsFor(inspection, kind).includes(id));
|
|
239
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-project-config.d.ts","sourceRoot":"","sources":["../src/resolve-project-config.ts"],"names":[],"mappings":"AAwBA,OAAO,
|
|
1
|
+
{"version":3,"file":"resolve-project-config.d.ts","sourceRoot":"","sources":["../src/resolve-project-config.ts"],"names":[],"mappings":"AAwBA,OAAO,EAIL,KAAK,QAAQ,EASb,KAAK,MAAM,EACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAUL,KAAK,YAAY,EAClB,MAAM,kBAAkB,CAAC;AAG1B;;;GAGG;AACH,MAAM,WAAW,sBAAuB,SAAQ,YAAY;IAC1D;;;;;;OAMG;IACH,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;CAC9C;AAkID;;;;;;;GAOG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,QAAQ,CAAC,CAAC,CAuInD"}
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { existsSync } from 'node:fs';
|
|
24
24
|
import * as nodePath from 'node:path';
|
|
25
|
-
import { importModuleViaLoader, ok, } from '@shrkcrft/core';
|
|
26
|
-
import { BaselineRuleSchema, GeneratedArtifactRuleSchema, loadProjectConfig, PolicyRuleSchema, RegistrationIdiomSchema, RegistryDeclarationSchema, ReusePrimitiveSchema, WiringRuleSchema, } from '@shrkcrft/config';
|
|
25
|
+
import { importModuleViaLoader, ok, resolvePlaneExtractors, } from '@shrkcrft/core';
|
|
26
|
+
import { BaselineRuleSchema, DocReferenceRuleSchema, GeneratedArtifactRuleSchema, loadProjectConfig, PolicyRuleSchema, RegistrationIdiomSchema, RegistryDeclarationSchema, ReusePrimitiveSchema, WiringRuleSchema, } from '@shrkcrft/config';
|
|
27
27
|
import { discoverPacks } from '@shrkcrft/packs';
|
|
28
28
|
/**
|
|
29
29
|
* Generic per-plane load + validate + merge. Seeds the merged map from the
|
|
@@ -145,17 +145,35 @@ export async function resolveProjectConfig(cwd) {
|
|
|
145
145
|
const generatedArtifacts = await mergePlane(base.config.generatedArtifacts ?? [], gatherPackContribs(validPacks, 'generatedArtifactFiles'), GeneratedArtifactRuleSchema, (r) => r.id, 'generatedArtifact', diagnostics, (item, packName) => item.regen !== undefined
|
|
146
146
|
? `pack ${packName}: generatedArtifact "${item.id}" declares a \`regen\` command — pack-contributed commands are never auto-run — skipped`
|
|
147
147
|
: undefined);
|
|
148
|
+
// No shell, no writes — a pack may contribute a prose-reference rule freely,
|
|
149
|
+
// unlike the two shell-executing planes above.
|
|
150
|
+
const docReferences = await mergePlane(base.config.docReferences ?? [], gatherPackContribs(validPacks, 'docReferenceFiles'), DocReferenceRuleSchema, (r) => r.id, 'docReference', diagnostics);
|
|
148
151
|
const reusePrimitives = await mergePlane(base.config.reusePrimitives ?? [], gatherPackContribs(validPacks, 'reusePrimitiveFiles'), ReusePrimitiveSchema, (r) => r.symbol, 'reusePrimitive', diagnostics);
|
|
152
|
+
// Pack-contributed elements have NOT been through the loader's `$use`
|
|
153
|
+
// resolution (that ran on the local config only), so resolve the merged
|
|
154
|
+
// planes here. A pack rule referencing an extractor this repo does not
|
|
155
|
+
// declare is DROPPED with a diagnostic — never kept half-resolved, which
|
|
156
|
+
// would read as "a source with no files" and match nothing, i.e. a silent
|
|
157
|
+
// pass. Local rules are already resolved, so every error found here belongs
|
|
158
|
+
// to a pack element by construction.
|
|
159
|
+
const resolvedPlanes = resolvePlaneExtractors({ wiringRules, registries, registrationGraph, baselines }, base.config.extractors);
|
|
160
|
+
const dropped = new Set();
|
|
161
|
+
for (const e of resolvedPlanes.errors) {
|
|
162
|
+
dropped.add(e.path.slice(0, e.path.indexOf(']') + 1));
|
|
163
|
+
diagnostics.push(`${e.path}: ${e.message} — rule skipped`);
|
|
164
|
+
}
|
|
165
|
+
const keep = (items, plane, keyOf) => dropped.size === 0 ? items : items.filter((i) => !dropped.has(`${plane}[${keyOf(i)}]`));
|
|
149
166
|
return ok({
|
|
150
167
|
...base,
|
|
151
168
|
config: {
|
|
152
169
|
...base.config,
|
|
153
|
-
wiringRules,
|
|
154
|
-
registries,
|
|
155
|
-
registrationGraph,
|
|
170
|
+
wiringRules: keep(resolvedPlanes.wiringRules ?? wiringRules, 'wiringRules', (r) => r.id),
|
|
171
|
+
registries: keep(resolvedPlanes.registries ?? registries, 'registries', (r) => r.name),
|
|
172
|
+
registrationGraph: keep(resolvedPlanes.registrationGraph ?? registrationGraph, 'registrationGraph', (r) => r.name),
|
|
156
173
|
policyRules,
|
|
157
|
-
baselines,
|
|
174
|
+
baselines: keep(resolvedPlanes.baselines ?? baselines, 'baselines', (r) => r.id),
|
|
158
175
|
generatedArtifacts,
|
|
176
|
+
docReferences,
|
|
159
177
|
reusePrimitives,
|
|
160
178
|
},
|
|
161
179
|
planeDiagnostics: diagnostics,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self-config-doctor-v2.d.ts","sourceRoot":"","sources":["../src/self-config-doctor-v2.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"self-config-doctor-v2.d.ts","sourceRoot":"","sources":["../src/self-config-doctor-v2.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAEvE,eAAO,MAAM,4BAA4B,qCAAqC,CAAC;AAE/E,oBAAY,oBAAoB;IAC9B,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED;;;GAGG;AACH,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,SAAS,GACT,QAAQ,GACR,UAAU,GACV,UAAU,GACV,UAAU,GACV,QAAQ,GACR,MAAM,GACN,MAAM,GACN,YAAY,GACZ,mBAAmB,GACnB,cAAc,GACd,YAAY,GACZ,UAAU,GACV,SAAS,GACT,mBAAmB,GACnB,mBAAmB,GACnB,MAAM,GACN,QAAQ,GACR,MAAM,GACN,SAAS,CAAC;AAEd;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAC1B,YAAY,GACZ,SAAS,GACT,WAAW,GACX,UAAU,GACV,UAAU,GACV,WAAW,GACX,OAAO,GACP,WAAW,GACX,YAAY,GACZ,SAAS,CAAC;AAEd,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CAChD;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,MAAM,EAAE,OAAO,4BAA4B,CAAC;IACrD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACnD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC7C,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;QAC/C,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KAChD,CAAC,CAAC;IACH,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAymBD,wBAAsB,6BAA6B,CACjD,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,yBAAyB,CAAC,CAyCpC;AAsBD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,yBAAyB,GAAG,MAAM,CA+BtF;AAED,wBAAgB,gCAAgC,CAC9C,MAAM,EAAE,yBAAyB,GAChC,MAAM,CAqBR"}
|
|
@@ -17,14 +17,10 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { existsSync } from 'node:fs';
|
|
19
19
|
import * as nodePath from 'node:path';
|
|
20
|
-
import { listConventions } from "./convention-registry.js";
|
|
21
|
-
import { loadAllContractTemplates } from "./contract-template-registry.js";
|
|
22
|
-
import { listMigrationProfilesFromPacks } from "./migration-profile-registry.js";
|
|
23
|
-
import { listPackHelpers } from "./pack-helper-registry.js";
|
|
24
|
-
import { HELPERS } from "./helper-registry.js";
|
|
25
20
|
import { listTaskRoutingHints } from "./task-routing-hint-registry.js";
|
|
26
21
|
import { listRegistrationHints } from "./registration-hint-registry.js";
|
|
27
22
|
import { listDecisions } from "./decision-records.js";
|
|
23
|
+
import { referenceIdExistsInAnyKind, referenceIdsFor, warmReferenceRegistries, } from "./reference-registry.js";
|
|
28
24
|
import { listPlaybooks } from "./playbook-registry.js";
|
|
29
25
|
import { buildPackContributionsInventory } from "./pack-contributions-inventory.js";
|
|
30
26
|
export const SELF_CONFIG_DOCTOR_V2_SCHEMA = 'sharkcraft.self-config-doctor/v2';
|
|
@@ -35,78 +31,38 @@ export var SelfConfigSeverityV2;
|
|
|
35
31
|
SelfConfigSeverityV2["Error"] = "error";
|
|
36
32
|
})(SelfConfigSeverityV2 || (SelfConfigSeverityV2 = {}));
|
|
37
33
|
async function buildLookupsV2(inspection) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
]);
|
|
51
|
-
const routingHints = new Set((await listTaskRoutingHints(inspection)).map((e) => e.hint.id));
|
|
52
|
-
const registrationHints = new Set((await listRegistrationHints(inspection)).map((e) => e.hint.id));
|
|
53
|
-
let playbooks;
|
|
54
|
-
try {
|
|
55
|
-
const pb = await listPlaybooks(inspection);
|
|
56
|
-
playbooks = new Set(pb.map((p) => p.id));
|
|
57
|
-
}
|
|
58
|
-
catch {
|
|
59
|
-
playbooks = new Set();
|
|
60
|
-
}
|
|
61
|
-
// Policies surface through the pack contributions inventory; the policy
|
|
62
|
-
// engine itself runs side-effects we want to avoid here.
|
|
63
|
-
const policies = new Set();
|
|
64
|
-
try {
|
|
65
|
-
const inv = buildPackContributionsInventory(inspection);
|
|
66
|
-
for (const entry of inv.entriesByKind['policy'] ?? [])
|
|
67
|
-
policies.add(entry.id);
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
// ignore
|
|
71
|
-
}
|
|
72
|
-
const decisions = new Set();
|
|
73
|
-
try {
|
|
74
|
-
for (const d of listDecisions(inspection))
|
|
75
|
-
decisions.add(d.id);
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
// ignore
|
|
79
|
-
}
|
|
80
|
-
// Commands & MCP tools — taken from the catalog / repository commands
|
|
81
|
-
// surface. Best-effort; if registries are absent the sets stay empty and
|
|
82
|
-
// the corresponding checks degrade to info-level.
|
|
83
|
-
const commands = new Set();
|
|
84
|
-
const mcpTools = new Set();
|
|
85
|
-
try {
|
|
86
|
-
const repoCmds = inspection.repositoryCommands;
|
|
87
|
-
for (const c of repoCmds ?? [])
|
|
88
|
-
commands.add(c.id);
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
// ignore
|
|
92
|
-
}
|
|
34
|
+
// Every set is a projection of the SHARED reference registry — the same
|
|
35
|
+
// module the prose linter and the structured-`references[]` validator use.
|
|
36
|
+
//
|
|
37
|
+
// These sets used to be built here from their own sources, and the doc claim
|
|
38
|
+
// "there is one definition of does-this-id-exist, not two" was true only by
|
|
39
|
+
// coincidence. It was not always true: `policies` came from the pack
|
|
40
|
+
// contributions inventory alone, so every LOCALLY declared policy read as
|
|
41
|
+
// unknown; `scaffoldPatterns` had no set at all; `commands` read a
|
|
42
|
+
// `repositoryCommands` property nothing assigns. Seven of shrk's own
|
|
43
|
+
// correctly-registered ids were reported missing.
|
|
44
|
+
await warmReferenceRegistries(inspection);
|
|
45
|
+
const ids = (kind) => new Set(referenceIdsFor(inspection, kind));
|
|
93
46
|
return {
|
|
94
|
-
knowledge,
|
|
95
|
-
rules,
|
|
96
|
-
paths,
|
|
97
|
-
templates,
|
|
98
|
-
pipelines,
|
|
99
|
-
policies,
|
|
100
|
-
playbooks,
|
|
101
|
-
conventions,
|
|
102
|
-
contractTemplates,
|
|
103
|
-
migrationProfiles,
|
|
104
|
-
helpers,
|
|
105
|
-
routingHints,
|
|
106
|
-
registrationHints,
|
|
107
|
-
decisions,
|
|
108
|
-
|
|
109
|
-
|
|
47
|
+
knowledge: ids('knowledge'),
|
|
48
|
+
rules: ids('rule'),
|
|
49
|
+
paths: ids('path-convention'),
|
|
50
|
+
templates: ids('template'),
|
|
51
|
+
pipelines: ids('pipeline'),
|
|
52
|
+
policies: ids('policy'),
|
|
53
|
+
playbooks: ids('playbook'),
|
|
54
|
+
conventions: ids('convention'),
|
|
55
|
+
contractTemplates: ids('contract-template'),
|
|
56
|
+
migrationProfiles: ids('migration-profile'),
|
|
57
|
+
helpers: ids('helper'),
|
|
58
|
+
routingHints: ids('routing-hint'),
|
|
59
|
+
registrationHints: ids('registration-hint'),
|
|
60
|
+
decisions: ids('decision'),
|
|
61
|
+
scaffoldPatterns: ids('scaffold-pattern'),
|
|
62
|
+
// The catalog lives in the CLI package, above this layer. `command`
|
|
63
|
+
// resolves by SHAPE in the shared registry rather than by a list this
|
|
64
|
+
// layer cannot see.
|
|
65
|
+
commands: new Set(),
|
|
110
66
|
};
|
|
111
67
|
}
|
|
112
68
|
function findingId(parts) {
|
|
@@ -169,16 +125,11 @@ async function checkSearchTuning(inspection, lookups, findings) {
|
|
|
169
125
|
if (!idMap)
|
|
170
126
|
continue;
|
|
171
127
|
for (const targetId of Object.keys(idMap)) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
lookups.conventions.has(targetId) ||
|
|
178
|
-
lookups.playbooks.has(targetId) ||
|
|
179
|
-
lookups.helpers.has(targetId) ||
|
|
180
|
-
lookups.commands.has(targetId);
|
|
181
|
-
if (found)
|
|
128
|
+
// Not a hand-maintained chain of `lookups.x.has(...)`: that list
|
|
129
|
+
// silently omitted policies, decisions and scaffold patterns, so ids
|
|
130
|
+
// that WERE registered got reported as unknown. Adding a kind to the
|
|
131
|
+
// registry now widens this automatically.
|
|
132
|
+
if (referenceIdExistsInAnyKind(inspection, targetId))
|
|
182
133
|
continue;
|
|
183
134
|
pushFinding(findings, {
|
|
184
135
|
severity: SelfConfigSeverityV2.Warning,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"self-config-doctor.d.ts","sourceRoot":"","sources":["../src/self-config-doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"self-config-doctor.d.ts","sourceRoot":"","sources":["../src/self-config-doctor.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAOvE,eAAO,MAAM,yBAAyB,qCAAqC,CAAC;AAE5E,oBAAY,kBAAkB;IAC5B,IAAI,SAAS;IACb,OAAO,YAAY;IACnB,KAAK,UAAU;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,MAAM,EAAE,OAAO,yBAAyB,CAAC;IAClD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,EAAE,EAAE,oBAAoB,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,iCAAiC,CAAC;IACnD,QAAQ,CAAC,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAChD,QAAQ,CAAC,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,SAAS,oBAAoB,EAAE,CAAC;CACvD;AA2TD,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,uBAAuB,CAAC,CAsClC;AAED,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,qBAAqB,GAChC,OAAO,CAAC,gBAAgB,CAAC,CAuC3B;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAyBlF;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,uBAAuB,GAAG,MAAM,CAoBtF"}
|
|
@@ -13,12 +13,8 @@
|
|
|
13
13
|
import { existsSync } from 'node:fs';
|
|
14
14
|
import * as nodePath from 'node:path';
|
|
15
15
|
import { buildPackContributionsInventory } from "./pack-contributions-inventory.js";
|
|
16
|
-
import { listConventions } from "./convention-registry.js";
|
|
17
|
-
import { loadAllContractTemplates } from "./contract-template-registry.js";
|
|
18
|
-
import { listMigrationProfilesFromPacks } from "./migration-profile-registry.js";
|
|
19
|
-
import { listPackHelpers } from "./pack-helper-registry.js";
|
|
20
16
|
import { listTaskRoutingHints } from "./task-routing-hint-registry.js";
|
|
21
|
-
import {
|
|
17
|
+
import { referenceIdsFor, warmReferenceRegistries, } from "./reference-registry.js";
|
|
22
18
|
export const SELF_CONFIG_DOCTOR_SCHEMA = 'sharkcraft.self-config-doctor/v1';
|
|
23
19
|
export var SelfConfigSeverity;
|
|
24
20
|
(function (SelfConfigSeverity) {
|
|
@@ -26,40 +22,27 @@ export var SelfConfigSeverity;
|
|
|
26
22
|
SelfConfigSeverity["Warning"] = "warning";
|
|
27
23
|
SelfConfigSeverity["Error"] = "error";
|
|
28
24
|
})(SelfConfigSeverity || (SelfConfigSeverity = {}));
|
|
25
|
+
/**
|
|
26
|
+
* Every set is a projection of the SHARED reference registry.
|
|
27
|
+
*
|
|
28
|
+
* This used to build its own sets from its own sources, and carried eleven more
|
|
29
|
+
* fields that nothing read — nine of them hardcoded `new Set()`, so any check
|
|
30
|
+
* that had started using one would have reported every correct id as unknown.
|
|
31
|
+
* The v2 doctor made exactly that mistake with `policies` and `commands`.
|
|
32
|
+
*/
|
|
29
33
|
async function buildLookups(inspection) {
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const paths = new Set((inspection.pathService?.list?.() ?? []).map((p) => p.id));
|
|
33
|
-
const templates = new Set(inspection.templateRegistry?.list?.().map((t) => t.id) ?? []);
|
|
34
|
-
const pipelines = new Set(inspection.pipelineRegistry?.list?.().map((p) => p.id) ?? []);
|
|
35
|
-
// Convention/profile/contract registries return entries asynchronously.
|
|
36
|
-
const conventions = new Set((await listConventions(inspection)).map((e) => e.convention.id));
|
|
37
|
-
const contractTemplatesPair = await loadAllContractTemplates(inspection);
|
|
38
|
-
const contractTemplates = new Set(contractTemplatesPair.entries.map((e) => e.template.id));
|
|
39
|
-
const migrationProfiles = new Set((await listMigrationProfilesFromPacks(inspection)).map((p) => p.id));
|
|
40
|
-
const helpers = new Set((await listPackHelpers(inspection)).map((e) => e.helper.id));
|
|
41
|
-
const routingHints = new Set((await listTaskRoutingHints(inspection)).map((e) => e.hint.id));
|
|
42
|
-
const registrationHints = new Set((await listRegistrationHints(inspection)).map((e) => e.hint.id));
|
|
34
|
+
await warmReferenceRegistries(inspection);
|
|
35
|
+
const ids = (kind) => new Set(referenceIdsFor(inspection, kind));
|
|
43
36
|
return {
|
|
44
|
-
knowledge,
|
|
45
|
-
rules,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
scaffoldPatterns: new Set(),
|
|
54
|
-
conventions,
|
|
55
|
-
contractTemplates,
|
|
56
|
-
migrationProfiles,
|
|
57
|
-
helpers,
|
|
58
|
-
routingHints,
|
|
59
|
-
registrationHints,
|
|
60
|
-
commands: new Set(),
|
|
61
|
-
mcpTools: new Set(),
|
|
62
|
-
files: new Set(),
|
|
37
|
+
knowledge: ids('knowledge'),
|
|
38
|
+
rules: ids('rule'),
|
|
39
|
+
templates: ids('template'),
|
|
40
|
+
pipelines: ids('pipeline'),
|
|
41
|
+
conventions: ids('convention'),
|
|
42
|
+
contractTemplates: ids('contract-template'),
|
|
43
|
+
migrationProfiles: ids('migration-profile'),
|
|
44
|
+
helpers: ids('helper'),
|
|
45
|
+
registrationHints: ids('registration-hint'),
|
|
63
46
|
};
|
|
64
47
|
}
|
|
65
48
|
function addFinding(out, finding) {
|
|
@@ -9,6 +9,7 @@ import { type IPackDiscoveryResult } from '@shrkcrft/packs';
|
|
|
9
9
|
import { PresetRegistry } from '@shrkcrft/presets';
|
|
10
10
|
import { BoundaryRegistry } from '@shrkcrft/boundaries';
|
|
11
11
|
import { type IDoctorResult } from './doctor-result.js';
|
|
12
|
+
import { type IGraphDivergence } from './code-intelligence-doctor.js';
|
|
12
13
|
import { type ILoaderDiagnostic } from './loader-diagnostics.js';
|
|
13
14
|
/**
|
|
14
15
|
* Find SharkCraft packs that live IN the repo but are not discovered (i.e.
|
|
@@ -83,5 +84,16 @@ export interface InspectOptions {
|
|
|
83
84
|
onLoaderDiagnostic?: (d: ILoaderDiagnostic) => void;
|
|
84
85
|
}
|
|
85
86
|
export declare function inspectSharkcraft(options?: InspectOptions): Promise<ISharkcraftInspection>;
|
|
86
|
-
|
|
87
|
+
/** Inputs `runDoctor` cannot compute from this layer. */
|
|
88
|
+
export interface IRunDoctorOptions {
|
|
89
|
+
/**
|
|
90
|
+
* Working-tree divergence of the graph index, from `@shrkcrft/graph`'s
|
|
91
|
+
* `detectGraphFreshness`. Callers above the graph layer (cli, mcp-server)
|
|
92
|
+
* pass it so the code-intelligence checks report a divergence-checked
|
|
93
|
+
* verdict; without it those checks say "not verified" rather than guessing
|
|
94
|
+
* freshness from a timestamp.
|
|
95
|
+
*/
|
|
96
|
+
graphDivergence?: IGraphDivergence;
|
|
97
|
+
}
|
|
98
|
+
export declare function runDoctor(inspection: ISharkcraftInspection, options?: IRunDoctorOptions): IDoctorResult;
|
|
87
99
|
//# sourceMappingURL=sharkcraft-inspector.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sharkcraft-inspector.d.ts","sourceRoot":"","sources":["../src/sharkcraft-inspector.ts"],"names":[],"mappings":"AAOA,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,KAAK,iBAAiB,EAAqB,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,yBAAyB,EAC9B,cAAc,EAIf,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,KAAK,mBAAmB,EAAyB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAAE,KAAK,mBAAmB,EAAyB,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxG,OAAO,EAAiB,KAAK,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAwC,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAA6B,MAAM,sBAAsB,CAAC;AACnF,OAAO,EAAqC,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"sharkcraft-inspector.d.ts","sourceRoot":"","sources":["../src/sharkcraft-inspector.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ import { BUILTIN_PRESETS, loadPresetsFromFile, PresetRegistry } from '@shrkcrft/
|
|
|
13
13
|
import { BoundaryRegistry, loadBoundaryRulesFromFile } from '@shrkcrft/boundaries';
|
|
14
14
|
import { DoctorSeverity } from "./doctor-result.js";
|
|
15
15
|
import { diagnoseActionHints } from "./action-hint-diagnostics.js";
|
|
16
|
-
import { buildCodeIntelligenceChecks } from "./code-intelligence-doctor.js";
|
|
16
|
+
import { buildCodeIntelligenceChecks, } from "./code-intelligence-doctor.js";
|
|
17
17
|
import { loadSearchTuning } from "./search-tuning-registry.js";
|
|
18
18
|
import { buildDelegateRecipeChecks } from "./delegate-doctor.js";
|
|
19
19
|
import { computeFileFingerprint, createInspectorCache, } from "./inspector-cache.js";
|
|
@@ -608,7 +608,7 @@ export async function inspectSharkcraft(options = {}) {
|
|
|
608
608
|
}
|
|
609
609
|
return inspection;
|
|
610
610
|
}
|
|
611
|
-
export function runDoctor(inspection) {
|
|
611
|
+
export function runDoctor(inspection, options = {}) {
|
|
612
612
|
const checks = [];
|
|
613
613
|
if (!inspection.workspace.hasPackageJson) {
|
|
614
614
|
checks.push({
|
|
@@ -825,7 +825,9 @@ export function runDoctor(inspection) {
|
|
|
825
825
|
// quality-gates, migrations). Each finding reads a stable on-disk
|
|
826
826
|
// state file under `.sharkcraft/` and stays silent when the user has
|
|
827
827
|
// not opted into the relevant feature.
|
|
828
|
-
for (const c of buildCodeIntelligenceChecks(inspection.projectRoot
|
|
828
|
+
for (const c of buildCodeIntelligenceChecks(inspection.projectRoot, {
|
|
829
|
+
...(options.graphDivergence ? { graphDivergence: options.graphDivergence } : {}),
|
|
830
|
+
})) {
|
|
829
831
|
checks.push(c);
|
|
830
832
|
}
|
|
831
833
|
// Delegate-worker recipe health: surface any recipe that isn't safely
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"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"}
|