@shrkcrft/cli 0.1.0-alpha.17 → 0.1.0-alpha.19

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.
Files changed (50) hide show
  1. package/dist/command-registry.d.ts +10 -0
  2. package/dist/command-registry.d.ts.map +1 -1
  3. package/dist/command-registry.js +7 -1
  4. package/dist/commands/command-catalog.d.ts.map +1 -1
  5. package/dist/commands/command-catalog.js +12 -0
  6. package/dist/commands/compress.command.d.ts +0 -7
  7. package/dist/commands/compress.command.d.ts.map +1 -1
  8. package/dist/commands/compress.command.js +7 -0
  9. package/dist/commands/delegate.command.d.ts +65 -0
  10. package/dist/commands/delegate.command.d.ts.map +1 -0
  11. package/dist/commands/delegate.command.js +657 -0
  12. package/dist/commands/deps-audit.command.js +1 -1
  13. package/dist/commands/doctor.command.d.ts.map +1 -1
  14. package/dist/commands/doctor.command.js +24 -3
  15. package/dist/commands/gen.command.d.ts.map +1 -1
  16. package/dist/commands/gen.command.js +13 -1
  17. package/dist/commands/graph-code-subverbs.d.ts +22 -0
  18. package/dist/commands/graph-code-subverbs.d.ts.map +1 -1
  19. package/dist/commands/graph-code-subverbs.js +476 -55
  20. package/dist/commands/graph.command.d.ts.map +1 -1
  21. package/dist/commands/graph.command.js +9 -3
  22. package/dist/commands/help.command.d.ts.map +1 -1
  23. package/dist/commands/help.command.js +7 -18
  24. package/dist/commands/knowledge-author.command.d.ts.map +1 -1
  25. package/dist/commands/knowledge-author.command.js +9 -0
  26. package/dist/commands/knowledge-propose.command.d.ts.map +1 -1
  27. package/dist/commands/knowledge-propose.command.js +4 -2
  28. package/dist/commands/knowledge.command.d.ts.map +1 -1
  29. package/dist/commands/knowledge.command.js +22 -2
  30. package/dist/commands/move-plan.command.js +1 -1
  31. package/dist/commands/preflight.command.d.ts.map +1 -1
  32. package/dist/commands/preflight.command.js +15 -0
  33. package/dist/commands/recommend.command.d.ts +6 -0
  34. package/dist/commands/recommend.command.d.ts.map +1 -1
  35. package/dist/commands/recommend.command.js +72 -0
  36. package/dist/commands/rules.command.d.ts.map +1 -1
  37. package/dist/commands/rules.command.js +20 -3
  38. package/dist/commands/smart-context.command.d.ts +26 -17
  39. package/dist/commands/smart-context.command.d.ts.map +1 -1
  40. package/dist/commands/smart-context.command.js +113 -16
  41. package/dist/commands/tests.command.d.ts.map +1 -1
  42. package/dist/commands/tests.command.js +13 -2
  43. package/dist/dashboard/code-intelligence-data.d.ts.map +1 -1
  44. package/dist/dashboard/code-intelligence-data.js +25 -3
  45. package/dist/main.d.ts.map +1 -1
  46. package/dist/main.js +3 -1
  47. package/dist/output/ccr-store-config.d.ts +1 -1
  48. package/dist/output/ccr-store-config.d.ts.map +1 -1
  49. package/dist/output/ccr-store-config.js +21 -2
  50. package/package.json +33 -33
