@shrkcrft/cli 0.1.0-alpha.1 → 0.1.0-alpha.10

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 (120) hide show
  1. package/README.md +1 -1
  2. package/dist/commands/api-diff.command.d.ts +11 -0
  3. package/dist/commands/api-diff.command.d.ts.map +1 -0
  4. package/dist/commands/api-diff.command.js +116 -0
  5. package/dist/commands/arch.command.d.ts +9 -0
  6. package/dist/commands/arch.command.d.ts.map +1 -0
  7. package/dist/commands/arch.command.js +186 -0
  8. package/dist/commands/boundaries.command.d.ts.map +1 -1
  9. package/dist/commands/boundaries.command.js +0 -12
  10. package/dist/commands/check.command.d.ts.map +1 -1
  11. package/dist/commands/check.command.js +20 -30
  12. package/dist/commands/code-intel.command.d.ts +18 -0
  13. package/dist/commands/code-intel.command.d.ts.map +1 -0
  14. package/dist/commands/code-intel.command.js +146 -0
  15. package/dist/commands/command-catalog.d.ts +7 -3
  16. package/dist/commands/command-catalog.d.ts.map +1 -1
  17. package/dist/commands/command-catalog.js +201 -47
  18. package/dist/commands/commands.command.d.ts.map +1 -1
  19. package/dist/commands/commands.command.js +4 -4
  20. package/dist/commands/completion.command.d.ts +10 -0
  21. package/dist/commands/completion.command.d.ts.map +1 -0
  22. package/dist/commands/completion.command.js +121 -0
  23. package/dist/commands/constructs.command.d.ts.map +1 -1
  24. package/dist/commands/constructs.command.js +5 -22
  25. package/dist/commands/context.command.d.ts.map +1 -1
  26. package/dist/commands/context.command.js +89 -0
  27. package/dist/commands/diff-check.command.d.ts +30 -0
  28. package/dist/commands/diff-check.command.d.ts.map +1 -0
  29. package/dist/commands/diff-check.command.js +210 -0
  30. package/dist/commands/doctor.command.d.ts.map +1 -1
  31. package/dist/commands/doctor.command.js +42 -9
  32. package/dist/commands/export.command.d.ts.map +1 -1
  33. package/dist/commands/export.command.js +76 -3
  34. package/dist/commands/framework.command.d.ts +12 -0
  35. package/dist/commands/framework.command.d.ts.map +1 -0
  36. package/dist/commands/framework.command.js +180 -0
  37. package/dist/commands/gate.command.d.ts +15 -0
  38. package/dist/commands/gate.command.d.ts.map +1 -0
  39. package/dist/commands/gate.command.js +296 -0
  40. package/dist/commands/graph-code-subverbs.d.ts +11 -0
  41. package/dist/commands/graph-code-subverbs.d.ts.map +1 -0
  42. package/dist/commands/graph-code-subverbs.js +818 -0
  43. package/dist/commands/graph.command.d.ts.map +1 -1
  44. package/dist/commands/graph.command.js +22 -0
  45. package/dist/commands/help.command.d.ts +4 -3
  46. package/dist/commands/help.command.d.ts.map +1 -1
  47. package/dist/commands/help.command.js +77 -21
  48. package/dist/commands/helper.command.js +1 -1
  49. package/dist/commands/impact.command.d.ts.map +1 -1
  50. package/dist/commands/impact.command.js +170 -1
  51. package/dist/commands/import.command.d.ts.map +1 -1
  52. package/dist/commands/import.command.js +121 -5
  53. package/dist/commands/init.command.d.ts.map +1 -1
  54. package/dist/commands/init.command.js +184 -16
  55. package/dist/commands/mcp.command.d.ts.map +1 -1
  56. package/dist/commands/mcp.command.js +2 -131
  57. package/dist/commands/migrate.command.d.ts +13 -0
  58. package/dist/commands/migrate.command.d.ts.map +1 -0
  59. package/dist/commands/migrate.command.js +152 -0
  60. package/dist/commands/onboard.command.d.ts.map +1 -1
  61. package/dist/commands/onboard.command.js +3 -15
  62. package/dist/commands/packs-new.d.ts +1 -1
  63. package/dist/commands/packs-new.d.ts.map +1 -1
  64. package/dist/commands/packs-new.js +5 -36
  65. package/dist/commands/packs.command.d.ts.map +1 -1
  66. package/dist/commands/packs.command.js +3 -17
  67. package/dist/commands/plan-context.command.d.ts +11 -0
  68. package/dist/commands/plan-context.command.d.ts.map +1 -0
  69. package/dist/commands/plan-context.command.js +77 -0
  70. package/dist/commands/profiles.command.js +4 -4
  71. package/dist/commands/release.command.js +13 -13
  72. package/dist/commands/review.command.d.ts.map +1 -1
  73. package/dist/commands/review.command.js +2 -28
  74. package/dist/commands/rule-graph-subverbs.d.ts +3 -0
  75. package/dist/commands/rule-graph-subverbs.d.ts.map +1 -0
  76. package/dist/commands/rule-graph-subverbs.js +132 -0
  77. package/dist/commands/search-structural.command.d.ts +18 -0
  78. package/dist/commands/search-structural.command.d.ts.map +1 -0
  79. package/dist/commands/search-structural.command.js +376 -0
  80. package/dist/commands/search.command.js +1 -1
  81. package/dist/commands/task-context.command.js +0 -16
  82. package/dist/commands/task.command.d.ts.map +1 -1
  83. package/dist/commands/task.command.js +8 -2
  84. package/dist/dashboard/code-intelligence-data.d.ts +33 -0
  85. package/dist/dashboard/code-intelligence-data.d.ts.map +1 -0
  86. package/dist/dashboard/code-intelligence-data.js +307 -0
  87. package/dist/dashboard/dashboard-api-server.d.ts.map +1 -1
  88. package/dist/dashboard/dashboard-api-server.js +137 -1
  89. package/dist/export/claude-commands-export.d.ts +60 -0
  90. package/dist/export/claude-commands-export.d.ts.map +1 -0
  91. package/dist/export/claude-commands-export.js +276 -0
  92. package/dist/export/export-formats.d.ts +1 -1
  93. package/dist/export/export-formats.d.ts.map +1 -1
  94. package/dist/export/export-formats.js +139 -12
  95. package/dist/init/init-templates.d.ts.map +1 -1
  96. package/dist/init/init-templates.js +133 -113
  97. package/dist/init/paths-advisory.d.ts +20 -0
  98. package/dist/init/paths-advisory.d.ts.map +1 -0
  99. package/dist/init/paths-advisory.js +88 -0
  100. package/dist/main.d.ts +1 -1
  101. package/dist/main.d.ts.map +1 -1
  102. package/dist/main.js +137 -46
  103. package/dist/output/failure-hints.d.ts +1 -9
  104. package/dist/output/failure-hints.d.ts.map +1 -1
  105. package/dist/output/failure-hints.js +2 -8
  106. package/dist/output/watch-loop.d.ts +9 -1
  107. package/dist/output/watch-loop.d.ts.map +1 -1
  108. package/dist/output/watch-loop.js +13 -3
  109. package/dist/schemas/json-schemas.d.ts +36 -36
  110. package/dist/schemas/json-schemas.js +36 -36
  111. package/dist/surface/about.d.ts.map +1 -1
  112. package/dist/surface/about.js +37 -15
  113. package/dist/surface/no-args-landing.d.ts.map +1 -1
  114. package/dist/surface/no-args-landing.js +9 -13
  115. package/dist/surface/surface-config-writer.d.ts.map +1 -1
  116. package/dist/surface/surface-config-writer.js +23 -11
  117. package/package.json +36 -25
  118. package/dist/commands/plugin.command.d.ts +0 -11
  119. package/dist/commands/plugin.command.d.ts.map +0 -1
  120. package/dist/commands/plugin.command.js +0 -394
