@shrkcrft/cli 0.1.0-alpha.2 → 0.1.0-alpha.21
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/audit/knowledge-audit-llm.d.ts +19 -0
- package/dist/audit/knowledge-audit-llm.d.ts.map +1 -0
- package/dist/audit/knowledge-audit-llm.js +164 -0
- package/dist/audit/knowledge-audit.d.ts +61 -0
- package/dist/audit/knowledge-audit.d.ts.map +1 -0
- package/dist/audit/knowledge-audit.js +203 -0
- package/dist/audit/knowledge-fix-plan-llm.d.ts +11 -0
- package/dist/audit/knowledge-fix-plan-llm.d.ts.map +1 -0
- package/dist/audit/knowledge-fix-plan-llm.js +141 -0
- package/dist/audit/knowledge-fix-plan.d.ts +41 -0
- package/dist/audit/knowledge-fix-plan.d.ts.map +1 -0
- package/dist/audit/knowledge-fix-plan.js +125 -0
- package/dist/audit/pipeline-audit-llm.d.ts +11 -0
- package/dist/audit/pipeline-audit-llm.d.ts.map +1 -0
- package/dist/audit/pipeline-audit-llm.js +134 -0
- package/dist/audit/pipeline-audit.d.ts +69 -0
- package/dist/audit/pipeline-audit.d.ts.map +1 -0
- package/dist/audit/pipeline-audit.js +166 -0
- package/dist/audit/templates-audit-llm.d.ts +19 -0
- package/dist/audit/templates-audit-llm.d.ts.map +1 -0
- package/dist/audit/templates-audit-llm.js +207 -0
- package/dist/audit/templates-audit.d.ts +63 -0
- package/dist/audit/templates-audit.d.ts.map +1 -0
- package/dist/audit/templates-audit.js +171 -0
- package/dist/audit/templates-fix-plan-llm.d.ts +19 -0
- package/dist/audit/templates-fix-plan-llm.d.ts.map +1 -0
- package/dist/audit/templates-fix-plan-llm.js +162 -0
- package/dist/audit/templates-fix-plan.d.ts +37 -0
- package/dist/audit/templates-fix-plan.d.ts.map +1 -0
- package/dist/audit/templates-fix-plan.js +174 -0
- package/dist/command-registry.d.ts +28 -0
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +91 -1
- package/dist/commands/ai-status.command.d.ts +19 -0
- package/dist/commands/ai-status.command.d.ts.map +1 -0
- package/dist/commands/ai-status.command.js +94 -0
- package/dist/commands/api-diff.command.d.ts +11 -0
- package/dist/commands/api-diff.command.d.ts.map +1 -0
- package/dist/commands/api-diff.command.js +144 -0
- package/dist/commands/apply.command.d.ts.map +1 -1
- package/dist/commands/apply.command.js +10 -2
- package/dist/commands/arch.command.d.ts +9 -0
- package/dist/commands/arch.command.d.ts.map +1 -0
- package/dist/commands/arch.command.js +186 -0
- package/dist/commands/ask.command.d.ts.map +1 -1
- package/dist/commands/ask.command.js +10 -9
- package/dist/commands/cache-align.command.d.ts +12 -0
- package/dist/commands/cache-align.command.d.ts.map +1 -0
- package/dist/commands/cache-align.command.js +78 -0
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +26 -2
- package/dist/commands/code-intel.command.d.ts +18 -0
- package/dist/commands/code-intel.command.d.ts.map +1 -0
- package/dist/commands/code-intel.command.js +146 -0
- package/dist/commands/codemod.command.d.ts.map +1 -1
- package/dist/commands/codemod.command.js +27 -6
- package/dist/commands/command-catalog.d.ts +15 -3
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +407 -34
- package/dist/commands/commands.command.d.ts.map +1 -1
- package/dist/commands/commands.command.js +4 -4
- package/dist/commands/completion.command.d.ts +10 -0
- package/dist/commands/completion.command.d.ts.map +1 -0
- package/dist/commands/completion.command.js +121 -0
- package/dist/commands/compress.command.d.ts +8 -0
- package/dist/commands/compress.command.d.ts.map +1 -0
- package/dist/commands/compress.command.js +147 -0
- package/dist/commands/constructs.command.d.ts.map +1 -1
- package/dist/commands/constructs.command.js +89 -23
- package/dist/commands/context.command.d.ts.map +1 -1
- package/dist/commands/context.command.js +121 -1
- package/dist/commands/contract-gate.command.d.ts.map +1 -1
- package/dist/commands/contract-gate.command.js +5 -1
- package/dist/commands/delegate.command.d.ts +65 -0
- package/dist/commands/delegate.command.d.ts.map +1 -0
- package/dist/commands/delegate.command.js +657 -0
- package/dist/commands/deps-audit.command.d.ts +23 -0
- package/dist/commands/deps-audit.command.d.ts.map +1 -0
- package/dist/commands/deps-audit.command.js +270 -0
- package/dist/commands/dev.command.d.ts.map +1 -1
- package/dist/commands/dev.command.js +5 -2
- package/dist/commands/diff-check.command.d.ts +30 -0
- package/dist/commands/diff-check.command.d.ts.map +1 -0
- package/dist/commands/diff-check.command.js +210 -0
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +162 -10
- package/dist/commands/export.command.d.ts.map +1 -1
- package/dist/commands/export.command.js +76 -3
- package/dist/commands/framework.command.d.ts +12 -0
- package/dist/commands/framework.command.d.ts.map +1 -0
- package/dist/commands/framework.command.js +180 -0
- package/dist/commands/gate.command.d.ts +15 -0
- package/dist/commands/gate.command.d.ts.map +1 -0
- package/dist/commands/gate.command.js +300 -0
- package/dist/commands/gen.command.d.ts.map +1 -1
- package/dist/commands/gen.command.js +13 -1
- package/dist/commands/graph-code-subverbs.d.ts +33 -0
- package/dist/commands/graph-code-subverbs.d.ts.map +1 -0
- package/dist/commands/graph-code-subverbs.js +1385 -0
- package/dist/commands/graph.command.d.ts.map +1 -1
- package/dist/commands/graph.command.js +31 -2
- package/dist/commands/help.command.d.ts +4 -3
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +86 -18
- package/dist/commands/helper.command.js +1 -1
- package/dist/commands/impact.command.d.ts.map +1 -1
- package/dist/commands/impact.command.js +171 -1
- package/dist/commands/import.command.d.ts.map +1 -1
- package/dist/commands/import.command.js +121 -5
- package/dist/commands/ingest.command.d.ts.map +1 -1
- package/dist/commands/ingest.command.js +5 -1
- package/dist/commands/init.command.d.ts.map +1 -1
- package/dist/commands/init.command.js +174 -7
- package/dist/commands/knowledge-author.command.d.ts.map +1 -1
- package/dist/commands/knowledge-author.command.js +9 -0
- package/dist/commands/knowledge-propose.command.d.ts.map +1 -1
- package/dist/commands/knowledge-propose.command.js +4 -2
- package/dist/commands/knowledge.command.d.ts.map +1 -1
- package/dist/commands/knowledge.command.js +26 -3
- package/dist/commands/migrate.command.d.ts +13 -0
- package/dist/commands/migrate.command.d.ts.map +1 -0
- package/dist/commands/migrate.command.js +152 -0
- package/dist/commands/move-plan.command.d.ts +23 -0
- package/dist/commands/move-plan.command.d.ts.map +1 -0
- package/dist/commands/move-plan.command.js +360 -0
- package/dist/commands/packs-new.d.ts +1 -1
- package/dist/commands/packs-new.d.ts.map +1 -1
- package/dist/commands/packs-new.js +5 -36
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +2 -10
- package/dist/commands/plan-context.command.d.ts +11 -0
- package/dist/commands/plan-context.command.d.ts.map +1 -0
- package/dist/commands/plan-context.command.js +85 -0
- package/dist/commands/preflight.command.d.ts.map +1 -1
- package/dist/commands/preflight.command.js +15 -0
- package/dist/commands/profiles.command.js +4 -4
- package/dist/commands/recommend.command.d.ts +6 -0
- package/dist/commands/recommend.command.d.ts.map +1 -1
- package/dist/commands/recommend.command.js +119 -5
- package/dist/commands/release.command.js +13 -13
- package/dist/commands/rule-graph-subverbs.d.ts +3 -0
- package/dist/commands/rule-graph-subverbs.d.ts.map +1 -0
- package/dist/commands/rule-graph-subverbs.js +132 -0
- package/dist/commands/rules.command.d.ts.map +1 -1
- package/dist/commands/rules.command.js +20 -3
- package/dist/commands/scaffold-validate.command.d.ts +22 -0
- package/dist/commands/scaffold-validate.command.d.ts.map +1 -0
- package/dist/commands/scaffold-validate.command.js +215 -0
- package/dist/commands/search-structural.command.d.ts +18 -0
- package/dist/commands/search-structural.command.d.ts.map +1 -0
- package/dist/commands/search-structural.command.js +376 -0
- package/dist/commands/search.command.js +1 -1
- package/dist/commands/smart-context.command.d.ts +67 -0
- package/dist/commands/smart-context.command.d.ts.map +1 -0
- package/dist/commands/smart-context.command.js +4728 -0
- package/dist/commands/spike.command.d.ts +22 -0
- package/dist/commands/spike.command.d.ts.map +1 -0
- package/dist/commands/spike.command.js +235 -0
- package/dist/commands/surface.command.d.ts +1 -0
- package/dist/commands/surface.command.d.ts.map +1 -1
- package/dist/commands/surface.command.js +10 -3
- package/dist/commands/task-context.command.d.ts.map +1 -1
- package/dist/commands/task-context.command.js +5 -17
- package/dist/commands/task.command.d.ts.map +1 -1
- package/dist/commands/task.command.js +8 -2
- package/dist/commands/template-quality.command.d.ts.map +1 -1
- package/dist/commands/template-quality.command.js +39 -3
- package/dist/commands/templates.command.d.ts.map +1 -1
- package/dist/commands/templates.command.js +37 -2
- package/dist/commands/tests.command.d.ts.map +1 -1
- package/dist/commands/tests.command.js +13 -2
- package/dist/commands/watch.command.d.ts +26 -0
- package/dist/commands/watch.command.d.ts.map +1 -0
- package/dist/commands/watch.command.js +456 -0
- package/dist/dashboard/code-intelligence-data.d.ts +33 -0
- package/dist/dashboard/code-intelligence-data.d.ts.map +1 -0
- package/dist/dashboard/code-intelligence-data.js +329 -0
- package/dist/dashboard/dashboard-api-server.d.ts.map +1 -1
- package/dist/dashboard/dashboard-api-server.js +256 -2
- package/dist/dashboard/knowledge-ask.d.ts +4 -0
- package/dist/dashboard/knowledge-ask.d.ts.map +1 -0
- package/dist/dashboard/knowledge-ask.js +112 -0
- package/dist/env/load-dotenv.d.ts +15 -0
- package/dist/env/load-dotenv.d.ts.map +1 -0
- package/dist/env/load-dotenv.js +70 -0
- package/dist/export/claude-commands-export.d.ts +60 -0
- package/dist/export/claude-commands-export.d.ts.map +1 -0
- package/dist/export/claude-commands-export.js +276 -0
- package/dist/export/export-formats.d.ts +1 -1
- package/dist/export/export-formats.d.ts.map +1 -1
- package/dist/export/export-formats.js +139 -12
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/init/init-templates.d.ts.map +1 -1
- package/dist/init/init-templates.js +133 -113
- package/dist/init/paths-advisory.d.ts +20 -0
- package/dist/init/paths-advisory.d.ts.map +1 -0
- package/dist/init/paths-advisory.js +88 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +331 -17
- package/dist/output/ccr-store-config.d.ts +18 -0
- package/dist/output/ccr-store-config.d.ts.map +1 -0
- package/dist/output/ccr-store-config.js +41 -0
- package/dist/output/format-output.d.ts.map +1 -1
- package/dist/output/format-output.js +6 -1
- package/dist/output/output-compression.d.ts +15 -0
- package/dist/output/output-compression.d.ts.map +1 -0
- package/dist/output/output-compression.js +60 -0
- package/dist/output/resolve-compress-type.d.ts +22 -0
- package/dist/output/resolve-compress-type.d.ts.map +1 -0
- package/dist/output/resolve-compress-type.js +21 -0
- package/dist/output/watch-loop.d.ts +9 -1
- package/dist/output/watch-loop.d.ts.map +1 -1
- package/dist/output/watch-loop.js +13 -3
- package/dist/schemas/json-schemas.d.ts +384 -36
- package/dist/schemas/json-schemas.d.ts.map +1 -1
- package/dist/schemas/json-schemas.js +247 -36
- package/dist/surface/profiles.d.ts.map +1 -1
- package/dist/surface/profiles.js +54 -10
- package/dist/surface/surface-config-writer.d.ts.map +1 -1
- package/dist/surface/surface-config-writer.js +23 -11
- package/dist/validation/run-validation-loop.d.ts.map +1 -1
- package/dist/validation/run-validation-loop.js +5 -1
- package/package.json +35 -21
- package/dist/commands/plugin.command.d.ts +0 -11
- package/dist/commands/plugin.command.d.ts.map +0 -1
- package/dist/commands/plugin.command.js +0 -394
|
@@ -179,7 +179,7 @@ async function runApplyBatchFromCli(args, batchPath) {
|
|
|
179
179
|
export const applyCommand = {
|
|
180
180
|
name: 'apply',
|
|
181
181
|
description: 'Apply a previously-saved generation plan (sharkcraft.plan/v1 JSON). The CLI is the only write path; MCP never writes. Plans that live under .sharkcraft/sessions/<id>/plans/ automatically update the session metadata (signature + divergence + applied + validation).',
|
|
182
|
-
usage: 'shrk [--cwd <dir>] apply <plan.json> [--session <id>] [--force] [--allow-divergent] [--verify-signature] [--require-signature] [--dry-run] [--validate] [--report] [--json] [--trace] [--explain-dispatch] | shrk apply --asset-preview <draft.ts> --target <file> [--write] [--allow-unknown-target] [--reason <text>] | shrk apply --batch <plan.json> [--allow-divergent] [--dry-run] [--json]',
|
|
182
|
+
usage: 'shrk [--cwd <dir>] apply <plan.json> [--session <id>] [--force] [--allow-divergent] [--verify-signature] [--require-signature] [--no-verify-signature] [--dry-run] [--validate] [--report] [--json] [--trace] [--explain-dispatch] | shrk apply --asset-preview <draft.ts> --target <file> [--write] [--allow-unknown-target] [--reason <text>] | shrk apply --batch <plan.json> [--allow-divergent] [--dry-run] [--json]',
|
|
183
183
|
async run(args) {
|
|
184
184
|
// Asset-preview flow: paste-with-review for authoring drafts.
|
|
185
185
|
// Distinct from the plan-based apply path: takes a TS draft and a
|
|
@@ -222,7 +222,15 @@ export const applyCommand = {
|
|
|
222
222
|
const explainOnly = flagBool(args, 'explain-dispatch');
|
|
223
223
|
let signatureStatus = DevSessionSignatureStatus.NotChecked;
|
|
224
224
|
let signatureMessage;
|
|
225
|
-
|
|
225
|
+
// A plan that CARRIES a signature self-enforces verification: the signature
|
|
226
|
+
// is the producer's tamper-evidence declaration, so a signed plan must not
|
|
227
|
+
// apply unverified just because the caller forgot --verify-signature
|
|
228
|
+
// (contract: "Apply requires --verify-signature for signed plans"). A
|
|
229
|
+
// tampered/invalid signature then refuses below. `--no-verify-signature` is
|
|
230
|
+
// the explicit escape hatch for sign-here / apply-there-without-the-secret.
|
|
231
|
+
const isSigned = Boolean(saved.signature);
|
|
232
|
+
const skipSig = flagBool(args, 'no-verify-signature') && !verifySig;
|
|
233
|
+
if (verifySig || (isSigned && !skipSig)) {
|
|
226
234
|
const result = verifyPlan(saved);
|
|
227
235
|
if (result.ok === true) {
|
|
228
236
|
signatureStatus = DevSessionSignatureStatus.Verified;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ICommandHandler } from '../command-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* `shrk arch` — semantic architecture checks on top of the code graph.
|
|
4
|
+
* Sub-verbs:
|
|
5
|
+
* - shrk arch check run all enabled checks (auto-loads sharkcraft/arch.ts)
|
|
6
|
+
* - shrk arch check --contract X point at an explicit contract file
|
|
7
|
+
*/
|
|
8
|
+
export declare const archCommand: ICommandHandler;
|
|
9
|
+
//# sourceMappingURL=arch.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arch.command.d.ts","sourceRoot":"","sources":["../../src/commands/arch.command.ts"],"names":[],"mappings":"AASA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAIhC;;;;;GAKG;AACH,eAAO,MAAM,WAAW,EAAE,eAoBzB,CAAC"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import * as nodePath from 'node:path';
|
|
3
|
+
import { ArchReportStore, diffSnapshots, runArchCheck, } from '@shrkcrft/architecture-guard';
|
|
4
|
+
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
5
|
+
import { safeImport } from '@shrkcrft/core';
|
|
6
|
+
import { asJson, header, kv } from "../output/format-output.js";
|
|
7
|
+
/**
|
|
8
|
+
* `shrk arch` — semantic architecture checks on top of the code graph.
|
|
9
|
+
* Sub-verbs:
|
|
10
|
+
* - shrk arch check run all enabled checks (auto-loads sharkcraft/arch.ts)
|
|
11
|
+
* - shrk arch check --contract X point at an explicit contract file
|
|
12
|
+
*/
|
|
13
|
+
export const archCommand = {
|
|
14
|
+
name: 'arch',
|
|
15
|
+
description: 'Architecture-guard checks: public-API misuse, barrel risks, cycle severity, project-specific contracts (sharkcraft/arch.ts auto-loaded). `shrk arch baseline <write|show|clear>` to gate doctor on a frozen baseline.',
|
|
16
|
+
usage: 'shrk arch check [--contract <path>] [--no-cycles] [--no-barrels] [--no-public-api] [--no-persist] [--json]\n shrk arch baseline <write|show|clear> [--contract <path>] [--json]',
|
|
17
|
+
async run(args) {
|
|
18
|
+
const sub = args.positional[0];
|
|
19
|
+
if (sub === 'baseline') {
|
|
20
|
+
return runArchBaseline({
|
|
21
|
+
...args,
|
|
22
|
+
positional: args.positional.slice(1),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (sub !== 'check') {
|
|
26
|
+
process.stderr.write(this.usage + '\n');
|
|
27
|
+
return 2;
|
|
28
|
+
}
|
|
29
|
+
return runArchCheckCommand(args);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
async function runArchCheckCommand(args) {
|
|
33
|
+
const cwd = resolveCwd(args);
|
|
34
|
+
const wantJson = flagBool(args, 'json');
|
|
35
|
+
const noCycles = flagBool(args, 'no-cycles');
|
|
36
|
+
const noBarrels = flagBool(args, 'no-barrels');
|
|
37
|
+
const noPublicApi = flagBool(args, 'no-public-api');
|
|
38
|
+
const noPersist = flagBool(args, 'no-persist');
|
|
39
|
+
const contractPath = flagString(args, 'contract');
|
|
40
|
+
const contract = await loadContract(cwd, contractPath);
|
|
41
|
+
const report = runArchCheck({
|
|
42
|
+
projectRoot: cwd,
|
|
43
|
+
...(contract ? { contract } : {}),
|
|
44
|
+
enable: {
|
|
45
|
+
publicApi: !noPublicApi,
|
|
46
|
+
barrels: !noBarrels,
|
|
47
|
+
cycles: !noCycles,
|
|
48
|
+
contract: !!contract,
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
// Persist a compact snapshot so `shrk doctor` can compare against
|
|
52
|
+
// baseline without re-running the full check. `--no-persist` opts out
|
|
53
|
+
// (useful when scripting against many trees).
|
|
54
|
+
if (!noPersist) {
|
|
55
|
+
try {
|
|
56
|
+
new ArchReportStore(cwd).writeLast(report);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// best-effort
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (wantJson) {
|
|
63
|
+
process.stdout.write(asJson(report) + '\n');
|
|
64
|
+
return report.countsBySeverity.error > 0 ? 1 : 0;
|
|
65
|
+
}
|
|
66
|
+
printArchReport(report);
|
|
67
|
+
return report.countsBySeverity.error > 0 ? 1 : 0;
|
|
68
|
+
}
|
|
69
|
+
async function runArchBaseline(args) {
|
|
70
|
+
const cwd = resolveCwd(args);
|
|
71
|
+
const verb = args.positional[0] ?? 'show';
|
|
72
|
+
const store = new ArchReportStore(cwd);
|
|
73
|
+
const wantJson = flagBool(args, 'json');
|
|
74
|
+
if (verb === 'write') {
|
|
75
|
+
const contractPath = flagString(args, 'contract');
|
|
76
|
+
const contract = await loadContract(cwd, contractPath);
|
|
77
|
+
const report = runArchCheck({
|
|
78
|
+
projectRoot: cwd,
|
|
79
|
+
...(contract ? { contract } : {}),
|
|
80
|
+
});
|
|
81
|
+
const snap = store.writeBaseline(report);
|
|
82
|
+
// Update last.json too so doctor's first delta read is meaningful.
|
|
83
|
+
store.writeLast(report);
|
|
84
|
+
if (wantJson) {
|
|
85
|
+
process.stdout.write(asJson({ wrote: store.baselinePath, baseline: snap }) + '\n');
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
process.stdout.write(`Architecture baseline written → ${store.baselinePath}\n`);
|
|
89
|
+
process.stdout.write(` ${snap.violationIds.length} violations (` +
|
|
90
|
+
`${snap.countsBySeverity.error} error, ` +
|
|
91
|
+
`${snap.countsBySeverity.warning} warning, ` +
|
|
92
|
+
`${snap.countsBySeverity.info} info) ` +
|
|
93
|
+
`across ${snap.filesAnalyzed} files.\n`);
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
if (verb === 'show') {
|
|
97
|
+
const baseline = store.readBaseline();
|
|
98
|
+
if (!baseline) {
|
|
99
|
+
const msg = `No baseline at ${store.baselinePath}. Run \`shrk arch baseline write\` to freeze one.\n`;
|
|
100
|
+
if (wantJson) {
|
|
101
|
+
process.stdout.write(asJson({ baseline: null, path: store.baselinePath }) + '\n');
|
|
102
|
+
return 1;
|
|
103
|
+
}
|
|
104
|
+
process.stdout.write(msg);
|
|
105
|
+
return 1;
|
|
106
|
+
}
|
|
107
|
+
if (wantJson) {
|
|
108
|
+
process.stdout.write(asJson({ path: store.baselinePath, baseline }) + '\n');
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
process.stdout.write(header('Architecture baseline'));
|
|
112
|
+
process.stdout.write(kv('path', store.baselinePath) + '\n');
|
|
113
|
+
process.stdout.write(kv('generated at', baseline.generatedAt) + '\n');
|
|
114
|
+
process.stdout.write(kv('files analyzed', String(baseline.filesAnalyzed)) + '\n');
|
|
115
|
+
process.stdout.write(kv('counts', `${baseline.countsBySeverity.error} error, ${baseline.countsBySeverity.warning} warning, ${baseline.countsBySeverity.info} info`) + '\n');
|
|
116
|
+
const last = store.readLast();
|
|
117
|
+
if (last) {
|
|
118
|
+
const delta = diffSnapshots(baseline, last);
|
|
119
|
+
process.stdout.write('\nDelta (last − baseline): ' +
|
|
120
|
+
`${delta.newViolationIds.length} new, ${delta.fixedViolationIds.length} fixed ` +
|
|
121
|
+
`(error ${delta.errorDelta >= 0 ? '+' : ''}${delta.errorDelta}, warning ${delta.warningDelta >= 0 ? '+' : ''}${delta.warningDelta})\n`);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
process.stdout.write('\n(no `last.json` yet — run `shrk arch check`.)\n');
|
|
125
|
+
}
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
if (verb === 'clear') {
|
|
129
|
+
const removed = store.clearBaseline();
|
|
130
|
+
if (wantJson) {
|
|
131
|
+
process.stdout.write(asJson({ removed, path: store.baselinePath }) + '\n');
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
process.stdout.write(removed ? `Baseline removed: ${store.baselinePath}\n` : 'No baseline to remove.\n');
|
|
135
|
+
return 0;
|
|
136
|
+
}
|
|
137
|
+
process.stderr.write('Usage: shrk arch baseline <write|show|clear> [--json]\n');
|
|
138
|
+
return 2;
|
|
139
|
+
}
|
|
140
|
+
function printArchReport(report) {
|
|
141
|
+
process.stdout.write(header('Architecture guard'));
|
|
142
|
+
process.stdout.write(kv('schema', report.schema) + '\n');
|
|
143
|
+
process.stdout.write(kv('files analyzed', String(report.filesAnalyzed)) + '\n');
|
|
144
|
+
process.stdout.write(kv('errors', String(report.countsBySeverity.error)) + '\n');
|
|
145
|
+
process.stdout.write(kv('warnings', String(report.countsBySeverity.warning)) + '\n');
|
|
146
|
+
if (report.violations.length === 0) {
|
|
147
|
+
process.stdout.write('\nNo violations.\n');
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
process.stdout.write('\nViolations:\n');
|
|
151
|
+
for (const v of report.violations.slice(0, 80)) {
|
|
152
|
+
const lineSuffix = v.line ? `:${v.line}` : '';
|
|
153
|
+
process.stdout.write(` [${v.severity}] [${v.kind}] ${v.file}${lineSuffix}\n ${v.message}\n`);
|
|
154
|
+
if (v.suggestedFix)
|
|
155
|
+
process.stdout.write(` → ${v.suggestedFix}\n`);
|
|
156
|
+
}
|
|
157
|
+
if (report.violations.length > 80) {
|
|
158
|
+
process.stdout.write(` … (${report.violations.length - 80} more)\n`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
for (const d of report.diagnostics.slice(0, 5))
|
|
162
|
+
process.stdout.write(`! ${d}\n`);
|
|
163
|
+
}
|
|
164
|
+
async function loadContract(cwd, explicit) {
|
|
165
|
+
const candidate = explicit
|
|
166
|
+
? nodePath.isAbsolute(explicit) ? explicit : nodePath.resolve(cwd, explicit)
|
|
167
|
+
: nodePath.join(cwd, 'sharkcraft', 'arch.ts');
|
|
168
|
+
if (!existsSync(candidate)) {
|
|
169
|
+
if (explicit)
|
|
170
|
+
process.stderr.write(`! contract file not found: ${candidate}\n`);
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
const result = await safeImport(candidate);
|
|
174
|
+
if (!result.ok) {
|
|
175
|
+
process.stderr.write(`! failed to load arch contract: ${result.error.message}\n`);
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
const mod = result.module;
|
|
179
|
+
const exported = mod.default ??
|
|
180
|
+
mod.contract;
|
|
181
|
+
if (!exported) {
|
|
182
|
+
process.stderr.write(`! arch contract module ${candidate} does not export a contract\n`);
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
return exported;
|
|
186
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ask.command.d.ts","sourceRoot":"","sources":["../../src/commands/ask.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ask.command.d.ts","sourceRoot":"","sources":["../../src/commands/ask.command.ts"],"names":[],"mappings":"AAOA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAIhC,eAAO,MAAM,UAAU,EAAE,eA6DxB,CAAC"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { inspectSharkcraft, buildProjectOverview, renderOverviewText } from '@shrkcrft/inspector';
|
|
2
2
|
import { buildContext } from '@shrkcrft/context';
|
|
3
|
-
import {
|
|
3
|
+
import { AiMessageRole, buildPromptMessages, selectAiProvider, } from '@shrkcrft/ai';
|
|
4
4
|
import { flagBool, flagNumber, flagString, resolveCwd, } from "../command-registry.js";
|
|
5
5
|
import { header } from "../output/format-output.js";
|
|
6
6
|
import { printError } from "../output/print-error.js";
|
|
7
7
|
export const askCommand = {
|
|
8
8
|
name: 'ask',
|
|
9
|
-
description: 'Ask a question. Builds repository context, sends prompt to
|
|
10
|
-
usage: 'shrk ask "<question>" [--max-tokens 3000] [--model
|
|
9
|
+
description: 'Ask a question. Builds repository context, sends prompt to the local LLM (Ollama / llama.cpp).',
|
|
10
|
+
usage: 'shrk ask "<question>" [--max-tokens 3000] [--provider auto|ollama|llamacpp] [--model <id>] [--dry-run]',
|
|
11
11
|
async run(args) {
|
|
12
12
|
const question = args.positional.join(' ').trim();
|
|
13
13
|
if (!question) {
|
|
@@ -16,6 +16,7 @@ export const askCommand = {
|
|
|
16
16
|
}
|
|
17
17
|
const maxTokens = flagNumber(args, 'max-tokens') ?? 3000;
|
|
18
18
|
const model = flagString(args, 'model');
|
|
19
|
+
const providerKind = flagString(args, 'provider');
|
|
19
20
|
const dryRun = flagBool(args, 'dry-run');
|
|
20
21
|
const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
|
|
21
22
|
const overview = buildProjectOverview(inspection.workspace, inspection.config?.projectName);
|
|
@@ -36,14 +37,14 @@ export const askCommand = {
|
|
|
36
37
|
}
|
|
37
38
|
return 0;
|
|
38
39
|
}
|
|
39
|
-
const
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
if (!provider.isReady()) {
|
|
43
|
-
process.stderr.write('ANTHROPIC_API_KEY is not set. Use --dry-run to print the prompt instead.\n');
|
|
40
|
+
const selection = selectAiProvider(providerKind);
|
|
41
|
+
if (!selection.provider) {
|
|
42
|
+
process.stderr.write('No local LLM is ready. Start Ollama (`ollama serve`) or set LLAMACPP_MODEL_PATH=/path/to/model.gguf in .env. Use --dry-run to print the prompt instead.\n');
|
|
44
43
|
return 1;
|
|
45
44
|
}
|
|
46
|
-
|
|
45
|
+
if (model)
|
|
46
|
+
selection.provider.configure({ model });
|
|
47
|
+
const res = await selection.provider.send({
|
|
47
48
|
messages: [...messages, { role: AiMessageRole.User, content: question }],
|
|
48
49
|
maxTokens: 1024,
|
|
49
50
|
model,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ICommandHandler } from '../command-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* `shrk align` — replace volatile tokens (UUIDs/JWTs/timestamps/hashes) with
|
|
4
|
+
* stable placeholders so a provider KV-cache prefix stays steady across turns.
|
|
5
|
+
* Aligned text → stdout; the reversible map is written to `--map <path>` (or
|
|
6
|
+
* `.sharkcraft/cache-align/align.json`). Pass an existing `--map` to carry
|
|
7
|
+
* ordinals forward. `shrk unalign` restores.
|
|
8
|
+
*/
|
|
9
|
+
export declare const alignCommand: ICommandHandler;
|
|
10
|
+
/** `shrk unalign` — the restore half: turn placeholders back into originals. */
|
|
11
|
+
export declare const unalignCommand: ICommandHandler;
|
|
12
|
+
//# sourceMappingURL=cache-align.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-align.command.d.ts","sourceRoot":"","sources":["../../src/commands/cache-align.command.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAkBhC;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,EAAE,eA4B1B,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,cAAc,EAAE,eAuB5B,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
2
|
+
import * as nodePath from 'node:path';
|
|
3
|
+
import { alignVolatileTokens, restoreVolatileTokens, } from '@shrkcrft/compress';
|
|
4
|
+
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
5
|
+
import { asJson } from "../output/format-output.js";
|
|
6
|
+
function readInput(args) {
|
|
7
|
+
const positional = args.positional[0];
|
|
8
|
+
const useStdin = flagBool(args, 'stdin') || positional === undefined || positional === '-';
|
|
9
|
+
return useStdin ? readFileSync(0, 'utf8') : readFileSync(positional, 'utf8');
|
|
10
|
+
}
|
|
11
|
+
function loadMap(path) {
|
|
12
|
+
if (!path || !existsSync(path))
|
|
13
|
+
return undefined;
|
|
14
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
15
|
+
if (typeof parsed === 'object' && parsed !== null && Array.isArray(parsed.bindings)) {
|
|
16
|
+
return parsed;
|
|
17
|
+
}
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* `shrk align` — replace volatile tokens (UUIDs/JWTs/timestamps/hashes) with
|
|
22
|
+
* stable placeholders so a provider KV-cache prefix stays steady across turns.
|
|
23
|
+
* Aligned text → stdout; the reversible map is written to `--map <path>` (or
|
|
24
|
+
* `.sharkcraft/cache-align/align.json`). Pass an existing `--map` to carry
|
|
25
|
+
* ordinals forward. `shrk unalign` restores.
|
|
26
|
+
*/
|
|
27
|
+
export const alignCommand = {
|
|
28
|
+
name: 'align',
|
|
29
|
+
description: 'Replace volatile tokens with stable placeholders for KV-cache prefix stability; reversible via `shrk unalign`.',
|
|
30
|
+
usage: 'shrk [--cwd <dir>] align [<file>|-] [--stdin] [--map <path>] [--json]',
|
|
31
|
+
run(args) {
|
|
32
|
+
const cwd = resolveCwd(args);
|
|
33
|
+
let content;
|
|
34
|
+
try {
|
|
35
|
+
content = readInput(args);
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
process.stderr.write(`align: cannot read input — ${e.message}\n`);
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
const mapPath = flagString(args, 'map') ?? nodePath.join(cwd, '.sharkcraft', 'cache-align', 'align.json');
|
|
42
|
+
const result = alignVolatileTokens(content, loadMap(mapPath));
|
|
43
|
+
mkdirSync(nodePath.dirname(mapPath), { recursive: true });
|
|
44
|
+
writeFileSync(mapPath, JSON.stringify(result.map, null, 2), 'utf8');
|
|
45
|
+
if (flagBool(args, 'json')) {
|
|
46
|
+
process.stdout.write(asJson({ aligned: result.aligned, map: result.map, replaced: result.replaced }) + '\n');
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
process.stdout.write(result.aligned + '\n');
|
|
50
|
+
process.stderr.write(`aligned: ${result.replaced} token(s) replaced · map → ${mapPath}\n`);
|
|
51
|
+
return 0;
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
/** `shrk unalign` — the restore half: turn placeholders back into originals. */
|
|
55
|
+
export const unalignCommand = {
|
|
56
|
+
name: 'unalign',
|
|
57
|
+
description: 'Restore the original volatile tokens in aligned text using its `--map`.',
|
|
58
|
+
usage: 'shrk [--cwd <dir>] unalign [<file>|-] [--stdin] --map <path>',
|
|
59
|
+
run(args) {
|
|
60
|
+
const cwd = resolveCwd(args);
|
|
61
|
+
const mapPath = flagString(args, 'map') ?? nodePath.join(cwd, '.sharkcraft', 'cache-align', 'align.json');
|
|
62
|
+
const map = loadMap(mapPath);
|
|
63
|
+
if (!map) {
|
|
64
|
+
process.stderr.write(`unalign: no alignment map at "${mapPath}" (pass --map <path>).\n`);
|
|
65
|
+
return 1;
|
|
66
|
+
}
|
|
67
|
+
let content;
|
|
68
|
+
try {
|
|
69
|
+
content = readInput(args);
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
process.stderr.write(`unalign: cannot read input — ${e.message}\n`);
|
|
73
|
+
return 1;
|
|
74
|
+
}
|
|
75
|
+
process.stdout.write(restoreVolatileTokens(content, map) + '\n');
|
|
76
|
+
return 0;
|
|
77
|
+
},
|
|
78
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.command.d.ts","sourceRoot":"","sources":["../../src/commands/check.command.ts"],"names":[],"mappings":"AAmBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"check.command.d.ts","sourceRoot":"","sources":["../../src/commands/check.command.ts"],"names":[],"mappings":"AAmBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAikBhC,eAAO,MAAM,YAAY,EAAE,eA0D1B,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { mkdirSync, writeFileSync, readFileSync, existsSync } from 'node:fs';
|
|
|
3
3
|
import * as nodePath from 'node:path';
|
|
4
4
|
import { flagBool, flagNumber, flagString, flagVars, resolveCwd, } from "../command-registry.js";
|
|
5
5
|
import { asJson, header, kv } from "../output/format-output.js";
|
|
6
|
+
import { maybeRunInWatchMode } from "../output/watch-loop.js";
|
|
6
7
|
import { validateTemplateVariables } from '@shrkcrft/templates';
|
|
7
8
|
import { FileChangeType, planGeneration } from '@shrkcrft/generator';
|
|
8
9
|
import { evaluateBoundaries, loadTsconfigPaths, scanImports, summarizeImports, } from '@shrkcrft/boundaries';
|
|
@@ -305,6 +306,22 @@ function readChangedScopeOptions(args, cwd) {
|
|
|
305
306
|
return out;
|
|
306
307
|
}
|
|
307
308
|
async function checkBoundaries(args) {
|
|
309
|
+
const watchExit = await maybeRunInWatchMode(args, checkBoundariesOnce, {
|
|
310
|
+
defaultPaths: BOUNDARIES_DEFAULT_WATCH_PATHS,
|
|
311
|
+
});
|
|
312
|
+
if (watchExit !== null)
|
|
313
|
+
return watchExit;
|
|
314
|
+
return checkBoundariesOnce(args);
|
|
315
|
+
}
|
|
316
|
+
const BOUNDARIES_DEFAULT_WATCH_PATHS = [
|
|
317
|
+
'sharkcraft',
|
|
318
|
+
'packages',
|
|
319
|
+
'apps',
|
|
320
|
+
'libs',
|
|
321
|
+
'src',
|
|
322
|
+
'tools',
|
|
323
|
+
];
|
|
324
|
+
async function checkBoundariesOnce(args) {
|
|
308
325
|
const cwd = resolveCwd(args);
|
|
309
326
|
const inspection = await inspectSharkcraft({ cwd });
|
|
310
327
|
const rules = inspection.boundaryRegistry.list();
|
|
@@ -504,8 +521,8 @@ async function checkBoundaries(args) {
|
|
|
504
521
|
// ────────────────────────────────────────────────────────────────────────
|
|
505
522
|
export const checkCommand = {
|
|
506
523
|
name: 'check',
|
|
507
|
-
description: 'Run SharkCraft-level validation across knowledge / rules / templates / pipelines / packs / action hints / doctor.',
|
|
508
|
-
usage: 'shrk [--cwd <dir>] check [packs|pipelines|knowledge|generation] [--strict] [--min-score <0-100>] [--json]',
|
|
524
|
+
description: 'Run SharkCraft-level validation across knowledge / rules / templates / pipelines / packs / action hints / doctor. `check boundaries [--watch [--paths a,b] [--debounce N] [--once]]` re-runs the boundary scan on file changes.',
|
|
525
|
+
usage: 'shrk [--cwd <dir>] check [packs|pipelines|knowledge|generation|boundaries|imports] [--strict] [--min-score <0-100>] [--json] [--watch [--paths <list>] [--debounce N] [--once]]',
|
|
509
526
|
async run(args) {
|
|
510
527
|
const sub = args.positional[0];
|
|
511
528
|
if (sub === 'generation')
|
|
@@ -517,6 +534,13 @@ export const checkCommand = {
|
|
|
517
534
|
if (sub === 'registry-lifecycle') {
|
|
518
535
|
const cwd = resolveCwd(args);
|
|
519
536
|
const { buildRegistryLifecycleReport, renderRegistryLifecycleReportText } = await import('@shrkcrft/inspector');
|
|
537
|
+
// The scan is a single synchronous pass with no streamed output; on a
|
|
538
|
+
// large repo it can run for tens of seconds. Without a heartbeat that
|
|
539
|
+
// silence reads as a hang, so announce the work first (human path only —
|
|
540
|
+
// JSON consumers want a clean stdout).
|
|
541
|
+
if (!flagBool(args, 'json')) {
|
|
542
|
+
process.stderr.write('⏳ Scanning source + registries for lifecycle coverage (can take a while on large repos)…\n');
|
|
543
|
+
}
|
|
520
544
|
const report = buildRegistryLifecycleReport({ projectRoot: cwd });
|
|
521
545
|
if (flagBool(args, 'json')) {
|
|
522
546
|
process.stdout.write(asJson(report) + '\n');
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ICommandHandler } from '../command-registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* `shrk code-intel` — one-shot view of the 14 code-intelligence
|
|
4
|
+
* doctor checks. Independent of `shrk doctor` so callers (agents,
|
|
5
|
+
* inner-loop scripts, the dashboard) can pull just this section
|
|
6
|
+
* without parsing through unrelated config / knowledge findings.
|
|
7
|
+
*
|
|
8
|
+
* Output modes:
|
|
9
|
+
* - text (default): grouped by severity, one line per finding.
|
|
10
|
+
* - --json: machine-readable, including the full check list.
|
|
11
|
+
* - --markdown: PR-comment-ready rendering.
|
|
12
|
+
*
|
|
13
|
+
* Filters:
|
|
14
|
+
* - --only ok,warning,error,info — restrict severities.
|
|
15
|
+
* - --check <id> — show only one check id.
|
|
16
|
+
*/
|
|
17
|
+
export declare const codeIntelCommand: ICommandHandler;
|
|
18
|
+
//# sourceMappingURL=code-intel.command.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-intel.command.d.ts","sourceRoot":"","sources":["../../src/commands/code-intel.command.ts"],"names":[],"mappings":"AAKA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAGhC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB,EAAE,eAuE9B,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { buildCodeIntelligenceChecks, DoctorSeverity, } from '@shrkcrft/inspector';
|
|
2
|
+
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
3
|
+
import { asJson, header, kv } from "../output/format-output.js";
|
|
4
|
+
/**
|
|
5
|
+
* `shrk code-intel` — one-shot view of the 14 code-intelligence
|
|
6
|
+
* doctor checks. Independent of `shrk doctor` so callers (agents,
|
|
7
|
+
* inner-loop scripts, the dashboard) can pull just this section
|
|
8
|
+
* without parsing through unrelated config / knowledge findings.
|
|
9
|
+
*
|
|
10
|
+
* Output modes:
|
|
11
|
+
* - text (default): grouped by severity, one line per finding.
|
|
12
|
+
* - --json: machine-readable, including the full check list.
|
|
13
|
+
* - --markdown: PR-comment-ready rendering.
|
|
14
|
+
*
|
|
15
|
+
* Filters:
|
|
16
|
+
* - --only ok,warning,error,info — restrict severities.
|
|
17
|
+
* - --check <id> — show only one check id.
|
|
18
|
+
*/
|
|
19
|
+
export const codeIntelCommand = {
|
|
20
|
+
name: 'code-intel',
|
|
21
|
+
description: 'One-shot view of code-intelligence doctor checks (graph, rule-graph, api-surface, quality-gate, migrations, architecture, impact, framework, structural-search, context-planner). Read-only.',
|
|
22
|
+
usage: 'shrk [--cwd <dir>] code-intel [--json] [--markdown] [--only ok,warning,error,info] [--check <id>] [--stale-days N]',
|
|
23
|
+
async run(args) {
|
|
24
|
+
const cwd = resolveCwd(args);
|
|
25
|
+
const wantJson = flagBool(args, 'json');
|
|
26
|
+
const wantMarkdown = flagBool(args, 'markdown');
|
|
27
|
+
const onlyRaw = flagString(args, 'only');
|
|
28
|
+
const checkId = flagString(args, 'check');
|
|
29
|
+
const staleDaysRaw = flagString(args, 'stale-days');
|
|
30
|
+
const staleDays = staleDaysRaw ? Number.parseInt(staleDaysRaw, 10) : undefined;
|
|
31
|
+
const options = {};
|
|
32
|
+
if (typeof staleDays === 'number' && Number.isFinite(staleDays) && staleDays > 0) {
|
|
33
|
+
options.staleThresholdDays = staleDays;
|
|
34
|
+
}
|
|
35
|
+
let checks = buildCodeIntelligenceChecks(cwd, options);
|
|
36
|
+
if (checkId) {
|
|
37
|
+
checks = checks.filter((c) => c.id === checkId);
|
|
38
|
+
}
|
|
39
|
+
if (onlyRaw) {
|
|
40
|
+
const allowed = new Set(onlyRaw
|
|
41
|
+
.split(',')
|
|
42
|
+
.map((s) => s.trim().toLowerCase())
|
|
43
|
+
.filter((s) => s.length > 0));
|
|
44
|
+
checks = checks.filter((c) => allowed.has(severityKey(c.severity)));
|
|
45
|
+
}
|
|
46
|
+
const summary = summarize(checks);
|
|
47
|
+
if (wantJson) {
|
|
48
|
+
process.stdout.write(asJson({
|
|
49
|
+
schema: 'sharkcraft.code-intelligence-state/v1',
|
|
50
|
+
totalChecks: checks.length,
|
|
51
|
+
summary,
|
|
52
|
+
checks,
|
|
53
|
+
}) + '\n');
|
|
54
|
+
return exitCode(summary);
|
|
55
|
+
}
|
|
56
|
+
if (wantMarkdown) {
|
|
57
|
+
process.stdout.write(renderMarkdown(checks, summary));
|
|
58
|
+
return exitCode(summary);
|
|
59
|
+
}
|
|
60
|
+
process.stdout.write(header('Code-intelligence state'));
|
|
61
|
+
process.stdout.write(kv('summary', `ok=${summary.ok} info=${summary.info} warnings=${summary.warnings} errors=${summary.errors}`) + '\n');
|
|
62
|
+
if (checks.length === 0) {
|
|
63
|
+
process.stdout.write('\nNo code-intelligence state on disk yet — opt in by running `shrk graph index`.\n');
|
|
64
|
+
return 0;
|
|
65
|
+
}
|
|
66
|
+
process.stdout.write('\n');
|
|
67
|
+
for (const c of checks) {
|
|
68
|
+
const icon = severityIcon(c.severity);
|
|
69
|
+
const advisory = c.advisory ? ' (advisory)' : '';
|
|
70
|
+
process.stdout.write(`${icon} ${c.id}${advisory}\n`);
|
|
71
|
+
process.stdout.write(` ${c.title}\n`);
|
|
72
|
+
process.stdout.write(` ${c.message}\n`);
|
|
73
|
+
if (c.fix)
|
|
74
|
+
process.stdout.write(` → ${c.fix}\n`);
|
|
75
|
+
if (c.whyThisMatters)
|
|
76
|
+
process.stdout.write(` why: ${c.whyThisMatters}\n`);
|
|
77
|
+
process.stdout.write('\n');
|
|
78
|
+
}
|
|
79
|
+
return exitCode(summary);
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
function severityKey(severity) {
|
|
83
|
+
return severity;
|
|
84
|
+
}
|
|
85
|
+
function severityIcon(severity) {
|
|
86
|
+
switch (severity) {
|
|
87
|
+
case DoctorSeverity.Ok:
|
|
88
|
+
return '✓';
|
|
89
|
+
case DoctorSeverity.Info:
|
|
90
|
+
return 'ℹ';
|
|
91
|
+
case DoctorSeverity.Warning:
|
|
92
|
+
return '⚠';
|
|
93
|
+
case DoctorSeverity.Error:
|
|
94
|
+
return '✗';
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function summarize(checks) {
|
|
98
|
+
const s = { ok: 0, info: 0, warnings: 0, errors: 0 };
|
|
99
|
+
for (const c of checks) {
|
|
100
|
+
if (c.severity === DoctorSeverity.Ok)
|
|
101
|
+
s.ok += 1;
|
|
102
|
+
else if (c.severity === DoctorSeverity.Info)
|
|
103
|
+
s.info += 1;
|
|
104
|
+
else if (c.severity === DoctorSeverity.Warning)
|
|
105
|
+
s.warnings += 1;
|
|
106
|
+
else if (c.severity === DoctorSeverity.Error)
|
|
107
|
+
s.errors += 1;
|
|
108
|
+
}
|
|
109
|
+
return s;
|
|
110
|
+
}
|
|
111
|
+
function exitCode(summary) {
|
|
112
|
+
// Exit 1 if any non-advisory warning or error remains. Advisory
|
|
113
|
+
// warnings are reported but never fail the command — they're hints,
|
|
114
|
+
// not blockers (same contract as `shrk doctor`).
|
|
115
|
+
return summary.errors > 0 ? 1 : 0;
|
|
116
|
+
}
|
|
117
|
+
function renderMarkdown(checks, summary) {
|
|
118
|
+
const lines = [];
|
|
119
|
+
lines.push('# SharkCraft code-intelligence state');
|
|
120
|
+
lines.push('');
|
|
121
|
+
lines.push('| ok | info | warnings | errors |');
|
|
122
|
+
lines.push('|---|---|---|---|');
|
|
123
|
+
lines.push(`| ${summary.ok} | ${summary.info} | ${summary.warnings} | ${summary.errors} |`);
|
|
124
|
+
lines.push('');
|
|
125
|
+
if (checks.length === 0) {
|
|
126
|
+
lines.push('_(no code-intelligence state on disk yet)_');
|
|
127
|
+
return lines.join('\n') + '\n';
|
|
128
|
+
}
|
|
129
|
+
for (const c of checks) {
|
|
130
|
+
const icon = severityIcon(c.severity);
|
|
131
|
+
const advisory = c.advisory ? ' _(advisory)_' : '';
|
|
132
|
+
lines.push(`### ${icon} \`${c.id}\` — ${c.title}${advisory}`);
|
|
133
|
+
lines.push('');
|
|
134
|
+
lines.push(c.message);
|
|
135
|
+
if (c.fix) {
|
|
136
|
+
lines.push('');
|
|
137
|
+
lines.push(`**Fix:** ${c.fix}`);
|
|
138
|
+
}
|
|
139
|
+
if (c.whyThisMatters) {
|
|
140
|
+
lines.push('');
|
|
141
|
+
lines.push(`**Why:** ${c.whyThisMatters}`);
|
|
142
|
+
}
|
|
143
|
+
lines.push('');
|
|
144
|
+
}
|
|
145
|
+
return lines.join('\n') + '\n';
|
|
146
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codemod.command.d.ts","sourceRoot":"","sources":["../../src/commands/codemod.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codemod.command.d.ts","sourceRoot":"","sources":["../../src/commands/codemod.command.ts"],"names":[],"mappings":"AAiBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAuEhC,eAAO,MAAM,cAAc,EAAE,eAsE5B,CAAC"}
|