@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.
Files changed (228) hide show
  1. package/dist/audit/knowledge-audit-llm.d.ts +19 -0
  2. package/dist/audit/knowledge-audit-llm.d.ts.map +1 -0
  3. package/dist/audit/knowledge-audit-llm.js +164 -0
  4. package/dist/audit/knowledge-audit.d.ts +61 -0
  5. package/dist/audit/knowledge-audit.d.ts.map +1 -0
  6. package/dist/audit/knowledge-audit.js +203 -0
  7. package/dist/audit/knowledge-fix-plan-llm.d.ts +11 -0
  8. package/dist/audit/knowledge-fix-plan-llm.d.ts.map +1 -0
  9. package/dist/audit/knowledge-fix-plan-llm.js +141 -0
  10. package/dist/audit/knowledge-fix-plan.d.ts +41 -0
  11. package/dist/audit/knowledge-fix-plan.d.ts.map +1 -0
  12. package/dist/audit/knowledge-fix-plan.js +125 -0
  13. package/dist/audit/pipeline-audit-llm.d.ts +11 -0
  14. package/dist/audit/pipeline-audit-llm.d.ts.map +1 -0
  15. package/dist/audit/pipeline-audit-llm.js +134 -0
  16. package/dist/audit/pipeline-audit.d.ts +69 -0
  17. package/dist/audit/pipeline-audit.d.ts.map +1 -0
  18. package/dist/audit/pipeline-audit.js +166 -0
  19. package/dist/audit/templates-audit-llm.d.ts +19 -0
  20. package/dist/audit/templates-audit-llm.d.ts.map +1 -0
  21. package/dist/audit/templates-audit-llm.js +207 -0
  22. package/dist/audit/templates-audit.d.ts +63 -0
  23. package/dist/audit/templates-audit.d.ts.map +1 -0
  24. package/dist/audit/templates-audit.js +171 -0
  25. package/dist/audit/templates-fix-plan-llm.d.ts +19 -0
  26. package/dist/audit/templates-fix-plan-llm.d.ts.map +1 -0
  27. package/dist/audit/templates-fix-plan-llm.js +162 -0
  28. package/dist/audit/templates-fix-plan.d.ts +37 -0
  29. package/dist/audit/templates-fix-plan.d.ts.map +1 -0
  30. package/dist/audit/templates-fix-plan.js +174 -0
  31. package/dist/command-registry.d.ts +28 -0
  32. package/dist/command-registry.d.ts.map +1 -1
  33. package/dist/command-registry.js +91 -1
  34. package/dist/commands/ai-status.command.d.ts +19 -0
  35. package/dist/commands/ai-status.command.d.ts.map +1 -0
  36. package/dist/commands/ai-status.command.js +94 -0
  37. package/dist/commands/api-diff.command.d.ts +11 -0
  38. package/dist/commands/api-diff.command.d.ts.map +1 -0
  39. package/dist/commands/api-diff.command.js +144 -0
  40. package/dist/commands/apply.command.d.ts.map +1 -1
  41. package/dist/commands/apply.command.js +10 -2
  42. package/dist/commands/arch.command.d.ts +9 -0
  43. package/dist/commands/arch.command.d.ts.map +1 -0
  44. package/dist/commands/arch.command.js +186 -0
  45. package/dist/commands/ask.command.d.ts.map +1 -1
  46. package/dist/commands/ask.command.js +10 -9
  47. package/dist/commands/cache-align.command.d.ts +12 -0
  48. package/dist/commands/cache-align.command.d.ts.map +1 -0
  49. package/dist/commands/cache-align.command.js +78 -0
  50. package/dist/commands/check.command.d.ts.map +1 -1
  51. package/dist/commands/check.command.js +26 -2
  52. package/dist/commands/code-intel.command.d.ts +18 -0
  53. package/dist/commands/code-intel.command.d.ts.map +1 -0
  54. package/dist/commands/code-intel.command.js +146 -0
  55. package/dist/commands/codemod.command.d.ts.map +1 -1
  56. package/dist/commands/codemod.command.js +27 -6
  57. package/dist/commands/command-catalog.d.ts +15 -3
  58. package/dist/commands/command-catalog.d.ts.map +1 -1
  59. package/dist/commands/command-catalog.js +407 -34
  60. package/dist/commands/commands.command.d.ts.map +1 -1
  61. package/dist/commands/commands.command.js +4 -4
  62. package/dist/commands/completion.command.d.ts +10 -0
  63. package/dist/commands/completion.command.d.ts.map +1 -0
  64. package/dist/commands/completion.command.js +121 -0
  65. package/dist/commands/compress.command.d.ts +8 -0
  66. package/dist/commands/compress.command.d.ts.map +1 -0
  67. package/dist/commands/compress.command.js +147 -0
  68. package/dist/commands/constructs.command.d.ts.map +1 -1
  69. package/dist/commands/constructs.command.js +89 -23
  70. package/dist/commands/context.command.d.ts.map +1 -1
  71. package/dist/commands/context.command.js +121 -1
  72. package/dist/commands/contract-gate.command.d.ts.map +1 -1
  73. package/dist/commands/contract-gate.command.js +5 -1
  74. package/dist/commands/delegate.command.d.ts +65 -0
  75. package/dist/commands/delegate.command.d.ts.map +1 -0
  76. package/dist/commands/delegate.command.js +657 -0
  77. package/dist/commands/deps-audit.command.d.ts +23 -0
  78. package/dist/commands/deps-audit.command.d.ts.map +1 -0
  79. package/dist/commands/deps-audit.command.js +270 -0
  80. package/dist/commands/dev.command.d.ts.map +1 -1
  81. package/dist/commands/dev.command.js +5 -2
  82. package/dist/commands/diff-check.command.d.ts +30 -0
  83. package/dist/commands/diff-check.command.d.ts.map +1 -0
  84. package/dist/commands/diff-check.command.js +210 -0
  85. package/dist/commands/doctor.command.d.ts.map +1 -1
  86. package/dist/commands/doctor.command.js +162 -10
  87. package/dist/commands/export.command.d.ts.map +1 -1
  88. package/dist/commands/export.command.js +76 -3
  89. package/dist/commands/framework.command.d.ts +12 -0
  90. package/dist/commands/framework.command.d.ts.map +1 -0
  91. package/dist/commands/framework.command.js +180 -0
  92. package/dist/commands/gate.command.d.ts +15 -0
  93. package/dist/commands/gate.command.d.ts.map +1 -0
  94. package/dist/commands/gate.command.js +300 -0
  95. package/dist/commands/gen.command.d.ts.map +1 -1
  96. package/dist/commands/gen.command.js +13 -1
  97. package/dist/commands/graph-code-subverbs.d.ts +33 -0
  98. package/dist/commands/graph-code-subverbs.d.ts.map +1 -0
  99. package/dist/commands/graph-code-subverbs.js +1385 -0
  100. package/dist/commands/graph.command.d.ts.map +1 -1
  101. package/dist/commands/graph.command.js +31 -2
  102. package/dist/commands/help.command.d.ts +4 -3
  103. package/dist/commands/help.command.d.ts.map +1 -1
  104. package/dist/commands/help.command.js +86 -18
  105. package/dist/commands/helper.command.js +1 -1
  106. package/dist/commands/impact.command.d.ts.map +1 -1
  107. package/dist/commands/impact.command.js +171 -1
  108. package/dist/commands/import.command.d.ts.map +1 -1
  109. package/dist/commands/import.command.js +121 -5
  110. package/dist/commands/ingest.command.d.ts.map +1 -1
  111. package/dist/commands/ingest.command.js +5 -1
  112. package/dist/commands/init.command.d.ts.map +1 -1
  113. package/dist/commands/init.command.js +174 -7
  114. package/dist/commands/knowledge-author.command.d.ts.map +1 -1
  115. package/dist/commands/knowledge-author.command.js +9 -0
  116. package/dist/commands/knowledge-propose.command.d.ts.map +1 -1
  117. package/dist/commands/knowledge-propose.command.js +4 -2
  118. package/dist/commands/knowledge.command.d.ts.map +1 -1
  119. package/dist/commands/knowledge.command.js +26 -3
  120. package/dist/commands/migrate.command.d.ts +13 -0
  121. package/dist/commands/migrate.command.d.ts.map +1 -0
  122. package/dist/commands/migrate.command.js +152 -0
  123. package/dist/commands/move-plan.command.d.ts +23 -0
  124. package/dist/commands/move-plan.command.d.ts.map +1 -0
  125. package/dist/commands/move-plan.command.js +360 -0
  126. package/dist/commands/packs-new.d.ts +1 -1
  127. package/dist/commands/packs-new.d.ts.map +1 -1
  128. package/dist/commands/packs-new.js +5 -36
  129. package/dist/commands/packs.command.d.ts.map +1 -1
  130. package/dist/commands/packs.command.js +2 -10
  131. package/dist/commands/plan-context.command.d.ts +11 -0
  132. package/dist/commands/plan-context.command.d.ts.map +1 -0
  133. package/dist/commands/plan-context.command.js +85 -0
  134. package/dist/commands/preflight.command.d.ts.map +1 -1
  135. package/dist/commands/preflight.command.js +15 -0
  136. package/dist/commands/profiles.command.js +4 -4
  137. package/dist/commands/recommend.command.d.ts +6 -0
  138. package/dist/commands/recommend.command.d.ts.map +1 -1
  139. package/dist/commands/recommend.command.js +119 -5
  140. package/dist/commands/release.command.js +13 -13
  141. package/dist/commands/rule-graph-subverbs.d.ts +3 -0
  142. package/dist/commands/rule-graph-subverbs.d.ts.map +1 -0
  143. package/dist/commands/rule-graph-subverbs.js +132 -0
  144. package/dist/commands/rules.command.d.ts.map +1 -1
  145. package/dist/commands/rules.command.js +20 -3
  146. package/dist/commands/scaffold-validate.command.d.ts +22 -0
  147. package/dist/commands/scaffold-validate.command.d.ts.map +1 -0
  148. package/dist/commands/scaffold-validate.command.js +215 -0
  149. package/dist/commands/search-structural.command.d.ts +18 -0
  150. package/dist/commands/search-structural.command.d.ts.map +1 -0
  151. package/dist/commands/search-structural.command.js +376 -0
  152. package/dist/commands/search.command.js +1 -1
  153. package/dist/commands/smart-context.command.d.ts +67 -0
  154. package/dist/commands/smart-context.command.d.ts.map +1 -0
  155. package/dist/commands/smart-context.command.js +4728 -0
  156. package/dist/commands/spike.command.d.ts +22 -0
  157. package/dist/commands/spike.command.d.ts.map +1 -0
  158. package/dist/commands/spike.command.js +235 -0
  159. package/dist/commands/surface.command.d.ts +1 -0
  160. package/dist/commands/surface.command.d.ts.map +1 -1
  161. package/dist/commands/surface.command.js +10 -3
  162. package/dist/commands/task-context.command.d.ts.map +1 -1
  163. package/dist/commands/task-context.command.js +5 -17
  164. package/dist/commands/task.command.d.ts.map +1 -1
  165. package/dist/commands/task.command.js +8 -2
  166. package/dist/commands/template-quality.command.d.ts.map +1 -1
  167. package/dist/commands/template-quality.command.js +39 -3
  168. package/dist/commands/templates.command.d.ts.map +1 -1
  169. package/dist/commands/templates.command.js +37 -2
  170. package/dist/commands/tests.command.d.ts.map +1 -1
  171. package/dist/commands/tests.command.js +13 -2
  172. package/dist/commands/watch.command.d.ts +26 -0
  173. package/dist/commands/watch.command.d.ts.map +1 -0
  174. package/dist/commands/watch.command.js +456 -0
  175. package/dist/dashboard/code-intelligence-data.d.ts +33 -0
  176. package/dist/dashboard/code-intelligence-data.d.ts.map +1 -0
  177. package/dist/dashboard/code-intelligence-data.js +329 -0
  178. package/dist/dashboard/dashboard-api-server.d.ts.map +1 -1
  179. package/dist/dashboard/dashboard-api-server.js +256 -2
  180. package/dist/dashboard/knowledge-ask.d.ts +4 -0
  181. package/dist/dashboard/knowledge-ask.d.ts.map +1 -0
  182. package/dist/dashboard/knowledge-ask.js +112 -0
  183. package/dist/env/load-dotenv.d.ts +15 -0
  184. package/dist/env/load-dotenv.d.ts.map +1 -0
  185. package/dist/env/load-dotenv.js +70 -0
  186. package/dist/export/claude-commands-export.d.ts +60 -0
  187. package/dist/export/claude-commands-export.d.ts.map +1 -0
  188. package/dist/export/claude-commands-export.js +276 -0
  189. package/dist/export/export-formats.d.ts +1 -1
  190. package/dist/export/export-formats.d.ts.map +1 -1
  191. package/dist/export/export-formats.js +139 -12
  192. package/dist/index.d.ts +3 -0
  193. package/dist/index.d.ts.map +1 -1
  194. package/dist/index.js +3 -0
  195. package/dist/init/init-templates.d.ts.map +1 -1
  196. package/dist/init/init-templates.js +133 -113
  197. package/dist/init/paths-advisory.d.ts +20 -0
  198. package/dist/init/paths-advisory.d.ts.map +1 -0
  199. package/dist/init/paths-advisory.js +88 -0
  200. package/dist/main.d.ts.map +1 -1
  201. package/dist/main.js +331 -17
  202. package/dist/output/ccr-store-config.d.ts +18 -0
  203. package/dist/output/ccr-store-config.d.ts.map +1 -0
  204. package/dist/output/ccr-store-config.js +41 -0
  205. package/dist/output/format-output.d.ts.map +1 -1
  206. package/dist/output/format-output.js +6 -1
  207. package/dist/output/output-compression.d.ts +15 -0
  208. package/dist/output/output-compression.d.ts.map +1 -0
  209. package/dist/output/output-compression.js +60 -0
  210. package/dist/output/resolve-compress-type.d.ts +22 -0
  211. package/dist/output/resolve-compress-type.d.ts.map +1 -0
  212. package/dist/output/resolve-compress-type.js +21 -0
  213. package/dist/output/watch-loop.d.ts +9 -1
  214. package/dist/output/watch-loop.d.ts.map +1 -1
  215. package/dist/output/watch-loop.js +13 -3
  216. package/dist/schemas/json-schemas.d.ts +384 -36
  217. package/dist/schemas/json-schemas.d.ts.map +1 -1
  218. package/dist/schemas/json-schemas.js +247 -36
  219. package/dist/surface/profiles.d.ts.map +1 -1
  220. package/dist/surface/profiles.js +54 -10
  221. package/dist/surface/surface-config-writer.d.ts.map +1 -1
  222. package/dist/surface/surface-config-writer.js +23 -11
  223. package/dist/validation/run-validation-loop.d.ts.map +1 -1
  224. package/dist/validation/run-validation-loop.js +5 -1
  225. package/package.json +35 -21
  226. package/dist/commands/plugin.command.d.ts +0 -11
  227. package/dist/commands/plugin.command.d.ts.map +0 -1
  228. package/dist/commands/plugin.command.js +0 -394
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `shrk profiles ...` — unified read-only surface for all pack-/local-
3
- * contributed profiles (plugin lifecycle, migration, and future kinds).
3
+ * contributed profiles (migration, and future kinds).
4
4
  */
