@shrkcrft/cli 0.1.0-alpha.8 → 0.1.0-alpha.9
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/README.md +1 -1
- package/dist/commands/boundaries.command.d.ts.map +1 -1
- package/dist/commands/boundaries.command.js +12 -0
- package/dist/commands/check.command.d.ts.map +1 -1
- package/dist/commands/check.command.js +30 -20
- package/dist/commands/command-catalog.d.ts +3 -7
- package/dist/commands/command-catalog.d.ts.map +1 -1
- package/dist/commands/command-catalog.js +47 -113
- package/dist/commands/commands.command.d.ts.map +1 -1
- package/dist/commands/commands.command.js +4 -4
- package/dist/commands/constructs.command.d.ts.map +1 -1
- package/dist/commands/constructs.command.js +22 -5
- package/dist/commands/doctor.command.d.ts.map +1 -1
- package/dist/commands/doctor.command.js +9 -42
- package/dist/commands/export.command.d.ts.map +1 -1
- package/dist/commands/export.command.js +3 -76
- package/dist/commands/help.command.d.ts +3 -4
- package/dist/commands/help.command.d.ts.map +1 -1
- package/dist/commands/help.command.js +21 -77
- package/dist/commands/helper.command.js +1 -1
- package/dist/commands/import.command.d.ts.map +1 -1
- package/dist/commands/import.command.js +5 -121
- package/dist/commands/init.command.d.ts.map +1 -1
- package/dist/commands/init.command.js +16 -184
- package/dist/commands/mcp.command.d.ts.map +1 -1
- package/dist/commands/mcp.command.js +131 -2
- package/dist/commands/onboard.command.d.ts.map +1 -1
- package/dist/commands/onboard.command.js +15 -3
- 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 +36 -5
- package/dist/commands/packs.command.d.ts.map +1 -1
- package/dist/commands/packs.command.js +17 -3
- package/dist/commands/plugin.command.d.ts +11 -0
- package/dist/commands/plugin.command.d.ts.map +1 -0
- package/dist/commands/plugin.command.js +394 -0
- package/dist/commands/profiles.command.js +4 -4
- package/dist/commands/release.command.js +13 -13
- package/dist/commands/review.command.d.ts.map +1 -1
- package/dist/commands/review.command.js +28 -2
- package/dist/commands/search.command.js +1 -1
- package/dist/commands/task-context.command.js +16 -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 +12 -139
- package/dist/init/init-templates.d.ts.map +1 -1
- package/dist/init/init-templates.js +113 -133
- package/dist/main.d.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +46 -117
- package/dist/output/failure-hints.d.ts +9 -1
- package/dist/output/failure-hints.d.ts.map +1 -1
- package/dist/output/failure-hints.js +8 -2
- package/dist/output/watch-loop.d.ts +1 -9
- package/dist/output/watch-loop.d.ts.map +1 -1
- package/dist/output/watch-loop.js +3 -13
- package/dist/schemas/json-schemas.d.ts +36 -36
- package/dist/schemas/json-schemas.js +36 -36
- package/dist/surface/about.d.ts.map +1 -1
- package/dist/surface/about.js +15 -37
- package/dist/surface/no-args-landing.d.ts.map +1 -1
- package/dist/surface/no-args-landing.js +13 -9
- package/dist/surface/surface-config-writer.d.ts.map +1 -1
- package/dist/surface/surface-config-writer.js +11 -23
- package/package.json +25 -26
- package/dist/commands/diff-check.command.d.ts +0 -30
- package/dist/commands/diff-check.command.d.ts.map +0 -1
- package/dist/commands/diff-check.command.js +0 -210
- package/dist/export/claude-commands-export.d.ts +0 -60
- package/dist/export/claude-commands-export.d.ts.map +0 -1
- package/dist/export/claude-commands-export.js +0 -276
- package/dist/init/paths-advisory.d.ts +0 -20
- package/dist/init/paths-advisory.d.ts.map +0 -1
- package/dist/init/paths-advisory.js +0 -88
package/dist/main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
2
|
import { CommandRegistry, extractGlobalCwd, parseArgs, } from "./command-registry.js";
|
|
3
3
|
import { initCommand } from "./commands/init.command.js";
|
|
4
4
|
import { inspectCommand } from "./commands/inspect.command.js";
|
|
@@ -20,7 +20,6 @@ import { presetsListCommand, presetsGetCommand, presetsExplainCommand, presetsRe
|
|
|
20
20
|
import { taskCommand } from "./commands/task.command.js";
|
|
21
21
|
import { preflightCommand } from "./commands/preflight.command.js";
|
|
22
22
|
import { checkCommand } from "./commands/check.command.js";
|
|
23
|
-
import { diffCheckCommand } from "./commands/diff-check.command.js";
|
|
24
23
|
import { driftCommand } from "./commands/drift.command.js";
|
|
25
24
|
import { graphCommand } from "./commands/graph.command.js";
|
|
26
25
|
import { coverageCommand } from "./commands/coverage.command.js";
|
|
@@ -57,6 +56,7 @@ import { biomeCommand } from "./commands/biome.command.js";
|
|
|
57
56
|
import { ideCommand } from "./commands/ide.command.js";
|
|
58
57
|
import { makeCommandsCommand } from "./commands/commands.command.js";
|
|
59
58
|
import { safetyCommand } from "./commands/safety.command.js";
|
|
59
|
+
import { pluginCommand } from "./commands/plugin.command.js";
|
|
60
60
|
import { profilesCommand } from "./commands/profiles.command.js";
|
|
61
61
|
import { auditProjectCouplingCommand } from "./commands/audit.command.js";
|
|
62
62
|
import { conventionsCommand } from "./commands/conventions.command.js";
|
|
@@ -120,6 +120,33 @@ import { buildSurfaceSummary, findCommandInSummary } from "./surface/surface-sum
|
|
|
120
120
|
import { makeSurfaceNotEnabledError, renderSurfaceNotEnabledText, SURFACE_NOT_ENABLED_EXIT_CODE, } from "./surface/not-enabled-error.js";
|
|
121
121
|
import { extractCommandPath, recordUsage, sanitizeFlagNames, } from "./usage/usage-log.js";
|
|
122
122
|
import { loadProjectConfig } from '@shrkcrft/config';
|
|
123
|
+
import { initTokenizer } from '@shrkcrft/context';
|
|
124
|
+
import { statSync } from 'node:fs';
|
|
125
|
+
import { resolve as resolvePath } from 'node:path';
|
|
126
|
+
function isUsableDirectory(path) {
|
|
127
|
+
try {
|
|
128
|
+
return statSync(path).isDirectory();
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
let tokenizerInitPromise = null;
|
|
135
|
+
/**
|
|
136
|
+
* Best-effort one-time upgrade from the estimator to gpt-tokenizer.
|
|
137
|
+
*
|
|
138
|
+
* The estimator is always active before this resolves, so commands that
|
|
139
|
+
* race the load still get a budget-safe (if slightly off) count. Subsequent
|
|
140
|
+
* `countTokens` calls get the real BPE count.
|
|
141
|
+
*/
|
|
142
|
+
async function ensureTokenizerReady() {
|
|
143
|
+
if (process.env.SHARKCRAFT_NO_REAL_TOKENIZER === '1')
|
|
144
|
+
return;
|
|
145
|
+
if (!tokenizerInitPromise) {
|
|
146
|
+
tokenizerInitPromise = initTokenizer().catch(() => false);
|
|
147
|
+
}
|
|
148
|
+
await tokenizerInitPromise;
|
|
149
|
+
}
|
|
123
150
|
export function buildRegistry() {
|
|
124
151
|
const registry = new CommandRegistry();
|
|
125
152
|
registry.register(initCommand);
|
|
@@ -162,7 +189,6 @@ export function buildRegistry() {
|
|
|
162
189
|
registry.register(taskCommand);
|
|
163
190
|
registry.register(explainCommand);
|
|
164
191
|
registry.register(checkCommand);
|
|
165
|
-
registry.register(diffCheckCommand);
|
|
166
192
|
// changed-only preflight orchestrator.
|
|
167
193
|
registry.register(preflightCommand);
|
|
168
194
|
registry.register(driftCommand);
|
|
@@ -193,6 +219,7 @@ export function buildRegistry() {
|
|
|
193
219
|
registry.register(eslintCommand);
|
|
194
220
|
registry.register(biomeCommand);
|
|
195
221
|
registry.register(ideCommand);
|
|
222
|
+
registry.register(pluginCommand);
|
|
196
223
|
registry.register(profilesCommand);
|
|
197
224
|
registry.registerSubcommand('audit', auditProjectCouplingCommand);
|
|
198
225
|
registry.register(conventionsCommand);
|
|
@@ -491,9 +518,15 @@ async function isUsageEnabled(cwd) {
|
|
|
491
518
|
}
|
|
492
519
|
}
|
|
493
520
|
async function runCliInner(argv) {
|
|
521
|
+
await ensureTokenizerReady();
|
|
494
522
|
const registry = buildRegistry();
|
|
495
523
|
// Pre-parse the global --cwd so it can appear anywhere (incl. before the command).
|
|
496
524
|
const { cwd: globalCwd, rest: cleanArgv } = extractGlobalCwd(argv);
|
|
525
|
+
if (globalCwd !== undefined && !isUsableDirectory(globalCwd)) {
|
|
526
|
+
process.stderr.write(`error: --cwd "${globalCwd}" is not an existing directory.\n` +
|
|
527
|
+
`Resolved to: ${resolvePath(globalCwd)}\n`);
|
|
528
|
+
return 2;
|
|
529
|
+
}
|
|
497
530
|
const [first] = cleanArgv;
|
|
498
531
|
// bare invocation lands on the curated tiered view.
|
|
499
532
|
if (!first) {
|
|
@@ -506,14 +539,7 @@ async function runCliInner(argv) {
|
|
|
506
539
|
return registry.get('help').run(parseArgs([], { globalCwd }));
|
|
507
540
|
}
|
|
508
541
|
if (first === '--full-help') {
|
|
509
|
-
|
|
510
|
-
// included them after `--full-help`.
|
|
511
|
-
const extra = [];
|
|
512
|
-
if (argv.includes('--all'))
|
|
513
|
-
extra.push('--all');
|
|
514
|
-
if (argv.includes('--verbose') || argv.includes('-v'))
|
|
515
|
-
extra.push('--verbose');
|
|
516
|
-
return registry.get('help').run(parseArgs(['--full', ...extra], { globalCwd }));
|
|
542
|
+
return registry.get('help').run(parseArgs(['--full'], { globalCwd }));
|
|
517
543
|
}
|
|
518
544
|
if (first === '--version' || first === '-v') {
|
|
519
545
|
return registry.get('version').run(parseArgs([], { globalCwd }));
|
|
@@ -557,7 +583,7 @@ async function runCliInner(argv) {
|
|
|
557
583
|
return 2;
|
|
558
584
|
}
|
|
559
585
|
const attempted = probe.slice(0, 2).join(' ');
|
|
560
|
-
process.stderr.write(`
|
|
586
|
+
process.stderr.write(`Unknown command: ${attempted}\n`);
|
|
561
587
|
printDidYouMean(attempted);
|
|
562
588
|
return 2;
|
|
563
589
|
}
|
|
@@ -665,125 +691,28 @@ async function checkSurfaceGate(matchedPath, cwd) {
|
|
|
665
691
|
return null;
|
|
666
692
|
}
|
|
667
693
|
}
|
|
668
|
-
// Score thresholds for did-you-mean output. Picked from observed
|
|
669
|
-
// scoring: 1-char-off typos score 8+ on plain commands; 3-4-char-off
|
|
670
|
-
// near-misses score ~5; loose / token-overlap matches score 1-3.
|
|
671
|
-
// Junk matches (frobnicate → bundle diff) can score 8 too because of
|
|
672
|
-
// token overlap, so we sharpen by also requiring the suggestion's
|
|
673
|
-
// command name to be reasonably close in length to the attempt.
|
|
674
|
-
const SUGGEST_CONFIDENT_SCORE = 7;
|
|
675
|
-
const SUGGEST_VISIBLE_SCORE = 3;
|
|
676
|
-
function reorderCandidates(attempted, candidates) {
|
|
677
|
-
// Stable sort: higher score first, then shorter command (more likely
|
|
678
|
-
// canonical), then lexicographic. The base suggester returns ties in
|
|
679
|
-
// arbitrary order — this makes the top suggestion more predictable.
|
|
680
|
-
const ranked = [...candidates];
|
|
681
|
-
ranked.sort((a, b) => {
|
|
682
|
-
if (b.score !== a.score)
|
|
683
|
-
return b.score - a.score;
|
|
684
|
-
if (a.command.length !== b.command.length) {
|
|
685
|
-
return a.command.length - b.command.length;
|
|
686
|
-
}
|
|
687
|
-
return a.command < b.command ? -1 : a.command > b.command ? 1 : 0;
|
|
688
|
-
});
|
|
689
|
-
return ranked;
|
|
690
|
-
}
|
|
691
|
-
/** Edit distance (Levenshtein). Used to gate did-you-mean confidence. */
|
|
692
|
-
function editDistance(a, b) {
|
|
693
|
-
const m = a.length;
|
|
694
|
-
const n = b.length;
|
|
695
|
-
if (m === 0)
|
|
696
|
-
return n;
|
|
697
|
-
if (n === 0)
|
|
698
|
-
return m;
|
|
699
|
-
const dp = new Array(n + 1);
|
|
700
|
-
for (let j = 0; j <= n; j += 1)
|
|
701
|
-
dp[j] = j;
|
|
702
|
-
for (let i = 1; i <= m; i += 1) {
|
|
703
|
-
let prev = dp[0];
|
|
704
|
-
dp[0] = i;
|
|
705
|
-
for (let j = 1; j <= n; j += 1) {
|
|
706
|
-
const tmp = dp[j];
|
|
707
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
708
|
-
dp[j] = Math.min(dp[j] + 1, dp[j - 1] + 1, prev + cost);
|
|
709
|
-
prev = tmp;
|
|
710
|
-
}
|
|
711
|
-
}
|
|
712
|
-
return dp[n];
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Suggestion is "confident" when the candidate's top token is close
|
|
716
|
-
* to the attempt in edit-distance terms — `doctorz`→`doctor` (1 edit)
|
|
717
|
-
* or `inspct`→`inspect` (1 edit) qualify; `frobnicate`→`bundle` (10
|
|
718
|
-
* edits) does not, even when the suggester scores them similarly
|
|
719
|
-
* because of incidental token overlap in descriptions.
|
|
720
|
-
*
|
|
721
|
-
* Threshold: edit distance ≤ max(1, attempt.length / 4) AND raw score
|
|
722
|
-
* meets `SUGGEST_VISIBLE_SCORE`. This catches typical fingers-on-keys
|
|
723
|
-
* typos while rejecting "you typed something totally different."
|
|
724
|
-
*/
|
|
725
|
-
function isConfidentMatch(attempted, suggestion) {
|
|
726
|
-
if (suggestion.score < SUGGEST_VISIBLE_SCORE)
|
|
727
|
-
return false;
|
|
728
|
-
const lower = attempted.toLowerCase();
|
|
729
|
-
const head = (suggestion.command.split(/\s+/)[0] ?? suggestion.command).toLowerCase();
|
|
730
|
-
const dist = editDistance(lower, head);
|
|
731
|
-
const tolerance = Math.max(1, Math.floor(lower.length / 4));
|
|
732
|
-
return dist <= tolerance;
|
|
733
|
-
}
|
|
734
694
|
function printDidYouMean(attempted) {
|
|
735
|
-
const
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
process.stderr.write('Run `shrk help` to see the curated commands, or `shrk --full-help` for the full catalog.\n');
|
|
739
|
-
const footer = errorFooterFor('unknown-command', { task: attempted });
|
|
740
|
-
if (footer)
|
|
741
|
-
process.stderr.write(renderErrorFooter(footer));
|
|
742
|
-
return;
|
|
743
|
-
}
|
|
744
|
-
// Confident single-match path: surface ONE suggestion clearly.
|
|
745
|
-
const top = reordered[0];
|
|
746
|
-
if (isConfidentMatch(attempted, top)) {
|
|
747
|
-
process.stderr.write(`Did you mean \`shrk ${top.command}\`?\n`);
|
|
748
|
-
process.stderr.write(` ${top.description}\n`);
|
|
749
|
-
// Second-tier suggestions only if they're also strong.
|
|
750
|
-
const others = reordered.slice(1, 3).filter((c) => isConfidentMatch(attempted, c));
|
|
751
|
-
if (others.length > 0) {
|
|
752
|
-
process.stderr.write('Other close matches:\n');
|
|
753
|
-
for (const c of others) {
|
|
754
|
-
process.stderr.write(` shrk ${c.command} — ${c.description}\n`);
|
|
755
|
-
}
|
|
756
|
-
}
|
|
695
|
+
const candidates = suggestDidYouMean(COMMAND_CATALOG, [attempted], 3);
|
|
696
|
+
if (candidates.length === 0) {
|
|
697
|
+
process.stderr.write("Tip: run `shrk commands suggest \"<partial>\"` or `shrk help` to discover commands.\n");
|
|
757
698
|
const footer = errorFooterFor('unknown-command', { task: attempted });
|
|
758
699
|
if (footer)
|
|
759
700
|
process.stderr.write(renderErrorFooter(footer));
|
|
760
701
|
return;
|
|
761
702
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
process.stderr.write('Closest matches in the catalog:\n');
|
|
765
|
-
for (const c of reordered.slice(0, 3)) {
|
|
703
|
+
process.stderr.write('Did you mean:\n');
|
|
704
|
+
for (const c of candidates) {
|
|
766
705
|
process.stderr.write(` shrk ${c.command} — ${c.description}\n`);
|
|
767
706
|
}
|
|
768
|
-
|
|
707
|
+
// append the standardised next-command footer so the user
|
|
708
|
+
// always has a deterministic exit route.
|
|
769
709
|
const footer = errorFooterFor('unknown-command', { task: attempted });
|
|
770
710
|
if (footer)
|
|
771
711
|
process.stderr.write(renderErrorFooter(footer));
|
|
772
712
|
}
|
|
773
713
|
// Entry point when invoked directly.
|
|
774
|
-
//
|
|
775
|
-
// Bun exposes `import.meta.main`; Node does not. When Node runs the
|
|
776
|
-
// compiled `dist/main.js` directly the path-suffix check (`main.js`)
|
|
777
|
-
// catches it. The npm bin shim points at `shrk` so that suffix also
|
|
778
|
-
// triggers it. Source dev under Bun still runs via `main.ts`.
|
|
779
714
|
const isMain = typeof import.meta !== 'undefined' && import.meta.main === true;
|
|
780
|
-
|
|
781
|
-
if (isMain ||
|
|
782
|
-
entryPath.endsWith('main.ts') ||
|
|
783
|
-
entryPath.endsWith('main.js') ||
|
|
784
|
-
entryPath.endsWith('shrk') ||
|
|
785
|
-
entryPath.endsWith('shrk.js') ||
|
|
786
|
-
entryPath.endsWith('shrk.cmd')) {
|
|
715
|
+
if (isMain || process.argv[1]?.endsWith('main.ts') || process.argv[1]?.endsWith('shrk')) {
|
|
787
716
|
const argv = process.argv.slice(2);
|
|
788
717
|
runCli(argv).then((code) => process.exit(code), (err) => {
|
|
789
718
|
process.stderr.write(`Fatal: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
@@ -12,7 +12,15 @@ export interface IFailureHint {
|
|
|
12
12
|
doc?: string;
|
|
13
13
|
}
|
|
14
14
|
export declare function renderFailureHints(hints: readonly IFailureHint[]): string;
|
|
15
|
-
export
|
|
15
|
+
export interface IDoctorHintsContext {
|
|
16
|
+
/**
|
|
17
|
+
* True when the workspace has no `sharkcraft/` folder. On a fresh repo
|
|
18
|
+
* the right next step is `shrk init`, not advanced suppressions/watch
|
|
19
|
+
* loops.
|
|
20
|
+
*/
|
|
21
|
+
sharkcraftFolderMissing?: boolean;
|
|
22
|
+
}
|
|
23
|
+
export declare function doctorHints(context?: IDoctorHintsContext): IFailureHint[];
|
|
16
24
|
export declare function staleKnowledgeHints(): IFailureHint[];
|
|
17
25
|
export declare function templateDriftHints(): IFailureHint[];
|
|
18
26
|
export declare function fuzzyImpactAmbiguousHints(): IFailureHint[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"failure-hints.d.ts","sourceRoot":"","sources":["../../src/output/failure-hints.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAUzE;AAID,wBAAgB,WAAW,
|
|
1
|
+
{"version":3,"file":"failure-hints.d.ts","sourceRoot":"","sources":["../../src/output/failure-hints.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,MAAM,CAUzE;AAID,MAAM,WAAW,mBAAmB;IAClC;;;;OAIG;IACH,uBAAuB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,wBAAgB,WAAW,CAAC,OAAO,GAAE,mBAAwB,GAAG,YAAY,EAAE,CAa7E;AAED,wBAAgB,mBAAmB,IAAI,YAAY,EAAE,CAMpD;AAED,wBAAgB,kBAAkB,IAAI,YAAY,EAAE,CAMnD;AAED,wBAAgB,yBAAyB,IAAI,YAAY,EAAE,CAK1D;AAED,wBAAgB,6BAA6B,IAAI,YAAY,EAAE,CAK9D;AAED,wBAAgB,kBAAkB,IAAI,YAAY,EAAE,CAKnD;AAED,wBAAgB,wBAAwB,IAAI,YAAY,EAAE,CAKzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAiB9D;AAED,MAAM,MAAM,eAAe,GACvB,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,oBAAoB,GACpB,uBAAuB,GACvB,kBAAkB,GAClB,eAAe,GACf,2BAA2B,GAC3B,sBAAsB,GACtB,+BAA+B,GAC/B,wBAAwB,GACxB,8BAA8B,CAAC;AAEnC;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,GAAG,SAAS,CA4E3G"}
|
|
@@ -11,8 +11,14 @@ export function renderFailureHints(hints) {
|
|
|
11
11
|
}
|
|
12
12
|
return lines.join('\n') + '\n';
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
export function doctorHints(context = {}) {
|
|
15
|
+
if (context.sharkcraftFolderMissing) {
|
|
16
|
+
return [
|
|
17
|
+
{ label: 'scaffold sharkcraft/ (auto-pick a preset)', command: 'shrk init --zero-config' },
|
|
18
|
+
{ label: 'preview the scaffold first', command: 'shrk init --zero-config --dry-run' },
|
|
19
|
+
{ label: 'try the killer demo (no folder required)', command: 'shrk check boundaries --changed-only --since main' },
|
|
20
|
+
];
|
|
21
|
+
}
|
|
16
22
|
return [
|
|
17
23
|
{ label: 'preview fix suggestions', command: 'shrk fix preview --action-hints' },
|
|
18
24
|
{ label: 'list suppressions', command: 'shrk doctor suppressions list' },
|
|
@@ -27,19 +27,11 @@ export interface IWatchPlan {
|
|
|
27
27
|
}
|
|
28
28
|
export declare function buildWatchPlan(options: IWatchLoopOptions, steps: readonly string[]): IWatchPlan;
|
|
29
29
|
import type { ParsedArgs } from '../command-registry.js';
|
|
30
|
-
export interface IWatchModeOptions {
|
|
31
|
-
/**
|
|
32
|
-
* Paths to watch when the user does not pass `--paths`. Defaults to
|
|
33
|
-
* `['sharkcraft']` if omitted. Use this for commands that scan code
|
|
34
|
-
* outside `sharkcraft/` (e.g. `check boundaries` scans the whole repo).
|
|
35
|
-
*/
|
|
36
|
-
defaultPaths?: readonly string[];
|
|
37
|
-
}
|
|
38
30
|
/**
|
|
39
31
|
* Run a command's `run` function inside a watch loop when --watch is set.
|
|
40
32
|
*
|
|
41
33
|
* @returns null if --watch is not set (caller proceeds as before), otherwise
|
|
42
34
|
* the exit code of the watch loop.
|
|
43
35
|
*/
|
|
44
|
-
export declare function maybeRunInWatchMode(args: ParsedArgs, runner: (innerArgs: ParsedArgs) => Promise<number
|
|
36
|
+
export declare function maybeRunInWatchMode(args: ParsedArgs, runner: (innerArgs: ParsedArgs) => Promise<number>): Promise<number | null>;
|
|
45
37
|
//# sourceMappingURL=watch-loop.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"watch-loop.d.ts","sourceRoot":"","sources":["../../src/output/watch-loop.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACvC;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,CAAC,CA6DjB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,0BAA0B,CAAC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,UAAU,CAYZ;AAED,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGzD
|
|
1
|
+
{"version":3,"file":"watch-loop.d.ts","sourceRoot":"","sources":["../../src/output/watch-loop.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,uCAAuC;IACvC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,kBAAkB;IACjC,4BAA4B;IAC5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACvC;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,iBAAiB,EAC1B,QAAQ,EAAE,kBAAkB,GAC3B,OAAO,CAAC,MAAM,CAAC,CA6DjB;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,0BAA0B,CAAC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,iBAAiB,EAC1B,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,UAAU,CAYZ;AAED,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGzD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,CAAC,SAAS,EAAE,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,GACjD,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA0BxB"}
|
|
@@ -81,41 +81,31 @@ export function buildWatchPlan(options, steps) {
|
|
|
81
81
|
steps,
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
-
import { flagBool, flagNumber,
|
|
84
|
+
import { flagBool, flagNumber, resolveCwd } from "../command-registry.js";
|
|
85
85
|
/**
|
|
86
86
|
* Run a command's `run` function inside a watch loop when --watch is set.
|
|
87
87
|
*
|
|
88
88
|
* @returns null if --watch is not set (caller proceeds as before), otherwise
|
|
89
89
|
* the exit code of the watch loop.
|
|
90
90
|
*/
|
|
91
|
-
export async function maybeRunInWatchMode(args, runner
|
|
91
|
+
export async function maybeRunInWatchMode(args, runner) {
|
|
92
92
|
if (!flagBool(args, 'watch'))
|
|
93
93
|
return null;
|
|
94
94
|
const cwd = resolveCwd(args);
|
|
95
95
|
const debounce = flagNumber(args, 'debounce') ?? 300;
|
|
96
96
|
const once = flagBool(args, 'once');
|
|
97
|
-
const pathsFlag = flagString(args, 'paths');
|
|
98
|
-
const userPaths = pathsFlag
|
|
99
|
-
? pathsFlag.split(',').map((s) => s.trim()).filter((s) => s.length > 0)
|
|
100
|
-
: [];
|
|
101
|
-
const paths = userPaths.length > 0
|
|
102
|
-
? userPaths
|
|
103
|
-
: options.defaultPaths && options.defaultPaths.length > 0
|
|
104
|
-
? options.defaultPaths
|
|
105
|
-
: ['sharkcraft'];
|
|
106
97
|
// Strip --watch so the inner snapshot doesn't recurse.
|
|
107
98
|
const innerFlags = new Map(args.flags);
|
|
108
99
|
innerFlags.delete('watch');
|
|
109
100
|
innerFlags.delete('once');
|
|
110
101
|
innerFlags.delete('debounce');
|
|
111
|
-
innerFlags.delete('paths');
|
|
112
102
|
const innerArgs = {
|
|
113
103
|
positional: args.positional,
|
|
114
104
|
flags: innerFlags,
|
|
115
105
|
multiFlags: args.multiFlags,
|
|
116
106
|
...(args.globalCwd ? { globalCwd: args.globalCwd } : {}),
|
|
117
107
|
};
|
|
118
|
-
return runWatchLoop({ cwd, debounce, once
|
|
108
|
+
return runWatchLoop({ cwd, debounce, once }, {
|
|
119
109
|
snapshot: async () => {
|
|
120
110
|
const ts = new Date().toLocaleTimeString();
|
|
121
111
|
process.stdout.write(`\n[watch] ${ts}\n`);
|