@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
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type IChangedScopeOptions } from '@shrkcrft/inspector';
|
|
2
|
+
export declare const FINISH_SCHEMA: "sharkcraft.finish/v1";
|
|
3
|
+
/** Outcome of one sub-gate. `skipped` = nothing to evaluate (loud, never silent green). */
|
|
4
|
+
export type FinishGateStatus = 'pass' | 'fail' | 'skipped';
|
|
5
|
+
/** One failing/relevant item, with file:line where the engine provides it. */
|
|
6
|
+
export interface IFinishItem {
|
|
7
|
+
readonly file?: string;
|
|
8
|
+
readonly line?: number;
|
|
9
|
+
readonly message: string;
|
|
10
|
+
}
|
|
11
|
+
export interface IFinishGate {
|
|
12
|
+
readonly name: 'boundaries' | 'imports' | 'wiring' | 'policy' | 'orphans';
|
|
13
|
+
readonly status: FinishGateStatus;
|
|
14
|
+
/** One-line reason (e.g. why skipped, or the error/warning counts). */
|
|
15
|
+
readonly detail: string;
|
|
16
|
+
readonly errors: number;
|
|
17
|
+
readonly warnings: number;
|
|
18
|
+
/** Failing/notable items (capped by the renderer, full in JSON). */
|
|
19
|
+
readonly items: readonly IFinishItem[];
|
|
20
|
+
}
|
|
21
|
+
export interface IFinishImpact {
|
|
22
|
+
readonly ran: boolean;
|
|
23
|
+
readonly risk?: string;
|
|
24
|
+
readonly directDependents?: number;
|
|
25
|
+
readonly transitiveDependents?: number;
|
|
26
|
+
/** Why the summary could not run (no graph index / no changed files). */
|
|
27
|
+
readonly note?: string;
|
|
28
|
+
}
|
|
29
|
+
export interface IFinishReport {
|
|
30
|
+
readonly schema: typeof FINISH_SCHEMA;
|
|
31
|
+
readonly scope: {
|
|
32
|
+
readonly mode: 'worktree' | 'staged' | 'since' | 'files';
|
|
33
|
+
readonly files: readonly string[];
|
|
34
|
+
readonly fileCount: number;
|
|
35
|
+
};
|
|
36
|
+
readonly gates: readonly IFinishGate[];
|
|
37
|
+
readonly impact: IFinishImpact;
|
|
38
|
+
/** `fail` iff any gate failed OR the config could not load; else `pass`. */
|
|
39
|
+
readonly verdict: 'pass' | 'fail';
|
|
40
|
+
/** Total warning-severity findings across gates (non-blocking). */
|
|
41
|
+
readonly warnings: number;
|
|
42
|
+
/** Set when sharkcraft.config.ts could not be loaded — forces a `fail`. */
|
|
43
|
+
readonly configError?: string;
|
|
44
|
+
readonly summary: string;
|
|
45
|
+
readonly nextAction: string;
|
|
46
|
+
}
|
|
47
|
+
export interface IRunFinishInput {
|
|
48
|
+
readonly cwd: string;
|
|
49
|
+
readonly mode: 'worktree' | 'staged' | 'since' | 'files';
|
|
50
|
+
readonly scope: IChangedScopeOptions;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The composite "is this changeset safe to finish?" orchestrator. Runs every
|
|
54
|
+
* deterministic CHANGED-ONLY gate inline — boundaries + import-hygiene + wiring
|
|
55
|
+
* + policy + deleted-orphans — plus a best-effort impact summary, and folds
|
|
56
|
+
* them into ONE pass/fail. This is the single trustworthy "done?" call an
|
|
57
|
+
* autonomous agent needs and can't reliably assemble by hand (only shrk can run
|
|
58
|
+
* the alias-resolved layer/wiring gates). Honors the `0-rules → skipped`
|
|
59
|
+
* semantics so a no-op sub-check is reported, never silently passed. Read-only.
|
|
60
|
+
*/
|
|
61
|
+
export declare function runFinishGates(input: IRunFinishInput): Promise<IFinishReport>;
|
|
62
|
+
//# sourceMappingURL=run-finish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-finish.d.ts","sourceRoot":"","sources":["../../src/finish/run-finish.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAa7B,eAAO,MAAM,aAAa,EAAG,sBAA+B,CAAC;AAE7D,2FAA2F;AAC3F,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;AAE3D,8EAA8E;AAC9E,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC1E,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAClC,uEAAuE;IACvE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oEAAoE;IACpE,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACvC,yEAAyE;IACzE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,aAAa,CAAC;IACtC,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;QACzD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;QAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAClC,mEAAmE;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2EAA2E;IAC3E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IACzD,QAAQ,CAAC,KAAK,EAAE,oBAAoB,CAAC;CACtC;AAYD;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,aAAa,CAAC,CAkHnF"}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { buildImportHygieneReport, filterViolationsToChangedScope, inspectSharkcraft, resolveChangedFiles, resolveProjectConfig, } from '@shrkcrft/inspector';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import * as nodePath from 'node:path';
|
|
4
|
+
import { evaluateBoundaries, loadTsconfigPaths, runPolicyLint, runWiring, scanImports, } from '@shrkcrft/boundaries';
|
|
5
|
+
import { computeDeletedOrphans } from "../diff/deleted-orphans.js";
|
|
6
|
+
export const FINISH_SCHEMA = 'sharkcraft.finish/v1';
|
|
7
|
+
/** Map the changed-scope onto the orphan check's diff inputs. */
|
|
8
|
+
function orphanOptsFor(input) {
|
|
9
|
+
if (input.mode === 'files')
|
|
10
|
+
return undefined; // a file list has no diff to read deletions from
|
|
11
|
+
if (input.mode === 'staged')
|
|
12
|
+
return { staged: true };
|
|
13
|
+
if (input.mode === 'since' && input.scope.since)
|
|
14
|
+
return { since: input.scope.since };
|
|
15
|
+
// Worktree mode: diff deletions vs HEAD so the orphan gate's "deleted" set
|
|
16
|
+
// matches the working-tree scope the other gates use (not the whole branch).
|
|
17
|
+
return { since: 'HEAD' };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The composite "is this changeset safe to finish?" orchestrator. Runs every
|
|
21
|
+
* deterministic CHANGED-ONLY gate inline — boundaries + import-hygiene + wiring
|
|
22
|
+
* + policy + deleted-orphans — plus a best-effort impact summary, and folds
|
|
23
|
+
* them into ONE pass/fail. This is the single trustworthy "done?" call an
|
|
24
|
+
* autonomous agent needs and can't reliably assemble by hand (only shrk can run
|
|
25
|
+
* the alias-resolved layer/wiring gates). Honors the `0-rules → skipped`
|
|
26
|
+
* semantics so a no-op sub-check is reported, never silently passed. Read-only.
|
|
27
|
+
*/
|
|
28
|
+
export async function runFinishGates(input) {
|
|
29
|
+
const { cwd } = input;
|
|
30
|
+
const changed = resolveChangedFiles(input.scope);
|
|
31
|
+
const changedFiles = changed.files;
|
|
32
|
+
const gates = [];
|
|
33
|
+
// ── boundaries (changed-only) ────────────────────────────────────────
|
|
34
|
+
const inspection = await inspectSharkcraft({ cwd });
|
|
35
|
+
const boundaryRules = inspection.boundaryRegistry.list();
|
|
36
|
+
if (boundaryRules.length === 0) {
|
|
37
|
+
gates.push(skip('boundaries', 'no boundary rules configured'));
|
|
38
|
+
}
|
|
39
|
+
else if (changedFiles.length === 0) {
|
|
40
|
+
gates.push(skip('boundaries', 'no files in changed scope'));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const scan = scanImports({ projectRoot: cwd });
|
|
44
|
+
const tsconfigPaths = loadTsconfigPaths(cwd);
|
|
45
|
+
const evalResult = evaluateBoundaries(scan, boundaryRules, {
|
|
46
|
+
...(tsconfigPaths.aliases.size > 0 ? { tsconfigPaths } : {}),
|
|
47
|
+
});
|
|
48
|
+
const filtered = filterViolationsToChangedScope(evalResult.violations, input.scope);
|
|
49
|
+
const errors = filtered.includedViolations.filter((v) => v.severity === 'error');
|
|
50
|
+
const warnings = filtered.includedViolations.filter((v) => v.severity === 'warning');
|
|
51
|
+
gates.push({
|
|
52
|
+
name: 'boundaries',
|
|
53
|
+
status: errors.length > 0 ? 'fail' : 'pass',
|
|
54
|
+
detail: `${errors.length} error(s), ${warnings.length} warning(s) across ${changedFiles.length} changed file(s)`,
|
|
55
|
+
errors: errors.length,
|
|
56
|
+
warnings: warnings.length,
|
|
57
|
+
items: [...errors, ...warnings].map((v) => ({
|
|
58
|
+
file: v.file,
|
|
59
|
+
line: v.line,
|
|
60
|
+
message: `[${v.severity}] ${v.ruleId}: ${v.message}`,
|
|
61
|
+
})),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
// ── import hygiene (changed-only) ────────────────────────────────────
|
|
65
|
+
if (changedFiles.length === 0) {
|
|
66
|
+
gates.push(skip('imports', 'no files in changed scope'));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const report = buildImportHygieneReport(cwd, { files: changedFiles });
|
|
70
|
+
const errors = report.counts?.['error'] ?? (report.verdict === 'errors' ? report.findings.length : 0);
|
|
71
|
+
const warnings = report.counts?.['warning'] ?? (report.verdict === 'warnings' ? report.findings.length : 0);
|
|
72
|
+
gates.push({
|
|
73
|
+
name: 'imports',
|
|
74
|
+
status: report.verdict === 'errors' ? 'fail' : 'pass',
|
|
75
|
+
detail: `verdict=${report.verdict} (${report.findings.length} finding(s))`,
|
|
76
|
+
errors,
|
|
77
|
+
warnings,
|
|
78
|
+
items: report.findings.map((f) => ({
|
|
79
|
+
file: f.file,
|
|
80
|
+
line: f.line,
|
|
81
|
+
message: `${f.kind}: ${f.suggestedFix || f.reason || f.snippet}`.trim(),
|
|
82
|
+
})),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
// ── wiring + policy (changed-only, from resolved config) ─────────────
|
|
86
|
+
const loaded = await resolveProjectConfig(cwd);
|
|
87
|
+
let configError;
|
|
88
|
+
if (!loaded.ok) {
|
|
89
|
+
// A MALFORMED config in a real sharkcraft project is a fail (the wiring/
|
|
90
|
+
// policy gates can't be trusted). The mere ABSENCE of a sharkcraft/ folder
|
|
91
|
+
// is not — those gates simply don't apply, so skip them without failing.
|
|
92
|
+
const isSharkcraftProject = existsSync(nodePath.join(cwd, 'sharkcraft'));
|
|
93
|
+
if (isSharkcraftProject)
|
|
94
|
+
configError = loaded.error.message;
|
|
95
|
+
const detail = isSharkcraftProject
|
|
96
|
+
? `config did not load: ${loaded.error.message}`
|
|
97
|
+
: 'no sharkcraft config (gate not applicable)';
|
|
98
|
+
gates.push(skip('wiring', detail));
|
|
99
|
+
gates.push(skip('policy', detail));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
gates.push(wiringGate(cwd, loaded.value.config.wiringRules ?? [], changedFiles), policyGate(cwd, loaded.value.config.policyRules ?? [], changedFiles));
|
|
103
|
+
}
|
|
104
|
+
// ── deleted-orphans (write-safety) ───────────────────────────────────
|
|
105
|
+
gates.push(await orphansGate(input));
|
|
106
|
+
// ── impact summary (informational, best-effort) ──────────────────────
|
|
107
|
+
const impact = await impactSummary(cwd, changedFiles);
|
|
108
|
+
// ── fold into one verdict ────────────────────────────────────────────
|
|
109
|
+
const failed = gates.filter((g) => g.status === 'fail');
|
|
110
|
+
const warnings = gates.reduce((n, g) => n + g.warnings, 0);
|
|
111
|
+
const verdict = failed.length > 0 || configError ? 'fail' : 'pass';
|
|
112
|
+
const skipped = gates.filter((g) => g.status === 'skipped').map((g) => g.name);
|
|
113
|
+
const summary = verdict === 'fail'
|
|
114
|
+
? `Not safe to finish: ${configError ? 'config failed to load; ' : ''}${failed.map((g) => `${g.name} (${g.errors} error(s))`).join(', ') || 'see gates'}.`
|
|
115
|
+
: changedFiles.length === 0 && input.mode !== 'files'
|
|
116
|
+
? 'No files in the changed scope — nothing to gate.'
|
|
117
|
+
: `Safe to finish: every applicable gate passed${warnings > 0 ? ` (${warnings} non-blocking warning(s))` : ''}${skipped.length > 0 ? `; skipped: ${skipped.join(', ')}` : ''}.`;
|
|
118
|
+
const nextAction = verdict === 'fail'
|
|
119
|
+
? 'Fix every failing gate item (each carries file:line), then re-run `shrk finish`.'
|
|
120
|
+
: 'Safe to declare done.';
|
|
121
|
+
return {
|
|
122
|
+
schema: FINISH_SCHEMA,
|
|
123
|
+
scope: { mode: input.mode, files: changedFiles, fileCount: changedFiles.length },
|
|
124
|
+
gates,
|
|
125
|
+
impact,
|
|
126
|
+
verdict,
|
|
127
|
+
warnings,
|
|
128
|
+
...(configError ? { configError } : {}),
|
|
129
|
+
summary,
|
|
130
|
+
nextAction,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
function skip(name, detail) {
|
|
134
|
+
return { name, status: 'skipped', detail, errors: 0, warnings: 0, items: [] };
|
|
135
|
+
}
|
|
136
|
+
function wiringGate(cwd, rules, changedFiles) {
|
|
137
|
+
if (rules.length === 0)
|
|
138
|
+
return skip('wiring', 'no wiring rules configured');
|
|
139
|
+
const report = runWiring(cwd, rules, { changedOnly: true, changedFiles });
|
|
140
|
+
if (report.evaluated === 0) {
|
|
141
|
+
return skip('wiring', `${report.rules.length} rule(s) configured but none matched the changed scope`);
|
|
142
|
+
}
|
|
143
|
+
const errors = report.violations.filter((v) => v.severity === 'error');
|
|
144
|
+
const warnings = report.violations.filter((v) => v.severity === 'warning');
|
|
145
|
+
// A misconfigured rule (bad regex / no capture group) yields a diagnostic +
|
|
146
|
+
// rule-level error but NO violation — it must FAIL the gate, never read as a
|
|
147
|
+
// silent green ("loud, never silent green").
|
|
148
|
+
const diag = report.diagnostics;
|
|
149
|
+
return {
|
|
150
|
+
name: 'wiring',
|
|
151
|
+
status: report.verdict === 'errors' || diag.length > 0 ? 'fail' : 'pass',
|
|
152
|
+
detail: `${report.evaluated}/${report.rules.length} rule(s) evaluated — ${errors.length} error(s), ${warnings.length} warning(s)${diag.length > 0 ? `, ${diag.length} misconfigured` : ''}`,
|
|
153
|
+
errors: errors.length + diag.length,
|
|
154
|
+
warnings: warnings.length,
|
|
155
|
+
items: [
|
|
156
|
+
...report.violations.map((v) => ({
|
|
157
|
+
file: v.file,
|
|
158
|
+
line: v.line,
|
|
159
|
+
message: `[${v.severity}] ${v.ruleId}: "${v.token}" ${v.direction === 'registered-missing' ? 'registered but not declared' : 'declared but not registered'}`,
|
|
160
|
+
})),
|
|
161
|
+
...diag.map((d) => ({ message: `misconfigured rule: ${d}` })),
|
|
162
|
+
],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function policyGate(cwd, rules, changedFiles) {
|
|
166
|
+
if (rules.length === 0)
|
|
167
|
+
return skip('policy', 'no policy rules configured');
|
|
168
|
+
const report = runPolicyLint(cwd, rules, { changedOnly: true, changedFiles });
|
|
169
|
+
if (report.evaluated === 0) {
|
|
170
|
+
return skip('policy', `${report.rules.length} rule(s) configured but none matched the changed scope`);
|
|
171
|
+
}
|
|
172
|
+
const errors = report.findings.filter((f) => f.severity === 'error');
|
|
173
|
+
const warnings = report.findings.filter((f) => f.severity === 'warning');
|
|
174
|
+
const diag = report.diagnostics;
|
|
175
|
+
return {
|
|
176
|
+
name: 'policy',
|
|
177
|
+
status: report.verdict === 'errors' || diag.length > 0 ? 'fail' : 'pass',
|
|
178
|
+
detail: `${report.evaluated}/${report.rules.length} rule(s) evaluated — ${errors.length} error(s), ${warnings.length} warning(s)${diag.length > 0 ? `, ${diag.length} misconfigured` : ''}`,
|
|
179
|
+
errors: errors.length + diag.length,
|
|
180
|
+
warnings: warnings.length,
|
|
181
|
+
items: [
|
|
182
|
+
...report.findings.map((f) => ({
|
|
183
|
+
file: f.file,
|
|
184
|
+
line: f.line,
|
|
185
|
+
message: `[${f.severity}] ${f.ruleId}: ${f.message ?? ''}`.trim(),
|
|
186
|
+
})),
|
|
187
|
+
...diag.map((d) => ({ message: `misconfigured rule: ${d}` })),
|
|
188
|
+
],
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
async function orphansGate(input) {
|
|
192
|
+
const opts = orphanOptsFor(input);
|
|
193
|
+
if (!opts)
|
|
194
|
+
return skip('orphans', 'explicit --files scope has no diff to read deletions from');
|
|
195
|
+
const scan = await computeDeletedOrphans(input.cwd, opts);
|
|
196
|
+
if (!scan.ok) {
|
|
197
|
+
return skip('orphans', scan.reason === 'graph-missing'
|
|
198
|
+
? 'code-graph index missing — run `shrk graph index` to enable the orphan check'
|
|
199
|
+
: `diff unavailable: ${scan.error ?? 'unknown'}`);
|
|
200
|
+
}
|
|
201
|
+
if (scan.deleted.length === 0)
|
|
202
|
+
return skip('orphans', `nothing deleted (vs ${scan.ref})`);
|
|
203
|
+
const orphans = scan.report?.orphans ?? [];
|
|
204
|
+
return {
|
|
205
|
+
name: 'orphans',
|
|
206
|
+
status: orphans.length > 0 ? 'fail' : 'pass',
|
|
207
|
+
detail: `${scan.deleted.length} deleted file(s) (vs ${scan.ref}) — ${orphans.length} surviving importer(s)`,
|
|
208
|
+
errors: orphans.length,
|
|
209
|
+
warnings: 0,
|
|
210
|
+
items: orphans.map((o) => ({
|
|
211
|
+
file: o.path ?? o.id,
|
|
212
|
+
...(typeof o.line === 'number' ? { line: o.line } : {}),
|
|
213
|
+
message: o.via === 'reference' && o.symbol
|
|
214
|
+
? `references \`${o.symbol}\` from deleted ${o.deletedFile}`
|
|
215
|
+
: `imports deleted ${o.deletedFile}`,
|
|
216
|
+
})),
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
async function impactSummary(cwd, changedFiles) {
|
|
220
|
+
if (changedFiles.length === 0)
|
|
221
|
+
return { ran: false, note: 'no changed files' };
|
|
222
|
+
try {
|
|
223
|
+
const { GraphStore } = await import('@shrkcrft/graph');
|
|
224
|
+
if (!new GraphStore(cwd).exists()) {
|
|
225
|
+
return { ran: false, note: 'code-graph index missing — run `shrk graph index`' };
|
|
226
|
+
}
|
|
227
|
+
const { analyzeGraphImpact } = await import('@shrkcrft/impact-engine');
|
|
228
|
+
const analysis = analyzeGraphImpact({ kind: 'files', files: [...changedFiles] }, { projectRoot: cwd, maxDepth: 5, limit: 200 });
|
|
229
|
+
return {
|
|
230
|
+
ran: true,
|
|
231
|
+
risk: analysis.risk,
|
|
232
|
+
directDependents: analysis.directDependents.length,
|
|
233
|
+
transitiveDependents: analysis.transitiveDependents.length,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
catch (e) {
|
|
237
|
+
return { ran: false, note: `impact summary unavailable: ${e instanceof Error ? e.message : String(e)}` };
|
|
238
|
+
}
|
|
239
|
+
}
|
package/dist/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,eAAe,EAKhB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":";AAEA,OAAO,EACL,eAAe,EAKhB,MAAM,uBAAuB,CAAC;AA4X/B,wBAAgB,aAAa,IAAI,eAAe,CAgY/C;AAED,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA2BrE;AAqID;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAoDxE"}
|
package/dist/main.js
CHANGED
|
@@ -22,6 +22,7 @@ import { presetsListCommand, presetsGetCommand, presetsExplainCommand, presetsRe
|
|
|
22
22
|
import { taskCommand } from "./commands/task.command.js";
|
|
23
23
|
import { preflightCommand } from "./commands/preflight.command.js";
|
|
24
24
|
import { checkCommand } from "./commands/check.command.js";
|
|
25
|
+
import { finishCommand } from "./commands/finish.command.js";
|
|
25
26
|
import { diffCheckCommand } from "./commands/diff-check.command.js";
|
|
26
27
|
import { driftCommand } from "./commands/drift.command.js";
|
|
27
28
|
import { graphCommand } from "./commands/graph.command.js";
|
|
@@ -33,6 +34,7 @@ import { frameworkCommand } from "./commands/framework.command.js";
|
|
|
33
34
|
import { apiDiffCommand } from "./commands/api-diff.command.js";
|
|
34
35
|
import { gateCommand } from "./commands/gate.command.js";
|
|
35
36
|
import { policyLintCommand } from "./commands/policy-lint.command.js";
|
|
37
|
+
import { wiringCommand } from "./commands/wiring.command.js";
|
|
36
38
|
import { reuseCommand } from "./commands/reuse.command.js";
|
|
37
39
|
import { migrateCommand } from "./commands/migrate.command.js";
|
|
38
40
|
import { coverageCommand } from "./commands/coverage.command.js";
|
|
@@ -189,6 +191,7 @@ export function buildRegistry() {
|
|
|
189
191
|
registry.register(explainCommand);
|
|
190
192
|
registry.register(checkCommand);
|
|
191
193
|
registry.register(diffCheckCommand);
|
|
194
|
+
registry.register(finishCommand);
|
|
192
195
|
// changed-only preflight orchestrator.
|
|
193
196
|
registry.register(preflightCommand);
|
|
194
197
|
registry.register(driftCommand);
|
|
@@ -201,6 +204,7 @@ export function buildRegistry() {
|
|
|
201
204
|
registry.register(apiDiffCommand);
|
|
202
205
|
registry.register(gateCommand);
|
|
203
206
|
registry.register(policyLintCommand);
|
|
207
|
+
registry.register(wiringCommand);
|
|
204
208
|
registry.register(reuseCommand);
|
|
205
209
|
registry.register(migrateCommand);
|
|
206
210
|
registry.register(coverageCommand);
|
|
@@ -601,7 +605,21 @@ async function runCliInner(argv) {
|
|
|
601
605
|
// (`shrk doctor`, `shrk packs list`, `shrk pack author status`). The
|
|
602
606
|
// resolver stops when it hits a flag or a token that isn't a child of the
|
|
603
607
|
// current node, returning the deepest handler + the leftover tokens.
|
|
604
|
-
|
|
608
|
+
let { handler, matchedPath, rest: leftover, node } = registry.resolve(cleanArgv);
|
|
609
|
+
// A multi-word command passed as a SINGLE quoted token (`shrk "graph status"`)
|
|
610
|
+
// arrives as one argv element with internal whitespace. The trie has no atomic
|
|
611
|
+
// `graph status` node, so the first descent misses (handler undefined) — yet
|
|
612
|
+
// did-you-mean would still list `graph status` as the #1 closest match, a
|
|
613
|
+
// self-contradiction. Re-split the lone token on whitespace and retry so the
|
|
614
|
+
// quoted form behaves identically to the unquoted `shrk graph status`.
|
|
615
|
+
// Genuinely unknown tokens leave `handler` undefined and fall through to the
|
|
616
|
+
// existing unknown-command path unchanged.
|
|
617
|
+
if (!handler && cleanArgv.length === 1 && /\s/.test(cleanArgv[0])) {
|
|
618
|
+
const retry = registry.resolve(cleanArgv[0].trim().split(/\s+/));
|
|
619
|
+
if (retry.handler) {
|
|
620
|
+
({ handler, matchedPath, rest: leftover, node } = retry);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
605
623
|
// `--help` / `-h` immediately after a (sub)group → render help for that
|
|
606
624
|
// path. This works at any depth.
|
|
607
625
|
if (leftover[0] === '--help' || leftover[0] === '-h') {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Source-mtime freshness — a small shared CLI helper.
|
|
3
|
+
*
|
|
4
|
+
* Several `… status` commands (`framework status`, `context status`) need to
|
|
5
|
+
* answer the same question: "is this stored artefact stale relative to the
|
|
6
|
+
* source tree it was built from?" They all walk the workspace for the newest
|
|
7
|
+
* source-file mtime and compare it to a stored build timestamp. This module
|
|
8
|
+
* is the single home for that walk so the commands stay byte-identical.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: this is deliberately CLI-local and distinct from
|
|
11
|
+
* `@shrkcrft/graph`'s `detectGraphFreshness` — that one models the graph
|
|
12
|
+
* store's own freshness and graph sits BELOW cli in the layer order, so it
|
|
13
|
+
* cannot be reused here.
|
|
14
|
+
*/
|
|
15
|
+
export declare const FRESHNESS_SKIP_DIRS: Set<string>;
|
|
16
|
+
export declare const FRESHNESS_SOURCE_EXTS: Set<string>;
|
|
17
|
+
export interface IStatusFreshness {
|
|
18
|
+
state: 'fresh' | 'stale' | 'unknown';
|
|
19
|
+
lastBuiltAt: string | null;
|
|
20
|
+
lastChangedAt: string | null;
|
|
21
|
+
behindMs: number;
|
|
22
|
+
}
|
|
23
|
+
/** Newest source-file mtime (ms) under `root`, ignoring build/output dirs. 0
|
|
24
|
+
* when nothing matched. */
|
|
25
|
+
export declare function newestSourceMtimeMs(root: string): number;
|
|
26
|
+
/** Compare a stored build timestamp to the newest source mtime in `scope`.
|
|
27
|
+
* `stale` when a source file is newer than the build; `unknown` when the
|
|
28
|
+
* build timestamp can't be parsed. */
|
|
29
|
+
export declare function computeMtimeFreshness(scope: string, builtAtIso: string | undefined | null): IStatusFreshness;
|
|
30
|
+
//# sourceMappingURL=freshness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"freshness.d.ts","sourceRoot":"","sources":["../../src/status/freshness.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,mBAAmB,aAG9B,CAAC;AACH,eAAO,MAAM,qBAAqB,aAGhC,CAAC;AAEH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC;IACrC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;4BAC4B;AAC5B,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA8BxD;AAED;;uCAEuC;AACvC,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,gBAAgB,CAc5G"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import * as nodePath from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Source-mtime freshness — a small shared CLI helper.
|
|
5
|
+
*
|
|
6
|
+
* Several `… status` commands (`framework status`, `context status`) need to
|
|
7
|
+
* answer the same question: "is this stored artefact stale relative to the
|
|
8
|
+
* source tree it was built from?" They all walk the workspace for the newest
|
|
9
|
+
* source-file mtime and compare it to a stored build timestamp. This module
|
|
10
|
+
* is the single home for that walk so the commands stay byte-identical.
|
|
11
|
+
*
|
|
12
|
+
* NOTE: this is deliberately CLI-local and distinct from
|
|
13
|
+
* `@shrkcrft/graph`'s `detectGraphFreshness` — that one models the graph
|
|
14
|
+
* store's own freshness and graph sits BELOW cli in the layer order, so it
|
|
15
|
+
* cannot be reused here.
|
|
16
|
+
*/
|
|
17
|
+
export const FRESHNESS_SKIP_DIRS = new Set([
|
|
18
|
+
'node_modules', 'dist', 'build', 'coverage', '.git', '.sharkcraft',
|
|
19
|
+
'.next', '.cache', '.tmp-pack', 'out', 'target',
|
|
20
|
+
]);
|
|
21
|
+
export const FRESHNESS_SOURCE_EXTS = new Set([
|
|
22
|
+
'.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs',
|
|
23
|
+
'.java', '.cs', '.py', '.go', '.rs', '.kt', '.swift',
|
|
24
|
+
]);
|
|
25
|
+
/** Newest source-file mtime (ms) under `root`, ignoring build/output dirs. 0
|
|
26
|
+
* when nothing matched. */
|
|
27
|
+
export function newestSourceMtimeMs(root) {
|
|
28
|
+
let newest = 0;
|
|
29
|
+
const stack = [root];
|
|
30
|
+
while (stack.length > 0) {
|
|
31
|
+
const dir = stack.pop();
|
|
32
|
+
let entries;
|
|
33
|
+
try {
|
|
34
|
+
entries = readdirSync(dir);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
for (const name of entries) {
|
|
40
|
+
if (FRESHNESS_SKIP_DIRS.has(name) || name.startsWith('.'))
|
|
41
|
+
continue;
|
|
42
|
+
const full = nodePath.join(dir, name);
|
|
43
|
+
let st;
|
|
44
|
+
try {
|
|
45
|
+
st = statSync(full);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (st.isDirectory()) {
|
|
51
|
+
stack.push(full);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
if (!st.isFile())
|
|
55
|
+
continue;
|
|
56
|
+
if (!FRESHNESS_SOURCE_EXTS.has(nodePath.extname(full).toLowerCase()))
|
|
57
|
+
continue;
|
|
58
|
+
if (st.mtimeMs > newest)
|
|
59
|
+
newest = st.mtimeMs;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return newest;
|
|
63
|
+
}
|
|
64
|
+
/** Compare a stored build timestamp to the newest source mtime in `scope`.
|
|
65
|
+
* `stale` when a source file is newer than the build; `unknown` when the
|
|
66
|
+
* build timestamp can't be parsed. */
|
|
67
|
+
export function computeMtimeFreshness(scope, builtAtIso) {
|
|
68
|
+
const newestMs = newestSourceMtimeMs(scope);
|
|
69
|
+
const lastChangedAt = newestMs > 0 ? new Date(newestMs).toISOString() : null;
|
|
70
|
+
const builtMs = builtAtIso ? Date.parse(builtAtIso) : NaN;
|
|
71
|
+
if (!Number.isFinite(builtMs)) {
|
|
72
|
+
return { state: 'unknown', lastBuiltAt: builtAtIso ?? null, lastChangedAt, behindMs: 0 };
|
|
73
|
+
}
|
|
74
|
+
const behindMs = newestMs > builtMs ? Math.round(newestMs - builtMs) : 0;
|
|
75
|
+
return {
|
|
76
|
+
state: behindMs > 0 ? 'stale' : 'fresh',
|
|
77
|
+
lastBuiltAt: builtAtIso ?? null,
|
|
78
|
+
lastChangedAt,
|
|
79
|
+
behindMs,
|
|
80
|
+
};
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shrkcrft/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.24",
|
|
4
4
|
"description": "SharkCraft CLI (`shrk`): structured project intelligence for AI coding agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SharkCraft contributors",
|
|
@@ -47,38 +47,38 @@
|
|
|
47
47
|
"typecheck": "tsc --noEmit -p tsconfig.json"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@shrkcrft/core": "^0.1.0-alpha.
|
|
51
|
-
"@shrkcrft/compress": "^0.1.0-alpha.
|
|
52
|
-
"@shrkcrft/config": "^0.1.0-alpha.
|
|
53
|
-
"@shrkcrft/workspace": "^0.1.0-alpha.
|
|
54
|
-
"@shrkcrft/knowledge": "^0.1.0-alpha.
|
|
55
|
-
"@shrkcrft/context": "^0.1.0-alpha.
|
|
56
|
-
"@shrkcrft/rules": "^0.1.0-alpha.
|
|
57
|
-
"@shrkcrft/paths": "^0.1.0-alpha.
|
|
58
|
-
"@shrkcrft/templates": "^0.1.0-alpha.
|
|
59
|
-
"@shrkcrft/plugin-api": "^0.1.0-alpha.
|
|
60
|
-
"@shrkcrft/dashboard": "^0.1.0-alpha.
|
|
61
|
-
"@shrkcrft/dashboard-api": "^0.1.0-alpha.
|
|
62
|
-
"@shrkcrft/pipelines": "^0.1.0-alpha.
|
|
63
|
-
"@shrkcrft/presets": "^0.1.0-alpha.
|
|
64
|
-
"@shrkcrft/boundaries": "^0.1.0-alpha.
|
|
65
|
-
"@shrkcrft/graph": "^0.1.0-alpha.
|
|
66
|
-
"@shrkcrft/rule-graph": "^0.1.0-alpha.
|
|
67
|
-
"@shrkcrft/structural-search": "^0.1.0-alpha.
|
|
68
|
-
"@shrkcrft/impact-engine": "^0.1.0-alpha.
|
|
69
|
-
"@shrkcrft/context-planner": "^0.1.0-alpha.
|
|
70
|
-
"@shrkcrft/architecture-guard": "^0.1.0-alpha.
|
|
71
|
-
"@shrkcrft/framework-scanners": "^0.1.0-alpha.
|
|
72
|
-
"@shrkcrft/api-surface-diff": "^0.1.0-alpha.
|
|
73
|
-
"@shrkcrft/quality-gates": "^0.1.0-alpha.
|
|
74
|
-
"@shrkcrft/migrate": "^0.1.0-alpha.
|
|
75
|
-
"@shrkcrft/generator": "^0.1.0-alpha.
|
|
76
|
-
"@shrkcrft/importer": "^0.1.0-alpha.
|
|
77
|
-
"@shrkcrft/inspector": "^0.1.0-alpha.
|
|
78
|
-
"@shrkcrft/ai": "^0.1.0-alpha.
|
|
79
|
-
"@shrkcrft/embeddings": "^0.1.0-alpha.
|
|
80
|
-
"@shrkcrft/shared": "^0.1.0-alpha.
|
|
81
|
-
"@shrkcrft/mcp-server": "^0.1.0-alpha.
|
|
50
|
+
"@shrkcrft/core": "^0.1.0-alpha.24",
|
|
51
|
+
"@shrkcrft/compress": "^0.1.0-alpha.24",
|
|
52
|
+
"@shrkcrft/config": "^0.1.0-alpha.24",
|
|
53
|
+
"@shrkcrft/workspace": "^0.1.0-alpha.24",
|
|
54
|
+
"@shrkcrft/knowledge": "^0.1.0-alpha.24",
|
|
55
|
+
"@shrkcrft/context": "^0.1.0-alpha.24",
|
|
56
|
+
"@shrkcrft/rules": "^0.1.0-alpha.24",
|
|
57
|
+
"@shrkcrft/paths": "^0.1.0-alpha.24",
|
|
58
|
+
"@shrkcrft/templates": "^0.1.0-alpha.24",
|
|
59
|
+
"@shrkcrft/plugin-api": "^0.1.0-alpha.24",
|
|
60
|
+
"@shrkcrft/dashboard": "^0.1.0-alpha.24",
|
|
61
|
+
"@shrkcrft/dashboard-api": "^0.1.0-alpha.24",
|
|
62
|
+
"@shrkcrft/pipelines": "^0.1.0-alpha.24",
|
|
63
|
+
"@shrkcrft/presets": "^0.1.0-alpha.24",
|
|
64
|
+
"@shrkcrft/boundaries": "^0.1.0-alpha.24",
|
|
65
|
+
"@shrkcrft/graph": "^0.1.0-alpha.24",
|
|
66
|
+
"@shrkcrft/rule-graph": "^0.1.0-alpha.24",
|
|
67
|
+
"@shrkcrft/structural-search": "^0.1.0-alpha.24",
|
|
68
|
+
"@shrkcrft/impact-engine": "^0.1.0-alpha.24",
|
|
69
|
+
"@shrkcrft/context-planner": "^0.1.0-alpha.24",
|
|
70
|
+
"@shrkcrft/architecture-guard": "^0.1.0-alpha.24",
|
|
71
|
+
"@shrkcrft/framework-scanners": "^0.1.0-alpha.24",
|
|
72
|
+
"@shrkcrft/api-surface-diff": "^0.1.0-alpha.24",
|
|
73
|
+
"@shrkcrft/quality-gates": "^0.1.0-alpha.24",
|
|
74
|
+
"@shrkcrft/migrate": "^0.1.0-alpha.24",
|
|
75
|
+
"@shrkcrft/generator": "^0.1.0-alpha.24",
|
|
76
|
+
"@shrkcrft/importer": "^0.1.0-alpha.24",
|
|
77
|
+
"@shrkcrft/inspector": "^0.1.0-alpha.24",
|
|
78
|
+
"@shrkcrft/ai": "^0.1.0-alpha.24",
|
|
79
|
+
"@shrkcrft/embeddings": "^0.1.0-alpha.24",
|
|
80
|
+
"@shrkcrft/shared": "^0.1.0-alpha.24",
|
|
81
|
+
"@shrkcrft/mcp-server": "^0.1.0-alpha.24",
|
|
82
82
|
"@huggingface/transformers": "^3.7.5"
|
|
83
83
|
},
|
|
84
84
|
"publishConfig": {
|