@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,7 +1,7 @@
1
- import { flagBool, flagString, } from "../command-registry.js";
1
+ import { flagBool, flagString } from "../command-registry.js";
2
2
  import { asJson, header } from "../output/format-output.js";
3
- import { COMMAND_CATALOG, CommandLifecycle, CommandSurface, R46_OVERLAY, SafetyLevel, buildCommandSafetyMatrix, commandLifecycle, commandSurface, commandTaskRole, defaultShowInHelp, renderCommandSafetyMatrixMarkdown, } from "./command-catalog.js";
4
- import { buildCommandTaxonomy, buildPrimaryCommandsReport, renderCommandTaxonomyMarkdown, renderCommandTaxonomyText, renderPrimaryCommandsText, } from '@shrkcrft/inspector';
3
+ import { buildCommandSafetyMatrix, COMMAND_CATALOG, CommandLifecycle, commandLifecycle, CommandSurface, commandSurface, commandTaskRole, defaultShowInHelp, R46_OVERLAY, renderCommandSafetyMatrixMarkdown, SafetyLevel } from "./command-catalog.js";
4
+ import { buildCommandTaxonomy, buildPrimaryCommandsReport, renderCommandTaxonomyMarkdown, renderCommandTaxonomyText, renderPrimaryCommandsText } from '@shrkcrft/inspector';
5
5
  export function makeCommandsCommand(registry) {
6
6
  return {
7
7
  name: 'commands',
@@ -589,7 +589,7 @@ export function buildCommandsUxReport() {
589
589
  // issue is clearly structural (none of these currently rise to error).
590
590
  for (const e of COMMAND_CATALOG) {
591
591
  const surface = commandSurface(e);
592
- // (a) primary commands should declare an audience (so adopters can see
592
+ // (a) primary commands should declare an audience (so consumers can see
593
593
  // who the command is for at a glance).
594
594
  if (surface === CommandSurface.Primary && (!e.intendedAudience || e.intendedAudience.length === 0)) {
595
595
  issues.push({
@@ -0,0 +1,10 @@
1
+ import { type ICommandHandler } from '../command-registry.js';
2
+ /**
3
+ * `shrk completion <bash|zsh|fish>` — print a sourcable completion
4
+ * script. The list of verbs is generated from the registered
5
+ * `COMMAND_CATALOG` so completion can't drift from the runtime
6
+ * surface. Subverbs for the high-traffic groups (graph, arch,
7
+ * impact, gate, context, search-structural) are hand-curated.
8
+ */
9
+ export declare const completionCommand: ICommandHandler;
10
+ //# sourceMappingURL=completion.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.command.d.ts","sourceRoot":"","sources":["../../src/commands/completion.command.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAIhC;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,eAqC/B,CAAC"}
@@ -0,0 +1,121 @@
1
+ import { flagBool, flagString, } from "../command-registry.js";
2
+ import { asJson } from "../output/format-output.js";
3
+ import { COMMAND_CATALOG } from "./command-catalog.js";
4
+ /**
5
+ * `shrk completion <bash|zsh|fish>` — print a sourcable completion
6
+ * script. The list of verbs is generated from the registered
7
+ * `COMMAND_CATALOG` so completion can't drift from the runtime
8
+ * surface. Subverbs for the high-traffic groups (graph, arch,
9
+ * impact, gate, context, search-structural) are hand-curated.
10
+ */
11
+ export const completionCommand = {
12
+ name: 'completion',
13
+ description: 'Print a sourcable shell-completion script for the `shrk` CLI. Pipe into your shell rc: `shrk completion bash >> ~/.bashrc`.',
14
+ usage: 'shrk completion <bash|zsh|fish> [--json]',
15
+ async run(args) {
16
+ const shell = (args.positional[0] ?? flagString(args, 'shell') ?? 'bash').toLowerCase();
17
+ const wantJson = flagBool(args, 'json');
18
+ const verbs = collectTopLevelVerbs();
19
+ if (wantJson) {
20
+ process.stdout.write(asJson({
21
+ schema: 'sharkcraft.cli-completion/v1',
22
+ shell,
23
+ verbs,
24
+ subverbs: SUBVERBS,
25
+ }) + '\n');
26
+ return 0;
27
+ }
28
+ switch (shell) {
29
+ case 'bash':
30
+ process.stdout.write(renderBash(verbs));
31
+ return 0;
32
+ case 'zsh':
33
+ process.stdout.write(renderZsh(verbs));
34
+ return 0;
35
+ case 'fish':
36
+ process.stdout.write(renderFish(verbs));
37
+ return 0;
38
+ default:
39
+ process.stderr.write(`Unknown shell "${shell}". Use bash | zsh | fish.\n`);
40
+ return 2;
41
+ }
42
+ },
43
+ };
44
+ /**
45
+ * Subverbs the high-traffic verbs accept. Hand-curated because the
46
+ * runtime catalog represents them as a single CLI surface; we don't
47
+ * want to parse the dispatch chain at completion time.
48
+ */
49
+ const SUBVERBS = Object.freeze({
50
+ graph: ['index', 'status', 'search', 'context', 'impact', 'callers', 'cycles', 'unresolved', 'deps', 'why', 'export'],
51
+ arch: ['check', 'baseline'],
52
+ impact: ['tests', 'graph', 'baseline'],
53
+ gate: ['scaffold-ci', 'scaffold-hook'],
54
+ context: ['build', 'refresh', 'status', 'benchmark'],
55
+ 'search-structural': ['registry'],
56
+ doctor: ['suppress', 'suppressions', 'acknowledge', 'acknowledgements', 'watch'],
57
+ });
58
+ function collectTopLevelVerbs() {
59
+ const set = new Set();
60
+ for (const e of COMMAND_CATALOG) {
61
+ // `command` may carry an argument hint like 'fix preview' — keep
62
+ // only the first token so completion works at the top level.
63
+ const head = e.command.split(/\s+/)[0];
64
+ if (head.length > 0)
65
+ set.add(head);
66
+ }
67
+ return [...set].sort();
68
+ }
69
+ function renderBash(verbs) {
70
+ const verbList = verbs.join(' ');
71
+ const subverbCases = Object.entries(SUBVERBS)
72
+ .map(([verb, subs]) => ` ${verb}) COMPREPLY=($(compgen -W "${subs.join(' ')}" -- "$cur")); return 0;;`)
73
+ .join('\n');
74
+ return `# shrk bash completion. Source from ~/.bashrc:
75
+ # eval "$(shrk completion bash)"
76
+ _shrk_complete() {
77
+ local cur prev words cword
78
+ _init_completion || return
79
+ if [ "$cword" -eq 1 ]; then
80
+ COMPREPLY=($(compgen -W "${verbList}" -- "$cur"))
81
+ return 0
82
+ fi
83
+ case "\${words[1]}" in
84
+ ${subverbCases}
85
+ esac
86
+ COMPREPLY=()
87
+ }
88
+ complete -F _shrk_complete shrk
89
+ `;
90
+ }
91
+ function renderZsh(verbs) {
92
+ const verbList = verbs.join(' ');
93
+ const subverbCases = Object.entries(SUBVERBS)
94
+ .map(([verb, subs]) => ` ${verb}) compadd -- ${subs.join(' ')};;`)
95
+ .join('\n');
96
+ return `# shrk zsh completion. Source from ~/.zshrc:
97
+ # eval "$(shrk completion zsh)"
98
+ _shrk() {
99
+ if [[ \${#words} -eq 2 ]]; then
100
+ compadd -- ${verbList}
101
+ return
102
+ fi
103
+ case "\${words[2]}" in
104
+ ${subverbCases}
105
+ esac
106
+ }
107
+ compdef _shrk shrk
108
+ `;
109
+ }
110
+ function renderFish(verbs) {
111
+ const lines = [
112
+ '# shrk fish completion. Source from ~/.config/fish/completions/shrk.fish:',
113
+ '# shrk completion fish > ~/.config/fish/completions/shrk.fish',
114
+ 'complete -e -c shrk',
115
+ `complete -c shrk -n '__fish_use_subcommand' -a '${verbs.join(' ')}'`,
116
+ ];
117
+ for (const [verb, subs] of Object.entries(SUBVERBS)) {
118
+ lines.push(`complete -c shrk -n '__fish_seen_subcommand_from ${verb}' -a '${subs.join(' ')}'`);
119
+ }
120
+ return lines.join('\n') + '\n';
121
+ }
@@ -0,0 +1,8 @@
1
+ import { type ICommandHandler } from '../command-registry.js';
2
+ export declare const compressCommand: ICommandHandler;
3
+ /**
4
+ * `shrk expand` — the retrieve half of CCR. Print the full original that
5
+ * `shrk compress` cached for a `<<ccr:KEY>>` key.
6
+ */
7
+ export declare const expandCommand: ICommandHandler;
8
+ //# sourceMappingURL=compress.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compress.command.d.ts","sourceRoot":"","sources":["../../src/commands/compress.command.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAgChC,eAAO,MAAM,eAAe,EAAE,eA8F7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,eA4B3B,CAAC"}
@@ -0,0 +1,147 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { Buffer } from 'node:buffer';
3
+ import { compressContent, ECompressionStrategy, EContentType, } from '@shrkcrft/compress';
4
+ import { flagBool, flagNumber, flagString, resolveCwd, } from "../command-registry.js";
5
+ import { asJson } from "../output/format-output.js";
6
+ import { ccrDir, openCcrStore } from "../output/ccr-store-config.js";
7
+ const CONTENT_TYPES = new Set(Object.values(EContentType));
8
+ // Below this size a passthrough no-op isn't worth a warning (tiny snippets
9
+ // legitimately have nothing to compress). Above it, a silent `−0%` re-emit is
10
+ // the opposite of the tool's purpose — nudge the user toward `--type`.
11
+ const PASSTHROUGH_HINT_MIN_BYTES = 128;
12
+ function readInput(args) {
13
+ const positional = args.positional[0];
14
+ const useStdin = flagBool(args, 'stdin') || positional === undefined || positional === '-';
15
+ if (useStdin)
16
+ return readFileSync(0, 'utf8');
17
+ return readFileSync(positional, 'utf8');
18
+ }
19
+ /**
20
+ * `shrk compress` — deterministically compress a blob (file or stdin) before
21
+ * it re-enters an agent prompt. Same information, fewer tokens. Lossy passes
22
+ * cache the original under `.sharkcraft/ccr/` so `shrk expand <key>` can get
23
+ * it back. The compressed text goes to stdout (pipeable); the savings summary
24
+ * goes to stderr unless `--json` is set.
25
+ */
26
+ const COMPRESS_BOOLEAN_FLAGS = new Set([
27
+ 'stdin',
28
+ 'lossless',
29
+ 'no-cache',
30
+ 'json',
31
+ ]);
32
+ export const compressCommand = {
33
+ name: 'compress',
34
+ description: 'Compress a blob (file or stdin) deterministically to cut tokens — JSON→table, logs/search/diffs→signal. Reversible via `shrk expand`.',
35
+ usage: 'shrk [--cwd <dir>] compress [<file>|-] [--stdin] [--type <content-type>] [--query <text>] [--max <n>] [--lossless] [--no-cache] [--json]',
36
+ booleanFlags: COMPRESS_BOOLEAN_FLAGS,
37
+ run(args) {
38
+ const cwd = resolveCwd(args);
39
+ let content;
40
+ try {
41
+ content = readInput(args);
42
+ }
43
+ catch (e) {
44
+ process.stderr.write(`compress: cannot read input — ${e.message}\n`);
45
+ return 1;
46
+ }
47
+ if (content.length === 0) {
48
+ process.stderr.write('compress: empty input.\n');
49
+ return 1;
50
+ }
51
+ const opts = {};
52
+ if (!flagBool(args, 'no-cache'))
53
+ opts.store = openCcrStore(cwd);
54
+ const query = flagString(args, 'query');
55
+ if (query)
56
+ opts.query = query;
57
+ const max = flagNumber(args, 'max');
58
+ if (max !== undefined && max > 0)
59
+ opts.maxItems = Math.floor(max);
60
+ if (flagBool(args, 'lossless'))
61
+ opts.lossless = true;
62
+ const type = flagString(args, 'type');
63
+ if (type && CONTENT_TYPES.has(type))
64
+ opts.contentType = type;
65
+ const result = compressContent(content, opts);
66
+ const pct = Math.round(result.savings.ratio * 100);
67
+ // A lossy result with no cached original (i.e. --no-cache) can't be undone
68
+ // by `shrk expand`. Warn so the dropped detail isn't lost silently.
69
+ if (result.lossy && !result.ccrKey) {
70
+ process.stderr.write('warning: compressed lossily but the original was NOT cached (--no-cache) — ' +
71
+ 'detail is unrecoverable; omit --no-cache to keep it retrievable via `shrk expand`.\n');
72
+ }
73
+ const queryApplied = query !== undefined && query.length > 0;
74
+ if (flagBool(args, 'json')) {
75
+ // tokens are a deterministic ESTIMATE (chars/divisor heuristic), not a
76
+ // real BPE count — flagged so callers don't treat savedRatio as exact.
77
+ const base = {
78
+ contentType: result.contentType,
79
+ strategy: result.strategy,
80
+ lossy: result.lossy,
81
+ tokensBefore: result.savings.before,
82
+ tokensAfter: result.savings.after,
83
+ tokensSaved: result.savings.saved,
84
+ savedRatio: result.savings.ratio,
85
+ tokensAreEstimated: true,
86
+ queryApplied,
87
+ ccrKey: result.ccrKey ?? null,
88
+ note: result.note,
89
+ };
90
+ // Net-loss guard: on a passthrough/no-win blob the engine returns the
91
+ // VERBATIM original as `compressed`. Echoing it back inside the JSON
92
+ // envelope (plus scaffold) costs more tokens than the input. Signal
93
+ // passthrough and omit the duplicated content — the caller still has it.
94
+ const noWin = result.strategy === ECompressionStrategy.Passthrough || result.savings.saved <= 0;
95
+ const payload = noWin
96
+ ? { ...base, passthrough: true, inputBytes: Buffer.byteLength(content, 'utf8') }
97
+ : { ...base, compressed: result.compressed };
98
+ process.stdout.write(asJson(payload) + '\n');
99
+ return 0;
100
+ }
101
+ process.stdout.write(result.compressed + '\n');
102
+ const cached = result.ccrKey ? ` · original cached as ${result.ccrKey} (shrk expand ${result.ccrKey})` : '';
103
+ process.stderr.write(`${result.strategy}: ~${result.savings.before} → ~${result.savings.after} tokens (−${pct}%, est.)${cached}\n`);
104
+ // Token-economy guard: when auto-detect declines to compress a non-trivial
105
+ // input, a silent `−0%` re-emit looks like success. Nudge toward `--type`
106
+ // (stdout stays the verbatim blob; exit code unchanged).
107
+ const inputBytes = Buffer.byteLength(content, 'utf8');
108
+ if (result.strategy === ECompressionStrategy.Passthrough &&
109
+ inputBytes >= PASSTHROUGH_HINT_MIN_BYTES &&
110
+ !flagBool(args, 'lossless')) {
111
+ process.stderr.write(`hint: nothing was compressed — auto-detect classified this as ${result.contentType} and found no win. ` +
112
+ 'Try `--type <content-type>` to force a strategy (json, git-diff, search-results, build-log, source-code, markdown).\n');
113
+ }
114
+ return 0;
115
+ },
116
+ };
117
+ /**
118
+ * `shrk expand` — the retrieve half of CCR. Print the full original that
119
+ * `shrk compress` cached for a `<<ccr:KEY>>` key.
120
+ */
121
+ export const expandCommand = {
122
+ name: 'expand',
123
+ description: 'Retrieve the full original a `shrk compress` run cached, by its `<<ccr:KEY>>` key.',
124
+ usage: 'shrk [--cwd <dir>] expand <key> [--json]',
125
+ run(args) {
126
+ const cwd = resolveCwd(args);
127
+ const key = (args.positional[0] ?? '').trim();
128
+ if (key.length === 0) {
129
+ process.stderr.write('expand: a CCR key is required (e.g. `shrk expand a1b2c3d4e5f60718`).\n');
130
+ return 1;
131
+ }
132
+ const store = openCcrStore(cwd);
133
+ const entry = store.get(key);
134
+ if (!entry) {
135
+ process.stderr.write(`expand: no cached original for key "${key}" under ${ccrDir(cwd)}.\n`);
136
+ return 1;
137
+ }
138
+ if (flagBool(args, 'json')) {
139
+ process.stdout.write(asJson({ key: entry.key, bytes: entry.bytes, content: entry.content }) + '\n');
140
+ return 0;
141
+ }
142
+ // Write the cached original VERBATIM — appending a newline broke byte-for-byte
143
+ // round-trip (`compress … ; expand` must reproduce the input exactly).
144
+ process.stdout.write(entry.content);
145
+ return 0;
146
+ },
147
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"constructs.command.d.ts","sourceRoot":"","sources":["../../src/commands/constructs.command.ts"],"names":[],"mappings":"AA6BA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAahC,eAAO,MAAM,qBAAqB,EAAE,eAqBnC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAoDlC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA8DpC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAmFrC,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,eAmCtC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAwBpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAiClC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAiBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAiBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eA4BrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eA8BrC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA0DpC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA0LpC,CAAC"}
1
+ {"version":3,"file":"constructs.command.d.ts","sourceRoot":"","sources":["../../src/commands/constructs.command.ts"],"names":[],"mappings":"AA8BA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAiGhC,eAAO,MAAM,qBAAqB,EAAE,eAqBnC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAoDlC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAwFpC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAoErC,CAAC;AAEF,eAAO,MAAM,wBAAwB,EAAE,eAmCtC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAwBpC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAiClC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAiBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eAiBrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eA4BrC,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eA8BrC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA0DpC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA0LpC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { mkdirSync, writeFileSync } from 'node:fs';
2
2
  import * as nodePath from 'node:path';
3
3
  import { AdoptionCheckpointStatus, buildConstructAdoptionDiff, buildConstructAdoptionPlan, buildSearchIndex, ConstructAdoptionCategory, evaluateAdoptionCheckpoint, hashDiffBody, inferConstructs, InferredConstructConfidence, inspectSharkcraft, loadConstructs, loadPlaybooks, readAdoptionCheckpoint, readConstructAdoptionStatus, recordAdoptionCheckpoint, renderConstructAdoptionDiff, renderConstructAdoptionMarkdown, renderConstructDraftsModule, searchIndex, SearchKind, traceConstruct, writeConstructAdoption, } from '@shrkcrft/inspector';
4
+ import { GraphQueryApi, GraphStore } from '@shrkcrft/graph';
4
5
  import { flagBool, flagNumber, flagString, resolveCwd, } from "../command-registry.js";
5
6
  import { asJson, header } from "../output/format-output.js";
6
7
  async function loadAll(args) {
@@ -9,6 +10,64 @@ async function loadAll(args) {
9
10
  const constructs = await loadConstructs(inspection);
10
11
  return { constructs, inspection };
11
12
  }
13
+ const GLOB_MAGIC = /[*?[\]{}]/;
14
+ function globToRegExp(glob) {
15
+ // Compile a minimal file glob (`**`, `*`, `?`) to an anchored RegExp. Mark the
16
+ // wildcards with control-char placeholders BEFORE regex-escaping the rest, so
17
+ // the escape pass and the wildcard expansion can never clobber each other (an
18
+ // earlier space-sentinel version was corrupted by editor whitespace handling).
19
+ const DSTAR_SLASH = '\u0000';
20
+ const DSTAR = '\u0001';
21
+ const STAR = '\u0002';
22
+ const QMARK = '\u0003';
23
+ const marked = glob
24
+ .replace(/\*\*\//g, DSTAR_SLASH)
25
+ .replace(/\*\*/g, DSTAR)
26
+ .replace(/\*/g, STAR)
27
+ .replace(/\?/g, QMARK);
28
+ const pattern = marked
29
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
30
+ .replaceAll(DSTAR_SLASH, '(?:.*/)?')
31
+ .replaceAll(DSTAR, '.*')
32
+ .replaceAll(STAR, '[^/]*')
33
+ .replaceAll(QMARK, '[^/]');
34
+ return new RegExp(`^${pattern}$`);
35
+ }
36
+ function enrichTraceWithGraph(declaredFiles, declaredNames, cwd) {
37
+ if (!new GraphStore(cwd).exists()) {
38
+ return { graphState: 'missing', resolvedFiles: [], unresolvedGlobs: [], undeclaredSymbols: [] };
39
+ }
40
+ const api = GraphQueryApi.fromStore(cwd);
41
+ const allPaths = [...api.allFiles()].map((n) => n.path).filter((p) => !!p);
42
+ const resolved = new Set();
43
+ const unresolvedGlobs = [];
44
+ for (const entry of declaredFiles) {
45
+ if (GLOB_MAGIC.test(entry)) {
46
+ const re = globToRegExp(entry);
47
+ const matches = allPaths.filter((p) => re.test(p));
48
+ if (matches.length === 0)
49
+ unresolvedGlobs.push(entry);
50
+ for (const m of matches)
51
+ resolved.add(m);
52
+ }
53
+ else if (api.findFile(entry)) {
54
+ resolved.add(entry);
55
+ }
56
+ }
57
+ const undeclared = new Set();
58
+ for (const path of resolved) {
59
+ for (const sym of api.symbolsIn(`file:${path}`)) {
60
+ if (sym.label && !declaredNames.has(sym.label))
61
+ undeclared.add(sym.label);
62
+ }
63
+ }
64
+ return {
65
+ graphState: 'fresh',
66
+ resolvedFiles: [...resolved].sort(),
67
+ unresolvedGlobs,
68
+ undeclaredSymbols: [...undeclared].sort(),
69
+ };
70
+ }
12
71
  export const constructsListCommand = {
13
72
  name: 'list',
14
73
  description: 'List registered constructs.',
@@ -91,7 +150,7 @@ export const constructsGetCommand = {
91
150
  };
92
151
  export const constructsTraceCommand = {
93
152
  name: 'trace',
94
- description: 'Trace all files / publicApi / events / tokens belonging to a construct. --deep adds related/sandbox/test pointers when present.',
153
+ description: 'Trace a construct\'s declared files / publicApi / events / tokens, verified against the code graph (expands file globs, flags globs that match nothing, lists undeclared symbols defined in those files). --deep adds related / test pointers.',
95
154
  usage: 'shrk constructs trace <id> [--deep] [--json]',
96
155
  async run(args) {
97
156
  const id = args.positional[0];
@@ -107,6 +166,10 @@ export const constructsTraceCommand = {
107
166
  }
108
167
  const trace = traceConstruct(c);
109
168
  const deep = flagBool(args, 'deep');
169
+ // Verify the hand-declared inventory against the code graph (additive — does
170
+ // not change the declared files/tokens the other subverbs rely on).
171
+ const declaredNames = new Set([...trace.publicApi, ...trace.tokens, ...trace.events]);
172
+ const graph = enrichTraceWithGraph(trace.files, declaredNames, resolveCwd(args));
110
173
  const relatedAll = [
111
174
  ...(c.relatedKnowledge ?? []),
112
175
  ...(c.relatedRules ?? []),
@@ -118,11 +181,11 @@ export const constructsTraceCommand = {
118
181
  ? {
119
182
  related: relatedAll,
120
183
  tags: c.tags ?? [],
121
- registryHints: c.tags?.filter((t) => /(registry|composer|defaults|sandbox|demo|barrel)/i.test(t)) ?? [],
184
+ registryHints: c.tags?.filter((t) => /(registry|barrel)/i.test(t)) ?? [],
122
185
  }
123
186
  : undefined;
124
187
  if (flagBool(args, 'json')) {
125
- process.stdout.write(asJson({ ...trace, ...(deepBlock ? { deep: deepBlock } : {}) }) + '\n');
188
+ process.stdout.write(asJson({ ...trace, graph, ...(deepBlock ? { deep: deepBlock } : {}) }) + '\n');
126
189
  return 0;
127
190
  }
128
191
  process.stdout.write(header(`Trace: ${id}`));
@@ -145,6 +208,26 @@ export const constructsTraceCommand = {
145
208
  for (const w of trace.warnings)
146
209
  process.stdout.write(` ! ${w}\n`);
147
210
  }
211
+ // Graph-verified view: this is the part that makes the declared inventory
212
+ // trustworthy rather than a hand-typed partial map.
213
+ if (graph.graphState === 'missing') {
214
+ process.stdout.write('\n(declared inventory only — run `shrk graph index` for a graph-verified inventory)\n');
215
+ }
216
+ else {
217
+ if (graph.unresolvedGlobs.length > 0) {
218
+ process.stdout.write('Unresolved file globs (matched 0 files in the graph):\n');
219
+ for (const g of graph.unresolvedGlobs)
220
+ process.stdout.write(` ! ${g}\n`);
221
+ }
222
+ if (graph.undeclaredSymbols.length > 0) {
223
+ process.stdout.write(`Graph found ${graph.undeclaredSymbols.length} symbol(s) defined in these files but NOT declared on the construct:\n`);
224
+ for (const s of graph.undeclaredSymbols.slice(0, 30))
225
+ process.stdout.write(` + ${s}\n`);
226
+ if (graph.undeclaredSymbols.length > 30) {
227
+ process.stdout.write(` … (${graph.undeclaredSymbols.length - 30} more)\n`);
228
+ }
229
+ }
230
+ }
148
231
  if (deepBlock) {
149
232
  process.stdout.write('\nDeep:\n');
150
233
  if (deepBlock.related.length > 0)
@@ -175,28 +258,11 @@ export const constructsImpactCommand = {
175
258
  }
176
259
  const trace = traceConstruct(c);
177
260
  /**
178
- * Registry touch-points are inferred from the active plugin
179
- * lifecycle profile (key-table + barrels). The engine no longer
180
- * hardcodes project-specific paths.
261
+ * Registry touch-points are not inferred pack-contributed
262
+ * touch-point hints can be added in the future via the convention
263
+ * registry.
181
264
  */
182
265
  const registryTouchPoints = [];
183
- try {
184
- const { listPluginLifecycleProfiles } = await import('@shrkcrft/inspector');
185
- const profiles = await listPluginLifecycleProfiles(inspection);
186
- for (const entry of profiles) {
187
- const p = entry.profile;
188
- if (c.tags?.some((t) => /plugin-key|key-table/i.test(t)) && p.keyTable) {
189
- registryTouchPoints.push(p.keyTable.path);
190
- }
191
- if (c.tags?.some((t) => /barrel|public-api/i.test(t)) && p.barrels) {
192
- for (const b of p.barrels)
193
- registryTouchPoints.push(b.path);
194
- }
195
- }
196
- }
197
- catch {
198
- // Best-effort enrichment; absence of profiles just means no touch-points.
199
- }
200
266
  const verificationCommands = [
201
267
  'shrk check boundaries --changed-only',
202
268
  'shrk doctor',
@@ -1 +1 @@
1
- {"version":3,"file":"context.command.d.ts","sourceRoot":"","sources":["../../src/commands/context.command.ts"],"names":[],"mappings":"AASA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAGhC,eAAO,MAAM,cAAc,EAAE,eA6H5B,CAAC"}
1
+ {"version":3,"file":"context.command.d.ts","sourceRoot":"","sources":["../../src/commands/context.command.ts"],"names":[],"mappings":"AAiBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAgChC,eAAO,MAAM,cAAc,EAAE,eAyI5B,CAAC"}
@@ -1,12 +1,38 @@
1
1
  import { entrypointBanner, inspectSharkcraft } from '@shrkcrft/inspector';
2
2
  import { buildContext } from '@shrkcrft/context';
3
+ import { loadIntentBenchmark, runIntentBenchmark, STARTER_INTENT_BENCHMARK, writeBenchmarkRun, } from '@shrkcrft/context-planner';
4
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
5
+ import * as nodePath from 'node:path';
3
6
  import { buildUniversalSearch, explainTaskRouting, recommendCommands, renderOverviewText, buildProjectOverview, } from '@shrkcrft/inspector';
4
7
  import { flagBool, flagNumber, flagString, flagList, resolveCwd, } from "../command-registry.js";
5
8
  import { asJson, header } from "../output/format-output.js";
9
+ /**
10
+ * Minimal JSON shape for agent / skill consumption — the context-side mirror
11
+ * of `shrk task --compact`. Drops the heavy `body` and `request` echo and
12
+ * carries the section map + structured action hints (so the agent reads
13
+ * forbiddenActions / verificationCommands / preferredFlow directly instead of
14
+ * regexing the markdown body). The schema marker is distinct so consumers can
15
+ * tell the shapes apart at a glance.
16
+ */
17
+ function minimalContext(task, result, commands) {
18
+ return {
19
+ schema: 'sharkcraft.context/v1-compact',
20
+ task,
21
+ tokens: { used: result.totalTokens, max: result.maxTokens },
22
+ sections: result.sections.map((s) => ({
23
+ title: s.title,
24
+ tokens: s.tokens,
25
+ ...(s.truncated ? { truncated: true } : {}),
26
+ })),
27
+ omittedSections: result.omittedSections,
28
+ actionHints: result.actionHints,
29
+ topCommands: (commands?.recommendations ?? []).slice(0, 5).map((r) => r.command),
30
+ };
31
+ }
6
32
  export const contextCommand = {
7
33
  name: 'context',
8
34
  description: 'Build relevant AI-ready context for a task (token-budgeted). Subcommands: build / refresh / status.',
9
- usage: 'shrk context [build|refresh|status] --task "<task>" [--max-tokens 3000] [--framework x] [--area y] [--json]',
35
+ usage: 'shrk context [build|refresh|status] --task "<task>" [--max-tokens 3000] [--framework x] [--area y] [--json] [--compact] [--full]',
10
36
  async run(args) {
11
37
  // Dispatch subcommands (build / refresh / status) based on first positional.
12
38
  const sub = args.positional[0];
@@ -19,6 +45,10 @@ export const contextCommand = {
19
45
  return contextRefreshCommand.run(sliced);
20
46
  return contextStatusCommand.run(sliced);
21
47
  }
48
+ if (sub === 'benchmark') {
49
+ const sliced = { ...args, positional: args.positional.slice(1) };
50
+ return runContextBenchmark(sliced);
51
+ }
22
52
  const task = flagString(args, 'task');
23
53
  if (!task) {
24
54
  process.stderr.write('Missing --task\n');
@@ -72,6 +102,14 @@ export const contextCommand = {
72
102
  // ignore — fall back to legacy context only.
73
103
  }
74
104
  if (flagBool(args, 'json') || flagBool(args, 'machine-json')) {
105
+ // `--compact` emits a minimal, structured agent shape (no long body /
106
+ // request echo) — the context-side mirror of `shrk task --compact`.
107
+ // Carries the load-bearing action hints as structured data so the agent
108
+ // never has to parse the markdown body. Full shape stays the default.
109
+ if (flagBool(args, 'compact')) {
110
+ process.stdout.write(asJson(minimalContext(task, result, commandRecommendations)) + '\n');
111
+ return 0;
112
+ }
75
113
  process.stdout.write(asJson({
76
114
  ...result,
77
115
  commands: commandRecommendations,
@@ -118,3 +156,85 @@ export const contextCommand = {
118
156
  return 0;
119
157
  },
120
158
  };
159
+ async function runContextBenchmark(args) {
160
+ const cwd = resolveCwd(args);
161
+ const wantJson = flagBool(args, 'json');
162
+ // `shrk context benchmark seed` writes a starter fixture to
163
+ // sharkcraft/intent-benchmark.json. Useful first step for adopting
164
+ // the surface — fixture is opinionated but small and easy to prune.
165
+ if (args.positional[0] === 'seed') {
166
+ return runContextBenchmarkSeed(cwd, args);
167
+ }
168
+ const noPersist = flagBool(args, 'no-persist');
169
+ const benchmark = loadIntentBenchmark(cwd);
170
+ if (!benchmark) {
171
+ const msg = `No benchmark at sharkcraft/intent-benchmark.json. Create one with schema "sharkcraft.intent-benchmark/v1" and a "cases" array of { task, expected } entries.\n`;
172
+ if (wantJson) {
173
+ process.stdout.write(asJson({ ok: false, error: 'benchmark-missing' }) + '\n');
174
+ return 1;
175
+ }
176
+ process.stderr.write(msg);
177
+ return 1;
178
+ }
179
+ const run = runIntentBenchmark(benchmark);
180
+ if (!noPersist) {
181
+ try {
182
+ writeBenchmarkRun(cwd, run);
183
+ }
184
+ catch {
185
+ // best-effort
186
+ }
187
+ }
188
+ if (wantJson) {
189
+ process.stdout.write(asJson(run) + '\n');
190
+ return run.failed === 0 ? 0 : 1;
191
+ }
192
+ process.stdout.write(header('Intent classifier benchmark'));
193
+ process.stdout.write(` total ${run.total}\n`);
194
+ process.stdout.write(` passed ${run.passed}\n`);
195
+ process.stdout.write(` failed ${run.failed}\n`);
196
+ process.stdout.write(` accuracy ${Math.round(run.accuracy * 1000) / 10}%\n`);
197
+ const failures = run.cases.filter((c) => !c.passed);
198
+ if (failures.length > 0) {
199
+ process.stdout.write('\nFailures:\n');
200
+ for (const c of failures.slice(0, 20)) {
201
+ process.stdout.write(` ✗ task="${truncateTask(c.task)}" expected=${c.expected} actual=${c.actual}\n`);
202
+ }
203
+ if (failures.length > 20) {
204
+ process.stdout.write(` … (${failures.length - 20} more)\n`);
205
+ }
206
+ }
207
+ return run.failed === 0 ? 0 : 1;
208
+ }
209
+ function truncateTask(s) {
210
+ if (s.length <= 60)
211
+ return s;
212
+ return s.slice(0, 57) + '…';
213
+ }
214
+ function runContextBenchmarkSeed(cwd, args) {
215
+ const wantJson = flagBool(args, 'json');
216
+ const force = flagBool(args, 'force');
217
+ const target = nodePath.join(cwd, 'sharkcraft', 'intent-benchmark.json');
218
+ if (existsSync(target) && !force) {
219
+ const msg = `${target} already exists. Use --force to overwrite.\n`;
220
+ if (wantJson) {
221
+ process.stdout.write(asJson({ ok: false, error: 'exists', path: target }) + '\n');
222
+ return 1;
223
+ }
224
+ process.stderr.write(msg);
225
+ return 1;
226
+ }
227
+ mkdirSync(nodePath.dirname(target), { recursive: true });
228
+ writeFileSync(target, JSON.stringify(STARTER_INTENT_BENCHMARK, null, 2), 'utf8');
229
+ if (wantJson) {
230
+ process.stdout.write(asJson({
231
+ ok: true,
232
+ wrote: target,
233
+ cases: STARTER_INTENT_BENCHMARK.cases.length,
234
+ }) + '\n');
235
+ return 0;
236
+ }
237
+ process.stdout.write(`Seeded ${STARTER_INTENT_BENCHMARK.cases.length} starter intent case(s) → ${target}\n`);
238
+ process.stdout.write('Run `shrk context benchmark` to record accuracy.\n');
239
+ return 0;
240
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"contract-gate.command.d.ts","sourceRoot":"","sources":["../../src/commands/contract-gate.command.ts"],"names":[],"mappings":"AAYA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAWhC,eAAO,MAAM,oBAAoB,EAAE,eAqDlC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA6EpC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,eA6DnC,CAAC"}
1
+ {"version":3,"file":"contract-gate.command.d.ts","sourceRoot":"","sources":["../../src/commands/contract-gate.command.ts"],"names":[],"mappings":"AAYA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAWhC,eAAO,MAAM,oBAAoB,EAAE,eAqDlC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eA6EpC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,eAiEnC,CAAC"}