@skill-map/cli 0.50.1 → 0.52.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.js +197 -95
- package/dist/conformance/index.js +13 -25
- package/dist/index.js +92 -409
- package/dist/kernel/index.js +92 -409
- package/dist/ui/{chunk-4N5LGWJ4.js → chunk-5MCXQKRN.js} +14 -14
- package/dist/ui/{chunk-DOWLJNMD.js → chunk-6B5EAHIM.js} +13 -13
- package/dist/ui/chunk-AQN27TN2.js +123 -0
- package/dist/ui/chunk-CAJ7ZI44.js +1 -0
- package/dist/ui/chunk-E2XO4JVD.js +1 -0
- package/dist/ui/chunk-WHZVGOS3.js +5 -0
- package/dist/ui/chunk-ZNDMBION.js +2206 -0
- package/dist/ui/index.html +8 -2
- package/dist/ui/main-2DWVSRRX.js +4 -0
- package/dist/ui/{styles-O3EXBCXH.css → styles-QBTVKEVX.css} +1 -1
- package/package.json +2 -2
- package/dist/ui/chunk-76APRPAZ.js +0 -123
- package/dist/ui/chunk-DQEAPUE5.js +0 -2349
- package/dist/ui/chunk-FQQYWQV6.js +0 -1
- package/dist/ui/chunk-OYCCFH2S.js +0 -1
- package/dist/ui/main-I3HSF6GU.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]="91ef81c7-e785-5818-839a-1f18ea093b57")}catch(e){}}();
|
|
4
4
|
import { existsSync as existsSync33 } from "fs";
|
|
5
5
|
import { Builtins, Cli as Cli2 } from "clipanion";
|
|
6
6
|
|
|
@@ -246,7 +246,7 @@ function bucketByKind(kind, instance, bag) {
|
|
|
246
246
|
// package.json
|
|
247
247
|
var package_default = {
|
|
248
248
|
name: "@skill-map/cli",
|
|
249
|
-
version: "0.
|
|
249
|
+
version: "0.52.0",
|
|
250
250
|
description: "skill-map reference implementation \u2014 kernel + CLI + adapters.",
|
|
251
251
|
license: "MIT",
|
|
252
252
|
type: "module",
|
|
@@ -1968,14 +1968,13 @@ var annotationStaleAnalyzer = {
|
|
|
1968
1968
|
const message = status === "stale-body" ? tx(ANNOTATION_STALE_TEXTS.bodyDrift, { path: node.path }) : status === "stale-frontmatter" ? tx(ANNOTATION_STALE_TEXTS.frontmatterDrift, { path: node.path }) : tx(ANNOTATION_STALE_TEXTS.bothDrift, { path: node.path });
|
|
1969
1969
|
issues.push({
|
|
1970
1970
|
analyzerId: ID10,
|
|
1971
|
-
severity: "
|
|
1971
|
+
severity: "info",
|
|
1972
1972
|
nodeIds: [node.path],
|
|
1973
1973
|
message,
|
|
1974
1974
|
data: { status }
|
|
1975
1975
|
});
|
|
1976
1976
|
ctx.emitContribution(node.path, "staleIcon", {
|
|
1977
1977
|
value: 0,
|
|
1978
|
-
severity: "warn",
|
|
1979
1978
|
tooltip: tooltipFor(status)
|
|
1980
1979
|
});
|
|
1981
1980
|
}
|
|
@@ -3987,7 +3986,7 @@ var nodeSupersedeAction = {
|
|
|
3987
3986
|
}
|
|
3988
3987
|
};
|
|
3989
3988
|
|
|
3990
|
-
//
|
|
3989
|
+
// kernel/update-check/index.ts
|
|
3991
3990
|
var SEMVER_SHAPE_RE = /^[0-9]+\.[0-9]+\.[0-9]+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
3992
3991
|
async function fetchLatestVersion(pkg, opts) {
|
|
3993
3992
|
const controller = new AbortController();
|
|
@@ -4122,9 +4121,9 @@ function ansiFor(opts) {
|
|
|
4122
4121
|
import { randomUUID } from "crypto";
|
|
4123
4122
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync5 } from "fs";
|
|
4124
4123
|
import { homedir } from "os";
|
|
4125
|
-
import { join as
|
|
4124
|
+
import { join as join3 } from "path";
|
|
4126
4125
|
|
|
4127
|
-
//
|
|
4126
|
+
// kernel/util/atomic-write.ts
|
|
4128
4127
|
import {
|
|
4129
4128
|
closeSync,
|
|
4130
4129
|
constants as fsConstants,
|
|
@@ -4182,17 +4181,31 @@ function writeJsonAtomic(path, content) {
|
|
|
4182
4181
|
}
|
|
4183
4182
|
|
|
4184
4183
|
// core/paths/db-path.ts
|
|
4185
|
-
import { join, resolve as resolve6 } from "path";
|
|
4184
|
+
import { join as join2, resolve as resolve6 } from "path";
|
|
4185
|
+
|
|
4186
|
+
// kernel/util/skill-map-paths.ts
|
|
4187
|
+
import { join } from "path";
|
|
4186
4188
|
var SKILL_MAP_DIR = ".skill-map";
|
|
4189
|
+
var KERNEL_SKILL_MAP_DIR = SKILL_MAP_DIR;
|
|
4190
|
+
var SETTINGS_FILENAME = "settings.json";
|
|
4191
|
+
var LOCAL_SETTINGS_FILENAME = "settings.local.json";
|
|
4192
|
+
function kernelSettingsPath(scopeRoot) {
|
|
4193
|
+
return join(scopeRoot, KERNEL_SKILL_MAP_DIR, SETTINGS_FILENAME);
|
|
4194
|
+
}
|
|
4195
|
+
function kernelLocalSettingsPath(scopeRoot) {
|
|
4196
|
+
return join(scopeRoot, KERNEL_SKILL_MAP_DIR, LOCAL_SETTINGS_FILENAME);
|
|
4197
|
+
}
|
|
4198
|
+
|
|
4199
|
+
// core/paths/db-path.ts
|
|
4187
4200
|
var DB_FILENAME = "skill-map.db";
|
|
4188
4201
|
var JOBS_DIRNAME = "jobs";
|
|
4189
4202
|
var PLUGINS_DIRNAME = "plugins";
|
|
4190
|
-
var
|
|
4191
|
-
var
|
|
4203
|
+
var SETTINGS_FILENAME2 = "settings.json";
|
|
4204
|
+
var LOCAL_SETTINGS_FILENAME2 = "settings.local.json";
|
|
4192
4205
|
var IGNORE_FILENAME = ".skillmapignore";
|
|
4193
4206
|
var DEFAULT_DB_REL = `${SKILL_MAP_DIR}/${DB_FILENAME}`;
|
|
4194
4207
|
var GITIGNORE_ENTRIES = [
|
|
4195
|
-
`${SKILL_MAP_DIR}/${
|
|
4208
|
+
`${SKILL_MAP_DIR}/${LOCAL_SETTINGS_FILENAME2}`,
|
|
4196
4209
|
`${SKILL_MAP_DIR}/${DB_FILENAME}`
|
|
4197
4210
|
];
|
|
4198
4211
|
function resolveDbPath(options) {
|
|
@@ -4209,23 +4222,23 @@ function defaultProjectPluginsDir(ctx) {
|
|
|
4209
4222
|
return resolve6(ctx.cwd, SKILL_MAP_DIR, PLUGINS_DIRNAME);
|
|
4210
4223
|
}
|
|
4211
4224
|
function defaultDbPath(scopeRoot) {
|
|
4212
|
-
return
|
|
4225
|
+
return join2(scopeRoot, SKILL_MAP_DIR, DB_FILENAME);
|
|
4213
4226
|
}
|
|
4214
4227
|
function defaultSettingsPath(scopeRoot) {
|
|
4215
|
-
return
|
|
4228
|
+
return join2(scopeRoot, SKILL_MAP_DIR, SETTINGS_FILENAME2);
|
|
4216
4229
|
}
|
|
4217
4230
|
function defaultLocalSettingsPath(scopeRoot) {
|
|
4218
|
-
return
|
|
4231
|
+
return join2(scopeRoot, SKILL_MAP_DIR, LOCAL_SETTINGS_FILENAME2);
|
|
4219
4232
|
}
|
|
4220
4233
|
function defaultIgnoreFilePath(scopeRoot) {
|
|
4221
|
-
return
|
|
4234
|
+
return join2(scopeRoot, IGNORE_FILENAME);
|
|
4222
4235
|
}
|
|
4223
4236
|
|
|
4224
4237
|
// cli/util/user-settings-store.ts
|
|
4225
4238
|
var FILENAME = "settings.json";
|
|
4226
4239
|
var SCHEMA_VERSION = 1;
|
|
4227
4240
|
function userSettingsFilePath() {
|
|
4228
|
-
return
|
|
4241
|
+
return join3(homedir(), SKILL_MAP_DIR, FILENAME);
|
|
4229
4242
|
}
|
|
4230
4243
|
function defaultSettings() {
|
|
4231
4244
|
return { schemaVersion: SCHEMA_VERSION, updateCheck: {}, telemetry: {} };
|
|
@@ -4264,7 +4277,7 @@ function backfillSubObjects(settings) {
|
|
|
4264
4277
|
};
|
|
4265
4278
|
}
|
|
4266
4279
|
function writeUserSettings(patch) {
|
|
4267
|
-
const dir =
|
|
4280
|
+
const dir = join3(homedir(), SKILL_MAP_DIR);
|
|
4268
4281
|
const path = userSettingsFilePath();
|
|
4269
4282
|
try {
|
|
4270
4283
|
const current = readUserSettings();
|
|
@@ -5361,18 +5374,6 @@ var CONFIG_LOADER_TEXTS = {
|
|
|
5361
5374
|
projectLocalOnlyStripped: "[config:{{layer}}] key {{key}} is project-local only; stripped from the committed project layer. Move it to .skill-map/settings.local.json (gitignored, per-checkout)."
|
|
5362
5375
|
};
|
|
5363
5376
|
|
|
5364
|
-
// kernel/util/skill-map-paths.ts
|
|
5365
|
-
import { join as join3 } from "path";
|
|
5366
|
-
var KERNEL_SKILL_MAP_DIR = SKILL_MAP_DIR;
|
|
5367
|
-
var SETTINGS_FILENAME2 = "settings.json";
|
|
5368
|
-
var LOCAL_SETTINGS_FILENAME2 = "settings.local.json";
|
|
5369
|
-
function kernelSettingsPath(scopeRoot) {
|
|
5370
|
-
return join3(scopeRoot, KERNEL_SKILL_MAP_DIR, SETTINGS_FILENAME2);
|
|
5371
|
-
}
|
|
5372
|
-
function kernelLocalSettingsPath(scopeRoot) {
|
|
5373
|
-
return join3(scopeRoot, KERNEL_SKILL_MAP_DIR, LOCAL_SETTINGS_FILENAME2);
|
|
5374
|
-
}
|
|
5375
|
-
|
|
5376
5377
|
// config/defaults.json
|
|
5377
5378
|
var defaults_default = {
|
|
5378
5379
|
schemaVersion: 1,
|
|
@@ -5830,11 +5831,20 @@ var FilesystemSidecarStore = class {
|
|
|
5830
5831
|
* files in the repo and entries are tiny).
|
|
5831
5832
|
*/
|
|
5832
5833
|
#locks = /* @__PURE__ */ new Map();
|
|
5834
|
+
/** Injected consent gate, see {@link TSidecarConsentGate}. */
|
|
5835
|
+
#consentGate;
|
|
5836
|
+
/**
|
|
5837
|
+
* @param consentGate the write-consent gate, invoked first inside
|
|
5838
|
+
* `applyPatch`. Production wires
|
|
5839
|
+
* `core/config/sidecar-consent.ts:ensureSidecarWritesAllowed`; tests
|
|
5840
|
+
* wire the same function (to exercise the real config-backed gate)
|
|
5841
|
+
* or a stub.
|
|
5842
|
+
*/
|
|
5843
|
+
constructor(consentGate) {
|
|
5844
|
+
this.#consentGate = consentGate;
|
|
5845
|
+
}
|
|
5833
5846
|
async applyPatch(sidecarAbsPath, changes, consent) {
|
|
5834
|
-
|
|
5835
|
-
confirm: consent.confirm,
|
|
5836
|
-
cwd: consent.cwd
|
|
5837
|
-
});
|
|
5847
|
+
this.#consentGate(consent);
|
|
5838
5848
|
const prev = this.#locks.get(sidecarAbsPath) ?? Promise.resolve();
|
|
5839
5849
|
let release;
|
|
5840
5850
|
const settled = new Promise((res) => {
|
|
@@ -6058,6 +6068,17 @@ function ensureGitForStaged(cwd) {
|
|
|
6058
6068
|
}
|
|
6059
6069
|
return "ok";
|
|
6060
6070
|
}
|
|
6071
|
+
function resolveGitAuthorName(cwd) {
|
|
6072
|
+
if (!isInsideGitRepo(cwd)) return null;
|
|
6073
|
+
const result = spawnSync("git", ["config", "user.name"], {
|
|
6074
|
+
cwd,
|
|
6075
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
6076
|
+
encoding: "utf8"
|
|
6077
|
+
});
|
|
6078
|
+
if (result.error !== void 0 || result.status !== 0) return null;
|
|
6079
|
+
const name = (result.stdout ?? "").trim();
|
|
6080
|
+
return name.length > 0 ? name : null;
|
|
6081
|
+
}
|
|
6061
6082
|
function stageSidecar(cwd, sidecarAbsPath) {
|
|
6062
6083
|
const result = spawnSync("git", ["add", "--", sidecarAbsPath], {
|
|
6063
6084
|
cwd,
|
|
@@ -7858,7 +7879,7 @@ function rowToContribution(row) {
|
|
|
7858
7879
|
};
|
|
7859
7880
|
}
|
|
7860
7881
|
|
|
7861
|
-
//
|
|
7882
|
+
// kernel/adapters/sqlite/schema-fingerprint.ts
|
|
7862
7883
|
import { createHash } from "crypto";
|
|
7863
7884
|
import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
|
|
7864
7885
|
import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
|
|
@@ -8979,13 +9000,14 @@ function isAllowedLstatError(err) {
|
|
|
8979
9000
|
|
|
8980
9001
|
// cli/commands/bump-plan.ts
|
|
8981
9002
|
function computeBumpPlan(nodes, options) {
|
|
9003
|
+
const invoker = resolveGitAuthorName(options.cwd) ?? "cli";
|
|
8982
9004
|
const items = [];
|
|
8983
9005
|
for (const node of nodes) {
|
|
8984
|
-
items.push(planOne(node, options));
|
|
9006
|
+
items.push(planOne(node, options, invoker));
|
|
8985
9007
|
}
|
|
8986
9008
|
return { items };
|
|
8987
9009
|
}
|
|
8988
|
-
function planOne(node, options) {
|
|
9010
|
+
function planOne(node, options, invoker) {
|
|
8989
9011
|
let absPath;
|
|
8990
9012
|
try {
|
|
8991
9013
|
assertContained(options.cwd, node.path);
|
|
@@ -8999,7 +9021,7 @@ function planOne(node, options) {
|
|
|
8999
9021
|
}
|
|
9000
9022
|
let result;
|
|
9001
9023
|
try {
|
|
9002
|
-
result = invokeBumpFor(node, absPath, options.force);
|
|
9024
|
+
result = invokeBumpFor(node, absPath, options.force, invoker);
|
|
9003
9025
|
} catch (err) {
|
|
9004
9026
|
return {
|
|
9005
9027
|
nodePath: node.path,
|
|
@@ -9021,7 +9043,7 @@ function planOne(node, options) {
|
|
|
9021
9043
|
report: result.report
|
|
9022
9044
|
};
|
|
9023
9045
|
}
|
|
9024
|
-
function invokeBumpFor(node, absPath, force) {
|
|
9046
|
+
function invokeBumpFor(node, absPath, force, invoker) {
|
|
9025
9047
|
if (!nodeBumpAction.invoke) {
|
|
9026
9048
|
throw new Error("built-in bump action is missing its invoke()");
|
|
9027
9049
|
}
|
|
@@ -9030,7 +9052,7 @@ function invokeBumpFor(node, absPath, force) {
|
|
|
9030
9052
|
return nodeBumpAction.invoke(input, {
|
|
9031
9053
|
node,
|
|
9032
9054
|
nodeAbsolutePath: absPath,
|
|
9033
|
-
invoker
|
|
9055
|
+
invoker,
|
|
9034
9056
|
now: () => /* @__PURE__ */ new Date(),
|
|
9035
9057
|
settings: {}
|
|
9036
9058
|
});
|
|
@@ -9334,7 +9356,7 @@ var BumpCommand = class extends SmCommand {
|
|
|
9334
9356
|
* the staging missed).
|
|
9335
9357
|
*/
|
|
9336
9358
|
async #executePending(plan, cwd, ansi) {
|
|
9337
|
-
const store = new FilesystemSidecarStore();
|
|
9359
|
+
const store = new FilesystemSidecarStore(ensureSidecarWritesAllowed);
|
|
9338
9360
|
const ctx = defaultRuntimeContext();
|
|
9339
9361
|
const consent = {
|
|
9340
9362
|
confirm: this.yes,
|
|
@@ -9480,7 +9502,7 @@ function buildBumpedOutcome(item, sidecarPath) {
|
|
|
9480
9502
|
if (item.report.createdSidecar === true) outcome.createdSidecar = true;
|
|
9481
9503
|
return outcome;
|
|
9482
9504
|
}
|
|
9483
|
-
async function applyBumpWrites(item, consent, store = new FilesystemSidecarStore()) {
|
|
9505
|
+
async function applyBumpWrites(item, consent, store = new FilesystemSidecarStore(ensureSidecarWritesAllowed)) {
|
|
9484
9506
|
let sidecarPath;
|
|
9485
9507
|
try {
|
|
9486
9508
|
for (const w of item.writes) {
|
|
@@ -11423,20 +11445,9 @@ function trimRedundantPath(message, primary) {
|
|
|
11423
11445
|
import { existsSync as existsSync16 } from "fs";
|
|
11424
11446
|
import { Command as Command4, Option as Option4 } from "clipanion";
|
|
11425
11447
|
|
|
11426
|
-
//
|
|
11448
|
+
// kernel/scan/detect-providers.ts
|
|
11427
11449
|
import { existsSync as existsSync15 } from "fs";
|
|
11428
11450
|
import { join as join10 } from "path";
|
|
11429
|
-
function resolveActiveProvider(cwd, providers = []) {
|
|
11430
|
-
const detected = detectProvidersFromFilesystem(cwd, providers);
|
|
11431
|
-
const fromConfig = readConfigValue("activeProvider", { cwd });
|
|
11432
|
-
if (typeof fromConfig === "string" && fromConfig.length > 0) {
|
|
11433
|
-
return { resolved: fromConfig, source: "config", detected };
|
|
11434
|
-
}
|
|
11435
|
-
if (detected.length > 0) {
|
|
11436
|
-
return { resolved: detected[0], source: "autodetect", detected };
|
|
11437
|
-
}
|
|
11438
|
-
return { resolved: null, source: "none", detected };
|
|
11439
|
-
}
|
|
11440
11451
|
function detectProvidersFromFilesystem(cwd, providers) {
|
|
11441
11452
|
const seen = /* @__PURE__ */ new Set();
|
|
11442
11453
|
const out = [];
|
|
@@ -11451,6 +11462,19 @@ function detectProvidersFromFilesystem(cwd, providers) {
|
|
|
11451
11462
|
return out;
|
|
11452
11463
|
}
|
|
11453
11464
|
|
|
11465
|
+
// core/config/active-provider.ts
|
|
11466
|
+
function resolveActiveProvider(cwd, providers = []) {
|
|
11467
|
+
const detected = detectProvidersFromFilesystem(cwd, providers);
|
|
11468
|
+
const fromConfig = readConfigValue("activeProvider", { cwd });
|
|
11469
|
+
if (typeof fromConfig === "string" && fromConfig.length > 0) {
|
|
11470
|
+
return { resolved: fromConfig, source: "config", detected };
|
|
11471
|
+
}
|
|
11472
|
+
if (detected.length > 0) {
|
|
11473
|
+
return { resolved: detected[0], source: "autodetect", detected };
|
|
11474
|
+
}
|
|
11475
|
+
return { resolved: null, source: "none", detected };
|
|
11476
|
+
}
|
|
11477
|
+
|
|
11454
11478
|
// cli/util/path-display.ts
|
|
11455
11479
|
import { isAbsolute as isAbsolute4, relative as pathRelative } from "path";
|
|
11456
11480
|
function relativeIfBelow(path, cwd) {
|
|
@@ -16327,7 +16351,7 @@ function resolveSidecarOverlay(relativePath2, nodePathForIssue, roots, liveBodyH
|
|
|
16327
16351
|
for (const parseIssue of result.issues) {
|
|
16328
16352
|
issues.push({
|
|
16329
16353
|
analyzerId: "invalid-sidecar",
|
|
16330
|
-
severity: "
|
|
16354
|
+
severity: "error",
|
|
16331
16355
|
nodeIds: [nodePathForIssue],
|
|
16332
16356
|
message: parseIssue.message,
|
|
16333
16357
|
data: { sidecarPath: relativePathFromRoots(mdAbs, roots) }
|
|
@@ -16982,7 +17006,7 @@ function resolveActiveProviderOption(optionValue, roots, providers) {
|
|
|
16982
17006
|
for (const root of roots) {
|
|
16983
17007
|
const absRoot = isAbsolute7(root) ? root : resolve28(root);
|
|
16984
17008
|
if (!existsSync23(absRoot)) continue;
|
|
16985
|
-
const detected =
|
|
17009
|
+
const detected = detectProvidersFromFilesystem(absRoot, providers)[0] ?? null;
|
|
16986
17010
|
if (detected !== null) return detected;
|
|
16987
17011
|
}
|
|
16988
17012
|
return null;
|
|
@@ -22272,7 +22296,7 @@ var IntentionalFailCommand = class extends SmCommand {
|
|
|
22272
22296
|
throw new Error(INTENTIONAL_FAIL_TEXTS.errorMessage);
|
|
22273
22297
|
}, 0);
|
|
22274
22298
|
await new Promise((resolve40) => setTimeout(resolve40, 5e3));
|
|
22275
|
-
return
|
|
22299
|
+
return ExitCode.Issues;
|
|
22276
22300
|
}
|
|
22277
22301
|
};
|
|
22278
22302
|
|
|
@@ -22341,6 +22365,25 @@ var SCAN_TEXTS = {
|
|
|
22341
22365
|
persistedTo: " {{dbPath}}\n",
|
|
22342
22366
|
/** Body line for dry-run mode, same indent, marker tail. */
|
|
22343
22367
|
wouldPersist: " would persist to {{dbPath}} (dry-run)\n",
|
|
22368
|
+
/**
|
|
22369
|
+
* Count-row nouns for the `{{counts}}` block in `scannedSummary`.
|
|
22370
|
+
* The caller selects the singular / plural form on `count === 1`
|
|
22371
|
+
* (English plural rule), so both forms live in the catalog instead of
|
|
22372
|
+
* being hand-suffixed with `s` at the call site (per the i18n
|
|
22373
|
+
* contract: catalog strings, no `${word}s` interpolation). `info` is
|
|
22374
|
+
* uncountable in English (no `infos`), so it carries a single form;
|
|
22375
|
+
* `countNoIssues` is the all-clean placeholder.
|
|
22376
|
+
*/
|
|
22377
|
+
countNodeNounSingular: "node",
|
|
22378
|
+
countNodeNounPlural: "nodes",
|
|
22379
|
+
countLinkNounSingular: "link",
|
|
22380
|
+
countLinkNounPlural: "links",
|
|
22381
|
+
countErrorNounSingular: "error",
|
|
22382
|
+
countErrorNounPlural: "errors",
|
|
22383
|
+
countWarningNounSingular: "warning",
|
|
22384
|
+
countWarningNounPlural: "warnings",
|
|
22385
|
+
countInfoNoun: "info",
|
|
22386
|
+
countNoIssues: "0 issues",
|
|
22344
22387
|
/**
|
|
22345
22388
|
* Cap-hit notice, printed when the walker stopped accepting nodes
|
|
22346
22389
|
* because `--max-nodes` (or the `scan.maxNodes` setting) was reached.
|
|
@@ -23422,27 +23465,29 @@ function fillSeverityBucket(bucket, nodeIds) {
|
|
|
23422
23465
|
function formatScanCounts(opts) {
|
|
23423
23466
|
const { nodes, links, severities, ansi } = opts;
|
|
23424
23467
|
const parts = [
|
|
23425
|
-
`${nodes} ${
|
|
23426
|
-
`${links} ${
|
|
23468
|
+
`${nodes} ${countNoun(nodes, SCAN_TEXTS.countNodeNounSingular, SCAN_TEXTS.countNodeNounPlural)}`,
|
|
23469
|
+
`${links} ${countNoun(links, SCAN_TEXTS.countLinkNounSingular, SCAN_TEXTS.countLinkNounPlural)}`
|
|
23427
23470
|
];
|
|
23428
23471
|
const total = severities.errors + severities.warns + severities.info;
|
|
23429
23472
|
if (total === 0) {
|
|
23430
|
-
parts.push(ansi.dim(
|
|
23473
|
+
parts.push(ansi.dim(SCAN_TEXTS.countNoIssues));
|
|
23431
23474
|
} else {
|
|
23432
23475
|
if (severities.errors > 0) {
|
|
23433
|
-
|
|
23476
|
+
const noun = countNoun(severities.errors, SCAN_TEXTS.countErrorNounSingular, SCAN_TEXTS.countErrorNounPlural);
|
|
23477
|
+
parts.push(ansi.red(`${severities.errors} ${noun}`));
|
|
23434
23478
|
}
|
|
23435
23479
|
if (severities.warns > 0) {
|
|
23436
|
-
|
|
23480
|
+
const noun = countNoun(severities.warns, SCAN_TEXTS.countWarningNounSingular, SCAN_TEXTS.countWarningNounPlural);
|
|
23481
|
+
parts.push(ansi.yellow(`${severities.warns} ${noun}`));
|
|
23437
23482
|
}
|
|
23438
23483
|
if (severities.info > 0) {
|
|
23439
|
-
parts.push(ansi.dim(`${severities.info}
|
|
23484
|
+
parts.push(ansi.dim(`${severities.info} ${SCAN_TEXTS.countInfoNoun}`));
|
|
23440
23485
|
}
|
|
23441
23486
|
}
|
|
23442
23487
|
return parts.join(" \xB7 ");
|
|
23443
23488
|
}
|
|
23444
|
-
function
|
|
23445
|
-
return count === 1 ?
|
|
23489
|
+
function countNoun(count, singular, plural) {
|
|
23490
|
+
return count === 1 ? singular : plural;
|
|
23446
23491
|
}
|
|
23447
23492
|
|
|
23448
23493
|
// cli/commands/scan-compare.ts
|
|
@@ -23888,11 +23933,10 @@ var SERVER_TEXTS = {
|
|
|
23888
23933
|
// here (after static + SPA fallback have had their turn).
|
|
23889
23934
|
unknownPath: "Not found: {{path}}.",
|
|
23890
23935
|
// ---- sidecar bump route (routes/sidecar.ts) ------------------------------
|
|
23891
|
-
// 409 refusal when a fresh node is bumped without `force`.
|
|
23892
|
-
// `sidecar-fresh
|
|
23893
|
-
//
|
|
23894
|
-
//
|
|
23895
|
-
// affinity with the CLI's bump verb).
|
|
23936
|
+
// 409 refusal when a fresh node is bumped without `force`. Dispatch
|
|
23937
|
+
// is via the typed `ConflictError` (`code: 'sidecar-fresh'`), so the
|
|
23938
|
+
// `sidecar-fresh:` prefix is NOT load-bearing; it stays only for
|
|
23939
|
+
// log-grep affinity with the CLI's bump verb.
|
|
23896
23940
|
sidecarFreshRefusal: "sidecar-fresh: Node is fresh; pass force:true to bump anyway.",
|
|
23897
23941
|
// 400 envelopes thrown by `parseBody` when the request payload is
|
|
23898
23942
|
// malformed. Each branch has its own key so the UI / log can
|
|
@@ -23920,9 +23964,9 @@ var SERVER_TEXTS = {
|
|
|
23920
23964
|
// dropped half the pipeline. Same gate the `?fresh=1` GET applies.
|
|
23921
23965
|
scanPostRequiresFullPipeline: "POST /api/scan cannot run while the server was started with --no-built-ins or --no-plugins (would persist a partial DB).",
|
|
23922
23966
|
// 409, another scan (watcher batch or another POST) is in flight.
|
|
23923
|
-
//
|
|
23924
|
-
// `scan-busy
|
|
23925
|
-
//
|
|
23967
|
+
// Dispatch is via the typed `ConflictError` (`code: 'scan-busy'`), so
|
|
23968
|
+
// the `scan-busy:` prefix is NOT load-bearing; it stays only for
|
|
23969
|
+
// log-grep affinity with the CLI's `sm scan` verb.
|
|
23926
23970
|
scanPostBusy: "scan-busy: Another scan is already in flight; retry once it finishes.",
|
|
23927
23971
|
// 500, DB missing on a write path. Read paths degrade to empty
|
|
23928
23972
|
// shapes; mutations cannot persist without a DB so they fail fast.
|
|
@@ -24535,6 +24579,7 @@ function registerHealthRoute(app, deps) {
|
|
|
24535
24579
|
var DEFAULT_LIMIT = 100;
|
|
24536
24580
|
var MAX_LIMIT = 1e3;
|
|
24537
24581
|
var BFF_MAX_BULK_CONTRIBUTIONS = 200;
|
|
24582
|
+
var MAX_WS_CLIENTS = 64;
|
|
24538
24583
|
|
|
24539
24584
|
// server/routes/issues.ts
|
|
24540
24585
|
function registerIssuesRoute(app, deps) {
|
|
@@ -24767,7 +24812,7 @@ function registerNodesRoutes(app, deps) {
|
|
|
24767
24812
|
const tags = result?.tags ?? [];
|
|
24768
24813
|
if (!bundle) {
|
|
24769
24814
|
throw new HTTPException7(404, {
|
|
24770
|
-
message: tx(SERVER_TEXTS.nodeNotFound, { path: nodePath })
|
|
24815
|
+
message: tx(SERVER_TEXTS.nodeNotFound, { path: sanitizeForTerminal(nodePath) })
|
|
24771
24816
|
});
|
|
24772
24817
|
}
|
|
24773
24818
|
const decoratedNode = { ...bundle.node, isFavorite, contributions, tags };
|
|
@@ -25774,24 +25819,39 @@ var parsePatchBody4 = makeBodyValidator(PATCH_BODY_SCHEMA3, {
|
|
|
25774
25819
|
import { existsSync as existsSync28 } from "fs";
|
|
25775
25820
|
import { HTTPException as HTTPException13 } from "hono/http-exception";
|
|
25776
25821
|
function registerActiveProviderRoute(app, deps) {
|
|
25777
|
-
app.get("/api/active-provider", (c) => {
|
|
25778
|
-
return c.json(buildEnvelope4(deps));
|
|
25822
|
+
app.get("/api/active-provider", async (c) => {
|
|
25823
|
+
return c.json(await buildEnvelope4(deps));
|
|
25779
25824
|
});
|
|
25780
25825
|
app.patch("/api/active-provider", async (c) => {
|
|
25781
25826
|
const body = await parsePatchBody5(c.req.raw);
|
|
25782
25827
|
const result = applyLensSwitch(deps, body.activeProvider);
|
|
25783
25828
|
deps.configService.reload();
|
|
25784
|
-
return c.json({ ...buildEnvelope4(deps), switch: result });
|
|
25829
|
+
return c.json({ ...await buildEnvelope4(deps), switch: result });
|
|
25785
25830
|
});
|
|
25786
25831
|
}
|
|
25787
|
-
function buildEnvelope4(deps) {
|
|
25832
|
+
async function buildEnvelope4(deps) {
|
|
25788
25833
|
const r = resolveActiveProvider(deps.runtimeContext.cwd, deps.providers);
|
|
25789
25834
|
return {
|
|
25790
25835
|
activeProvider: r.resolved,
|
|
25791
25836
|
detected: r.detected,
|
|
25792
|
-
source: r.source
|
|
25837
|
+
source: r.source,
|
|
25838
|
+
selectable: await resolveSelectableProviders(deps)
|
|
25793
25839
|
};
|
|
25794
25840
|
}
|
|
25841
|
+
async function resolveSelectableProviders(deps) {
|
|
25842
|
+
const resolveEnabled = await buildFreshResolver({
|
|
25843
|
+
databasePath: deps.options.dbPath,
|
|
25844
|
+
effectiveConfig: () => deps.configService.effective(),
|
|
25845
|
+
fallbackResolver: deps.pluginRuntime.resolveEnabled
|
|
25846
|
+
});
|
|
25847
|
+
const selectable = /* @__PURE__ */ new Set();
|
|
25848
|
+
for (const provider of deps.providers) {
|
|
25849
|
+
if (isPluginExtensionEnabled(provider, resolveEnabled)) {
|
|
25850
|
+
selectable.add(provider.id);
|
|
25851
|
+
}
|
|
25852
|
+
}
|
|
25853
|
+
return [...selectable];
|
|
25854
|
+
}
|
|
25795
25855
|
function applyLensSwitch(deps, newValue) {
|
|
25796
25856
|
const cwd = deps.runtimeContext.cwd;
|
|
25797
25857
|
try {
|
|
@@ -26057,7 +26117,7 @@ async function runPersistedScan(c, deps) {
|
|
|
26057
26117
|
});
|
|
26058
26118
|
} catch (err) {
|
|
26059
26119
|
if (err instanceof ScanBusyError) {
|
|
26060
|
-
throw new
|
|
26120
|
+
throw new ConflictError({ code: "scan-busy", message: SERVER_TEXTS.scanPostBusy });
|
|
26061
26121
|
}
|
|
26062
26122
|
throw err;
|
|
26063
26123
|
}
|
|
@@ -26248,9 +26308,9 @@ function registerSidecarRoutes(app, deps) {
|
|
|
26248
26308
|
} catch (err) {
|
|
26249
26309
|
throw new HTTPException15(400, { message: formatErrorMessage(err) });
|
|
26250
26310
|
}
|
|
26251
|
-
const result = invokeBump2(node, absPath, body);
|
|
26311
|
+
const result = invokeBump2(node, absPath, body, deps.runtimeContext.cwd);
|
|
26252
26312
|
if (result.report.ok === false && result.report.reason === "fresh") {
|
|
26253
|
-
throw new
|
|
26313
|
+
throw new ConflictError({ code: "sidecar-fresh", message: SERVER_TEXTS.sidecarFreshRefusal });
|
|
26254
26314
|
}
|
|
26255
26315
|
if (result.report.ok === true && result.report.noop === true) {
|
|
26256
26316
|
const envelope2 = {
|
|
@@ -26265,7 +26325,7 @@ function registerSidecarRoutes(app, deps) {
|
|
|
26265
26325
|
};
|
|
26266
26326
|
return c.json(envelope2);
|
|
26267
26327
|
}
|
|
26268
|
-
const store = new FilesystemSidecarStore();
|
|
26328
|
+
const store = new FilesystemSidecarStore(ensureSidecarWritesAllowed);
|
|
26269
26329
|
try {
|
|
26270
26330
|
for (const w of result.writes ?? []) {
|
|
26271
26331
|
if (w.kind === "sidecar") {
|
|
@@ -26320,7 +26380,7 @@ async function loadNode(deps, nodePath) {
|
|
|
26320
26380
|
}
|
|
26321
26381
|
return node;
|
|
26322
26382
|
}
|
|
26323
|
-
function invokeBump2(node, absPath, body) {
|
|
26383
|
+
function invokeBump2(node, absPath, body, cwd) {
|
|
26324
26384
|
if (!nodeBumpAction.invoke) {
|
|
26325
26385
|
throw new HTTPException15(500, { message: SERVER_TEXTS.sidecarBumpInvokeMissing });
|
|
26326
26386
|
}
|
|
@@ -26329,7 +26389,7 @@ function invokeBump2(node, absPath, body) {
|
|
|
26329
26389
|
return nodeBumpAction.invoke(input, {
|
|
26330
26390
|
node,
|
|
26331
26391
|
nodeAbsolutePath: absPath,
|
|
26332
|
-
invoker: "ui",
|
|
26392
|
+
invoker: resolveGitAuthorName(cwd) ?? "ui",
|
|
26333
26393
|
now: () => /* @__PURE__ */ new Date(),
|
|
26334
26394
|
settings: {}
|
|
26335
26395
|
});
|
|
@@ -26533,6 +26593,14 @@ var LoopbackGateError = class extends HTTPException16 {
|
|
|
26533
26593
|
this.code = init.code;
|
|
26534
26594
|
}
|
|
26535
26595
|
};
|
|
26596
|
+
var ConflictError = class extends HTTPException16 {
|
|
26597
|
+
code;
|
|
26598
|
+
constructor(init) {
|
|
26599
|
+
super(409, { message: init.message });
|
|
26600
|
+
this.name = "ConflictError";
|
|
26601
|
+
this.code = init.code;
|
|
26602
|
+
}
|
|
26603
|
+
};
|
|
26536
26604
|
function createApp(deps) {
|
|
26537
26605
|
const app = new Hono();
|
|
26538
26606
|
const configService = new ConfigService({
|
|
@@ -26609,16 +26677,12 @@ function createApp(deps) {
|
|
|
26609
26677
|
});
|
|
26610
26678
|
return app;
|
|
26611
26679
|
}
|
|
26612
|
-
function codeForStatus(status
|
|
26680
|
+
function codeForStatus(status) {
|
|
26613
26681
|
if (status === 404) return "not-found";
|
|
26614
26682
|
if (status === 400) return "bad-query";
|
|
26615
26683
|
if (status === 403) return "locked";
|
|
26616
26684
|
if (status === 412) return "confirm-required";
|
|
26617
26685
|
if (status === 413) return "payload-too-large";
|
|
26618
|
-
if (status === 409) {
|
|
26619
|
-
if (message.startsWith("scan-busy:")) return "scan-busy";
|
|
26620
|
-
return "sidecar-fresh";
|
|
26621
|
-
}
|
|
26622
26686
|
return "internal";
|
|
26623
26687
|
}
|
|
26624
26688
|
function formatError2(err, c) {
|
|
@@ -26655,12 +26719,23 @@ function formatError2(err, c) {
|
|
|
26655
26719
|
};
|
|
26656
26720
|
return c.json(envelope, 403);
|
|
26657
26721
|
}
|
|
26722
|
+
if (err instanceof ConflictError) {
|
|
26723
|
+
const envelope = {
|
|
26724
|
+
ok: false,
|
|
26725
|
+
error: {
|
|
26726
|
+
code: err.code,
|
|
26727
|
+
message: err.message,
|
|
26728
|
+
details: null
|
|
26729
|
+
}
|
|
26730
|
+
};
|
|
26731
|
+
return c.json(envelope, 409);
|
|
26732
|
+
}
|
|
26658
26733
|
if (err instanceof HTTPException16) {
|
|
26659
26734
|
const status = err.status;
|
|
26660
26735
|
const envelope = {
|
|
26661
26736
|
ok: false,
|
|
26662
26737
|
error: {
|
|
26663
|
-
code: codeForStatus(status
|
|
26738
|
+
code: codeForStatus(status),
|
|
26664
26739
|
message: err.message,
|
|
26665
26740
|
details: null
|
|
26666
26741
|
}
|
|
@@ -26711,6 +26786,7 @@ function formatInternalErrorFallThrough(err, c) {
|
|
|
26711
26786
|
var MAX_BUFFERED_BYTES = 4 * 1024 * 1024;
|
|
26712
26787
|
var CLOSE_CODE_GOING_AWAY = 1001;
|
|
26713
26788
|
var CLOSE_CODE_MESSAGE_TOO_BIG = 1009;
|
|
26789
|
+
var CLOSE_CODE_TRY_AGAIN_LATER = 1013;
|
|
26714
26790
|
var READY_STATE_OPEN = 1;
|
|
26715
26791
|
var WsBroadcaster = class {
|
|
26716
26792
|
#clients = /* @__PURE__ */ new Set();
|
|
@@ -26733,6 +26809,13 @@ var WsBroadcaster = class {
|
|
|
26733
26809
|
}
|
|
26734
26810
|
return;
|
|
26735
26811
|
}
|
|
26812
|
+
if (this.#clients.size >= MAX_WS_CLIENTS) {
|
|
26813
|
+
try {
|
|
26814
|
+
ws.close(CLOSE_CODE_TRY_AGAIN_LATER, "too many connections");
|
|
26815
|
+
} catch {
|
|
26816
|
+
}
|
|
26817
|
+
return;
|
|
26818
|
+
}
|
|
26736
26819
|
this.#clients.add(ws);
|
|
26737
26820
|
}
|
|
26738
26821
|
/**
|
|
@@ -26979,14 +27062,19 @@ function validatePort(port) {
|
|
|
26979
27062
|
return null;
|
|
26980
27063
|
}
|
|
26981
27064
|
function validateHost(host, devCors) {
|
|
26982
|
-
if (
|
|
27065
|
+
if (isLoopbackHost(host)) return null;
|
|
27066
|
+
if (devCors) {
|
|
26983
27067
|
return {
|
|
26984
27068
|
code: "host-dev-cors-rejected",
|
|
26985
27069
|
message: `--dev-cors requires a loopback --host (got ${host})`,
|
|
26986
27070
|
value: host
|
|
26987
27071
|
};
|
|
26988
27072
|
}
|
|
26989
|
-
return
|
|
27073
|
+
return {
|
|
27074
|
+
code: "host-not-loopback",
|
|
27075
|
+
message: `--host must be a loopback address; multi-host serve is not supported pre-1.0 (got ${host})`,
|
|
27076
|
+
value: host
|
|
27077
|
+
};
|
|
26990
27078
|
}
|
|
26991
27079
|
function validateWatcher(noWatcher, noBuiltIns, _noPlugins) {
|
|
26992
27080
|
if (noWatcher) return null;
|
|
@@ -27274,6 +27362,14 @@ var SERVE_TEXTS = {
|
|
|
27274
27362
|
*/
|
|
27275
27363
|
hostDevCorsRejected: "{{glyph}} sm serve: --dev-cors requires a loopback --host (got {{host}}).\n {{hint}}\n",
|
|
27276
27364
|
hostDevCorsRejectedHint: "Use --host 127.0.0.1 (or ::1) when --dev-cors is set. Multi-host serve reopens after v0.6.0 (Decision #119).",
|
|
27365
|
+
/**
|
|
27366
|
+
* §3.1b error block when `--host` is any non-loopback address (without
|
|
27367
|
+
* `--dev-cors`). The BFF is loopback-only and unauthenticated pre-1.0
|
|
27368
|
+
* (Decision #119), so binding off-loopback is refused outright rather
|
|
27369
|
+
* than relying on the DNS-rebinding gate as the sole control.
|
|
27370
|
+
*/
|
|
27371
|
+
hostNotLoopback: "{{glyph}} sm serve: --host must be a loopback address (got {{host}}).\n {{hint}}\n",
|
|
27372
|
+
hostNotLoopbackHint: "Use --host 127.0.0.1 (or ::1). The server has no auth and is loopback-only; multi-host serve reopens after v0.6.0 (Decision #119).",
|
|
27277
27373
|
/**
|
|
27278
27374
|
* §3.1b error block when `--port` falls outside the [0, 65535] range.
|
|
27279
27375
|
* Hint names the accepted range so the operator can re-run.
|
|
@@ -27822,6 +27918,12 @@ function formatValidationError(err, ansi) {
|
|
|
27822
27918
|
host: sanitizeForTerminal(err.value),
|
|
27823
27919
|
hint: ansi.dim(SERVE_TEXTS.hostDevCorsRejectedHint)
|
|
27824
27920
|
});
|
|
27921
|
+
case "host-not-loopback":
|
|
27922
|
+
return tx(SERVE_TEXTS.hostNotLoopback, {
|
|
27923
|
+
glyph: errGlyph,
|
|
27924
|
+
host: sanitizeForTerminal(err.value),
|
|
27925
|
+
hint: ansi.dim(SERVE_TEXTS.hostNotLoopbackHint)
|
|
27926
|
+
});
|
|
27825
27927
|
case "port-out-of-range":
|
|
27826
27928
|
return tx(SERVE_TEXTS.portOutOfRange, {
|
|
27827
27929
|
glyph: errGlyph,
|
|
@@ -28414,7 +28516,7 @@ var SidecarRefreshCommand = class extends SmCommand {
|
|
|
28414
28516
|
);
|
|
28415
28517
|
return ExitCode.Ok;
|
|
28416
28518
|
}
|
|
28417
|
-
const store = new FilesystemSidecarStore();
|
|
28519
|
+
const store = new FilesystemSidecarStore(ensureSidecarWritesAllowed);
|
|
28418
28520
|
try {
|
|
28419
28521
|
await store.applyPatch(
|
|
28420
28522
|
sidecarAbsPath,
|
|
@@ -28701,7 +28803,7 @@ var SidecarAnnotateCommand = class extends SmCommand {
|
|
|
28701
28803
|
return ExitCode.Error;
|
|
28702
28804
|
}
|
|
28703
28805
|
}
|
|
28704
|
-
const store = new FilesystemSidecarStore();
|
|
28806
|
+
const store = new FilesystemSidecarStore(ensureSidecarWritesAllowed);
|
|
28705
28807
|
try {
|
|
28706
28808
|
await store.applyPatch(
|
|
28707
28809
|
sidecarAbsPath,
|
|
@@ -29490,4 +29592,4 @@ function resolveBareDefault() {
|
|
|
29490
29592
|
process.exit(ExitCode.Error);
|
|
29491
29593
|
}
|
|
29492
29594
|
//# sourceMappingURL=cli.js.map
|
|
29493
|
-
//# debugId=
|
|
29595
|
+
//# debugId=91ef81c7-e785-5818-839a-1f18ea093b57
|