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