@@ -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;AA0BhC,eAAO,MAAM,YAAY,EAAE,eA2M1B,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,7 +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, runGraphImpact, runGraphIndex, runGraphSearch, runGraphStatus, runGraphUnresolved, } from "./graph-code-subverbs.js";
6
+ import { runGraphCallers, runGraphContext, runGraphCycles, runGraphDeps, runGraphHubs, runGraphImpact, runGraphIndex, runGraphPath, runGraphSearch, runGraphStatus, runGraphUnresolved, } from "./graph-code-subverbs.js";
7
7
  const KNOWN_KINDS = [
8
8
  'knowledge',
9
9
  'rule',
@@ -17,9 +17,11 @@ const KNOWN_KINDS = [
17
17
  ];
18
18
  export const graphCommand = {
19
19
  name: 'graph',
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|callers|cycles|unresolved|deps|why|export` for code-graph workflows.',
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
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|callers|cycles|unresolved|deps|why|export ...',
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)',
23
25
  async run(args) {
24
26
  // Code-intelligence subverbs (R65) don't need the knowledge graph —
25
27
  // dispatch them before the expensive inspection so they stay fast.
@@ -34,6 +36,10 @@ export const graphCommand = {
34
36
  return runGraphContext(args);
35
37
  if (earlySub === 'impact')
36
38
  return runGraphImpact(args);
39
+ if (earlySub === 'path')
40
+ return runGraphPath(args);
41
+ if (earlySub === 'hubs')
42
+ return runGraphHubs(args);
37
43
  if (earlySub === 'callers')
38
44
  return runGraphCallers(args);
39
45
  if (earlySub === 'cycles')
@@ -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;AAqB9D;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAmD1C;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
+ {"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"}
@@ -31,21 +31,16 @@ export function renderStartScreen() {
31
31
  lines.push('Usage: shrk [--cwd <dir>] <command> [...args]');
32
32
  lines.push('');
33
33
  lines.push('Bootstrap:');
34
- lines.push(' $ shrk init --infer --write — scan the repo + populate sharkcraft/ from real signals (recommended for new repos)');
35
- lines.push(' $ shrk import claude-md ./CLAUDE.md --populate --write — populate sharkcraft/ from existing CLAUDE.md / AGENTS.md / .cursor/rules');
36
- lines.push(' $ shrk init --with-claude-skill --write — scaffold sharkcraft/ AND inline rules into .claude/skills/ (one-step)');
37
- lines.push(' $ shrk init — scaffold sharkcraft/ + config skeleton (preset defaults)');
34
+ lines.push(' $ shrk init --infer --write — scan the repo + populate sharkcraft/ from real signals (new repos)');
38
35
  lines.push(' $ shrk doctor — is the workspace healthy?');
39
- lines.push(' $ shrk inspect — detect frameworks, paths, package manager');
40
36
  lines.push(' $ shrk onboard — analyze an existing repo (advisory)');
41
37
  lines.push('');
42
38
  lines.push('Use it for a task:');
43
- lines.push(' $ shrk brief — single-page brief Claude reads first (project + rules + paths + verification)');
44
39
  lines.push(' $ shrk recommend "<task>" — what should I do?');
45
40
  lines.push(' $ shrk context --task "<task>" — token-budgeted relevant context');
46
41
  lines.push(' $ shrk task "<task>" — full AI-ready task packet (JSON)');
47
- lines.push(' $ shrk code-intelone-shot code-intelligence health summary');
48
- lines.push(' $ shrk coverage — what knowledge is missing');
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');
49
44
  lines.push('');
50
45
  lines.push('Generate code safely:');
51
46
  lines.push(' $ shrk gen <template> <name> — generate from template (dry-run by default)');
@@ -54,22 +49,16 @@ export function renderStartScreen() {
54
49
  lines.push(' $ shrk quality — pre-PR gate (doctor + boundaries + coverage + drift)');
55
50
  lines.push('');
56
51
  lines.push('Browse what shrk knows:');
57
- lines.push(' $ shrk graph status current code-graph freshness and health');
52
+ lines.push(' $ shrk graph status — code-graph freshness and health');
53
+ lines.push(' $ shrk coverage — what knowledge is missing');
58
54
  lines.push(' $ shrk knowledge list — knowledge entries');
59
- lines.push(' $ shrk rules list — rules + conventions');
60
- lines.push(' $ shrk templates list — generator templates');
61
- lines.push(' $ shrk import — parse AGENTS.md / CLAUDE.md / .cursor/rules');
62
- lines.push(' $ shrk export — render to a flat agent-rule file');
63
55
  lines.push('');
64
56
  lines.push('Run shrk for an agent:');
65
- lines.push(' $ shrk export claude-skill --write — generate .claude/skills/<name>/SKILL.md (rules INTO the prompt — no MCP roundtrip)');
66
- lines.push(' $ shrk export agents-md --write — generate AGENTS.md / CLAUDE.md / .cursor/rules / copilot-instructions');
67
57
  lines.push(' $ shrk mcp serve — start the MCP server (stdio) for live queries');
68
58
  lines.push(' $ shrk dashboard — start the local read-only dashboard');
69
59
  lines.push('');
70
- lines.push('Discover the rest (always callable, hidden from this screen by default):');
71
- lines.push(' $ shrk surface list — full ~70-verb catalog by tier');
72
- lines.push(' $ shrk surface profiles — named profiles (small-app / monorepo / ci / agent / pack-author)');
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');
73
62
  lines.push(' $ shrk help <command> — usage for a specific command');
74
63
  lines.push(' $ shrk --full-help — long, exhaustive help');
75
64
  lines.push(' $ shrk --about — what shrk is and is not');
@@ -1 +1 @@
1
- {"version":3,"file":"knowledge-author.command.d.ts","sourceRoot":"","sources":["../../src/commands/knowledge-author.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAoBH,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAwChC,eAAO,MAAM,mBAAmB,EAAE,eAgEjC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA0GpC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAoEpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eA2DlC,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,eAmB3C,CAAC"}
1
+ {"version":3,"file":"knowledge-author.command.d.ts","sourceRoot":"","sources":["../../src/commands/knowledge-author.command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAoBH,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAwChC,eAAO,MAAM,mBAAmB,EAAE,eAgEjC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA0GpC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAoEpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAsElC,CAAC;AAEF,eAAO,MAAM,6BAA6B,EAAE,eAmB3C,CAAC"}
@@ -300,6 +300,15 @@ export const knowledgeLintCommand = {
300
300
  async run(args) {
301
301
  const cwd = resolveCwd(args);
302
302
  const inspection = await inspectSharkcraft({ cwd });
303
+ // Loud guard: a 0-entry scan is NOT a clean pass — it almost always means
304
+ // the loader found nothing (wrong cwd / no `sharkcraft/` folder / no
305
+ // entries), which otherwise reads as "lint passed". Surface it on stderr so
306
+ // it can't be mistaken for success, while keeping stdout/JSON clean.
307
+ if (inspection.knowledgeEntries.length === 0) {
308
+ process.stderr.write('WARN knowledge lint scanned 0 entries — there is nothing to lint (this is NOT a clean pass).\n' +
309
+ ' Likely causes: no `sharkcraft/` folder here, not at the workspace root, or no\n' +
310
+ ' knowledge entries are defined. Run `shrk doctor` to confirm how many entries load.\n');
311
+ }
303
312
  const entryIds = flagList(args, 'id');
304
313
  const includeAdvisory = !flagBool(args, 'no-advisory');
305
314
  const stale = buildKnowledgeStaleReport(inspection);
@@ -1 +1 @@
1
- {"version":3,"file":"knowledge-propose.command.d.ts","sourceRoot":"","sources":["../../src/commands/knowledge-propose.command.ts"],"names":[],"mappings":"AAqBA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAkDhC,eAAO,MAAM,uBAAuB,EAAE,eA0ErC,CAAC"}
1
+ {"version":3,"file":"knowledge-propose.command.d.ts","sourceRoot":"","sources":["../../src/commands/knowledge-propose.command.ts"],"names":[],"mappings":"AAqBA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAkDhC,eAAO,MAAM,uBAAuB,EAAE,eA4ErC,CAAC"}
@@ -10,7 +10,7 @@
10
10
  import { mkdirSync, writeFileSync } from 'node:fs';
11
11
  import * as nodePath from 'node:path';
12
12
  import { AssetKind, AssetProvenanceOperation, KNOWLEDGE_PROPOSE_SCHEMA, proposeKnowledge, recordProvenance, renderKnowledgeProposeMarkdown, } from '@shrkcrft/inspector';
13
- import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
13
+ import { flagBool, flagNumber, flagString, resolveCwd, } from "../command-registry.js";
14
14
  import { asJson } from "../output/format-output.js";
15
15
  import { detectAuthoringSource } from "../authoring/authoring-kit.js";
16
16
  function renderProposalAsTs(p) {
@@ -54,13 +54,14 @@ function writeDraftFiles(cwd, report) {
54
54
  export const knowledgeProposeCommand = {
55
55
  name: 'propose',
56
56
  description: 'Propose stub knowledge entries for exported top-level constructs that lack coverage. Preview-first; --write materialises drafts under .sharkcraft/authoring/proposed/.',
57
- usage: 'shrk knowledge propose [--path <file>] [--symbol <name>] [--since <ref>|--all] [--json] [--write]',
57
+ usage: 'shrk knowledge propose [--path <file>] [--symbol <name>] [--since <ref>|--all] [--max <n>] [--json] [--write]',
58
58
  async run(args) {
59
59
  const cwd = resolveCwd(args);
60
60
  const path = flagString(args, 'path');
61
61
  const symbol = flagString(args, 'symbol');
62
62
  const sinceFlag = flagString(args, 'since');
63
63
  const all = flagBool(args, 'all');
64
+ const max = flagNumber(args, 'max');
64
65
  const since = path
65
66
  ? undefined
66
67
  : symbol
@@ -73,6 +74,7 @@ export const knowledgeProposeCommand = {
73
74
  ...(path ? { path } : {}),
74
75
  ...(symbol ? { symbol } : {}),
75
76
  ...(since !== undefined ? { since } : {}),
77
+ ...(max !== undefined && max >= 0 ? { max } : {}),
76
78
  });
77
79
  if (flagBool(args, 'json')) {
78
80
  const payload = flagBool(args, 'write')
@@ -1 +1 @@
1
- {"version":3,"file":"knowledge.command.d.ts","sourceRoot":"","sources":["../../src/commands/knowledge.command.ts"],"names":[],"mappings":"AAaA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAoFhC,eAAO,MAAM,oBAAoB,EAAE,eAsBlC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,eAuBjC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAqCpC,CAAC;AAoBF,eAAO,MAAM,0BAA0B,EAAE,eAWxC,CAAC;AA8NF,eAAO,MAAM,sBAAsB,EAAE,eAQpC,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,eA8CxC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAuBrC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,EAAE,eA8B1C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,eA8BxC,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,eAkC1C,CAAC"}
1
+ {"version":3,"file":"knowledge.command.d.ts","sourceRoot":"","sources":["../../src/commands/knowledge.command.ts"],"names":[],"mappings":"AAaA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAoFhC,eAAO,MAAM,oBAAoB,EAAE,eA2ClC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,eAuBjC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAqCpC,CAAC;AAoBF,eAAO,MAAM,0BAA0B,EAAE,eAWxC,CAAC;AA8NF,eAAO,MAAM,sBAAsB,EAAE,eAQpC,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,eA8CxC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAuBrC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,EAAE,eA8B1C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,eA8BxC,CAAC;AAEF,eAAO,MAAM,4BAA4B,EAAE,eAkC1C,CAAC"}
@@ -54,7 +54,7 @@ ${p.ci.exitNonZero ? `<p style="color:#a40000;font-weight:bold">FAIL: ${esc(p.ci
54
54
  export const knowledgeListCommand = {
55
55
  name: 'list',
56
56
  description: 'List knowledge entries.',
57
- usage: 'shrk knowledge list [--type rule] [--scope x,y] [--json]',
57
+ usage: 'shrk knowledge list [--type rule] [--scope x,y] [--top N] [--brief] [--json]',
58
58
  async run(args) {
59
59
  const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
60
60
  const types = flagList(args, 'type');
@@ -64,8 +64,28 @@ export const knowledgeListCommand = {
64
64
  entries = entries.filter((e) => types.includes(String(e.type)));
65
65
  if (scope.length)
66
66
  entries = entries.filter((e) => scope.some((s) => e.scope.includes(s)));
67
+ // --top N: a deterministic, token-bounded slice. Sort by id first so the
68
+ // "top N" is stable across machines (entries otherwise load in fs-scan
69
+ // order). Reduce at the source instead of piping through `shrk compress`.
70
+ const top = flagNumber(args, 'top');
71
+ if (top !== undefined && top > 0) {
72
+ entries = [...entries].sort((a, b) => a.id.localeCompare(b.id)).slice(0, top);
73
+ }
67
74
  if (flagBool(args, 'json')) {
68
- process.stdout.write(asJson(entries.map((e) => ({ ...e }))) + '\n');
75
+ // --brief: project to the high-signal fields, dropping content / examples
76
+ // / metadata (the bulk of the payload) so an agent pays far fewer tokens.
77
+ const payload = flagBool(args, 'brief')
78
+ ? entries.map((e) => ({
79
+ id: e.id,
80
+ type: e.type,
81
+ priority: e.priority,
82
+ title: e.title,
83
+ scope: e.scope,
84
+ tags: e.tags,
85
+ appliesWhen: e.appliesWhen,
86
+ }))
87
+ : entries.map((e) => ({ ...e }));
88
+ process.stdout.write(asJson(payload) + '\n');
69
89
  return 0;
70
90
  }
71
91
  process.stdout.write(header(`Knowledge (${entries.length})`));
@@ -48,7 +48,7 @@ export const movePlanCommand = {
48
48
  }
49
49
  const store = new GraphStore(cwd);
50
50
  if (!store.exists()) {
51
- process.stderr.write('No SharkCraft graph found. Run `shrk graph build` so move-plan can trace importers.\n');
51
+ process.stderr.write('No SharkCraft graph found. Run `shrk graph index` so move-plan can trace importers.\n');
52
52
  return 1;
53
53
  }
54
54
  const api = GraphQueryApi.fromStore(cwd);
@@ -1 +1 @@
1
- {"version":3,"file":"preflight.command.d.ts","sourceRoot":"","sources":["../../src/commands/preflight.command.ts"],"names":[],"mappings":"AAoBA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAgBhC,eAAO,MAAM,gBAAgB,EAAE,eAmF9B,CAAC"}
1
+ {"version":3,"file":"preflight.command.d.ts","sourceRoot":"","sources":["../../src/commands/preflight.command.ts"],"names":[],"mappings":"AAoBA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAiBhC,eAAO,MAAM,gBAAgB,EAAE,eAoG9B,CAAC"}
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { planChangedPreflight, PreflightAction, PreflightProfile, renderChangedPreflightText, resolveChangedFiles, } from '@shrkcrft/inspector';
15
15
  import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
16
+ import { loadProjectConfig } from '@shrkcrft/config';
16
17
  import { asJson, header } from "../output/format-output.js";
17
18
  function parseProfile(value) {
18
19
  if (value === 'quick')
@@ -55,10 +56,24 @@ export const preflightCommand = {
55
56
  resolveOpts.includeWorktree = true;
56
57
  }
57
58
  const changed = resolveChangedFiles(resolveOpts);
59
+ // Ground the test/typecheck gates in the project's declared verification
60
+ // commands when present, rather than the generic `bun test` / tsc defaults.
61
+ // Best-effort: a repo without sharkcraft/ config keeps the defaults.
62
+ let testCommand;
63
+ let typecheckCommand;
64
+ const loaded = await loadProjectConfig(cwd);
65
+ if (loaded.ok) {
66
+ const vcs = loaded.value.config.verificationCommands ?? [];
67
+ const pick = (...ids) => vcs.find((v) => ids.includes(v.id))?.command;
68
+ testCommand = pick('test', 'tests', 'unit', 'unit-tests');
69
+ typecheckCommand = pick('typecheck', 'tsc', 'types', 'typecheck-all');
70
+ }
58
71
  const plan = planChangedPreflight({
59
72
  projectRoot: cwd,
60
73
  changedFiles: changed.files,
61
74
  profile,
75
+ ...(testCommand ? { testCommand } : {}),
76
+ ...(typecheckCommand ? { typecheckCommand } : {}),
62
77
  });
63
78
  if (flagBool(args, 'json')) {
64
79
  process.stdout.write(asJson({ plan, scopeMode: changed.mode }) + '\n');
@@ -1,4 +1,10 @@
1
1
  import { type ICommandHandler } from '../command-registry.js';
2
2
  export declare const recommendCommand: ICommandHandler;
3
+ /**
4
+ * Does the query look like create/build work (a routing hint's `shrk gen`
5
+ * playbook is most useful here)? Mirrors {@link looksLikePlanning}: a
6
+ * create/build verb leading the query or in slots 1–3.
7
+ */
8
+ export declare function looksLikeCreateBuild(query: string): boolean;
3
9
  export declare function looksLikePlanning(query: string): boolean;
4
10
  //# sourceMappingURL=recommend.command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"recommend.command.d.ts","sourceRoot":"","sources":["../../src/commands/recommend.command.ts"],"names":[],"mappings":"AASA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAShC,eAAO,MAAM,gBAAgB,EAAE,eA0K9B,CAAC;AAoGF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAcxD"}
1
+ {"version":3,"file":"recommend.command.d.ts","sourceRoot":"","sources":["../../src/commands/recommend.command.ts"],"names":[],"mappings":"AASA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAShC,eAAO,MAAM,gBAAgB,EAAE,eA+M9B,CAAC;AAgHF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAY3D;AAcD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAcxD"}
@@ -79,6 +79,36 @@ export const recommendCommand = {
79
79
  searchReport = null;
80
80
  }
81
81
  }
82
+ // R1 — promote a strongly-matched task-routing hint's recommends.commands
83
+ // into the HEADLINE for create/build intents. Routing hints are scored by
84
+ // explainTaskRouting but were previously only shown under --verbose, so the
85
+ // headline fell back to generic review/report/impact commands even when the
86
+ // pack declared the right `shrk gen <template>` playbook. When the top hint
87
+ // clears the threshold AND the query looks like create/build work, its
88
+ // commands lead and the generic defaults slide to the tail. Deterministic.
89
+ const topHint = routingMatches[0];
90
+ const hintCommands = topHint?.hint.recommends.commands ?? [];
91
+ if (query.length > 0 &&
92
+ looksLikeCreateBuild(query) &&
93
+ topHint &&
94
+ topHint.score >= ROUTING_HINT_PROMOTE_THRESHOLD &&
95
+ hintCommands.length > 0) {
96
+ const promoted = hintCommands.map((command) => ({
97
+ command,
98
+ why: `Routing hint "${topHint.hint.id}" matched (score ${topHint.score}) — project playbook for this create/build task.`,
99
+ safetyLevel: promotedSafetyLevel(command),
100
+ }));
101
+ const promotedSet = new Set(promoted.map((p) => p.command));
102
+ const isGenericDefault = (c) => /^(bun run )?shrk (review|report|impact)\b/i.test(c);
103
+ const existing = report.recommendations;
104
+ const keptNonGeneric = existing.filter((r) => !promotedSet.has(r.command) && !isGenericDefault(r.command));
105
+ const keptGeneric = existing.filter((r) => !promotedSet.has(r.command) && isGenericDefault(r.command));
106
+ report.recommendations = [
107
+ ...promoted,
108
+ ...keptNonGeneric,
109
+ ...keptGeneric,
110
+ ];
111
+ }
82
112
  if (machineJson) {
83
113
  process.stdout.write(asJson({
84
114
  ...report,
@@ -250,6 +280,48 @@ const PLANNING_VERBS = new Set([
250
280
  'evaluate',
251
281
  'assess',
252
282
  ]);
283
+ /**
284
+ * Minimum routing-hint score (from `explainTaskRouting`: +2 per keyword, +3 per
285
+ * phrase, +2 per regex, + confidenceBoost) required to promote a hint's
286
+ * commands into the recommend headline. 3 ⇒ at least one phrase match or two
287
+ * keyword/regex hits — a real match, not a single weak keyword.
288
+ */
289
+ const ROUTING_HINT_PROMOTE_THRESHOLD = 3;
290
+ const CREATE_BUILD_VERBS = new Set([
291
+ 'create', 'build', 'add', 'generate', 'scaffold', 'implement', 'make', 'new', 'introduce', 'write',
292
+ ]);
293
+ /**
294
+ * Does the query look like create/build work (a routing hint's `shrk gen`
295
+ * playbook is most useful here)? Mirrors {@link looksLikePlanning}: a
296
+ * create/build verb leading the query or in slots 1–3.
297
+ */
298
+ export function looksLikeCreateBuild(query) {
299
+ const tokens = query
300
+ .toLowerCase()
301
+ .replace(/[^a-z0-9\s]/g, ' ')
302
+ .split(/\s+/)
303
+ .filter((t) => t.length > 0);
304
+ if (tokens.length === 0)
305
+ return false;
306
+ if (CREATE_BUILD_VERBS.has(tokens[0]))
307
+ return true;
308
+ for (let i = 1; i < Math.min(4, tokens.length); i++) {
309
+ if (CREATE_BUILD_VERBS.has(tokens[i]))
310
+ return true;
311
+ }
312
+ return false;
313
+ }
314
+ /** Conservative safety classification for a promoted routing-hint command. */
315
+ function promotedSafetyLevel(command) {
316
+ if (/^(bun run )?shrk (gen|init|apply|import)\b/i.test(command))
317
+ return 'writes-source';
318
+ if (/^(bun run )?shrk (brief|dev|onboard|simulate|orchestrate|spec)\b/i.test(command)) {
319
+ return 'writes-drafts';
320
+ }
321
+ if (/^(bun|bunx|npm|pnpm|node|git|nx) /i.test(command))
322
+ return 'runs-shell';
323
+ return 'read-only';
324
+ }
253
325
  export function looksLikePlanning(query) {
254
326
  const tokens = query
255
327
  .toLowerCase()
@@ -1 +1 @@
1
- {"version":3,"file":"rules.command.d.ts","sourceRoot":"","sources":["../../src/commands/rules.command.ts"],"names":[],"mappings":"AAcA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAQhC,eAAO,MAAM,gBAAgB,EAAE,eAe9B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,eAuB7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAmClC,CAAC;AAuBF,eAAO,MAAM,oBAAoB,EAAE,eAiFlC,CAAC;AAkBF;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,eAsB7B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,eA6BhC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,eA6BhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,eA2F9B,CAAC;AAoCF,eAAO,MAAM,kBAAkB,EAAE,eAiChC,CAAC"}
1
+ {"version":3,"file":"rules.command.d.ts","sourceRoot":"","sources":["../../src/commands/rules.command.ts"],"names":[],"mappings":"AAcA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAQhC,eAAO,MAAM,gBAAgB,EAAE,eAgC9B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,eAuB7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAmClC,CAAC;AAuBF,eAAO,MAAM,oBAAoB,EAAE,eAiFlC,CAAC;AAkBF;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,EAAE,eAsB7B,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,eA6BhC,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kBAAkB,EAAE,eA6BhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,EAAE,eA2F9B,CAAC;AAoCF,eAAO,MAAM,kBAAkB,EAAE,eAiChC,CAAC"}
@@ -8,12 +8,29 @@ import { knowledgeAddCommand, knowledgeRemoveCommand, knowledgeUpdateCommand, }
8
8
  export const rulesListCommand = {
9
9
  name: 'list',
10
10
  description: 'List all rules.',
11
- usage: 'shrk rules list [--json]',
11
+ usage: 'shrk rules list [--top N] [--brief] [--json]',
12
12
  async run(args) {
13
13
  const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
14
- const rules = inspection.ruleService.list();
14
+ let rules = inspection.ruleService.list();
15
+ // --top N: deterministic, token-bounded slice (id-sorted so it's stable).
16
+ const top = flagNumber(args, 'top');
17
+ if (top !== undefined && top > 0) {
18
+ rules = [...rules].sort((a, b) => a.id.localeCompare(b.id)).slice(0, top);
19
+ }
15
20
  if (flagBool(args, 'json')) {
16
- process.stdout.write(asJson(rules) + '\n');
21
+ // --brief: project to the high-signal fields (drop content/examples).
22
+ const payload = flagBool(args, 'brief')
23
+ ? rules.map((r) => ({
24
+ id: r.id,
25
+ type: r.type,
26
+ priority: r.priority,
27
+ title: r.title,
28
+ scope: r.scope,
29
+ tags: r.tags,
30
+ appliesWhen: r.appliesWhen,
31
+ }))
32
+ : rules;
33
+ process.stdout.write(asJson(payload) + '\n');
17
34
  return 0;
18
35
  }
19
36
  process.stdout.write(header(`Rules (${rules.length})`));
@@ -1,21 +1,4 @@
1
1
  import { type ICommandHandler } from '../command-registry.js';
2
- /**
3
- * Gemini-backed context enrichment.
4
- *
5
- * Sits next to `shrk ask` as an explicit, opt-in AI surface — the
6
- * deterministic engine (`shrk context`, `shrk brief`, MCP tools) stays
7
- * AI-free. See docs/smart-context.md and the
8
- * `.claude/skills/shrk-smart-context/` skill for the agent workflow.
9
- *
10
- * Verbs:
11
- * - `smart-context "<task>"` — single brief (default).
12
- * - `smart-context "<task>" --plan` — single structured plan.
13
- * - `smart-context "<task>" --ai-plan` — two-stage AI-assisted plan.
14
- * - `smart-context "<task>" --save` — persist under .sharkcraft/smart-context/.
15
- * - `smart-context plan-ahead "t1" "t2"` — batch-save plans for an upcoming queue.
16
- * - `smart-context list` — list saved entries.
17
- * - `smart-context show <slug>` — print a saved entry.
18
- */
19
2
  export declare const smartContextCommand: ICommandHandler;
20
3
  /** `shrk smart-context plan-ahead "task1" "task2" ...` — batch-saves plans. */
21
4
  export declare const smartContextPlanAheadCommand: ICommandHandler;
@@ -55,4 +38,30 @@ export declare const smartContextAuditPipelinesCommand: ICommandHandler;
55
38
  export declare const smartContextEmbeddingsBuildCommand: ICommandHandler;
56
39
  /** `shrk smart-context embeddings-status` — freshness report (no model load). */
57
40
  export declare const smartContextEmbeddingsStatusCommand: ICommandHandler;
41
+ interface IIndexFreshness {
42
+ /** Files currently in the semantic index. */
43
+ indexed: number;
44
+ /** stale + missing + untracked — how far the index is behind the working tree. */
45
+ behind: number;
46
+ stale: number;
47
+ missing: number;
48
+ untracked: number;
49
+ /** True when this run refreshed the index inline (--refresh or under the auto cap). */
50
+ refreshed: boolean;
51
+ /**
52
+ * Deleted-file suggestions DROPPED from this query's results — a stale index
53
+ * returned hits for files no longer on disk; they were pruned before the agent
54
+ * ever saw them. Present (and > 0) only when the prune actually fired.
55
+ */
56
+ prunedDeleted?: number;
57
+ /** Command to bring the index current, when it is still behind. */
58
+ nextCommand?: string;
59
+ }
60
+ /**
61
+ * Render the one-line freshness warning for a stale semantic index — including
62
+ * how many deleted-file suggestions were dropped from the results this query.
63
+ * Returns null when the index is current (no noise). Pure + testable.
64
+ */
65
+ export declare function renderIndexFreshnessWarning(f: IIndexFreshness | undefined): string | null;
66
+ export {};
58
67
  //# sourceMappingURL=smart-context.command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"smart-context.command.d.ts","sourceRoot":"","sources":["../../src/commands/smart-context.command.ts"],"names":[],"mappings":"AAyBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAyDhC;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,mBAAmB,EAAE,eA6LjC,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,4BAA4B,EAAE,eAmF1C,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,EAAE,eAwBrC,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,EAAE,eAkCrC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAmH/C,CAAC;AA2JF;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAoH/C,CAAC;AA2JF;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAgG/C,CAAC;AAyPF,4EAA4E;AAC5E,eAAO,MAAM,kCAAkC,EAAE,eAuHhD,CAAC;AAMF,iFAAiF;AACjF,eAAO,MAAM,mCAAmC,EAAE,eAsCjD,CAAC"}
1
+ {"version":3,"file":"smart-context.command.d.ts","sourceRoot":"","sources":["../../src/commands/smart-context.command.ts"],"names":[],"mappings":"AAyBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAmFhC,eAAO,MAAM,mBAAmB,EAAE,eAuNjC,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,4BAA4B,EAAE,eAmF1C,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,EAAE,eAwBrC,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,EAAE,eAkCrC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAmH/C,CAAC;AA2JF;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAoH/C,CAAC;AA2JF;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAgG/C,CAAC;AAyPF,4EAA4E;AAC5E,eAAO,MAAM,kCAAkC,EAAE,eAuHhD,CAAC;AAMF,iFAAiF;AACjF,eAAO,MAAM,mCAAmC,EAAE,eAsCjD,CAAC;AAqJF,UAAU,eAAe;IACvB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAWzF"}