@@ -0,0 +1,376 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import * as nodePath from 'node:path';
3
+ import { applyRewritePlan, PatternRegistryStore, planRewrite, runSearch, signRewritePlan, STARTER_PATTERNS, verifySignedRewritePlan, } from '@shrkcrft/structural-search';
4
+ import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
5
+ import { asJson, header, kv } from "../output/format-output.js";
6
+ /**
7
+ * `shrk search structural` — declarative AST pattern matching with
8
+ * optional rewrite mode (Wave 8). Patterns are JSON (no executable
9
+ * predicates) — either inline via --pattern or from a file via
10
+ * --pattern-file.
11
+ *
12
+ * Rewrite flow:
13
+ * 1. Pass `--rewrite '<json>'` (a `RewriteRecipe`) to compute a
14
+ * rewrite plan.
15
+ * 2. Preview is shown by default (no fs writes).
16
+ * 3. Pass `--apply` to actually write the changes.
17
+ *
18
+ * The plan can be inspected as JSON via `--json` and replayed via
19
+ * `--plan-in <path>` (write the plan with `--plan-out <path>` first).
20
+ */
21
+ export const searchStructuralCommand = {
22
+ name: 'search-structural',
23
+ description: 'Run an AST-shape pattern over the project. Patterns are declarative JSON. Optional rewrite mode: --rewrite <recipe-json> previews; --apply writes the change to disk.',
24
+ usage: 'shrk search-structural (--pattern <json> | --pattern-file <path>) [--limit N] [--rewrite <recipe-json>] [--rewrite-file <path>] [--apply] [--dry-run] [--plan-out <path>] [--plan-in <path>] [--sign] [--verify-signature] [--secret-env <VAR>] [--json]',
25
+ async run(args) {
26
+ const cwd = resolveCwd(args);
27
+ const wantJson = flagBool(args, 'json');
28
+ // `shrk search-structural registry ...` — pattern registry subverbs.
29
+ // Dispatch before any pattern parsing so a missing pattern file
30
+ // doesn't reject a registry-only call.
31
+ if (args.positional[0] === 'registry') {
32
+ return runRegistry({ ...args, positional: args.positional.slice(1) });
33
+ }
34
+ const planInPath = flagString(args, 'plan-in');
35
+ if (planInPath) {
36
+ return runFromSavedPlan(cwd, planInPath, args, wantJson);
37
+ }
38
+ const inline = flagString(args, 'pattern');
39
+ const patternFile = flagString(args, 'pattern-file');
40
+ if (!inline && !patternFile) {
41
+ process.stderr.write(this.usage + '\n');
42
+ return 2;
43
+ }
44
+ let pattern;
45
+ try {
46
+ pattern = parseJson(inline, patternFile, cwd);
47
+ }
48
+ catch (e) {
49
+ process.stderr.write(`Pattern parse error: ${e.message}\n`);
50
+ return 2;
51
+ }
52
+ const limit = Number(flagString(args, 'limit') ?? '200');
53
+ // Rewrite path?
54
+ const recipeInline = flagString(args, 'rewrite');
55
+ const recipeFile = flagString(args, 'rewrite-file');
56
+ if (recipeInline || recipeFile) {
57
+ let recipe;
58
+ try {
59
+ recipe = parseJson(recipeInline, recipeFile, cwd);
60
+ }
61
+ catch (e) {
62
+ process.stderr.write(`Recipe parse error: ${e.message}\n`);
63
+ return 2;
64
+ }
65
+ return runRewrite(cwd, pattern, recipe, args, wantJson);
66
+ }
67
+ // Plain match path.
68
+ const result = runSearch({ projectRoot: cwd, pattern, limit });
69
+ if (wantJson) {
70
+ process.stdout.write(asJson(result) + '\n');
71
+ return 0;
72
+ }
73
+ process.stdout.write(header(`Structural search: ${result.pattern.summary}`));
74
+ process.stdout.write(kv('files scanned', String(result.filesScanned)) + '\n');
75
+ process.stdout.write(kv('matches', String(result.matchCount)) + '\n');
76
+ if (result.truncated)
77
+ process.stdout.write(kv('truncated', 'yes') + '\n');
78
+ for (const m of result.matches.slice(0, 50)) {
79
+ process.stdout.write(` ${m.file}:${m.line}:${m.column} ${m.nodeKind} ${m.excerpt}\n`);
80
+ }
81
+ for (const d of result.diagnostics.slice(0, 10)) {
82
+ process.stdout.write(`! ${d}\n`);
83
+ }
84
+ return 0;
85
+ },
86
+ };
87
+ async function runRewrite(cwd, pattern, recipe, args, wantJson) {
88
+ const apply = flagBool(args, 'apply');
89
+ const dryRun = flagBool(args, 'dry-run');
90
+ const planOut = flagString(args, 'plan-out');
91
+ const wantSign = flagBool(args, 'sign');
92
+ const secretEnv = flagString(args, 'secret-env') ?? 'SHRKCRFT_REWRITE_SECRET';
93
+ const plan = planRewrite({ projectRoot: cwd, pattern, recipe });
94
+ if (planOut) {
95
+ const abs = nodePath.isAbsolute(planOut) ? planOut : nodePath.resolve(cwd, planOut);
96
+ const { writeFileSync, mkdirSync } = await import('node:fs');
97
+ mkdirSync(nodePath.dirname(abs), { recursive: true });
98
+ const payload = wantSign
99
+ ? signPlanOrFail(plan, secretEnv)
100
+ : plan;
101
+ if (!payload)
102
+ return 2;
103
+ writeFileSync(abs, JSON.stringify(payload, null, 2), 'utf8');
104
+ }
105
+ if (!apply) {
106
+ // Preview only.
107
+ if (wantJson) {
108
+ process.stdout.write(asJson(plan) + '\n');
109
+ return 0;
110
+ }
111
+ process.stdout.write(header(`Rewrite plan (preview): ${recipe.kind}`));
112
+ process.stdout.write(kv('files scanned', String(plan.filesScanned)) + '\n');
113
+ process.stdout.write(kv('files to change', String(plan.files.length)) + '\n');
114
+ process.stdout.write(kv('total edits', String(plan.totalEdits)) + '\n');
115
+ if (planOut)
116
+ process.stdout.write(kv('plan written to', planOut) + '\n');
117
+ for (const f of plan.files.slice(0, 20)) {
118
+ process.stdout.write(`\n ${f.path}:\n`);
119
+ for (const e of f.edits.slice(0, 5)) {
120
+ process.stdout.write(` L${e.line} ${truncate(e.before)} → ${truncate(e.replacement)}\n`);
121
+ }
122
+ if (f.edits.length > 5)
123
+ process.stdout.write(` … (${f.edits.length - 5} more edits)\n`);
124
+ }
125
+ if (plan.files.length > 20) {
126
+ process.stdout.write(`\n … (${plan.files.length - 20} more files)\n`);
127
+ }
128
+ for (const d of plan.diagnostics.slice(0, 10))
129
+ process.stdout.write(`! ${d}\n`);
130
+ process.stdout.write(`\nTo write these changes: rerun with --apply.\n`);
131
+ return 0;
132
+ }
133
+ // Apply path.
134
+ const result = applyRewritePlan(plan, { projectRoot: cwd, dryRun });
135
+ if (wantJson) {
136
+ process.stdout.write(asJson({ plan, result, dryRun }) + '\n');
137
+ return 0;
138
+ }
139
+ process.stdout.write(header(`Rewrite ${dryRun ? '(dry-run)' : '(applied)'}: ${recipe.kind}`));
140
+ process.stdout.write(kv('files attempted', String(result.filesAttempted)) + '\n');
141
+ process.stdout.write(kv('files changed', String(result.filesChanged)) + '\n');
142
+ process.stdout.write(kv('bytes written', String(result.bytesWritten)) + '\n');
143
+ if (result.conflicts.length > 0) {
144
+ process.stdout.write(kv('conflicts (skipped)', String(result.conflicts.length)) + '\n');
145
+ for (const c of result.conflicts.slice(0, 10))
146
+ process.stdout.write(` • ${c}\n`);
147
+ }
148
+ for (const d of result.diagnostics.slice(0, 10))
149
+ process.stdout.write(`! ${d}\n`);
150
+ return result.conflicts.length > 0 ? 1 : 0;
151
+ }
152
+ async function runFromSavedPlan(cwd, planPath, args, wantJson) {
153
+ const abs = nodePath.isAbsolute(planPath) ? planPath : nodePath.resolve(cwd, planPath);
154
+ let raw;
155
+ try {
156
+ raw = JSON.parse(readFileSync(abs, 'utf8'));
157
+ }
158
+ catch (e) {
159
+ process.stderr.write(`Plan file read error: ${e.message}\n`);
160
+ return 2;
161
+ }
162
+ const apply = flagBool(args, 'apply');
163
+ const dryRun = flagBool(args, 'dry-run');
164
+ const verify = flagBool(args, 'verify-signature');
165
+ const secretEnv = flagString(args, 'secret-env') ?? 'SHRKCRFT_REWRITE_SECRET';
166
+ if (!apply) {
167
+ process.stderr.write('Replaying a saved plan requires --apply (or --apply --dry-run).\n');
168
+ return 2;
169
+ }
170
+ const wrapper = raw;
171
+ const isSigned = wrapper.schema === 'sharkcraft.structural-rewrite-plan-signed/v1';
172
+ if (verify) {
173
+ if (!isSigned) {
174
+ process.stderr.write('--verify-signature passed but plan is not signed.\n');
175
+ return 1;
176
+ }
177
+ const secret = process.env[secretEnv];
178
+ if (!secret) {
179
+ process.stderr.write(`Missing secret: env var ${secretEnv} not set.\n`);
180
+ return 1;
181
+ }
182
+ const v = verifySignedRewritePlan(raw, { secret });
183
+ if (!v.ok) {
184
+ process.stderr.write(`Signature verification failed (${v.reason}): ${v.message ?? ''}\n`);
185
+ return 1;
186
+ }
187
+ }
188
+ const plan = isSigned ? raw.plan : raw;
189
+ const result = applyRewritePlan(plan, { projectRoot: cwd, dryRun });
190
+ if (wantJson) {
191
+ process.stdout.write(asJson({ result, dryRun, verified: verify }) + '\n');
192
+ return result.conflicts.length > 0 ? 1 : 0;
193
+ }
194
+ process.stdout.write(header(`Rewrite ${dryRun ? '(dry-run)' : '(applied)'} from saved plan`));
195
+ if (verify)
196
+ process.stdout.write(kv('signature', 'verified') + '\n');
197
+ process.stdout.write(kv('files changed', String(result.filesChanged)) + '\n');
198
+ process.stdout.write(kv('conflicts (skipped)', String(result.conflicts.length)) + '\n');
199
+ return result.conflicts.length > 0 ? 1 : 0;
200
+ }
201
+ function signPlanOrFail(plan, secretEnv) {
202
+ const secret = process.env[secretEnv];
203
+ if (!secret) {
204
+ process.stderr.write(`Missing secret: env var ${secretEnv} not set (required for --sign).\n`);
205
+ return undefined;
206
+ }
207
+ return signRewritePlan(plan, { secret });
208
+ }
209
+ function parseJson(inline, fileFlag, cwd) {
210
+ if (inline)
211
+ return JSON.parse(inline);
212
+ const abs = nodePath.isAbsolute(fileFlag)
213
+ ? fileFlag
214
+ : nodePath.resolve(cwd, fileFlag);
215
+ return JSON.parse(readFileSync(abs, 'utf8'));
216
+ }
217
+ function truncate(s) {
218
+ const oneLine = s.replace(/\s+/g, ' ').trim();
219
+ return oneLine.length > 60 ? oneLine.slice(0, 57) + '…' : oneLine;
220
+ }
221
+ async function runRegistry(args) {
222
+ const cwd = resolveCwd(args);
223
+ const wantJson = flagBool(args, 'json');
224
+ const sub = args.positional[0] ?? 'list';
225
+ const store = new PatternRegistryStore(cwd);
226
+ if (sub === 'list') {
227
+ const reg = store.read();
228
+ if (wantJson) {
229
+ process.stdout.write(asJson({ path: store.absPath, registry: reg }) + '\n');
230
+ return 0;
231
+ }
232
+ if (reg.patterns.length === 0) {
233
+ process.stdout.write('No patterns registered.\n');
234
+ process.stdout.write(`(file: ${store.absPath})\n`);
235
+ return 0;
236
+ }
237
+ process.stdout.write(header(`Pattern registry (${reg.patterns.length})`));
238
+ process.stdout.write(kv('path', store.absPath) + '\n');
239
+ for (const p of reg.patterns) {
240
+ const err = p.lastValidationError ? ` ✗ ${p.lastValidationError}` : '';
241
+ const validated = p.lastValidatedAt ? ` [validated ${p.lastValidatedAt}]` : '';
242
+ process.stdout.write(` • ${p.id} (${p.pattern.kind})${validated}${err}\n`);
243
+ if (p.title)
244
+ process.stdout.write(` ${p.title}\n`);
245
+ }
246
+ return 0;
247
+ }
248
+ if (sub === 'add') {
249
+ const id = flagString(args, 'id');
250
+ const inline = flagString(args, 'pattern');
251
+ const patternFile = flagString(args, 'pattern-file');
252
+ const title = flagString(args, 'title');
253
+ const description = flagString(args, 'description');
254
+ if (!id) {
255
+ process.stderr.write('Usage: shrk search-structural registry add --id <id> (--pattern <json> | --pattern-file <path>) [--title "..."] [--description "..."]\n');
256
+ return 2;
257
+ }
258
+ if (!inline && !patternFile) {
259
+ process.stderr.write('Missing pattern body (--pattern or --pattern-file).\n');
260
+ return 2;
261
+ }
262
+ let pattern;
263
+ try {
264
+ pattern = parseJson(inline, patternFile, cwd);
265
+ }
266
+ catch (e) {
267
+ process.stderr.write(`Pattern parse error: ${e.message}\n`);
268
+ return 2;
269
+ }
270
+ const envelope = {
271
+ schema: 'sharkcraft.structural-pattern/v1',
272
+ id,
273
+ ...(title ? { title } : {}),
274
+ ...(description ? { description } : {}),
275
+ pattern,
276
+ };
277
+ const { result, entry } = store.add(envelope);
278
+ if (!result.ok) {
279
+ if (wantJson) {
280
+ process.stdout.write(asJson({ ok: false, error: result.error }) + '\n');
281
+ }
282
+ else {
283
+ process.stderr.write(`Pattern rejected: ${result.error}\n`);
284
+ }
285
+ return 2;
286
+ }
287
+ if (wantJson) {
288
+ process.stdout.write(asJson({ ok: true, entry, path: store.absPath }) + '\n');
289
+ return 0;
290
+ }
291
+ process.stdout.write(`Pattern registered: ${entry?.id} (${entry?.pattern.kind})\n`);
292
+ process.stdout.write(` → ${store.absPath}\n`);
293
+ return 0;
294
+ }
295
+ if (sub === 'remove') {
296
+ const id = args.positional[1] ?? flagString(args, 'id');
297
+ if (!id) {
298
+ process.stderr.write('Usage: shrk search-structural registry remove <id>\n');
299
+ return 2;
300
+ }
301
+ const removed = store.remove(id);
302
+ if (wantJson) {
303
+ process.stdout.write(asJson({ removed, id }) + '\n');
304
+ return removed ? 0 : 1;
305
+ }
306
+ process.stdout.write(removed ? `Removed pattern "${id}".\n` : `No pattern with id "${id}".\n`);
307
+ return removed ? 0 : 1;
308
+ }
309
+ if (sub === 'validate') {
310
+ const result = store.validateAll();
311
+ if (wantJson) {
312
+ process.stdout.write(asJson(result) + '\n');
313
+ return result.failed === 0 ? 0 : 1;
314
+ }
315
+ process.stdout.write(header('Pattern registry validation'));
316
+ process.stdout.write(kv('total', String(result.total)) + '\n');
317
+ process.stdout.write(kv('failed', String(result.failed)) + '\n');
318
+ if (result.failed > 0) {
319
+ process.stdout.write('\nFailures:\n');
320
+ for (const e of result.errors) {
321
+ process.stdout.write(` ✗ ${e.id} — ${e.error}\n`);
322
+ }
323
+ return 1;
324
+ }
325
+ process.stdout.write('\nAll patterns valid.\n');
326
+ return 0;
327
+ }
328
+ if (sub === 'clear') {
329
+ const cleared = store.clear();
330
+ if (wantJson) {
331
+ process.stdout.write(asJson({ cleared, path: store.absPath }) + '\n');
332
+ return 0;
333
+ }
334
+ process.stdout.write(cleared ? `Cleared ${store.absPath}\n` : 'No registry file to clear.\n');
335
+ return 0;
336
+ }
337
+ if (sub === 'seed') {
338
+ const force = flagBool(args, 'force');
339
+ const existing = store.read();
340
+ if (existing.patterns.length > 0 && !force) {
341
+ const msg = `Registry already has ${existing.patterns.length} pattern(s). Use --force to merge / overwrite seed entries.\n`;
342
+ if (wantJson) {
343
+ process.stdout.write(asJson({ ok: false, error: 'non-empty' }) + '\n');
344
+ return 1;
345
+ }
346
+ process.stderr.write(msg);
347
+ return 1;
348
+ }
349
+ const added = [];
350
+ const failed = [];
351
+ for (const envelope of STARTER_PATTERNS) {
352
+ const { result, entry } = store.add(envelope);
353
+ if (result.ok && entry) {
354
+ added.push(entry.id);
355
+ }
356
+ else {
357
+ failed.push({ id: envelope.id ?? '?', error: result.error ?? 'unknown' });
358
+ }
359
+ }
360
+ if (wantJson) {
361
+ process.stdout.write(asJson({ ok: failed.length === 0, added, failed, path: store.absPath }) + '\n');
362
+ return failed.length === 0 ? 0 : 1;
363
+ }
364
+ process.stdout.write(`Seeded ${added.length} starter pattern(s) → ${store.absPath}\n`);
365
+ for (const id of added)
366
+ process.stdout.write(` + ${id}\n`);
367
+ if (failed.length > 0) {
368
+ process.stdout.write('\nFailures:\n');
369
+ for (const f of failed)
370
+ process.stdout.write(` ✗ ${f.id} — ${f.error}\n`);
371
+ }
372
+ return failed.length === 0 ? 0 : 1;
373
+ }
374
+ process.stderr.write('Usage: shrk search-structural registry <list|add|remove|validate|clear|seed> [--json]\n');
375
+ return 2;
376
+ }
@@ -27,7 +27,7 @@ function parseSources(args) {
27
27
  }
