@skill-map/cli 0.58.0 → 0.60.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/SKILL.md +12 -5
- package/dist/cli/tutorial/sm-tutorial/references/fixtures.md +15 -4
- package/dist/cli/tutorial/sm-tutorial/references/part-cli.md +3 -3
- package/dist/cli/tutorial/sm-tutorial/references/part-connect-harness.md +19 -15
- package/dist/cli/tutorial/sm-tutorial/references/part-daily-loop.md +4 -2
- package/dist/cli/tutorial/sm-tutorial/references/part-fundamentals.md +59 -44
- package/dist/cli/tutorial/sm-tutorial/references/part-project-kickoff.md +18 -0
- package/dist/cli.js +169 -84
- package/dist/index.js +3 -3
- package/dist/kernel/index.d.ts +20 -0
- package/dist/kernel/index.js +3 -3
- package/dist/ui/chunk-4N3NRZEH.js +809 -0
- package/dist/ui/chunk-5SSKJ7AM.js +1 -0
- package/dist/ui/{chunk-WB7FKIBP.js → chunk-7VUEZZFJ.js} +1 -1
- package/dist/ui/{chunk-P2DAPRK7.js → chunk-7X3DZNG4.js} +1 -1
- package/dist/ui/chunk-AKKFFP7Y.js +1 -0
- package/dist/ui/{chunk-ZJCU4CXS.js → chunk-COXOWJFC.js} +2 -2
- package/dist/ui/{chunk-JA4Z74I3.js → chunk-FRUHVCND.js} +1 -1
- package/dist/ui/chunk-GDZRZU57.js +1843 -0
- package/dist/ui/{chunk-K2MAVAHG.js → chunk-GKQA75EF.js} +1 -1
- package/dist/ui/chunk-HQ6M2HXK.js +369 -0
- package/dist/ui/chunk-JRVAI7GI.js +2 -0
- package/dist/ui/chunk-JTCIY3SL.js +742 -0
- package/dist/ui/chunk-MBBJJEUX.js +917 -0
- package/dist/ui/{chunk-LCOYSPKE.js → chunk-MGWGV4VD.js} +1 -1
- package/dist/ui/chunk-N6MUHKWR.js +105 -0
- package/dist/ui/chunk-OGXBHDY4.js +1 -0
- package/dist/ui/{chunk-KHARMPTZ.js → chunk-OVVTCPBJ.js} +1 -1
- package/dist/ui/{chunk-UBQUCSQ4.js → chunk-Q4PXVDJA.js} +1 -1
- package/dist/ui/chunk-ZYPXVXYF.js +4 -0
- package/dist/ui/index.html +1 -1
- package/dist/ui/main-5MKN73KQ.js +4 -0
- package/package.json +2 -2
- package/dist/ui/chunk-DPLNM4UD.js +0 -2
- package/dist/ui/chunk-G3ZVF4TM.js +0 -1
- package/dist/ui/chunk-H6O2DYVT.js +0 -1110
- package/dist/ui/chunk-KJZQIUZA.js +0 -917
- package/dist/ui/chunk-Q2A6FWC7.js +0 -4
- package/dist/ui/chunk-QVNZN5F7.js +0 -1843
- package/dist/ui/chunk-SXXFDP6V.js +0 -1
- package/dist/ui/chunk-YHJL5LP3.js +0 -913
- package/dist/ui/main-KOFMNAVE.js +0 -4
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]="7e14428f-63d1-5e95-8756-98cea6d3c76e")}catch(e){}}();
|
|
4
4
|
import { existsSync as existsSync33 } 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.60.0",
|
|
254
254
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
255
255
|
license: "MIT",
|
|
256
256
|
type: "module",
|
|
@@ -1812,10 +1812,6 @@ var annotationFieldUnknownAnalyzer = {
|
|
|
1812
1812
|
const rootKeys = indexRootContributions(contributions);
|
|
1813
1813
|
const knownPluginIds = collectPluginIds(contributions);
|
|
1814
1814
|
const issues = [];
|
|
1815
|
-
const perNode = /* @__PURE__ */ new Map();
|
|
1816
|
-
const bump2 = (nodePath) => {
|
|
1817
|
-
perNode.set(nodePath, (perNode.get(nodePath) ?? 0) + 1);
|
|
1818
|
-
};
|
|
1819
1815
|
for (const node of ctx.nodes) {
|
|
1820
1816
|
const root = sidecarRoots.get(node.path);
|
|
1821
1817
|
if (!root) continue;
|
|
@@ -1833,7 +1829,6 @@ var annotationFieldUnknownAnalyzer = {
|
|
|
1833
1829
|
}),
|
|
1834
1830
|
data: { surface: "annotations", key }
|
|
1835
1831
|
});
|
|
1836
|
-
bump2(node.path);
|
|
1837
1832
|
}
|
|
1838
1833
|
}
|
|
1839
1834
|
}
|
|
@@ -1862,7 +1857,6 @@ var annotationFieldUnknownAnalyzer = {
|
|
|
1862
1857
|
}),
|
|
1863
1858
|
data: { surface: "plugin-namespace", pluginId: key, key: contribKey }
|
|
1864
1859
|
});
|
|
1865
|
-
bump2(node.path);
|
|
1866
1860
|
}
|
|
1867
1861
|
continue;
|
|
1868
1862
|
}
|
|
@@ -1876,10 +1870,8 @@ var annotationFieldUnknownAnalyzer = {
|
|
|
1876
1870
|
}),
|
|
1877
1871
|
data: { surface: "root", key }
|
|
1878
1872
|
});
|
|
1879
|
-
bump2(node.path);
|
|
1880
1873
|
}
|
|
1881
1874
|
}
|
|
1882
|
-
void perNode;
|
|
1883
1875
|
return issues;
|
|
1884
1876
|
}
|
|
1885
1877
|
};
|
|
@@ -2015,6 +2007,10 @@ var annotationStaleAnalyzer = {
|
|
|
2015
2007
|
pluginId: CORE_PLUGIN_ID,
|
|
2016
2008
|
kind: "analyzer",
|
|
2017
2009
|
description: "Marks sidecars (`.sm`) that are out of date with their `.md`.",
|
|
2010
|
+
// Ships experimental (disabled by default, Decision #128), gated as a
|
|
2011
|
+
// unit with the `core/node-bump` action that resolves the drift it
|
|
2012
|
+
// reports.
|
|
2013
|
+
stability: "experimental",
|
|
2018
2014
|
mode: "deterministic",
|
|
2019
2015
|
// The natural fix is to bump the node: refreshes the sidecar hashes,
|
|
2020
2016
|
// increments `annotations.version`, and stamps the audit block. The
|
|
@@ -2661,14 +2657,14 @@ var experimental = {
|
|
|
2661
2657
|
slot: "card.footer.right",
|
|
2662
2658
|
icon: "fa-solid fa-flask",
|
|
2663
2659
|
label: "experimental",
|
|
2664
|
-
emitWhenEmpty:
|
|
2660
|
+
emitWhenEmpty: true,
|
|
2665
2661
|
priority: 10
|
|
2666
2662
|
};
|
|
2667
2663
|
var deprecated = {
|
|
2668
2664
|
slot: "card.footer.right",
|
|
2669
2665
|
icon: "pi-ban",
|
|
2670
2666
|
label: "deprecated",
|
|
2671
|
-
emitWhenEmpty:
|
|
2667
|
+
emitWhenEmpty: true,
|
|
2672
2668
|
priority: 10
|
|
2673
2669
|
};
|
|
2674
2670
|
var nodeStabilityAnalyzer = {
|
|
@@ -3663,7 +3659,16 @@ var nodeBumpAction = {
|
|
|
3663
3659
|
pluginId: CORE_PLUGIN_ID,
|
|
3664
3660
|
kind: "action",
|
|
3665
3661
|
description: "Marks a node as updated: bumps `annotations.version`, refreshes sidecar hashes, and records the timestamp.",
|
|
3662
|
+
// Ships experimental (disabled by default, Decision #128), gated as a
|
|
3663
|
+
// unit with the companion `core/annotation-stale` analyzer: a disabled
|
|
3664
|
+
// action projects no Bump button, so the button never appears without
|
|
3665
|
+
// the drift analyzer that motivates it.
|
|
3666
|
+
stability: "experimental",
|
|
3666
3667
|
mode: "deterministic",
|
|
3668
|
+
// Declares the sidecar-write capability: `invoke()` returns a
|
|
3669
|
+
// `{ kind: 'sidecar' }` write, so consumers (the `allowSidecarWriters`
|
|
3670
|
+
// policy) can gate this action without invoking it.
|
|
3671
|
+
writes: ["sidecar"],
|
|
3667
3672
|
ui: { bumpButton },
|
|
3668
3673
|
project(ctx) {
|
|
3669
3674
|
for (const node of ctx.nodes) {
|
|
@@ -3764,6 +3769,10 @@ var nodeSetStabilityAction = {
|
|
|
3764
3769
|
kind: "action",
|
|
3765
3770
|
description: "Sets the lifecycle stage of the current node (writes `stability` to the sidecar).",
|
|
3766
3771
|
mode: "deterministic",
|
|
3772
|
+
// Declares the sidecar-write capability: `invoke()` returns a
|
|
3773
|
+
// `{ kind: 'sidecar' }` write, so the `allowSidecarWriters` policy can
|
|
3774
|
+
// gate this action without invoking it.
|
|
3775
|
+
writes: ["sidecar"],
|
|
3767
3776
|
ui: { setStabilityButton },
|
|
3768
3777
|
project(ctx) {
|
|
3769
3778
|
for (const node of ctx.nodes) {
|
|
@@ -3826,33 +3835,18 @@ function invokeSetStability(input, ctx) {
|
|
|
3826
3835
|
return { report, writes: [write] };
|
|
3827
3836
|
}
|
|
3828
3837
|
|
|
3829
|
-
// plugins/core/actions/node-set-tags/text.ts
|
|
3830
|
-
var TAGS_TEXTS = {
|
|
3831
|
-
/** Label of the inspector action button that edits the node's tags. */
|
|
3832
|
-
editLabel: "Edit tags",
|
|
3833
|
-
/** Prompt label for the string-list tags input. */
|
|
3834
|
-
promptLabel: "Tags"
|
|
3835
|
-
};
|
|
3836
|
-
|
|
3837
3838
|
// plugins/core/actions/node-set-tags/index.ts
|
|
3838
3839
|
var ID27 = "node-set-tags";
|
|
3839
|
-
var setTagsButton = {
|
|
3840
|
-
slot: "inspector.action.button",
|
|
3841
|
-
priority: 15
|
|
3842
|
-
};
|
|
3843
3840
|
var nodeSetTagsAction = {
|
|
3844
3841
|
id: ID27,
|
|
3845
3842
|
pluginId: CORE_PLUGIN_ID,
|
|
3846
3843
|
kind: "action",
|
|
3847
3844
|
description: "Sets the taxonomy tags of the current node (writes `tags` to the sidecar; whole-array replace).",
|
|
3848
3845
|
mode: "deterministic",
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
emitSetTagsButton(ctx, node);
|
|
3854
|
-
}
|
|
3855
|
-
},
|
|
3846
|
+
// Declares the sidecar-write capability: `invoke()` returns a
|
|
3847
|
+
// `{ kind: 'sidecar' }` write, so the `allowSidecarWriters` policy can
|
|
3848
|
+
// gate this action without invoking it.
|
|
3849
|
+
writes: ["sidecar"],
|
|
3856
3850
|
// The runtime contract uses generic <TInput, TReport>; this narrows
|
|
3857
3851
|
// both. The cast is the standard pattern for built-ins that want
|
|
3858
3852
|
// typed local I/O while staying compatible with the open generic.
|
|
@@ -3861,29 +3855,21 @@ var nodeSetTagsAction = {
|
|
|
3861
3855
|
return invokeSetTags(input, ctx);
|
|
3862
3856
|
}
|
|
3863
3857
|
};
|
|
3864
|
-
function
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
});
|
|
3877
|
-
}
|
|
3878
|
-
function currentTags(node) {
|
|
3879
|
-
const ann = node.sidecar?.annotations;
|
|
3880
|
-
if (!ann || typeof ann !== "object" || Array.isArray(ann)) return [];
|
|
3881
|
-
const value = ann["tags"];
|
|
3882
|
-
if (!Array.isArray(value)) return [];
|
|
3883
|
-
return value.filter((t) => typeof t === "string");
|
|
3858
|
+
function sanitizeTags(raw) {
|
|
3859
|
+
if (!Array.isArray(raw)) return [];
|
|
3860
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3861
|
+
const out = [];
|
|
3862
|
+
for (const entry of raw) {
|
|
3863
|
+
if (typeof entry !== "string") continue;
|
|
3864
|
+
const tag = entry.trim();
|
|
3865
|
+
if (tag.length === 0 || seen.has(tag)) continue;
|
|
3866
|
+
seen.add(tag);
|
|
3867
|
+
out.push(tag);
|
|
3868
|
+
}
|
|
3869
|
+
return out;
|
|
3884
3870
|
}
|
|
3885
3871
|
function invokeSetTags(input, ctx) {
|
|
3886
|
-
const tags =
|
|
3872
|
+
const tags = sanitizeTags(input.tags);
|
|
3887
3873
|
const timestamp = ctx.now().toISOString();
|
|
3888
3874
|
const write = {
|
|
3889
3875
|
kind: "sidecar",
|
|
@@ -5306,6 +5292,7 @@ var CONFIG_LOADER_TEXTS = {
|
|
|
5306
5292
|
var defaults_default = {
|
|
5307
5293
|
schemaVersion: 1,
|
|
5308
5294
|
allowEditSmFiles: false,
|
|
5295
|
+
allowSidecarWriters: true,
|
|
5309
5296
|
tokenizer: "cl100k_base",
|
|
5310
5297
|
roots: [],
|
|
5311
5298
|
ignore: [],
|
|
@@ -5728,7 +5715,27 @@ var EConsentRequiredError = class extends Error {
|
|
|
5728
5715
|
this.hintTarget = init.hintTarget;
|
|
5729
5716
|
}
|
|
5730
5717
|
};
|
|
5718
|
+
var ESidecarWritersForbiddenError = class extends Error {
|
|
5719
|
+
key;
|
|
5720
|
+
constructor(init) {
|
|
5721
|
+
super(
|
|
5722
|
+
`Sidecar-writing extensions are disabled in this project ('${init.key}' is false in .skill-map/settings.json). This is a team-level project policy and cannot be overridden.`
|
|
5723
|
+
);
|
|
5724
|
+
this.name = "ESidecarWritersForbiddenError";
|
|
5725
|
+
this.key = init.key;
|
|
5726
|
+
}
|
|
5727
|
+
};
|
|
5728
|
+
function assertSidecarWritersAllowed(cwd) {
|
|
5729
|
+
const allowed = readConfigValue("allowSidecarWriters", {
|
|
5730
|
+
cwd,
|
|
5731
|
+
default: true
|
|
5732
|
+
});
|
|
5733
|
+
if (allowed === false) {
|
|
5734
|
+
throw new ESidecarWritersForbiddenError({ key: "allowSidecarWriters" });
|
|
5735
|
+
}
|
|
5736
|
+
}
|
|
5731
5737
|
function ensureSidecarWritesAllowed(opts) {
|
|
5738
|
+
assertSidecarWritersAllowed(opts.cwd);
|
|
5732
5739
|
const allowed = readConfigValue("allowEditSmFiles", {
|
|
5733
5740
|
cwd: opts.cwd,
|
|
5734
5741
|
default: false
|
|
@@ -8635,13 +8642,18 @@ function applyIssueFilters(query, filter) {
|
|
|
8635
8642
|
const tokens = filter.analyzerIds;
|
|
8636
8643
|
q = q.where(
|
|
8637
8644
|
({ eb, or }) => or(
|
|
8638
|
-
tokens.flatMap((token) =>
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
+
tokens.flatMap((token) => {
|
|
8646
|
+
const conds = [
|
|
8647
|
+
eb("analyzerId", "=", token),
|
|
8648
|
+
// `'%/' || ?` keeps the LIKE pattern's `%` literal in the
|
|
8649
|
+
// template and binds `token` separately, no interpolation of
|
|
8650
|
+
// user input into the SQL string.
|
|
8651
|
+
eb("analyzerId", "like", `%/${token}`)
|
|
8652
|
+
];
|
|
8653
|
+
const slash = token.indexOf("/");
|
|
8654
|
+
if (slash >= 0) conds.push(eb("analyzerId", "=", token.slice(slash + 1)));
|
|
8655
|
+
return conds;
|
|
8656
|
+
})
|
|
8645
8657
|
)
|
|
8646
8658
|
);
|
|
8647
8659
|
}
|
|
@@ -9119,6 +9131,8 @@ var BumpCommand = class extends SmCommand {
|
|
|
9119
9131
|
const flagError = this.#validateFlagCombo(ansi);
|
|
9120
9132
|
if (flagError !== null) return flagError;
|
|
9121
9133
|
const ctx = defaultRuntimeContext();
|
|
9134
|
+
const policyError = this.#assertWritersAllowed(ansi, ctx.cwd);
|
|
9135
|
+
if (policyError !== null) return policyError;
|
|
9122
9136
|
const dbPath = resolveDbPath({ db: this.db, ...ctx });
|
|
9123
9137
|
const persisted = await tryWithSqlite(
|
|
9124
9138
|
{ databasePath: dbPath, autoBackup: false },
|
|
@@ -9139,6 +9153,22 @@ var BumpCommand = class extends SmCommand {
|
|
|
9139
9153
|
() => this.pending ? this.#runPending(persisted.nodes, ctx.cwd, ansi) : this.#runSingle(persisted.nodes, ctx.cwd, ansi)
|
|
9140
9154
|
);
|
|
9141
9155
|
}
|
|
9156
|
+
/**
|
|
9157
|
+
* Fail-fast guard for the `allowSidecarWriters: false` project policy.
|
|
9158
|
+
* Returns `ExitCode.Error` (after printing the policy message) when
|
|
9159
|
+
* sidecar writers are forbidden, or `null` when writes may proceed.
|
|
9160
|
+
* Re-throws any non-policy error so unexpected failures still surface.
|
|
9161
|
+
*/
|
|
9162
|
+
#assertWritersAllowed(ansi, cwd) {
|
|
9163
|
+
try {
|
|
9164
|
+
assertSidecarWritersAllowed(cwd);
|
|
9165
|
+
return null;
|
|
9166
|
+
} catch (err) {
|
|
9167
|
+
if (!(err instanceof ESidecarWritersForbiddenError)) throw err;
|
|
9168
|
+
this.printer.error(`${ansi.red("\u2715")} ${err.message}`);
|
|
9169
|
+
return ExitCode.Error;
|
|
9170
|
+
}
|
|
9171
|
+
}
|
|
9142
9172
|
/**
|
|
9143
9173
|
* Three argument-validation guards, hoisted out of `run()` so the
|
|
9144
9174
|
* lint complexity cap on `run()` is satisfied without an
|
|
@@ -9546,11 +9576,12 @@ import { Command as Command3, Option as Option3 } from "clipanion";
|
|
|
9546
9576
|
function matchesAnalyzerFilter(analyzerId, filter) {
|
|
9547
9577
|
if (filter.length === 0) return true;
|
|
9548
9578
|
if (filter.includes(analyzerId)) return true;
|
|
9549
|
-
const
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
if (filter.includes(short)) return true;
|
|
9579
|
+
for (const entry of filter) {
|
|
9580
|
+
const slashIdx = entry.indexOf("/");
|
|
9581
|
+
if (slashIdx >= 0 && entry.slice(slashIdx + 1) === analyzerId) return true;
|
|
9553
9582
|
}
|
|
9583
|
+
const argSlashIdx = analyzerId.indexOf("/");
|
|
9584
|
+
if (argSlashIdx >= 0 && filter.includes(analyzerId.slice(argSlashIdx + 1))) return true;
|
|
9554
9585
|
return false;
|
|
9555
9586
|
}
|
|
9556
9587
|
|
|
@@ -11125,6 +11156,7 @@ function filterBuiltInManifests(manifests, resolveEnabled) {
|
|
|
11125
11156
|
function composeScanExtensions(opts) {
|
|
11126
11157
|
const resolveEnabled = opts.resolveEnabled ?? opts.pluginRuntime.resolveEnabled;
|
|
11127
11158
|
const resolveSettings = opts.resolveSettings;
|
|
11159
|
+
const forbidSidecarWriters = opts.forbidSidecarWriters === true;
|
|
11128
11160
|
const providers = [];
|
|
11129
11161
|
const extractors = [];
|
|
11130
11162
|
const analyzers = [];
|
|
@@ -11134,7 +11166,8 @@ function composeScanExtensions(opts) {
|
|
|
11134
11166
|
accumulateBuiltInScanExtensions(
|
|
11135
11167
|
{ providers, extractors, analyzers, hooks, actions },
|
|
11136
11168
|
resolveEnabled,
|
|
11137
|
-
resolveSettings
|
|
11169
|
+
resolveSettings,
|
|
11170
|
+
forbidSidecarWriters
|
|
11138
11171
|
);
|
|
11139
11172
|
}
|
|
11140
11173
|
for (const ext of opts.pluginRuntime.extensions.providers) {
|
|
@@ -11150,7 +11183,9 @@ function composeScanExtensions(opts) {
|
|
|
11150
11183
|
if (isPluginExtensionEnabled(ext, resolveEnabled)) hooks.push(withResolvedSettings(ext, resolveSettings));
|
|
11151
11184
|
}
|
|
11152
11185
|
for (const ext of opts.pluginRuntime.extensions.actions) {
|
|
11153
|
-
if (isPluginExtensionEnabled(ext, resolveEnabled))
|
|
11186
|
+
if (!isPluginExtensionEnabled(ext, resolveEnabled)) continue;
|
|
11187
|
+
if (forbidSidecarWriters && isSidecarWriterAction(ext)) continue;
|
|
11188
|
+
actions.push(ext);
|
|
11154
11189
|
}
|
|
11155
11190
|
const finalProviders = opts.killSwitches?.providers === true ? [] : providers;
|
|
11156
11191
|
const finalExtractors = opts.killSwitches?.extractors === true ? [] : extractors;
|
|
@@ -11170,7 +11205,10 @@ function withResolvedSettings(ext, resolveSettings) {
|
|
|
11170
11205
|
if (!resolveSettings) return ext;
|
|
11171
11206
|
return { ...ext, resolvedSettings: resolveSettings(ext) };
|
|
11172
11207
|
}
|
|
11173
|
-
function
|
|
11208
|
+
function isSidecarWriterAction(ext) {
|
|
11209
|
+
return ext.writes?.includes("sidecar") === true;
|
|
11210
|
+
}
|
|
11211
|
+
function accumulateBuiltInScanExtensions(buckets, resolveEnabled, resolveSettings, forbidSidecarWriters = false) {
|
|
11174
11212
|
for (const plugin of builtInPlugins) {
|
|
11175
11213
|
for (const ext of plugin.extensions) {
|
|
11176
11214
|
if (!isBuiltInExtensionEnabled(plugin, ext, resolveEnabled)) continue;
|
|
@@ -11188,6 +11226,7 @@ function accumulateBuiltInScanExtensions(buckets, resolveEnabled, resolveSetting
|
|
|
11188
11226
|
buckets.hooks.push(withResolvedSettings(ext, resolveSettings));
|
|
11189
11227
|
break;
|
|
11190
11228
|
case "action":
|
|
11229
|
+
if (forbidSidecarWriters && isSidecarWriterAction(ext)) break;
|
|
11191
11230
|
buckets.actions.push(ext);
|
|
11192
11231
|
break;
|
|
11193
11232
|
case "formatter":
|
|
@@ -18430,7 +18469,8 @@ function registerExtensions(kernel, pluginRuntime, opts, cfg) {
|
|
|
18430
18469
|
const composeOpts = {
|
|
18431
18470
|
noBuiltIns: opts.noBuiltIns,
|
|
18432
18471
|
pluginRuntime,
|
|
18433
|
-
resolveSettings: buildSettingsResolver(cfg)
|
|
18472
|
+
resolveSettings: buildSettingsResolver(cfg),
|
|
18473
|
+
forbidSidecarWriters: cfg.allowSidecarWriters === false
|
|
18434
18474
|
};
|
|
18435
18475
|
if (opts.killSwitches) composeOpts.killSwitches = opts.killSwitches;
|
|
18436
18476
|
if (opts.resolveEnabledOverride) composeOpts.resolveEnabled = opts.resolveEnabledOverride;
|
|
@@ -23643,7 +23683,8 @@ function createWatcherRuntime(opts) {
|
|
|
23643
23683
|
noBuiltIns: opts.noBuiltIns,
|
|
23644
23684
|
pluginRuntime,
|
|
23645
23685
|
resolveEnabled: resolveEnabledOverride,
|
|
23646
|
-
resolveSettings: buildSettingsResolver(cfg)
|
|
23686
|
+
resolveSettings: buildSettingsResolver(cfg),
|
|
23687
|
+
forbidSidecarWriters: cfg.allowSidecarWriters === false
|
|
23647
23688
|
};
|
|
23648
23689
|
if (opts.killSwitches) composeOpts.killSwitches = opts.killSwitches;
|
|
23649
23690
|
const composed = composeScanExtensions(composeOpts);
|
|
@@ -24653,6 +24694,7 @@ var ScanCompareCommand = class extends SmCommand {
|
|
|
24653
24694
|
noBuiltIns: false,
|
|
24654
24695
|
pluginRuntime,
|
|
24655
24696
|
resolveSettings: buildSettingsResolver(cfg),
|
|
24697
|
+
forbidSidecarWriters: cfg.allowSidecarWriters === false,
|
|
24656
24698
|
killSwitches: readConformanceKillSwitches()
|
|
24657
24699
|
});
|
|
24658
24700
|
let current;
|
|
@@ -25119,8 +25161,13 @@ var SERVER_TEXTS = {
|
|
|
25119
25161
|
// silently widen the scan surface.
|
|
25120
25162
|
projectPrefsBodyNotJson: "Request body must be valid JSON.",
|
|
25121
25163
|
projectPrefsBodyNotObject: "Request body must be a JSON object.",
|
|
25122
|
-
projectPrefsBodyEmpty: "Request body must contain a `scan` block with `referencePaths`.",
|
|
25164
|
+
projectPrefsBodyEmpty: "Request body must contain `allowSidecarWriters` and/or a `scan` block with `referencePaths`.",
|
|
25123
25165
|
projectPrefsConfirmNotBoolean: "`confirm` must be a boolean.",
|
|
25166
|
+
projectPrefsSidecarWritersNotBoolean: "`allowSidecarWriters` must be a boolean.",
|
|
25167
|
+
// Server-stderr advisory after `PATCH /api/project-preferences`
|
|
25168
|
+
// toggles the committed sidecar-writer policy. Lets the operator see
|
|
25169
|
+
// the team-shared change land without opening settings.json.
|
|
25170
|
+
projectPrefsSidecarWritersSet: "project-prefs: allowSidecarWriters = {{value}}",
|
|
25124
25171
|
projectPrefsScanNotObject: '`scan` must be an object (e.g. `{"scan": {"referencePaths": ["~/Documents"]}}`).',
|
|
25125
25172
|
projectPrefsListNotArray: "`{{key}}` must be an array of strings.",
|
|
25126
25173
|
projectPrefsListEntryNotString: "`{{key}}` entries must be strings.",
|
|
@@ -26950,6 +26997,10 @@ function registerProjectPreferencesRoute(app, deps) {
|
|
|
26950
26997
|
function buildEnvelope3(deps) {
|
|
26951
26998
|
const cwd = deps.runtimeContext.cwd;
|
|
26952
26999
|
return {
|
|
27000
|
+
allowSidecarWriters: readConfigValue("allowSidecarWriters", {
|
|
27001
|
+
cwd,
|
|
27002
|
+
default: true
|
|
27003
|
+
}) ?? true,
|
|
26953
27004
|
scan: {
|
|
26954
27005
|
referencePaths: readConfigValue("scan.referencePaths", {
|
|
26955
27006
|
cwd,
|
|
@@ -26959,9 +27010,15 @@ function buildEnvelope3(deps) {
|
|
|
26959
27010
|
};
|
|
26960
27011
|
}
|
|
26961
27012
|
async function applyPatch3(deps, body) {
|
|
26962
|
-
const writes = collectWrites(body);
|
|
26963
|
-
if (writes.length === 0) return;
|
|
26964
27013
|
const cwd = deps.runtimeContext.cwd;
|
|
27014
|
+
const policyChanged = typeof body.allowSidecarWriters === "boolean" && writeSidecarWritersPolicy(body.allowSidecarWriters, cwd);
|
|
27015
|
+
const scan = applyScanWrites(body, cwd);
|
|
27016
|
+
if (policyChanged || scan.mutated) await maybeRestartWatcher2(deps);
|
|
27017
|
+
if (policyChanged || scan.attempted) deps.configService.reload();
|
|
27018
|
+
}
|
|
27019
|
+
function applyScanWrites(body, cwd) {
|
|
27020
|
+
const writes = collectWrites(body);
|
|
27021
|
+
if (writes.length === 0) return { attempted: false, mutated: false };
|
|
26965
27022
|
const missingPaths = collectMissingPaths(writes, cwd);
|
|
26966
27023
|
if (missingPaths.length > 0) {
|
|
26967
27024
|
throw new HTTPException12(400, {
|
|
@@ -26979,12 +27036,29 @@ async function applyPatch3(deps, body) {
|
|
|
26979
27036
|
})
|
|
26980
27037
|
});
|
|
26981
27038
|
}
|
|
26982
|
-
let
|
|
27039
|
+
let mutated = false;
|
|
26983
27040
|
for (const w of writes) {
|
|
26984
|
-
if (runWrite(w, cwd))
|
|
27041
|
+
if (runWrite(w, cwd)) mutated = true;
|
|
27042
|
+
}
|
|
27043
|
+
return { attempted: true, mutated };
|
|
27044
|
+
}
|
|
27045
|
+
function writeSidecarWritersPolicy(value, cwd) {
|
|
27046
|
+
const before = readConfigValue("allowSidecarWriters", { cwd, default: true }) ?? true;
|
|
27047
|
+
if (before === value) return false;
|
|
27048
|
+
try {
|
|
27049
|
+
writeConfigValue("allowSidecarWriters", value, { target: "project", cwd });
|
|
27050
|
+
} catch (err) {
|
|
27051
|
+
throw new HTTPException12(400, {
|
|
27052
|
+
message: tx(SERVER_TEXTS.projectPrefsPersistFailed, {
|
|
27053
|
+
key: "allowSidecarWriters",
|
|
27054
|
+
message: formatErrorMessage(err)
|
|
27055
|
+
})
|
|
27056
|
+
});
|
|
26985
27057
|
}
|
|
26986
|
-
|
|
26987
|
-
|
|
27058
|
+
log.warn(
|
|
27059
|
+
tx(SERVER_TEXTS.projectPrefsSidecarWritersSet, { value: String(value) })
|
|
27060
|
+
);
|
|
27061
|
+
return true;
|
|
26988
27062
|
}
|
|
26989
27063
|
function collectWrites(body) {
|
|
26990
27064
|
if (!body.scan) return [];
|
|
@@ -27092,9 +27166,10 @@ function isExistingDirectory(entry, cwd) {
|
|
|
27092
27166
|
var PATCH_BODY_SCHEMA3 = {
|
|
27093
27167
|
type: "object",
|
|
27094
27168
|
additionalProperties: false,
|
|
27095
|
-
required: ["scan"],
|
|
27169
|
+
anyOf: [{ required: ["allowSidecarWriters"] }, { required: ["scan"] }],
|
|
27096
27170
|
properties: {
|
|
27097
27171
|
confirm: { type: "boolean" },
|
|
27172
|
+
allowSidecarWriters: { type: "boolean" },
|
|
27098
27173
|
scan: {
|
|
27099
27174
|
type: "object",
|
|
27100
27175
|
additionalProperties: false,
|
|
@@ -27113,10 +27188,11 @@ var parsePatchBody4 = makeBodyValidator(PATCH_BODY_SCHEMA3, {
|
|
|
27113
27188
|
notObject: SERVER_TEXTS.projectPrefsBodyNotObject,
|
|
27114
27189
|
invalid: SERVER_TEXTS.projectPrefsBodyEmpty,
|
|
27115
27190
|
mapping: {
|
|
27116
|
-
"
|
|
27191
|
+
":anyOf": SERVER_TEXTS.projectPrefsBodyEmpty,
|
|
27117
27192
|
"/scan:minProperties": SERVER_TEXTS.projectPrefsBodyEmpty,
|
|
27118
27193
|
"/scan:type:object": SERVER_TEXTS.projectPrefsScanNotObject,
|
|
27119
27194
|
"/confirm:type:boolean": SERVER_TEXTS.projectPrefsConfirmNotBoolean,
|
|
27195
|
+
"/allowSidecarWriters:type:boolean": SERVER_TEXTS.projectPrefsSidecarWritersNotBoolean,
|
|
27120
27196
|
"/scan/referencePaths:type:array": tx(SERVER_TEXTS.projectPrefsListNotArray, { key: "scan.referencePaths" }),
|
|
27121
27197
|
"/scan/referencePaths/*:type:string": tx(SERVER_TEXTS.projectPrefsListEntryNotString, { key: "scan.referencePaths" }),
|
|
27122
27198
|
"/scan/referencePaths/*:pattern": SERVER_TEXTS.projectPrefsEntryHasComma
|
|
@@ -27348,6 +27424,7 @@ async function materializeWrites(writes, body, cwd) {
|
|
|
27348
27424
|
}
|
|
27349
27425
|
} catch (err) {
|
|
27350
27426
|
if (err instanceof EConsentRequiredError) throw err;
|
|
27427
|
+
if (err instanceof ESidecarWritersForbiddenError) throw err;
|
|
27351
27428
|
throw new HTTPException15(500, { message: formatErrorMessage(err) });
|
|
27352
27429
|
}
|
|
27353
27430
|
}
|
|
@@ -28092,18 +28169,26 @@ function formatError2(err, c) {
|
|
|
28092
28169
|
};
|
|
28093
28170
|
return c.json(envelope, 400);
|
|
28094
28171
|
}
|
|
28172
|
+
const sidecar = formatSidecarConsentError(err, c);
|
|
28173
|
+
if (sidecar) return sidecar;
|
|
28174
|
+
return formatInternalErrorFallThrough(err, c);
|
|
28175
|
+
}
|
|
28176
|
+
function formatSidecarConsentError(err, c) {
|
|
28095
28177
|
if (err instanceof EConsentRequiredError) {
|
|
28096
28178
|
const envelope = {
|
|
28097
28179
|
ok: false,
|
|
28098
|
-
error: {
|
|
28099
|
-
code: "confirm-required",
|
|
28100
|
-
message: err.message,
|
|
28101
|
-
details: { key: err.key }
|
|
28102
|
-
}
|
|
28180
|
+
error: { code: "confirm-required", message: err.message, details: { key: err.key } }
|
|
28103
28181
|
};
|
|
28104
28182
|
return c.json(envelope, 412);
|
|
28105
28183
|
}
|
|
28106
|
-
|
|
28184
|
+
if (err instanceof ESidecarWritersForbiddenError) {
|
|
28185
|
+
const envelope = {
|
|
28186
|
+
ok: false,
|
|
28187
|
+
error: { code: "sidecar-writers-forbidden", message: err.message, details: { key: err.key } }
|
|
28188
|
+
};
|
|
28189
|
+
return c.json(envelope, 403);
|
|
28190
|
+
}
|
|
28191
|
+
return null;
|
|
28107
28192
|
}
|
|
28108
28193
|
function formatConflict(err, c) {
|
|
28109
28194
|
if (err instanceof ActionRefusedError) {
|
|
@@ -30973,4 +31058,4 @@ function resolveBareDefault() {
|
|
|
30973
31058
|
process.exit(ExitCode.Error);
|
|
30974
31059
|
}
|
|
30975
31060
|
//# sourceMappingURL=cli.js.map
|
|
30976
|
-
//# debugId=
|
|
31061
|
+
//# debugId=7e14428f-63d1-5e95-8756-98cea6d3c76e
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// kernel/i18n/registry.texts.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]="da133af4-c6e3-580c-95d3-203903628998")}catch(e){}}();
|
|
4
4
|
var REGISTRY_TEXTS = {
|
|
5
5
|
duplicateExtension: "Extension already registered: {{kind}}:{{qualifiedId}}",
|
|
6
6
|
unknownKind: "Unknown extension kind: {{kind}}",
|
|
@@ -102,7 +102,7 @@ import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
|
|
|
102
102
|
// package.json
|
|
103
103
|
var package_default = {
|
|
104
104
|
name: "@skill-map/cli",
|
|
105
|
-
version: "0.
|
|
105
|
+
version: "0.60.0",
|
|
106
106
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
107
107
|
license: "MIT",
|
|
108
108
|
type: "module",
|
|
@@ -3845,4 +3845,4 @@ export {
|
|
|
3845
3845
|
runScanWithRenames
|
|
3846
3846
|
};
|
|
3847
3847
|
//# sourceMappingURL=index.js.map
|
|
3848
|
-
//# debugId=
|
|
3848
|
+
//# debugId=da133af4-c6e3-580c-95d3-203903628998
|
package/dist/kernel/index.d.ts
CHANGED
|
@@ -3268,6 +3268,13 @@ type TActionWrite = {
|
|
|
3268
3268
|
path: string;
|
|
3269
3269
|
changes: Record<string, unknown>;
|
|
3270
3270
|
};
|
|
3271
|
+
/**
|
|
3272
|
+
* The discriminant kinds an Action may emit through `IActionResult.writes`.
|
|
3273
|
+
* Today the union has a single member (`'sidecar'`); the alias keeps the
|
|
3274
|
+
* manifest `writes` capability (`IAction.writes`) in lock-step with the
|
|
3275
|
+
* runtime write union so a new write kind only has to be added in one place.
|
|
3276
|
+
*/
|
|
3277
|
+
type TActionWriteKind = TActionWrite['kind'];
|
|
3271
3278
|
interface IActionResult<TReport = unknown> {
|
|
3272
3279
|
report: TReport;
|
|
3273
3280
|
writes?: TActionWrite[];
|
|
@@ -3353,6 +3360,19 @@ interface IAction extends IExtensionBase {
|
|
|
3353
3360
|
* `expectedDurationSeconds` with the `prob*` prefix convention.
|
|
3354
3361
|
*/
|
|
3355
3362
|
probExpectedDurationSeconds?: number;
|
|
3363
|
+
/**
|
|
3364
|
+
* Declared persistent-write capability. Mirrors the `kind`s this
|
|
3365
|
+
* Action's `invoke()` may return in `IActionResult.writes`. Today the
|
|
3366
|
+
* only kind is `'sidecar'` (the Action creates / modifies a `.sm`
|
|
3367
|
+
* annotation sidecar). An Action that returns a sidecar write MUST
|
|
3368
|
+
* declare `['sidecar']` here: the manifest declaration is what
|
|
3369
|
+
* consumers gate on WITHOUT invoking the action, so the
|
|
3370
|
+
* `allowSidecarWriters: false` project policy can drop every
|
|
3371
|
+
* sidecar-writer from the scan composer (its `inspector.action.button`
|
|
3372
|
+
* never projects) and the sidecar store can refuse the write. Absent =
|
|
3373
|
+
* the Action performs no persistent writes (read-only / report-only).
|
|
3374
|
+
*/
|
|
3375
|
+
writes?: TActionWriteKind[];
|
|
3356
3376
|
/**
|
|
3357
3377
|
* Optional declarative filter; absent → applies to every node.
|
|
3358
3378
|
*/
|
package/dist/kernel/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// kernel/i18n/registry.texts.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]="694d5ef3-1132-5669-b493-3082eef46469")}catch(e){}}();
|
|
4
4
|
var REGISTRY_TEXTS = {
|
|
5
5
|
duplicateExtension: "Extension already registered: {{kind}}:{{qualifiedId}}",
|
|
6
6
|
unknownKind: "Unknown extension kind: {{kind}}",
|
|
@@ -102,7 +102,7 @@ import { Tiktoken as Tiktoken2 } from "js-tiktoken/lite";
|
|
|
102
102
|
// package.json
|
|
103
103
|
var package_default = {
|
|
104
104
|
name: "@skill-map/cli",
|
|
105
|
-
version: "0.
|
|
105
|
+
version: "0.60.0",
|
|
106
106
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
107
107
|
license: "MIT",
|
|
108
108
|
type: "module",
|
|
@@ -3845,4 +3845,4 @@ export {
|
|
|
3845
3845
|
runScanWithRenames
|
|
3846
3846
|
};
|
|
3847
3847
|
//# sourceMappingURL=index.js.map
|
|
3848
|
-
//# debugId=
|
|
3848
|
+
//# debugId=694d5ef3-1132-5669-b493-3082eef46469
|