@skill-map/cli 0.68.1 → 0.69.0
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/cli/tutorial/sm-tutorial/references/_core.md +15 -6
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.json +70 -70
- package/dist/cli/tutorial/sm-tutorial/references/_manifest.yml +38 -38
- package/dist/cli/tutorial/sm-tutorial/references/fixtures.md +3 -3
- package/dist/cli/tutorial/sm-tutorial/references/part-authoring.md +25 -8
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-daily.md +77 -29
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-fundamentals.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-basic-kickoff.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-cli.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-daily-loop.md +77 -31
- package/dist/cli/tutorial/sm-tutorial/references/part-fundamentals.md +3 -3
- package/dist/cli/tutorial/sm-tutorial/references/part-plugins.md +1 -1
- package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +2 -2
- package/dist/cli/tutorial/sm-tutorial/references/part-settings.md +2 -2
- package/dist/cli.js +699 -326
- package/dist/conformance/index.js +3 -3
- package/dist/index.js +11 -10
- package/dist/kernel/index.d.ts +27 -17
- package/dist/kernel/index.js +11 -10
- package/dist/migrations/001_initial.sql +7 -3
- package/dist/ui/chunk-E7GLGHVY.js +1 -0
- package/dist/ui/chunk-RLRSNHYG.js +3 -0
- package/dist/ui/{chunk-22EQLC23.js → chunk-RRRXQNG6.js} +1 -1
- package/dist/ui/{chunk-K3ZRQNN5.js → chunk-SI4MGFOW.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/dist/ui/{main-R7BIU4HU.js → main-23NGLEUB.js} +3 -3
- package/migrations/001_initial.sql +7 -3
- package/package.json +2 -2
- package/dist/ui/chunk-PU5OP5RN.js +0 -1
- package/dist/ui/chunk-TLMV4LOQ.js +0 -3
- /package/dist/ui/{chunk-KMHXNOFZ.js → chunk-SXSNTF26.js} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// cli/entry.ts
|
|
2
2
|
|
|
3
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="75d0c2c2-d08f-5d7c-aa62-3e1d53dd4ef1")}catch(e){}}();
|
|
4
4
|
import { existsSync as existsSync34 } from "fs";
|
|
5
5
|
import { Builtins, Cli as Cli2 } from "clipanion";
|
|
6
6
|
|
|
@@ -250,7 +250,7 @@ function bucketByKind(kind, instance, bag) {
|
|
|
250
250
|
// package.json
|
|
251
251
|
var package_default = {
|
|
252
252
|
name: "@skill-map/cli",
|
|
253
|
-
version: "0.
|
|
253
|
+
version: "0.69.0",
|
|
254
254
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
255
255
|
license: "MIT",
|
|
256
256
|
type: "module",
|
|
@@ -5551,7 +5551,8 @@ var defaults_default = {
|
|
|
5551
5551
|
// kernel/config/loader.ts
|
|
5552
5552
|
var PROJECT_LOCAL_ONLY_KEYS = /* @__PURE__ */ new Set([
|
|
5553
5553
|
"allowEditSmFiles",
|
|
5554
|
-
"scan.referencePaths"
|
|
5554
|
+
"scan.referencePaths",
|
|
5555
|
+
"pluginTrust.projectEnabled"
|
|
5555
5556
|
]);
|
|
5556
5557
|
var DEFAULTS = defaults_default;
|
|
5557
5558
|
function loadConfig(opts) {
|
|
@@ -5832,7 +5833,8 @@ function enumerateConfigPaths(obj, prefix = "") {
|
|
|
5832
5833
|
|
|
5833
5834
|
// core/config/helper.ts
|
|
5834
5835
|
var PRIVACY_SENSITIVE_KEYS = /* @__PURE__ */ new Set([
|
|
5835
|
-
"scan.referencePaths"
|
|
5836
|
+
"scan.referencePaths",
|
|
5837
|
+
"pluginTrust.projectEnabled"
|
|
5836
5838
|
]);
|
|
5837
5839
|
var ProjectLocalOnlyKeyError = class extends Error {
|
|
5838
5840
|
constructor(key) {
|
|
@@ -5919,6 +5921,14 @@ function projectPathExposure(inputs) {
|
|
|
5919
5921
|
if (exposed.length === 0) return empty;
|
|
5920
5922
|
return { expandsSurface: true, exposedPaths: exposed };
|
|
5921
5923
|
}
|
|
5924
|
+
function projectTrustExposure(inputs) {
|
|
5925
|
+
if (inputs.value !== true) return { expandsSurface: false };
|
|
5926
|
+
const before = readConfigValue("pluginTrust.projectEnabled", {
|
|
5927
|
+
cwd: inputs.cwd,
|
|
5928
|
+
default: false
|
|
5929
|
+
}) ?? false;
|
|
5930
|
+
return { expandsSurface: before !== true };
|
|
5931
|
+
}
|
|
5922
5932
|
function resolveScanPathForExposure(raw, cwd) {
|
|
5923
5933
|
if (raw.startsWith("~/")) return resolve7(join4(osHomedir(), raw.slice(2)));
|
|
5924
5934
|
if (raw === "~") return resolve7(osHomedir());
|
|
@@ -7567,40 +7577,38 @@ function formatMigrationName(m) {
|
|
|
7567
7577
|
}
|
|
7568
7578
|
|
|
7569
7579
|
// kernel/adapters/sqlite/plugins.ts
|
|
7570
|
-
async function
|
|
7580
|
+
async function setPluginTrusted(db, pluginId, trusted, now = Date.now()) {
|
|
7571
7581
|
await db.insertInto("config_plugins").values({
|
|
7572
7582
|
pluginId,
|
|
7573
|
-
|
|
7574
|
-
configJson: null,
|
|
7583
|
+
trusted: trusted ? 1 : 0,
|
|
7575
7584
|
updatedAt: now
|
|
7576
7585
|
}).onConflict(
|
|
7577
7586
|
(oc) => oc.column("pluginId").doUpdateSet({
|
|
7578
|
-
|
|
7587
|
+
trusted: trusted ? 1 : 0,
|
|
7579
7588
|
updatedAt: now
|
|
7580
7589
|
})
|
|
7581
7590
|
).execute();
|
|
7582
7591
|
}
|
|
7583
|
-
async function
|
|
7584
|
-
const row = await db.selectFrom("config_plugins").select(["
|
|
7592
|
+
async function getPluginTrusted(db, pluginId) {
|
|
7593
|
+
const row = await db.selectFrom("config_plugins").select(["trusted"]).where("pluginId", "=", pluginId).executeTakeFirst();
|
|
7585
7594
|
if (!row) return void 0;
|
|
7586
|
-
return row.
|
|
7595
|
+
return row.trusted === 1;
|
|
7587
7596
|
}
|
|
7588
|
-
async function
|
|
7589
|
-
const rows = await db.selectFrom("config_plugins").select(["pluginId", "
|
|
7597
|
+
async function listPluginTrust(db) {
|
|
7598
|
+
const rows = await db.selectFrom("config_plugins").select(["pluginId", "trusted", "updatedAt"]).orderBy("pluginId", "asc").execute();
|
|
7590
7599
|
return rows.map((r) => ({
|
|
7591
7600
|
pluginId: r.pluginId,
|
|
7592
|
-
|
|
7593
|
-
configJson: r.configJson,
|
|
7601
|
+
trusted: r.trusted === 1,
|
|
7594
7602
|
updatedAt: r.updatedAt
|
|
7595
7603
|
}));
|
|
7596
7604
|
}
|
|
7597
|
-
async function
|
|
7605
|
+
async function deletePluginTrust(db, pluginId) {
|
|
7598
7606
|
await db.deleteFrom("config_plugins").where("pluginId", "=", pluginId).execute();
|
|
7599
7607
|
}
|
|
7600
|
-
async function
|
|
7601
|
-
const rows = await
|
|
7608
|
+
async function loadPluginTrustMap(db) {
|
|
7609
|
+
const rows = await listPluginTrust(db);
|
|
7602
7610
|
const out = /* @__PURE__ */ new Map();
|
|
7603
|
-
for (const row of rows) out.set(row.pluginId, row.
|
|
7611
|
+
for (const row of rows) out.set(row.pluginId, row.trusted);
|
|
7604
7612
|
return out;
|
|
7605
7613
|
}
|
|
7606
7614
|
|
|
@@ -8755,7 +8763,7 @@ var SqliteStorageAdapter = class {
|
|
|
8755
8763
|
jobs;
|
|
8756
8764
|
favorites;
|
|
8757
8765
|
preferences;
|
|
8758
|
-
|
|
8766
|
+
trust;
|
|
8759
8767
|
migrations;
|
|
8760
8768
|
pluginMigrations;
|
|
8761
8769
|
constructor(options) {
|
|
@@ -8872,12 +8880,12 @@ var SqliteStorageAdapter = class {
|
|
|
8872
8880
|
loadUpdateCheckCache: () => loadUpdateCheckCache(this.db),
|
|
8873
8881
|
saveUpdateCheckCache: (cache) => saveUpdateCheckCache(this.db, cache)
|
|
8874
8882
|
};
|
|
8875
|
-
this.
|
|
8876
|
-
set: (pluginId,
|
|
8877
|
-
get: (pluginId) =>
|
|
8878
|
-
list: () =>
|
|
8879
|
-
delete: (pluginId) =>
|
|
8880
|
-
|
|
8883
|
+
this.trust = {
|
|
8884
|
+
set: (pluginId, trusted) => setPluginTrusted(this.db, pluginId, trusted),
|
|
8885
|
+
get: (pluginId) => getPluginTrusted(this.db, pluginId),
|
|
8886
|
+
list: () => listPluginTrust(this.db),
|
|
8887
|
+
delete: (pluginId) => deletePluginTrust(this.db, pluginId),
|
|
8888
|
+
loadTrustMap: () => loadPluginTrustMap(this.db)
|
|
8881
8889
|
};
|
|
8882
8890
|
const path = this.#options.databasePath;
|
|
8883
8891
|
this.migrations = {
|
|
@@ -10064,21 +10072,22 @@ var PLUGIN_LOADER_TEXTS = {
|
|
|
10064
10072
|
// schema. Both are GitHub blob URLs.
|
|
10065
10073
|
invalidManifestExtensionShape: "{{relEntry}}: {{errors}}. See {{docUrl}}.",
|
|
10066
10074
|
importExceededTimeout: "import exceeded {{timeoutMs}}ms; likely a top-level side effect (network call, infinite loop, large blocking work). Move side effects into the runtime methods (`detect` / `evaluate` / `render` / etc.).",
|
|
10067
|
-
disabledByConfig: "disabled by
|
|
10075
|
+
disabledByConfig: "disabled by settings.json (plugins.<id>.enabled)",
|
|
10068
10076
|
/**
|
|
10069
10077
|
* Reason stamped on a project-local disk plugin discovered but not
|
|
10070
|
-
* imported because the operator never granted local trust.
|
|
10071
|
-
* from `disabledByConfig` (an explicit toggle-off
|
|
10072
|
-
*
|
|
10073
|
-
* `
|
|
10078
|
+
* imported because the operator never granted local import trust.
|
|
10079
|
+
* Distinct from `disabledByConfig` (an explicit operational toggle-off
|
|
10080
|
+
* in the config layers): this id is enabled but carries no
|
|
10081
|
+
* `config_plugins` trust grant, so its code stays unexecuted until
|
|
10082
|
+
* `sm plugins trust` records local consent.
|
|
10074
10083
|
*/
|
|
10075
|
-
untrustedNotLoaded: "not loaded: project-local plugin is
|
|
10084
|
+
untrustedNotLoaded: "not loaded: project-local plugin is enabled but not trusted on this machine. Run `sm plugins trust {{pluginId}}` to load it.",
|
|
10076
10085
|
/**
|
|
10077
10086
|
* One-time aggregate notice the runtime emits when project-local
|
|
10078
10087
|
* plugins were found on disk but left unloaded for lack of trust. The
|
|
10079
10088
|
* `{{count}}` plugins ride the scan without executing any code.
|
|
10080
10089
|
*/
|
|
10081
|
-
untrustedPluginsFoundNotice: "{{count}} project-local plugin(s) found in .skill-map/plugins/ but not loaded (untrusted). Their code did NOT run. Review with `sm plugins list`, then
|
|
10090
|
+
untrustedPluginsFoundNotice: "{{count}} project-local plugin(s) found in .skill-map/plugins/ but not loaded (untrusted). Their code did NOT run. Review with `sm plugins list`, then trust any you vetted with `sm plugins trust <id>`.",
|
|
10082
10091
|
invalidManifestDirMismatch: "directory name '{{dirName}}' does not match manifest id '{{manifestId}}'. Rename the directory to match the id, or update the manifest id to match the directory.",
|
|
10083
10092
|
idCollision: "Plugin '{{id}}' at {{pathA}} collides with the plugin at {{pathB}}. Rename one and rerun.",
|
|
10084
10093
|
loadErrorPluginIdMismatch: "{{relEntry}}: extension declares pluginId '{{declared}}' but its plugin.json declares id '{{manifestId}}'. Remove the explicit pluginId from the extension; the loader injects it from plugin.json#/id.",
|
|
@@ -11031,26 +11040,33 @@ var SHIPS_DISABLED = /* @__PURE__ */ new Set([
|
|
|
11031
11040
|
function installedDefaultEnabled(stability) {
|
|
11032
11041
|
return stability === void 0 || !SHIPS_DISABLED.has(stability);
|
|
11033
11042
|
}
|
|
11034
|
-
function resolvePluginEnabled(pluginId, cfg,
|
|
11043
|
+
function resolvePluginEnabled(pluginId, cfg, installedDefault = true) {
|
|
11035
11044
|
if (isPluginLocked(pluginId)) return true;
|
|
11036
|
-
|
|
11045
|
+
const slash = pluginId.indexOf("/");
|
|
11046
|
+
if (slash >= 0) {
|
|
11047
|
+
return resolveQualifiedEnabled(
|
|
11048
|
+
pluginId.slice(0, slash),
|
|
11049
|
+
pluginId.slice(slash + 1),
|
|
11050
|
+
cfg,
|
|
11051
|
+
installedDefault
|
|
11052
|
+
);
|
|
11053
|
+
}
|
|
11037
11054
|
const settingsEntry = cfg.plugins[pluginId];
|
|
11038
11055
|
if (settingsEntry?.enabled !== void 0) return settingsEntry.enabled;
|
|
11039
11056
|
return installedDefault;
|
|
11040
11057
|
}
|
|
11041
|
-
function
|
|
11042
|
-
|
|
11058
|
+
function resolveQualifiedEnabled(plugin, ext, cfg, installedDefault) {
|
|
11059
|
+
const pluginEntry = cfg.plugins[plugin];
|
|
11060
|
+
const perExt = pluginEntry?.extensions?.[ext]?.enabled;
|
|
11061
|
+
if (perExt !== void 0) return perExt;
|
|
11062
|
+
if (pluginEntry?.enabled !== void 0) return pluginEntry.enabled;
|
|
11063
|
+
return installedDefault;
|
|
11043
11064
|
}
|
|
11044
|
-
function
|
|
11045
|
-
return (pluginId) =>
|
|
11046
|
-
|
|
11047
|
-
|
|
11048
|
-
|
|
11049
|
-
if (!enabled) continue;
|
|
11050
|
-
if (key === pluginId || key.startsWith(prefix)) return true;
|
|
11051
|
-
}
|
|
11052
|
-
return false;
|
|
11053
|
-
};
|
|
11065
|
+
function makeEnabledResolver(cfg) {
|
|
11066
|
+
return (pluginId, installedDefault) => resolvePluginEnabled(pluginId, cfg, installedDefault);
|
|
11067
|
+
}
|
|
11068
|
+
function makeTrustResolver(trustMap, trustProjectEnabled) {
|
|
11069
|
+
return (pluginId) => isPluginLocked(pluginId) || trustMap.get(pluginId) === true || trustProjectEnabled;
|
|
11054
11070
|
}
|
|
11055
11071
|
|
|
11056
11072
|
// core/runtime/plugin-runtime/resolver.ts
|
|
@@ -11075,11 +11091,15 @@ async function buildResolverInputs(ctx) {
|
|
|
11075
11091
|
db: void 0,
|
|
11076
11092
|
...ctx
|
|
11077
11093
|
});
|
|
11078
|
-
const
|
|
11094
|
+
const trustMap = await tryWithSqlite(
|
|
11079
11095
|
{ databasePath: dbPath, autoBackup: false },
|
|
11080
|
-
(adapter) => adapter.
|
|
11096
|
+
(adapter) => adapter.trust.loadTrustMap()
|
|
11081
11097
|
) ?? /* @__PURE__ */ new Map();
|
|
11082
|
-
return {
|
|
11098
|
+
return {
|
|
11099
|
+
resolveEnabled: makeEnabledResolver(cfg),
|
|
11100
|
+
trustMap,
|
|
11101
|
+
trustProjectEnabled: cfg.pluginTrust?.projectEnabled ?? false
|
|
11102
|
+
};
|
|
11083
11103
|
}
|
|
11084
11104
|
|
|
11085
11105
|
// kernel/scan/walk-content.ts
|
|
@@ -11616,11 +11636,13 @@ async function loadPluginRuntime(opts = {}) {
|
|
|
11616
11636
|
const searchPaths = resolveSearchPaths(opts, ctx);
|
|
11617
11637
|
const validators = loadSchemaValidators();
|
|
11618
11638
|
let resolveEnabled;
|
|
11619
|
-
let
|
|
11639
|
+
let trustMap;
|
|
11640
|
+
let trustProjectEnabled;
|
|
11620
11641
|
try {
|
|
11621
11642
|
const inputs = await buildResolverInputs(ctx);
|
|
11622
11643
|
resolveEnabled = inputs.resolveEnabled;
|
|
11623
|
-
|
|
11644
|
+
trustMap = inputs.trustMap;
|
|
11645
|
+
trustProjectEnabled = inputs.trustProjectEnabled;
|
|
11624
11646
|
} catch {
|
|
11625
11647
|
}
|
|
11626
11648
|
const loaderOpts = {
|
|
@@ -11630,7 +11652,10 @@ async function loadPluginRuntime(opts = {}) {
|
|
|
11630
11652
|
};
|
|
11631
11653
|
if (resolveEnabled) loaderOpts.resolveEnabled = resolveEnabled;
|
|
11632
11654
|
if (!opts.pluginDir) {
|
|
11633
|
-
loaderOpts.resolveImportTrust =
|
|
11655
|
+
loaderOpts.resolveImportTrust = makeTrustResolver(
|
|
11656
|
+
trustMap ?? /* @__PURE__ */ new Map(),
|
|
11657
|
+
trustProjectEnabled ?? false
|
|
11658
|
+
);
|
|
11634
11659
|
}
|
|
11635
11660
|
const loader = createPluginLoader(loaderOpts);
|
|
11636
11661
|
const discovered = await loader.discoverAndLoadAll();
|
|
@@ -12269,6 +12294,18 @@ var CONFIG_TEXTS = {
|
|
|
12269
12294
|
* screen what they just opted into.
|
|
12270
12295
|
*/
|
|
12271
12296
|
privacyGateConfirmed: '{{glyph}} Opening disk access for "{{key}}":\n{{paths}}\n',
|
|
12297
|
+
/**
|
|
12298
|
+
* Surfaced when `sm config set pluginTrust.projectEnabled true` is run
|
|
12299
|
+
* without `--yes`. Turning the opt-in on expands the LOCAL
|
|
12300
|
+
* code-execution surface (every plugin the project enables becomes
|
|
12301
|
+
* trusted), so the verb refuses without confirmation.
|
|
12302
|
+
*/
|
|
12303
|
+
trustGateRequired: '{{glyph}} sm config: setting "pluginTrust.projectEnabled" to true trusts every plugin this project enables.\n Their code may then import and run on this machine without a per-plugin trust grant.\n {{hint}}\n',
|
|
12304
|
+
trustGateRequiredHint: "Rerun with --yes to confirm. Turning it off needs no flag. Prefer per-plugin `sm plugins trust <id>` for narrower consent.",
|
|
12305
|
+
/**
|
|
12306
|
+
* Receipt printed when the trust gate has been confirmed via `--yes`.
|
|
12307
|
+
*/
|
|
12308
|
+
trustGateConfirmed: "{{glyph}} Local plugin trust opt-in enabled: every plugin this project enables is now trusted on this machine.\n",
|
|
12272
12309
|
/**
|
|
12273
12310
|
* Confirmation printed after `sm config set activeProvider <id>`
|
|
12274
12311
|
* succeeds. The lens change atomically drops the scan_* zone (per
|
|
@@ -12665,7 +12702,7 @@ var ConfigSetCommand = class extends SmCommand {
|
|
|
12665
12702
|
key = Option4.String({ required: true });
|
|
12666
12703
|
value = Option4.String({ required: true });
|
|
12667
12704
|
yes = Option4.Boolean("--yes", false, {
|
|
12668
|
-
description: "Confirm a
|
|
12705
|
+
description: "Confirm a surface-expanding write: disk access outside the project (scan.referencePaths) or blanket local plugin trust (pluginTrust.projectEnabled)."
|
|
12669
12706
|
});
|
|
12670
12707
|
// CLI orchestrator: each branch is one validation gate (forbidden
|
|
12671
12708
|
// segment / privacy guard / schema violation) or output dispatch.
|
|
@@ -12678,32 +12715,12 @@ var ConfigSetCommand = class extends SmCommand {
|
|
|
12678
12715
|
const stderrAnsi = this.ansiFor("stderr");
|
|
12679
12716
|
const errGlyph = stderrAnsi.red("\u2715");
|
|
12680
12717
|
const value = parseCliValue(this.value);
|
|
12681
|
-
if (
|
|
12682
|
-
const
|
|
12683
|
-
|
|
12684
|
-
|
|
12685
|
-
|
|
12686
|
-
|
|
12687
|
-
if (exposure.expandsSurface && !this.yes) {
|
|
12688
|
-
this.printer.info(
|
|
12689
|
-
tx(CONFIG_TEXTS.privacyGateRequired, {
|
|
12690
|
-
glyph: errGlyph,
|
|
12691
|
-
key: this.key,
|
|
12692
|
-
paths: exposure.exposedPaths.map((p) => ` - ${p}`).join("\n"),
|
|
12693
|
-
hint: stderrAnsi.dim(CONFIG_TEXTS.privacyGateRequiredHint)
|
|
12694
|
-
})
|
|
12695
|
-
);
|
|
12696
|
-
return ExitCode.Error;
|
|
12697
|
-
}
|
|
12698
|
-
if (exposure.expandsSurface) {
|
|
12699
|
-
this.printer.info(
|
|
12700
|
-
tx(CONFIG_TEXTS.privacyGateConfirmed, {
|
|
12701
|
-
glyph: stderrAnsi.dim("\u24D8"),
|
|
12702
|
-
key: this.key,
|
|
12703
|
-
paths: exposure.exposedPaths.map((p) => ` - ${p}`).join("\n")
|
|
12704
|
-
})
|
|
12705
|
-
);
|
|
12706
|
-
}
|
|
12718
|
+
if (this.key === "pluginTrust.projectEnabled") {
|
|
12719
|
+
const trustGate = this.#applyTrustGate(value, ctx.cwd, errGlyph, stderrAnsi);
|
|
12720
|
+
if (trustGate !== null) return trustGate;
|
|
12721
|
+
} else if (PRIVACY_SENSITIVE_KEYS.has(this.key)) {
|
|
12722
|
+
const pathGate = this.#applyPathGate(value, ctx.cwd, errGlyph, stderrAnsi);
|
|
12723
|
+
if (pathGate !== null) return pathGate;
|
|
12707
12724
|
}
|
|
12708
12725
|
if (this.key === "activeProvider" && typeof value === "string") {
|
|
12709
12726
|
const known = new Set(builtIns().providers.map((p) => p.id));
|
|
@@ -12781,6 +12798,58 @@ var ConfigSetCommand = class extends SmCommand {
|
|
|
12781
12798
|
}
|
|
12782
12799
|
return ExitCode.Ok;
|
|
12783
12800
|
}
|
|
12801
|
+
/**
|
|
12802
|
+
* Disk-access privacy gate for `scan.referencePaths`-style keys.
|
|
12803
|
+
* Returns an exit code to bail with (gate refused) or `null` to
|
|
12804
|
+
* proceed. On a confirmed (`--yes`) expansion it prints the receipt
|
|
12805
|
+
* and returns `null`.
|
|
12806
|
+
*/
|
|
12807
|
+
#applyPathGate(value, cwd, errGlyph, stderrAnsi) {
|
|
12808
|
+
const exposure = projectPathExposure({ key: this.key, value, cwd });
|
|
12809
|
+
if (!exposure.expandsSurface) return null;
|
|
12810
|
+
if (!this.yes) {
|
|
12811
|
+
this.printer.info(
|
|
12812
|
+
tx(CONFIG_TEXTS.privacyGateRequired, {
|
|
12813
|
+
glyph: errGlyph,
|
|
12814
|
+
key: this.key,
|
|
12815
|
+
paths: exposure.exposedPaths.map((p) => ` - ${p}`).join("\n"),
|
|
12816
|
+
hint: stderrAnsi.dim(CONFIG_TEXTS.privacyGateRequiredHint)
|
|
12817
|
+
})
|
|
12818
|
+
);
|
|
12819
|
+
return ExitCode.Error;
|
|
12820
|
+
}
|
|
12821
|
+
this.printer.info(
|
|
12822
|
+
tx(CONFIG_TEXTS.privacyGateConfirmed, {
|
|
12823
|
+
glyph: stderrAnsi.dim("\u24D8"),
|
|
12824
|
+
key: this.key,
|
|
12825
|
+
paths: exposure.exposedPaths.map((p) => ` - ${p}`).join("\n")
|
|
12826
|
+
})
|
|
12827
|
+
);
|
|
12828
|
+
return null;
|
|
12829
|
+
}
|
|
12830
|
+
/**
|
|
12831
|
+
* Code-execution-surface gate for `pluginTrust.projectEnabled`.
|
|
12832
|
+
* Turning the local opt-in ON trusts every plugin the project enables,
|
|
12833
|
+
* so it requires `--yes`. Returns an exit code to bail with, or `null`
|
|
12834
|
+
* to proceed (on a confirmed expansion it prints the receipt).
|
|
12835
|
+
*/
|
|
12836
|
+
#applyTrustGate(value, cwd, errGlyph, stderrAnsi) {
|
|
12837
|
+
const exposure = projectTrustExposure({ value, cwd });
|
|
12838
|
+
if (!exposure.expandsSurface) return null;
|
|
12839
|
+
if (!this.yes) {
|
|
12840
|
+
this.printer.info(
|
|
12841
|
+
tx(CONFIG_TEXTS.trustGateRequired, {
|
|
12842
|
+
glyph: errGlyph,
|
|
12843
|
+
hint: stderrAnsi.dim(CONFIG_TEXTS.trustGateRequiredHint)
|
|
12844
|
+
})
|
|
12845
|
+
);
|
|
12846
|
+
return ExitCode.Error;
|
|
12847
|
+
}
|
|
12848
|
+
this.printer.info(
|
|
12849
|
+
tx(CONFIG_TEXTS.trustGateConfirmed, { glyph: stderrAnsi.dim("\u24D8") })
|
|
12850
|
+
);
|
|
12851
|
+
return null;
|
|
12852
|
+
}
|
|
12784
12853
|
/**
|
|
12785
12854
|
* Side effect of `sm config set activeProvider <id>`, atomically
|
|
12786
12855
|
* drops the `scan_*` zone so the persisted graph never reflects the
|
|
@@ -13101,7 +13170,7 @@ function grantFixturePluginTrust(scope, binary, env) {
|
|
|
13101
13170
|
const db = new DatabaseSync7(dbPath);
|
|
13102
13171
|
try {
|
|
13103
13172
|
const stmt = db.prepare(
|
|
13104
|
-
"INSERT INTO config_plugins (plugin_id,
|
|
13173
|
+
"INSERT INTO config_plugins (plugin_id, trusted, updated_at) VALUES (?, 1, 0) ON CONFLICT(plugin_id) DO UPDATE SET trusted = 1"
|
|
13105
13174
|
);
|
|
13106
13175
|
for (const id of ids) stmt.run(id);
|
|
13107
13176
|
} finally {
|
|
@@ -21780,6 +21849,23 @@ var PLUGINS_TEXTS = {
|
|
|
21780
21849
|
toggleAppliedSingle: "{{verbPast}}: {{id}}\n",
|
|
21781
21850
|
toggleAppliedManyHeader: "{{verbPast}}: {{count}} extension(s)\n",
|
|
21782
21851
|
toggleAppliedManyRow: " - {{id}}\n",
|
|
21852
|
+
// --- trust / untrust -------------------------------------------------
|
|
21853
|
+
/**
|
|
21854
|
+
* Receipt printed after `sm plugins trust|untrust`. `verbPast` is
|
|
21855
|
+
* `trusted` / `untrusted`. Trust is per-plugin (bare id), so the rows
|
|
21856
|
+
* carry plugin ids, not qualified extension ids.
|
|
21857
|
+
*/
|
|
21858
|
+
trustAppliedSingle: "{{verbPast}}: {{id}}\n",
|
|
21859
|
+
trustAppliedManyHeader: "{{verbPast}}: {{count}} plugin(s)\n",
|
|
21860
|
+
trustAppliedManyRow: " - {{id}}\n",
|
|
21861
|
+
/**
|
|
21862
|
+
* Rejection when a trust verb targets a built-in (or host-locked) id.
|
|
21863
|
+
* Those are never import-trust-gated, so a trust grant is meaningless.
|
|
21864
|
+
*/
|
|
21865
|
+
trustBuiltInRejected: '{{glyph}} Plugin "{{id}}" is a built-in (or host-locked) and is never import-trust-gated.\n {{hint}}\n',
|
|
21866
|
+
trustBuiltInRejectedHint: "Import trust applies only to project-local drop-in plugins under .skill-map/plugins/.",
|
|
21867
|
+
/** `--all` found no project-local drop-in plugins to act on. */
|
|
21868
|
+
trustNoPlugins: "No project-local plugins discovered to {{verb}}.\n",
|
|
21783
21869
|
/**
|
|
21784
21870
|
* Macro expansion summary printed on stderr before the confirm
|
|
21785
21871
|
* prompt (or before the `--yes` rejection). The block lists every
|
|
@@ -21911,7 +21997,7 @@ var PLUGINS_TEXTS = {
|
|
|
21911
21997
|
* Success block printed after scaffolding. Kind-agnostic (the main stub
|
|
21912
21998
|
* path is interpolated). Follows the no-em-dash rule across every line.
|
|
21913
21999
|
*/
|
|
21914
|
-
createSuccess: "Created {{targetDir}}\nNext:\n - Edit {{mainFile}}\n - Run sm plugins doctor to confirm it loads\n - sm plugins slots list: browse slots and input-types\n",
|
|
22000
|
+
createSuccess: "Created {{targetDir}}\nNext:\n - Edit {{mainFile}}\n - Run sm plugins doctor to confirm it loads\n - Run sm plugins trust {{pluginId}} to let its code run (project-local plugins are untrusted until you allow them)\n - sm plugins slots list: browse slots and input-types\n",
|
|
21915
22001
|
// --- slots list verb -------------------------------------------------
|
|
21916
22002
|
/** Section header for the view-slots catalogue. */
|
|
21917
22003
|
slotsListHeaderViewSlots: " View slots ({{count}})\n",
|
|
@@ -21953,12 +22039,7 @@ function resolveSearchPaths2(opts, cwd) {
|
|
|
21953
22039
|
async function buildResolver() {
|
|
21954
22040
|
const ctx = defaultRuntimeContext();
|
|
21955
22041
|
const { effective: cfg } = loadConfig({ cwd: ctx.cwd });
|
|
21956
|
-
|
|
21957
|
-
const dbOverrides = await tryWithSqlite(
|
|
21958
|
-
{ databasePath: dbPath, autoBackup: false },
|
|
21959
|
-
(adapter) => adapter.pluginConfig.loadOverrideMap()
|
|
21960
|
-
) ?? /* @__PURE__ */ new Map();
|
|
21961
|
-
return makeEnabledResolver(cfg, dbOverrides);
|
|
22042
|
+
return makeEnabledResolver(cfg);
|
|
21962
22043
|
}
|
|
21963
22044
|
async function loadAll(opts) {
|
|
21964
22045
|
const ctx = defaultRuntimeContext();
|
|
@@ -22954,6 +23035,9 @@ var TogglePluginsBase = class extends SmCommand {
|
|
|
22954
23035
|
yes = Option25.Boolean("--yes,-y", false, {
|
|
22955
23036
|
description: "Skip the interactive confirm when a bare plugin id (or --all) fans the toggle out across multiple extensions."
|
|
22956
23037
|
});
|
|
23038
|
+
local = Option25.Boolean("--local", false, {
|
|
23039
|
+
description: "Write the enable toggle to the gitignored settings.local.json (per-checkout) instead of the team-shared settings.json."
|
|
23040
|
+
});
|
|
22957
23041
|
ids = Option25.Rest({ name: "ids" });
|
|
22958
23042
|
async toggle(enabled) {
|
|
22959
23043
|
const verb = enabled ? "enable" : "disable";
|
|
@@ -23121,20 +23205,25 @@ var TogglePluginsBase = class extends SmCommand {
|
|
|
23121
23205
|
return ExitCode.NotFound;
|
|
23122
23206
|
}
|
|
23123
23207
|
/**
|
|
23124
|
-
* Persist every qualified id in
|
|
23125
|
-
*
|
|
23126
|
-
*
|
|
23127
|
-
*
|
|
23128
|
-
*
|
|
23208
|
+
* Persist the per-extension `enabled` toggle for every qualified id in
|
|
23209
|
+
* the config layers (`plugins.<plugin>.extensions.<ext>.enabled`),
|
|
23210
|
+
* targeting `settings.json` by default or `settings.local.json` with
|
|
23211
|
+
* `--local`. On disable, also purge the plugin's `scan_contributions`
|
|
23212
|
+
* rows immediately (matches the BFF route, see
|
|
23213
|
+
* `server/routes/plugins.ts:applyChangeToAdapter`). Every key is
|
|
23214
|
+
* `<plugin>/<ext>` shape so both the config dot-path and the
|
|
23215
|
+
* contribution purge split into `(pluginId, extensionId)` cleanly.
|
|
23129
23216
|
*/
|
|
23130
23217
|
async #persistKeys(keys, enabled) {
|
|
23131
23218
|
const ctx = defaultRuntimeContext();
|
|
23219
|
+
const target = this.local ? "project-local" : "project";
|
|
23220
|
+
for (const id of keys) {
|
|
23221
|
+
writeConfigValue(toEnableConfigKey(id), enabled, { target, cwd: ctx.cwd });
|
|
23222
|
+
}
|
|
23223
|
+
if (enabled) return;
|
|
23132
23224
|
const dbPath = resolveDbPath({ db: void 0, cwd: ctx.cwd });
|
|
23133
23225
|
await withSqlite({ databasePath: dbPath, autoBackup: false }, async (adapter) => {
|
|
23134
|
-
for (const id of keys)
|
|
23135
|
-
await adapter.pluginConfig.set(id, enabled);
|
|
23136
|
-
if (!enabled) await purgeContributionsFor(adapter, id);
|
|
23137
|
-
}
|
|
23226
|
+
for (const id of keys) await purgeContributionsFor(adapter, id);
|
|
23138
23227
|
});
|
|
23139
23228
|
}
|
|
23140
23229
|
#renderSuccess(keys, enabled) {
|
|
@@ -23175,17 +23264,23 @@ async function purgeContributionsFor(adapter, id) {
|
|
|
23175
23264
|
}
|
|
23176
23265
|
await adapter.contributions.purgeByPlugin(id.slice(0, slash), id.slice(slash + 1));
|
|
23177
23266
|
}
|
|
23267
|
+
function toEnableConfigKey(id) {
|
|
23268
|
+
const slash = id.indexOf("/");
|
|
23269
|
+
if (slash < 0) return `plugins.${id}.enabled`;
|
|
23270
|
+
return `plugins.${id.slice(0, slash)}.extensions.${id.slice(slash + 1)}.enabled`;
|
|
23271
|
+
}
|
|
23178
23272
|
var PluginsEnableCommand = class extends TogglePluginsBase {
|
|
23179
23273
|
static paths = [["plugins", "enable"]];
|
|
23180
23274
|
static usage = Command26.Usage({
|
|
23181
23275
|
category: "Plugins",
|
|
23182
|
-
description: "Enable one or more extensions (or --all). Persists in
|
|
23276
|
+
description: "Enable one or more extensions (or --all). Persists the per-extension enabled in the config layers.",
|
|
23183
23277
|
details: `
|
|
23184
|
-
Writes
|
|
23185
|
-
extension id
|
|
23186
|
-
|
|
23187
|
-
|
|
23188
|
-
|
|
23278
|
+
Writes plugins.<plugin>.extensions.<ext>.enabled=true per qualified
|
|
23279
|
+
extension id to the team-shared settings.json (or settings.local.json
|
|
23280
|
+
with --local). This is the OPERATIONAL axis only; it does NOT grant
|
|
23281
|
+
import trust for a project-local plugin (use sm plugins trust).
|
|
23282
|
+
Use sm plugins disable to flip; sm config reset
|
|
23283
|
+
plugins.<plugin>.extensions.<ext>.enabled drops the override.
|
|
23189
23284
|
|
|
23190
23285
|
Accepts qualified ids (\`claude/at-directive\`) and bare plugin
|
|
23191
23286
|
ids (\`claude\`, which fans the toggle out across every extension
|
|
@@ -23207,10 +23302,11 @@ var PluginsDisableCommand = class extends TogglePluginsBase {
|
|
|
23207
23302
|
static paths = [["plugins", "disable"]];
|
|
23208
23303
|
static usage = Command26.Usage({
|
|
23209
23304
|
category: "Plugins",
|
|
23210
|
-
description: "Disable one or more extensions (or --all). Persists in
|
|
23305
|
+
description: "Disable one or more extensions (or --all). Persists the per-extension enabled in the config layers; does not delete files.",
|
|
23211
23306
|
details: `
|
|
23212
|
-
Writes
|
|
23213
|
-
extension id
|
|
23307
|
+
Writes plugins.<plugin>.extensions.<ext>.enabled=false per qualified
|
|
23308
|
+
extension id to the team-shared settings.json (or settings.local.json
|
|
23309
|
+
with --local). Discovery still surfaces the plugin in
|
|
23214
23310
|
sm plugins list, but with status=disabled; the kernel will not
|
|
23215
23311
|
run any of its disabled extensions.
|
|
23216
23312
|
|
|
@@ -23259,10 +23355,176 @@ function resolveBareToggle(id, catalogue) {
|
|
|
23259
23355
|
};
|
|
23260
23356
|
}
|
|
23261
23357
|
|
|
23358
|
+
// cli/commands/plugins/trust.ts
|
|
23359
|
+
import { Command as Command27, Option as Option26 } from "clipanion";
|
|
23360
|
+
var TrustPluginsBase = class extends SmCommand {
|
|
23361
|
+
all = Option26.Boolean("--all", false);
|
|
23362
|
+
ids = Option26.Rest({ name: "ids" });
|
|
23363
|
+
async applyTrust(trusted) {
|
|
23364
|
+
const verb = trusted ? "trust" : "untrust";
|
|
23365
|
+
const stderrAnsi = this.ansiFor("stderr");
|
|
23366
|
+
const argError = this.#validateArgs(stderrAnsi, verb);
|
|
23367
|
+
if (argError !== null) return argError;
|
|
23368
|
+
const plugins = await loadAll({ pluginDir: void 0 });
|
|
23369
|
+
const discoveredIds = new Set(plugins.map((p) => p.id));
|
|
23370
|
+
const resolved = this.#resolvePluginIds(plugins, discoveredIds, verb, stderrAnsi);
|
|
23371
|
+
if (typeof resolved === "number") return resolved;
|
|
23372
|
+
if (resolved.length === 0) {
|
|
23373
|
+
this.printer.info(tx(PLUGINS_TEXTS.trustNoPlugins, { verb }));
|
|
23374
|
+
return ExitCode.Ok;
|
|
23375
|
+
}
|
|
23376
|
+
await this.#persist(resolved, trusted);
|
|
23377
|
+
this.#renderSuccess(resolved, trusted);
|
|
23378
|
+
return ExitCode.Ok;
|
|
23379
|
+
}
|
|
23380
|
+
/**
|
|
23381
|
+
* `--all` vs `<id>...` mutex check (one must be present, not both).
|
|
23382
|
+
* Reuses the toggle family's two-line rejection blocks so trust /
|
|
23383
|
+
* enable read in parallel.
|
|
23384
|
+
*/
|
|
23385
|
+
#validateArgs(ansi, verb) {
|
|
23386
|
+
const errGlyph = ansi.red("\u2715");
|
|
23387
|
+
if (this.all && this.ids.length > 0) {
|
|
23388
|
+
this.printer.error(
|
|
23389
|
+
tx(PLUGINS_TEXTS.toggleBothIdAndAll, {
|
|
23390
|
+
glyph: errGlyph,
|
|
23391
|
+
hint: ansi.dim(tx(PLUGINS_TEXTS.toggleBothIdAndAllHint, { verb }))
|
|
23392
|
+
})
|
|
23393
|
+
);
|
|
23394
|
+
return ExitCode.Error;
|
|
23395
|
+
}
|
|
23396
|
+
if (!this.all && this.ids.length === 0) {
|
|
23397
|
+
this.printer.error(
|
|
23398
|
+
tx(PLUGINS_TEXTS.toggleNeitherIdNorAll, {
|
|
23399
|
+
glyph: errGlyph,
|
|
23400
|
+
hint: ansi.dim(tx(PLUGINS_TEXTS.toggleNeitherIdNorAllHint, { verb }))
|
|
23401
|
+
})
|
|
23402
|
+
);
|
|
23403
|
+
return ExitCode.Error;
|
|
23404
|
+
}
|
|
23405
|
+
return null;
|
|
23406
|
+
}
|
|
23407
|
+
/**
|
|
23408
|
+
* Resolve `<id>...` (or `--all`) into the deduped set of BARE plugin
|
|
23409
|
+
* ids to write. A qualified `<plugin>/<ext>` collapses to its plugin.
|
|
23410
|
+
* The first unresolvable id (built-in / host-locked, or unknown)
|
|
23411
|
+
* aborts the whole batch before any write so the operator never lands
|
|
23412
|
+
* in a partial state.
|
|
23413
|
+
*/
|
|
23414
|
+
#resolvePluginIds(_plugins, discoveredIds, _verb, ansi) {
|
|
23415
|
+
if (this.all) {
|
|
23416
|
+
return [...discoveredIds];
|
|
23417
|
+
}
|
|
23418
|
+
const out = [];
|
|
23419
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23420
|
+
for (const rawId of this.ids) {
|
|
23421
|
+
const bare = collapseToPluginId(rawId);
|
|
23422
|
+
if (isBuiltInOrLocked(bare)) {
|
|
23423
|
+
this.printer.error(
|
|
23424
|
+
tx(PLUGINS_TEXTS.trustBuiltInRejected, {
|
|
23425
|
+
glyph: ansi.red("\u2715"),
|
|
23426
|
+
id: sanitizeForTerminal(bare),
|
|
23427
|
+
hint: ansi.dim(PLUGINS_TEXTS.trustBuiltInRejectedHint)
|
|
23428
|
+
})
|
|
23429
|
+
);
|
|
23430
|
+
return ExitCode.NotFound;
|
|
23431
|
+
}
|
|
23432
|
+
if (!discoveredIds.has(bare)) {
|
|
23433
|
+
this.printer.error(
|
|
23434
|
+
tx(PLUGINS_TEXTS.pluginNotFound, {
|
|
23435
|
+
glyph: ansi.red("\u2715"),
|
|
23436
|
+
id: sanitizeForTerminal(bare),
|
|
23437
|
+
hint: ansi.dim(PLUGINS_TEXTS.pluginNotFoundHint)
|
|
23438
|
+
})
|
|
23439
|
+
);
|
|
23440
|
+
return ExitCode.NotFound;
|
|
23441
|
+
}
|
|
23442
|
+
if (seen.has(bare)) continue;
|
|
23443
|
+
seen.add(bare);
|
|
23444
|
+
out.push(bare);
|
|
23445
|
+
}
|
|
23446
|
+
return out;
|
|
23447
|
+
}
|
|
23448
|
+
/**
|
|
23449
|
+
* Write the trust grant for every resolved bare plugin id. Single
|
|
23450
|
+
* SQLite open for the whole batch. `trusted` true grants import trust,
|
|
23451
|
+
* false revokes it (the next scan / restart reverts the plugin to
|
|
23452
|
+
* discovered-but-unexecuted).
|
|
23453
|
+
*/
|
|
23454
|
+
async #persist(pluginIds, trusted) {
|
|
23455
|
+
const ctx = defaultRuntimeContext();
|
|
23456
|
+
const dbPath = resolveDbPath({ db: void 0, cwd: ctx.cwd });
|
|
23457
|
+
await withSqlite({ databasePath: dbPath, autoBackup: false }, async (adapter) => {
|
|
23458
|
+
for (const id of pluginIds) await adapter.trust.set(id, trusted);
|
|
23459
|
+
});
|
|
23460
|
+
}
|
|
23461
|
+
#renderSuccess(pluginIds, trusted) {
|
|
23462
|
+
const verbPast = trusted ? "trusted" : "untrusted";
|
|
23463
|
+
if (pluginIds.length === 1) {
|
|
23464
|
+
this.printer.data(tx(PLUGINS_TEXTS.trustAppliedSingle, { verbPast, id: pluginIds[0] }));
|
|
23465
|
+
return;
|
|
23466
|
+
}
|
|
23467
|
+
this.printer.data(
|
|
23468
|
+
tx(PLUGINS_TEXTS.trustAppliedManyHeader, { verbPast, count: pluginIds.length })
|
|
23469
|
+
);
|
|
23470
|
+
for (const id of pluginIds) {
|
|
23471
|
+
this.printer.data(tx(PLUGINS_TEXTS.trustAppliedManyRow, { id }));
|
|
23472
|
+
}
|
|
23473
|
+
}
|
|
23474
|
+
};
|
|
23475
|
+
function collapseToPluginId(id) {
|
|
23476
|
+
const slash = id.indexOf("/");
|
|
23477
|
+
return slash < 0 ? id : id.slice(0, slash);
|
|
23478
|
+
}
|
|
23479
|
+
function isBuiltInOrLocked(id) {
|
|
23480
|
+
if (isPluginLocked(id)) return true;
|
|
23481
|
+
return builtInPlugins.some((p) => p.id === id);
|
|
23482
|
+
}
|
|
23483
|
+
var PluginsTrustCommand = class extends TrustPluginsBase {
|
|
23484
|
+
static paths = [["plugins", "trust"]];
|
|
23485
|
+
static usage = Command27.Usage({
|
|
23486
|
+
category: "Plugins",
|
|
23487
|
+
description: "Grant LOCAL import trust to one or more project-local plugins (or --all). Persists in the config_plugins trust store.",
|
|
23488
|
+
details: `
|
|
23489
|
+
Records this machine's consent to import and run the plugin's code.
|
|
23490
|
+
Trust is the SECURITY axis, distinct from enable: a project-local
|
|
23491
|
+
plugin runs only when it is BOTH enabled (config) and trusted (this
|
|
23492
|
+
DB store). Per-plugin (bare id); a qualified <plugin>/<ext> collapses
|
|
23493
|
+
to its plugin. Local only, never committed, so it cannot travel in a
|
|
23494
|
+
clone.
|
|
23495
|
+
|
|
23496
|
+
Accepts one or more ids, or --all (every discovered drop-in plugin).
|
|
23497
|
+
Batches are all-or-nothing: a built-in / host-locked / unknown id
|
|
23498
|
+
aborts before any write. Repeated ids are deduped. Granting trust
|
|
23499
|
+
lets an enabled plugin's code import on the next scan / sm serve
|
|
23500
|
+
restart.
|
|
23501
|
+
`
|
|
23502
|
+
});
|
|
23503
|
+
async run() {
|
|
23504
|
+
return this.applyTrust(true);
|
|
23505
|
+
}
|
|
23506
|
+
};
|
|
23507
|
+
var PluginsUntrustCommand = class extends TrustPluginsBase {
|
|
23508
|
+
static paths = [["plugins", "untrust"]];
|
|
23509
|
+
static usage = Command27.Usage({
|
|
23510
|
+
category: "Plugins",
|
|
23511
|
+
description: "Revoke LOCAL import trust from one or more project-local plugins (or --all). Does not delete files or change enable state.",
|
|
23512
|
+
details: `
|
|
23513
|
+
Drops the plugin's config_plugins trust row, so it reverts to
|
|
23514
|
+
discovered-but-unexecuted on the next scan / restart. Does NOT change
|
|
23515
|
+
the enable state and does NOT delete the plugin directory. Same
|
|
23516
|
+
id / batch semantics as sm plugins trust.
|
|
23517
|
+
`
|
|
23518
|
+
});
|
|
23519
|
+
async run() {
|
|
23520
|
+
return this.applyTrust(false);
|
|
23521
|
+
}
|
|
23522
|
+
};
|
|
23523
|
+
|
|
23262
23524
|
// cli/commands/plugins/create.ts
|
|
23263
23525
|
import { existsSync as existsSync26, mkdirSync as mkdirSync5, writeFileSync } from "fs";
|
|
23264
23526
|
import { dirname as dirname18, join as join18, resolve as resolve37 } from "path";
|
|
23265
|
-
import { Command as
|
|
23527
|
+
import { Command as Command28, Option as Option27 } from "clipanion";
|
|
23266
23528
|
|
|
23267
23529
|
// cli/commands/plugins/scaffold/action.ts
|
|
23268
23530
|
function indexStub(extId) {
|
|
@@ -23618,6 +23880,7 @@ Generated by \`sm plugins create ${kind} ${pluginId}\`. Edit \`${mainFileRel}\`
|
|
|
23618
23880
|
|
|
23619
23881
|
## Verbs
|
|
23620
23882
|
|
|
23883
|
+
- \`sm plugins trust ${pluginId}\`: allow this project-local plugin's code to run (it is untrusted until you do)
|
|
23621
23884
|
- \`sm plugins list ${pluginId}\`: manifest + extensions + load status
|
|
23622
23885
|
- \`sm plugins doctor\`: full plugin diagnostic
|
|
23623
23886
|
- \`sm scan\`: re-emit contributions / re-run analysis
|
|
@@ -23667,7 +23930,7 @@ function generateScaffold(kind, pluginId, specVersion) {
|
|
|
23667
23930
|
// cli/commands/plugins/create.ts
|
|
23668
23931
|
var PluginsCreateCommand = class extends SmCommand {
|
|
23669
23932
|
static paths = [["plugins", "create"]];
|
|
23670
|
-
static usage =
|
|
23933
|
+
static usage = Command28.Usage({
|
|
23671
23934
|
category: "Plugins",
|
|
23672
23935
|
description: "Scaffold a new plugin directory.",
|
|
23673
23936
|
details: "Emits plugin.json + a per-kind extension stub + README. `<kind>` is one of: provider, extractor, analyzer, action, formatter, hook. The extractor stub ships one view contribution (slot `card.footer.left`) and one setting (`string-list`); edit to taste. Use `sm plugins slots list` to browse the slot / input-type catalog.",
|
|
@@ -23679,10 +23942,10 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
23679
23942
|
});
|
|
23680
23943
|
// First positional: the extension kind (required). Declared before
|
|
23681
23944
|
// `pluginId` so clipanion assigns it the first positional slot.
|
|
23682
|
-
kind =
|
|
23683
|
-
pluginId =
|
|
23684
|
-
at =
|
|
23685
|
-
force =
|
|
23945
|
+
kind = Option27.String({ required: true, name: "kind" });
|
|
23946
|
+
pluginId = Option27.String({ required: true, name: "plugin-id" });
|
|
23947
|
+
at = Option27.String("--at", { required: false });
|
|
23948
|
+
force = Option27.Boolean("--force", false);
|
|
23686
23949
|
async run() {
|
|
23687
23950
|
const ansi = this.ansiFor("stderr");
|
|
23688
23951
|
const errGlyph = ansi.red("\u2715");
|
|
@@ -23733,7 +23996,8 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
23733
23996
|
this.printer.data(
|
|
23734
23997
|
tx(PLUGINS_TEXTS.createSuccess, {
|
|
23735
23998
|
targetDir: sanitizeForTerminal(targetDir),
|
|
23736
|
-
mainFile
|
|
23999
|
+
mainFile,
|
|
24000
|
+
pluginId: this.pluginId
|
|
23737
24001
|
})
|
|
23738
24002
|
);
|
|
23739
24003
|
return ExitCode.Ok;
|
|
@@ -23741,7 +24005,7 @@ var PluginsCreateCommand = class extends SmCommand {
|
|
|
23741
24005
|
};
|
|
23742
24006
|
|
|
23743
24007
|
// cli/commands/plugins/slots.ts
|
|
23744
|
-
import { Command as
|
|
24008
|
+
import { Command as Command29 } from "clipanion";
|
|
23745
24009
|
|
|
23746
24010
|
// cli/commands/plugins/slots-catalog.ts
|
|
23747
24011
|
var VIEW_SLOTS_CATALOG = [
|
|
@@ -23777,7 +24041,7 @@ var INPUT_TYPES_CATALOG = [
|
|
|
23777
24041
|
// cli/commands/plugins/slots.ts
|
|
23778
24042
|
var PluginsSlotsListCommand = class extends SmCommand {
|
|
23779
24043
|
static paths = [["plugins", "slots", "list"]];
|
|
23780
|
-
static usage =
|
|
24044
|
+
static usage = Command29.Usage({
|
|
23781
24045
|
category: "Plugins",
|
|
23782
24046
|
description: "Print the closed catalogs of view slots and input-types.",
|
|
23783
24047
|
details: "Read-only. Use this when picking a slot / input-type for a new plugin."
|
|
@@ -23826,15 +24090,15 @@ var PluginsSlotsListCommand = class extends SmCommand {
|
|
|
23826
24090
|
};
|
|
23827
24091
|
|
|
23828
24092
|
// cli/commands/plugins/upgrade.ts
|
|
23829
|
-
import { Command as
|
|
24093
|
+
import { Command as Command30, Option as Option28 } from "clipanion";
|
|
23830
24094
|
var PluginsUpgradeCommand = class extends SmCommand {
|
|
23831
24095
|
static paths = [["plugins", "upgrade"]];
|
|
23832
|
-
static usage =
|
|
24096
|
+
static usage = Command30.Usage({
|
|
23833
24097
|
category: "Plugins",
|
|
23834
24098
|
description: "Apply catalog migrations to plugin manifests.",
|
|
23835
24099
|
details: "No migrations registered against catalog v1.0.0 yet; this verb is a no-op today. The structure exists so future slot renames / deprecations land without spec churn."
|
|
23836
24100
|
});
|
|
23837
|
-
pluginId =
|
|
24101
|
+
pluginId = Option28.String({ required: false, name: "plugin-id" });
|
|
23838
24102
|
async run() {
|
|
23839
24103
|
this.printer.data(
|
|
23840
24104
|
"sm plugins upgrade: no migrations registered for catalog v1.0.0.\n All loaded plugins are catalog-current.\n Run `sm plugins doctor` to surface any incompatible-catalog status.\n"
|
|
@@ -23844,7 +24108,7 @@ var PluginsUpgradeCommand = class extends SmCommand {
|
|
|
23844
24108
|
};
|
|
23845
24109
|
|
|
23846
24110
|
// cli/commands/plugins/config.ts
|
|
23847
|
-
import { Command as
|
|
24111
|
+
import { Command as Command31, Option as Option29 } from "clipanion";
|
|
23848
24112
|
|
|
23849
24113
|
// cli/i18n/plugins-config.texts.ts
|
|
23850
24114
|
var PLUGINS_CONFIG_TEXTS = {
|
|
@@ -23885,7 +24149,7 @@ var PLUGINS_CONFIG_TEXTS = {
|
|
|
23885
24149
|
// cli/commands/plugins/config.ts
|
|
23886
24150
|
var PluginsConfigCommand = class extends SmCommand {
|
|
23887
24151
|
static paths = [["plugins", "config"]];
|
|
23888
|
-
static usage =
|
|
24152
|
+
static usage = Command31.Usage({
|
|
23889
24153
|
category: "Plugins",
|
|
23890
24154
|
description: "Read or write an extension's declared settings.",
|
|
23891
24155
|
details: `
|
|
@@ -23900,13 +24164,13 @@ var PluginsConfigCommand = class extends SmCommand {
|
|
|
23900
24164
|
Secret values are shown as <redacted>. Run \`sm scan\` to apply.
|
|
23901
24165
|
`
|
|
23902
24166
|
});
|
|
23903
|
-
id =
|
|
23904
|
-
settingId =
|
|
23905
|
-
value =
|
|
23906
|
-
reset =
|
|
24167
|
+
id = Option29.String({ required: true });
|
|
24168
|
+
settingId = Option29.String({ required: false });
|
|
24169
|
+
value = Option29.String({ required: false });
|
|
24170
|
+
reset = Option29.Boolean("--reset", false, {
|
|
23907
24171
|
description: "Remove the override for <settingId> so the manifest default applies."
|
|
23908
24172
|
});
|
|
23909
|
-
pluginDir =
|
|
24173
|
+
pluginDir = Option29.String("--plugin-dir", { required: false });
|
|
23910
24174
|
// Read-only when listing; the write / reset paths emit their own
|
|
23911
24175
|
// receipt. `sm config` exempts the config family from "done in <…>";
|
|
23912
24176
|
// mirror that here for the read path. The write path keeps the line.
|
|
@@ -24219,6 +24483,8 @@ var PLUGIN_COMMANDS = [
|
|
|
24219
24483
|
PluginsDoctorCommand,
|
|
24220
24484
|
PluginsEnableCommand,
|
|
24221
24485
|
PluginsDisableCommand,
|
|
24486
|
+
PluginsTrustCommand,
|
|
24487
|
+
PluginsUntrustCommand,
|
|
24222
24488
|
PluginsCreateCommand,
|
|
24223
24489
|
PluginsSlotsListCommand,
|
|
24224
24490
|
PluginsUpgradeCommand,
|
|
@@ -24228,7 +24494,7 @@ var PLUGIN_COMMANDS = [
|
|
|
24228
24494
|
// cli/commands/refresh.ts
|
|
24229
24495
|
import { readFile as readFile4 } from "fs/promises";
|
|
24230
24496
|
import { resolve as resolve38 } from "path";
|
|
24231
|
-
import { Command as
|
|
24497
|
+
import { Command as Command32, Option as Option30 } from "clipanion";
|
|
24232
24498
|
|
|
24233
24499
|
// cli/i18n/refresh.texts.ts
|
|
24234
24500
|
var REFRESH_TEXTS = {
|
|
@@ -24284,7 +24550,7 @@ var REFRESH_TEXTS = {
|
|
|
24284
24550
|
// cli/commands/refresh.ts
|
|
24285
24551
|
var RefreshCommand = class extends SmCommand {
|
|
24286
24552
|
static paths = [["refresh"]];
|
|
24287
|
-
static usage =
|
|
24553
|
+
static usage = Command32.Usage({
|
|
24288
24554
|
category: "Scan",
|
|
24289
24555
|
description: "Refresh enrichment rows: granular (single node) or batch (every stale row).",
|
|
24290
24556
|
details: `
|
|
@@ -24306,11 +24572,11 @@ var RefreshCommand = class extends SmCommand {
|
|
|
24306
24572
|
["Refresh every node with stale enrichments", "$0 refresh --stale"]
|
|
24307
24573
|
]
|
|
24308
24574
|
});
|
|
24309
|
-
nodePath =
|
|
24310
|
-
stale =
|
|
24575
|
+
nodePath = Option30.String({ name: "node", required: false });
|
|
24576
|
+
stale = Option30.Boolean("--stale", false, {
|
|
24311
24577
|
description: "Refresh every node carrying a stale enrichment row (no-op in this revision; reserved for future Action-prob enrichments)."
|
|
24312
24578
|
});
|
|
24313
|
-
noPlugins =
|
|
24579
|
+
noPlugins = Option30.Boolean("--no-plugins", false, {
|
|
24314
24580
|
description: "Skip drop-in plugin discovery; use only the built-in extractor set."
|
|
24315
24581
|
});
|
|
24316
24582
|
// The remaining cyclomatic count comes from CLI ergonomics that don't
|
|
@@ -24614,7 +24880,7 @@ var IntentionalFailCommand = class extends SmCommand {
|
|
|
24614
24880
|
};
|
|
24615
24881
|
|
|
24616
24882
|
// cli/commands/scan.ts
|
|
24617
|
-
import { Command as
|
|
24883
|
+
import { Command as Command34, Option as Option32 } from "clipanion";
|
|
24618
24884
|
|
|
24619
24885
|
// kernel/util/format-bytes.ts
|
|
24620
24886
|
var UNITS = ["B", "KiB", "MiB", "GiB", "TiB", "PiB"];
|
|
@@ -24773,22 +25039,17 @@ var SCAN_TEXTS = {
|
|
|
24773
25039
|
};
|
|
24774
25040
|
|
|
24775
25041
|
// cli/commands/watch.ts
|
|
24776
|
-
import { Command as
|
|
25042
|
+
import { Command as Command33, Option as Option31 } from "clipanion";
|
|
24777
25043
|
|
|
24778
25044
|
// core/watcher/runtime.ts
|
|
24779
25045
|
import { dirname as dirname19, isAbsolute as isAbsolute13, relative as relative9, resolve as resolve39, sep as sep6 } from "path";
|
|
24780
25046
|
|
|
24781
25047
|
// core/runtime/fresh-resolver.ts
|
|
24782
25048
|
async function buildFreshResolver(deps) {
|
|
24783
|
-
|
|
24784
|
-
{ databasePath: deps.databasePath, autoBackup: false },
|
|
24785
|
-
async (adapter) => adapter.pluginConfig.loadOverrideMap()
|
|
24786
|
-
);
|
|
24787
|
-
if (overrides === null) return deps.fallbackResolver;
|
|
24788
|
-
return makeEnabledResolver(deps.effectiveConfig(), overrides);
|
|
25049
|
+
return makeEnabledResolver(deps.effectiveConfig());
|
|
24789
25050
|
}
|
|
24790
|
-
function composeResolver(effectiveConfig
|
|
24791
|
-
return makeEnabledResolver(effectiveConfig
|
|
25051
|
+
function composeResolver(effectiveConfig) {
|
|
25052
|
+
return makeEnabledResolver(effectiveConfig);
|
|
24792
25053
|
}
|
|
24793
25054
|
|
|
24794
25055
|
// core/watcher/i18n/runtime.texts.ts
|
|
@@ -24904,9 +25165,7 @@ function createWatcherRuntime(opts) {
|
|
|
24904
25165
|
const runOnePass = async (changedPaths) => {
|
|
24905
25166
|
notifyBatchStart();
|
|
24906
25167
|
const resolveEnabledOverride = await buildFreshResolver({
|
|
24907
|
-
|
|
24908
|
-
effectiveConfig: () => cfg,
|
|
24909
|
-
fallbackResolver: pluginRuntime.resolveEnabled
|
|
25168
|
+
effectiveConfig: () => cfg
|
|
24910
25169
|
});
|
|
24911
25170
|
const kernel = createKernel();
|
|
24912
25171
|
registerEnabledExtensions(kernel, pluginRuntime, {
|
|
@@ -25370,7 +25629,7 @@ async function runWatchLoop(opts) {
|
|
|
25370
25629
|
}
|
|
25371
25630
|
var WatchCommand = class extends SmCommand {
|
|
25372
25631
|
static paths = [["watch"]];
|
|
25373
|
-
static usage =
|
|
25632
|
+
static usage = Command33.Usage({
|
|
25374
25633
|
category: "Scan",
|
|
25375
25634
|
description: "Watch roots and run an incremental scan after each debounced batch of filesystem events.",
|
|
25376
25635
|
details: `
|
|
@@ -25394,25 +25653,25 @@ var WatchCommand = class extends SmCommand {
|
|
|
25394
25653
|
["Stream ScanResult per batch as ndjson", "$0 watch --json"]
|
|
25395
25654
|
]
|
|
25396
25655
|
});
|
|
25397
|
-
roots =
|
|
25398
|
-
noTokens =
|
|
25656
|
+
roots = Option31.Rest({ name: "roots" });
|
|
25657
|
+
noTokens = Option31.Boolean("--no-tokens", false, {
|
|
25399
25658
|
description: "Skip per-node token counts (cl100k_base BPE)."
|
|
25400
25659
|
});
|
|
25401
|
-
strict =
|
|
25660
|
+
strict = Option31.Boolean("--strict", false, {
|
|
25402
25661
|
description: "Promote frontmatter-validation findings from warn to error inside each batch. Does not change the watcher exit code."
|
|
25403
25662
|
});
|
|
25404
|
-
noPlugins =
|
|
25663
|
+
noPlugins = Option31.Boolean("--no-plugins", false, {
|
|
25405
25664
|
description: "Skip drop-in plugin discovery for the watcher session."
|
|
25406
25665
|
});
|
|
25407
|
-
maxConsecutiveFailures =
|
|
25666
|
+
maxConsecutiveFailures = Option31.String("--max-consecutive-failures", {
|
|
25408
25667
|
required: false,
|
|
25409
25668
|
description: "Shut down with exit 2 after N consecutive batch failures (default 5; 0 disables the breaker)."
|
|
25410
25669
|
});
|
|
25411
|
-
maxScan =
|
|
25670
|
+
maxScan = Option31.String("--max-scan", {
|
|
25412
25671
|
required: false,
|
|
25413
25672
|
description: "Per-batch override of scan.maxScan (default 50000), the WALK-INTAKE ceiling. The scan walks, parses, analyzes, and reference-validates the full corpus up to this number. Bidirectional: raises OR lowers the ceiling. When a batch hits it, additional files are dropped in stable order and the UI surfaces the persistent truncation banner. Validation: integer >= 1."
|
|
25414
25673
|
});
|
|
25415
|
-
maxNodes =
|
|
25674
|
+
maxNodes = Option31.String("--max-nodes", {
|
|
25416
25675
|
required: false,
|
|
25417
25676
|
description: "Per-batch override of scan.maxNodes (default 256), the MAP RENDER cap (pure metadata): it does NOT bound the scan, only the graph projection. Bidirectional: raises OR lowers the render cap. Validation: integer >= 1."
|
|
25418
25677
|
});
|
|
@@ -25499,7 +25758,7 @@ function parseMaxNodesLimit(raw, stderr, noColor) {
|
|
|
25499
25758
|
// cli/commands/scan.ts
|
|
25500
25759
|
var ScanCommand = class extends SmCommand {
|
|
25501
25760
|
static paths = [["scan"]];
|
|
25502
|
-
static usage =
|
|
25761
|
+
static usage = Command34.Usage({
|
|
25503
25762
|
category: "Scan",
|
|
25504
25763
|
description: "Scan roots for markdown nodes, run extractors and analyzers.",
|
|
25505
25764
|
details: `
|
|
@@ -25534,39 +25793,39 @@ var ScanCommand = class extends SmCommand {
|
|
|
25534
25793
|
["What would the next incremental scan persist?", "$0 scan --changed -n --json"]
|
|
25535
25794
|
]
|
|
25536
25795
|
});
|
|
25537
|
-
roots =
|
|
25538
|
-
noBuiltIns =
|
|
25796
|
+
roots = Option32.Rest({ name: "roots" });
|
|
25797
|
+
noBuiltIns = Option32.Boolean("--no-built-ins", false, {
|
|
25539
25798
|
description: "Skip the built-in extension set. Yields a zero-filled ScanResult (kernel-empty-boot parity); skips DB persistence."
|
|
25540
25799
|
});
|
|
25541
|
-
noPlugins =
|
|
25800
|
+
noPlugins = Option32.Boolean("--no-plugins", false, {
|
|
25542
25801
|
description: "Skip drop-in plugin discovery. Only the built-in set runs. Combine with --no-built-ins for a fully empty pipeline."
|
|
25543
25802
|
});
|
|
25544
|
-
noTokens =
|
|
25803
|
+
noTokens = Option32.Boolean("--no-tokens", false, {
|
|
25545
25804
|
description: "Skip per-node token counts (cl100k_base BPE). Leaves node.tokens undefined; spec-valid since the field is optional."
|
|
25546
25805
|
});
|
|
25547
|
-
dryRun =
|
|
25806
|
+
dryRun = Option32.Boolean("-n,--dry-run", false, {
|
|
25548
25807
|
description: "Run the scan in memory and skip every DB write. Combined with --changed, still opens the DB read-side to load the prior snapshot."
|
|
25549
25808
|
});
|
|
25550
|
-
changed =
|
|
25809
|
+
changed = Option32.Boolean("--changed", false, {
|
|
25551
25810
|
description: "Incremental scan: reuse unchanged nodes from the persisted prior snapshot. Degrades to a full scan if no prior snapshot exists."
|
|
25552
25811
|
});
|
|
25553
|
-
allowEmpty =
|
|
25812
|
+
allowEmpty = Option32.Boolean("--allow-empty", false, {
|
|
25554
25813
|
description: "Allow a zero-result scan to wipe an already-populated DB (replace-all replace by zero rows). Off by default to avoid the typo-trap where an invalid root silently clears your data."
|
|
25555
25814
|
});
|
|
25556
|
-
strict =
|
|
25815
|
+
strict = Option32.Boolean("--strict", false, {
|
|
25557
25816
|
description: "Promote frontmatter-validation findings from warn to error (exit code 1 on any violation). Overrides scan.strict from config when both are set."
|
|
25558
25817
|
});
|
|
25559
|
-
watch =
|
|
25818
|
+
watch = Option32.Boolean("--watch", false, {
|
|
25560
25819
|
description: "Long-running mode: watch the roots and trigger an incremental scan after each debounced batch of filesystem events. Alias of `sm watch`."
|
|
25561
25820
|
});
|
|
25562
|
-
yes =
|
|
25821
|
+
yes = Option32.Boolean("--yes", false, {
|
|
25563
25822
|
description: "Non-interactive mode. For ambiguous activeProvider auto-detect, multiple provider markers (.claude/, .codex/, AGENTS.md, .cursor/) under the scan tree exit non-zero instead of prompting; set the lens manually via `sm config set activeProvider <id>` and re-run. Also auto-confirms the pre-1.0 schema-drift rebuild (when the DB was written by a different skill-map major.minor it is deleted and regenerated) instead of prompting."
|
|
25564
25823
|
});
|
|
25565
|
-
maxScan =
|
|
25824
|
+
maxScan = Option32.String("--max-scan", {
|
|
25566
25825
|
required: false,
|
|
25567
25826
|
description: "Per-invocation override of `scan.maxScan` (default 50000). The WALK-INTAKE ceiling: the scan walks, parses, analyzes, and reference-validates the full corpus up to this number. Bidirectional: raises OR lowers the ceiling. When the walker hits it, additional files are dropped in stable order and the scan is marked truncated in scan_meta (the UI raises a persistent banner pointing at the .skillmapignore editor in Settings \u2192 Project). Validation: integer >= 1."
|
|
25568
25827
|
});
|
|
25569
|
-
maxNodes =
|
|
25828
|
+
maxNodes = Option32.String("--max-nodes", {
|
|
25570
25829
|
required: false,
|
|
25571
25830
|
description: "Per-invocation override of `scan.maxNodes` (default 256). The MAP RENDER cap (pure metadata): it does NOT bound the scan, only how many nodes the graph view projects onto the canvas. Bidirectional: raises OR lowers the render cap. Validation: integer >= 1."
|
|
25572
25831
|
});
|
|
@@ -25927,10 +26186,10 @@ function capOverrides(caps) {
|
|
|
25927
26186
|
|
|
25928
26187
|
// cli/commands/scan-compare.ts
|
|
25929
26188
|
import { access, readFile as readFile5 } from "fs/promises";
|
|
25930
|
-
import { Command as
|
|
26189
|
+
import { Command as Command35, Option as Option33 } from "clipanion";
|
|
25931
26190
|
var ScanCompareCommand = class extends SmCommand {
|
|
25932
26191
|
static paths = [["scan", "compare-with"]];
|
|
25933
|
-
static usage =
|
|
26192
|
+
static usage = Command35.Usage({
|
|
25934
26193
|
category: "Scan",
|
|
25935
26194
|
description: "Run a fresh scan in memory and emit a delta against the saved ScanResult dump at <dump>. Read-only.",
|
|
25936
26195
|
details: `
|
|
@@ -25958,15 +26217,15 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
25958
26217
|
["JSON output for tooling", "$0 scan compare-with baseline.json --json"]
|
|
25959
26218
|
]
|
|
25960
26219
|
});
|
|
25961
|
-
dump =
|
|
25962
|
-
roots =
|
|
25963
|
-
noTokens =
|
|
26220
|
+
dump = Option33.String({ required: true });
|
|
26221
|
+
roots = Option33.Rest({ name: "roots" });
|
|
26222
|
+
noTokens = Option33.Boolean("--no-tokens", false, {
|
|
25964
26223
|
description: "Skip per-node token counts during the fresh scan."
|
|
25965
26224
|
});
|
|
25966
|
-
strict =
|
|
26225
|
+
strict = Option33.Boolean("--strict", false, {
|
|
25967
26226
|
description: "Promote layered-config warnings and frontmatter-validation findings from warn to error."
|
|
25968
26227
|
});
|
|
25969
|
-
noPlugins =
|
|
26228
|
+
noPlugins = Option33.Boolean("--no-plugins", false, {
|
|
25970
26229
|
description: "Skip drop-in plugin discovery."
|
|
25971
26230
|
});
|
|
25972
26231
|
// Cyclomatic count comes from CLI ergonomics: 3 distinct try/catch
|
|
@@ -26173,7 +26432,7 @@ function renderDeltaIssues(issues) {
|
|
|
26173
26432
|
// cli/commands/serve.ts
|
|
26174
26433
|
import { spawn as spawn2 } from "child_process";
|
|
26175
26434
|
import { existsSync as existsSync32 } from "fs";
|
|
26176
|
-
import { Command as
|
|
26435
|
+
import { Command as Command36, Option as Option34 } from "clipanion";
|
|
26177
26436
|
|
|
26178
26437
|
// kernel/util/dev-mode.ts
|
|
26179
26438
|
import { sep as sep7 } from "path";
|
|
@@ -26420,6 +26679,14 @@ var SERVER_TEXTS = {
|
|
|
26420
26679
|
pluginsBodyNotJson: "Request body must be valid JSON.",
|
|
26421
26680
|
pluginsBodyNotObject: "Request body must be a JSON object.",
|
|
26422
26681
|
pluginsEnabledRequired: "`enabled` is required and must be a boolean.",
|
|
26682
|
+
pluginsTrustedRequired: "`trusted` is required and must be a boolean.",
|
|
26683
|
+
// 403, trust toggle targeted a built-in (or host-locked) id. Those are
|
|
26684
|
+
// never import-trust-gated, so a trust grant is meaningless. Reuses the
|
|
26685
|
+
// 403 `locked` envelope code per the spec.
|
|
26686
|
+
pluginsTrustBuiltIn: 'Plugin "{{id}}" is a built-in (or host-locked) and is never import-trust-gated.',
|
|
26687
|
+
// 400, the trust route received a qualified `<plugin>/<ext>` id; trust
|
|
26688
|
+
// is per-plugin, so it must be a bare plugin id.
|
|
26689
|
+
pluginsTrustQualifiedRejected: 'Plugin id "{{id}}" contains "/"; import trust is per-plugin, pass the bare plugin id.',
|
|
26423
26690
|
// 400, cascade route rejects qualified ids: the bare-id PATCH is the
|
|
26424
26691
|
// bundle macro endpoint. Anything containing `/` needs the dedicated
|
|
26425
26692
|
// per-extension route below.
|
|
@@ -26482,9 +26749,11 @@ var SERVER_TEXTS = {
|
|
|
26482
26749
|
// silently widen the scan surface.
|
|
26483
26750
|
projectPrefsBodyNotJson: "Request body must be valid JSON.",
|
|
26484
26751
|
projectPrefsBodyNotObject: "Request body must be a JSON object.",
|
|
26485
|
-
projectPrefsBodyEmpty: "Request body must contain `allowSidecarWriters` and/or a `
|
|
26752
|
+
projectPrefsBodyEmpty: "Request body must contain `allowSidecarWriters`, a `scan` block with `referencePaths`, and/or a `pluginTrust` block with `projectEnabled`.",
|
|
26486
26753
|
projectPrefsConfirmNotBoolean: "`confirm` must be a boolean.",
|
|
26487
26754
|
projectPrefsSidecarWritersNotBoolean: "`allowSidecarWriters` must be a boolean.",
|
|
26755
|
+
projectPrefsTrustNotObject: '`pluginTrust` must be an object (e.g. `{"pluginTrust": {"projectEnabled": true}}`).',
|
|
26756
|
+
projectPrefsTrustEnabledNotBoolean: "`pluginTrust.projectEnabled` must be a boolean.",
|
|
26488
26757
|
// Server-stderr advisory after `PATCH /api/project-preferences`
|
|
26489
26758
|
// toggles the committed sidecar-writer policy. Lets the operator see
|
|
26490
26759
|
// the team-shared change land without opening settings.json.
|
|
@@ -26493,6 +26762,12 @@ var SERVER_TEXTS = {
|
|
|
26493
26762
|
projectPrefsListNotArray: "`{{key}}` must be an array of strings.",
|
|
26494
26763
|
projectPrefsListEntryNotString: "`{{key}}` entries must be strings.",
|
|
26495
26764
|
projectPrefsConfirmRequired: "This change opens disk access outside the project: {{paths}}. Re-issue the request with `confirm: true` to proceed.",
|
|
26765
|
+
// 412, turning on the local plugin-trust opt-in. Expands the LOCAL
|
|
26766
|
+
// code-execution surface (every plugin the project enables becomes
|
|
26767
|
+
// trusted), so the route refuses without `confirm: true`.
|
|
26768
|
+
projectPrefsTrustConfirmRequired: "Turning on pluginTrust.projectEnabled trusts every plugin this project enables; their code may then import and run on this machine. Re-issue the request with `confirm: true` to proceed.",
|
|
26769
|
+
// Server-stderr advisory after the local plugin-trust opt-in changes.
|
|
26770
|
+
projectPrefsTrustSet: "project-prefs: pluginTrust.projectEnabled = {{value}}",
|
|
26496
26771
|
projectPrefsPersistFailed: "Could not persist `{{key}}`: {{message}}",
|
|
26497
26772
|
// Returned for every NEW entry that does not resolve to an existing
|
|
26498
26773
|
// directory on disk. The list is comma-separated; pre-existing
|
|
@@ -27667,6 +27942,24 @@ var parsePatchBody = makeBodyValidator(SINGLE_PATCH_BODY_SCHEMA, {
|
|
|
27667
27942
|
"/enabled:type:boolean": SERVER_TEXTS.pluginsEnabledRequired
|
|
27668
27943
|
}
|
|
27669
27944
|
});
|
|
27945
|
+
var TRUST_PATCH_BODY_SCHEMA = {
|
|
27946
|
+
type: "object",
|
|
27947
|
+
additionalProperties: false,
|
|
27948
|
+
required: ["trusted"],
|
|
27949
|
+
properties: {
|
|
27950
|
+
trusted: { type: "boolean" }
|
|
27951
|
+
}
|
|
27952
|
+
};
|
|
27953
|
+
var parseTrustPatchBody = makeBodyValidator(TRUST_PATCH_BODY_SCHEMA, {
|
|
27954
|
+
notJson: SERVER_TEXTS.pluginsBodyNotJson,
|
|
27955
|
+
notObject: SERVER_TEXTS.pluginsBodyNotObject,
|
|
27956
|
+
invalid: SERVER_TEXTS.pluginsTrustedRequired,
|
|
27957
|
+
mapping: {
|
|
27958
|
+
":required:trusted": SERVER_TEXTS.pluginsTrustedRequired,
|
|
27959
|
+
"/trusted:required": SERVER_TEXTS.pluginsTrustedRequired,
|
|
27960
|
+
"/trusted:type:boolean": SERVER_TEXTS.pluginsTrustedRequired
|
|
27961
|
+
}
|
|
27962
|
+
});
|
|
27670
27963
|
var BULK_PATCH_BODY_SCHEMA = {
|
|
27671
27964
|
type: "object",
|
|
27672
27965
|
additionalProperties: false,
|
|
@@ -27712,7 +28005,8 @@ var parseBulkPatchBody = makeBodyValidator(BULK_PATCH_BODY_SCHEMA, {
|
|
|
27712
28005
|
function registerPluginsRoute(app, deps) {
|
|
27713
28006
|
app.get("/api/plugins", async (c) => {
|
|
27714
28007
|
const resolveEnabled = await buildFreshResolver2(deps);
|
|
27715
|
-
const
|
|
28008
|
+
const trust = await loadTrustState(deps);
|
|
28009
|
+
const items = listItems(deps, resolveEnabled, trust);
|
|
27716
28010
|
const errorsByPlugin = await loadRuntimeContributionErrors(deps);
|
|
27717
28011
|
attachRuntimeContributionErrors(items, errorsByPlugin);
|
|
27718
28012
|
return c.json(
|
|
@@ -27771,7 +28065,28 @@ function registerPluginsRoute(app, deps) {
|
|
|
27771
28065
|
});
|
|
27772
28066
|
}
|
|
27773
28067
|
const body = await parsePatchBody(c.req.raw);
|
|
27774
|
-
return await
|
|
28068
|
+
return await persistManyAndProject(c, deps, [qualified], body.enabled);
|
|
28069
|
+
});
|
|
28070
|
+
app.patch("/api/plugins/:id/trust", async (c) => {
|
|
28071
|
+
const id = c.req.param("id");
|
|
28072
|
+
if (id.includes("/")) {
|
|
28073
|
+
throw new HTTPException10(400, {
|
|
28074
|
+
message: tx(SERVER_TEXTS.pluginsTrustQualifiedRejected, { id })
|
|
28075
|
+
});
|
|
28076
|
+
}
|
|
28077
|
+
const handle = findHandle(id, deps);
|
|
28078
|
+
if (!handle) {
|
|
28079
|
+
throw new HTTPException10(404, {
|
|
28080
|
+
message: tx(SERVER_TEXTS.pluginsUnknown, { id })
|
|
28081
|
+
});
|
|
28082
|
+
}
|
|
28083
|
+
if (handle.kind === "built-in" || isPluginLocked(id)) {
|
|
28084
|
+
throw new HTTPException10(403, {
|
|
28085
|
+
message: tx(SERVER_TEXTS.pluginsTrustBuiltIn, { id })
|
|
28086
|
+
});
|
|
28087
|
+
}
|
|
28088
|
+
const body = await parseTrustPatchBody(c.req.raw);
|
|
28089
|
+
return await persistTrustAndProject(c, deps, id, body.trusted);
|
|
27775
28090
|
});
|
|
27776
28091
|
app.patch("/api/plugins", async (c) => {
|
|
27777
28092
|
const { changes } = await parseBulkPatchBody(c.req.raw);
|
|
@@ -27789,13 +28104,21 @@ function registerPluginsRoute(app, deps) {
|
|
|
27789
28104
|
return await persistBulkAndProject(c, deps, changes);
|
|
27790
28105
|
});
|
|
27791
28106
|
}
|
|
27792
|
-
function listItems(deps, resolveEnabled) {
|
|
28107
|
+
function listItems(deps, resolveEnabled, trust) {
|
|
27793
28108
|
const config = deps.configService.effective();
|
|
27794
28109
|
return [
|
|
27795
28110
|
...deps.options.noBuiltIns ? [] : buildBuiltInItems(resolveEnabled, config),
|
|
27796
|
-
...buildDiscoveredItems(deps.pluginRuntime.discovered, deps, resolveEnabled, config)
|
|
28111
|
+
...buildDiscoveredItems(deps.pluginRuntime.discovered, deps, resolveEnabled, config, trust)
|
|
27797
28112
|
];
|
|
27798
28113
|
}
|
|
28114
|
+
async function loadTrustState(deps) {
|
|
28115
|
+
const trustMap = await tryWithSqlite(
|
|
28116
|
+
{ databasePath: deps.options.dbPath, autoBackup: false },
|
|
28117
|
+
(adapter) => adapter.trust.loadTrustMap()
|
|
28118
|
+
) ?? /* @__PURE__ */ new Map();
|
|
28119
|
+
const trustProjectEnabled = deps.configService.effective().pluginTrust?.projectEnabled ?? false;
|
|
28120
|
+
return { trustMap, trustProjectEnabled };
|
|
28121
|
+
}
|
|
27799
28122
|
function buildBuiltInItems(resolveEnabled, config) {
|
|
27800
28123
|
return sortPluginsForPresentation(builtInPlugins).map((plugin) => {
|
|
27801
28124
|
const pluginLocked = isPluginLocked(plugin.id);
|
|
@@ -27833,10 +28156,10 @@ function buildBuiltInItems(resolveEnabled, config) {
|
|
|
27833
28156
|
};
|
|
27834
28157
|
});
|
|
27835
28158
|
}
|
|
27836
|
-
function buildDiscoveredItems(discovered, deps, resolveEnabled, config) {
|
|
27837
|
-
return discovered.map((plugin) => buildDiscoveredItem(plugin, deps, resolveEnabled, config));
|
|
28159
|
+
function buildDiscoveredItems(discovered, deps, resolveEnabled, config, trust) {
|
|
28160
|
+
return discovered.map((plugin) => buildDiscoveredItem(plugin, deps, resolveEnabled, config, trust));
|
|
27838
28161
|
}
|
|
27839
|
-
function buildDiscoveredItem(plugin, deps, resolveEnabled, config) {
|
|
28162
|
+
function buildDiscoveredItem(plugin, deps, resolveEnabled, config, trust) {
|
|
27840
28163
|
const pluginLocked = isPluginLocked(plugin.id);
|
|
27841
28164
|
const extensions = projectExtensionRows(plugin, resolveEnabled, pluginLocked, config);
|
|
27842
28165
|
const optional = optionalDiscoveredFields(plugin, extensions);
|
|
@@ -27848,8 +28171,15 @@ function buildDiscoveredItem(plugin, deps, resolveEnabled, config) {
|
|
|
27848
28171
|
reason: plugin.reason ?? null,
|
|
27849
28172
|
source: classifyPluginSource(plugin.path, deps),
|
|
27850
28173
|
...optional,
|
|
28174
|
+
...discoveredFlags(plugin, pluginLocked, trust)
|
|
28175
|
+
};
|
|
28176
|
+
}
|
|
28177
|
+
function discoveredFlags(plugin, pluginLocked, trust) {
|
|
28178
|
+
const trusted = trust.trustMap.get(plugin.id) === true || trust.trustProjectEnabled;
|
|
28179
|
+
return {
|
|
27851
28180
|
...pluginLocked ? { locked: true } : {},
|
|
27852
|
-
...
|
|
28181
|
+
...trusted ? { trusted: true } : {},
|
|
28182
|
+
...plugin.status === "disabled" && plugin.untrusted !== true ? { startsAsDisabled: true } : {}
|
|
27853
28183
|
};
|
|
27854
28184
|
}
|
|
27855
28185
|
function optionalDiscoveredFields(plugin, extensions) {
|
|
@@ -27941,49 +28271,54 @@ function attachRuntimeContributionErrors(items, errorsByPlugin) {
|
|
|
27941
28271
|
if (errors && errors.length > 0) item.runtimeContributionErrors = errors;
|
|
27942
28272
|
}
|
|
27943
28273
|
}
|
|
27944
|
-
async function
|
|
27945
|
-
const
|
|
28274
|
+
async function persistManyAndProject(c, deps, keys, enabled) {
|
|
28275
|
+
const cwd = deps.runtimeContext.cwd;
|
|
28276
|
+
for (const key of keys) {
|
|
28277
|
+
writeConfigValue(toEnableConfigKey2(key), enabled, { target: "project", cwd });
|
|
28278
|
+
}
|
|
28279
|
+
if (!enabled && keys.length > 0) await purgeContributionsForKeys(deps, keys);
|
|
28280
|
+
if (keys.length > 0) deps.configService.reload();
|
|
28281
|
+
return await projectListResponse(c, deps);
|
|
28282
|
+
}
|
|
28283
|
+
async function persistTrustAndProject(c, deps, pluginId, trusted) {
|
|
28284
|
+
const ok = await tryWithSqlite(
|
|
27946
28285
|
{ databasePath: deps.options.dbPath, autoBackup: false },
|
|
27947
28286
|
async (adapter) => {
|
|
27948
|
-
await
|
|
27949
|
-
return
|
|
28287
|
+
await adapter.trust.set(pluginId, trusted);
|
|
28288
|
+
return true;
|
|
27950
28289
|
}
|
|
27951
28290
|
);
|
|
27952
|
-
|
|
28291
|
+
if (ok === null) {
|
|
28292
|
+
throw new DbMissingError(
|
|
28293
|
+
tx(SERVER_TEXTS.pluginsDbMissing, { path: deps.options.dbPath })
|
|
28294
|
+
);
|
|
28295
|
+
}
|
|
28296
|
+
return await projectListResponse(c, deps);
|
|
27953
28297
|
}
|
|
27954
|
-
|
|
27955
|
-
const
|
|
28298
|
+
function toEnableConfigKey2(id) {
|
|
28299
|
+
const slash = id.indexOf("/");
|
|
28300
|
+
if (slash < 0) return `plugins.${id}.enabled`;
|
|
28301
|
+
return `plugins.${id.slice(0, slash)}.extensions.${id.slice(slash + 1)}.enabled`;
|
|
28302
|
+
}
|
|
28303
|
+
async function purgeContributionsForKeys(deps, keys) {
|
|
28304
|
+
await tryWithSqlite(
|
|
27956
28305
|
{ databasePath: deps.options.dbPath, autoBackup: false },
|
|
27957
28306
|
async (adapter) => {
|
|
27958
28307
|
for (const key of keys) {
|
|
27959
|
-
|
|
28308
|
+
const slash = key.indexOf("/");
|
|
28309
|
+
if (slash < 0) {
|
|
28310
|
+
await adapter.contributions.purgeByPlugin(key);
|
|
28311
|
+
} else {
|
|
28312
|
+
await adapter.contributions.purgeByPlugin(key.slice(0, slash), key.slice(slash + 1));
|
|
28313
|
+
}
|
|
27960
28314
|
}
|
|
27961
|
-
return await adapter.pluginConfig.loadOverrideMap();
|
|
27962
28315
|
}
|
|
27963
28316
|
);
|
|
27964
|
-
return projectListResponse(c, deps, overrides);
|
|
27965
|
-
}
|
|
27966
|
-
async function applyChangeToAdapter(adapter, configKey, enabled) {
|
|
27967
|
-
await adapter.pluginConfig.set(configKey, enabled);
|
|
27968
|
-
if (enabled) return;
|
|
27969
|
-
const slash = configKey.indexOf("/");
|
|
27970
|
-
if (slash < 0) {
|
|
27971
|
-
await adapter.contributions.purgeByPlugin(configKey);
|
|
27972
|
-
return;
|
|
27973
|
-
}
|
|
27974
|
-
await adapter.contributions.purgeByPlugin(
|
|
27975
|
-
configKey.slice(0, slash),
|
|
27976
|
-
configKey.slice(slash + 1)
|
|
27977
|
-
);
|
|
27978
28317
|
}
|
|
27979
|
-
function projectListResponse(c, deps
|
|
27980
|
-
|
|
27981
|
-
|
|
27982
|
-
|
|
27983
|
-
);
|
|
27984
|
-
}
|
|
27985
|
-
const freshResolver = composeResolver2(deps, overrides);
|
|
27986
|
-
const items = listItems(deps, freshResolver);
|
|
28318
|
+
async function projectListResponse(c, deps) {
|
|
28319
|
+
const resolveEnabled = composeResolver2(deps);
|
|
28320
|
+
const trust = await loadTrustState(deps);
|
|
28321
|
+
const items = listItems(deps, resolveEnabled, trust);
|
|
27987
28322
|
return c.json(
|
|
27988
28323
|
buildListEnvelope({
|
|
27989
28324
|
kind: "plugins",
|
|
@@ -28088,27 +28423,26 @@ function handleExtensionSettings(handle, extensionId) {
|
|
|
28088
28423
|
return readManifestSettings(ext?.instance);
|
|
28089
28424
|
}
|
|
28090
28425
|
async function persistBulkAndProject(c, deps, changes) {
|
|
28091
|
-
const
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
28095
|
-
|
|
28096
|
-
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
28100
|
-
|
|
28101
|
-
|
|
28426
|
+
const { disabledKeys, toggleTouched } = applyBulkEnableWrites(deps, changes);
|
|
28427
|
+
const settingsTouched = persistBulkSettings(deps, changes);
|
|
28428
|
+
if (disabledKeys.length > 0) await purgeContributionsForKeys(deps, disabledKeys);
|
|
28429
|
+
if (toggleTouched || settingsTouched) deps.configService.reload();
|
|
28430
|
+
return await projectListResponse(c, deps);
|
|
28431
|
+
}
|
|
28432
|
+
function applyBulkEnableWrites(deps, changes) {
|
|
28433
|
+
const cwd = deps.runtimeContext.cwd;
|
|
28434
|
+
const disabledKeys = [];
|
|
28435
|
+
let toggleTouched = false;
|
|
28436
|
+
for (const change of changes) {
|
|
28437
|
+
if (change.enabled === void 0) continue;
|
|
28438
|
+
const writeKeys = expandBulkChangeKeys(change, deps);
|
|
28439
|
+
for (const key of writeKeys) {
|
|
28440
|
+
writeConfigValue(toEnableConfigKey2(key), change.enabled, { target: "project", cwd });
|
|
28441
|
+
if (!change.enabled) disabledKeys.push(key);
|
|
28102
28442
|
}
|
|
28103
|
-
|
|
28104
|
-
if (overrides === null) {
|
|
28105
|
-
throw new DbMissingError(
|
|
28106
|
-
tx(SERVER_TEXTS.pluginsDbMissing, { path: deps.options.dbPath })
|
|
28107
|
-
);
|
|
28443
|
+
if (writeKeys.length > 0) toggleTouched = true;
|
|
28108
28444
|
}
|
|
28109
|
-
|
|
28110
|
-
if (settingsTouched) deps.configService.reload();
|
|
28111
|
-
return projectListResponse(c, deps, overrides);
|
|
28445
|
+
return { disabledKeys, toggleTouched };
|
|
28112
28446
|
}
|
|
28113
28447
|
function persistBulkSettings(deps, changes) {
|
|
28114
28448
|
const cwd = deps.runtimeContext.cwd;
|
|
@@ -28143,13 +28477,11 @@ function expandBulkChangeKeys(change, deps) {
|
|
|
28143
28477
|
}
|
|
28144
28478
|
async function buildFreshResolver2(deps) {
|
|
28145
28479
|
return buildFreshResolver({
|
|
28146
|
-
|
|
28147
|
-
effectiveConfig: () => deps.configService.effective(),
|
|
28148
|
-
fallbackResolver: deps.pluginRuntime.resolveEnabled
|
|
28480
|
+
effectiveConfig: () => deps.configService.effective()
|
|
28149
28481
|
});
|
|
28150
28482
|
}
|
|
28151
|
-
function composeResolver2(deps
|
|
28152
|
-
return composeResolver(deps.configService.effective()
|
|
28483
|
+
function composeResolver2(deps) {
|
|
28484
|
+
return composeResolver(deps.configService.effective());
|
|
28153
28485
|
}
|
|
28154
28486
|
function findHandle(id, deps) {
|
|
28155
28487
|
const builtIn = builtInPlugins.find((b) => b.id === id);
|
|
@@ -28467,6 +28799,12 @@ function buildEnvelope3(deps) {
|
|
|
28467
28799
|
cwd,
|
|
28468
28800
|
default: []
|
|
28469
28801
|
}) ?? []
|
|
28802
|
+
},
|
|
28803
|
+
pluginTrust: {
|
|
28804
|
+
projectEnabled: readConfigValue("pluginTrust.projectEnabled", {
|
|
28805
|
+
cwd,
|
|
28806
|
+
default: false
|
|
28807
|
+
}) ?? false
|
|
28470
28808
|
}
|
|
28471
28809
|
};
|
|
28472
28810
|
}
|
|
@@ -28474,8 +28812,32 @@ async function applyPatch3(deps, body) {
|
|
|
28474
28812
|
const cwd = deps.runtimeContext.cwd;
|
|
28475
28813
|
const policyChanged = typeof body.allowSidecarWriters === "boolean" && writeSidecarWritersPolicy(body.allowSidecarWriters, cwd);
|
|
28476
28814
|
const scan = applyScanWrites(body, cwd);
|
|
28815
|
+
const trustChanged = applyTrustWrite(body, cwd);
|
|
28477
28816
|
if (policyChanged || scan.mutated) await maybeRestartWatcher2(deps);
|
|
28478
|
-
if (policyChanged || scan.attempted) deps.configService.reload();
|
|
28817
|
+
if (policyChanged || scan.attempted || trustChanged) deps.configService.reload();
|
|
28818
|
+
}
|
|
28819
|
+
function applyTrustWrite(body, cwd) {
|
|
28820
|
+
const next = body.pluginTrust?.projectEnabled;
|
|
28821
|
+
if (next === void 0) return false;
|
|
28822
|
+
const before = readConfigValue("pluginTrust.projectEnabled", { cwd, default: false }) ?? false;
|
|
28823
|
+
if (before === next) return false;
|
|
28824
|
+
if (projectTrustExposure({ value: next, cwd }).expandsSurface && body.confirm !== true) {
|
|
28825
|
+
throw new HTTPException13(412, {
|
|
28826
|
+
message: SERVER_TEXTS.projectPrefsTrustConfirmRequired
|
|
28827
|
+
});
|
|
28828
|
+
}
|
|
28829
|
+
try {
|
|
28830
|
+
writeConfigValue("pluginTrust.projectEnabled", next, { target: "project-local", cwd });
|
|
28831
|
+
} catch (err) {
|
|
28832
|
+
throw new HTTPException13(400, {
|
|
28833
|
+
message: tx(SERVER_TEXTS.projectPrefsPersistFailed, {
|
|
28834
|
+
key: "pluginTrust.projectEnabled",
|
|
28835
|
+
message: formatErrorMessage(err)
|
|
28836
|
+
})
|
|
28837
|
+
});
|
|
28838
|
+
}
|
|
28839
|
+
log.warn(tx(SERVER_TEXTS.projectPrefsTrustSet, { value: String(next) }));
|
|
28840
|
+
return true;
|
|
28479
28841
|
}
|
|
28480
28842
|
function applyScanWrites(body, cwd) {
|
|
28481
28843
|
const writes = collectWrites(body);
|
|
@@ -28627,7 +28989,11 @@ function isExistingDirectory(entry, cwd) {
|
|
|
28627
28989
|
var PATCH_BODY_SCHEMA3 = {
|
|
28628
28990
|
type: "object",
|
|
28629
28991
|
additionalProperties: false,
|
|
28630
|
-
anyOf: [
|
|
28992
|
+
anyOf: [
|
|
28993
|
+
{ required: ["allowSidecarWriters"] },
|
|
28994
|
+
{ required: ["scan"] },
|
|
28995
|
+
{ required: ["pluginTrust"] }
|
|
28996
|
+
],
|
|
28631
28997
|
properties: {
|
|
28632
28998
|
confirm: { type: "boolean" },
|
|
28633
28999
|
allowSidecarWriters: { type: "boolean" },
|
|
@@ -28641,6 +29007,14 @@ var PATCH_BODY_SCHEMA3 = {
|
|
|
28641
29007
|
items: { type: "string", pattern: "^[^,]+$" }
|
|
28642
29008
|
}
|
|
28643
29009
|
}
|
|
29010
|
+
},
|
|
29011
|
+
pluginTrust: {
|
|
29012
|
+
type: "object",
|
|
29013
|
+
additionalProperties: false,
|
|
29014
|
+
minProperties: 1,
|
|
29015
|
+
properties: {
|
|
29016
|
+
projectEnabled: { type: "boolean" }
|
|
29017
|
+
}
|
|
28644
29018
|
}
|
|
28645
29019
|
}
|
|
28646
29020
|
};
|
|
@@ -28652,6 +29026,9 @@ var parsePatchBody4 = makeBodyValidator(PATCH_BODY_SCHEMA3, {
|
|
|
28652
29026
|
":anyOf": SERVER_TEXTS.projectPrefsBodyEmpty,
|
|
28653
29027
|
"/scan:minProperties": SERVER_TEXTS.projectPrefsBodyEmpty,
|
|
28654
29028
|
"/scan:type:object": SERVER_TEXTS.projectPrefsScanNotObject,
|
|
29029
|
+
"/pluginTrust:minProperties": SERVER_TEXTS.projectPrefsBodyEmpty,
|
|
29030
|
+
"/pluginTrust:type:object": SERVER_TEXTS.projectPrefsTrustNotObject,
|
|
29031
|
+
"/pluginTrust/projectEnabled:type:boolean": SERVER_TEXTS.projectPrefsTrustEnabledNotBoolean,
|
|
28655
29032
|
"/confirm:type:boolean": SERVER_TEXTS.projectPrefsConfirmNotBoolean,
|
|
28656
29033
|
"/allowSidecarWriters:type:boolean": SERVER_TEXTS.projectPrefsSidecarWritersNotBoolean,
|
|
28657
29034
|
"/scan/referencePaths:type:array": tx(SERVER_TEXTS.projectPrefsListNotArray, { key: "scan.referencePaths" }),
|
|
@@ -28694,9 +29071,7 @@ async function buildEnvelope4(deps) {
|
|
|
28694
29071
|
}
|
|
28695
29072
|
async function resolveSelectableProviders(deps) {
|
|
28696
29073
|
const resolveEnabled = await buildFreshResolver({
|
|
28697
|
-
|
|
28698
|
-
effectiveConfig: () => deps.configService.effective(),
|
|
28699
|
-
fallbackResolver: deps.pluginRuntime.resolveEnabled
|
|
29074
|
+
effectiveConfig: () => deps.configService.effective()
|
|
28700
29075
|
});
|
|
28701
29076
|
const selectable = /* @__PURE__ */ new Set();
|
|
28702
29077
|
for (const provider of deps.providers) {
|
|
@@ -29263,9 +29638,7 @@ async function runPersistedScan(c, deps) {
|
|
|
29263
29638
|
}
|
|
29264
29639
|
async function buildBffResolverOverride(deps) {
|
|
29265
29640
|
return buildFreshResolver({
|
|
29266
|
-
|
|
29267
|
-
effectiveConfig: () => deps.configService.effective(),
|
|
29268
|
-
fallbackResolver: deps.pluginRuntime.resolveEnabled
|
|
29641
|
+
effectiveConfig: () => deps.configService.effective()
|
|
29269
29642
|
});
|
|
29270
29643
|
}
|
|
29271
29644
|
async function loadPersistedScanMeta(deps) {
|
|
@@ -30604,7 +30977,7 @@ var SERVE_TEXTS = {
|
|
|
30604
30977
|
// cli/commands/serve.ts
|
|
30605
30978
|
var ServeCommand = class extends SmCommand {
|
|
30606
30979
|
static paths = [["serve"]];
|
|
30607
|
-
static usage =
|
|
30980
|
+
static usage = Command36.Usage({
|
|
30608
30981
|
category: "Setup",
|
|
30609
30982
|
description: "Start the Hono BFF (single-port: REST + WebSocket + SPA bundle).",
|
|
30610
30983
|
details: `
|
|
@@ -30628,18 +31001,18 @@ var ServeCommand = class extends SmCommand {
|
|
|
30628
31001
|
["Point at a pre-built UI bundle", "$0 serve --ui-dist ./ui/dist/browser"]
|
|
30629
31002
|
]
|
|
30630
31003
|
});
|
|
30631
|
-
port =
|
|
31004
|
+
port = Option34.String("--port", {
|
|
30632
31005
|
required: false,
|
|
30633
31006
|
description: "Listening port (default 4242). 0 = OS-assigned."
|
|
30634
31007
|
});
|
|
30635
|
-
host =
|
|
31008
|
+
host = Option34.String("--host", {
|
|
30636
31009
|
required: false,
|
|
30637
31010
|
description: "Listening host (default 127.0.0.1). Loopback-only enforced when --dev-cors is set."
|
|
30638
31011
|
});
|
|
30639
|
-
noBuiltIns =
|
|
31012
|
+
noBuiltIns = Option34.Boolean("--no-built-ins", false, {
|
|
30640
31013
|
description: "Skip built-in plugin registration (parity with sm scan --no-built-ins)."
|
|
30641
31014
|
});
|
|
30642
|
-
noPlugins =
|
|
31015
|
+
noPlugins = Option34.Boolean("--no-plugins", false, {
|
|
30643
31016
|
description: "Skip drop-in plugin discovery."
|
|
30644
31017
|
});
|
|
30645
31018
|
// `Option.Boolean('--open', true)`, Clipanion's parser auto-derives
|
|
@@ -30649,35 +31022,35 @@ var ServeCommand = class extends SmCommand {
|
|
|
30649
31022
|
// two registrations for the same flag and rejects the invocation
|
|
30650
31023
|
// with "Ambiguous Syntax Error". Same convention shipped by every
|
|
30651
31024
|
// other `--no-...` flag in the CLI tree.
|
|
30652
|
-
open =
|
|
31025
|
+
open = Option34.Boolean("--open", true, {
|
|
30653
31026
|
description: "Auto-open the SPA in the user's default browser after listen. --no-open opts out."
|
|
30654
31027
|
});
|
|
30655
|
-
devCors =
|
|
31028
|
+
devCors = Option34.Boolean("--dev-cors", false, {
|
|
30656
31029
|
description: "Enable permissive CORS for the Angular dev-server proxy workflow."
|
|
30657
31030
|
});
|
|
30658
31031
|
// `--ui-dist` is intentionally undocumented in the Usage block above
|
|
30659
31032
|
// (the demo build pipeline + tests rely on it; everyday users never
|
|
30660
31033
|
// need it). Clipanion still exposes it on the parser; the Usage
|
|
30661
31034
|
// omission is the "hidden" contract per the 14.1 brief.
|
|
30662
|
-
uiDist =
|
|
30663
|
-
noUi =
|
|
31035
|
+
uiDist = Option34.String("--ui-dist", { required: false, hidden: true });
|
|
31036
|
+
noUi = Option34.Boolean("--no-ui", false, {
|
|
30664
31037
|
description: "Don't serve the Angular UI bundle. Use this when running the BFF alongside `ui:dev` (Angular dev server with HMR). The root `/` then renders an inline placeholder pointing the user at the dev server."
|
|
30665
31038
|
});
|
|
30666
|
-
noWatcher =
|
|
31039
|
+
noWatcher = Option34.Boolean("--no-watcher", false, {
|
|
30667
31040
|
description: "Disable the chokidar-fed scan-and-broadcast loop. Use only for CI / read-only deployments."
|
|
30668
31041
|
});
|
|
30669
|
-
yes =
|
|
31042
|
+
yes = Option34.Boolean("--yes", false, {
|
|
30670
31043
|
description: "Skip the interactive prompt and rebuild the local cache when the on-disk DB has drifted (version skew or an inline schema change). Non-TTY invocations rebuild without asking regardless of this flag."
|
|
30671
31044
|
});
|
|
30672
31045
|
// `--watcher-debounce-ms` is undocumented sugar for advanced users
|
|
30673
31046
|
// who want to tighten / relax the watcher's batching window without
|
|
30674
31047
|
// editing settings.json. Hidden flag, the Usage block omits it.
|
|
30675
|
-
watcherDebounceMs =
|
|
30676
|
-
maxScan =
|
|
31048
|
+
watcherDebounceMs = Option34.String("--watcher-debounce-ms", { required: false, hidden: true });
|
|
31049
|
+
maxScan = Option34.String("--max-scan", {
|
|
30677
31050
|
required: false,
|
|
30678
31051
|
description: "Per-invocation override of scan.maxScan (default 50000), the WALK-INTAKE ceiling. The scan walks, parses, analyzes, and reference-validates the full corpus up to this number. Bidirectional: raises OR lowers the ceiling. Applies to every scan the server runs (initial watcher pass, debounced batches, POST /api/scan, GET /api/scan?fresh=1). Same flag is honoured on the bare `sm` invocation, which routes to `sm serve`."
|
|
30679
31052
|
});
|
|
30680
|
-
maxNodes =
|
|
31053
|
+
maxNodes = Option34.String("--max-nodes", {
|
|
30681
31054
|
required: false,
|
|
30682
31055
|
description: "Per-invocation override of scan.maxNodes (default 256), the MAP RENDER cap (pure metadata): it does NOT bound the scan, only how many nodes the graph view projects onto the canvas. Bidirectional: raises OR lowers the render cap. Same flag is honoured on the bare `sm` invocation, which routes to `sm serve`."
|
|
30683
31056
|
});
|
|
@@ -31041,7 +31414,7 @@ function tryOpenBrowser(url, stderr, warnGlyph) {
|
|
|
31041
31414
|
}
|
|
31042
31415
|
|
|
31043
31416
|
// cli/commands/show.ts
|
|
31044
|
-
import { Command as
|
|
31417
|
+
import { Command as Command37, Option as Option35 } from "clipanion";
|
|
31045
31418
|
|
|
31046
31419
|
// cli/i18n/show.texts.ts
|
|
31047
31420
|
var SHOW_TEXTS = {
|
|
@@ -31092,7 +31465,7 @@ var SHOW_TEXTS = {
|
|
|
31092
31465
|
// cli/commands/show.ts
|
|
31093
31466
|
var ShowCommand = class extends SmCommand {
|
|
31094
31467
|
static paths = [["show"]];
|
|
31095
|
-
static usage =
|
|
31468
|
+
static usage = Command37.Usage({
|
|
31096
31469
|
category: "Browse",
|
|
31097
31470
|
description: "Node detail: weight, frontmatter, links, issues.",
|
|
31098
31471
|
details: `
|
|
@@ -31108,7 +31481,7 @@ var ShowCommand = class extends SmCommand {
|
|
|
31108
31481
|
["Machine-readable detail", "$0 show .claude/agents/architect.md --json"]
|
|
31109
31482
|
]
|
|
31110
31483
|
});
|
|
31111
|
-
nodePath =
|
|
31484
|
+
nodePath = Option35.String({ required: true });
|
|
31112
31485
|
async run() {
|
|
31113
31486
|
const dbPath = resolveDbPath({ db: this.db, ...defaultRuntimeContext() });
|
|
31114
31487
|
const exit = requireDbOrExit(dbPath, this.context.stderr);
|
|
@@ -31350,7 +31723,7 @@ function rankConfidenceForGrouping(c) {
|
|
|
31350
31723
|
// cli/commands/sidecar.ts
|
|
31351
31724
|
import { unlink as unlink3 } from "fs/promises";
|
|
31352
31725
|
import { resolve as resolve43 } from "path";
|
|
31353
|
-
import { Command as
|
|
31726
|
+
import { Command as Command38, Option as Option36 } from "clipanion";
|
|
31354
31727
|
|
|
31355
31728
|
// cli/i18n/sidecar.texts.ts
|
|
31356
31729
|
var SIDECAR_TEXTS = {
|
|
@@ -31431,7 +31804,7 @@ async function runWithSidecarConsent(bag, ansi, dispatch) {
|
|
|
31431
31804
|
}
|
|
31432
31805
|
var SidecarRefreshCommand = class extends SmCommand {
|
|
31433
31806
|
static paths = [["sidecar", "refresh"]];
|
|
31434
|
-
static usage =
|
|
31807
|
+
static usage = Command38.Usage({
|
|
31435
31808
|
category: "Actions",
|
|
31436
31809
|
description: "Refresh a sidecar's `for.{bodyHash, frontmatterHash}` to match the live node. Does NOT bump the version.",
|
|
31437
31810
|
details: `
|
|
@@ -31448,8 +31821,8 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
31448
31821
|
["Refresh a node's sidecar hashes", "$0 sidecar refresh .claude/agents/architect.md"]
|
|
31449
31822
|
]
|
|
31450
31823
|
});
|
|
31451
|
-
nodePath =
|
|
31452
|
-
yes =
|
|
31824
|
+
nodePath = Option36.String({ required: true });
|
|
31825
|
+
yes = Option36.Boolean("--yes", false, {
|
|
31453
31826
|
description: "Confirm writing .sm sidecar files in this project (sets allowEditSmFiles=true on first run)."
|
|
31454
31827
|
});
|
|
31455
31828
|
async run() {
|
|
@@ -31571,7 +31944,7 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
31571
31944
|
};
|
|
31572
31945
|
var SidecarPruneCommand = class extends SmCommand {
|
|
31573
31946
|
static paths = [["sidecar", "prune"]];
|
|
31574
|
-
static usage =
|
|
31947
|
+
static usage = Command38.Usage({
|
|
31575
31948
|
category: "Actions",
|
|
31576
31949
|
description: "Delete orphan .sm files (sidecars whose accompanying .md no longer exists).",
|
|
31577
31950
|
details: `
|
|
@@ -31593,8 +31966,8 @@ var SidecarPruneCommand = class extends SmCommand {
|
|
|
31593
31966
|
["Delete every orphan .sm file (non-interactive)", "$0 sidecar prune --yes"]
|
|
31594
31967
|
]
|
|
31595
31968
|
});
|
|
31596
|
-
dryRun =
|
|
31597
|
-
yes =
|
|
31969
|
+
dryRun = Option36.Boolean("-n,--dry-run", false);
|
|
31970
|
+
yes = Option36.Boolean("--yes,--force", false, {
|
|
31598
31971
|
description: "Skip the interactive confirmation prompt. Required for non-interactive callers (CI, pre-commit hooks)."
|
|
31599
31972
|
});
|
|
31600
31973
|
// Complexity is from per-orphan handling, empty-set / dry-run /
|
|
@@ -31714,7 +32087,7 @@ var SidecarPruneCommand = class extends SmCommand {
|
|
|
31714
32087
|
};
|
|
31715
32088
|
var SidecarAnnotateCommand = class extends SmCommand {
|
|
31716
32089
|
static paths = [["sidecar", "annotate"]];
|
|
31717
|
-
static usage =
|
|
32090
|
+
static usage = Command38.Usage({
|
|
31718
32091
|
category: "Actions",
|
|
31719
32092
|
description: "Scaffold an empty `<basename>.sm` next to a node ready for editing.",
|
|
31720
32093
|
details: `
|
|
@@ -31732,9 +32105,9 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
31732
32105
|
["Overwrite an existing one", "$0 sidecar annotate .claude/agents/architect.md --force"]
|
|
31733
32106
|
]
|
|
31734
32107
|
});
|
|
31735
|
-
nodePath =
|
|
31736
|
-
force =
|
|
31737
|
-
yes =
|
|
32108
|
+
nodePath = Option36.String({ required: true });
|
|
32109
|
+
force = Option36.Boolean("--force", false);
|
|
32110
|
+
yes = Option36.Boolean("--yes", false, {
|
|
31738
32111
|
description: "Confirm writing .sm sidecar files in this project (sets allowEditSmFiles=true on first run)."
|
|
31739
32112
|
});
|
|
31740
32113
|
async run() {
|
|
@@ -31873,7 +32246,7 @@ var SIDECAR_COMMANDS = [
|
|
|
31873
32246
|
];
|
|
31874
32247
|
|
|
31875
32248
|
// cli/commands/stubs.ts
|
|
31876
|
-
import { Command as
|
|
32249
|
+
import { Command as Command39, Option as Option37 } from "clipanion";
|
|
31877
32250
|
|
|
31878
32251
|
// cli/i18n/stubs.texts.ts
|
|
31879
32252
|
var STUBS_TEXTS = {
|
|
@@ -31899,7 +32272,7 @@ var StubCommand = class extends SmCommand {
|
|
|
31899
32272
|
};
|
|
31900
32273
|
var DoctorCommand = class extends StubCommand {
|
|
31901
32274
|
static paths = [["doctor"]];
|
|
31902
|
-
static usage =
|
|
32275
|
+
static usage = Command39.Usage({
|
|
31903
32276
|
category: "Setup",
|
|
31904
32277
|
description: planned("Diagnostic report: DB integrity, pending migrations, orphan rows, plugin status, runner availability.")
|
|
31905
32278
|
});
|
|
@@ -31907,18 +32280,18 @@ var DoctorCommand = class extends StubCommand {
|
|
|
31907
32280
|
};
|
|
31908
32281
|
var FindingsCommand = class extends StubCommand {
|
|
31909
32282
|
static paths = [["findings"]];
|
|
31910
|
-
static usage =
|
|
32283
|
+
static usage = Command39.Usage({
|
|
31911
32284
|
category: "Browse",
|
|
31912
32285
|
description: planned("Probabilistic findings: injection, stale summaries, low confidence.")
|
|
31913
32286
|
});
|
|
31914
|
-
kind =
|
|
31915
|
-
since =
|
|
31916
|
-
threshold =
|
|
32287
|
+
kind = Option37.String("--kind", { required: false });
|
|
32288
|
+
since = Option37.String("--since", { required: false });
|
|
32289
|
+
threshold = Option37.String("--threshold", { required: false });
|
|
31917
32290
|
verbName = "findings";
|
|
31918
32291
|
};
|
|
31919
32292
|
var ActionsListCommand = class extends StubCommand {
|
|
31920
32293
|
static paths = [["actions", "list"]];
|
|
31921
|
-
static usage =
|
|
32294
|
+
static usage = Command39.Usage({
|
|
31922
32295
|
category: "Jobs",
|
|
31923
32296
|
description: planned("Registered action types (manifest view).")
|
|
31924
32297
|
});
|
|
@@ -31926,103 +32299,103 @@ var ActionsListCommand = class extends StubCommand {
|
|
|
31926
32299
|
};
|
|
31927
32300
|
var ActionsShowCommand = class extends StubCommand {
|
|
31928
32301
|
static paths = [["actions", "show"]];
|
|
31929
|
-
static usage =
|
|
32302
|
+
static usage = Command39.Usage({
|
|
31930
32303
|
category: "Jobs",
|
|
31931
32304
|
description: planned("Full action manifest, including preconditions and expected duration.")
|
|
31932
32305
|
});
|
|
31933
|
-
id =
|
|
32306
|
+
id = Option37.String({ required: true });
|
|
31934
32307
|
verbName = "actions show";
|
|
31935
32308
|
};
|
|
31936
32309
|
var JobSubmitCommand = class extends StubCommand {
|
|
31937
32310
|
static paths = [["job", "submit"]];
|
|
31938
|
-
static usage =
|
|
32311
|
+
static usage = Command39.Usage({
|
|
31939
32312
|
category: "Jobs",
|
|
31940
32313
|
description: planned("Enqueue a single job or fan out to every matching node (--all).")
|
|
31941
32314
|
});
|
|
31942
|
-
action =
|
|
31943
|
-
node =
|
|
31944
|
-
all =
|
|
32315
|
+
action = Option37.String({ required: true });
|
|
32316
|
+
node = Option37.String("-n", { required: false });
|
|
32317
|
+
all = Option37.Boolean("--all", false);
|
|
31945
32318
|
// CLI flag stays `--run`; field name is `runFlag` per the
|
|
31946
32319
|
// shadow-avoidance convention documented on `SmCommand`.
|
|
31947
|
-
runFlag =
|
|
31948
|
-
force =
|
|
31949
|
-
ttl =
|
|
31950
|
-
priority =
|
|
32320
|
+
runFlag = Option37.Boolean("--run", false);
|
|
32321
|
+
force = Option37.Boolean("--force", false);
|
|
32322
|
+
ttl = Option37.String("--ttl", { required: false });
|
|
32323
|
+
priority = Option37.String("--priority", { required: false });
|
|
31951
32324
|
verbName = "job submit";
|
|
31952
32325
|
};
|
|
31953
32326
|
var JobListCommand = class extends StubCommand {
|
|
31954
32327
|
static paths = [["job", "list"]];
|
|
31955
|
-
static usage =
|
|
31956
|
-
status =
|
|
31957
|
-
action =
|
|
31958
|
-
node =
|
|
32328
|
+
static usage = Command39.Usage({ category: "Jobs", description: planned("List jobs.") });
|
|
32329
|
+
status = Option37.String("--status", { required: false });
|
|
32330
|
+
action = Option37.String("--action", { required: false });
|
|
32331
|
+
node = Option37.String("--node", { required: false });
|
|
31959
32332
|
verbName = "job list";
|
|
31960
32333
|
};
|
|
31961
32334
|
var JobShowCommand = class extends StubCommand {
|
|
31962
32335
|
static paths = [["job", "show"]];
|
|
31963
|
-
static usage =
|
|
31964
|
-
id =
|
|
32336
|
+
static usage = Command39.Usage({ category: "Jobs", description: planned("Job detail: state, claim time, TTL, runner, content hash.") });
|
|
32337
|
+
id = Option37.String({ required: true });
|
|
31965
32338
|
verbName = "job show";
|
|
31966
32339
|
};
|
|
31967
32340
|
var JobPreviewCommand = class extends StubCommand {
|
|
31968
32341
|
static paths = [["job", "preview"]];
|
|
31969
|
-
static usage =
|
|
31970
|
-
id =
|
|
32342
|
+
static usage = Command39.Usage({ category: "Jobs", description: planned("Render the job MD file without executing.") });
|
|
32343
|
+
id = Option37.String({ required: true });
|
|
31971
32344
|
verbName = "job preview";
|
|
31972
32345
|
};
|
|
31973
32346
|
var JobClaimCommand = class extends StubCommand {
|
|
31974
32347
|
static paths = [["job", "claim"]];
|
|
31975
|
-
static usage =
|
|
32348
|
+
static usage = Command39.Usage({
|
|
31976
32349
|
category: "Jobs",
|
|
31977
32350
|
description: planned("Atomic primitive: return next queued job id, mark it running.")
|
|
31978
32351
|
});
|
|
31979
|
-
filter =
|
|
32352
|
+
filter = Option37.String("--filter", { required: false });
|
|
31980
32353
|
verbName = "job claim";
|
|
31981
32354
|
};
|
|
31982
32355
|
var JobRunCommand = class extends StubCommand {
|
|
31983
32356
|
static paths = [["job", "run"]];
|
|
31984
|
-
static usage =
|
|
32357
|
+
static usage = Command39.Usage({
|
|
31985
32358
|
category: "Jobs",
|
|
31986
32359
|
description: planned("Full CLI-runner loop: claim + spawn + record.")
|
|
31987
32360
|
});
|
|
31988
|
-
all =
|
|
31989
|
-
max =
|
|
32361
|
+
all = Option37.Boolean("--all", false);
|
|
32362
|
+
max = Option37.String("--max", { required: false });
|
|
31990
32363
|
verbName = "job run";
|
|
31991
32364
|
};
|
|
31992
32365
|
var JobStatusCommand = class extends StubCommand {
|
|
31993
32366
|
static paths = [["job", "status"]];
|
|
31994
|
-
static usage =
|
|
32367
|
+
static usage = Command39.Usage({
|
|
31995
32368
|
category: "Jobs",
|
|
31996
32369
|
description: planned("Counts (per status) or single-job status.")
|
|
31997
32370
|
});
|
|
31998
|
-
id =
|
|
32371
|
+
id = Option37.String({ required: false });
|
|
31999
32372
|
verbName = "job status";
|
|
32000
32373
|
};
|
|
32001
32374
|
var JobCancelCommand = class extends StubCommand {
|
|
32002
32375
|
static paths = [["job", "cancel"]];
|
|
32003
|
-
static usage =
|
|
32376
|
+
static usage = Command39.Usage({
|
|
32004
32377
|
category: "Jobs",
|
|
32005
32378
|
description: planned("Force a running job to failed with reason user-cancelled.")
|
|
32006
32379
|
});
|
|
32007
|
-
id =
|
|
32008
|
-
all =
|
|
32380
|
+
id = Option37.String({ required: false });
|
|
32381
|
+
all = Option37.Boolean("--all", false);
|
|
32009
32382
|
verbName = "job cancel";
|
|
32010
32383
|
};
|
|
32011
32384
|
var RecordCommand = class extends StubCommand {
|
|
32012
32385
|
static paths = [["record"]];
|
|
32013
|
-
static usage =
|
|
32386
|
+
static usage = Command39.Usage({
|
|
32014
32387
|
category: "Jobs",
|
|
32015
32388
|
description: planned("Close a running job with success or failure. Nonce is the sole credential.")
|
|
32016
32389
|
});
|
|
32017
|
-
id =
|
|
32018
|
-
nonce =
|
|
32019
|
-
status =
|
|
32020
|
-
report =
|
|
32021
|
-
tokensIn =
|
|
32022
|
-
tokensOut =
|
|
32023
|
-
durationMs =
|
|
32024
|
-
model =
|
|
32025
|
-
error =
|
|
32390
|
+
id = Option37.String("--id", { required: true });
|
|
32391
|
+
nonce = Option37.String("--nonce", { required: true });
|
|
32392
|
+
status = Option37.String("--status", { required: true });
|
|
32393
|
+
report = Option37.String("--report", { required: false });
|
|
32394
|
+
tokensIn = Option37.String("--tokens-in", { required: false });
|
|
32395
|
+
tokensOut = Option37.String("--tokens-out", { required: false });
|
|
32396
|
+
durationMs = Option37.String("--duration-ms", { required: false });
|
|
32397
|
+
model = Option37.String("--model", { required: false });
|
|
32398
|
+
error = Option37.String("--error", { required: false });
|
|
32026
32399
|
verbName = "record";
|
|
32027
32400
|
};
|
|
32028
32401
|
var STUB_COMMANDS = [
|
|
@@ -32046,7 +32419,7 @@ import { cpSync as cpSync3, existsSync as existsSync33, mkdirSync as mkdirSync6,
|
|
|
32046
32419
|
import { dirname as dirname21, join as join21, resolve as resolve44 } from "path";
|
|
32047
32420
|
import { createInterface as createInterface6 } from "readline";
|
|
32048
32421
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
32049
|
-
import { Command as
|
|
32422
|
+
import { Command as Command40, Option as Option38 } from "clipanion";
|
|
32050
32423
|
|
|
32051
32424
|
// cli/i18n/tutorial.texts.ts
|
|
32052
32425
|
var TUTORIAL_TEXTS = {
|
|
@@ -32110,7 +32483,7 @@ var TRIGGER_EN = "run the tutorial";
|
|
|
32110
32483
|
var TRIGGER_ES = "ejecuta el tutorial";
|
|
32111
32484
|
var TutorialCommand = class extends SmCommand {
|
|
32112
32485
|
static paths = [["tutorial"]];
|
|
32113
|
-
static usage =
|
|
32486
|
+
static usage = Command40.Usage({
|
|
32114
32487
|
category: "Setup",
|
|
32115
32488
|
description: "Materialize an interactive tester tutorial as a Claude Code skill folder under `<cwd>/.claude/skills/`.",
|
|
32116
32489
|
details: `
|
|
@@ -32139,18 +32512,18 @@ var TutorialCommand = class extends SmCommand {
|
|
|
32139
32512
|
// more. Accept one so a stale `sm tutorial master` lands on a friendly
|
|
32140
32513
|
// usage error (guarded in `run()`) instead of clipanion's generic
|
|
32141
32514
|
// "extraneous argument" message.
|
|
32142
|
-
legacyPositional =
|
|
32515
|
+
legacyPositional = Option38.String({ required: false });
|
|
32143
32516
|
// Named `forProvider`, NOT `for` (reserved word). The CLI surface stays
|
|
32144
32517
|
// `--for`; selects the destination Provider whose `scaffold.skillDir`
|
|
32145
32518
|
// the skill is materialised under, skipping the interactive prompt.
|
|
32146
|
-
forProvider =
|
|
32519
|
+
forProvider = Option38.String("--for", {
|
|
32147
32520
|
required: false,
|
|
32148
32521
|
description: "Destination provider id (e.g. claude). Skips the prompt."
|
|
32149
32522
|
});
|
|
32150
|
-
force =
|
|
32523
|
+
force = Option38.Boolean("--force", false, {
|
|
32151
32524
|
description: "Overwrite an existing target directory without prompting."
|
|
32152
32525
|
});
|
|
32153
|
-
experimental =
|
|
32526
|
+
experimental = Option38.Boolean("--experimental", false, {
|
|
32154
32527
|
description: "Offer experimental providers as destinations. They ship disabled; enable the chosen one with `sm plugins enable <id>`."
|
|
32155
32528
|
});
|
|
32156
32529
|
async run() {
|
|
@@ -32384,7 +32757,7 @@ function resolveSkillSourceDir() {
|
|
|
32384
32757
|
}
|
|
32385
32758
|
|
|
32386
32759
|
// cli/commands/version.ts
|
|
32387
|
-
import { Command as
|
|
32760
|
+
import { Command as Command41 } from "clipanion";
|
|
32388
32761
|
|
|
32389
32762
|
// cli/i18n/version.texts.ts
|
|
32390
32763
|
var VERSION_TEXTS = {
|
|
@@ -32399,7 +32772,7 @@ var VERSION_TEXTS = {
|
|
|
32399
32772
|
// cli/commands/version.ts
|
|
32400
32773
|
var VersionCommand = class extends SmCommand {
|
|
32401
32774
|
static paths = [["version"]];
|
|
32402
|
-
static usage =
|
|
32775
|
+
static usage = Command41.Usage({
|
|
32403
32776
|
category: "Introspection",
|
|
32404
32777
|
description: "Print the CLI / spec / runtime / db-schema version matrix."
|
|
32405
32778
|
});
|
|
@@ -32616,4 +32989,4 @@ function resolveBareDefault() {
|
|
|
32616
32989
|
process.exit(ExitCode.Error);
|
|
32617
32990
|
}
|
|
32618
32991
|
//# sourceMappingURL=cli.js.map
|
|
32619
|
-
//# debugId=
|
|
32992
|
+
//# debugId=75d0c2c2-d08f-5d7c-aa62-3e1d53dd4ef1
|