28
28
  export const searchCommand = {
29
29
  name: 'search',
30
- description: 'Universal search across commands, MCP tools, knowledge, rules, paths, conventions, templates, helpers, playbooks, constructs, policies, decisions, scaffold patterns, contract templates, migration profiles, plugin lifecycle profiles, feedback rules, task routing hints, docs, recent reports. Default emits the 7-section unified output; pass --legacy for the flat output.',
30
+ description: 'Universal search across commands, MCP tools, knowledge, rules, paths, conventions, templates, helpers, playbooks, constructs, policies, decisions, scaffold patterns, contract templates, migration profiles, feedback rules, task routing hints, docs, recent reports. Default emits the 7-section unified output; pass --legacy for the flat output.',
31
31
  usage: 'shrk search <query> [--kind <kind>] [--source local|pack|...] [--limit N] [--explain] [--commands-only] [--actions-only] [--format text|markdown|json] [--legacy]',
32
32
  async run(args) {
33
33
  // Sub-dispatch for `shrk search tuning [list|doctor]`.
@@ -399,22 +399,6 @@ async function collectLikelyFilesV2(input) {
399
399
  }
400
400
  }
401
401
  }
402
- // Boost files that sit on registered plugin-lifecycle profile barrels.
403
- try {
404
- const { listPluginLifecycleProfiles } = await import('@shrkcrft/inspector');
405
- const profiles = await listPluginLifecycleProfiles(inspection);
406
- for (const entry of profiles) {
407
- for (const b of entry.profile.barrels ?? []) {
408
- for (const f of [...scoreByPath.keys()]) {
409
- if (f.includes(b.path))
410
- bump(f, 3, `lifecycle profile barrel: ${b.id}`);
411
- }
412
- }
413
- }
414
- }
415
- catch {
416
- // Profile registry unavailable — skip the boost.
417
- }
418
402
  // 10) Tests — files that look like they test the matched files.
