@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph.command.d.ts","sourceRoot":"","sources":["../../src/commands/graph.command.ts"],"names":[],"mappings":"AAUA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"graph.command.d.ts","sourceRoot":"","sources":["../../src/commands/graph.command.ts"],"names":[],"mappings":"AAUA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA4BhC,eAAO,MAAM,YAAY,EAAE,eA+M1B,CAAC"}
|
|
@@ -3,6 +3,7 @@ import * as nodePath from 'node:path';
|
|
|
3
3
|
import { analyzeImportGraph, buildKnowledgeGraph, findGraphPath, getGraphNode, inspectSharkcraft, } from '@shrkcrft/inspector';
|
|
4
4
|
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
5
5
|
import { asJson, header, kv } from "../output/format-output.js";
|
|
6
|
+
import { runGraphCallers, runGraphContext, runGraphCycles, runGraphDeps, runGraphHubs, runGraphImpact, runGraphIndex, runGraphPath, runGraphSearch, runGraphStatus, runGraphUnresolved, } from "./graph-code-subverbs.js";
|
|
6
7
|
const KNOWN_KINDS = [
|
|
7
8
|
'knowledge',
|
|
8
9
|
'rule',
|
|
@@ -16,9 +17,37 @@ const KNOWN_KINDS = [
|
|
|
16
17
|
];
|
|
17
18
|
export const graphCommand = {
|
|
18
19
|
name: 'graph',
|
|
19
|
-
description: 'Show the SharkCraft knowledge graph
|
|
20
|
-
usage: 'shrk [--cwd <dir>] graph [<id>] [--type <kind>] [--format text|json|dot|mermaid] [--output <file>] [--json]
|
|
20
|
+
description: 'Show the SharkCraft knowledge graph and the code-intelligence graph surface. Use `shrk graph <id>` for asset-graph nodes and `shrk graph index|status|search|context|impact|path|hubs|callers|cycles|unresolved|deps|why|export` for code-graph workflows.',
|
|
21
|
+
usage: 'shrk [--cwd <dir>] graph [<id>] [--type <kind>] [--format text|json|dot|mermaid] [--output <file>] [--json]\n' +
|
|
22
|
+
'shrk graph index|status|search|context|impact|path|hubs|callers|cycles|unresolved|deps|why|export ...\n' +
|
|
23
|
+
'shrk graph path <from> <to> — is code A wired to code B? (shortest import/call path)\n' +
|
|
24
|
+
'shrk graph hubs [--limit N] [--path <dir>] — most-depended-on symbols/files (load-bearing code; scope to a subsystem)',
|
|
21
25
|
async run(args) {
|
|
26
|
+
// Code-intelligence subverbs (R65) don't need the knowledge graph —
|
|
27
|
+
// dispatch them before the expensive inspection so they stay fast.
|
|
28
|
+
const earlySub = args.positional[0];
|
|
29
|
+
if (earlySub === 'index')
|
|
30
|
+
return runGraphIndex(args);
|
|
31
|
+
if (earlySub === 'status')
|
|
32
|
+
return runGraphStatus(args);
|
|
33
|
+
if (earlySub === 'search')
|
|
34
|
+
return runGraphSearch(args);
|
|
35
|
+
if (earlySub === 'context')
|
|
36
|
+
return runGraphContext(args);
|
|
37
|
+
if (earlySub === 'impact')
|
|
38
|
+
return runGraphImpact(args);
|
|
39
|
+
if (earlySub === 'path')
|
|
40
|
+
return runGraphPath(args);
|
|
41
|
+
if (earlySub === 'hubs')
|
|
42
|
+
return runGraphHubs(args);
|
|
43
|
+
if (earlySub === 'callers')
|
|
44
|
+
return runGraphCallers(args);
|
|
45
|
+
if (earlySub === 'cycles')
|
|
46
|
+
return runGraphCycles(args);
|
|
47
|
+
if (earlySub === 'unresolved')
|
|
48
|
+
return runGraphUnresolved(args);
|
|
49
|
+
if (earlySub === 'deps')
|
|
50
|
+
return runGraphDeps({ ...args, positional: args.positional.slice(1) });
|
|
22
51
|
const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
|
|
23
52
|
const graph = buildKnowledgeGraph(inspection);
|
|
24
53
|
const sub = args.positional[0];
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { CommandRegistry } from '../command-registry.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Product start screen for bare `shrk` / `shrk --help`. Shows the
|
|
4
|
+
* curated ~20-command "starter" surface organized by workflow phase.
|
|
5
|
+
* Everything else stays callable; users see the full ~70-verb catalog
|
|
6
|
+
* via `shrk --full-help` or browse it through `shrk surface list`.
|
|
6
7
|
*
|
|
7
8
|
* Returns the lines (without trailing newline). Pulled into a function
|
|
8
9
|
* so tests can assert on the structure without grepping stdout.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.command.d.ts","sourceRoot":"","sources":["../../src/commands/help.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"help.command.d.ts","sourceRoot":"","sources":["../../src/commands/help.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAqB9D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAwC1C;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe;;;;cAK3C;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAA;KAAE,GAAG,MAAM;EA2HpF"}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
import { header } from "../output/format-output.js";
|
|
2
|
+
import { COMMAND_CATALOG, defaultShowInHelp } from "./command-catalog.js";
|
|
3
|
+
const EXTRA_HELP_LINES = Object.freeze({
|
|
4
|
+
graph: [
|
|
5
|
+
'',
|
|
6
|
+
'Code-intelligence subverbs:',
|
|
7
|
+
' graph index — build or refresh the code graph',
|
|
8
|
+
' graph status — freshness, counts, and unresolved-import summary',
|
|
9
|
+
' graph search — find files/symbols/packages in the code graph',
|
|
10
|
+
' graph context — inspect one file or symbol with bridge enrichment',
|
|
11
|
+
' graph impact — reverse dependent closure for a file or symbol',
|
|
12
|
+
' graph callers — files that call/reference a symbol',
|
|
13
|
+
' graph cycles — list import cycles',
|
|
14
|
+
' graph unresolved — list unresolved imports grouped by file',
|
|
15
|
+
' graph deps — inbound/outbound package dependencies',
|
|
16
|
+
' graph why — shortest-path explanation in the knowledge graph',
|
|
17
|
+
],
|
|
18
|
+
});
|
|
2
19
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
20
|
+
* Product start screen for bare `shrk` / `shrk --help`. Shows the
|
|
21
|
+
* curated ~20-command "starter" surface organized by workflow phase.
|
|
22
|
+
* Everything else stays callable; users see the full ~70-verb catalog
|
|
23
|
+
* via `shrk --full-help` or browse it through `shrk surface list`.
|
|
6
24
|
*
|
|
7
25
|
* Returns the lines (without trailing newline). Pulled into a function
|
|
8
26
|
* so tests can assert on the structure without grepping stdout.
|
|
@@ -12,20 +30,37 @@ export function renderStartScreen() {
|
|
|
12
30
|
lines.push('SharkCraft CLI — deterministic, local-first project intelligence for AI coding agents.');
|
|
13
31
|
lines.push('Usage: shrk [--cwd <dir>] <command> [...args]');
|
|
14
32
|
lines.push('');
|
|
15
|
-
lines.push('
|
|
16
|
-
lines.push(' $ shrk
|
|
33
|
+
lines.push('Bootstrap:');
|
|
34
|
+
lines.push(' $ shrk init --infer --write — scan the repo + populate sharkcraft/ from real signals (new repos)');
|
|
17
35
|
lines.push(' $ shrk doctor — is the workspace healthy?');
|
|
18
|
-
lines.push(' $ shrk
|
|
19
|
-
lines.push('
|
|
20
|
-
lines.push('
|
|
21
|
-
lines.push(' $ shrk
|
|
36
|
+
lines.push(' $ shrk onboard — analyze an existing repo (advisory)');
|
|
37
|
+
lines.push('');
|
|
38
|
+
lines.push('Use it for a task:');
|
|
39
|
+
lines.push(' $ shrk recommend "<task>" — what should I do?');
|
|
40
|
+
lines.push(' $ shrk context --task "<task>" — token-budgeted relevant context');
|
|
41
|
+
lines.push(' $ shrk task "<task>" — full AI-ready task packet (JSON)');
|
|
42
|
+
lines.push(' $ shrk why <file> — which rules govern this file');
|
|
43
|
+
lines.push(' $ shrk impact <file> — blast radius: what breaks if I change this');
|
|
44
|
+
lines.push('');
|
|
45
|
+
lines.push('Generate code safely:');
|
|
46
|
+
lines.push(' $ shrk gen <template> <name> — generate from template (dry-run by default)');
|
|
47
|
+
lines.push(' $ shrk apply <plan.json> — apply a reviewed plan (CLI is the only write path)');
|
|
48
|
+
lines.push(' $ shrk check boundaries — enforce layer / import boundaries');
|
|
49
|
+
lines.push(' $ shrk quality — pre-PR gate (doctor + boundaries + coverage + drift)');
|
|
50
|
+
lines.push('');
|
|
51
|
+
lines.push('Browse what shrk knows:');
|
|
52
|
+
lines.push(' $ shrk graph status — code-graph freshness and health');
|
|
53
|
+
lines.push(' $ shrk coverage — what knowledge is missing');
|
|
54
|
+
lines.push(' $ shrk knowledge list — knowledge entries');
|
|
55
|
+
lines.push('');
|
|
56
|
+
lines.push('Run shrk for an agent:');
|
|
57
|
+
lines.push(' $ shrk mcp serve — start the MCP server (stdio) for live queries');
|
|
58
|
+
lines.push(' $ shrk dashboard — start the local read-only dashboard');
|
|
22
59
|
lines.push('');
|
|
23
|
-
lines.push('Discover the rest (
|
|
24
|
-
lines.push(' $ shrk surface list — full
|
|
25
|
-
lines.push(' $ shrk surface profiles — named profiles (small-app / monorepo / ci / agent / pack-author)');
|
|
26
|
-
lines.push(' $ shrk surface explain <cmd> — why a command has its current tier');
|
|
60
|
+
lines.push('Discover the rest (everything stays callable — this screen shows ~17 of ~70 verbs):');
|
|
61
|
+
lines.push(' $ shrk surface list — full catalog by tier');
|
|
27
62
|
lines.push(' $ shrk help <command> — usage for a specific command');
|
|
28
|
-
lines.push(' $ shrk --full-help —
|
|
63
|
+
lines.push(' $ shrk --full-help — long, exhaustive help');
|
|
29
64
|
lines.push(' $ shrk --about — what shrk is and is not');
|
|
30
65
|
lines.push('');
|
|
31
66
|
lines.push('Free-form input is fine — `shrk "<task>"` routes to `shrk recommend`.');
|
|
@@ -48,10 +83,13 @@ export function makeHelpCommand(registry) {
|
|
|
48
83
|
? args.positional[0].split(/\s+/).filter(Boolean)
|
|
49
84
|
: args.positional.filter(Boolean);
|
|
50
85
|
const { handler, matchedPath, node } = registry.resolve(tokens);
|
|
51
|
-
if (handler && matchedPath.join(' ') === tokens.join(' ')) {
|
|
86
|
+
if (handler && matchedPath.join(' ') === tokens.join(' ') && node.children.size === 0) {
|
|
52
87
|
// Exact match on a callable command.
|
|
53
88
|
const canonical = registry.listCommandAliases().get(tokens[0]);
|
|
54
89
|
process.stdout.write(`${matchedPath.join(' ')} — ${handler.description}\n${handler.usage}\n`);
|
|
90
|
+
const extra = EXTRA_HELP_LINES[matchedPath.join(' ')];
|
|
91
|
+
if (extra)
|
|
92
|
+
process.stdout.write(extra.join('\n') + '\n');
|
|
55
93
|
if (canonical && tokens.length === 1) {
|
|
56
94
|
process.stdout.write(`(alias for: ${canonical})\n`);
|
|
57
95
|
}
|
|
@@ -89,13 +127,41 @@ export function makeHelpCommand(registry) {
|
|
|
89
127
|
process.stdout.write(renderStartScreen());
|
|
90
128
|
return 0;
|
|
91
129
|
}
|
|
130
|
+
const wantsAll = args.flags.get('all') === true;
|
|
92
131
|
process.stdout.write(`SharkCraft CLI — structured project intelligence for AI coding agents\n`);
|
|
93
132
|
process.stdout.write(`Usage: shrk [--cwd <dir>] <command> [...args]\n`);
|
|
133
|
+
// The catalog has ~360 entries; only ~30 top-level verbs pay
|
|
134
|
+
// rent (see PRIMARY_VERBS_ALLOWLIST in command-catalog.ts).
|
|
135
|
+
// Default --full-help filters to that set; `--full-help --all`
|
|
136
|
+
// dumps the entire catalog for power users.
|
|
137
|
+
const visibleVerbs = new Set();
|
|
138
|
+
if (!wantsAll) {
|
|
139
|
+
for (const entry of COMMAND_CATALOG) {
|
|
140
|
+
if (defaultShowInHelp(entry)) {
|
|
141
|
+
const verb = entry.command.split(/\s+/)[0] ?? '';
|
|
142
|
+
if (verb)
|
|
143
|
+
visibleVerbs.add(verb);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const visibleTopLevel = registry.list().filter((c) => {
|
|
148
|
+
if (wantsAll)
|
|
149
|
+
return true;
|
|
150
|
+
return visibleVerbs.has(c.name);
|
|
151
|
+
});
|
|
94
152
|
process.stdout.write(header('Top-level commands'));
|
|
95
|
-
for (const c of
|
|
153
|
+
for (const c of visibleTopLevel) {
|
|
96
154
|
process.stdout.write(` ${c.name.padEnd(10)} — ${c.description}\n`);
|
|
97
155
|
}
|
|
98
|
-
|
|
156
|
+
if (!wantsAll) {
|
|
157
|
+
const hiddenCount = registry.list().length - visibleTopLevel.length;
|
|
158
|
+
if (hiddenCount > 0) {
|
|
159
|
+
process.stdout.write(`\n …and ${hiddenCount} more, hidden from default help. Run \`shrk --full-help --all\` to see them, ` +
|
|
160
|
+
`or \`shrk surface list\` to browse by tier.\n`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// Show each canonical group once — also filtered by the allowlist
|
|
164
|
+
// unless --all was passed.
|
|
99
165
|
const canonicalGroups = [];
|
|
100
166
|
const aliasMap = registry.listGroupAliases();
|
|
101
167
|
const seen = new Set();
|
|
@@ -103,7 +169,9 @@ export function makeHelpCommand(registry) {
|
|
|
103
169
|
const canonical = aliasMap.get(g) ?? g;
|
|
104
170
|
if (!seen.has(canonical)) {
|
|
105
171
|
seen.add(canonical);
|
|
106
|
-
|
|
172
|
+
if (wantsAll || visibleVerbs.has(canonical)) {
|
|
173
|
+
canonicalGroups.push(canonical);
|
|
174
|
+
}
|
|
107
175
|
}
|
|
108
176
|
}
|
|
109
177
|
const aliasesByCanonical = new Map();
|
|
@@ -85,7 +85,7 @@ export const helperPlanCommand = {
|
|
|
85
85
|
// profile is available. Today the helper-registry detects this inside
|
|
86
86
|
// buildHelperPlan via requireProfile(); we surface a friendly message.
|
|
87
87
|
if ('requiresProfile' in def && def.requiresProfile) {
|
|
88
|
-
process.stderr.write(`Helper "${id}" requires a
|
|
88
|
+
process.stderr.write(`Helper "${id}" requires a registered profile. Available:\n $ shrk profiles list\n`);
|
|
89
89
|
// Still try to build the plan; the registry throws with the same idea.
|
|
90
90
|
}
|
|
91
91
|
const cwd = resolveCwd(args);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"impact.command.d.ts","sourceRoot":"","sources":["../../src/commands/impact.command.ts"],"names":[],"mappings":"AAsBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"impact.command.d.ts","sourceRoot":"","sources":["../../src/commands/impact.command.ts"],"names":[],"mappings":"AAsBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA0VhC,eAAO,MAAM,aAAa,EAAE,eA8V3B,CAAC"}
|
|
@@ -2,7 +2,7 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
2
2
|
import * as nodePath from 'node:path';
|
|
3
3
|
import { analyzeImpact, analyzeTestImpact, findSymbolInProject, FuzzyImpactSourceKind, getChangedFiles, ImpactInputKind, inspectSharkcraft, QueryMatchKind, readFeatureBundle, renderImpactGraph, renderImpactHtml, renderImpactMarkdown, renderImpactText, resolveFuzzyImpact, warmConstructCache, } from '@shrkcrft/inspector';
|
|
4
4
|
import { flagBool, flagNumber, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
5
|
-
import { asJson, header } from "../output/format-output.js";
|
|
5
|
+
import { asJson, header, kv } from "../output/format-output.js";
|
|
6
6
|
function collectFiles(args, cwd) {
|
|
7
7
|
const diagnostics = [];
|
|
8
8
|
const explicitFiles = flagList(args, 'files');
|
|
@@ -199,6 +199,85 @@ async function emitCodemodPlan(opts) {
|
|
|
199
199
|
}
|
|
200
200
|
return 0;
|
|
201
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* --via-graph adapter: takes the same input flags as `shrk impact` and
|
|
204
|
+
* routes through `@shrkcrft/impact-engine` for the v3 graph-backed
|
|
205
|
+
* payload. Defers to that engine; emits a clean error when the graph
|
|
206
|
+
* isn't indexed yet.
|
|
207
|
+
*/
|
|
208
|
+
async function runViaGraph(args) {
|
|
209
|
+
const cwd = resolveCwd(args);
|
|
210
|
+
const wantJson = flagBool(args, 'json') || flagString(args, 'format') === 'json';
|
|
211
|
+
const positional = args.positional[0];
|
|
212
|
+
const viaGraphRaw = args.flags.get('via-graph');
|
|
213
|
+
const files = flagList(args, 'files');
|
|
214
|
+
const since = flagString(args, 'since');
|
|
215
|
+
const symbol = flagString(args, 'symbol');
|
|
216
|
+
const fileFlag = flagString(args, 'file');
|
|
217
|
+
const limit = flagNumber(args, 'limit') ?? 200;
|
|
218
|
+
const maxDepth = flagNumber(args, 'max-depth') ?? 5;
|
|
219
|
+
const target = positional ?? fileFlag ?? (typeof viaGraphRaw === 'string' ? viaGraphRaw : undefined);
|
|
220
|
+
const inputs = files.length > 0
|
|
221
|
+
? { kind: 'files', files }
|
|
222
|
+
: symbol
|
|
223
|
+
? { kind: 'symbol', symbolId: symbol }
|
|
224
|
+
: since
|
|
225
|
+
? { kind: 'gitref', ref: since }
|
|
226
|
+
: target
|
|
227
|
+
? { kind: 'files', files: [target] }
|
|
228
|
+
: undefined;
|
|
229
|
+
if (!inputs) {
|
|
230
|
+
process.stderr.write('Usage: shrk impact --via-graph <fileOrQuery> | --symbol <name> | --files a,b | --since <ref>\n');
|
|
231
|
+
return 2;
|
|
232
|
+
}
|
|
233
|
+
const { analyzeGraphImpact, ImpactReportStore, snapshotImpactAnalysis } = await import('@shrkcrft/impact-engine');
|
|
234
|
+
const analysis = analyzeGraphImpact(inputs, { projectRoot: cwd, limit, maxDepth });
|
|
235
|
+
// Persist a compact snapshot for the doctor + dashboard to read.
|
|
236
|
+
// `--no-persist` opts out (useful when scripting against many trees
|
|
237
|
+
// or when stdout is the only sink the caller cares about).
|
|
238
|
+
const noPersist = flagBool(args, 'no-persist');
|
|
239
|
+
if (!noPersist) {
|
|
240
|
+
try {
|
|
241
|
+
const summary = inputs.kind === 'files'
|
|
242
|
+
? inputs.files.slice(0, 3).join(', ') + (inputs.files.length > 3 ? '…' : '')
|
|
243
|
+
: inputs.kind === 'symbol'
|
|
244
|
+
? `symbol:${inputs.symbolId}`
|
|
245
|
+
: `gitref:${inputs.ref}`;
|
|
246
|
+
new ImpactReportStore(cwd).write(snapshotImpactAnalysis(analysis, summary));
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
// best-effort — never fail the command on a persistence error
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (wantJson) {
|
|
253
|
+
process.stdout.write(asJson(analysis) + '\n');
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
256
|
+
process.stdout.write(header(`Impact (graph): ${target ?? symbol ?? files.join(',') ?? since}`));
|
|
257
|
+
process.stdout.write(` risk: ${analysis.risk}\n`);
|
|
258
|
+
process.stdout.write(` direct dependents: ${analysis.directDependents.length}\n`);
|
|
259
|
+
process.stdout.write(` transitive dependents: ${analysis.transitiveDependents.length}\n`);
|
|
260
|
+
process.stdout.write(` affected symbols: ${analysis.affectedSymbols.length}\n`);
|
|
261
|
+
process.stdout.write(` caller files: ${analysis.affectedCallerFiles.length}\n`);
|
|
262
|
+
process.stdout.write(` affected packages: ${analysis.affectedPackages.length}\n`);
|
|
263
|
+
process.stdout.write(` affected rules: ${analysis.affectedRules.length}\n`);
|
|
264
|
+
process.stdout.write(` affected templates: ${analysis.affectedTemplates.length}\n`);
|
|
265
|
+
process.stdout.write(` likely tests: ${analysis.likelyTests.length}\n`);
|
|
266
|
+
process.stdout.write(` public API touched: ${analysis.publicApiTouched ? 'yes' : 'no'}\n`);
|
|
267
|
+
if (analysis.riskReasons.length > 0) {
|
|
268
|
+
process.stdout.write('\nRisk reasons:\n');
|
|
269
|
+
for (const r of analysis.riskReasons)
|
|
270
|
+
process.stdout.write(` • ${r}\n`);
|
|
271
|
+
}
|
|
272
|
+
if (analysis.validationScope.length > 0) {
|
|
273
|
+
process.stdout.write('\nRun before merging:\n');
|
|
274
|
+
for (const c of analysis.validationScope)
|
|
275
|
+
process.stdout.write(` $ ${c}\n`);
|
|
276
|
+
}
|
|
277
|
+
for (const d of analysis.diagnostics.slice(0, 5))
|
|
278
|
+
process.stdout.write(`! ${d}\n`);
|
|
279
|
+
return 0;
|
|
280
|
+
}
|
|
202
281
|
export const impactCommand = {
|
|
203
282
|
name: 'impact',
|
|
204
283
|
description: 'Architecture impact analysis: direct + transitive dependents, risk + suggested commands. Supports fuzzy <query> resolution. Read-only.',
|
|
@@ -210,6 +289,16 @@ export const impactCommand = {
|
|
|
210
289
|
if (args.positional[0] === 'graph') {
|
|
211
290
|
return runImpactGraph({ ...args, positional: args.positional.slice(1) });
|
|
212
291
|
}
|
|
292
|
+
if (args.positional[0] === 'baseline') {
|
|
293
|
+
return runImpactBaseline({ ...args, positional: args.positional.slice(1) });
|
|
294
|
+
}
|
|
295
|
+
// --via-graph: route through @shrkcrft/impact-engine for the v3
|
|
296
|
+
// graph-backed payload (sharkcraft.graph-impact-analysis/v3). Keeps
|
|
297
|
+
// the legacy v2 inspector path as the default so existing
|
|
298
|
+
// consumers don't shift.
|
|
299
|
+
if (args.flags.has('via-graph')) {
|
|
300
|
+
return runViaGraph(args);
|
|
301
|
+
}
|
|
213
302
|
const cwd = resolveCwd(args);
|
|
214
303
|
const inspection = await inspectSharkcraft({ cwd });
|
|
215
304
|
// Warm construct cache so fuzzy resolution can map plugin keys / events /
|
|
@@ -817,3 +906,84 @@ function renderResolutionMd(r) {
|
|
|
817
906
|
}
|
|
818
907
|
// Sentinel — keep `QueryMatchKind` import alive for tooling. Used inside fuzzy-impact.ts.
|
|
819
908
|
void QueryMatchKind;
|
|
909
|
+
async function runImpactBaseline(args) {
|
|
910
|
+
const cwd = resolveCwd(args);
|
|
911
|
+
const wantJson = flagBool(args, 'json');
|
|
912
|
+
const verb = args.positional[0] ?? 'show';
|
|
913
|
+
const { ImpactReportStore, diffImpactReports } = await import('@shrkcrft/impact-engine');
|
|
914
|
+
const store = new ImpactReportStore(cwd);
|
|
915
|
+
if (verb === 'write') {
|
|
916
|
+
const last = store.read();
|
|
917
|
+
if (!last) {
|
|
918
|
+
const msg = `No recent impact run at ${store.absPath}. Run \`shrk impact --via-graph <target>\` first.\n`;
|
|
919
|
+
if (wantJson) {
|
|
920
|
+
process.stdout.write(asJson({ ok: false, error: 'no-last-run' }) + '\n');
|
|
921
|
+
return 1;
|
|
922
|
+
}
|
|
923
|
+
process.stderr.write(msg);
|
|
924
|
+
return 1;
|
|
925
|
+
}
|
|
926
|
+
store.writeBaseline(last);
|
|
927
|
+
if (wantJson) {
|
|
928
|
+
process.stdout.write(asJson({ wrote: store.baselinePath, baseline: last }) + '\n');
|
|
929
|
+
return 0;
|
|
930
|
+
}
|
|
931
|
+
process.stdout.write(`Impact baseline written → ${store.baselinePath}\n`);
|
|
932
|
+
process.stdout.write(` Input: ${last.inputSummary}\n` +
|
|
933
|
+
` Risk: ${last.risk}\n` +
|
|
934
|
+
` Dependents: ${last.directDependentCount} direct, ${last.transitiveDependentCount} transitive\n` +
|
|
935
|
+
` Packages: ${last.affectedPackageCount}\n`);
|
|
936
|
+
return 0;
|
|
937
|
+
}
|
|
938
|
+
if (verb === 'show') {
|
|
939
|
+
const baseline = store.readBaseline();
|
|
940
|
+
if (!baseline) {
|
|
941
|
+
const msg = `No baseline at ${store.baselinePath}. Run \`shrk impact baseline write\` to freeze the current run.\n`;
|
|
942
|
+
if (wantJson) {
|
|
943
|
+
process.stdout.write(asJson({ baseline: null, path: store.baselinePath }) + '\n');
|
|
944
|
+
return 1;
|
|
945
|
+
}
|
|
946
|
+
process.stderr.write(msg);
|
|
947
|
+
return 1;
|
|
948
|
+
}
|
|
949
|
+
const last = store.read();
|
|
950
|
+
if (wantJson) {
|
|
951
|
+
process.stdout.write(asJson({
|
|
952
|
+
path: store.baselinePath,
|
|
953
|
+
baseline,
|
|
954
|
+
...(last ? { last, delta: diffImpactReports(baseline, last) } : {}),
|
|
955
|
+
}) + '\n');
|
|
956
|
+
return 0;
|
|
957
|
+
}
|
|
958
|
+
process.stdout.write(header('Impact baseline'));
|
|
959
|
+
process.stdout.write(kv('path', store.baselinePath) + '\n');
|
|
960
|
+
process.stdout.write(kv('input', baseline.inputSummary) + '\n');
|
|
961
|
+
process.stdout.write(kv('risk', baseline.risk) + '\n');
|
|
962
|
+
process.stdout.write(kv('dependents', `${baseline.directDependentCount} direct, ${baseline.transitiveDependentCount} transitive`) + '\n');
|
|
963
|
+
process.stdout.write(kv('packages', String(baseline.affectedPackageCount)) + '\n');
|
|
964
|
+
if (last) {
|
|
965
|
+
const d = diffImpactReports(baseline, last);
|
|
966
|
+
process.stdout.write('\nDelta (last − baseline): ' +
|
|
967
|
+
`dependents ${d.dependentDelta >= 0 ? '+' : ''}${d.dependentDelta}, ` +
|
|
968
|
+
`packages ${d.packageDelta >= 0 ? '+' : ''}${d.packageDelta}` +
|
|
969
|
+
(d.riskDrift ? `, risk ${d.riskDrift}` : '') +
|
|
970
|
+
(d.worsened ? ' ✗ worsened' : ' ✓ within baseline') +
|
|
971
|
+
'\n');
|
|
972
|
+
}
|
|
973
|
+
else {
|
|
974
|
+
process.stdout.write('\n(no recent `last.json` — run `shrk impact --via-graph` to populate it.)\n');
|
|
975
|
+
}
|
|
976
|
+
return 0;
|
|
977
|
+
}
|
|
978
|
+
if (verb === 'clear') {
|
|
979
|
+
const removed = store.clearBaseline();
|
|
980
|
+
if (wantJson) {
|
|
981
|
+
process.stdout.write(asJson({ removed, path: store.baselinePath }) + '\n');
|
|
982
|
+
return 0;
|
|
983
|
+
}
|
|
984
|
+
process.stdout.write(removed ? `Baseline removed: ${store.baselinePath}\n` : 'No baseline to remove.\n');
|
|
985
|
+
return 0;
|
|
986
|
+
}
|
|
987
|
+
process.stderr.write('Usage: shrk impact baseline <write|show|clear> [--json]\n');
|
|
988
|
+
return 2;
|
|
989
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.command.d.ts","sourceRoot":"","sources":["../../src/commands/import.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import.command.d.ts","sourceRoot":"","sources":["../../src/commands/import.command.ts"],"names":[],"mappings":"AAUA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAyBhC,eAAO,MAAM,aAAa,EAAE,eA8H3B,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import * as nodePath from 'node:path';
|
|
3
|
-
import { emitKnowledgeTs, importAgentsMd, importClaudeMd, importCursorRules, } from '@shrkcrft/importer';
|
|
3
|
+
import { emitKnowledgeTs, importAgentsMd, importClaudeMd, importCursorRules, synthesizePopulatedFromImport, } from '@shrkcrft/importer';
|
|
4
4
|
import { flagBool, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
5
|
-
import { asJson, header, kv } from "../output/format-output.js";
|
|
5
|
+
import { asJson, bullet, header, kv } from "../output/format-output.js";
|
|
6
6
|
function repeatedFlagList(args, name) {
|
|
7
7
|
return flagList(args, name, { dedupe: true });
|
|
8
8
|
}
|
|
@@ -22,8 +22,8 @@ function defaultOutput(format) {
|
|
|
22
22
|
}
|
|
23
23
|
export const importCommand = {
|
|
24
24
|
name: 'import',
|
|
25
|
-
description: 'Parse existing agent rule files (AGENTS.md / CLAUDE.md / .cursor/rules) into a
|
|
26
|
-
usage: 'shrk [--cwd <dir>] import <format> [<path>] [--prefix <id>] [--tag <t>] [--scope <s>] [--output <file>] [--write] [--force] [--json]',
|
|
25
|
+
description: 'Parse existing agent rule files (AGENTS.md / CLAUDE.md / .cursor/rules) into shrk\'s structure. By default (`--write`), saves a single draft TS file under sharkcraft/imports/ for the user to adopt by hand. Pass `--populate` to route entries directly into sharkcraft/rules.ts + paths.ts + knowledge.ts (by type) with a confidence triage report — same shape as `shrk init --infer`. Both modes dry-run by default.',
|
|
26
|
+
usage: 'shrk [--cwd <dir>] import <format> [<path>] [--prefix <id>] [--tag <t>] [--scope <s>] [--output <file>] [--write] [--populate] [--force] [--json]',
|
|
27
27
|
async run(args) {
|
|
28
28
|
const format = args.positional[0];
|
|
29
29
|
if (!format || !KNOWN_FORMATS.includes(format)) {
|
|
@@ -57,9 +57,24 @@ export const importCommand = {
|
|
|
57
57
|
}
|
|
58
58
|
const outPath = nodePath.resolve(cwd, flagString(args, 'output') ?? flagString(args, 'out') ?? defaultOutput(fmt));
|
|
59
59
|
const write = flagBool(args, 'write');
|
|
60
|
+
const populate = flagBool(args, 'populate');
|
|
60
61
|
const tsSource = emitKnowledgeTs(result.entries, {
|
|
61
62
|
sourceLabel: `${fmt} (${result.sourceFiles.join(', ') || path})`,
|
|
62
63
|
});
|
|
64
|
+
// ── `--populate` path: distribute entries into populated
|
|
65
|
+
// sharkcraft/* files (rules.ts / paths.ts / knowledge.ts) with
|
|
66
|
+
// confidence triage. Mirrors `shrk init --infer`'s contract.
|
|
67
|
+
if (populate) {
|
|
68
|
+
return runPopulateImport({
|
|
69
|
+
cwd,
|
|
70
|
+
fmt,
|
|
71
|
+
path,
|
|
72
|
+
result,
|
|
73
|
+
write,
|
|
74
|
+
force: flagBool(args, 'force'),
|
|
75
|
+
wantJson: flagBool(args, 'json'),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
63
78
|
if (flagBool(args, 'json')) {
|
|
64
79
|
process.stdout.write(asJson({
|
|
65
80
|
format: fmt,
|
|
@@ -113,3 +128,104 @@ export const importCommand = {
|
|
|
113
128
|
return 0;
|
|
114
129
|
},
|
|
115
130
|
};
|
|
131
|
+
/**
|
|
132
|
+
* `shrk import <format> --populate` path. Routes parsed entries
|
|
133
|
+
* into populated `sharkcraft/*.ts` files by KnowledgeType, with
|
|
134
|
+
* confidence triage and a companion `.imported-report.md`. Same
|
|
135
|
+
* shape as `shrk init --infer`.
|
|
136
|
+
*/
|
|
137
|
+
function runPopulateImport(args) {
|
|
138
|
+
const { cwd, fmt, path, result, write, force, wantJson } = args;
|
|
139
|
+
const sharkcraftDir = nodePath.join(cwd, 'sharkcraft');
|
|
140
|
+
const projectName = readProjectName(cwd) ?? 'project';
|
|
141
|
+
const description = `Imported from ${fmt} (${path})`;
|
|
142
|
+
const populated = synthesizePopulatedFromImport(result.entries, {
|
|
143
|
+
projectName,
|
|
144
|
+
description,
|
|
145
|
+
sourceLabel: `${fmt} (${result.sourceFiles.join(', ') || path})`,
|
|
146
|
+
});
|
|
147
|
+
if (wantJson) {
|
|
148
|
+
process.stdout.write(asJson({
|
|
149
|
+
format: fmt,
|
|
150
|
+
source: path,
|
|
151
|
+
mode: write ? 'populate' : 'populate-dry-run',
|
|
152
|
+
sharkcraftDir,
|
|
153
|
+
entryCount: result.entries.length,
|
|
154
|
+
warnings: result.warnings,
|
|
155
|
+
files: populated.files.map((f) => ({ path: f.path, kind: f.kind })),
|
|
156
|
+
report: populated.report,
|
|
157
|
+
}) + '\n');
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
160
|
+
process.stdout.write(header(`Import (${fmt}) — populate`));
|
|
161
|
+
process.stdout.write(kv('source', path) + '\n');
|
|
162
|
+
process.stdout.write(kv('files read', String(result.sourceFiles.length)) + '\n');
|
|
163
|
+
process.stdout.write(kv('entries parsed', String(result.entries.length)) + '\n');
|
|
164
|
+
process.stdout.write(kv('target', sharkcraftDir) + '\n');
|
|
165
|
+
process.stdout.write(kv('mode', write ? 'write' : 'dry-run (preview only)') + '\n\n');
|
|
166
|
+
process.stdout.write(`Triage: ${populated.report.adoptedHigh.length} adopted directly · ` +
|
|
167
|
+
`${populated.report.adoptedMedium.length} marked for review · ` +
|
|
168
|
+
`${populated.report.dropped.length} dropped (in report).\n\n`);
|
|
169
|
+
if (result.warnings.length > 0) {
|
|
170
|
+
process.stdout.write(header('Parser warnings'));
|
|
171
|
+
for (const w of result.warnings) {
|
|
172
|
+
process.stdout.write(` ${w.origin}: ${w.message}\n`);
|
|
173
|
+
}
|
|
174
|
+
process.stdout.write('\n');
|
|
175
|
+
}
|
|
176
|
+
if (!write) {
|
|
177
|
+
process.stdout.write('Would write:\n');
|
|
178
|
+
for (const f of populated.files)
|
|
179
|
+
process.stdout.write(bullet(f.path) + '\n');
|
|
180
|
+
process.stdout.write('\nRe-run with --write to persist.\n');
|
|
181
|
+
return 0;
|
|
182
|
+
}
|
|
183
|
+
const written = [];
|
|
184
|
+
const skipped = [];
|
|
185
|
+
for (const file of populated.files) {
|
|
186
|
+
const fullPath = nodePath.join(sharkcraftDir, file.path);
|
|
187
|
+
mkdirSync(nodePath.dirname(fullPath), { recursive: true });
|
|
188
|
+
if (existsSync(fullPath) && !force) {
|
|
189
|
+
skipped.push(file.path);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
writeFileSync(fullPath, file.content, 'utf8');
|
|
193
|
+
written.push(file.path);
|
|
194
|
+
}
|
|
195
|
+
if (written.length) {
|
|
196
|
+
process.stdout.write('Wrote:\n');
|
|
197
|
+
for (const p of written)
|
|
198
|
+
process.stdout.write(bullet(p) + '\n');
|
|
199
|
+
}
|
|
200
|
+
if (skipped.length) {
|
|
201
|
+
process.stdout.write('\nSkipped (already exist; use --force to overwrite):\n');
|
|
202
|
+
for (const p of skipped)
|
|
203
|
+
process.stdout.write(bullet(p) + '\n');
|
|
204
|
+
}
|
|
205
|
+
process.stdout.write(`\nRead the import report: \`${nodePath.join('sharkcraft', '.imported-report.md')}\`\n` +
|
|
206
|
+
`It lists what was adopted high-confidence, what's marked for your review, ` +
|
|
207
|
+
`and what \`shrk import\` deliberately doesn't recover from markdown.\n`);
|
|
208
|
+
process.stdout.write('\nNext:\n');
|
|
209
|
+
process.stdout.write(bullet('$ shrk doctor — verify the populated setup') + '\n');
|
|
210
|
+
process.stdout.write(bullet('$ shrk brief — single-page brief Claude reads first') + '\n');
|
|
211
|
+
process.stdout.write(bullet('$ shrk export claude-skill --write — inline the rules into Claude\'s prompt') + '\n');
|
|
212
|
+
return 0;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Best-effort read of `package.json#name` for use as `projectName`
|
|
216
|
+
* in the generated config. Falls back to undefined; the synthesizer
|
|
217
|
+
* uses 'project' as a default.
|
|
218
|
+
*/
|
|
219
|
+
function readProjectName(cwd) {
|
|
220
|
+
const pkgPath = nodePath.join(cwd, 'package.json');
|
|
221
|
+
try {
|
|
222
|
+
if (!existsSync(pkgPath))
|
|
223
|
+
return undefined;
|
|
224
|
+
const raw = readFileSync(pkgPath, 'utf8');
|
|
225
|
+
const parsed = JSON.parse(raw);
|
|
226
|
+
return parsed.name ?? undefined;
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
return undefined;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ingest.command.d.ts","sourceRoot":"","sources":["../../src/commands/ingest.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ingest.command.d.ts","sourceRoot":"","sources":["../../src/commands/ingest.command.ts"],"names":[],"mappings":"AA0CA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAOhC,eAAO,MAAM,aAAa,EAAE,eA4B3B,CAAC;AAmZF,eAAO,MAAM,qBAAqB,EAAE,eAkBnC,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,eA8B9B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,eAkC9B,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import * as nodePath from 'node:path';
|
|
3
|
+
import { cliCommandNameSet } from "./command-catalog.js";
|
|
3
4
|
import { applyIngestPlan, buildContradictionReport, buildGeneratedCodeReport, buildIngestAdoptionPlan, buildIngestApplyPlan, buildRepositoryKnowledgeModel, buildStabilityMap, inspectSharkcraft, IngestAdoptionStatus, IngestDepth, IngestSection, loadIngestApplyPlan, renderContradictionReportHtml, renderContradictionReportJson, renderContradictionReportMarkdown, renderContradictionReportText, renderGeneratedCodeReportJson, renderGeneratedCodeReportMarkdown, renderGeneratedCodeReportText, renderIngestAdoptionPatch, renderIngestAdoptionPlanMarkdown, renderIngestApplyReviewMarkdown, renderRepositoryKnowledgeModelHtml, renderRepositoryKnowledgeModelJson, renderRepositoryKnowledgeModelMarkdown, renderRepositoryKnowledgeModelText, renderStabilityMapJson, renderStabilityMapMarkdown, renderStabilityMapText, saveIngestApplyPlan, signIngestApplyPlan, writeIngestAdoption, writeIngestDrafts, } from '@shrkcrft/inspector';
|
|
4
5
|
import { flagBool, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
5
6
|
import { asJson, header, kv } from "../output/format-output.js";
|
|
@@ -442,7 +443,10 @@ export const contradictionsCommand = {
|
|
|
442
443
|
const cwd = resolveCwd(args);
|
|
443
444
|
const format = parseFormat(flagString(args, 'format'));
|
|
444
445
|
const inspection = await inspectSharkcraft({ cwd });
|
|
445
|
-
const report = buildContradictionReport({
|
|
446
|
+
const report = buildContradictionReport({
|
|
447
|
+
inspection,
|
|
448
|
+
cliCommandNames: cliCommandNameSet(),
|
|
449
|
+
});
|
|
446
450
|
if (format === 'json')
|
|
447
451
|
process.stdout.write(renderContradictionReportJson(report) + '\n');
|
|
448
452
|
else if (format === 'markdown')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.command.d.ts","sourceRoot":"","sources":["../../src/commands/init.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"init.command.d.ts","sourceRoot":"","sources":["../../src/commands/init.command.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAwB,KAAK,eAAe,EAA+B,MAAM,wBAAwB,CAAC;AAuSjH,eAAO,MAAM,WAAW,EAAE,eA2HzB,CAAC"}
|