@shrkcrft/cli 0.1.0-alpha.22 → 0.1.0-alpha.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/command-registry.d.ts +9 -0
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +15 -0
- package/dist/commands/ai-status.command.d.ts.map +1 -1
- package/dist/commands/ai-status.command.js +10 -0
- package/dist/commands/apply.command.d.ts.map +1 -1
- package/dist/commands/apply.command.js +9 -2
- package/dist/commands/ask.command.d.ts.map +1 -1
- package/dist/commands/ask.command.js +2 -1
- package/dist/commands/changes.command.d.ts.map +1 -1
- package/dist/commands/changes.command.js +14 -4
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +139 -7
- package/dist/commands/command-catalog.d.ts +11 -0
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +291 -0
- package/dist/commands/commands.command.d.ts +15 -0
- package/dist/commands/commands.command.d.ts.map +1 -1
- package/dist/commands/commands.command.js +162 -3
- package/dist/commands/compress.command.d.ts.map +1 -1
- package/dist/commands/compress.command.js +39 -4
- package/dist/commands/context.command.d.ts.map +1 -1
- package/dist/commands/context.command.js +3 -1
- package/dist/commands/daily.commands.d.ts.map +1 -1
- package/dist/commands/daily.commands.js +48 -5
- package/dist/commands/diff-check.command.d.ts.map +1 -1
- package/dist/commands/diff-check.command.js +6 -2
- package/dist/commands/feedback.command.d.ts.map +1 -1
- package/dist/commands/feedback.command.js +4 -0
- package/dist/commands/finish.command.d.ts +3 -0
- package/dist/commands/finish.command.d.ts.map +1 -0
- package/dist/commands/finish.command.js +70 -0
- package/dist/commands/framework.command.d.ts.map +1 -1
- package/dist/commands/framework.command.js +20 -3
- package/dist/commands/gate.command.d.ts.map +1 -1
- package/dist/commands/gate.command.js +98 -13
- package/dist/commands/graph-code-subverbs.d.ts.map +1 -1
- package/dist/commands/graph-code-subverbs.js +215 -81
- package/dist/commands/graph.command.d.ts.map +1 -1
- package/dist/commands/graph.command.js +6 -0
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +20 -2
- package/dist/commands/impact.command.d.ts.map +1 -1
- package/dist/commands/impact.command.js +86 -1
- package/dist/commands/knowledge.command.d.ts.map +1 -1
- package/dist/commands/knowledge.command.js +21 -1
- package/dist/commands/onboard.command.d.ts.map +1 -1
- package/dist/commands/onboard.command.js +11 -2
- package/dist/commands/orchestrate.command.d.ts.map +1 -1
- package/dist/commands/orchestrate.command.js +6 -1
- package/dist/commands/pack-author.command.d.ts.map +1 -1
- package/dist/commands/pack-author.command.js +13 -1
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +95 -17
- package/dist/commands/paths.command.d.ts.map +1 -1
- package/dist/commands/paths.command.js +8 -1
- package/dist/commands/pipelines.command.d.ts.map +1 -1
- package/dist/commands/pipelines.command.js +2 -1
- package/dist/commands/plan-context.command.d.ts.map +1 -1
- package/dist/commands/plan-context.command.js +6 -3
- package/dist/commands/plan-simulate.command.js +1 -1
- package/dist/commands/policy-lint.command.d.ts.map +1 -1
- package/dist/commands/policy-lint.command.js +20 -7
- package/dist/commands/recommend.command.d.ts.map +1 -1
- package/dist/commands/recommend.command.js +10 -2
- package/dist/commands/registry.command.d.ts.map +1 -1
- package/dist/commands/registry.command.js +117 -9
- package/dist/commands/report.command.js +1 -1
- package/dist/commands/reuse.command.d.ts.map +1 -1
- package/dist/commands/reuse.command.js +17 -5
- package/dist/commands/review.command.d.ts.map +1 -1
- package/dist/commands/review.command.js +20 -2
- package/dist/commands/rule-graph-subverbs.d.ts.map +1 -1
- package/dist/commands/rule-graph-subverbs.js +31 -4
- package/dist/commands/search-structural.command.d.ts.map +1 -1
- package/dist/commands/search-structural.command.js +2 -2
- package/dist/commands/search.command.d.ts.map +1 -1
- package/dist/commands/search.command.js +19 -1
- package/dist/commands/simulate.command.d.ts.map +1 -1
- package/dist/commands/simulate.command.js +6 -1
- package/dist/commands/smart-context.command.d.ts.map +1 -1
- package/dist/commands/smart-context.command.js +101 -41
- package/dist/commands/spec.command.d.ts.map +1 -1
- package/dist/commands/spec.command.js +73 -13
- package/dist/commands/task-context.command.d.ts.map +1 -1
- package/dist/commands/task-context.command.js +26 -2
- package/dist/commands/test.command.d.ts.map +1 -1
- package/dist/commands/test.command.js +17 -0
- package/dist/commands/trace.command.d.ts.map +1 -1
- package/dist/commands/trace.command.js +87 -4
- package/dist/commands/wiring.command.d.ts +12 -0
- package/dist/commands/wiring.command.d.ts.map +1 -0
- package/dist/commands/wiring.command.js +384 -0
- package/dist/diff/collect-changed-paths.d.ts +5 -3
- package/dist/diff/collect-changed-paths.d.ts.map +1 -1
- package/dist/diff/collect-changed-paths.js +73 -36
- package/dist/diff/deleted-orphans.d.ts +42 -0
- package/dist/diff/deleted-orphans.d.ts.map +1 -0
- package/dist/diff/deleted-orphans.js +46 -0
- package/dist/finish/run-finish.d.ts +62 -0
- package/dist/finish/run-finish.d.ts.map +1 -0
- package/dist/finish/run-finish.js +239 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +19 -1
- package/dist/status/freshness.d.ts +30 -0
- package/dist/status/freshness.d.ts.map +1 -0
- package/dist/status/freshness.js +81 -0
- package/package.json +33 -33
|
@@ -114,10 +114,18 @@ export const recommendCommand = {
|
|
|
114
114
|
}));
|
|
115
115
|
const promotedSet = new Set(promoted.map((p) => p.command));
|
|
116
116
|
const isGenericDefault = (c) => /^(bun run )?shrk (review|report|impact)\b/i.test(c);
|
|
117
|
+
// The recommender (inspector) already arbitrates the keyword recipe
|
|
118
|
+
// against the shared ranker and may have promoted a `shrk gen <template>`
|
|
119
|
+
// / `shrk task` headline (its `why` starts with "Ranker matched"). That
|
|
120
|
+
// ranker-confirmed scaffold is the engine's corrected route — keep it
|
|
121
|
+
// ahead of even the routing-hint promotion so the headline survives.
|
|
122
|
+
const isRankerPromoted = (r) => /^Ranker matched /.test(r.why);
|
|
117
123
|
const existing = report.recommendations;
|
|
118
|
-
const
|
|
119
|
-
const
|
|
124
|
+
const keptRankerPromoted = existing.filter((r) => !promotedSet.has(r.command) && isRankerPromoted(r));
|
|
125
|
+
const keptNonGeneric = existing.filter((r) => !promotedSet.has(r.command) && !isRankerPromoted(r) && !isGenericDefault(r.command));
|
|
126
|
+
const keptGeneric = existing.filter((r) => !promotedSet.has(r.command) && !isRankerPromoted(r) && isGenericDefault(r.command));
|
|
120
127
|
report.recommendations = [
|
|
128
|
+
...keptRankerPromoted,
|
|
121
129
|
...promoted,
|
|
122
130
|
...keptNonGeneric,
|
|
123
131
|
...keptGeneric,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.command.d.ts","sourceRoot":"","sources":["../../src/commands/registry.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.command.d.ts","sourceRoot":"","sources":["../../src/commands/registry.command.ts"],"names":[],"mappings":"AAwBA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAGhC,eAAO,MAAM,wBAAwB,EAAE,eAetC,CAAC;AAsGF,eAAO,MAAM,eAAe,EAAE,eAuB7B,CAAC"}
|
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `shrk registry` commands.
|
|
3
3
|
*
|
|
4
|
-
* shrk registry lifecycle [--json]
|
|
4
|
+
* shrk registry lifecycle [--json] # register/remove symmetry
|
|
5
|
+
* shrk registry <name> list [--json] # every declared id
|
|
6
|
+
* shrk registry <name> exists <id> [--json] # is the id taken? (exit 1 if not)
|
|
7
|
+
* shrk registry <name> where <id> [--json] # declaration (+ consumer) sites
|
|
8
|
+
*
|
|
9
|
+
* `<name>` resolves a `registries[]` declaration in sharkcraft.config.ts — one
|
|
10
|
+
* deterministic multi-root scan that answers "is this id taken / where is it"
|
|
11
|
+
* without an agent re-running a fragile grep.
|
|
5
12
|
*/
|
|
6
|
-
import { buildRegistryLifecycleReport, renderRegistryLifecycleReportText, } from '@shrkcrft/inspector';
|
|
7
|
-
import {
|
|
13
|
+
import { buildRegistryLifecycleReport, renderRegistryLifecycleReportText, resolveProjectConfig, } from '@shrkcrft/inspector';
|
|
14
|
+
import { scanRegistry, registryExists, registryWhere, } from '@shrkcrft/boundaries';
|
|
15
|
+
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
8
16
|
import { asJson } from "../output/format-output.js";
|
|
9
17
|
export const registryLifecycleCommand = {
|
|
10
18
|
name: 'lifecycle',
|
|
11
|
-
description: 'Scan the workspace for register
|
|
12
|
-
usage: 'shrk registry lifecycle [--json]',
|
|
19
|
+
description: 'Scan the workspace for register/remove symmetry. Read-only.',
|
|
20
|
+
usage: 'shrk registry lifecycle [--scope <dir>] [--json]',
|
|
13
21
|
async run(args) {
|
|
14
22
|
const cwd = resolveCwd(args);
|
|
15
|
-
const
|
|
23
|
+
const scope = flagString(args, 'scope');
|
|
24
|
+
const report = buildRegistryLifecycleReport({ projectRoot: cwd, ...(scope ? { scope } : {}) });
|
|
16
25
|
if (flagBool(args, 'json')) {
|
|
17
26
|
process.stdout.write(asJson(report) + '\n');
|
|
18
27
|
return report.missingRemovers.length === 0 ? 0 : 1;
|
|
@@ -21,17 +30,116 @@ export const registryLifecycleCommand = {
|
|
|
21
30
|
return report.missingRemovers.length === 0 ? 0 : 1;
|
|
22
31
|
},
|
|
23
32
|
};
|
|
33
|
+
async function loadRegistries(cwd) {
|
|
34
|
+
const loaded = await resolveProjectConfig(cwd);
|
|
35
|
+
if (!loaded.ok)
|
|
36
|
+
return { ok: false, message: loaded.error.message };
|
|
37
|
+
return {
|
|
38
|
+
ok: true,
|
|
39
|
+
registries: loaded.value.config.registries ?? [],
|
|
40
|
+
planeDiagnostics: loaded.value.planeDiagnostics,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function findRegistry(registries, name) {
|
|
44
|
+
return registries.find((r) => r.name === name);
|
|
45
|
+
}
|
|
46
|
+
/** Run a `list | exists | where` query against a declared registry. */
|
|
47
|
+
async function runRegistryInventory(args, name) {
|
|
48
|
+
const cwd = resolveCwd(args);
|
|
49
|
+
const json = flagBool(args, 'json');
|
|
50
|
+
const action = args.positional[1];
|
|
51
|
+
const id = args.positional[2];
|
|
52
|
+
const loaded = await loadRegistries(cwd);
|
|
53
|
+
if (!loaded.ok) {
|
|
54
|
+
if (json)
|
|
55
|
+
process.stdout.write(asJson({ error: loaded.message }) + '\n');
|
|
56
|
+
else
|
|
57
|
+
process.stderr.write(`Could not load config: ${loaded.message}\n Run \`shrk doctor\` for details.\n`);
|
|
58
|
+
return 1;
|
|
59
|
+
}
|
|
60
|
+
const decl = findRegistry(loaded.registries, name);
|
|
61
|
+
if (!decl) {
|
|
62
|
+
const names = loaded.registries.map((r) => r.name);
|
|
63
|
+
const avail = names.length > 0 ? `Declared registries: ${names.join(', ')}.` : 'No registries declared in sharkcraft.config.ts `registries[]`.';
|
|
64
|
+
if (json)
|
|
65
|
+
process.stdout.write(asJson({ error: `unknown registry "${name}"`, available: names }) + '\n');
|
|
66
|
+
else
|
|
67
|
+
process.stderr.write(`No registry named "${name}". ${avail}\n`);
|
|
68
|
+
return 2;
|
|
69
|
+
}
|
|
70
|
+
const inventory = scanRegistry(cwd, decl);
|
|
71
|
+
if (action === 'list' || action === undefined) {
|
|
72
|
+
// Fold pack-plane merge notes (missing/invalid pack registry files, dropped
|
|
73
|
+
// collisions) into the inventory's own scan diagnostics.
|
|
74
|
+
const diagnostics = [...inventory.diagnostics, ...loaded.planeDiagnostics];
|
|
75
|
+
if (json) {
|
|
76
|
+
process.stdout.write(asJson({ name: inventory.name, count: inventory.entries.length, ids: inventory.entries.map((e) => e.id), diagnostics }) + '\n');
|
|
77
|
+
return 0;
|
|
78
|
+
}
|
|
79
|
+
process.stdout.write(`Registry "${inventory.name}"${inventory.description ? ' — ' + inventory.description : ''}\n`);
|
|
80
|
+
process.stdout.write(` ${inventory.entries.length} id(s)\n`);
|
|
81
|
+
for (const e of inventory.entries) {
|
|
82
|
+
process.stdout.write(` • ${e.id} (${e.sites.length} site${e.sites.length === 1 ? '' : 's'})\n`);
|
|
83
|
+
}
|
|
84
|
+
for (const d of diagnostics)
|
|
85
|
+
process.stdout.write(` ! ${d}\n`);
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
if (action === 'exists') {
|
|
89
|
+
if (!id) {
|
|
90
|
+
process.stderr.write(`Usage: shrk registry ${name} exists <id>\n`);
|
|
91
|
+
return 2;
|
|
92
|
+
}
|
|
93
|
+
const exists = registryExists(inventory, id);
|
|
94
|
+
if (json)
|
|
95
|
+
process.stdout.write(asJson({ name: inventory.name, id, exists }) + '\n');
|
|
96
|
+
else
|
|
97
|
+
process.stdout.write(`${exists ? 'yes' : 'no'} — "${id}" is ${exists ? 'declared' : 'NOT declared'} in registry "${inventory.name}".\n`);
|
|
98
|
+
return exists ? 0 : 1;
|
|
99
|
+
}
|
|
100
|
+
if (action === 'where') {
|
|
101
|
+
if (!id) {
|
|
102
|
+
process.stderr.write(`Usage: shrk registry ${name} where <id>\n`);
|
|
103
|
+
return 2;
|
|
104
|
+
}
|
|
105
|
+
const entry = registryWhere(inventory, id);
|
|
106
|
+
if (json) {
|
|
107
|
+
process.stdout.write(asJson({ name: inventory.name, id, found: entry !== undefined, entry: entry ?? null }) + '\n');
|
|
108
|
+
return entry ? 0 : 1;
|
|
109
|
+
}
|
|
110
|
+
if (!entry) {
|
|
111
|
+
process.stdout.write(`"${id}" is not declared in registry "${inventory.name}".\n`);
|
|
112
|
+
return 1;
|
|
113
|
+
}
|
|
114
|
+
process.stdout.write(`"${id}" in registry "${inventory.name}":\n`);
|
|
115
|
+
for (const s of entry.sites)
|
|
116
|
+
process.stdout.write(` declared ${s.file}:${s.line}\n`);
|
|
117
|
+
for (const s of entry.consumerSites ?? [])
|
|
118
|
+
process.stdout.write(` consumed ${s.file}:${s.line}\n`);
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
process.stderr.write(`Unknown action "${action}". Usage: shrk registry ${name} list | exists <id> | where <id>\n`);
|
|
122
|
+
return 2;
|
|
123
|
+
}
|
|
24
124
|
export const registryCommand = {
|
|
25
125
|
name: 'registry',
|
|
26
|
-
description: 'Registry inspections
|
|
27
|
-
usage: 'shrk registry lifecycle',
|
|
126
|
+
description: 'Registry inspections: lifecycle symmetry + declared-registry inventory. Read-only.',
|
|
127
|
+
usage: 'shrk registry lifecycle | <name> list | <name> exists <id> | <name> where <id>',
|
|
28
128
|
async run(args) {
|
|
29
129
|
const sub = args.positional[0];
|
|
30
130
|
if (sub === 'lifecycle') {
|
|
31
131
|
args.positional = args.positional.slice(1);
|
|
32
132
|
return registryLifecycleCommand.run(args);
|
|
33
133
|
}
|
|
34
|
-
|
|
134
|
+
if (sub !== undefined && sub.length > 0) {
|
|
135
|
+
// `<name> list | exists <id> | where <id>` — sub is the registry name.
|
|
136
|
+
return runRegistryInventory(args, sub);
|
|
137
|
+
}
|
|
138
|
+
const cwd = resolveCwd(args);
|
|
139
|
+
const loaded = await loadRegistries(cwd);
|
|
140
|
+
const names = loaded.ok ? loaded.registries.map((r) => r.name) : [];
|
|
141
|
+
process.stderr.write('Usage: shrk registry lifecycle | <name> list | <name> exists <id> | <name> where <id>\n' +
|
|
142
|
+
(names.length > 0 ? `Declared registries: ${names.join(', ')}.\n` : 'No registries declared (sharkcraft.config.ts `registries[]`).\n'));
|
|
35
143
|
return 2;
|
|
36
144
|
},
|
|
37
145
|
};
|
|
@@ -8,7 +8,7 @@ const VALID_FORMATS = new Set(['text', 'markdown', 'html', 'json']);
|
|
|
8
8
|
export const reportCommand = {
|
|
9
9
|
name: 'report',
|
|
10
10
|
description: 'Render runtime reports in text / markdown / html / json. Subcommands: adoption / session / quality / safety / review / coverage / drift / graph.',
|
|
11
|
-
usage: 'shrk report <adoption|session <id>|quality|safety|review <packet.json>|coverage|drift|graph> [--format text|markdown|html|json] [--output <path>] [--collapse-long-sections] [--max-items N] [--
|
|
11
|
+
usage: 'shrk report <adoption|session <id>|quality|safety|review <packet.json>|coverage|drift|graph> [--format text|markdown|html|json] [--output <path>] [--collapse-long-sections] [--max-items N] [--json]',
|
|
12
12
|
async run(args) {
|
|
13
13
|
const sub = args.positional[0];
|
|
14
14
|
const sliced = { ...args, positional: args.positional.slice(1) };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reuse.command.d.ts","sourceRoot":"","sources":["../../src/commands/reuse.command.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA4DhC,eAAO,MAAM,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"reuse.command.d.ts","sourceRoot":"","sources":["../../src/commands/reuse.command.ts"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA4DhC,eAAO,MAAM,YAAY,EAAE,eAqK1B,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { GraphStore, GraphQueryApi } from '@shrkcrft/graph';
|
|
2
|
-
import {
|
|
2
|
+
import { resolveProjectConfig } from '@shrkcrft/inspector';
|
|
3
3
|
import { flagBool, flagNumber, resolveCwd, } from "../command-registry.js";
|
|
4
4
|
import { asJson, header } from "../output/format-output.js";
|
|
5
5
|
const STOP = new Set([
|
|
@@ -49,7 +49,7 @@ export const reuseCommand = {
|
|
|
49
49
|
process.stderr.write('Usage: shrk reuse "<what I want to build>" [--limit N] [--json]\n');
|
|
50
50
|
return 2;
|
|
51
51
|
}
|
|
52
|
-
const loaded = await
|
|
52
|
+
const loaded = await resolveProjectConfig(cwd);
|
|
53
53
|
if (!loaded.ok) {
|
|
54
54
|
const msg = loaded.error.message;
|
|
55
55
|
if (wantJson) {
|
|
@@ -61,14 +61,24 @@ export const reuseCommand = {
|
|
|
61
61
|
return 1;
|
|
62
62
|
}
|
|
63
63
|
const primitives = loaded.value.config.reusePrimitives ?? [];
|
|
64
|
+
const planeDiagnostics = loaded.value.planeDiagnostics;
|
|
65
|
+
// reuse has no pre-existing diagnostics surface; expose pack-plane merge
|
|
66
|
+
// notes (missing/invalid pack primitive files, dropped collisions) so a
|
|
67
|
+
// pack contribution that failed to load isn't silently invisible.
|
|
68
|
+
const planeJson = planeDiagnostics.length > 0 ? { planeDiagnostics } : {};
|
|
69
|
+
const writePlaneNotes = () => {
|
|
70
|
+
for (const d of planeDiagnostics)
|
|
71
|
+
process.stdout.write(` ! ${d}\n`);
|
|
72
|
+
};
|
|
64
73
|
if (primitives.length === 0) {
|
|
65
74
|
if (wantJson) {
|
|
66
|
-
process.stdout.write(asJson({ schema: 'sharkcraft.reuse/v1', intent, results: [] }) + '\n');
|
|
75
|
+
process.stdout.write(asJson({ schema: 'sharkcraft.reuse/v1', intent, results: [], ...planeJson }) + '\n');
|
|
67
76
|
return 0;
|
|
68
77
|
}
|
|
69
78
|
process.stdout.write(header(`Reuse: "${intent}"`));
|
|
70
79
|
process.stdout.write(' No reuse primitives configured. Declare `reusePrimitives[]` in sharkcraft.config.ts\n' +
|
|
71
80
|
' to map roles/intents to canonical symbols (see docs/reuse.md).\n');
|
|
81
|
+
writePlaneNotes();
|
|
72
82
|
return 0;
|
|
73
83
|
}
|
|
74
84
|
const tokens = tokenize(intent);
|
|
@@ -82,13 +92,14 @@ export const reuseCommand = {
|
|
|
82
92
|
if (ranked.length === 0) {
|
|
83
93
|
const roles = [...new Set(primitives.flatMap((p) => p.roles))].sort();
|
|
84
94
|
if (wantJson) {
|
|
85
|
-
process.stdout.write(asJson({ schema: 'sharkcraft.reuse/v1', intent, results: [], availableRoles: roles }) + '\n');
|
|
95
|
+
process.stdout.write(asJson({ schema: 'sharkcraft.reuse/v1', intent, results: [], availableRoles: roles, ...planeJson }) + '\n');
|
|
86
96
|
return 0;
|
|
87
97
|
}
|
|
88
98
|
process.stdout.write(header(`Reuse: "${intent}"`));
|
|
89
99
|
process.stdout.write(' No primitive matched. Available roles:\n');
|
|
90
100
|
for (const r of roles.slice(0, 40))
|
|
91
101
|
process.stdout.write(` • ${r}\n`);
|
|
102
|
+
writePlaneNotes();
|
|
92
103
|
return 0;
|
|
93
104
|
}
|
|
94
105
|
const results = ranked.map(({ p, score }) => {
|
|
@@ -149,10 +160,11 @@ export const reuseCommand = {
|
|
|
149
160
|
return r;
|
|
150
161
|
});
|
|
151
162
|
if (wantJson) {
|
|
152
|
-
process.stdout.write(asJson({ schema: 'sharkcraft.reuse/v1', intent, graphIndexed: !!api, results }) + '\n');
|
|
163
|
+
process.stdout.write(asJson({ schema: 'sharkcraft.reuse/v1', intent, graphIndexed: !!api, results, ...planeJson }) + '\n');
|
|
153
164
|
return 0;
|
|
154
165
|
}
|
|
155
166
|
process.stdout.write(header(`Reuse: "${intent}"`));
|
|
167
|
+
writePlaneNotes();
|
|
156
168
|
if (!api) {
|
|
157
169
|
process.stdout.write(' (code graph missing — import path/siblings/consumers limited; run `shrk graph index`)\n');
|
|
158
170
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review.command.d.ts","sourceRoot":"","sources":["../../src/commands/review.command.ts"],"names":[],"mappings":"AAgBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA6GhC,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"review.command.d.ts","sourceRoot":"","sources":["../../src/commands/review.command.ts"],"names":[],"mappings":"AAgBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AA6GhC,eAAO,MAAM,aAAa,EAAE,eAiG3B,CAAC"}
|
|
@@ -77,7 +77,20 @@ function scaffoldOptionsFromArgs(args) {
|
|
|
77
77
|
export const reviewCommand = {
|
|
78
78
|
name: 'review',
|
|
79
79
|
description: 'Build a PR-review packet: changed files (via git), affected path conventions, relevant rules/templates/pipelines, boundary violations on those files, missing-test heuristic, verification commands. Also: `shrk review scaffold github-action` prints a workflow template with optional `--with-boundaries / --with-coverage / --with-drift / --artifact-only / --comment-placeholder` flags. `shrk review render-comment <packet.json>` renders a Markdown PR comment from a saved packet.',
|
|
80
|
-
usage: 'shrk [--cwd <dir>] review [--since <ref>] [--staged] [--
|
|
80
|
+
usage: 'shrk [--cwd <dir>] review [files... | --files a,b] [--since <ref>] [--staged] [--no-untracked] [--json] | shrk review scaffold github-action [...] | shrk review render-comment <packet.json> [--output <file>]',
|
|
81
|
+
booleanFlags: new Set([
|
|
82
|
+
'json',
|
|
83
|
+
'staged',
|
|
84
|
+
'untracked',
|
|
85
|
+
'no-untracked',
|
|
86
|
+
'v2',
|
|
87
|
+
'v3',
|
|
88
|
+
'with-boundaries',
|
|
89
|
+
'with-coverage',
|
|
90
|
+
'with-drift',
|
|
91
|
+
'artifact-only',
|
|
92
|
+
'comment-placeholder',
|
|
93
|
+
]),
|
|
81
94
|
async run(args) {
|
|
82
95
|
if (args.positional[0] === 'scaffold') {
|
|
83
96
|
const which = args.positional[1] ?? 'github-action';
|
|
@@ -97,11 +110,16 @@ export const reviewCommand = {
|
|
|
97
110
|
}
|
|
98
111
|
const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
|
|
99
112
|
const since = flagString(args, 'since');
|
|
100
|
-
|
|
113
|
+
// Accept files via `--files a,b` OR as bare positional args
|
|
114
|
+
// (`shrk review a.ts b.ts`). Positionals were previously dropped silently,
|
|
115
|
+
// yielding a confident "0 changed files" with exit 0.
|
|
116
|
+
const filesFlag = flagList(args, 'files');
|
|
117
|
+
const files = filesFlag.length ? filesFlag : args.positional;
|
|
101
118
|
const packet = buildReviewPacket(inspection, {
|
|
102
119
|
...(since ? { since } : {}),
|
|
103
120
|
...(flagBool(args, 'staged') ? { staged: true } : {}),
|
|
104
121
|
...(files.length ? { files } : {}),
|
|
122
|
+
...(flagBool(args, 'no-untracked') ? { untracked: false } : {}),
|
|
105
123
|
});
|
|
106
124
|
if (flagBool(args, 'json')) {
|
|
107
125
|
process.stdout.write(asJson(packet) + '\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rule-graph-subverbs.d.ts","sourceRoot":"","sources":["../../src/commands/rule-graph-subverbs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rule-graph-subverbs.d.ts","sourceRoot":"","sources":["../../src/commands/rule-graph-subverbs.ts"],"names":[],"mappings":"AASA,OAAO,EAAwB,KAAK,eAAe,EAAmB,MAAM,wBAAwB,CAAC;AAGrG,eAAO,MAAM,gBAAgB,EAAE,eAc9B,CAAC"}
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* because the verbs operate on a separate `.sharkcraft/bridge/` store
|
|
6
6
|
* and don't conceptually belong under `shrk graph`.
|
|
7
7
|
*/
|
|
8
|
-
import { buildBridge, RuleGraphQueryApi } from '@shrkcrft/rule-graph';
|
|
8
|
+
import { buildBridge, BridgeStore, RuleGraphQueryApi } from '@shrkcrft/rule-graph';
|
|
9
|
+
import { detectGraphFreshness } from '@shrkcrft/graph';
|
|
9
10
|
import { flagBool, resolveCwd } from "../command-registry.js";
|
|
10
11
|
import { asJson, header, kv } from "../output/format-output.js";
|
|
11
12
|
export const ruleGraphCommand = {
|
|
@@ -54,13 +55,39 @@ async function runStatus(args) {
|
|
|
54
55
|
return 1;
|
|
55
56
|
}
|
|
56
57
|
const api = RuleGraphQueryApi.fromStores(cwd);
|
|
57
|
-
//
|
|
58
|
+
// The bridge maps code-graph files → asset registries, so it is stale once
|
|
59
|
+
// the underlying code graph has drifted. Reuse the already-available graph
|
|
60
|
+
// freshness signal (the same one `graph status` reports) rather than a
|
|
61
|
+
// hardcoded 'fresh'. `lastBuiltAt` comes from the bridge manifest.
|
|
62
|
+
let lastBuiltAt = null;
|
|
63
|
+
try {
|
|
64
|
+
lastBuiltAt = new BridgeStore(cwd).loadSnapshot().manifest.lastBuiltAt;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
lastBuiltAt = null;
|
|
68
|
+
}
|
|
69
|
+
const fresh = detectGraphFreshness(cwd);
|
|
70
|
+
const behind = fresh.modified.length + fresh.added.length + fresh.deleted.length;
|
|
71
|
+
const state = behind > 0 ? 'stale' : 'fresh';
|
|
58
72
|
if (wantJson) {
|
|
59
|
-
process.stdout.write(asJson({
|
|
73
|
+
process.stdout.write(asJson({
|
|
74
|
+
ok: true,
|
|
75
|
+
state,
|
|
76
|
+
lastBuiltAt,
|
|
77
|
+
modifiedSinceIndex: fresh.modified.length,
|
|
78
|
+
newSinceIndex: fresh.added.length,
|
|
79
|
+
deletedSinceIndex: fresh.deleted.length,
|
|
80
|
+
...(state === 'stale' ? { nextCommand: 'shrk rule-graph index' } : {}),
|
|
81
|
+
}) + '\n');
|
|
60
82
|
return 0;
|
|
61
83
|
}
|
|
62
84
|
process.stdout.write(header('Rule-graph status'));
|
|
63
|
-
|
|
85
|
+
if (lastBuiltAt)
|
|
86
|
+
process.stdout.write(kv('last built', lastBuiltAt) + '\n');
|
|
87
|
+
process.stdout.write(kv('state', state) + '\n');
|
|
88
|
+
if (state === 'stale') {
|
|
89
|
+
process.stdout.write(`! stale — ${fresh.modified.length} modified, ${fresh.added.length} new, ${fresh.deleted.length} deleted in the code graph since the bridge was built; re-run \`shrk rule-graph index\`\n`);
|
|
90
|
+
}
|
|
64
91
|
void api;
|
|
65
92
|
return 0;
|
|
66
93
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-structural.command.d.ts","sourceRoot":"","sources":["../../src/commands/search-structural.command.ts"],"names":[],"mappings":"AAgBA,OAAO,
|
|
1
|
+
{"version":3,"file":"search-structural.command.d.ts","sourceRoot":"","sources":["../../src/commands/search-structural.command.ts"],"names":[],"mappings":"AAgBA,OAAO,EAKL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAGhC;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,uBAAuB,EAAE,eAkErC,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from 'node:fs';
|
|
2
2
|
import * as nodePath from 'node:path';
|
|
3
3
|
import { applyRewritePlan, PatternRegistryStore, planRewrite, runSearch, signRewritePlan, STARTER_PATTERNS, verifySignedRewritePlan, } from '@shrkcrft/structural-search';
|
|
4
|
-
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
4
|
+
import { flagBool, flagPositiveInt, flagString, resolveCwd, } from "../command-registry.js";
|
|
5
5
|
import { asJson, header, kv } from "../output/format-output.js";
|
|
6
6
|
/**
|
|
7
7
|
* `shrk search structural` — declarative AST pattern matching with
|
|
@@ -49,7 +49,7 @@ export const searchStructuralCommand = {
|
|
|
49
49
|
process.stderr.write(`Pattern parse error: ${e.message}\n`);
|
|
50
50
|
return 2;
|
|
51
51
|
}
|
|
52
|
-
const limit =
|
|
52
|
+
const limit = flagPositiveInt(args, 'limit', 200);
|
|
53
53
|
// Rewrite path?
|
|
54
54
|
const recipeInline = flagString(args, 'rewrite');
|
|
55
55
|
const recipeFile = flagString(args, 'rewrite-file');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.command.d.ts","sourceRoot":"","sources":["../../src/commands/search.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search.command.d.ts","sourceRoot":"","sources":["../../src/commands/search.command.ts"],"names":[],"mappings":"AAiBA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAkChC,eAAO,MAAM,aAAa,EAAE,eAsH3B,CAAC;AAEF,eAAO,MAAM,uBAAuB,EAAE,eA+FrC,CAAC;AAwEF;;;;;;GAMG;AACH,eAAO,MAAM,2BAA2B,EAAE,eASzC,CAAC"}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import { buildSearchIndex, entrypointBanner, explainSearchTuning, inspectSharkcraft, loadConstructs, loadPlaybooks, loadSearchTuning, renderSearchText, renderTuningExplainHtml, renderTuningExplainMarkdown, searchIndex, SearchKind, SearchSource, } from '@shrkcrft/inspector';
|
|
1
|
+
import { buildSearchIndex, entrypointBanner, explainSearchTuning, inspectSharkcraft, loadConstructs, loadPlaybooks, loadSearchTuning, renderSearchText, renderTuningExplainHtml, renderTuningExplainMarkdown, searchIndex, SearchKind, SearchResultKind, SearchSource, } from '@shrkcrft/inspector';
|
|
2
2
|
import { flagBool, flagNumber, flagString, flagList, resolveCwd, } from "../command-registry.js";
|
|
3
3
|
import { asJson } from "../output/format-output.js";
|
|
4
4
|
const VALID_KINDS = new Set(Object.values(SearchKind));
|
|
5
5
|
const VALID_SOURCES = new Set(Object.values(SearchSource));
|
|
6
|
+
// Universal-search (v2) filter vocabularies. `--kind` is one of the
|
|
7
|
+
// `SearchResultKind` enum values; `--source` is the local/pack origin the
|
|
8
|
+
// engine actually filters hits by (`makeHit` only ever emits these two). Both
|
|
9
|
+
// are validated up front so a typo'd value rejects loudly instead of silently
|
|
10
|
+
// filtering every hit out and returning an empty result with exit 0.
|
|
11
|
+
const VALID_RESULT_KINDS = Object.values(SearchResultKind);
|
|
12
|
+
const VALID_RESULT_SOURCES = ['local', 'pack'];
|
|
6
13
|
function parseKinds(args) {
|
|
7
14
|
const list = flagList(args, 'type').concat(flagList(args, 'kind'));
|
|
8
15
|
if (list.length === 0)
|
|
@@ -48,6 +55,17 @@ export const searchCommand = {
|
|
|
48
55
|
const { buildUniversalSearch, renderUniversalSearchText, renderUniversalSearchMarkdown, } = await import('@shrkcrft/inspector');
|
|
49
56
|
const kindFilter = flagString(args, 'kind');
|
|
50
57
|
const sourceFilter = flagString(args, 'source');
|
|
58
|
+
// Validate the filter vocabularies BEFORE building opts — universal-search
|
|
59
|
+
// silently drops every non-matching hit, so an unknown `--kind`/`--source`
|
|
60
|
+
// would otherwise return an empty result with exit 0.
|
|
61
|
+
if (kindFilter && !VALID_RESULT_KINDS.includes(kindFilter)) {
|
|
62
|
+
process.stderr.write(`Unknown --kind ${kindFilter}. Valid: ${VALID_RESULT_KINDS.join(', ')}\n`);
|
|
63
|
+
return 2;
|
|
64
|
+
}
|
|
65
|
+
if (sourceFilter && !VALID_RESULT_SOURCES.includes(sourceFilter)) {
|
|
66
|
+
process.stderr.write(`Unknown --source ${sourceFilter}. Valid: ${VALID_RESULT_SOURCES.join(', ')}\n`);
|
|
67
|
+
return 2;
|
|
68
|
+
}
|
|
51
69
|
const limit = flagNumber(args, 'limit');
|
|
52
70
|
const opts = {};
|
|
53
71
|
if (kindFilter)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simulate.command.d.ts","sourceRoot":"","sources":["../../src/commands/simulate.command.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"simulate.command.d.ts","sourceRoot":"","sources":["../../src/commands/simulate.command.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAKhC,eAAO,MAAM,eAAe,EAAE,eAyD7B,CAAC"}
|
|
@@ -3,10 +3,11 @@ import * as nodePath from 'node:path';
|
|
|
3
3
|
import { inspectSharkcraft, OrchestrationMode, renderWorkflowSimulationText, simulateWorkflow, } from '@shrkcrft/inspector';
|
|
4
4
|
import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
|
|
5
5
|
import { asJson } from "../output/format-output.js";
|
|
6
|
+
const VALID_SIMULATION_MODES = ['conservative', 'balanced', 'aggressive'];
|
|
6
7
|
export const simulateCommand = {
|
|
7
8
|
name: 'simulate',
|
|
8
9
|
description: 'Predict what a workflow would do without executing anything. Read-only. Optionally takes a playbook or pipeline id.',
|
|
9
|
-
usage: 'shrk simulate "<task>" [--playbook <id>] [--pipeline <id>] [--
|
|
10
|
+
usage: 'shrk simulate "<task>" [--playbook <id>] [--pipeline <id>] [--mode conservative|balanced|aggressive] [--json] [--output <file>]',
|
|
10
11
|
async run(args) {
|
|
11
12
|
const task = args.positional.join(' ').trim();
|
|
12
13
|
if (!task) {
|
|
@@ -18,6 +19,10 @@ export const simulateCommand = {
|
|
|
18
19
|
const playbookId = flagString(args, 'playbook');
|
|
19
20
|
const pipelineId = flagString(args, 'pipeline');
|
|
20
21
|
const modeRaw = (flagString(args, 'mode') ?? '').toLowerCase();
|
|
22
|
+
// Warn on a typo'd --mode rather than silently treating it as balanced.
|
|
23
|
+
if (modeRaw && !VALID_SIMULATION_MODES.includes(modeRaw)) {
|
|
24
|
+
process.stderr.write(`Unknown --mode ${modeRaw}. Valid: ${VALID_SIMULATION_MODES.join(', ')} (defaulting to balanced).\n`);
|
|
25
|
+
}
|
|
21
26
|
const mode = modeRaw === 'conservative'
|
|
22
27
|
? OrchestrationMode.Conservative
|
|
23
28
|
: modeRaw === 'aggressive'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smart-context.command.d.ts","sourceRoot":"","sources":["../../src/commands/smart-context.command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"smart-context.command.d.ts","sourceRoot":"","sources":["../../src/commands/smart-context.command.ts"],"names":[],"mappings":"AA2BA,OAAO,EAML,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAC;AAmFhC,eAAO,MAAM,mBAAmB,EAAE,eAmQjC,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,4BAA4B,EAAE,eAsF1C,CAAC;AAEF,sDAAsD;AACtD,eAAO,MAAM,uBAAuB,EAAE,eAwBrC,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,EAAE,eAkCrC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAmH/C,CAAC;AA2JF;;;;;;;GAOG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAoH/C,CAAC;AA2JF;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,EAAE,eAgG/C,CAAC;AAyPF,4EAA4E;AAC5E,eAAO,MAAM,kCAAkC,EAAE,eAuHhD,CAAC;AAMF,iFAAiF;AACjF,eAAO,MAAM,mCAAmC,EAAE,eAsCjD,CAAC;AAqJF,UAAU,eAAe;IACvB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,kFAAkF;IAClF,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,SAAS,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,CAAC,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAWzF"}
|