419
403
  const tests = [];
420
404
  for (const f of [...scoreByPath.keys()]) {
@@ -1 +1 @@
1
- {"version":3,"file":"task.command.d.ts","sourceRoot":"","sources":["../../src/commands/task.command.ts"],"names":[],"mappings":"AAiBA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA2DhC,eAAO,MAAM,WAAW,EAAE,eA8PzB,CAAC"}
1
+ {"version":3,"file":"task.command.d.ts","sourceRoot":"","sources":["../../src/commands/task.command.ts"],"names":[],"mappings":"AAiBA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA2DhC,eAAO,MAAM,WAAW,EAAE,eAoQzB,CAAC"}
@@ -58,8 +58,8 @@ function minimalTaskPacket(p) {
58
58
  }
59
59
  export const taskCommand = {
60
60
  name: 'task',
61
- description: 'Build an AI-ready task packet: relevant context, action hints, recommended pipeline, templates, paths, verification commands. Pass `--next` to skip the packet and survey the workspace for the highest-leverage next action.',
62
- usage: 'shrk [--cwd <dir>] task "<task>" [--max-tokens 4000] [--scope x,y] [--explain-ranking] [--json] [--compact] OR shrk task --next [--json]',
61
+ description: 'Build an AI-ready task packet: relevant context, action hints, recommended pipeline, templates, paths, verification commands. Defaults to a compact packet (top-5 rules / top-3 templates / 5 hints per field) to keep agent token cost low. Pass `--full` to get the unrestricted packet, or `--next` to skip the packet and survey the workspace for the highest-leverage next action.',
62
+ usage: 'shrk [--cwd <dir>] task "<task>" [--max-tokens 4000] [--scope x,y] [--explain-ranking] [--full] [--json] OR shrk task --next [--json]',
63
63
  async run(args) {
64
64
  const positional = args.positional;
65
65
  // `--next` short-circuits the packet build. Survey doctor / lint /
@@ -142,10 +142,16 @@ export const taskCommand = {
142
142
  const maxTokens = flagNumber(args, 'max-tokens') ?? 3500;
143
143
  const scope = flagList(args, 'scope');
144
144
  const explainRanking = flagBool(args, 'explain-ranking') || flagBool(args, 'json');
145
+ // `--full` (or `--verbose`, which already affects text rendering) opts
146
+ // out of the compact packet — pass it when an agent genuinely needs
147
+ // the full ranking + uncapped action-hint aggregates. Default is the
148
+ // tight packet (5 rules / 3 templates / 5 hints per field).
149
+ const compact = !flagBool(args, 'full') && !flagBool(args, 'verbose');
145
150
  const packet = buildTaskPacket(inspection, task, {
146
151
  maxTokens,
147
152
  ...(scope.length ? { scope } : {}),
148
153
  explainRanking,
154
+ compact,
149
155
  });
150
156
  // Uncertainty summary always computed; coverage gaps when requested.
151
157
  const uncertainty = buildUncertaintySummary(packet);
@@ -0,0 +1,33 @@
1
+ import type { IDashboardCodeIntelligenceResponse, IDashboardMigrationsResponse, IDashboardQualityGatesResponse, IDashboardRoutesResponse } from '@shrkcrft/dashboard-api';
2
+ /**
3
+ * Build the Code Intelligence overview response.
4
+ *
5
+ * Reads the three on-disk stores plus runs the architecture-guard
6
+ * check inline. Every section degrades to `available: false` with a
7
+ * `hint` when its backing store is missing — the dashboard renders
8
+ * those as "run `shrk graph index` to enable" cards rather than
9
+ * blocking the whole panel.
10
+ *
11
+ * Pure read — never builds or writes anything.
12
+ */
13
+ export declare function buildDashboardCodeIntelligence(projectRoot: string): IDashboardCodeIntelligenceResponse;
14
+ /**
15
+ * Build the cross-framework routes panel response.
16
+ *
17
+ * Reads the framework store. For each entity with `subtype: 'route'`
18
+ * (or `api-route`), emits a row with `framework`, `method`, `path`,
19
+ * `handler`, and `file`. Sorted alphabetically by (framework, method,
20
+ * path).
21
+ */
22
+ export declare function buildDashboardRoutes(projectRoot: string): IDashboardRoutesResponse;
23
+ /**
24
+ * Build the Migrations panel response.
25
+ *
26
+ * Reads every `.sharkcraft/migrations/*.state.json` (written by
27
+ * `@shrkcrft/migrate` after each step), shapes each into a dashboard
28
+ * row, and stamps `resumePoint` so the UI can highlight where a
29
+ * partially-failed migration would pick up.
30
+ */
31
+ export declare function buildDashboardMigrations(projectRoot: string): IDashboardMigrationsResponse;
32
+ export declare function buildDashboardQualityGates(projectRoot: string): IDashboardQualityGatesResponse;
33
+ //# sourceMappingURL=code-intelligence-data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-intelligence-data.d.ts","sourceRoot":"","sources":["../../src/dashboard/code-intelligence-data.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,kCAAkC,EAElC,4BAA4B,EAE5B,8BAA8B,EAC9B,wBAAwB,EAEzB,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAAC,WAAW,EAAE,MAAM,GAAG,kCAAkC,CAuCtG;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,wBAAwB,CAyClF;AA0ED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,4BAA4B,CAuE1F;AAaD,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,8BAA8B,CAgD9F"}