5
5
  import { findProfile, inspectSharkcraft, listProfileIssues, listProfiles, ProfileKind, } from '@shrkcrft/inspector';
6
6
  import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
@@ -15,7 +15,7 @@ function parseKind(value) {
15
15
  }
16
16
  export const profilesListCommand = {
17
17
  name: 'list',
18
- description: 'List all registered profiles (plugin-lifecycle, migration, ...).',
18
+ description: 'List all registered profiles (migration, ...).',
19
19
  usage: 'shrk profiles list [--kind <kind>] [--json]',
20
20
  async run(args) {
21
21
  const cwd = resolveCwd(args);
@@ -28,7 +28,7 @@ export const profilesListCommand = {
28
28
  }
29
29
  process.stdout.write(header(`Profiles (${entries.length}${kind ? `, kind=${kind}` : ''})`));
30
30
  if (entries.length === 0) {
31
- process.stdout.write(' (none — contribute via packs: pluginLifecycleProfileFiles, migrationProfileFiles, etc.)\n');
31
+ process.stdout.write(' (none — contribute via packs: migrationProfileFiles, etc.)\n');
32
32
  return 0;
33
33
  }
34
34
  for (const e of entries) {
@@ -132,7 +132,7 @@ export const profilesSearchCommand = {
132
132
  };
133
133
  export const profilesCommand = {
134
134
  name: 'profiles',
135
- description: 'List / inspect pack-contributed profiles (plugin-lifecycle, migration, conventions, …).',
135
+ description: 'List / inspect pack-contributed profiles (migration, conventions, …).',
136
136
  usage: 'shrk profiles list|get|doctor|search ...',
137
137
  async run(args) {
138
138
  const sub = args.positional[0];
@@ -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":"AAUA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAShC,eAAO,MAAM,gBAAgB,EAAE,eAkP9B,CAAC;AA0HF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAY3D;AAcD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAcxD"}
@@ -1,5 +1,5 @@
1
1
  import { readFileSync } from 'node:fs';
2
- import { buildUniversalSearch, entrypointBanner, explainTaskRouting, inspectSharkcraft, recommendCommands, renderUncertaintyReportText, } from '@shrkcrft/inspector';
2
+ import { buildUniversalSearch, entrypointBanner, explainTaskRouting, inspectSharkcraft, rankAll, recommendCommands, renderUncertaintyReportText, } from '@shrkcrft/inspector';
3
3
  import { flagBool, flagNumber, flagString, resolveCwd, } from "../command-registry.js";
4
4
  import { asJson } from "../output/format-output.js";
5
5
  import { loadSurfaceContext } from "../surface/load-surface-context.js";
@@ -65,6 +65,10 @@ export const recommendCommand = {
65
65
  const machineJson = flagBool(args, 'json') || flagBool(args, 'machine-json');
66
66
  let routingMatches = [];
67
67
  let searchReport = null;
68
+ // Reconcile with `brief`/`task`: those route through the SAME shared ranker
69
+ // (`rankAll`). Consult it here so `recommend` never claims a "coverage gap"
70
+ // for a task the rest of the engine confidently matches to a template/pipeline.
71
+ let ranking = null;
68
72
  if (query.length > 0) {
69
73
  try {
70
74
  routingMatches = await explainTaskRouting(inspection, query);
@@ -78,6 +82,46 @@ export const recommendCommand = {
78
82
  catch {
79
83
  searchReport = null;
80
84
  }
85
+ try {
86
+ ranking = rankAll(inspection, query);
87
+ }
88
+ catch {
89
+ ranking = null;
90
+ }
91
+ }
92
+ const topTemplate = ranking?.templates[0];
93
+ const topPipeline = ranking?.pipelines[0];
94
+ const engineHasMatch = (topTemplate?.score ?? 0) >= TEMPLATE_MATCH_THRESHOLD ||
95
+ (topPipeline?.score ?? 0) >= PIPELINE_MATCH_THRESHOLD;
96
+ // R1 — promote a strongly-matched task-routing hint's recommends.commands
97
+ // into the HEADLINE for create/build intents. Routing hints are scored by
98
+ // explainTaskRouting but were previously only shown under --verbose, so the
99
+ // headline fell back to generic review/report/impact commands even when the
100
+ // pack declared the right `shrk gen <template>` playbook. When the top hint
101
+ // clears the threshold AND the query looks like create/build work, its
102
+ // commands lead and the generic defaults slide to the tail. Deterministic.
103
+ const topHint = routingMatches[0];
104
+ const hintCommands = topHint?.hint.recommends.commands ?? [];
105
+ if (query.length > 0 &&
106
+ looksLikeCreateBuild(query) &&
107
+ topHint &&
108
+ topHint.score >= ROUTING_HINT_PROMOTE_THRESHOLD &&
109
+ hintCommands.length > 0) {
110
+ const promoted = hintCommands.map((command) => ({
111
+ command,
112
+ why: `Routing hint "${topHint.hint.id}" matched (score ${topHint.score}) — project playbook for this create/build task.`,
113
+ safetyLevel: promotedSafetyLevel(command),
114
+ }));
115
+ const promotedSet = new Set(promoted.map((p) => p.command));
116
+ const isGenericDefault = (c) => /^(bun run )?shrk (review|report|impact)\b/i.test(c);
117
+ const existing = report.recommendations;
118
+ const keptNonGeneric = existing.filter((r) => !promotedSet.has(r.command) && !isGenericDefault(r.command));
119
+ const keptGeneric = existing.filter((r) => !promotedSet.has(r.command) && isGenericDefault(r.command));
120
+ report.recommendations = [
121
+ ...promoted,
122
+ ...keptNonGeneric,
123
+ ...keptGeneric,
124
+ ];
81
125
  }
82
126
  if (machineJson) {
83
127
  process.stdout.write(asJson({
@@ -85,6 +129,12 @@ export const recommendCommand = {
85
129
  routingMatches,
86
130
  search: searchReport,
87
131
  gated,
132
+ rankerMatch: ranking
133
+ ? {
134
+ topTemplate: topTemplate ? { id: topTemplate.item.id, score: topTemplate.score } : null,
135
+ topPipeline: topPipeline ? { id: topPipeline.item.id, score: topPipeline.score } : null,
136
+ }
137
+ : null,
88
138
  }) + '\n');
89
139
  return 0;
90
140
  }
@@ -128,16 +178,29 @@ export const recommendCommand = {
128
178
  }
129
179
  }
130
180
  }
131
- // Coverage gap — explicit if recommendations look thin and no routing hint fired.
132
- if (report.recommendations.length <= 1 &&
133
- routingMatches.length === 0 &&
134
- query.length > 0) {
181
+ // Coverage gap — explicit if recommendations look thin AND no routing hint
182
+ // fired AND the shared ranker (the engine `brief`/`task` use) also found no
183
+ // template/pipeline. The last clause stops `recommend` from contradicting
184
+ // `task`/`brief`, which would confidently route the same task.
185
+ const thinResult = report.recommendations.length <= 1 && routingMatches.length === 0 && query.length > 0;
186
+ if (thinResult && !engineHasMatch) {
135
187
  process.stdout.write(`\n⚠ Coverage gap — no recipe, no routing hint, and no helper/template matched "${query}".\n` +
136
188
  ` Suggest:\n` +
137
189
  ` shrk coverage scaffolds --task "${query}"\n` +
138
190
  ` shrk feedback actions\n` +
139
191
  ` (or contribute a pack template / helper / routing hint)\n`);
140
192
  }
193
+ else if (thinResult && engineHasMatch && !actionsOnly) {
194
+ // The recipe/routing surface was thin, but the shared ranker DID match —
195
+ // surface that concrete next step instead of a misleading gap.
196
+ process.stdout.write('\nEngine match (shared ranker — same as `shrk task` / `shrk brief`):\n');
197
+ if (topTemplate && topTemplate.score >= TEMPLATE_MATCH_THRESHOLD) {
198
+ process.stdout.write(` $ shrk gen ${topTemplate.item.id} <name> --dry-run [writes-source] — template "${topTemplate.item.name}" matched (score ${topTemplate.score}).\n`);
199
+ }
200
+ if (topPipeline && topPipeline.score >= PIPELINE_MATCH_THRESHOLD) {
201
+ process.stdout.write(` Pipeline: ${topPipeline.item.id} — run \`shrk task "${query}"\` for the full packet.\n`);
202
+ }
203
+ }
141
204
  if (gated.length > 0 && !actionsOnly) {
142
205
  process.stdout.write(`\nGated (experimental, not enabled in this repo):\n`);
143
206
  for (const g of gated.slice(0, 3)) {
@@ -250,6 +313,57 @@ const PLANNING_VERBS = new Set([
250
313
  'evaluate',
251
314
  'assess',
252
315
  ]);
316
+ /**
317
+ * Minimum routing-hint score (from `explainTaskRouting`: +2 per keyword, +3 per
318
+ * phrase, +2 per regex, + confidenceBoost) required to promote a hint's
319
+ * commands into the recommend headline. 3 ⇒ at least one phrase match or two
320
+ * keyword/regex hits — a real match, not a single weak keyword.
321
+ */
322
+ const ROUTING_HINT_PROMOTE_THRESHOLD = 3;
323
+ /**
324
+ * Minimum `rankAll` score for a template / pipeline to count as a real engine
325
+ * match — used only to suppress a false "coverage gap" verdict (and surface the
326
+ * match) when the recipe/routing surface is thin but the shared ranker, which
327
+ * `brief`/`task` also use, found project coverage. Conservative: a single weak
328
+ * token hit scores below this.
329
+ */
330
+ const TEMPLATE_MATCH_THRESHOLD = 3;
331
+ const PIPELINE_MATCH_THRESHOLD = 3;
332
+ const CREATE_BUILD_VERBS = new Set([
333
+ 'create', 'build', 'add', 'generate', 'scaffold', 'implement', 'make', 'new', 'introduce', 'write',
334
+ ]);
335
+ /**
336
+ * Does the query look like create/build work (a routing hint's `shrk gen`
337
+ * playbook is most useful here)? Mirrors {@link looksLikePlanning}: a
338
+ * create/build verb leading the query or in slots 1–3.
339
+ */
340
+ export function looksLikeCreateBuild(query) {
341
+ const tokens = query
342
+ .toLowerCase()
343
+ .replace(/[^a-z0-9\s]/g, ' ')
344
+ .split(/\s+/)
345
+ .filter((t) => t.length > 0);
346
+ if (tokens.length === 0)
347
+ return false;
348
+ if (CREATE_BUILD_VERBS.has(tokens[0]))
349
+ return true;
350
+ for (let i = 1; i < Math.min(4, tokens.length); i++) {
351
+ if (CREATE_BUILD_VERBS.has(tokens[i]))
352
+ return true;
353
+ }
354
+ return false;
355
+ }
356
+ /** Conservative safety classification for a promoted routing-hint command. */
357
+ function promotedSafetyLevel(command) {
358
+ if (/^(bun run )?shrk (gen|init|apply|import)\b/i.test(command))
359
+ return 'writes-source';
360
+ if (/^(bun run )?shrk (brief|dev|onboard|simulate|orchestrate|spec)\b/i.test(command)) {
361
+ return 'writes-drafts';
362
+ }
363
+ if (/^(bun|bunx|npm|pnpm|node|git|nx) /i.test(command))
364
+ return 'runs-shell';
365
+ return 'read-only';
366
+ }
253
367
  export function looksLikePlanning(query) {
254
368
  const tokens = query
255
369
  .toLowerCase()
@@ -204,8 +204,8 @@ function resolveSmokeFlags(args) {
204
204
  const noAssertions = flagBool(args, 'no-assertions');
205
205
  return { assertionsEnabled: !noAssertions };
206
206
  }
207
- // Generic adopter target replaces the previous hardcoded project target.
208
- const BUILTIN_TARGET_IDS = ['sharkcraft', 'dogfood', 'synthetic', 'adopter'];
207
+ // Generic consumer target replaces the previous hardcoded project target.
208
+ const BUILTIN_TARGET_IDS = ['sharkcraft', 'dogfood', 'synthetic', 'consumer'];
209
209
  function resolveTargets(cwd, args, requested) {
210
210
  const want = (id) => requested.length === 0 || requested.includes(id);
211
211
  const out = [];
@@ -224,19 +224,19 @@ function resolveTargets(cwd, args, requested) {
224
224
  writeFileSync(nodePath.join(root, 'package.json'), JSON.stringify({ name: 'sharkcraft-synth', version: '0.0.0', type: 'module' }, null, 2), 'utf8');
225
225
  out.push({ id: 'synthetic', cwd: root, label: 'synthetic-fixture' });
226
226
  }
227
- if (want('adopter')) {
228
- const adopterRoot = flagString(args, 'adopter-root') ??
229
- process.env['SHARKCRAFT_ADOPTER_ROOT'] ??
227
+ if (want('consumer')) {
228
+ const consumerRoot = flagString(args, 'consumer-root') ??
229
+ process.env['SHARKCRAFT_CONSUMER_ROOT'] ??
230
230
  '';
231
- if (adopterRoot && existsSync(adopterRoot)) {
232
- out.push({ id: 'adopter', cwd: adopterRoot, label: `adopter:${adopterRoot}` });
231
+ if (consumerRoot && existsSync(consumerRoot)) {
232
+ out.push({ id: 'consumer', cwd: consumerRoot, label: `consumer:${consumerRoot}` });
233
233
  }
234
234
  else {
235
235
  out.push({
236
- id: 'adopter',
237
- cwd: adopterRoot || '(unset)',
238
- label: 'adopter target',
239
- warning: 'Adopter root not set (pass --adopter-root or set SHARKCRAFT_ADOPTER_ROOT) — skipped.',
236
+ id: 'consumer',
237
+ cwd: consumerRoot || '(unset)',
238
+ label: 'consumer target',
239
+ warning: 'Consumer root not set (pass --consumer-root or set SHARKCRAFT_CONSUMER_ROOT) — skipped.',
240
240
  });
241
241
  }
242
242
  }
@@ -292,7 +292,7 @@ async function runReleaseSmoke(args) {
292
292
  * examples/dogfood-target as the fixture.
293
293
  * - `synthetic` runs the scenarios that don't depend on a prepared source
294
294
  * (unconfigured-repo + pack-authoring).
295
- * - `adopter` runs the read-only scenarios that don't write outside the
295
+ * - `consumer` runs the read-only scenarios that don't write outside the
296
296
  * fixture (e.g. an external project that consumes a SharkCraft pack).
297
297
  */
298
298
  function isScenarioApplicableTo(scenario, target) {
@@ -304,7 +304,7 @@ function isScenarioApplicableTo(scenario, target) {
304
304
  if (target.id === 'dogfood') {
305
305
  return scenario === 'dev-workflow' || scenario === 'pr-review' || scenario === 'governance';
306
306
  }
307
- if (target.id === 'adopter') {
307
+ if (target.id === 'consumer') {
308
308
  return scenario === 'unconfigured-repo' || scenario === 'pack-authoring' || scenario === 'governance';
309
309
  }
310
310
  return true;
@@ -0,0 +1,3 @@
1
+ import { type ICommandHandler } from '../command-registry.js';
2
+ export declare const ruleGraphCommand: ICommandHandler;
3
+ //# sourceMappingURL=rule-graph-subverbs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-graph-subverbs.d.ts","sourceRoot":"","sources":["../../src/commands/rule-graph-subverbs.ts"],"names":[],"mappings":"AAQA,OAAO,EAAwB,KAAK,eAAe,EAAmB,MAAM,wBAAwB,CAAC;AAGrG,eAAO,MAAM,gBAAgB,EAAE,eAc9B,CAAC"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * CLI subverbs for `@shrkcrft/rule-graph`.
3
+ *
4
+ * Sub-namespace: `shrk rule-graph <verb>`. Lives in its own command
5
+ * because the verbs operate on a separate `.sharkcraft/bridge/` store
6
+ * and don't conceptually belong under `shrk graph`.
7
+ */
8
+ import { buildBridge, RuleGraphQueryApi } from '@shrkcrft/rule-graph';
9
+ import { flagBool, resolveCwd } from "../command-registry.js";
10
+ import { asJson, header, kv } from "../output/format-output.js";
11
+ export const ruleGraphCommand = {
12
+ name: 'rule-graph',
13
+ description: 'Bridge the SharkCraft code graph to asset registries (boundary rules, path conventions, templates). Sub-verbs: index, status, for <file>.',
14
+ usage: 'shrk rule-graph index [--json] | shrk rule-graph status [--json] | shrk rule-graph for <file> [--json]',
15
+ async run(args) {
16
+ const sub = args.positional[0];
17
+ if (sub === 'index')
18
+ return runIndex(args);
19
+ if (sub === 'status')
20
+ return runStatus(args);
21
+ if (sub === 'for')
22
+ return runFor(args);
23
+ process.stderr.write(this.usage + '\n');
24
+ return 2;
25
+ },
26
+ };
27
+ async function runIndex(args) {
28
+ const cwd = resolveCwd(args);
29
+ const wantJson = flagBool(args, 'json');
30
+ const r = await buildBridge({ projectRoot: cwd });
31
+ if (wantJson) {
32
+ process.stdout.write(asJson({ ok: true, manifest: r.manifest, durationMs: r.durationMs }) + '\n');
33
+ return 0;
34
+ }
35
+ process.stdout.write(header('Rule-graph bridge'));
36
+ process.stdout.write(kv('schema', r.manifest.schema) + '\n');
37
+ process.stdout.write(kv('bridge edges', String(sumValues(r.manifest.edgesByKind))) + '\n');
38
+ process.stdout.write(kv('rules → files', String(r.manifest.sourceCounts['rule'] ?? 0)) + '\n');
39
+ process.stdout.write(kv('paths → files', String(r.manifest.sourceCounts['path'] ?? 0)) + '\n');
40
+ process.stdout.write(kv('templates → files', String(r.manifest.sourceCounts['template'] ?? 0)) + '\n');
41
+ process.stdout.write(kv('duration', `${r.durationMs}ms`) + '\n');
42
+ return 0;
43
+ }
44
+ async function runStatus(args) {
45
+ const cwd = resolveCwd(args);
46
+ const wantJson = flagBool(args, 'json');
47
+ const missing = RuleGraphQueryApi.missingDescription(cwd);
48
+ if (missing) {
49
+ if (wantJson) {
50
+ process.stdout.write(asJson({ ok: false, state: 'missing', message: missing, nextCommand: 'shrk rule-graph index' }) + '\n');
51
+ return 1;
52
+ }
53
+ process.stderr.write(missing + '\n');
54
+ return 1;
55
+ }
56
+ const api = RuleGraphQueryApi.fromStores(cwd);
57
+ // No public counters from the API itself — just confirm it loads.
58
+ if (wantJson) {
59
+ process.stdout.write(asJson({ ok: true, state: 'fresh' }) + '\n');
60
+ return 0;
61
+ }
62
+ process.stdout.write(header('Rule-graph status'));
63
+ process.stdout.write(kv('state', 'fresh') + '\n');
64
+ void api;
65
+ return 0;
66
+ }
67
+ async function runFor(args) {
68
+ const cwd = resolveCwd(args);
69
+ const wantJson = flagBool(args, 'json');
70
+ const file = args.positional[1];
71
+ if (!file) {
72
+ process.stderr.write('Usage: shrk rule-graph for <file>\n');
73
+ return 2;
74
+ }
75
+ const missing = RuleGraphQueryApi.missingDescription(cwd);
76
+ if (missing) {
77
+ if (wantJson) {
78
+ process.stdout.write(asJson({ ok: false, message: missing, nextCommand: 'shrk rule-graph index' }) + '\n');
79
+ return 1;
80
+ }
81
+ process.stderr.write(missing + '\n');
82
+ return 1;
83
+ }
84
+ const api = RuleGraphQueryApi.fromStores(cwd);
85
+ const r = api.forFile(file);
86
+ if (!r) {
87
+ const payload = { ok: false, error: 'not-found', file };
88
+ if (wantJson) {
89
+ process.stdout.write(asJson(payload) + '\n');
90
+ return 1;
91
+ }
92
+ process.stderr.write(`No file node for "${file}".\n`);
93
+ return 1;
94
+ }
95
+ const payload = {
96
+ schema: 'sharkcraft.rule-graph-for-file/v1',
97
+ file: r.path,
98
+ rules: r.rules.map((h) => ({ id: h.target.id, label: h.target.label, severity: h.edge.data?.['severity'] ?? undefined })),
99
+ paths: r.paths.map((h) => ({ id: h.target.id, label: h.target.label })),
100
+ templates: r.templates.map((h) => ({ id: h.target.id, label: h.target.label })),
101
+ };
102
+ if (wantJson) {
103
+ process.stdout.write(asJson(payload) + '\n');
104
+ return 0;
105
+ }
106
+ process.stdout.write(header(`Rule-graph for: ${r.path}`));
107
+ if (payload.rules.length > 0) {
108
+ process.stdout.write('\nRules (boundary):\n');
109
+ for (const h of payload.rules)
110
+ process.stdout.write(` ${h.id} — ${h.label}${h.severity ? ' [' + h.severity + ']' : ''}\n`);
111
+ }
112
+ if (payload.paths.length > 0) {
113
+ process.stdout.write('\nPath conventions:\n');
114
+ for (const h of payload.paths)
115
+ process.stdout.write(` ${h.id} — ${h.label}\n`);
116
+ }
117
+ if (payload.templates.length > 0) {
118
+ process.stdout.write('\nTemplates:\n');
119
+ for (const h of payload.templates)
120
+ process.stdout.write(` ${h.id} — ${h.label}\n`);
121
+ }
122
+ if (payload.rules.length === 0 && payload.paths.length === 0 && payload.templates.length === 0) {
123
+ process.stdout.write(' (no bridge edges for this file)\n');
124
+ }
125
+ return 0;
126
+ }
127
+ function sumValues(record) {
128
+ let n = 0;
129
+ for (const v of Object.values(record))
130
+ n += v;
131
+ return n;
132
+ }
@@ -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})`));
@@ -0,0 +1,22 @@
1
+ import { type ICommandHandler } from '../command-registry.js';
2
+ /**
3
+ * `shrk scaffold-validate <plan-file>` — verify that the files
4
+ * recorded in a saved generation plan actually exist on disk and
5
+ * look like they came from the template.
6
+ *
7
+ * Read-only: never writes, never re-runs the template. Designed to
8
+ * run after `shrk apply` (or after a human manually copied a plan
9
+ * into place) to catch:
10
+ * - missing files (apply was interrupted, or somebody deleted)
11
+ * - shrunken files (someone replaced the body with `// TODO`)
12
+ * - mismatched operation type (plan said `create`, disk shows
13
+ * something else)
14
+ *
15
+ * NOT a full template-replay check — we can't know the exact
16
+ * expected body without re-rendering the template, which would
17
+ * be far more expensive and would couple this command to every
18
+ * template's variable resolution. Sizes + existence + type catches
19
+ * 95% of real-world failures.
20
+ */
21
+ export declare const scaffoldValidateCommand: ICommandHandler;
22
+ //# sourceMappingURL=scaffold-validate.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold-validate.command.d.ts","sourceRoot":"","sources":["../../src/commands/scaffold-validate.command.ts"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAgChC;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,uBAAuB,EAAE,eAkGrC,CAAC"}