arkgate 4.8.23 → 4.8.25
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 +153 -0
- package/README.md +7 -5
- package/bin/ark-check-runtime.mjs +41 -91
- package/bin/ark-dashboard.mjs +56 -53
- package/bin/ark-layer-match.mjs +707 -121
- package/bin/ark-mcp-runtime.mjs +448 -169
- package/bin/ark-mcp.mjs +68 -4
- package/bin/ark-shared.mjs +42 -22
- package/bin/ark.mjs +65 -97
- package/bin/lib/adapter-contract-types.mjs +5 -0
- package/bin/lib/adapter-contract.mjs +15 -0
- package/bin/lib/adoption-stance.mjs +2 -2
- package/bin/lib/adr-path.mjs +3 -3
- package/bin/lib/agent-gates.mjs +0 -61
- package/bin/lib/agent-homes.mjs +12 -21
- package/bin/lib/agent-projection-command.mjs +9 -5
- package/bin/lib/ambient-state.mjs +9 -30
- package/bin/lib/analysis-engine.mjs +15 -11
- package/bin/lib/architecture-scan.mjs +61 -15
- package/bin/lib/ark-order-doctor.mjs +4 -29
- package/bin/lib/ark-order-facts.mjs +319 -17
- package/bin/lib/ark-order-sensors.mjs +28 -101
- package/bin/lib/ark-order-types.mjs +3 -2
- package/bin/lib/ark-run-doctor.mjs +17 -28
- package/bin/lib/ark-run-facts.mjs +461 -48
- package/bin/lib/ark-run-sensors.mjs +6 -4
- package/bin/lib/arkgate-pins.mjs +91 -0
- package/bin/lib/arkrule-file-hints.mjs +2 -47
- package/bin/lib/arkrules-contract.mjs +124 -133
- package/bin/lib/arkrules-sensors.mjs +55 -252
- package/bin/lib/check-args.mjs +85 -1
- package/bin/lib/ci-and-commands.mjs +24 -78
- package/bin/lib/ci-merge-boundary.mjs +1 -1
- package/bin/lib/class-source-scan.mjs +479 -0
- package/bin/lib/clone-detection.mjs +474 -0
- package/bin/lib/codex-home.mjs +5 -3
- package/bin/lib/config-contract-slices.mjs +739 -0
- package/bin/lib/config-contract.mjs +42 -607
- package/bin/lib/config-extras.mjs +16 -22
- package/bin/lib/config-warnings.mjs +32 -0
- package/bin/lib/contract-smells.mjs +33 -15
- package/bin/lib/core-ratchet.mjs +0 -2
- package/bin/lib/dashboard-cli.mjs +62 -0
- package/bin/lib/deep-module-coach.mjs +2 -4
- package/bin/lib/deploy-path.mjs +13 -38
- package/bin/lib/design-delta.mjs +1 -1
- package/bin/lib/design-smells.mjs +2 -2
- package/bin/lib/diagnostic-catalog.mjs +23 -9
- package/bin/lib/doctor-advisories.mjs +78 -8
- package/bin/lib/doctor-green-cite.mjs +1 -1
- package/bin/lib/doctor-human.mjs +1 -1
- package/bin/lib/doctor-next-actions.mjs +19 -4
- package/bin/lib/doctor-plan.mjs +9 -13
- package/bin/lib/duplication-io.mjs +572 -0
- package/bin/lib/effective-contract-load.mjs +282 -83
- package/bin/lib/enforcement-profiles.mjs +40 -4
- package/bin/lib/entry-points-io.mjs +424 -0
- package/bin/lib/extra-merge-teeth.mjs +36 -0
- package/bin/lib/field-install.mjs +38 -14
- package/bin/lib/first-run-help.mjs +10 -5
- package/bin/lib/flat-parent-importers.mjs +139 -0
- package/bin/lib/flat-parent-pilot.mjs +40 -100
- package/bin/lib/gate-files.mjs +58 -90
- package/bin/lib/git-change-scope.mjs +109 -0
- package/bin/lib/github-enforcement.mjs +166 -29
- package/bin/lib/golden-pattern.mjs +1 -1
- package/bin/lib/hook-templates.mjs +17 -15
- package/bin/lib/host-support-matrix.mjs +3 -1
- package/bin/lib/html-report-advisories.mjs +4 -0
- package/bin/lib/html-report-depth.mjs +2 -2
- package/bin/lib/html-report.mjs +2 -2
- package/bin/lib/import-graph-projection.mjs +112 -0
- package/bin/lib/import-resolve.mjs +13 -1
- package/bin/lib/improvement-compass-doctor.mjs +1 -24
- package/bin/lib/install-migrate.mjs +50 -73
- package/bin/lib/invariant-coverage-io.mjs +4 -3
- package/bin/lib/invariant-coverage.mjs +85 -11
- package/bin/lib/invariant-probe-cli.mjs +347 -0
- package/bin/lib/invariant-probe-io.mjs +165 -0
- package/bin/lib/invariant-probe-runner.mjs +268 -0
- package/bin/lib/invariant-probe-sites.mjs +174 -0
- package/bin/lib/invariant-probe-workspace.mjs +183 -0
- package/bin/lib/invariant-probe.mjs +461 -0
- package/bin/lib/invariant-tests-path.mjs +16 -22
- package/bin/lib/literal-path-drift.mjs +4 -2
- package/bin/lib/managed-upgrade.mjs +2 -8
- package/bin/lib/mcp-adoption.mjs +13 -6
- package/bin/lib/mcp-hook-payload.mjs +403 -63
- package/bin/lib/orphan-modules-io.mjs +458 -0
- package/bin/lib/orphan-modules.mjs +251 -0
- package/bin/lib/outside-importers.mjs +197 -0
- package/bin/lib/package-manager.mjs +60 -2
- package/bin/lib/parse-health.mjs +1 -1
- package/bin/lib/passthrough-commands.mjs +83 -0
- package/bin/lib/persistence-write-hint.mjs +106 -0
- package/bin/lib/pin-dependent-gates.mjs +117 -0
- package/bin/lib/policy-delta-io.mjs +219 -14
- package/bin/lib/post-green-path.mjs +1 -1
- package/bin/lib/prepare-change.mjs +115 -7
- package/bin/lib/prepare-write.mjs +2 -2
- package/bin/lib/presets.mjs +59 -73
- package/bin/lib/product-copy.mjs +1 -6
- package/bin/lib/project-root.mjs +31 -62
- package/bin/lib/remediation.mjs +23 -4
- package/bin/lib/resolved-candidate-facts.mjs +405 -117
- package/bin/lib/rules-inventory.mjs +22 -3
- package/bin/lib/rules-under-contract.mjs +247 -9
- package/bin/lib/scan-files.mjs +36 -4
- package/bin/lib/schema-validation.mjs +130 -0
- package/bin/lib/sensor-promote-cli.mjs +2 -11
- package/bin/lib/sensor-promote-io.mjs +33 -22
- package/bin/lib/sensor-promotion.mjs +1 -1
- package/bin/lib/skill-catalog-apply.mjs +1 -1
- package/bin/lib/skill-install.mjs +42 -38
- package/bin/lib/snippet-analysis.mjs +140 -6
- package/bin/lib/source-policy.mjs +34 -0
- package/bin/lib/start-install-recovery.mjs +72 -2
- package/bin/lib/start-preview.mjs +31 -1
- package/bin/lib/states-transitions-presence.mjs +3 -3
- package/bin/lib/status-command.mjs +35 -22
- package/bin/lib/status-manifest.mjs +50 -30
- package/bin/lib/status-transition-catalog.mjs +0 -6
- package/bin/lib/suggestions.mjs +3 -3
- package/bin/lib/team-parliament-io.mjs +76 -88
- package/bin/lib/team-parliament.mjs +21 -10
- package/bin/lib/upgrade-behavior-changes.mjs +2 -2
- package/bin/lib/upgrade-command.mjs +2 -24
- package/bin/lib/upgrade-outcome.mjs +1 -1
- package/bin/lib/upstream-report.mjs +21 -10
- package/bin/lib/violations.mjs +10 -9
- package/bin/lib/weakest-link.mjs +13 -0
- package/bin/lib/write-path-capabilities.mjs +6 -4
- package/dist/chunk-A5EIY3HI.cjs +5 -0
- package/dist/chunk-AHACEKSV.js +16 -0
- package/dist/chunk-SVSQVGFJ.js +5 -0
- package/dist/chunk-UN5EH4QV.cjs +16 -0
- package/dist/{configTypes-Bbf_MFGe.d.ts → configTypes-GPvvdleM.d.cts} +30 -4
- package/dist/configTypes-GPvvdleM.d.ts +257 -0
- package/dist/eslint/index.cjs +18 -5
- package/dist/eslint/index.d.cts +368 -0
- package/dist/eslint/index.d.ts +139 -156
- package/dist/eslint/index.js +11 -5
- package/dist/index.cjs +36 -35
- package/dist/index.d.cts +5547 -0
- package/dist/index.d.ts +3283 -198
- package/dist/index.js +36 -35
- package/dist/inspectorListen-6DQVJ4DC.js +1 -0
- package/dist/inspectorListen-KGMIQ2TF.cjs +1 -0
- package/dist/nestjs/index.cjs +1 -18
- package/dist/nestjs/index.d.cts +22 -0
- package/dist/nestjs/index.d.ts +1 -3
- package/dist/nestjs/index.js +1 -18
- package/dist/order/index.cjs +1 -1
- package/dist/order/index.d.cts +155 -0
- package/dist/order/index.d.ts +15 -3
- package/dist/order/index.js +1 -1
- package/dist/runtime/index.cjs +13 -30
- package/dist/{diagnosticCatalog-35mrwAHe.d.ts → runtime/index.d.cts} +828 -276
- package/dist/runtime/index.d.ts +2741 -133
- package/dist/runtime/index.js +13 -30
- package/dist/{types-Bdj32QwA.d.ts → types-CnauMQQL.d.cts} +607 -163
- package/dist/types-CnauMQQL.d.ts +1800 -0
- package/docs/README.md +3 -1
- package/docs/agent-guide.md +217 -16
- package/docs/ai-gates.md +174 -26
- package/docs/arkorder.md +32 -15
- package/docs/brownfield-adoption.md +5 -1
- package/docs/configuration.md +230 -31
- package/docs/develop.md +2 -1
- package/docs/diagnostics.md +212 -19
- package/docs/package-surface.md +35 -9
- package/docs/product-voice.md +7 -1
- package/package.json +69 -19
- package/schemas/ark.analysis-result.schema.json +15 -0
- package/schemas/ark.config.schema.json +77 -12
- package/schemas/ark.invariant-probe.schema.json +368 -0
- package/schemas/ark.resolved-candidate-facts.schema.json +1 -1
- package/schemas/ark.status-manifest.schema.json +22 -0
- package/server.json +3 -9
- package/templates/agent-skills/README.md +1 -1
- package/templates/agent-skills/ark-adopt/SKILL.md +5 -1
- package/templates/agent-skills/ark-contract/SKILL.md +17 -0
- package/templates/agent-skills/ark-coverage/SKILL.md +2 -0
- package/templates/agent-skills/ark-explore/SKILL.md +7 -0
- package/templates/agent-skills/ark-fix/SKILL.md +20 -0
- package/templates/agent-skills/ark-order/SKILL.md +4 -2
- package/templates/agent-skills/ark-place/SKILL.md +8 -0
- package/templates/agent-skills/ark-runtime/SKILL.md +6 -1
- package/templates/arkrules/PersistenceAdapters.json +1 -1
- package/templates/arkrules/PresentationAdapters.json +1 -1
- package/templates/skills/ark-adopt.md +5 -1
- package/templates/skills/ark-contract.md +17 -0
- package/templates/skills/ark-coverage.md +2 -0
- package/templates/skills/ark-explore.md +7 -0
- package/templates/skills/ark-fix.md +20 -0
- package/templates/skills/ark-order.md +4 -2
- package/templates/skills/ark-place.md +8 -0
- package/templates/skills/ark-runtime.md +6 -1
- package/bin/lib/ark-order-error.mjs +0 -18
- package/bin/lib/ark-order-invariants.mjs +0 -346
- package/dist/types-Ik_OakcI.d.ts +0 -183
|
@@ -19,6 +19,15 @@ import {
|
|
|
19
19
|
} from './reshape-decisions.mjs';
|
|
20
20
|
import { printParseHealthSection, summarizeParseHealth } from './parse-health.mjs';
|
|
21
21
|
import { detectGraphBlindSpots, printGraphBlindSection } from './graph-blind.mjs';
|
|
22
|
+
import {
|
|
23
|
+
computeOrphanModules,
|
|
24
|
+
printOrphanModulesCompactLine,
|
|
25
|
+
printOrphanModulesSection,
|
|
26
|
+
} from './orphan-modules-io.mjs';
|
|
27
|
+
import {
|
|
28
|
+
computeCrossWallDuplication,
|
|
29
|
+
printCrossWallDuplicationSection,
|
|
30
|
+
} from './duplication-io.mjs';
|
|
22
31
|
import {
|
|
23
32
|
formatArkRulesDoctorLines,
|
|
24
33
|
summarizeRulesUnderContract,
|
|
@@ -38,7 +47,12 @@ import {
|
|
|
38
47
|
} from './ark-order-doctor.mjs';
|
|
39
48
|
import { composeMergePlanesHonesty } from './extra-merge-teeth.mjs';
|
|
40
49
|
import { collectPrototypeShortcutsResidual } from './prototype-shortcuts.mjs';
|
|
41
|
-
import {
|
|
50
|
+
import {
|
|
51
|
+
crossParentViaSharedHubs,
|
|
52
|
+
sliceAliasReport,
|
|
53
|
+
sliceCountReport,
|
|
54
|
+
sliceIdentityCollisions,
|
|
55
|
+
} from '../ark-layer-match.mjs';
|
|
42
56
|
|
|
43
57
|
export function attachExtraDoctorSections(rulesUnderContract, config, classification, findings) {
|
|
44
58
|
const arkRulesMerge = {
|
|
@@ -57,6 +71,7 @@ export function attachExtraDoctorSections(rulesUnderContract, config, classifica
|
|
|
57
71
|
findings,
|
|
58
72
|
classification,
|
|
59
73
|
arkRules: arkRulesMerge,
|
|
74
|
+
layerFlow: { layers: config?.layers, rules: config?.rules },
|
|
60
75
|
});
|
|
61
76
|
const arkOrder = summarizeArkOrderSection({
|
|
62
77
|
arkOrder: config?.arkOrder,
|
|
@@ -137,6 +152,7 @@ export function printCompactExtraDoctorLines(advisories, io) {
|
|
|
137
152
|
io.line(io.warn, flatMoves[0].evidence);
|
|
138
153
|
if (flatMoves.length > 1) io.line(' ', `${flatMoves.length - 1} more flat-parent suggestion(s) in --doctor --all`);
|
|
139
154
|
}
|
|
155
|
+
printOrphanModulesCompactLine(advisories?.orphanModules, io);
|
|
140
156
|
const noDomain = advisories?.noDomainFrontend;
|
|
141
157
|
if (noDomain?.ask) {
|
|
142
158
|
console.log('');
|
|
@@ -231,8 +247,13 @@ function classificationFromCoverage(cov) {
|
|
|
231
247
|
};
|
|
232
248
|
}
|
|
233
249
|
|
|
234
|
-
/**
|
|
235
|
-
|
|
250
|
+
/**
|
|
251
|
+
* `activeViolations` must already exclude frozen baseline keys (report residual parity).
|
|
252
|
+
* `facts.importGraph` is the scan's importer index; `view.details` (Details / report) adds
|
|
253
|
+
* the unused-exports tier and copies across a wall. `view.changed` (a changed-files scope)
|
|
254
|
+
* keeps copies across a wall `not-run`.
|
|
255
|
+
*/
|
|
256
|
+
export function computeDoctorAdvisories(root, config, cov, rules, files, ts, parseHealth, facts, activeViolations, view = {}) {
|
|
236
257
|
const physicalCohesion = computePhysicalCohesion(root, files);
|
|
237
258
|
const decisionMemory = computeReshapeDecisionMemory(root, files);
|
|
238
259
|
physicalCohesion.reshapeDecisions = decisionMemory.summary;
|
|
@@ -289,6 +310,7 @@ export function computeDoctorAdvisories(root, config, cov, rules, files, ts, par
|
|
|
289
310
|
});
|
|
290
311
|
const sliceIdentityHits = sliceIdentityCollisions(rules ?? config?.rules);
|
|
291
312
|
const slices = sliceCountReport(activeViolations);
|
|
313
|
+
const sharedWalkHubs = crossParentViaSharedHubs(activeViolations);
|
|
292
314
|
const aliasFiles = [];
|
|
293
315
|
for (const entry of Array.isArray(files) ? files : []) {
|
|
294
316
|
const rel = aliasScanPath(root, entry);
|
|
@@ -300,9 +322,12 @@ export function computeDoctorAdvisories(root, config, cov, rules, files, ts, par
|
|
|
300
322
|
files: aliasFiles,
|
|
301
323
|
rules: rules ?? config?.rules,
|
|
302
324
|
layers: config?.layers,
|
|
325
|
+
facts,
|
|
326
|
+
ts,
|
|
303
327
|
});
|
|
304
328
|
return {
|
|
305
329
|
...(slices ? { slices } : {}),
|
|
330
|
+
...(sharedWalkHubs ? { sharedWalkHubs } : {}),
|
|
306
331
|
...(sliceAliases ? { sliceAliases } : {}),
|
|
307
332
|
...(flatParentPilot ? { flatParentPilot } : {}),
|
|
308
333
|
...(prototypeShortcuts ? { prototypeShortcuts } : {}),
|
|
@@ -315,10 +340,32 @@ export function computeDoctorAdvisories(root, config, cov, rules, files, ts, par
|
|
|
315
340
|
parseHealth: parseHealth ?? summarizeParseHealth(),
|
|
316
341
|
// Y09 direction: advisory graph-blind spots (template-interpolation); never hard verdict.
|
|
317
342
|
graphBlindSpots: detectGraphBlindSpots(ts, root, files),
|
|
343
|
+
// ADR 0037: files nothing imports (projection of the resolved import edges; notAScore).
|
|
344
|
+
orphanModules: computeOrphanModules({
|
|
345
|
+
root,
|
|
346
|
+
config: { ...config, rules: rules ?? config?.rules },
|
|
347
|
+
ts,
|
|
348
|
+
importGraph: facts?.importGraph,
|
|
349
|
+
details: view.details === true,
|
|
350
|
+
}),
|
|
351
|
+
// ADR 0038: copies across a wall (doctor-time token fingerprints; Details / report only).
|
|
352
|
+
crossWallDuplication: computeCrossWallDuplication({
|
|
353
|
+
root,
|
|
354
|
+
config,
|
|
355
|
+
rules: rules ?? config?.rules,
|
|
356
|
+
ts,
|
|
357
|
+
files: aliasFiles,
|
|
358
|
+
details: view.details === true,
|
|
359
|
+
changed: view.changed === true,
|
|
360
|
+
}),
|
|
318
361
|
// AR12 — Rules under contract (honest counts; real test I/O, never empty-fileContents stub).
|
|
319
362
|
// P1M: pass classification so extraMergeTeeth cannot arm at 0% governed.
|
|
320
363
|
stewardNudge: collectStewardNudge(root, config),
|
|
321
364
|
rulesUnderContract,
|
|
365
|
+
// AR15: doctor.rulesMigration — inventoried / under contract / frozen (not a score).
|
|
366
|
+
...(rulesUnderContract?.rulesMigration
|
|
367
|
+
? { rulesMigration: rulesUnderContract.rulesMigration }
|
|
368
|
+
: {}),
|
|
322
369
|
arkRun,
|
|
323
370
|
arkOrder,
|
|
324
371
|
};
|
|
@@ -328,13 +375,34 @@ export function printDoctorAdvisories(advisories, io) {
|
|
|
328
375
|
printFlatParentPilot(advisories?.flatParentPilot, io);
|
|
329
376
|
const sliceAliases = advisories?.sliceAliases;
|
|
330
377
|
if (sliceAliases && sliceAliases.notAScore === true && Array.isArray(sliceAliases.moves)) {
|
|
378
|
+
if (sliceAliases.moves.length > 0) {
|
|
379
|
+
console.log('');
|
|
380
|
+
console.log(io.color.bold('Slice aliases (owed move)'));
|
|
381
|
+
io.line(io.warn, sliceAliases.debt);
|
|
382
|
+
for (const move of sliceAliases.moves) {
|
|
383
|
+
io.line(io.warn, `${move.from} → ${move.to}. Move these files to ${move.destination}. They are not finished.`);
|
|
384
|
+
if (move.advisory) io.line(io.warn, move.advisory);
|
|
385
|
+
for (const file of move.files ?? []) io.line(' ', file);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (Array.isArray(sliceAliases.pinned) && sliceAliases.pinned.length > 0) {
|
|
389
|
+
console.log('');
|
|
390
|
+
console.log(io.color.bold('Pinned slice aliases'));
|
|
391
|
+
for (const row of sliceAliases.pinned) {
|
|
392
|
+
const label = typeof row.reason === 'string' && row.reason.length > 0 ? ` (${row.reason})` : '';
|
|
393
|
+
io.line(' ', `${row.from} → ${row.to}${label} stays. It is not an owed move.`);
|
|
394
|
+
for (const file of row.files ?? []) io.line(' ', file);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
const hubs = advisories?.sharedWalkHubs;
|
|
399
|
+
if (hubs && hubs.notAScore === true && Array.isArray(hubs.hubs) && hubs.hubs.length > 0) {
|
|
331
400
|
console.log('');
|
|
332
|
-
console.log(io.color.bold('
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
io.line(io.warn, `${move.from} → ${move.to}. Move these files to ${move.destination}. They are not finished.`);
|
|
336
|
-
for (const file of move.files ?? []) io.line(' ', file);
|
|
401
|
+
console.log(io.color.bold('Shared walk hubs (not a score)'));
|
|
402
|
+
for (const hub of hubs.hubs) {
|
|
403
|
+
io.line(io.warn, `${hub.file} sits on ${hub.count} of ${hubs.total} CROSS_PARENT_VIA_SHARED paths.`);
|
|
337
404
|
}
|
|
405
|
+
io.line(' ', io.color.dim(`Next: ${hubs.nextAction}`));
|
|
338
406
|
}
|
|
339
407
|
const sliceIdentity = advisories?.sliceIdentity;
|
|
340
408
|
if (Array.isArray(sliceIdentity?.collisions) && sliceIdentity.collisions.length > 0) {
|
|
@@ -354,6 +422,8 @@ export function printDoctorAdvisories(advisories, io) {
|
|
|
354
422
|
printReshapeDecisionsSection(advisories.physicalCohesion?.reshapeDecisions, io);
|
|
355
423
|
printParseHealthSection(advisories.parseHealth, io);
|
|
356
424
|
printGraphBlindSection(advisories.graphBlindSpots, io);
|
|
425
|
+
printOrphanModulesSection(advisories.orphanModules, io);
|
|
426
|
+
printCrossWallDuplicationSection(advisories.crossWallDuplication, io);
|
|
357
427
|
const nudge = advisories.stewardNudge;
|
|
358
428
|
if ((nudge?.needsStewards || nudge?.drift || nudge?.emptyStewardsPastGrace) && nudge.ask) {
|
|
359
429
|
console.log('');
|
|
@@ -9,7 +9,7 @@ import { REQUIRED_GATE_WORKFLOW } from './gate-files.mjs';
|
|
|
9
9
|
import { CI_MERGE_BOUNDARY_REL } from './ci-merge-boundary.mjs';
|
|
10
10
|
|
|
11
11
|
export const HEALTHY_CLAIM = 'Healthy — nothing to do.';
|
|
12
|
-
|
|
12
|
+
const HEALTHY_KEEP = ' Keep write path + CI.';
|
|
13
13
|
export const UNCITE_SUFFIX =
|
|
14
14
|
'not green until a file, config key, or test is named';
|
|
15
15
|
|
package/bin/lib/doctor-human.mjs
CHANGED
|
@@ -169,7 +169,7 @@ export function printDoctorCompactHuman(view) {
|
|
|
169
169
|
adrPresence: view.adrPresence,
|
|
170
170
|
statesTransitions: view.statesTransitions, statusTransitionCatalog: view.statusTransitionCatalog, noDomainFrontend: view.noDomainFrontend, invariantTestsPath: view.invariantTestsPath, invariantCoverageRoots: view.invariantCoverageRoots,
|
|
171
171
|
},
|
|
172
|
-
{ line, warn }
|
|
172
|
+
{ line, warn, color }
|
|
173
173
|
);
|
|
174
174
|
|
|
175
175
|
if (violations.length === 0) {
|
|
@@ -13,7 +13,7 @@ import { REQUIRED_GATE_WORKFLOW } from './gate-files.mjs';
|
|
|
13
13
|
export const PACKAGE_UNRESOLVED_NEXT_ACTION =
|
|
14
14
|
'Install arkgate in this project first (npx --package=arkgate, or pnpm add -D arkgate -w / yarn add -D arkgate -W at a workspace root), then re-run --doctor';
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
function packageUnresolvedNextAction(ctx) {
|
|
17
17
|
if (ctx?.packageInstalled !== false || ctx?.selfHost === true) return null;
|
|
18
18
|
const code = ctx?.packageVersionTruth?.code;
|
|
19
19
|
if (code === 'PACKAGE_PIN_SELF_HOST' || code === 'PACKAGE_PIN_ABSENT') return null;
|
|
@@ -24,6 +24,19 @@ export function packageUnresolvedNextAction(ctx) {
|
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* PACKAGE_PIN_ABSENT leads when a generated gate file (hook, MCP entry, CI workflow, script)
|
|
29
|
+
* runs Ark through the local runner: without the pin that command 404s or runs a stale global.
|
|
30
|
+
*/
|
|
31
|
+
export function packagePinAbsentPrimaryAction(ctx) {
|
|
32
|
+
if (ctx?.selfHost === true) return null;
|
|
33
|
+
const truth = ctx?.packageVersionTruth;
|
|
34
|
+
if (truth?.code !== 'PACKAGE_PIN_ABSENT') return null;
|
|
35
|
+
const files = Array.isArray(truth.dependentGateFiles) ? truth.dependentGateFiles : [];
|
|
36
|
+
if (files.length === 0) return null;
|
|
37
|
+
return `Add arkgate to package.json devDependencies and install — ${files.join(', ')} run Ark through the local runner, which does not resolve without the pin (PACKAGE_PIN_ABSENT)`;
|
|
38
|
+
}
|
|
39
|
+
|
|
27
40
|
/** Compact doctor JSON #1 — same rank as collectDoctorNextActions when package is missing. */
|
|
28
41
|
export function preferredDoctorPrimaryNextAction({
|
|
29
42
|
adopted,
|
|
@@ -35,6 +48,7 @@ export function preferredDoctorPrimaryNextAction({
|
|
|
35
48
|
} = {}) {
|
|
36
49
|
return (
|
|
37
50
|
packageUnresolvedNextAction({ packageInstalled, selfHost, packageVersionTruth }) ||
|
|
51
|
+
packagePinAbsentPrimaryAction({ selfHost, packageVersionTruth }) ||
|
|
38
52
|
(adopted === 'not-adopted' ? NOT_ADOPTED_NEXT_ACTION : postGreenPath?.action ?? dualTruthNext ?? null)
|
|
39
53
|
);
|
|
40
54
|
}
|
|
@@ -87,7 +101,7 @@ function domainSampleIsGlobLeak(row, cov) {
|
|
|
87
101
|
}
|
|
88
102
|
|
|
89
103
|
/** Overlapping roots from matching Domain wildcards, else sample path prefixes. */
|
|
90
|
-
|
|
104
|
+
function overlappingRootsFromCoverage(cov) {
|
|
91
105
|
const samples = Array.isArray(cov?.dualMembership?.samples) ? cov.dualMembership.samples : [];
|
|
92
106
|
const domainPatterns = layerPatterns(cov, 'DomainModel');
|
|
93
107
|
const fromPatterns = [];
|
|
@@ -149,7 +163,8 @@ export function collectDoctorNextActions(ctx) {
|
|
|
149
163
|
if (notAdopted || ctx.adopted === ADOPTED_NOT || ctx.adopted == null) {
|
|
150
164
|
actions.push(ctx.notAdoptedNextAction || NOT_ADOPTED_NEXT_ACTION);
|
|
151
165
|
}
|
|
152
|
-
const
|
|
166
|
+
const pinAbsentPrimary = packagePinAbsentPrimaryAction(ctx);
|
|
167
|
+
const resolvePkg = packageUnresolvedNextAction(ctx) || pinAbsentPrimary;
|
|
153
168
|
if (resolvePkg) actions.push(resolvePkg);
|
|
154
169
|
const nudge = ctx.stewardNudge;
|
|
155
170
|
if (
|
|
@@ -220,7 +235,7 @@ export function collectDoctorNextActions(ctx) {
|
|
|
220
235
|
ctx.dualTruthNext ||
|
|
221
236
|
'bump package.json arkgate pin to match this CLI (or install without --no-install)'
|
|
222
237
|
);
|
|
223
|
-
} else if (ctx.packageVersionTruth?.code === 'PACKAGE_PIN_ABSENT') {
|
|
238
|
+
} else if (ctx.packageVersionTruth?.code === 'PACKAGE_PIN_ABSENT' && !pinAbsentPrimary) {
|
|
224
239
|
actions.push(
|
|
225
240
|
ctx.dualTruthNext ||
|
|
226
241
|
'Add arkgate to package.json and install so CI/npx resolve this CLI (PACKAGE_PIN_ABSENT)'
|
package/bin/lib/doctor-plan.mjs
CHANGED
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
shouldShowNewHereNudge,
|
|
11
11
|
} from '../ark-shared.mjs';
|
|
12
12
|
import * as arkShared from '../ark-shared.mjs';
|
|
13
|
-
import { summarizeRulesUnderContract } from './rules-under-contract.mjs';
|
|
14
13
|
import { describePackageVersionDualTruth } from './field-install.mjs';
|
|
14
|
+
import { withPinDependentGateFiles } from './pin-dependent-gates.mjs';
|
|
15
15
|
import { detectAgentHomeGaps } from './agent-homes.mjs';
|
|
16
16
|
import { collectDoctorNextActions, preferredDoctorPrimaryNextAction } from './doctor-next-actions.mjs';
|
|
17
17
|
import { printDoctorCompactHuman, printDoctorDetailsHuman } from './doctor-human.mjs';
|
|
@@ -21,10 +21,9 @@ import { collectStatesTransitionsResidual } from './states-transitions-presence.
|
|
|
21
21
|
import { collectStatusTransitionCatalogResidual } from './status-transition-catalog.mjs';
|
|
22
22
|
import { collectNoDomainFrontendResidual } from './no-domain-frontend.mjs';
|
|
23
23
|
import { collectInvariantCoverageResiduals } from './invariant-tests-path.mjs';
|
|
24
|
-
import { anyChildWallAdvisory,
|
|
24
|
+
import { anyChildWallAdvisory, applyAdvisorySiblingRatchet, sliceAliasOwesMove } from '../ark-layer-match.mjs';
|
|
25
25
|
export { printAdrPresenceHint };
|
|
26
26
|
export { printDoctorCompactHuman, printDoctorDetailsHuman };
|
|
27
|
-
export { summarizeRulesUnderContract };
|
|
28
27
|
/** Optional S3 dual-match classifier when ark-shared exports it (soft dep for S5 landing). */
|
|
29
28
|
const matchingLayersForRelativePath =
|
|
30
29
|
typeof arkShared.matchingLayersForRelativePath === 'function'
|
|
@@ -533,7 +532,7 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
|
|
|
533
532
|
const skillGaps = detectSkillGaps(root);
|
|
534
533
|
const agentHomeGaps = detectAgentHomeGaps(root);
|
|
535
534
|
// Dual-truth: CLI version vs package.json pin (field residual after upgrade --no-install).
|
|
536
|
-
const packageVersionTruth = describePackageVersionDualTruth(root);
|
|
535
|
+
const packageVersionTruth = withPinDependentGateFiles(root, describePackageVersionDualTruth(root));
|
|
537
536
|
const staleRunners = staleRunnerGateFiles(root);
|
|
538
537
|
const adoption = collectAdoptionGaps(root, config, cov);
|
|
539
538
|
// Prefer writePath from adoption (same detector); recompute only if missing (tests/stubs).
|
|
@@ -557,12 +556,9 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
|
|
|
557
556
|
? [...baseline.keys].filter((key) => !currentKeys.has(key)).length
|
|
558
557
|
: 0;
|
|
559
558
|
const activeCount = violations.length - suppressed;
|
|
560
|
-
// productHonesty: blocking = failsStrict !== false only
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
if (!baseline.exists) return true;
|
|
564
|
-
return !baseline.keys.has(occurrenceKeys[index]);
|
|
565
|
-
}).length;
|
|
559
|
+
// productHonesty: blocking = failsStrict !== false only, after the same sibling ratchet as --baseline.
|
|
560
|
+
const judged = baseline.exists ? applyAdvisorySiblingRatchet(violations, occurrenceKeys, baseline.keys, { rules, layers: config?.layers }) : violations;
|
|
561
|
+
const blockingActive = judged.filter((v, i) => v.failsStrict !== false && !(baseline.exists && baseline.keys.has(occurrenceKeys[i]))).length;
|
|
566
562
|
const emptyScopeEarly = cov.emptyScope === true || cov.governed.totalFiles === 0;
|
|
567
563
|
const presentationRowEarly = cov.layers.find((r) => r.name === 'PresentationAdapters');
|
|
568
564
|
const totalFilesEarly = cov.governed.totalFiles || 0;
|
|
@@ -612,7 +608,8 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
|
|
|
612
608
|
options.ts,
|
|
613
609
|
options.parseHealth,
|
|
614
610
|
options.facts ?? options.architectureFacts,
|
|
615
|
-
activeViolations
|
|
611
|
+
activeViolations,
|
|
612
|
+
{ details: options.all === true, changed: options.changed === true }
|
|
616
613
|
);
|
|
617
614
|
// After physical cohesion so a reshape pilot is a candidate (#309).
|
|
618
615
|
const pilotLoop = summarizePilotLoop(
|
|
@@ -694,7 +691,7 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
|
|
|
694
691
|
github: githubForBoundary,
|
|
695
692
|
adoptionStance: stanceFile,
|
|
696
693
|
stewardNudge: doctorAdvisories.stewardNudge,
|
|
697
|
-
physicalCohesionResidual: physicalCohesionResidualRemains(doctorAdvisories.physicalCohesion), childWallAdvisory: anyChildWallAdvisory(config?.rules), sliceAliasDebt:
|
|
694
|
+
physicalCohesionResidual: physicalCohesionResidualRemains(doctorAdvisories.physicalCohesion), childWallAdvisory: anyChildWallAdvisory(config?.rules), sliceAliasDebt: sliceAliasOwesMove(config?.rules),
|
|
698
695
|
});
|
|
699
696
|
|
|
700
697
|
// Improvement compass: projection only — never feeds ok/valid/goal.met.
|
|
@@ -976,4 +973,3 @@ export function runDoctor(root, config, files, rules, violations, asJson, option
|
|
|
976
973
|
printDoctorCompactHuman(humanView);
|
|
977
974
|
if (options.all) printDoctorDetailsHuman(humanView);
|
|
978
975
|
}
|
|
979
|
-
|