akm-cli 0.9.0 → 0.9.1-beta.1
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/CHANGELOG.md +707 -0
- package/README.md +28 -63
- package/STABILITY.md +4 -2
- package/dist/commands/agent/contribute-cli.js +1 -1
- package/dist/commands/feedback-cli.js +7 -1
- package/dist/commands/health/llm-usage.js +2 -1
- package/dist/commands/health/surfaces.js +4 -77
- package/dist/commands/health.js +65 -11
- package/dist/commands/improve/distill/quality-gate.js +6 -1
- package/dist/commands/improve/eligibility.js +7 -1
- package/dist/commands/improve/improve.js +126 -10
- package/dist/commands/improve/locks.js +7 -0
- package/dist/commands/improve/memory/memory-improve.js +8 -0
- package/dist/commands/improve/run-context.js +5 -0
- package/dist/commands/improve/session-asset.js +4 -0
- package/dist/commands/lint/base-linter.js +31 -7
- package/dist/commands/lint/index.js +200 -50
- package/dist/commands/lint/types.js +22 -1
- package/dist/commands/proposal/repository.js +17 -1
- package/dist/commands/sources/info.js +12 -2
- package/dist/commands/sources/installed-stashes.js +6 -1
- package/dist/commands/tasks/tasks.js +8 -2
- package/dist/commands/workflow-cli.js +17 -11
- package/dist/core/abort-deadline.js +28 -0
- package/dist/core/adapter/adapters/agent-skills-adapter.js +67 -5
- package/dist/core/adapter/adapters/akm-adapter.js +13 -10
- package/dist/core/adapter/adapters/akm-lint.js +72 -20
- package/dist/core/adapter/adapters/akm-task-adapter.js +40 -19
- package/dist/core/adapter/adapters/tool-dir-shared.js +5 -3
- package/dist/core/asset/frontmatter.js +4 -0
- package/dist/core/common.js +66 -6
- package/dist/core/concurrent.js +32 -0
- package/dist/core/config/schema/workflow.js +11 -0
- package/dist/core/errors.js +25 -0
- package/dist/core/events.js +30 -24
- package/dist/core/file-lock.js +7 -1
- package/dist/core/improve-result.js +5 -0
- package/dist/core/json-schema.js +327 -9
- package/dist/core/loopback.js +89 -0
- package/dist/core/migration-operation.js +17 -2
- package/dist/core/path-access.js +107 -0
- package/dist/core/redaction.js +64 -17
- package/dist/core/spawn-env.js +234 -0
- package/dist/core/state-db-scope.js +134 -0
- package/dist/core/subprocess.js +181 -37
- package/dist/core/write-provenance.js +85 -0
- package/dist/core/write-source.js +7 -0
- package/dist/indexer/db/graph-db.js +17 -6
- package/dist/indexer/ensure-index.js +10 -3
- package/dist/indexer/index-written-assets.js +17 -2
- package/dist/indexer/indexer.js +55 -15
- package/dist/indexer/passes/memory-inference.js +4 -0
- package/dist/indexer/search/db-search.js +8 -15
- package/dist/integrations/agent/engine-resolution.js +24 -11
- package/dist/integrations/agent/model-aliases.js +1 -1
- package/dist/integrations/agent/profiles.js +9 -1
- package/dist/integrations/agent/spawn.js +15 -87
- package/dist/integrations/lockfile.js +45 -2
- package/dist/output/text/lint-format.js +17 -4
- package/dist/scripts/akm-migrate-node.js +1435 -753
- package/dist/scripts/akm-migrate.js +1403 -721
- package/dist/sources/providers/git-stash.js +19 -0
- package/dist/sources/providers/git.js +1 -1
- package/dist/sources/snapshot-fetchers/website-ingest.js +126 -20
- package/dist/storage/database.js +6 -1
- package/dist/storage/managed-db.js +19 -0
- package/dist/storage/repositories/index-connection.js +28 -3
- package/dist/storage/repositories/index-entries-repository.js +6 -1
- package/dist/storage/repositories/workflow-runs-repository.js +66 -13
- package/dist/tasks/log-redaction.js +156 -0
- package/dist/tasks/parser.js +82 -5
- package/dist/tasks/runner.js +139 -11
- package/dist/tasks/schema.js +65 -0
- package/dist/workflows/concurrency-policy.js +95 -1
- package/dist/workflows/exec/dispatch-redaction.js +114 -0
- package/dist/workflows/exec/exec-unit.js +542 -0
- package/dist/workflows/exec/frozen-judge.js +114 -42
- package/dist/workflows/exec/native-executor.js +457 -238
- package/dist/workflows/exec/param-secrets.js +4 -3
- package/dist/workflows/exec/run-workflow.js +424 -219
- package/dist/workflows/exec/step-work.js +496 -165
- package/dist/workflows/exec/unit-dispatch.js +31 -1
- package/dist/workflows/exec/unit-writer.js +53 -13
- package/dist/workflows/exec/worktree.js +454 -41
- package/dist/workflows/ir/compile.js +26 -2
- package/dist/workflows/ir/freeze.js +82 -15
- package/dist/workflows/ir/schema.js +105 -20
- package/dist/workflows/parser.js +216 -18
- package/dist/workflows/program/schema.js +24 -0
- package/dist/workflows/renderer.js +32 -4
- package/dist/workflows/resource-limits.js +182 -0
- package/dist/workflows/runtime/runs.js +146 -6
- package/dist/workflows/validate-summary.js +17 -2
- package/docs/README.md +74 -32
- package/docs/migration/release-notes/0.9.0.md +2 -1
- package/docs/migration/v0.7-to-v0.8.md +2 -1
- package/docs/migration/v0.8-to-v0.9.md +3 -1
- package/docs/reference/README.md +11 -4
- package/docs/reference/bundle-types.md +19 -0
- package/docs/reference/cli.md +105 -16
- package/docs/reference/configuration.md +15 -2
- package/docs/reference/data-and-telemetry.md +30 -10
- package/docs/reference/supported-formats.md +50 -0
- package/docs/reference/workflow-schema.md +1014 -0
- package/docs/reference/workflows.md +37 -633
- package/package.json +13 -6
- package/schemas/akm-config.json +8 -0
- package/schemas/akm-task.json +27 -5
- package/schemas/akm-workflow.json +85 -10
|
@@ -6977,12 +6977,21 @@ function rethrowIfTestIsolationError(err) {
|
|
|
6977
6977
|
throw err;
|
|
6978
6978
|
}
|
|
6979
6979
|
}
|
|
6980
|
+
function isDataDirUnreadableError(err) {
|
|
6981
|
+
return err instanceof ConfigError && err.code === "DATA_DIR_UNREADABLE";
|
|
6982
|
+
}
|
|
6983
|
+
function rethrowIfDataDirUnreadable(err) {
|
|
6984
|
+
if (isDataDirUnreadableError(err)) {
|
|
6985
|
+
throw err;
|
|
6986
|
+
}
|
|
6987
|
+
}
|
|
6980
6988
|
var CONFIG_HINTS, USAGE_HINTS, NOT_FOUND_HINTS, AkmError, ConfigError, UsageError, NotFoundError;
|
|
6981
6989
|
var init_errors = __esm(() => {
|
|
6982
6990
|
CONFIG_HINTS = {
|
|
6983
6991
|
STASH_DIR_NOT_FOUND: "Run `akm setup` to create and configure your bundle, or configure a defaultBundle path.",
|
|
6984
6992
|
STASH_DIR_NOT_A_DIRECTORY: "The configured default bundle path exists but isn't a directory. Update it to point at a folder.",
|
|
6985
6993
|
STASH_DIR_UNREADABLE: "Check the path exists and your user has read permission, or update the default bundle path.",
|
|
6994
|
+
DATA_DIR_UNREADABLE: "The data directory is not readable by the user running akm. Check its owner and mode, or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user owns.",
|
|
6986
6995
|
EMBEDDING_NOT_CONFIGURED: 'Run `akm config set embedding \'{"endpoint":"...","model":"..."}\'` to enable embeddings.',
|
|
6987
6996
|
LLM_NOT_CONFIGURED: 'Run `akm setup` or configure an `engines` entry with `kind: "llm"`, then select it with `defaults.llmEngine`.',
|
|
6988
6997
|
TEST_ISOLATION_MISSING: "Under bun test, when AKM_BUNDLE_DIR is set you MUST also set XDG_DATA_HOME (or AKM_DATA_DIR) and XDG_STATE_HOME (or AKM_STATE_DIR) to temp directories so the test does not touch the developer's real ~/.local/share/akm or ~/.local/state/akm.",
|
|
@@ -7411,13 +7420,23 @@ function hasErrnoCode(error, code) {
|
|
|
7411
7420
|
return false;
|
|
7412
7421
|
return error.code === code;
|
|
7413
7422
|
}
|
|
7423
|
+
function isContainedRelativePath(value) {
|
|
7424
|
+
if (value === "" || value.startsWith("/") || value.startsWith("\\") || value.startsWith("~"))
|
|
7425
|
+
return false;
|
|
7426
|
+
if (/^[A-Za-z]:/.test(value))
|
|
7427
|
+
return false;
|
|
7428
|
+
return !value.split(/[/\\]+/).includes("..");
|
|
7429
|
+
}
|
|
7414
7430
|
function isWithin(candidate, root) {
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
const
|
|
7419
|
-
|
|
7420
|
-
|
|
7431
|
+
return isContainedResolvedPath(safeRealpath(candidate), safeRealpath(root));
|
|
7432
|
+
}
|
|
7433
|
+
function isContainedResolvedPath(resolvedCandidate, resolvedRoot) {
|
|
7434
|
+
const rel = path2.relative(normalizeFsPathForComparison(resolvedRoot), normalizeFsPathForComparison(resolvedCandidate));
|
|
7435
|
+
if (rel === "")
|
|
7436
|
+
return true;
|
|
7437
|
+
if (path2.isAbsolute(rel))
|
|
7438
|
+
return false;
|
|
7439
|
+
return rel.split(/[/\\]+/)[0] !== "..";
|
|
7421
7440
|
}
|
|
7422
7441
|
function safeRealpath(p) {
|
|
7423
7442
|
const resolved = path2.resolve(p);
|
|
@@ -8124,31 +8143,83 @@ var require_main = __commonJS((exports, module) => {
|
|
|
8124
8143
|
module.exports = DotenvModule;
|
|
8125
8144
|
});
|
|
8126
8145
|
|
|
8146
|
+
// src/core/path-access.ts
|
|
8147
|
+
import fs5 from "fs";
|
|
8148
|
+
function errnoOf(error) {
|
|
8149
|
+
const code = error?.code;
|
|
8150
|
+
return typeof code === "string" ? code : undefined;
|
|
8151
|
+
}
|
|
8152
|
+
function classifyPathAccess(target) {
|
|
8153
|
+
try {
|
|
8154
|
+
fs5.statSync(target);
|
|
8155
|
+
} catch (error) {
|
|
8156
|
+
const code = errnoOf(error);
|
|
8157
|
+
if (code === "ENOENT" || code === "ENOTDIR")
|
|
8158
|
+
return { access: "absent" };
|
|
8159
|
+
return { access: "inaccessible", ...code ? { code } : {} };
|
|
8160
|
+
}
|
|
8161
|
+
try {
|
|
8162
|
+
fs5.accessSync(target, fs5.constants.R_OK);
|
|
8163
|
+
} catch (error) {
|
|
8164
|
+
const code = errnoOf(error);
|
|
8165
|
+
return { access: "inaccessible", ...code ? { code } : {} };
|
|
8166
|
+
}
|
|
8167
|
+
return { access: "present" };
|
|
8168
|
+
}
|
|
8169
|
+
function isPathAbsent(target) {
|
|
8170
|
+
return classifyPathAccess(target).access === "absent";
|
|
8171
|
+
}
|
|
8172
|
+
function describeInaccessiblePath(target, code) {
|
|
8173
|
+
const parts = [target];
|
|
8174
|
+
if (code)
|
|
8175
|
+
parts.push(`(${code})`);
|
|
8176
|
+
try {
|
|
8177
|
+
const stat = fs5.statSync(target);
|
|
8178
|
+
parts.push(`mode ${(stat.mode & 511).toString(8).padStart(3, "0")}, owner uid ${stat.uid}`);
|
|
8179
|
+
} catch {
|
|
8180
|
+
const parent = target.slice(0, Math.max(0, target.lastIndexOf("/")));
|
|
8181
|
+
if (parent) {
|
|
8182
|
+
try {
|
|
8183
|
+
const stat = fs5.statSync(parent);
|
|
8184
|
+
parts.push(`parent ${parent} is mode ${(stat.mode & 511).toString(8).padStart(3, "0")}, owner uid ${stat.uid}`);
|
|
8185
|
+
} catch {}
|
|
8186
|
+
}
|
|
8187
|
+
}
|
|
8188
|
+
const uid = typeof process.getuid === "function" ? process.getuid() : undefined;
|
|
8189
|
+
if (uid !== undefined)
|
|
8190
|
+
parts.push(`running as uid ${uid}`);
|
|
8191
|
+
return parts.join("; ");
|
|
8192
|
+
}
|
|
8193
|
+
var init_path_access = () => {};
|
|
8194
|
+
|
|
8127
8195
|
// src/core/migration-operation.ts
|
|
8128
8196
|
import crypto2 from "crypto";
|
|
8129
|
-
import
|
|
8130
|
-
import path8 from "path";
|
|
8197
|
+
import path9 from "path";
|
|
8131
8198
|
function installationId() {
|
|
8132
|
-
return crypto2.createHash("sha256").update(
|
|
8199
|
+
return crypto2.createHash("sha256").update(path9.resolve(path9.dirname(getConfigPath()))).update("\x00").update(path9.resolve(getDataDir())).digest("hex").slice(0, 24);
|
|
8133
8200
|
}
|
|
8134
8201
|
function getMigrationOperationRoot() {
|
|
8135
|
-
return
|
|
8202
|
+
return path9.join(getDataDir(), "backups", "migrations", installationId());
|
|
8136
8203
|
}
|
|
8137
8204
|
function getMigrationRestoreJournalPath() {
|
|
8138
|
-
return
|
|
8205
|
+
return path9.join(getMigrationOperationRoot(), "restore-active.json");
|
|
8139
8206
|
}
|
|
8140
8207
|
function getMigrationApplyJournalPath() {
|
|
8141
|
-
return
|
|
8208
|
+
return path9.join(getMigrationOperationRoot(), "apply-active.json");
|
|
8142
8209
|
}
|
|
8143
8210
|
function getMigrationGeneratedConfigPath() {
|
|
8144
|
-
return
|
|
8211
|
+
return path9.join(getMigrationOperationRoot(), "generated-config.json");
|
|
8145
8212
|
}
|
|
8146
8213
|
function assertNoPendingMigrationOperation() {
|
|
8147
8214
|
for (const [kind, journalPath] of [
|
|
8148
8215
|
["restore", getMigrationRestoreJournalPath()],
|
|
8149
8216
|
["migration apply", getMigrationApplyJournalPath()]
|
|
8150
8217
|
]) {
|
|
8151
|
-
|
|
8218
|
+
const { access, code } = classifyPathAccess(journalPath);
|
|
8219
|
+
if (access === "inaccessible") {
|
|
8220
|
+
throw new ConfigError(`Cannot determine whether an AKM ${kind} recovery is pending: ${describeInaccessiblePath(journalPath, code)}. ` + "Refusing canonical config/database access \u2014 proceeding could write on top of a half-applied migration.", "DATA_DIR_UNREADABLE");
|
|
8221
|
+
}
|
|
8222
|
+
if (access === "present") {
|
|
8152
8223
|
throw new ConfigError(`AKM ${kind} recovery is pending at ${journalPath}; refusing canonical config/database access until recovery completes.`, "INVALID_CONFIG_FILE");
|
|
8153
8224
|
}
|
|
8154
8225
|
}
|
|
@@ -8159,6 +8230,7 @@ function assertNoPendingMigrationOperation() {
|
|
|
8159
8230
|
var afterPendingCheckHook;
|
|
8160
8231
|
var init_migration_operation = __esm(() => {
|
|
8161
8232
|
init_errors();
|
|
8233
|
+
init_path_access();
|
|
8162
8234
|
init_paths();
|
|
8163
8235
|
});
|
|
8164
8236
|
|
|
@@ -8171,11 +8243,11 @@ function selectProvider() {
|
|
|
8171
8243
|
}
|
|
8172
8244
|
return provider;
|
|
8173
8245
|
}
|
|
8174
|
-
function openDatabase(
|
|
8175
|
-
return selectProvider().open(
|
|
8246
|
+
function openDatabase(path10, opts) {
|
|
8247
|
+
return selectProvider().open(path10, opts);
|
|
8176
8248
|
}
|
|
8177
|
-
function openDatabaseFinalizing(
|
|
8178
|
-
const db = selectProvider().open(
|
|
8249
|
+
function openDatabaseFinalizing(path10, opts) {
|
|
8250
|
+
const db = selectProvider().open(path10, opts);
|
|
8179
8251
|
const tracked = new Set;
|
|
8180
8252
|
const origPrepare = db.prepare.bind(db);
|
|
8181
8253
|
const origClose = db.close.bind(db);
|
|
@@ -8195,9 +8267,9 @@ function openDatabaseFinalizing(path9, opts) {
|
|
|
8195
8267
|
};
|
|
8196
8268
|
return db;
|
|
8197
8269
|
}
|
|
8198
|
-
function openBunDatabase(
|
|
8270
|
+
function openBunDatabase(path10, opts) {
|
|
8199
8271
|
const { Database: BunDatabase } = loadBunSqlite();
|
|
8200
|
-
const db = opts ? new BunDatabase(
|
|
8272
|
+
const db = opts ? new BunDatabase(path10, bunOptions(opts)) : new BunDatabase(path10);
|
|
8201
8273
|
return db;
|
|
8202
8274
|
}
|
|
8203
8275
|
function bunOptions(opts) {
|
|
@@ -8223,7 +8295,11 @@ function loadBetterSqlite3() {
|
|
|
8223
8295
|
mod = nodeRequire2("better-sqlite3");
|
|
8224
8296
|
} catch (err) {
|
|
8225
8297
|
throw new Error(`akm could not load 'better-sqlite3', the SQLite driver it needs on Node.js.
|
|
8226
|
-
` + ` \u2022
|
|
8298
|
+
` + ` \u2022 If the error below says the module was compiled against a DIFFERENT Node.js
|
|
8299
|
+
` + ` version, you upgraded Node after installing akm. Reinstall akm (or run
|
|
8300
|
+
` + " `npm rebuild better-sqlite3` in its install directory) so the binding is\n" + ` rebuilt for the Node you are now running. This is the common case after a
|
|
8301
|
+
` + ` Node major upgrade, and it is NOT a broken install.
|
|
8302
|
+
` + ` \u2022 Otherwise, reinstall akm with a working C/C++ build toolchain so its optional
|
|
8227
8303
|
` + " 'better-sqlite3' native binding rebuilds (a global `npm i -g better-sqlite3`\n" + ` will NOT be resolved \u2014 Node loads it from akm's own node_modules).
|
|
8228
8304
|
` + ` \u2022 Or run akm under Bun, which has a built-in SQLite driver and needs no native build.
|
|
8229
8305
|
` + ` Underlying load error: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -8232,14 +8308,14 @@ function loadBetterSqlite3() {
|
|
|
8232
8308
|
}
|
|
8233
8309
|
return betterSqlite3Ctor;
|
|
8234
8310
|
}
|
|
8235
|
-
function openNodeDatabase(
|
|
8311
|
+
function openNodeDatabase(path10, opts) {
|
|
8236
8312
|
const BetterSqlite3 = loadBetterSqlite3();
|
|
8237
8313
|
const options = {};
|
|
8238
8314
|
if (opts?.readonly !== undefined)
|
|
8239
8315
|
options.readonly = opts.readonly;
|
|
8240
8316
|
if (opts?.create === false)
|
|
8241
8317
|
options.fileMustExist = true;
|
|
8242
|
-
const db = opts ? new BetterSqlite3(
|
|
8318
|
+
const db = opts ? new BetterSqlite3(path10, options) : new BetterSqlite3(path10);
|
|
8243
8319
|
return {
|
|
8244
8320
|
prepare: db.prepare.bind(db),
|
|
8245
8321
|
exec: db.exec.bind(db),
|
|
@@ -8271,7 +8347,7 @@ var init_database = __esm(() => {
|
|
|
8271
8347
|
// src/core/file-lock.ts
|
|
8272
8348
|
import { randomUUID } from "crypto";
|
|
8273
8349
|
import fs6 from "fs";
|
|
8274
|
-
import
|
|
8350
|
+
import path10 from "path";
|
|
8275
8351
|
function readLockSnapshot(lockPath) {
|
|
8276
8352
|
let fd;
|
|
8277
8353
|
try {
|
|
@@ -8296,7 +8372,7 @@ function sameIdentity(left, right) {
|
|
|
8296
8372
|
return left.dev === right.dev && left.ino === right.ino && left.size === right.size && left.mtimeMs === right.mtimeMs;
|
|
8297
8373
|
}
|
|
8298
8374
|
function operationMutexPath(lockPath) {
|
|
8299
|
-
return
|
|
8375
|
+
return path10.join(path10.dirname(lockPath), `.${path10.basename(lockPath)}.operations.sensitive`);
|
|
8300
8376
|
}
|
|
8301
8377
|
function withLockOperationMutex(lockPath, run) {
|
|
8302
8378
|
const db = openDatabase(operationMutexPath(lockPath));
|
|
@@ -8362,7 +8438,10 @@ function probeLock(lockPath, opts) {
|
|
|
8362
8438
|
let snapshot;
|
|
8363
8439
|
try {
|
|
8364
8440
|
snapshot = readLockSnapshot(lockPath);
|
|
8365
|
-
} catch {
|
|
8441
|
+
} catch (error) {
|
|
8442
|
+
const code = error?.code;
|
|
8443
|
+
if (code === "EACCES" || code === "EPERM")
|
|
8444
|
+
return { state: "inaccessible", code };
|
|
8366
8445
|
return { state: "stale", reason: "unreadable" };
|
|
8367
8446
|
}
|
|
8368
8447
|
if (!snapshot)
|
|
@@ -8529,10 +8608,10 @@ var init_warn = () => {};
|
|
|
8529
8608
|
import { AsyncLocalStorage } from "async_hooks";
|
|
8530
8609
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
8531
8610
|
import fs10 from "fs";
|
|
8532
|
-
import
|
|
8611
|
+
import path12 from "path";
|
|
8533
8612
|
function tryAcquireMaintenanceBarrier() {
|
|
8534
8613
|
const lockPath = getMaintenanceBarrierPath();
|
|
8535
|
-
fs10.mkdirSync(
|
|
8614
|
+
fs10.mkdirSync(path12.dirname(lockPath), { recursive: true });
|
|
8536
8615
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
8537
8616
|
const ownership = tryAcquireLockSync(lockPath, createLockPayload({ purpose: "maintenance-start" }));
|
|
8538
8617
|
if (ownership) {
|
|
@@ -8583,9 +8662,9 @@ function withMaintenanceStartBarrierSyncWait(run) {
|
|
|
8583
8662
|
}
|
|
8584
8663
|
function acquireMaintenanceActivitySync(name) {
|
|
8585
8664
|
return withMaintenanceStartBarrierSyncWait(() => {
|
|
8586
|
-
const directory =
|
|
8665
|
+
const directory = path12.join(path12.dirname(getMaintenanceBarrierPath()), "maintenance-activities");
|
|
8587
8666
|
fs10.mkdirSync(directory, { recursive: true, mode: 448 });
|
|
8588
|
-
const lockPath =
|
|
8667
|
+
const lockPath = path12.join(directory, `${name}-${process.pid}-${randomUUID2()}.lock`);
|
|
8589
8668
|
const ownership = tryAcquireLockSync(lockPath, createLockPayload({ purpose: name }));
|
|
8590
8669
|
if (!ownership) {
|
|
8591
8670
|
throw new ConfigError(`Could not register AKM maintenance activity at ${lockPath}.`, "INVALID_CONFIG_FILE");
|
|
@@ -15636,33 +15715,33 @@ var require_URL = __commonJS((exports, module) => {
|
|
|
15636
15715
|
else
|
|
15637
15716
|
return basepath.substring(0, lastslash + 1) + refpath;
|
|
15638
15717
|
}
|
|
15639
|
-
function remove_dot_segments(
|
|
15640
|
-
if (!
|
|
15641
|
-
return
|
|
15718
|
+
function remove_dot_segments(path43) {
|
|
15719
|
+
if (!path43)
|
|
15720
|
+
return path43;
|
|
15642
15721
|
var output = "";
|
|
15643
|
-
while (
|
|
15644
|
-
if (
|
|
15645
|
-
|
|
15722
|
+
while (path43.length > 0) {
|
|
15723
|
+
if (path43 === "." || path43 === "..") {
|
|
15724
|
+
path43 = "";
|
|
15646
15725
|
break;
|
|
15647
15726
|
}
|
|
15648
|
-
var twochars =
|
|
15649
|
-
var threechars =
|
|
15650
|
-
var fourchars =
|
|
15727
|
+
var twochars = path43.substring(0, 2);
|
|
15728
|
+
var threechars = path43.substring(0, 3);
|
|
15729
|
+
var fourchars = path43.substring(0, 4);
|
|
15651
15730
|
if (threechars === "../") {
|
|
15652
|
-
|
|
15731
|
+
path43 = path43.substring(3);
|
|
15653
15732
|
} else if (twochars === "./") {
|
|
15654
|
-
|
|
15733
|
+
path43 = path43.substring(2);
|
|
15655
15734
|
} else if (threechars === "/./") {
|
|
15656
|
-
|
|
15657
|
-
} else if (twochars === "/." &&
|
|
15658
|
-
|
|
15659
|
-
} else if (fourchars === "/../" || threechars === "/.." &&
|
|
15660
|
-
|
|
15735
|
+
path43 = "/" + path43.substring(3);
|
|
15736
|
+
} else if (twochars === "/." && path43.length === 2) {
|
|
15737
|
+
path43 = "/";
|
|
15738
|
+
} else if (fourchars === "/../" || threechars === "/.." && path43.length === 3) {
|
|
15739
|
+
path43 = "/" + path43.substring(4);
|
|
15661
15740
|
output = output.replace(/\/?[^\/]*$/, "");
|
|
15662
15741
|
} else {
|
|
15663
|
-
var segment =
|
|
15742
|
+
var segment = path43.match(/(\/?([^\/]*))/)[0];
|
|
15664
15743
|
output += segment;
|
|
15665
|
-
|
|
15744
|
+
path43 = path43.substring(segment.length);
|
|
15666
15745
|
}
|
|
15667
15746
|
}
|
|
15668
15747
|
return output;
|
|
@@ -26972,9 +27051,9 @@ var init_sqlite_pragmas = __esm(() => {
|
|
|
26972
27051
|
|
|
26973
27052
|
// src/storage/managed-db.ts
|
|
26974
27053
|
import fs44 from "fs";
|
|
26975
|
-
import
|
|
27054
|
+
import path50 from "path";
|
|
26976
27055
|
function openManagedDatabase(spec) {
|
|
26977
|
-
const dir =
|
|
27056
|
+
const dir = path50.dirname(spec.path);
|
|
26978
27057
|
if (spec.create !== false && !fs44.existsSync(dir)) {
|
|
26979
27058
|
fs44.mkdirSync(dir, { recursive: true });
|
|
26980
27059
|
}
|
|
@@ -27010,14 +27089,14 @@ __export(exports_state_db, {
|
|
|
27010
27089
|
getStateDbPath: () => getStateDbPath
|
|
27011
27090
|
});
|
|
27012
27091
|
import fs45 from "fs";
|
|
27013
|
-
import
|
|
27092
|
+
import path51 from "path";
|
|
27014
27093
|
function getStateDbPath() {
|
|
27015
|
-
return
|
|
27094
|
+
return path51.join(getDataDir(), "state.db");
|
|
27016
27095
|
}
|
|
27017
27096
|
function openStateDatabase(dbPath) {
|
|
27018
27097
|
const canonicalPath = getStateDbPath();
|
|
27019
27098
|
const resolvedPath = dbPath ?? canonicalPath;
|
|
27020
|
-
const isCanonical =
|
|
27099
|
+
const isCanonical = path51.resolve(resolvedPath) === path51.resolve(canonicalPath);
|
|
27021
27100
|
if (isCanonical)
|
|
27022
27101
|
assertNoPendingMigrationOperation();
|
|
27023
27102
|
const releaseActivity = isCanonical ? acquireMaintenanceActivitySync("state-db") : undefined;
|
|
@@ -27907,9 +27986,9 @@ __export(exports_index_connection, {
|
|
|
27907
27986
|
openReadonlyExistingDatabase: () => openReadonlyExistingDatabase,
|
|
27908
27987
|
openIndexDatabase: () => openIndexDatabase,
|
|
27909
27988
|
openExistingDatabase: () => openExistingDatabase,
|
|
27910
|
-
closeDatabase: () => closeDatabase
|
|
27989
|
+
closeDatabase: () => closeDatabase,
|
|
27990
|
+
assertIndexPathReadable: () => assertIndexPathReadable
|
|
27911
27991
|
});
|
|
27912
|
-
import fs46 from "fs";
|
|
27913
27992
|
import { createRequire as createRequire4 } from "module";
|
|
27914
27993
|
function openIndexDatabase(dbPath, options) {
|
|
27915
27994
|
return openManagedDatabase({
|
|
@@ -27937,14 +28016,22 @@ function resolveConfiguredEmbeddingDim() {
|
|
|
27937
28016
|
}
|
|
27938
28017
|
function openExistingDatabase(dbPath) {
|
|
27939
28018
|
const resolvedPath = dbPath ?? getDbPath();
|
|
27940
|
-
|
|
28019
|
+
assertIndexPathReadable(resolvedPath);
|
|
28020
|
+
if (classifyPathAccess(resolvedPath).access === "absent") {
|
|
27941
28021
|
throw new Error(`Index database not found at ${resolvedPath}. Run 'akm index' to build it.`);
|
|
27942
28022
|
}
|
|
27943
28023
|
return openManagedDatabase({ path: resolvedPath, init: loadVecExtension, create: false });
|
|
27944
28024
|
}
|
|
28025
|
+
function assertIndexPathReadable(resolvedPath) {
|
|
28026
|
+
const { access, code } = classifyPathAccess(resolvedPath);
|
|
28027
|
+
if (access !== "inaccessible")
|
|
28028
|
+
return;
|
|
28029
|
+
throw new ConfigError(`Index database exists but is not readable: ${describeInaccessiblePath(resolvedPath, code)}.`, "DATA_DIR_UNREADABLE");
|
|
28030
|
+
}
|
|
27945
28031
|
function openReadonlyExistingDatabase(dbPath) {
|
|
27946
28032
|
const resolvedPath = dbPath ?? getDbPath();
|
|
27947
|
-
|
|
28033
|
+
assertIndexPathReadable(resolvedPath);
|
|
28034
|
+
if (classifyPathAccess(resolvedPath).access === "absent")
|
|
27948
28035
|
return;
|
|
27949
28036
|
return openDatabase(resolvedPath, { readonly: true, create: false });
|
|
27950
28037
|
}
|
|
@@ -27952,6 +28039,8 @@ function closeDatabase(db) {
|
|
|
27952
28039
|
db.close();
|
|
27953
28040
|
}
|
|
27954
28041
|
var init_index_connection = __esm(() => {
|
|
28042
|
+
init_errors();
|
|
28043
|
+
init_path_access();
|
|
27955
28044
|
init_paths();
|
|
27956
28045
|
init_database();
|
|
27957
28046
|
init_managed_db();
|
|
@@ -27971,12 +28060,11 @@ __export(exports_graph_db, {
|
|
|
27971
28060
|
drainExtractionQueue: () => drainExtractionQueue,
|
|
27972
28061
|
deleteStoredGraph: () => deleteStoredGraph
|
|
27973
28062
|
});
|
|
27974
|
-
import fs47 from "fs";
|
|
27975
28063
|
function withReadableGraphDb(db, fn) {
|
|
27976
28064
|
if (db)
|
|
27977
28065
|
return fn(db);
|
|
27978
28066
|
const dbPath = getDbPath();
|
|
27979
|
-
if (
|
|
28067
|
+
if (isPathAbsent(dbPath))
|
|
27980
28068
|
throw new Error("GRAPH_DB_MISSING");
|
|
27981
28069
|
const opened = openExistingDatabase(dbPath);
|
|
27982
28070
|
try {
|
|
@@ -28150,6 +28238,7 @@ function loadGraphFilesOnly(stashPath, db) {
|
|
|
28150
28238
|
});
|
|
28151
28239
|
} catch (err) {
|
|
28152
28240
|
rethrowIfTestIsolationError(err);
|
|
28241
|
+
rethrowIfDataDirUnreadable(err);
|
|
28153
28242
|
return [];
|
|
28154
28243
|
}
|
|
28155
28244
|
}
|
|
@@ -28212,6 +28301,7 @@ function loadStoredGraphMeta(stashPath, db) {
|
|
|
28212
28301
|
});
|
|
28213
28302
|
} catch (err) {
|
|
28214
28303
|
rethrowIfTestIsolationError(err);
|
|
28304
|
+
rethrowIfDataDirUnreadable(err);
|
|
28215
28305
|
return null;
|
|
28216
28306
|
}
|
|
28217
28307
|
}
|
|
@@ -28296,11 +28386,13 @@ function loadStoredGraphSnapshot(stashPath, db) {
|
|
|
28296
28386
|
});
|
|
28297
28387
|
} catch (err) {
|
|
28298
28388
|
rethrowIfTestIsolationError(err);
|
|
28389
|
+
rethrowIfDataDirUnreadable(err);
|
|
28299
28390
|
return null;
|
|
28300
28391
|
}
|
|
28301
28392
|
}
|
|
28302
28393
|
var init_graph_db = __esm(() => {
|
|
28303
28394
|
init_errors();
|
|
28395
|
+
init_path_access();
|
|
28304
28396
|
init_paths();
|
|
28305
28397
|
init_index_connection();
|
|
28306
28398
|
});
|
|
@@ -28312,9 +28404,9 @@ __export(exports_migrate_storage, {
|
|
|
28312
28404
|
main: () => main,
|
|
28313
28405
|
MIGRATIONS: () => MIGRATIONS
|
|
28314
28406
|
});
|
|
28315
|
-
import
|
|
28407
|
+
import fs46 from "fs";
|
|
28316
28408
|
import os7 from "os";
|
|
28317
|
-
import
|
|
28409
|
+
import path52 from "path";
|
|
28318
28410
|
import readline from "readline";
|
|
28319
28411
|
function parseFromArg(args) {
|
|
28320
28412
|
const idx = args.indexOf("--from");
|
|
@@ -28328,14 +28420,14 @@ function parseFromArg(args) {
|
|
|
28328
28420
|
return val;
|
|
28329
28421
|
}
|
|
28330
28422
|
function ensureDir(dir) {
|
|
28331
|
-
if (!
|
|
28332
|
-
|
|
28423
|
+
if (!fs46.existsSync(dir)) {
|
|
28424
|
+
fs46.mkdirSync(dir, { recursive: true });
|
|
28333
28425
|
}
|
|
28334
28426
|
}
|
|
28335
28427
|
function copyAndVerify(src, dest) {
|
|
28336
|
-
|
|
28337
|
-
const srcStat =
|
|
28338
|
-
const destStat =
|
|
28428
|
+
fs46.copyFileSync(src, dest);
|
|
28429
|
+
const srcStat = fs46.statSync(src);
|
|
28430
|
+
const destStat = fs46.statSync(dest);
|
|
28339
28431
|
return destStat.size === srcStat.size;
|
|
28340
28432
|
}
|
|
28341
28433
|
function copyTree(src, dest, opts) {
|
|
@@ -28343,9 +28435,9 @@ function copyTree(src, dest, opts) {
|
|
|
28343
28435
|
let skipped = 0;
|
|
28344
28436
|
let failed = 0;
|
|
28345
28437
|
ensureDir(dest);
|
|
28346
|
-
for (const entry of
|
|
28347
|
-
const srcEntry =
|
|
28348
|
-
const destEntry =
|
|
28438
|
+
for (const entry of fs46.readdirSync(src, { withFileTypes: true })) {
|
|
28439
|
+
const srcEntry = path52.join(src, entry.name);
|
|
28440
|
+
const destEntry = path52.join(dest, entry.name);
|
|
28349
28441
|
if (entry.isDirectory()) {
|
|
28350
28442
|
const sub = copyTree(srcEntry, destEntry, opts);
|
|
28351
28443
|
copied += sub.copied;
|
|
@@ -28353,7 +28445,7 @@ function copyTree(src, dest, opts) {
|
|
|
28353
28445
|
failed += sub.failed;
|
|
28354
28446
|
continue;
|
|
28355
28447
|
}
|
|
28356
|
-
if (!opts.clobber &&
|
|
28448
|
+
if (!opts.clobber && fs46.existsSync(destEntry)) {
|
|
28357
28449
|
skipped++;
|
|
28358
28450
|
continue;
|
|
28359
28451
|
}
|
|
@@ -28371,9 +28463,9 @@ function copyTree(src, dest, opts) {
|
|
|
28371
28463
|
}
|
|
28372
28464
|
function countFilesRecursive(dir) {
|
|
28373
28465
|
let count = 0;
|
|
28374
|
-
for (const entry of
|
|
28466
|
+
for (const entry of fs46.readdirSync(dir, { withFileTypes: true })) {
|
|
28375
28467
|
if (entry.isDirectory()) {
|
|
28376
|
-
count += countFilesRecursive(
|
|
28468
|
+
count += countFilesRecursive(path52.join(dir, entry.name));
|
|
28377
28469
|
} else {
|
|
28378
28470
|
count++;
|
|
28379
28471
|
}
|
|
@@ -28386,12 +28478,12 @@ async function runSteps(steps, ctx) {
|
|
|
28386
28478
|
}
|
|
28387
28479
|
}
|
|
28388
28480
|
function migrateDb(ctx, filename) {
|
|
28389
|
-
const src =
|
|
28390
|
-
const dest =
|
|
28391
|
-
if (!
|
|
28481
|
+
const src = path52.join(ctx.paths.cacheDir, filename);
|
|
28482
|
+
const dest = path52.join(ctx.paths.dataDir, filename);
|
|
28483
|
+
if (!fs46.existsSync(src)) {
|
|
28392
28484
|
return { name: filename, status: "skipped", detail: "source not found" };
|
|
28393
28485
|
}
|
|
28394
|
-
if (
|
|
28486
|
+
if (fs46.existsSync(dest)) {
|
|
28395
28487
|
return { name: filename, status: "skipped", detail: "destination already exists" };
|
|
28396
28488
|
}
|
|
28397
28489
|
if (ctx.dryRun) {
|
|
@@ -28409,8 +28501,8 @@ function migrateDb(ctx, filename) {
|
|
|
28409
28501
|
return { name: filename, status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` };
|
|
28410
28502
|
}
|
|
28411
28503
|
async function migrateEventsJsonl(ctx) {
|
|
28412
|
-
const src =
|
|
28413
|
-
if (!
|
|
28504
|
+
const src = path52.join(ctx.paths.cacheDir, "events.jsonl");
|
|
28505
|
+
if (!fs46.existsSync(src)) {
|
|
28414
28506
|
return { name: "events.jsonl \u2192 state.db", status: "skipped", detail: "source not found" };
|
|
28415
28507
|
}
|
|
28416
28508
|
if (ctx.dryRun) {
|
|
@@ -28455,13 +28547,13 @@ async function migrateEventsJsonl(ctx) {
|
|
|
28455
28547
|
}
|
|
28456
28548
|
}
|
|
28457
28549
|
function migrateTaskHistory(ctx) {
|
|
28458
|
-
const src =
|
|
28459
|
-
const dest =
|
|
28460
|
-
if (!
|
|
28550
|
+
const src = path52.join(ctx.paths.cacheDir, "tasks", "history");
|
|
28551
|
+
const dest = path52.join(ctx.paths.stateDir, "tasks", "history");
|
|
28552
|
+
if (!fs46.existsSync(src)) {
|
|
28461
28553
|
return { name: "tasks/history/", status: "skipped", detail: "source directory not found" };
|
|
28462
28554
|
}
|
|
28463
28555
|
try {
|
|
28464
|
-
const files =
|
|
28556
|
+
const files = fs46.readdirSync(src).filter((f) => f.endsWith(".jsonl"));
|
|
28465
28557
|
if (files.length === 0) {
|
|
28466
28558
|
return { name: "tasks/history/", status: "skipped", detail: "no *.jsonl files found in source directory" };
|
|
28467
28559
|
}
|
|
@@ -28476,8 +28568,8 @@ function migrateTaskHistory(ctx) {
|
|
|
28476
28568
|
let copied = 0;
|
|
28477
28569
|
let failed = 0;
|
|
28478
28570
|
for (const file of files) {
|
|
28479
|
-
const srcFile =
|
|
28480
|
-
const destFile =
|
|
28571
|
+
const srcFile = path52.join(src, file);
|
|
28572
|
+
const destFile = path52.join(dest, file);
|
|
28481
28573
|
try {
|
|
28482
28574
|
if (copyAndVerify(srcFile, destFile)) {
|
|
28483
28575
|
copied++;
|
|
@@ -28506,12 +28598,12 @@ function migrateTaskHistory(ctx) {
|
|
|
28506
28598
|
}
|
|
28507
28599
|
}
|
|
28508
28600
|
function migrateLockfile(ctx) {
|
|
28509
|
-
const src =
|
|
28510
|
-
const dest =
|
|
28511
|
-
if (!
|
|
28601
|
+
const src = path52.join(ctx.paths.configDir, "akm.lock");
|
|
28602
|
+
const dest = path52.join(ctx.paths.dataDir, "akm.lock");
|
|
28603
|
+
if (!fs46.existsSync(src)) {
|
|
28512
28604
|
return { name: "akm.lock", status: "skipped", detail: "source not found" };
|
|
28513
28605
|
}
|
|
28514
|
-
if (
|
|
28606
|
+
if (fs46.existsSync(dest)) {
|
|
28515
28607
|
return { name: "akm.lock", status: "skipped", detail: "destination already exists" };
|
|
28516
28608
|
}
|
|
28517
28609
|
if (ctx.dryRun) {
|
|
@@ -28531,12 +28623,12 @@ function migrateLockfile(ctx) {
|
|
|
28531
28623
|
return { name: "akm.lock", status: "failed", detail: `size mismatch after copy: ${src} \u2192 ${dest}` };
|
|
28532
28624
|
}
|
|
28533
28625
|
function migrateConfigBackups(ctx) {
|
|
28534
|
-
const src =
|
|
28535
|
-
const dest =
|
|
28536
|
-
if (!
|
|
28626
|
+
const src = path52.join(ctx.paths.cacheDir, "config-backups");
|
|
28627
|
+
const dest = path52.join(ctx.paths.dataDir, "config-backups");
|
|
28628
|
+
if (!fs46.existsSync(src)) {
|
|
28537
28629
|
return { name: "config-backups/", status: "skipped", detail: "source directory not found" };
|
|
28538
28630
|
}
|
|
28539
|
-
if (
|
|
28631
|
+
if (fs46.existsSync(dest)) {
|
|
28540
28632
|
return { name: "config-backups/", status: "skipped", detail: "destination already exists" };
|
|
28541
28633
|
}
|
|
28542
28634
|
if (ctx.dryRun) {
|
|
@@ -28553,7 +28645,7 @@ function migrateConfigBackups(ctx) {
|
|
|
28553
28645
|
try {
|
|
28554
28646
|
const srcCount = countFilesRecursive(src);
|
|
28555
28647
|
const { copied, failed } = copyTree(src, dest, { clobber: true });
|
|
28556
|
-
const destCount =
|
|
28648
|
+
const destCount = fs46.existsSync(dest) ? countFilesRecursive(dest) : 0;
|
|
28557
28649
|
if (failed === 0 && destCount === srcCount) {
|
|
28558
28650
|
return {
|
|
28559
28651
|
name: "config-backups/",
|
|
@@ -28572,11 +28664,11 @@ function migrateConfigBackups(ctx) {
|
|
|
28572
28664
|
}
|
|
28573
28665
|
}
|
|
28574
28666
|
async function migrateTaskHistoryToDb(ctx) {
|
|
28575
|
-
const src =
|
|
28576
|
-
if (!
|
|
28667
|
+
const src = path52.join(ctx.paths.cacheDir, "tasks", "history");
|
|
28668
|
+
if (!fs46.existsSync(src)) {
|
|
28577
28669
|
return { name: "tasks/history/ \u2192 state.db", status: "skipped", detail: "source directory not found" };
|
|
28578
28670
|
}
|
|
28579
|
-
const files =
|
|
28671
|
+
const files = fs46.readdirSync(src).filter((f) => f.endsWith(".jsonl"));
|
|
28580
28672
|
if (files.length === 0) {
|
|
28581
28673
|
return {
|
|
28582
28674
|
name: "tasks/history/ \u2192 state.db",
|
|
@@ -28600,8 +28692,8 @@ async function migrateTaskHistoryToDb(ctx) {
|
|
|
28600
28692
|
let failed = 0;
|
|
28601
28693
|
try {
|
|
28602
28694
|
for (const file of files) {
|
|
28603
|
-
const filePath =
|
|
28604
|
-
const text2 =
|
|
28695
|
+
const filePath = path52.join(src, file);
|
|
28696
|
+
const text2 = fs46.readFileSync(filePath, "utf8");
|
|
28605
28697
|
const lines = text2.split(`
|
|
28606
28698
|
`).filter((l) => l.trim().length > 0);
|
|
28607
28699
|
db.exec("BEGIN");
|
|
@@ -28660,15 +28752,15 @@ async function migrateTaskHistoryToDb(ctx) {
|
|
|
28660
28752
|
}
|
|
28661
28753
|
}
|
|
28662
28754
|
function noteRegistryIndexCache(ctx) {
|
|
28663
|
-
const src =
|
|
28664
|
-
if (!
|
|
28755
|
+
const src = path52.join(ctx.paths.cacheDir, "registry-index");
|
|
28756
|
+
if (!fs46.existsSync(src)) {
|
|
28665
28757
|
return {
|
|
28666
28758
|
name: "registry-index/ (note)",
|
|
28667
28759
|
status: "skipped",
|
|
28668
28760
|
detail: "no old $CACHE/registry-index/ directory found"
|
|
28669
28761
|
};
|
|
28670
28762
|
}
|
|
28671
|
-
const legacyFiles =
|
|
28763
|
+
const legacyFiles = fs46.readdirSync(src).filter((f) => f.endsWith(".json") && !f.startsWith("website-"));
|
|
28672
28764
|
if (legacyFiles.length === 0) {
|
|
28673
28765
|
return { name: "registry-index/ (note)", status: "skipped", detail: "no old *.json cache files found" };
|
|
28674
28766
|
}
|
|
@@ -28678,7 +28770,7 @@ function noteRegistryIndexCache(ctx) {
|
|
|
28678
28770
|
These are ignored in v0.9 \u2014 data is now stored in the registry_index_cache` + `
|
|
28679
28771
|
table in $DATA/index.db and will be rebuilt on next 'akm search --from registry'.
|
|
28680
28772
|
You may safely delete these files after migration:
|
|
28681
|
-
` + legacyFiles.map((f) => ` ${
|
|
28773
|
+
` + legacyFiles.map((f) => ` ${path52.join(src, f)}`).join(`
|
|
28682
28774
|
`));
|
|
28683
28775
|
}
|
|
28684
28776
|
return {
|
|
@@ -28689,20 +28781,20 @@ function noteRegistryIndexCache(ctx) {
|
|
|
28689
28781
|
}
|
|
28690
28782
|
function legacyGraphCandidatePaths(ctx) {
|
|
28691
28783
|
return [
|
|
28692
|
-
|
|
28693
|
-
|
|
28694
|
-
|
|
28784
|
+
path52.join(ctx.paths.cacheDir, "graph-snapshot.json"),
|
|
28785
|
+
path52.join(ctx.paths.dataDir, "graph-snapshot.json"),
|
|
28786
|
+
path52.join(ctx.paths.dataDir, "graph-export.json")
|
|
28695
28787
|
];
|
|
28696
28788
|
}
|
|
28697
28789
|
function findLegacyGraphFile(ctx) {
|
|
28698
28790
|
for (const candidate of legacyGraphCandidatePaths(ctx)) {
|
|
28699
|
-
if (
|
|
28791
|
+
if (fs46.existsSync(candidate) && fs46.statSync(candidate).isFile())
|
|
28700
28792
|
return candidate;
|
|
28701
28793
|
}
|
|
28702
|
-
const graphDir =
|
|
28703
|
-
if (
|
|
28794
|
+
const graphDir = path52.join(ctx.paths.cacheDir, "graph");
|
|
28795
|
+
if (fs46.existsSync(graphDir) && fs46.statSync(graphDir).isDirectory()) {
|
|
28704
28796
|
try {
|
|
28705
|
-
const json =
|
|
28797
|
+
const json = fs46.readdirSync(graphDir).filter((f) => f.endsWith(".json")).map((f) => path52.join(graphDir, f));
|
|
28706
28798
|
const [first] = json;
|
|
28707
28799
|
if (first)
|
|
28708
28800
|
return first;
|
|
@@ -28739,7 +28831,7 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
28739
28831
|
if (!legacyFile) {
|
|
28740
28832
|
return { name, status: "skipped", detail: "no legacy graph file found" };
|
|
28741
28833
|
}
|
|
28742
|
-
if (!
|
|
28834
|
+
if (!fs46.existsSync(ctx.paths.indexDbPath)) {
|
|
28743
28835
|
return {
|
|
28744
28836
|
name,
|
|
28745
28837
|
status: "skipped",
|
|
@@ -28754,7 +28846,7 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
28754
28846
|
};
|
|
28755
28847
|
}
|
|
28756
28848
|
try {
|
|
28757
|
-
const raw =
|
|
28849
|
+
const raw = fs46.readFileSync(legacyFile, "utf8");
|
|
28758
28850
|
let parsed;
|
|
28759
28851
|
try {
|
|
28760
28852
|
parsed = JSON.parse(raw);
|
|
@@ -28832,7 +28924,7 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
28832
28924
|
}
|
|
28833
28925
|
const renamed = `${legacyFile}.migrated`;
|
|
28834
28926
|
try {
|
|
28835
|
-
|
|
28927
|
+
fs46.renameSync(legacyFile, renamed);
|
|
28836
28928
|
} catch (err) {
|
|
28837
28929
|
const msg = err instanceof Error ? err.message : String(err);
|
|
28838
28930
|
return {
|
|
@@ -28856,9 +28948,9 @@ async function migrateGraphFileToDb(ctx) {
|
|
|
28856
28948
|
}
|
|
28857
28949
|
function resolvePrimaryStashDir(configDirPath) {
|
|
28858
28950
|
try {
|
|
28859
|
-
const cfgPath =
|
|
28860
|
-
if (
|
|
28861
|
-
const cfg = JSON.parse(
|
|
28951
|
+
const cfgPath = path52.join(configDirPath, "config.json");
|
|
28952
|
+
if (fs46.existsSync(cfgPath)) {
|
|
28953
|
+
const cfg = JSON.parse(fs46.readFileSync(cfgPath, "utf8"));
|
|
28862
28954
|
if (typeof cfg.stashDir === "string" && cfg.stashDir.length > 0)
|
|
28863
28955
|
return cfg.stashDir;
|
|
28864
28956
|
}
|
|
@@ -28867,8 +28959,8 @@ function resolvePrimaryStashDir(configDirPath) {
|
|
|
28867
28959
|
}
|
|
28868
28960
|
function countEnvFilesRecursive(dir) {
|
|
28869
28961
|
let count = 0;
|
|
28870
|
-
for (const entry of
|
|
28871
|
-
const full =
|
|
28962
|
+
for (const entry of fs46.readdirSync(dir, { withFileTypes: true })) {
|
|
28963
|
+
const full = path52.join(dir, entry.name);
|
|
28872
28964
|
if (entry.isDirectory()) {
|
|
28873
28965
|
count += countEnvFilesRecursive(full);
|
|
28874
28966
|
} else if (entry.name === ".env" || entry.name.endsWith(".env")) {
|
|
@@ -28880,13 +28972,13 @@ function countEnvFilesRecursive(dir) {
|
|
|
28880
28972
|
function chmodTreeSecure(dir) {
|
|
28881
28973
|
const isWin = process.platform === "win32";
|
|
28882
28974
|
try {
|
|
28883
|
-
|
|
28975
|
+
fs46.chmodSync(dir, 448);
|
|
28884
28976
|
} catch (err) {
|
|
28885
28977
|
if (!isWin)
|
|
28886
28978
|
return { ok: false, detail: `chmod 0700 ${dir} failed: ${err instanceof Error ? err.message : err}` };
|
|
28887
28979
|
}
|
|
28888
|
-
for (const entry of
|
|
28889
|
-
const full =
|
|
28980
|
+
for (const entry of fs46.readdirSync(dir, { withFileTypes: true })) {
|
|
28981
|
+
const full = path52.join(dir, entry.name);
|
|
28890
28982
|
if (entry.isDirectory()) {
|
|
28891
28983
|
const sub = chmodTreeSecure(full);
|
|
28892
28984
|
if (!sub.ok)
|
|
@@ -28894,8 +28986,8 @@ function chmodTreeSecure(dir) {
|
|
|
28894
28986
|
continue;
|
|
28895
28987
|
}
|
|
28896
28988
|
try {
|
|
28897
|
-
|
|
28898
|
-
if (!isWin && (
|
|
28989
|
+
fs46.chmodSync(full, 384);
|
|
28990
|
+
if (!isWin && (fs46.statSync(full).mode & 511) !== 384) {
|
|
28899
28991
|
return { ok: false, detail: `mode verification failed for ${full}` };
|
|
28900
28992
|
}
|
|
28901
28993
|
} catch (err) {
|
|
@@ -28908,13 +29000,13 @@ function chmodTreeSecure(dir) {
|
|
|
28908
29000
|
async function migrateVaultsToEnv(ctx) {
|
|
28909
29001
|
const name = "vaults/ \u2192 env/";
|
|
28910
29002
|
const stashDir = resolvePrimaryStashDir(ctx.paths.configDir);
|
|
28911
|
-
const vaultsDir =
|
|
28912
|
-
const envDir =
|
|
28913
|
-
const marker =
|
|
28914
|
-
if (!
|
|
29003
|
+
const vaultsDir = path52.join(stashDir, "vaults");
|
|
29004
|
+
const envDir = path52.join(stashDir, "env");
|
|
29005
|
+
const marker = path52.join(vaultsDir, MIGRATED_MARKER);
|
|
29006
|
+
if (!fs46.existsSync(vaultsDir)) {
|
|
28915
29007
|
return { name, status: "skipped", detail: `no vaults/ directory under ${stashDir}` };
|
|
28916
29008
|
}
|
|
28917
|
-
if (
|
|
29009
|
+
if (fs46.existsSync(marker)) {
|
|
28918
29010
|
return { name, status: "skipped", detail: "already migrated (.migrated marker present)" };
|
|
28919
29011
|
}
|
|
28920
29012
|
const vaultEnvCount = countEnvFilesRecursive(vaultsDir);
|
|
@@ -28945,7 +29037,7 @@ async function migrateVaultsToEnv(ctx) {
|
|
|
28945
29037
|
detail: `post-copy count ${envEnvCount} < source ${vaultEnvCount}; no marker written`
|
|
28946
29038
|
};
|
|
28947
29039
|
}
|
|
28948
|
-
|
|
29040
|
+
fs46.writeFileSync(marker, `migrated vaults/ -> env/ at ${new Date().toISOString()}
|
|
28949
29041
|
`, { mode: 384 });
|
|
28950
29042
|
return {
|
|
28951
29043
|
name,
|
|
@@ -29039,12 +29131,12 @@ task_history: task_id PK).
|
|
|
29039
29131
|
Migration complete. No errors.`);
|
|
29040
29132
|
console.log(`
|
|
29041
29133
|
Old files at the original locations are safe to delete manually after verifying akm works:
|
|
29042
|
-
${
|
|
29043
|
-
${
|
|
29044
|
-
${
|
|
29045
|
-
${
|
|
29046
|
-
${
|
|
29047
|
-
${
|
|
29134
|
+
${path52.join(cacheDir, "index.db")}
|
|
29135
|
+
${path52.join(cacheDir, "workflow.db")}
|
|
29136
|
+
${path52.join(cacheDir, "events.jsonl")}
|
|
29137
|
+
${path52.join(cacheDir, "tasks", "history")}
|
|
29138
|
+
${path52.join(cacheDir, "config-backups")}
|
|
29139
|
+
${path52.join(configDir, "akm.lock")}
|
|
29048
29140
|
|
|
29049
29141
|
Next step \u2014 repopulate graph data (if migrating from 0.7):
|
|
29050
29142
|
The 0.8.0 graph schema redesign (DB_VERSION 12 \u2192 13) rebuilds the graph
|
|
@@ -29138,12 +29230,12 @@ async function main(args = process.argv.slice(2)) {
|
|
|
29138
29230
|
var MIGRATED_MARKER = ".migrated", dataDir, stateDir, cacheDir, configDir, stateDbPath, indexDbPath, PATHS, versionReports, v07To08Migration, v08To09Migration, MIGRATIONS;
|
|
29139
29231
|
var init_migrate_storage = __esm(() => {
|
|
29140
29232
|
init_paths();
|
|
29141
|
-
dataDir = process.env.AKM_DATA_DIR?.trim() ?? (process.env.XDG_DATA_HOME?.trim() ?
|
|
29142
|
-
stateDir = process.env.AKM_STATE_DIR?.trim() ?? (process.env.XDG_STATE_HOME?.trim() ?
|
|
29233
|
+
dataDir = process.env.AKM_DATA_DIR?.trim() ?? (process.env.XDG_DATA_HOME?.trim() ? path52.join(process.env.XDG_DATA_HOME.trim(), "akm") : path52.join(os7.homedir(), ".local", "share", "akm"));
|
|
29234
|
+
stateDir = process.env.AKM_STATE_DIR?.trim() ?? (process.env.XDG_STATE_HOME?.trim() ? path52.join(process.env.XDG_STATE_HOME.trim(), "akm") : path52.join(os7.homedir(), ".local", "state", "akm"));
|
|
29143
29235
|
cacheDir = getCacheDir();
|
|
29144
29236
|
configDir = getConfigDir();
|
|
29145
|
-
stateDbPath =
|
|
29146
|
-
indexDbPath =
|
|
29237
|
+
stateDbPath = path52.join(dataDir, "state.db");
|
|
29238
|
+
indexDbPath = path52.join(dataDir, "index.db");
|
|
29147
29239
|
PATHS = {
|
|
29148
29240
|
cacheDir,
|
|
29149
29241
|
configDir,
|
|
@@ -29158,15 +29250,15 @@ var init_migrate_storage = __esm(() => {
|
|
|
29158
29250
|
sourceVersion: "0.7",
|
|
29159
29251
|
isNeeded: (paths) => {
|
|
29160
29252
|
const candidates = [
|
|
29161
|
-
|
|
29162
|
-
|
|
29163
|
-
|
|
29164
|
-
|
|
29165
|
-
|
|
29166
|
-
|
|
29167
|
-
|
|
29253
|
+
path52.join(paths.cacheDir, "index.db"),
|
|
29254
|
+
path52.join(paths.cacheDir, "workflow.db"),
|
|
29255
|
+
path52.join(paths.cacheDir, "events.jsonl"),
|
|
29256
|
+
path52.join(paths.cacheDir, "tasks", "history"),
|
|
29257
|
+
path52.join(paths.configDir, "akm.lock"),
|
|
29258
|
+
path52.join(paths.cacheDir, "config-backups"),
|
|
29259
|
+
path52.join(paths.cacheDir, "registry-index")
|
|
29168
29260
|
];
|
|
29169
|
-
return candidates.some((p) =>
|
|
29261
|
+
return candidates.some((p) => fs46.existsSync(p));
|
|
29170
29262
|
},
|
|
29171
29263
|
steps: [
|
|
29172
29264
|
{ id: "index-db", title: "index.db", run: (ctx) => migrateDb(ctx, "index.db") },
|
|
@@ -30641,9 +30733,12 @@ function glyphFor(fixed) {
|
|
|
30641
30733
|
return { glyph: "\u2713", severityRank: 2 };
|
|
30642
30734
|
return { glyph: "\u26A0", severityRank: 1 };
|
|
30643
30735
|
}
|
|
30736
|
+
function locationOf(issue) {
|
|
30737
|
+
return typeof issue.line === "number" ? `${issue.file}:${issue.line}` : issue.file;
|
|
30738
|
+
}
|
|
30644
30739
|
function issueEntry(issue) {
|
|
30645
30740
|
const { glyph, severityRank } = glyphFor(issue.fixed);
|
|
30646
|
-
return { severityRank, glyph, headline: `${issue
|
|
30741
|
+
return { severityRank, glyph, headline: `${locationOf(issue)} [${issue.issue}] ${issue.detail}` };
|
|
30647
30742
|
}
|
|
30648
30743
|
function renderIssueSection(title, issues) {
|
|
30649
30744
|
if (issues.length === 0)
|
|
@@ -30655,12 +30750,14 @@ function formatLintPlain(r) {
|
|
|
30655
30750
|
return null;
|
|
30656
30751
|
const fixed = Array.isArray(r.fixed) ? r.fixed : [];
|
|
30657
30752
|
const flagged = Array.isArray(r.flagged) ? r.flagged : [];
|
|
30753
|
+
const warnings = Array.isArray(r.warnings) ? r.warnings : [];
|
|
30658
30754
|
const summary = r.summary;
|
|
30659
30755
|
const lines = [];
|
|
30660
30756
|
if (typeof r.ok === "boolean")
|
|
30661
30757
|
lines.push(`ok: ${r.ok}`);
|
|
30662
|
-
lines.push(`summary: fixed=${summary?.fixed ?? fixed.length} flagged=${summary?.flagged ?? flagged.length}`);
|
|
30758
|
+
lines.push(`summary: fixed=${summary?.fixed ?? fixed.length} flagged=${summary?.flagged ?? flagged.length}` + ` warnings=${summary?.warnings ?? warnings.length}`);
|
|
30663
30759
|
lines.push("", ...renderIssueSection("flagged", flagged));
|
|
30760
|
+
lines.push("", ...renderIssueSection("warnings", warnings));
|
|
30664
30761
|
lines.push("", ...renderIssueSection("fixed", fixed));
|
|
30665
30762
|
return lines.join(`
|
|
30666
30763
|
`).trim();
|
|
@@ -31758,10 +31855,10 @@ init_errors();
|
|
|
31758
31855
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
31759
31856
|
import fs43 from "fs";
|
|
31760
31857
|
import os6 from "os";
|
|
31761
|
-
import
|
|
31858
|
+
import path49 from "path";
|
|
31762
31859
|
|
|
31763
31860
|
// src/core/adapter/adapters/akm-lint.ts
|
|
31764
|
-
import
|
|
31861
|
+
import path8 from "path";
|
|
31765
31862
|
|
|
31766
31863
|
// src/commands/env/env.ts
|
|
31767
31864
|
import fs3 from "fs";
|
|
@@ -31854,8 +31951,48 @@ function isDangerousEnvKey(key) {
|
|
|
31854
31951
|
return false;
|
|
31855
31952
|
}
|
|
31856
31953
|
|
|
31954
|
+
// src/workflows/resource-limits.ts
|
|
31955
|
+
var WORKFLOW_MAX_PLAN_BYTES = 2 * 1024 * 1024;
|
|
31956
|
+
var WORKFLOW_MAX_SOURCE_BYTES = 1024 * 1024;
|
|
31957
|
+
var WORKFLOW_MAX_STEPS = 256;
|
|
31958
|
+
var WORKFLOW_MAX_PARAMS = 128;
|
|
31959
|
+
var WORKFLOW_MAX_ROUTE_BRANCHES = 256;
|
|
31960
|
+
var WORKFLOW_MAX_INSTRUCTION_BYTES = 256 * 1024;
|
|
31961
|
+
var WORKFLOW_MAX_SCHEMA_BYTES = 256 * 1024;
|
|
31962
|
+
var WORKFLOW_MAX_EXTRA_PARAMS_BYTES = 64 * 1024;
|
|
31963
|
+
var WORKFLOW_MAX_MAP_EXPANSION = 1e4;
|
|
31964
|
+
var WORKFLOW_MAX_INPUTS = 64;
|
|
31965
|
+
var WORKFLOW_MAX_CONCURRENCY = 64;
|
|
31966
|
+
var WORKFLOW_MAX_GATE_LOOPS = 100;
|
|
31967
|
+
var WORKFLOW_MAX_RETRIES = 100;
|
|
31968
|
+
var WORKFLOW_MAX_TIMEOUT_MS = 2 ** 31 - 1;
|
|
31969
|
+
var WORKFLOW_ENGINE_NAME_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
|
|
31970
|
+
var WORKFLOW_MAX_ENGINE_NAME_LENGTH = 63;
|
|
31971
|
+
var WORKFLOW_MAX_EXEC_ARGV = 64;
|
|
31972
|
+
var WORKFLOW_MAX_EXEC_ARG_BYTES = 4096;
|
|
31973
|
+
var WORKFLOW_MAX_EXEC_CWD_LENGTH = 1024;
|
|
31974
|
+
var WORKFLOW_MAX_EXEC_PASS_ENV = 32;
|
|
31975
|
+
var WORKFLOW_ENV_VAR_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
31976
|
+
var WORKFLOW_MAX_EXEC_OUTPUT_BYTES = 8 * 1024 * 1024;
|
|
31977
|
+
var EXEC_CONTEXT_LIMITS_POSIX = {
|
|
31978
|
+
perVarBytes: 96 * 1024,
|
|
31979
|
+
totalBytes: 128 * 1024,
|
|
31980
|
+
source: "Linux caps one argv/environ string at MAX_ARG_STRLEN (32 pages = 131 072 bytes) and macOS caps argv+environ at ARG_MAX (256 KiB)"
|
|
31981
|
+
};
|
|
31982
|
+
var WORKFLOW_MAX_EVIDENCE_JSON_BYTES = 1024 * 1024;
|
|
31983
|
+
function utf8Bytes(value) {
|
|
31984
|
+
return Buffer.byteLength(value, "utf8");
|
|
31985
|
+
}
|
|
31986
|
+
function jsonBytes(value) {
|
|
31987
|
+
return utf8Bytes(JSON.stringify(value));
|
|
31988
|
+
}
|
|
31989
|
+
|
|
31857
31990
|
// src/tasks/schema.ts
|
|
31858
31991
|
var TASK_SCHEMA_VERSION = 2;
|
|
31992
|
+
var TASK_EXTENSION = ".yml";
|
|
31993
|
+
var TASK_NEAR_MISS_EXTENSION = ".yaml";
|
|
31994
|
+
var TASK_MAX_TIMEOUT_MS = WORKFLOW_MAX_TIMEOUT_MS;
|
|
31995
|
+
var TASK_MAX_REDACT_NAMES = WORKFLOW_MAX_EXEC_PASS_ENV;
|
|
31859
31996
|
function taskFieldProblems(data) {
|
|
31860
31997
|
const problems = [];
|
|
31861
31998
|
if (data.version !== TASK_SCHEMA_VERSION)
|
|
@@ -31866,6 +32003,25 @@ function taskFieldProblems(data) {
|
|
|
31866
32003
|
problems.push("enabled (must be a boolean when present)");
|
|
31867
32004
|
return problems;
|
|
31868
32005
|
}
|
|
32006
|
+
function parseTaskYaml(raw) {
|
|
32007
|
+
try {
|
|
32008
|
+
const doc = $parse(raw);
|
|
32009
|
+
if (doc && typeof doc === "object" && !Array.isArray(doc))
|
|
32010
|
+
return { ok: true, data: doc };
|
|
32011
|
+
return { ok: true, data: {} };
|
|
32012
|
+
} catch (e) {
|
|
32013
|
+
const message = (e instanceof Error ? e.message : String(e)).split(`
|
|
32014
|
+
`)[0]?.trim() ?? "unknown parse error";
|
|
32015
|
+
return { ok: false, data: {}, error: message };
|
|
32016
|
+
}
|
|
32017
|
+
}
|
|
32018
|
+
function taskYamlParseDetail(error) {
|
|
32019
|
+
return `task YAML does not parse: ${error}`;
|
|
32020
|
+
}
|
|
32021
|
+
function taskExtensionDetail(relPath) {
|
|
32022
|
+
const base = relPath.replace(/\.yaml$/i, "");
|
|
32023
|
+
return `task file uses the ${TASK_NEAR_MISS_EXTENSION} extension; akm recognizes tasks only as ` + `${TASK_EXTENSION}, so this file is never indexed or scheduled \u2014 rename it to ${base}${TASK_EXTENSION}.`;
|
|
32024
|
+
}
|
|
31869
32025
|
|
|
31870
32026
|
// src/workflows/program/expressions.ts
|
|
31871
32027
|
var GRAMMAR_HINT = "allowed forms: params.<name>, steps.<id>.output(.<ident>|[<int>])*";
|
|
@@ -31970,6 +32126,36 @@ function formatReference(expr) {
|
|
|
31970
32126
|
}
|
|
31971
32127
|
}
|
|
31972
32128
|
|
|
32129
|
+
// src/workflows/program/schema.ts
|
|
32130
|
+
var PROGRAM_REDUCERS = ["collect", "vote"];
|
|
32131
|
+
var PROGRAM_ON_ERROR = ["fail", "continue"];
|
|
32132
|
+
var PROGRAM_ISOLATION_KINDS = ["none", "worktree"];
|
|
32133
|
+
var RETRY_REASON_SET = {
|
|
32134
|
+
timeout: true,
|
|
32135
|
+
spawn_failed: true,
|
|
32136
|
+
non_zero_exit: true,
|
|
32137
|
+
parse_error: true,
|
|
32138
|
+
cooldown: true,
|
|
32139
|
+
llm_rate_limit: true,
|
|
32140
|
+
llm_content_filter: true,
|
|
32141
|
+
llm_invalid_json: true,
|
|
32142
|
+
content_policy_reject: true,
|
|
32143
|
+
unsupported_type: true,
|
|
32144
|
+
no_change: true,
|
|
32145
|
+
aborted: true
|
|
32146
|
+
};
|
|
32147
|
+
var PROGRAM_RETRY_REASONS = Object.keys(RETRY_REASON_SET);
|
|
32148
|
+
var PROGRAM_STEP_ID_PATTERN = /^[A-Za-z_][A-Za-z0-9_-]*$/;
|
|
32149
|
+
var PROGRAM_PARAM_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
32150
|
+
function projectExecCore(exec) {
|
|
32151
|
+
return {
|
|
32152
|
+
command: [...exec.command],
|
|
32153
|
+
...exec.cwd ? { cwd: exec.cwd } : {},
|
|
32154
|
+
...exec.passEnv && exec.passEnv.length > 0 ? { passEnv: [...exec.passEnv] } : {},
|
|
32155
|
+
...exec.inheritEnv ? { inheritEnv: true } : {}
|
|
32156
|
+
};
|
|
32157
|
+
}
|
|
32158
|
+
|
|
31973
32159
|
// src/workflows/ir/compile.ts
|
|
31974
32160
|
function compileWorkflowPlan(document, title) {
|
|
31975
32161
|
const errors2 = [];
|
|
@@ -32069,6 +32255,7 @@ function compileUnit(unit, id, instructions, defaults, inputs, source) {
|
|
|
32069
32255
|
instructions,
|
|
32070
32256
|
templating: "verbatim",
|
|
32071
32257
|
...inputs && inputs.length > 0 ? { inputs: [...inputs] } : {},
|
|
32258
|
+
...unit?.exec ? { exec: projectExecCore(unit.exec) } : {},
|
|
32072
32259
|
...unit?.output !== undefined ? { schema: unit.output } : {},
|
|
32073
32260
|
...unit?.retry ? { retry: { max: unit.retry.max, on: [...unit.retry.on] } } : {},
|
|
32074
32261
|
onError: unit?.onError ?? defaults?.onError ?? "fail",
|
|
@@ -32116,6 +32303,14 @@ function collectWorkflowWarnings(document) {
|
|
|
32116
32303
|
const warnings = [];
|
|
32117
32304
|
const declaredParams = document.params ? new Set(Object.keys(document.params)) : undefined;
|
|
32118
32305
|
for (const step of document.steps) {
|
|
32306
|
+
const maxLoops = step.gate?.maxLoops ?? 1;
|
|
32307
|
+
const execUnit = step.map ? step.map.unit?.exec : step.unit?.exec;
|
|
32308
|
+
if (maxLoops > 1 && execUnit && step.gateRubric?.text.trim()) {
|
|
32309
|
+
warnings.push({
|
|
32310
|
+
line: step.source.start,
|
|
32311
|
+
message: `Step "${step.id}" declares \`gate.max_loops: ${maxLoops}\` on an \`exec\` step \u2014 it runs its command ` + `ONCE. A gate loop re-executes the step so it can address the judge's feedback, and a frozen argv cannot ` + `read that feedback; looping would only repeat the command's side effects. The gate still evaluates and ` + `can still fail the step.`
|
|
32312
|
+
});
|
|
32313
|
+
}
|
|
32119
32314
|
if ((step.map || step.route === undefined) && step.output === undefined) {
|
|
32120
32315
|
warnings.push({
|
|
32121
32316
|
line: step.source.start,
|
|
@@ -32147,6 +32342,22 @@ function collectWorkflowWarnings(document) {
|
|
|
32147
32342
|
// src/core/asset/frontmatter.ts
|
|
32148
32343
|
import fs4 from "fs";
|
|
32149
32344
|
|
|
32345
|
+
// src/core/write-provenance.ts
|
|
32346
|
+
import path7 from "path";
|
|
32347
|
+
var activeJournals = new Set;
|
|
32348
|
+
function recordWrittenPath(filePath) {
|
|
32349
|
+
if (activeJournals.size === 0 || !filePath)
|
|
32350
|
+
return;
|
|
32351
|
+
let absolute;
|
|
32352
|
+
try {
|
|
32353
|
+
absolute = path7.resolve(filePath);
|
|
32354
|
+
} catch {
|
|
32355
|
+
return;
|
|
32356
|
+
}
|
|
32357
|
+
for (const journal of activeJournals)
|
|
32358
|
+
journal.touched.add(absolute);
|
|
32359
|
+
}
|
|
32360
|
+
|
|
32150
32361
|
// src/core/asset/asset-serialize.ts
|
|
32151
32362
|
function serializeFrontmatter(frontmatter) {
|
|
32152
32363
|
return $stringify(frontmatter).trimEnd();
|
|
@@ -32249,6 +32460,7 @@ ${serializeFrontmatter(nextFrontmatter)}
|
|
|
32249
32460
|
---
|
|
32250
32461
|
${parsed.content}` : assembleAsset(nextFrontmatter, parsed.content);
|
|
32251
32462
|
fs4.writeFileSync(filePath, next, "utf8");
|
|
32463
|
+
recordWrittenPath(filePath);
|
|
32252
32464
|
return true;
|
|
32253
32465
|
}
|
|
32254
32466
|
function parseFrontmatterBlock(raw) {
|
|
@@ -32300,6 +32512,9 @@ function parseMarkdownToc(content) {
|
|
|
32300
32512
|
return { headings, totalLines: lines.length };
|
|
32301
32513
|
}
|
|
32302
32514
|
|
|
32515
|
+
// src/workflows/parser.ts
|
|
32516
|
+
init_common();
|
|
32517
|
+
|
|
32303
32518
|
// src/core/extra-params.ts
|
|
32304
32519
|
var EXTRA_PARAMS_PROTECTED_TOP_LEVEL_KEYS = [
|
|
32305
32520
|
"model",
|
|
@@ -32332,10 +32547,10 @@ function validateExtraParams(value) {
|
|
|
32332
32547
|
return [{ path: [], message: "must be an object" }];
|
|
32333
32548
|
}
|
|
32334
32549
|
const issues = [];
|
|
32335
|
-
const visit2 = (entry,
|
|
32550
|
+
const visit2 = (entry, path8) => {
|
|
32336
32551
|
if (Array.isArray(entry)) {
|
|
32337
32552
|
entry.forEach((child, index) => {
|
|
32338
|
-
visit2(child, [...
|
|
32553
|
+
visit2(child, [...path8, index]);
|
|
32339
32554
|
});
|
|
32340
32555
|
return;
|
|
32341
32556
|
}
|
|
@@ -32343,13 +32558,13 @@ function validateExtraParams(value) {
|
|
|
32343
32558
|
return;
|
|
32344
32559
|
for (const [key, child] of Object.entries(entry)) {
|
|
32345
32560
|
const normalized = normalizeExtraParamKey(key);
|
|
32346
|
-
if (
|
|
32561
|
+
if (path8.length === 0 && PROTECTED_TOP_LEVEL_KEYS.has(normalized)) {
|
|
32347
32562
|
issues.push({ path: [key], message: `${key} is protected by AKM` });
|
|
32348
32563
|
}
|
|
32349
32564
|
if (CREDENTIAL_KEYS.has(normalized)) {
|
|
32350
|
-
issues.push({ path: [...
|
|
32565
|
+
issues.push({ path: [...path8, key], message: `${key} cannot carry credentials` });
|
|
32351
32566
|
}
|
|
32352
|
-
visit2(child, [...
|
|
32567
|
+
visit2(child, [...path8, key]);
|
|
32353
32568
|
}
|
|
32354
32569
|
};
|
|
32355
32570
|
visit2(value, []);
|
|
@@ -32360,44 +32575,179 @@ function formatExtraParamsIssue(label, issue) {
|
|
|
32360
32575
|
return `${label}${suffix} ${issue.message}`;
|
|
32361
32576
|
}
|
|
32362
32577
|
|
|
32363
|
-
// src/
|
|
32364
|
-
var
|
|
32365
|
-
var
|
|
32366
|
-
var
|
|
32367
|
-
var
|
|
32368
|
-
|
|
32369
|
-
|
|
32370
|
-
|
|
32371
|
-
|
|
32372
|
-
|
|
32373
|
-
|
|
32374
|
-
|
|
32375
|
-
|
|
32376
|
-
|
|
32377
|
-
|
|
32378
|
-
|
|
32379
|
-
|
|
32380
|
-
|
|
32381
|
-
|
|
32382
|
-
|
|
32383
|
-
|
|
32384
|
-
|
|
32385
|
-
|
|
32386
|
-
|
|
32387
|
-
|
|
32388
|
-
|
|
32389
|
-
|
|
32390
|
-
|
|
32391
|
-
|
|
32392
|
-
|
|
32393
|
-
|
|
32394
|
-
|
|
32395
|
-
|
|
32396
|
-
|
|
32397
|
-
|
|
32578
|
+
// src/core/json-schema.ts
|
|
32579
|
+
var MAX_DEFINITION_DEPTH = 64;
|
|
32580
|
+
var JSON_SCHEMA_SUBSET_SUPPORTED_KEYWORDS = "type, enum, properties, required, items, additionalProperties: false, minItems, maxItems, " + "minLength, maxLength, minimum, maximum, allOf, anyOf, oneOf, not";
|
|
32581
|
+
var KNOWN_TYPE_NAMES = new Set(["string", "number", "integer", "boolean", "object", "array", "null"]);
|
|
32582
|
+
var UNSUPPORTED_KEYWORDS = new Set([
|
|
32583
|
+
"$ref",
|
|
32584
|
+
"$defs",
|
|
32585
|
+
"definitions",
|
|
32586
|
+
"$anchor",
|
|
32587
|
+
"$dynamicRef",
|
|
32588
|
+
"$dynamicAnchor",
|
|
32589
|
+
"if",
|
|
32590
|
+
"then",
|
|
32591
|
+
"else",
|
|
32592
|
+
"const",
|
|
32593
|
+
"pattern",
|
|
32594
|
+
"format",
|
|
32595
|
+
"patternProperties",
|
|
32596
|
+
"propertyNames",
|
|
32597
|
+
"additionalItems",
|
|
32598
|
+
"prefixItems",
|
|
32599
|
+
"contains",
|
|
32600
|
+
"minContains",
|
|
32601
|
+
"maxContains",
|
|
32602
|
+
"uniqueItems",
|
|
32603
|
+
"multipleOf",
|
|
32604
|
+
"exclusiveMinimum",
|
|
32605
|
+
"exclusiveMaximum",
|
|
32606
|
+
"minProperties",
|
|
32607
|
+
"maxProperties",
|
|
32608
|
+
"dependencies",
|
|
32609
|
+
"dependentRequired",
|
|
32610
|
+
"dependentSchemas",
|
|
32611
|
+
"unevaluatedItems",
|
|
32612
|
+
"unevaluatedProperties",
|
|
32613
|
+
"contentEncoding",
|
|
32614
|
+
"contentMediaType",
|
|
32615
|
+
"contentSchema"
|
|
32616
|
+
]);
|
|
32617
|
+
var UNSUPPORTED_KEYWORD_HINTS = new Map([
|
|
32618
|
+
["$ref", `inline the referenced schema (the subset resolves no references, so it cannot follow "$ref")`],
|
|
32619
|
+
["$defs", `inline the definitions at their use sites \u2014 "$ref" is not resolved, so "$defs" can never be reached`],
|
|
32620
|
+
[
|
|
32621
|
+
"definitions",
|
|
32622
|
+
`inline the definitions at their use sites \u2014 "$ref" is not resolved, so "definitions" can never be reached`
|
|
32623
|
+
],
|
|
32624
|
+
["const", `use a single-value "enum" (e.g. enum: [pass])`],
|
|
32625
|
+
[
|
|
32626
|
+
"pattern",
|
|
32627
|
+
`use "enum" when the allowed strings can be listed, or "minLength"/"maxLength" for a size bound \u2014 ` + `a regular-expression constraint is not expressible in the subset; check the shape in the step's gate rubric instead`
|
|
32628
|
+
],
|
|
32629
|
+
[
|
|
32630
|
+
"format",
|
|
32631
|
+
`"format" is annotation-only in JSON Schema 2020-12 and the subset enforces no string-shape keyword \u2014 ` + `use "enum" when the allowed values can be listed, otherwise check the shape in the step's gate rubric`
|
|
32632
|
+
],
|
|
32633
|
+
["patternProperties", `declare the properties explicitly under "properties", or drop the constraint`],
|
|
32634
|
+
["if", `use "anyOf"/"oneOf" to express the alternatives directly`],
|
|
32635
|
+
["then", `use "anyOf"/"oneOf" to express the alternatives directly`],
|
|
32636
|
+
["else", `use "anyOf"/"oneOf" to express the alternatives directly`],
|
|
32637
|
+
["uniqueItems", `drop the constraint, or validate uniqueness in the step's gate rubric`]
|
|
32638
|
+
]);
|
|
32639
|
+
function checkJsonSchemaDefinition(schema) {
|
|
32640
|
+
const issues = [];
|
|
32641
|
+
checkDefinitionNode(schema, [], issues, 0);
|
|
32642
|
+
return issues;
|
|
32398
32643
|
}
|
|
32399
|
-
function
|
|
32400
|
-
return
|
|
32644
|
+
function pointerFor(path8) {
|
|
32645
|
+
return path8.length === 0 ? "$" : `$.${path8.map(String).join(".")}`;
|
|
32646
|
+
}
|
|
32647
|
+
function pushIssue(issues, path8, keyword, kind, message) {
|
|
32648
|
+
issues.push({ path: [...path8], pointer: pointerFor(path8), keyword, kind, message });
|
|
32649
|
+
}
|
|
32650
|
+
function isPlainObject(value) {
|
|
32651
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
32652
|
+
}
|
|
32653
|
+
function checkDefinitionNode(schema, path8, issues, depth) {
|
|
32654
|
+
if (depth > MAX_DEFINITION_DEPTH) {
|
|
32655
|
+
pushIssue(issues, path8, "(depth)", "malformed", `schema nesting exceeds the depth limit of ${MAX_DEFINITION_DEPTH}`);
|
|
32656
|
+
return;
|
|
32657
|
+
}
|
|
32658
|
+
for (const keyword of Object.keys(schema)) {
|
|
32659
|
+
if (UNSUPPORTED_KEYWORDS.has(keyword)) {
|
|
32660
|
+
const hint = UNSUPPORTED_KEYWORD_HINTS.get(keyword);
|
|
32661
|
+
pushIssue(issues, [...path8, keyword], keyword, "unsupported", `keyword "${keyword}" is not enforced by the workflow schema subset \u2014 the schema would silently not ` + `constrain what it looks like it constrains${hint ? `; ${hint}` : ""}`);
|
|
32662
|
+
}
|
|
32663
|
+
}
|
|
32664
|
+
const declared = schema.type;
|
|
32665
|
+
if (declared !== undefined) {
|
|
32666
|
+
const names = Array.isArray(declared) ? declared : [declared];
|
|
32667
|
+
if (names.length === 0) {
|
|
32668
|
+
pushIssue(issues, [...path8, "type"], "type", "malformed", `"type" must name at least one type`);
|
|
32669
|
+
}
|
|
32670
|
+
for (const [index, name] of names.entries()) {
|
|
32671
|
+
const namePath = Array.isArray(declared) ? [...path8, "type", index] : [...path8, "type"];
|
|
32672
|
+
if (typeof name !== "string") {
|
|
32673
|
+
pushIssue(issues, namePath, "type", "malformed", `"type" must be a string or an array of strings`);
|
|
32674
|
+
} else if (!KNOWN_TYPE_NAMES.has(name)) {
|
|
32675
|
+
pushIssue(issues, namePath, "type", "malformed", `unknown type ${JSON.stringify(name)} (valid types: ${[...KNOWN_TYPE_NAMES].join(", ")})`);
|
|
32676
|
+
}
|
|
32677
|
+
}
|
|
32678
|
+
}
|
|
32679
|
+
if (schema.enum !== undefined && (!Array.isArray(schema.enum) || schema.enum.length === 0)) {
|
|
32680
|
+
pushIssue(issues, [...path8, "enum"], "enum", "malformed", `"enum" must be a non-empty array of allowed values`);
|
|
32681
|
+
}
|
|
32682
|
+
for (const keyword of ["allOf", "anyOf", "oneOf"]) {
|
|
32683
|
+
const branches = schema[keyword];
|
|
32684
|
+
if (branches === undefined)
|
|
32685
|
+
continue;
|
|
32686
|
+
if (!Array.isArray(branches) || branches.length === 0) {
|
|
32687
|
+
pushIssue(issues, [...path8, keyword], keyword, "malformed", `"${keyword}" must be a non-empty array of schema objects`);
|
|
32688
|
+
continue;
|
|
32689
|
+
}
|
|
32690
|
+
branches.forEach((branch, index) => {
|
|
32691
|
+
if (isPlainObject(branch)) {
|
|
32692
|
+
checkDefinitionNode(branch, [...path8, keyword, index], issues, depth + 1);
|
|
32693
|
+
} else {
|
|
32694
|
+
pushIssue(issues, [...path8, keyword, index], keyword, "malformed", `"${keyword}[${index}]" must be a schema object`);
|
|
32695
|
+
}
|
|
32696
|
+
});
|
|
32697
|
+
}
|
|
32698
|
+
if (schema.not !== undefined) {
|
|
32699
|
+
if (isPlainObject(schema.not)) {
|
|
32700
|
+
checkDefinitionNode(schema.not, [...path8, "not"], issues, depth + 1);
|
|
32701
|
+
} else {
|
|
32702
|
+
pushIssue(issues, [...path8, "not"], "not", "malformed", `"not" must be a schema object`);
|
|
32703
|
+
}
|
|
32704
|
+
}
|
|
32705
|
+
if (schema.required !== undefined) {
|
|
32706
|
+
if (!Array.isArray(schema.required) || !schema.required.every((key) => typeof key === "string")) {
|
|
32707
|
+
pushIssue(issues, [...path8, "required"], "required", "malformed", `"required" must be an array of property-name strings`);
|
|
32708
|
+
}
|
|
32709
|
+
}
|
|
32710
|
+
if (schema.properties !== undefined) {
|
|
32711
|
+
if (!isPlainObject(schema.properties)) {
|
|
32712
|
+
pushIssue(issues, [...path8, "properties"], "properties", "malformed", `"properties" must be an object mapping property names to schemas`);
|
|
32713
|
+
} else {
|
|
32714
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
32715
|
+
if (isPlainObject(propSchema)) {
|
|
32716
|
+
checkDefinitionNode(propSchema, [...path8, "properties", key], issues, depth + 1);
|
|
32717
|
+
} else {
|
|
32718
|
+
pushIssue(issues, [...path8, "properties", key], "properties", "malformed", `property ${JSON.stringify(key)} must be a schema object`);
|
|
32719
|
+
}
|
|
32720
|
+
}
|
|
32721
|
+
}
|
|
32722
|
+
}
|
|
32723
|
+
if (schema.items !== undefined) {
|
|
32724
|
+
if (isPlainObject(schema.items)) {
|
|
32725
|
+
checkDefinitionNode(schema.items, [...path8, "items"], issues, depth + 1);
|
|
32726
|
+
} else if (Array.isArray(schema.items)) {
|
|
32727
|
+
pushIssue(issues, [...path8, "items"], "items", "unsupported", `tuple-form "items" (an array of schemas) is not enforced by the workflow schema subset \u2014 use a single schema object`);
|
|
32728
|
+
} else {
|
|
32729
|
+
pushIssue(issues, [...path8, "items"], "items", "malformed", `"items" must be a schema object`);
|
|
32730
|
+
}
|
|
32731
|
+
}
|
|
32732
|
+
if (schema.additionalProperties !== undefined && typeof schema.additionalProperties !== "boolean") {
|
|
32733
|
+
if (isPlainObject(schema.additionalProperties)) {
|
|
32734
|
+
pushIssue(issues, [...path8, "additionalProperties"], "additionalProperties", "unsupported", `schema-form "additionalProperties" is not enforced by the workflow schema subset \u2014 only "additionalProperties: false" is`);
|
|
32735
|
+
} else {
|
|
32736
|
+
pushIssue(issues, [...path8, "additionalProperties"], "additionalProperties", "malformed", `"additionalProperties" must be a boolean (only "false" is enforced)`);
|
|
32737
|
+
}
|
|
32738
|
+
}
|
|
32739
|
+
for (const keyword of ["minItems", "maxItems", "minLength", "maxLength"]) {
|
|
32740
|
+
const value = schema[keyword];
|
|
32741
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isInteger(value) || value < 0)) {
|
|
32742
|
+
pushIssue(issues, [...path8, keyword], keyword, "malformed", `"${keyword}" must be a non-negative integer`);
|
|
32743
|
+
}
|
|
32744
|
+
}
|
|
32745
|
+
for (const keyword of ["minimum", "maximum"]) {
|
|
32746
|
+
const value = schema[keyword];
|
|
32747
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value))) {
|
|
32748
|
+
pushIssue(issues, [...path8, keyword], keyword, "malformed", `"${keyword}" must be a finite number`);
|
|
32749
|
+
}
|
|
32750
|
+
}
|
|
32401
32751
|
}
|
|
32402
32752
|
|
|
32403
32753
|
// src/workflows/schema.ts
|
|
@@ -32471,7 +32821,9 @@ var TOP_LEVEL_KEYS = [...ENVELOPE_KEYS, ...WORKFLOW_KEYS];
|
|
|
32471
32821
|
var DEFAULTS_KEYS = ["engine", "model", "timeout", "on_error", "llm"];
|
|
32472
32822
|
var BUDGET_KEYS = ["max_tokens", "max_units"];
|
|
32473
32823
|
var STEP_KEYS = ["id", "unit", "map", "route", "inputs", "output", "gate"];
|
|
32474
|
-
var UNIT_KEYS = ["engine", "model", "llm", "timeout", "retry", "on_error", "output", "env", "isolation"];
|
|
32824
|
+
var UNIT_KEYS = ["exec", "engine", "model", "llm", "timeout", "retry", "on_error", "output", "env", "isolation"];
|
|
32825
|
+
var EXEC_KEYS = ["command", "cwd", "pass_env", "inherit_env"];
|
|
32826
|
+
var UNIT_ENGINE_KEYS = ["engine", "model", "llm"];
|
|
32475
32827
|
var MAP_KEYS = ["over", "concurrency", "reducer", "unit"];
|
|
32476
32828
|
var ROUTE_KEYS = ["input", "when", "default"];
|
|
32477
32829
|
var RETRY_KEYS = ["max", "on"];
|
|
@@ -32489,7 +32841,7 @@ function parseWorkflow(markdown, source) {
|
|
|
32489
32841
|
};
|
|
32490
32842
|
}
|
|
32491
32843
|
const errors2 = [];
|
|
32492
|
-
const
|
|
32844
|
+
const path8 = source.path;
|
|
32493
32845
|
const lines = markdown.split(/\r?\n/);
|
|
32494
32846
|
const totalLines = lines.length;
|
|
32495
32847
|
const fmBlock = parseFrontmatterBlock(markdown);
|
|
@@ -32541,7 +32893,7 @@ function parseWorkflow(markdown, source) {
|
|
|
32541
32893
|
return 2;
|
|
32542
32894
|
};
|
|
32543
32895
|
const ctx = {
|
|
32544
|
-
filePath:
|
|
32896
|
+
filePath: path8,
|
|
32545
32897
|
errors: errors2,
|
|
32546
32898
|
lineAt,
|
|
32547
32899
|
lineAtOffset: (offset) => Math.max(1, lineCounter2.linePos(offset).line + lineOffset),
|
|
@@ -32553,10 +32905,10 @@ function parseWorkflow(markdown, source) {
|
|
|
32553
32905
|
if (range) {
|
|
32554
32906
|
const start = Math.max(1, lineCounter2.linePos(range[0]).line + lineOffset);
|
|
32555
32907
|
const end = Math.max(start, lineCounter2.linePos(Math.max(range[0], range[1] - 1)).line + lineOffset);
|
|
32556
|
-
return { path:
|
|
32908
|
+
return { path: path8, start, end };
|
|
32557
32909
|
}
|
|
32558
32910
|
}
|
|
32559
|
-
return { path:
|
|
32911
|
+
return { path: path8, start: frontmatterEndLine, end: frontmatterEndLine };
|
|
32560
32912
|
},
|
|
32561
32913
|
err: (p, message) => errors2.push({ line: lineAt(p), message }),
|
|
32562
32914
|
errAtLine: (line, message) => errors2.push({ line, message })
|
|
@@ -32579,7 +32931,7 @@ function parseWorkflow(markdown, source) {
|
|
|
32579
32931
|
const parsedSteps = parseSteps(ctx, root.steps);
|
|
32580
32932
|
const toc = parseMarkdownToc(markdown);
|
|
32581
32933
|
const declaredIds = new Set(parsedSteps.map((s) => s.id));
|
|
32582
|
-
const { sections, preamble } = bindStepSections(toc.headings, lines, fmBlock.bodyStartLine, totalLines,
|
|
32934
|
+
const { sections, preamble } = bindStepSections(toc.headings, lines, fmBlock.bodyStartLine, totalLines, path8, declaredIds, errors2);
|
|
32583
32935
|
const steps = parsedSteps.map((step, index) => {
|
|
32584
32936
|
const section = sections.get(step.id);
|
|
32585
32937
|
if (!section) {
|
|
@@ -32622,14 +32974,14 @@ function parseWorkflow(markdown, source) {
|
|
|
32622
32974
|
...budget ? { budget } : {},
|
|
32623
32975
|
steps,
|
|
32624
32976
|
...preamble ? { preamble } : {},
|
|
32625
|
-
source: { path:
|
|
32977
|
+
source: { path: path8, lineCount: totalLines }
|
|
32626
32978
|
};
|
|
32627
32979
|
runSemanticChecks(draft, root, frontmatterEndLine, errors2);
|
|
32628
32980
|
if (errors2.length > 0)
|
|
32629
32981
|
return { ok: false, errors: sortErrors(errors2) };
|
|
32630
32982
|
return { ok: true, document: draft };
|
|
32631
32983
|
}
|
|
32632
|
-
function bindStepSections(headings, lines, bodyStartLine, totalLines,
|
|
32984
|
+
function bindStepSections(headings, lines, bodyStartLine, totalLines, path8, declaredIds, errors2) {
|
|
32633
32985
|
const sections = new Map;
|
|
32634
32986
|
const h2s = headings.filter((h) => h.level === 2);
|
|
32635
32987
|
const firstH2Line = h2s[0]?.line;
|
|
@@ -32653,24 +33005,24 @@ function bindStepSections(headings, lines, bodyStartLine, totalLines, path7, dec
|
|
|
32653
33005
|
continue;
|
|
32654
33006
|
}
|
|
32655
33007
|
const sectionEnd = findNextHeadingAtOrAboveLevel(headings, i, 2, totalLines);
|
|
32656
|
-
const gate = findGateSubsection(headings, i, sectionEnd,
|
|
33008
|
+
const gate = findGateSubsection(headings, i, sectionEnd, path8, h.text, errors2);
|
|
32657
33009
|
const instructionsEnd = gate ? gate.headingLine - 1 : sectionEnd;
|
|
32658
33010
|
const instructionsText = sliceProseLines(lines, h.line + 1, instructionsEnd);
|
|
32659
33011
|
const section = { headingLine: h.line };
|
|
32660
33012
|
if (instructionsText) {
|
|
32661
|
-
section.instructions = { text: instructionsText, source: { path:
|
|
33013
|
+
section.instructions = { text: instructionsText, source: { path: path8, start: h.line + 1, end: instructionsEnd } };
|
|
32662
33014
|
}
|
|
32663
33015
|
if (gate) {
|
|
32664
33016
|
const gateText = sliceProseLines(lines, gate.bodyStart, gate.bodyEnd);
|
|
32665
33017
|
if (gateText) {
|
|
32666
|
-
section.gateRubric = { text: gateText, source: { path:
|
|
33018
|
+
section.gateRubric = { text: gateText, source: { path: path8, start: gate.bodyStart, end: gate.bodyEnd } };
|
|
32667
33019
|
}
|
|
32668
33020
|
}
|
|
32669
33021
|
sections.set(h.text, section);
|
|
32670
33022
|
}
|
|
32671
33023
|
return { sections, preamble: preambleRaw || undefined };
|
|
32672
33024
|
}
|
|
32673
|
-
function findGateSubsection(headings, stepHeadingIndex, sectionEnd,
|
|
33025
|
+
function findGateSubsection(headings, stepHeadingIndex, sectionEnd, path8, stepId, errors2) {
|
|
32674
33026
|
let found;
|
|
32675
33027
|
for (let j = stepHeadingIndex + 1;j < headings.length; j++) {
|
|
32676
33028
|
const h = headings[j];
|
|
@@ -32752,19 +33104,19 @@ function checkEnvelopeFields(ctx, root, fmEndLine) {
|
|
|
32752
33104
|
ctx.err(["stale_after"], `Workflow frontmatter "stale_after" must be a string.`);
|
|
32753
33105
|
}
|
|
32754
33106
|
}
|
|
32755
|
-
function checkActorStamp(ctx, value,
|
|
33107
|
+
function checkActorStamp(ctx, value, path8, label) {
|
|
32756
33108
|
if (value === undefined)
|
|
32757
33109
|
return;
|
|
32758
33110
|
if (!isPlainRecord(value)) {
|
|
32759
|
-
ctx.err(
|
|
33111
|
+
ctx.err(path8, `Workflow frontmatter ${label} must be a mapping with a non-empty "by".`);
|
|
32760
33112
|
return;
|
|
32761
33113
|
}
|
|
32762
|
-
checkUnknownKeys(ctx, value,
|
|
33114
|
+
checkUnknownKeys(ctx, value, path8, ACTOR_STAMP_KEYS, `${label} actor stamp`);
|
|
32763
33115
|
if (typeof value.by !== "string" || value.by.length === 0) {
|
|
32764
|
-
ctx.err([...
|
|
33116
|
+
ctx.err([...path8, "by"], `Workflow frontmatter ${label} must be a mapping with a non-empty "by".`);
|
|
32765
33117
|
}
|
|
32766
33118
|
if (value.at !== undefined && typeof value.at !== "string") {
|
|
32767
|
-
ctx.err([...
|
|
33119
|
+
ctx.err([...path8, "at"], `Workflow frontmatter ${label} actor stamp "at" must be a string.`);
|
|
32768
33120
|
}
|
|
32769
33121
|
}
|
|
32770
33122
|
function readTags(ctx, value, fmEndLine) {
|
|
@@ -32803,6 +33155,10 @@ function parseParams(ctx, raw) {
|
|
|
32803
33155
|
ctx.err(["params", paramName], `Param "${paramName}" must be a JSON Schema object (e.g. { type: string }).`);
|
|
32804
33156
|
continue;
|
|
32805
33157
|
}
|
|
33158
|
+
if (jsonBytes(value) > WORKFLOW_MAX_SCHEMA_BYTES) {
|
|
33159
|
+
ctx.err(["params", paramName], `Param "${paramName}" schema exceeds the 256 KiB resource limit.`);
|
|
33160
|
+
}
|
|
33161
|
+
checkSchemaDefinition(ctx, value, ["params", paramName], `Param "${paramName}" schema`);
|
|
32806
33162
|
params[paramName] = value;
|
|
32807
33163
|
}
|
|
32808
33164
|
return Object.keys(params).length > 0 ? params : undefined;
|
|
@@ -32810,32 +33166,31 @@ function parseParams(ctx, raw) {
|
|
|
32810
33166
|
function parseDefaults(ctx, raw) {
|
|
32811
33167
|
if (raw === undefined)
|
|
32812
33168
|
return;
|
|
32813
|
-
const
|
|
33169
|
+
const path8 = ["defaults"];
|
|
32814
33170
|
if (!isPlainRecord(raw)) {
|
|
32815
|
-
ctx.err(
|
|
33171
|
+
ctx.err(path8, `"defaults" must be a mapping with any of: ${DEFAULTS_KEYS.join(", ")}.`);
|
|
32816
33172
|
return;
|
|
32817
33173
|
}
|
|
32818
|
-
checkUnknownKeys(ctx, raw,
|
|
33174
|
+
checkUnknownKeys(ctx, raw, path8, DEFAULTS_KEYS, `"defaults"`);
|
|
32819
33175
|
const defaults = {};
|
|
32820
33176
|
if (raw.engine !== undefined) {
|
|
32821
|
-
|
|
32822
|
-
|
|
32823
|
-
|
|
32824
|
-
ctx.err([...path7, "engine"], `"defaults.engine" must be a non-empty engine name.`);
|
|
33177
|
+
const engine = parseEngineName(ctx, raw.engine, [...path8, "engine"], `"defaults.engine"`);
|
|
33178
|
+
if (engine !== undefined)
|
|
33179
|
+
defaults.engine = engine;
|
|
32825
33180
|
}
|
|
32826
33181
|
if (raw.model !== undefined) {
|
|
32827
33182
|
if (typeof raw.model === "string" && raw.model.trim() !== "")
|
|
32828
33183
|
defaults.model = raw.model.trim();
|
|
32829
33184
|
else
|
|
32830
|
-
ctx.err([...
|
|
33185
|
+
ctx.err([...path8, "model"], `"defaults.model" must be a non-empty string (a model alias or exact id).`);
|
|
32831
33186
|
}
|
|
32832
|
-
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...
|
|
33187
|
+
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...path8, "timeout"], `"defaults.timeout"`);
|
|
32833
33188
|
if (timeoutMs !== undefined)
|
|
32834
33189
|
defaults.timeoutMs = timeoutMs;
|
|
32835
|
-
const onError = parseEnumField(ctx, raw.on_error, [...
|
|
33190
|
+
const onError = parseEnumField(ctx, raw.on_error, [...path8, "on_error"], `"defaults.on_error"`, PROGRAM_ON_ERROR);
|
|
32836
33191
|
if (onError !== undefined)
|
|
32837
33192
|
defaults.onError = onError;
|
|
32838
|
-
const llm = parseLlmOverrides(ctx, raw.llm, [...
|
|
33193
|
+
const llm = parseLlmOverrides(ctx, raw.llm, [...path8, "llm"], `"defaults.llm"`);
|
|
32839
33194
|
if (llm !== undefined)
|
|
32840
33195
|
defaults.llm = llm;
|
|
32841
33196
|
return Object.keys(defaults).length > 0 ? defaults : undefined;
|
|
@@ -32843,25 +33198,25 @@ function parseDefaults(ctx, raw) {
|
|
|
32843
33198
|
function parseBudget(ctx, raw) {
|
|
32844
33199
|
if (raw === undefined)
|
|
32845
33200
|
return;
|
|
32846
|
-
const
|
|
33201
|
+
const path8 = ["budget"];
|
|
32847
33202
|
if (!isPlainRecord(raw)) {
|
|
32848
|
-
ctx.err(
|
|
33203
|
+
ctx.err(path8, `"budget" must be a mapping with any of: ${BUDGET_KEYS.join(", ")}.`);
|
|
32849
33204
|
return;
|
|
32850
33205
|
}
|
|
32851
|
-
checkUnknownKeys(ctx, raw,
|
|
33206
|
+
checkUnknownKeys(ctx, raw, path8, BUDGET_KEYS, `"budget"`);
|
|
32852
33207
|
const budget = {};
|
|
32853
33208
|
if (raw.max_tokens !== undefined) {
|
|
32854
33209
|
if (typeof raw.max_tokens === "number" && Number.isInteger(raw.max_tokens) && raw.max_tokens >= 1) {
|
|
32855
33210
|
budget.maxTokens = raw.max_tokens;
|
|
32856
33211
|
} else {
|
|
32857
|
-
ctx.err([...
|
|
33212
|
+
ctx.err([...path8, "max_tokens"], `"budget.max_tokens" must be an integer >= 1.`);
|
|
32858
33213
|
}
|
|
32859
33214
|
}
|
|
32860
33215
|
if (raw.max_units !== undefined) {
|
|
32861
33216
|
if (typeof raw.max_units === "number" && Number.isInteger(raw.max_units) && raw.max_units >= 1 && raw.max_units <= WORKFLOW_MAX_MAP_EXPANSION) {
|
|
32862
33217
|
budget.maxUnits = raw.max_units;
|
|
32863
33218
|
} else {
|
|
32864
|
-
ctx.err([...
|
|
33219
|
+
ctx.err([...path8, "max_units"], `"budget.max_units" must be an integer from 1 through ${WORKFLOW_MAX_MAP_EXPANSION}.`);
|
|
32865
33220
|
}
|
|
32866
33221
|
}
|
|
32867
33222
|
return Object.keys(budget).length > 0 ? budget : undefined;
|
|
@@ -32884,49 +33239,49 @@ function parseSteps(ctx, raw) {
|
|
|
32884
33239
|
const seenIds = new Map;
|
|
32885
33240
|
const routeChecks = [];
|
|
32886
33241
|
raw.forEach((rawStep, index) => {
|
|
32887
|
-
const
|
|
33242
|
+
const path8 = ["steps", index];
|
|
32888
33243
|
if (!isPlainRecord(rawStep)) {
|
|
32889
|
-
ctx.err(
|
|
33244
|
+
ctx.err(path8, `Step ${index + 1} must be a mapping with an "id".`);
|
|
32890
33245
|
return;
|
|
32891
33246
|
}
|
|
32892
33247
|
const label = typeof rawStep.id === "string" && rawStep.id !== "" ? `Step "${rawStep.id}"` : `Step ${index + 1}`;
|
|
32893
|
-
checkUnknownKeys(ctx, rawStep,
|
|
33248
|
+
checkUnknownKeys(ctx, rawStep, path8, STEP_KEYS, label);
|
|
32894
33249
|
let id = "";
|
|
32895
33250
|
if (typeof rawStep.id !== "string" || rawStep.id === "") {
|
|
32896
|
-
ctx.err([...
|
|
33251
|
+
ctx.err([...path8, "id"], `${label} requires a non-empty string "id".`);
|
|
32897
33252
|
} else if (!PROGRAM_STEP_ID_PATTERN.test(rawStep.id)) {
|
|
32898
|
-
ctx.err([...
|
|
33253
|
+
ctx.err([...path8, "id"], `${label} has an invalid id "${rawStep.id}". A step id cannot be referenced from steps.${rawStep.id}.output ` + `unless it matches [A-Za-z_][A-Za-z0-9_-]* (a letter or underscore first, then letters, digits, ` + `underscores, or dashes; no dots, no leading digit).`);
|
|
32899
33254
|
} else {
|
|
32900
33255
|
id = rawStep.id;
|
|
32901
33256
|
const firstIndex = seenIds.get(id);
|
|
32902
33257
|
if (firstIndex !== undefined) {
|
|
32903
|
-
ctx.err([...
|
|
33258
|
+
ctx.err([...path8, "id"], `Duplicate step id "${id}" (first used by step ${firstIndex + 1}). Step ids must be unique.`);
|
|
32904
33259
|
} else {
|
|
32905
33260
|
seenIds.set(id, index);
|
|
32906
33261
|
}
|
|
32907
33262
|
}
|
|
32908
33263
|
const declaredKinds = ["map", "route"].filter((kind) => rawStep[kind] !== undefined);
|
|
32909
33264
|
if (declaredKinds.length > 1) {
|
|
32910
|
-
ctx.err(
|
|
33265
|
+
ctx.err(path8, `${label} must declare at most one of "map" or "route" (found ${declaredKinds.join(" + ")}).`);
|
|
32911
33266
|
}
|
|
32912
33267
|
const isRoute = rawStep.route !== undefined;
|
|
32913
33268
|
const isMapStep = rawStep.map !== undefined;
|
|
32914
33269
|
if (isRoute && rawStep.unit !== undefined) {
|
|
32915
|
-
ctx.err(
|
|
33270
|
+
ctx.err(path8, `${label} is a route step and cannot also declare "unit" (route steps dispatch no unit).`);
|
|
32916
33271
|
}
|
|
32917
33272
|
if (isMapStep && rawStep.unit !== undefined) {
|
|
32918
|
-
ctx.err(
|
|
33273
|
+
ctx.err(path8, `${label} is a map step; the per-item dispatch-override bag belongs at "map.unit", not top-level "unit".`);
|
|
32919
33274
|
}
|
|
32920
33275
|
if (isRoute && rawStep.inputs !== undefined) {
|
|
32921
|
-
ctx.err(
|
|
32922
|
-
}
|
|
32923
|
-
const unit = rawStep.unit !== undefined && !isRoute && !isMapStep ? parseUnit(ctx, rawStep.unit, [...
|
|
32924
|
-
const map = isMapStep ? parseMap(ctx, rawStep.map, [...
|
|
32925
|
-
const route = isRoute ? parseRoute(ctx, rawStep.route, [...
|
|
32926
|
-
const inputs = !isRoute ? parseInputs(ctx, rawStep.inputs, [...
|
|
32927
|
-
const output = parseSchemaObject(ctx, rawStep.output, [...
|
|
32928
|
-
const gate = rawStep.gate !== undefined ? parseGate(ctx, rawStep.gate, [...
|
|
32929
|
-
const step = { id, source: ctx.refAt(
|
|
33276
|
+
ctx.err(path8, `${label} is a route step and cannot declare "inputs" (route steps dispatch no unit).`);
|
|
33277
|
+
}
|
|
33278
|
+
const unit = rawStep.unit !== undefined && !isRoute && !isMapStep ? parseUnit(ctx, rawStep.unit, [...path8, "unit"], label) : undefined;
|
|
33279
|
+
const map = isMapStep ? parseMap(ctx, rawStep.map, [...path8, "map"], label) : undefined;
|
|
33280
|
+
const route = isRoute ? parseRoute(ctx, rawStep.route, [...path8, "route"], label, index, routeChecks) : undefined;
|
|
33281
|
+
const inputs = !isRoute ? parseInputs(ctx, rawStep.inputs, [...path8, "inputs"], label) : undefined;
|
|
33282
|
+
const output = parseSchemaObject(ctx, rawStep.output, [...path8, "output"], `${label} "output"`);
|
|
33283
|
+
const gate = rawStep.gate !== undefined ? parseGate(ctx, rawStep.gate, [...path8, "gate"], label) : undefined;
|
|
33284
|
+
const step = { id, source: ctx.refAt(path8) };
|
|
32930
33285
|
if (unit)
|
|
32931
33286
|
step.unit = unit;
|
|
32932
33287
|
if (map)
|
|
@@ -32958,75 +33313,175 @@ function parseSteps(ctx, raw) {
|
|
|
32958
33313
|
}
|
|
32959
33314
|
return steps;
|
|
32960
33315
|
}
|
|
32961
|
-
function parseUnit(ctx, raw,
|
|
33316
|
+
function parseUnit(ctx, raw, path8, stepLabel) {
|
|
32962
33317
|
if (!isPlainRecord(raw)) {
|
|
32963
|
-
ctx.err(
|
|
33318
|
+
ctx.err(path8, `${stepLabel} "unit" must be a mapping (a dispatch-override bag).`);
|
|
32964
33319
|
return;
|
|
32965
33320
|
}
|
|
32966
|
-
checkUnknownKeys(ctx, raw,
|
|
32967
|
-
const unit = { source: ctx.refAt(
|
|
33321
|
+
checkUnknownKeys(ctx, raw, path8, UNIT_KEYS, `${stepLabel} "unit"`);
|
|
33322
|
+
const unit = { source: ctx.refAt(path8) };
|
|
33323
|
+
if (raw.exec !== undefined) {
|
|
33324
|
+
const exec = parseExec(ctx, raw.exec, [...path8, "exec"], stepLabel);
|
|
33325
|
+
if (exec !== undefined)
|
|
33326
|
+
unit.exec = exec;
|
|
33327
|
+
for (const key of UNIT_ENGINE_KEYS) {
|
|
33328
|
+
if (raw[key] === undefined)
|
|
33329
|
+
continue;
|
|
33330
|
+
ctx.err([...path8, key], `${stepLabel} "unit" declares both "exec" and "${key}". An exec unit runs a shell command and never ` + `reaches an engine, so "${key}" would have no effect \u2014 remove one of the two.`);
|
|
33331
|
+
}
|
|
33332
|
+
}
|
|
32968
33333
|
if (raw.engine !== undefined) {
|
|
32969
|
-
|
|
32970
|
-
|
|
32971
|
-
|
|
32972
|
-
ctx.err([...path7, "engine"], `${stepLabel} "engine" must be a non-empty engine name.`);
|
|
33334
|
+
const engine = parseEngineName(ctx, raw.engine, [...path8, "engine"], `${stepLabel} "engine"`);
|
|
33335
|
+
if (engine !== undefined)
|
|
33336
|
+
unit.engine = engine;
|
|
32973
33337
|
}
|
|
32974
33338
|
if (raw.model !== undefined) {
|
|
32975
33339
|
if (typeof raw.model === "string" && raw.model.trim() !== "")
|
|
32976
33340
|
unit.model = raw.model.trim();
|
|
32977
33341
|
else
|
|
32978
|
-
ctx.err([...
|
|
33342
|
+
ctx.err([...path8, "model"], `${stepLabel} "model" must be a non-empty string (a model alias or exact id).`);
|
|
32979
33343
|
}
|
|
32980
|
-
const llm = parseLlmOverrides(ctx, raw.llm, [...
|
|
33344
|
+
const llm = parseLlmOverrides(ctx, raw.llm, [...path8, "llm"], `${stepLabel} "llm"`);
|
|
32981
33345
|
if (llm !== undefined)
|
|
32982
33346
|
unit.llm = llm;
|
|
32983
|
-
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...
|
|
33347
|
+
const timeoutMs = parseTimeoutField(ctx, raw.timeout, [...path8, "timeout"], `${stepLabel} "timeout"`);
|
|
32984
33348
|
if (timeoutMs !== undefined)
|
|
32985
33349
|
unit.timeoutMs = timeoutMs;
|
|
32986
|
-
const retry = parseRetry(ctx, raw.retry, [...
|
|
33350
|
+
const retry = parseRetry(ctx, raw.retry, [...path8, "retry"], stepLabel);
|
|
32987
33351
|
if (retry !== undefined)
|
|
32988
33352
|
unit.retry = retry;
|
|
32989
|
-
const onError = parseEnumField(ctx, raw.on_error, [...
|
|
33353
|
+
const onError = parseEnumField(ctx, raw.on_error, [...path8, "on_error"], `${stepLabel} "on_error"`, PROGRAM_ON_ERROR);
|
|
32990
33354
|
if (onError !== undefined)
|
|
32991
33355
|
unit.onError = onError;
|
|
32992
|
-
const output = parseSchemaObject(ctx, raw.output, [...
|
|
33356
|
+
const output = parseSchemaObject(ctx, raw.output, [...path8, "output"], `${stepLabel} unit "output"`);
|
|
32993
33357
|
if (output !== undefined)
|
|
32994
33358
|
unit.output = output;
|
|
32995
33359
|
if (raw.env !== undefined) {
|
|
32996
33360
|
if (Array.isArray(raw.env) && raw.env.every((entry) => typeof entry === "string" && entry.trim() !== "")) {
|
|
32997
33361
|
unit.env = raw.env.map((entry) => entry.trim());
|
|
32998
33362
|
} else {
|
|
32999
|
-
ctx.err([...
|
|
33363
|
+
ctx.err([...path8, "env"], `${stepLabel} "env" must be a list of non-empty env asset refs.`);
|
|
33000
33364
|
}
|
|
33001
33365
|
}
|
|
33002
|
-
const isolation = parseEnumField(ctx, raw.isolation, [...
|
|
33366
|
+
const isolation = parseEnumField(ctx, raw.isolation, [...path8, "isolation"], `${stepLabel} "isolation"`, PROGRAM_ISOLATION_KINDS);
|
|
33003
33367
|
if (isolation !== undefined)
|
|
33004
33368
|
unit.isolation = isolation;
|
|
33005
33369
|
return unit;
|
|
33006
33370
|
}
|
|
33007
|
-
function
|
|
33371
|
+
function parseExec(ctx, raw, path8, stepLabel) {
|
|
33008
33372
|
if (!isPlainRecord(raw)) {
|
|
33009
|
-
ctx.err(
|
|
33373
|
+
ctx.err(path8, `${stepLabel} "exec" must be a mapping with a "command" argv list.`);
|
|
33374
|
+
return;
|
|
33375
|
+
}
|
|
33376
|
+
checkUnknownKeys(ctx, raw, path8, EXEC_KEYS, `${stepLabel} "exec"`);
|
|
33377
|
+
const command = parseExecCommand(ctx, raw.command, [...path8, "command"], stepLabel);
|
|
33378
|
+
if (command === undefined)
|
|
33379
|
+
return;
|
|
33380
|
+
const exec = { command };
|
|
33381
|
+
const cwd = parseExecCwd(ctx, raw.cwd, [...path8, "cwd"], stepLabel);
|
|
33382
|
+
if (cwd !== undefined)
|
|
33383
|
+
exec.cwd = cwd;
|
|
33384
|
+
const passEnv = parseExecPassEnv(ctx, raw.pass_env, [...path8, "pass_env"], stepLabel);
|
|
33385
|
+
if (passEnv !== undefined)
|
|
33386
|
+
exec.passEnv = passEnv;
|
|
33387
|
+
if (raw.inherit_env !== undefined) {
|
|
33388
|
+
if (typeof raw.inherit_env !== "boolean") {
|
|
33389
|
+
ctx.err([...path8, "inherit_env"], `${stepLabel} "exec.inherit_env" must be true or false. true gives the command akm's whole environment ` + `instead of the default allowlist; omit it (or write false) to keep the allowlist.`);
|
|
33390
|
+
} else if (raw.inherit_env) {
|
|
33391
|
+
exec.inheritEnv = true;
|
|
33392
|
+
}
|
|
33393
|
+
}
|
|
33394
|
+
return exec;
|
|
33395
|
+
}
|
|
33396
|
+
function parseExecPassEnv(ctx, raw, path8, stepLabel) {
|
|
33397
|
+
if (raw === undefined)
|
|
33398
|
+
return;
|
|
33399
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
33400
|
+
ctx.err(path8, `${stepLabel} "exec.pass_env" must be a non-empty list of environment variable NAMES to copy through from ` + `akm's own environment, e.g. pass_env: [CARGO_HOME]. Values never appear here \u2014 use "env:" bindings for those.`);
|
|
33401
|
+
return;
|
|
33402
|
+
}
|
|
33403
|
+
if (raw.length > WORKFLOW_MAX_EXEC_PASS_ENV) {
|
|
33404
|
+
ctx.err(path8, `${stepLabel} "exec.pass_env" must have at most ${WORKFLOW_MAX_EXEC_PASS_ENV} entries. A command needing ` + `more than that wants "inherit_env: true", which says so explicitly.`);
|
|
33405
|
+
return;
|
|
33406
|
+
}
|
|
33407
|
+
const names = [];
|
|
33408
|
+
for (const [index, entry] of raw.entries()) {
|
|
33409
|
+
if (typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry)) {
|
|
33410
|
+
ctx.err(path8, `${stepLabel} "exec.pass_env[${index}]" must be an environment variable name matching ` + `${WORKFLOW_ENV_VAR_NAME_PATTERN.source}.`);
|
|
33411
|
+
return;
|
|
33412
|
+
}
|
|
33413
|
+
if (names.includes(entry)) {
|
|
33414
|
+
ctx.err(path8, `${stepLabel} "exec.pass_env" lists "${entry}" more than once.`);
|
|
33415
|
+
return;
|
|
33416
|
+
}
|
|
33417
|
+
names.push(entry);
|
|
33418
|
+
}
|
|
33419
|
+
return names;
|
|
33420
|
+
}
|
|
33421
|
+
function parseExecCommand(ctx, raw, path8, stepLabel) {
|
|
33422
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
33423
|
+
ctx.err(path8, `${stepLabel} "exec" requires "command": a non-empty argv list, e.g. command: ["bun", "run", "test:unit"]. ` + `A single shell string is not accepted \u2014 the command is spawned directly, never through a shell.`);
|
|
33010
33424
|
return;
|
|
33011
33425
|
}
|
|
33012
|
-
|
|
33426
|
+
if (raw.length > WORKFLOW_MAX_EXEC_ARGV) {
|
|
33427
|
+
ctx.err(path8, `${stepLabel} "exec.command" must have at most ${WORKFLOW_MAX_EXEC_ARGV} entries.`);
|
|
33428
|
+
return;
|
|
33429
|
+
}
|
|
33430
|
+
const argv = [];
|
|
33431
|
+
for (const [index, entry] of raw.entries()) {
|
|
33432
|
+
if (typeof entry !== "string" || entry === "") {
|
|
33433
|
+
ctx.err(path8, `${stepLabel} "exec.command[${index}]" must be a non-empty string.`);
|
|
33434
|
+
return;
|
|
33435
|
+
}
|
|
33436
|
+
if (utf8Bytes(entry) > WORKFLOW_MAX_EXEC_ARG_BYTES) {
|
|
33437
|
+
ctx.err(path8, `${stepLabel} "exec.command[${index}]" exceeds ${WORKFLOW_MAX_EXEC_ARG_BYTES} bytes.`);
|
|
33438
|
+
return;
|
|
33439
|
+
}
|
|
33440
|
+
argv.push(entry);
|
|
33441
|
+
}
|
|
33442
|
+
return argv;
|
|
33443
|
+
}
|
|
33444
|
+
function parseExecCwd(ctx, raw, path8, stepLabel) {
|
|
33445
|
+
if (raw === undefined)
|
|
33446
|
+
return;
|
|
33447
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
33448
|
+
ctx.err(path8, `${stepLabel} "exec.cwd" must be a non-empty relative path inside the unit's working directory.`);
|
|
33449
|
+
return;
|
|
33450
|
+
}
|
|
33451
|
+
const value = raw.trim();
|
|
33452
|
+
if (value.length > WORKFLOW_MAX_EXEC_CWD_LENGTH) {
|
|
33453
|
+
ctx.err(path8, `${stepLabel} "exec.cwd" exceeds ${WORKFLOW_MAX_EXEC_CWD_LENGTH} characters.`);
|
|
33454
|
+
return;
|
|
33455
|
+
}
|
|
33456
|
+
if (!isContainedRelativePath(value)) {
|
|
33457
|
+
ctx.err(path8, `${stepLabel} "exec.cwd" (${JSON.stringify(value)}) must be a RELATIVE path inside the unit's working ` + `directory \u2014 absolute paths, Windows drive letters, "~", and ".." segments are rejected.`);
|
|
33458
|
+
return;
|
|
33459
|
+
}
|
|
33460
|
+
return value;
|
|
33461
|
+
}
|
|
33462
|
+
function parseMap(ctx, raw, path8, stepLabel) {
|
|
33463
|
+
if (!isPlainRecord(raw)) {
|
|
33464
|
+
ctx.err(path8, `${stepLabel} "map" must be a mapping with an "over" key.`);
|
|
33465
|
+
return;
|
|
33466
|
+
}
|
|
33467
|
+
checkUnknownKeys(ctx, raw, path8, MAP_KEYS, `${stepLabel} "map"`);
|
|
33013
33468
|
let over = "";
|
|
33014
33469
|
if (typeof raw.over === "string" && raw.over.trim() !== "") {
|
|
33015
33470
|
over = raw.over.trim();
|
|
33016
|
-
checkReferenceSyntax(ctx, over, [...
|
|
33471
|
+
checkReferenceSyntax(ctx, over, [...path8, "over"], `${stepLabel} "over"`);
|
|
33017
33472
|
} else {
|
|
33018
|
-
ctx.err([...
|
|
33473
|
+
ctx.err([...path8, "over"], `${stepLabel} "map" requires "over": a reference naming the item list (e.g. steps.discover.output.files).`);
|
|
33019
33474
|
}
|
|
33020
33475
|
let concurrency;
|
|
33021
33476
|
if (raw.concurrency !== undefined) {
|
|
33022
|
-
if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0) {
|
|
33477
|
+
if (typeof raw.concurrency === "number" && Number.isInteger(raw.concurrency) && raw.concurrency > 0 && raw.concurrency <= WORKFLOW_MAX_CONCURRENCY) {
|
|
33023
33478
|
concurrency = raw.concurrency;
|
|
33024
33479
|
} else {
|
|
33025
|
-
ctx.err([...
|
|
33480
|
+
ctx.err([...path8, "concurrency"], `${stepLabel} "concurrency" must be an integer from 1 through ${WORKFLOW_MAX_CONCURRENCY}.`);
|
|
33026
33481
|
}
|
|
33027
33482
|
}
|
|
33028
|
-
const reducer = parseEnumField(ctx, raw.reducer, [...
|
|
33029
|
-
const unit = raw.unit !== undefined ? parseUnit(ctx, raw.unit, [...
|
|
33483
|
+
const reducer = parseEnumField(ctx, raw.reducer, [...path8, "reducer"], `${stepLabel} "reducer"`, PROGRAM_REDUCERS);
|
|
33484
|
+
const unit = raw.unit !== undefined ? parseUnit(ctx, raw.unit, [...path8, "unit"], stepLabel) : undefined;
|
|
33030
33485
|
const map = { over };
|
|
33031
33486
|
if (concurrency !== undefined)
|
|
33032
33487
|
map.concurrency = concurrency;
|
|
@@ -33036,21 +33491,21 @@ function parseMap(ctx, raw, path7, stepLabel) {
|
|
|
33036
33491
|
map.unit = unit;
|
|
33037
33492
|
return map;
|
|
33038
33493
|
}
|
|
33039
|
-
function parseRoute(ctx, raw,
|
|
33494
|
+
function parseRoute(ctx, raw, path8, stepLabel, stepIndex, routeChecks) {
|
|
33040
33495
|
if (!isPlainRecord(raw)) {
|
|
33041
|
-
ctx.err(
|
|
33496
|
+
ctx.err(path8, `${stepLabel} "route" must be a mapping with "input" and "when" keys.`);
|
|
33042
33497
|
return;
|
|
33043
33498
|
}
|
|
33044
|
-
checkUnknownKeys(ctx, raw,
|
|
33499
|
+
checkUnknownKeys(ctx, raw, path8, ROUTE_KEYS, `${stepLabel} "route"`);
|
|
33045
33500
|
let input = "";
|
|
33046
33501
|
if (typeof raw.input === "string" && raw.input.trim() !== "") {
|
|
33047
33502
|
input = raw.input.trim();
|
|
33048
|
-
checkReferenceSyntax(ctx, input, [...
|
|
33503
|
+
checkReferenceSyntax(ctx, input, [...path8, "input"], `${stepLabel} "route.input"`);
|
|
33049
33504
|
} else {
|
|
33050
|
-
ctx.err([...
|
|
33505
|
+
ctx.err([...path8, "input"], `${stepLabel} "route" requires "input": a reference naming the value to route on.`);
|
|
33051
33506
|
}
|
|
33052
33507
|
const check = { stepIndex, stepLabel, branches: [] };
|
|
33053
|
-
const whenPath = [...
|
|
33508
|
+
const whenPath = [...path8, "when"];
|
|
33054
33509
|
if (!Array.isArray(raw.when) || raw.when.length === 0) {
|
|
33055
33510
|
ctx.err(whenPath, `${stepLabel} "route" requires "when": a non-empty list of { match, step } branches (e.g. when: [{ match: pass, step: ship }]).`);
|
|
33056
33511
|
} else {
|
|
@@ -33090,9 +33545,9 @@ function parseRoute(ctx, raw, path7, stepLabel, stepIndex, routeChecks) {
|
|
|
33090
33545
|
if (raw.default !== undefined) {
|
|
33091
33546
|
if (typeof raw.default === "string" && raw.default.trim() !== "") {
|
|
33092
33547
|
defaultStepId = raw.default.trim();
|
|
33093
|
-
check.defaultTarget = { stepId: defaultStepId, line: ctx.lineAt([...
|
|
33548
|
+
check.defaultTarget = { stepId: defaultStepId, line: ctx.lineAt([...path8, "default"]) };
|
|
33094
33549
|
} else {
|
|
33095
|
-
ctx.err([...
|
|
33550
|
+
ctx.err([...path8, "default"], `${stepLabel} "route.default" must be a step id string.`);
|
|
33096
33551
|
}
|
|
33097
33552
|
}
|
|
33098
33553
|
routeChecks.push(check);
|
|
@@ -33101,55 +33556,67 @@ function parseRoute(ctx, raw, path7, stepLabel, stepIndex, routeChecks) {
|
|
|
33101
33556
|
route.defaultStepId = defaultStepId;
|
|
33102
33557
|
return route;
|
|
33103
33558
|
}
|
|
33104
|
-
function parseInputs(ctx, raw,
|
|
33559
|
+
function parseInputs(ctx, raw, path8, stepLabel) {
|
|
33105
33560
|
if (raw === undefined)
|
|
33106
33561
|
return;
|
|
33107
33562
|
if (!Array.isArray(raw) || raw.length === 0) {
|
|
33108
|
-
ctx.err(
|
|
33563
|
+
ctx.err(path8, `${stepLabel} "inputs" must be a non-empty list of reference strings.`);
|
|
33109
33564
|
return;
|
|
33110
33565
|
}
|
|
33111
33566
|
if (raw.length > WORKFLOW_MAX_INPUTS) {
|
|
33112
|
-
ctx.err(
|
|
33567
|
+
ctx.err(path8, `${stepLabel} "inputs" must contain at most ${WORKFLOW_MAX_INPUTS} entries.`);
|
|
33113
33568
|
}
|
|
33114
33569
|
const out = [];
|
|
33115
33570
|
raw.forEach((entry, i) => {
|
|
33116
33571
|
if (typeof entry !== "string" || entry.trim() === "") {
|
|
33117
|
-
ctx.err([...
|
|
33572
|
+
ctx.err([...path8, i], `${stepLabel} "inputs[${i}]" must be a non-empty reference string.`);
|
|
33118
33573
|
return;
|
|
33119
33574
|
}
|
|
33120
33575
|
const value = entry.trim();
|
|
33121
|
-
checkReferenceSyntax(ctx, value, [...
|
|
33576
|
+
checkReferenceSyntax(ctx, value, [...path8, i], `${stepLabel} "inputs[${i}]"`);
|
|
33122
33577
|
out.push(value);
|
|
33123
33578
|
});
|
|
33124
33579
|
return out.length > 0 ? out : undefined;
|
|
33125
33580
|
}
|
|
33126
|
-
function parseGate(ctx, raw,
|
|
33581
|
+
function parseGate(ctx, raw, path8, stepLabel) {
|
|
33127
33582
|
if (!isPlainRecord(raw)) {
|
|
33128
|
-
ctx.err(
|
|
33583
|
+
ctx.err(path8, `${stepLabel} "gate" must be a mapping with any of: ${GATE_KEYS.join(", ")}.`);
|
|
33129
33584
|
return;
|
|
33130
33585
|
}
|
|
33131
|
-
checkUnknownKeys(ctx, raw,
|
|
33586
|
+
checkUnknownKeys(ctx, raw, path8, GATE_KEYS, `${stepLabel} "gate"`);
|
|
33132
33587
|
const gate = {};
|
|
33133
33588
|
if (raw.max_loops !== undefined) {
|
|
33134
|
-
if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1) {
|
|
33589
|
+
if (typeof raw.max_loops === "number" && Number.isInteger(raw.max_loops) && raw.max_loops >= 1 && raw.max_loops <= WORKFLOW_MAX_GATE_LOOPS) {
|
|
33135
33590
|
gate.maxLoops = raw.max_loops;
|
|
33136
33591
|
} else {
|
|
33137
|
-
ctx.err([...
|
|
33592
|
+
ctx.err([...path8, "max_loops"], `${stepLabel} "gate.max_loops" must be an integer from 1 through ${WORKFLOW_MAX_GATE_LOOPS}.`);
|
|
33138
33593
|
}
|
|
33139
33594
|
}
|
|
33140
33595
|
return gate;
|
|
33141
33596
|
}
|
|
33142
|
-
function
|
|
33597
|
+
function parseEngineName(ctx, raw, path8, label) {
|
|
33598
|
+
if (typeof raw !== "string" || raw.trim() === "") {
|
|
33599
|
+
ctx.err(path8, `${label} must be a non-empty engine name.`);
|
|
33600
|
+
return;
|
|
33601
|
+
}
|
|
33602
|
+
const name = raw.trim();
|
|
33603
|
+
if (!WORKFLOW_ENGINE_NAME_PATTERN.test(name) || name.length > WORKFLOW_MAX_ENGINE_NAME_LENGTH) {
|
|
33604
|
+
ctx.err(path8, `${label} has an invalid engine name ${JSON.stringify(name)}. Engine names are lowercase words of letters ` + `and digits separated by single dashes, starting with a letter (e.g. "code-review-llm"), at most ` + `${WORKFLOW_MAX_ENGINE_NAME_LENGTH} characters.`);
|
|
33605
|
+
return;
|
|
33606
|
+
}
|
|
33607
|
+
return name;
|
|
33608
|
+
}
|
|
33609
|
+
function parseRetry(ctx, raw, path8, stepLabel) {
|
|
33143
33610
|
if (raw === undefined)
|
|
33144
33611
|
return;
|
|
33145
33612
|
if (!isPlainRecord(raw)) {
|
|
33146
|
-
ctx.err(
|
|
33613
|
+
ctx.err(path8, `${stepLabel} "retry" must be a mapping: { max: <n>, on: [<failure_reason>, \u2026] }.`);
|
|
33147
33614
|
return;
|
|
33148
33615
|
}
|
|
33149
|
-
checkUnknownKeys(ctx, raw,
|
|
33616
|
+
checkUnknownKeys(ctx, raw, path8, RETRY_KEYS, `${stepLabel} "retry"`);
|
|
33150
33617
|
let ok = true;
|
|
33151
|
-
if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0)) {
|
|
33152
|
-
ctx.err([...
|
|
33618
|
+
if (!(typeof raw.max === "number" && Number.isInteger(raw.max) && raw.max >= 0 && raw.max <= WORKFLOW_MAX_RETRIES)) {
|
|
33619
|
+
ctx.err([...path8, "max"], `${stepLabel} "retry.max" is required and must be an integer from 0 through ${WORKFLOW_MAX_RETRIES}.`);
|
|
33153
33620
|
ok = false;
|
|
33154
33621
|
}
|
|
33155
33622
|
const on = [];
|
|
@@ -33158,27 +33625,27 @@ function parseRetry(ctx, raw, path7, stepLabel) {
|
|
|
33158
33625
|
if (typeof reason === "string" && PROGRAM_RETRY_REASONS.includes(reason)) {
|
|
33159
33626
|
on.push(reason);
|
|
33160
33627
|
} else {
|
|
33161
|
-
ctx.err([...
|
|
33628
|
+
ctx.err([...path8, "on", i], `${stepLabel} "retry.on" has unknown failure reason ${JSON.stringify(reason)}. Valid reasons: ${PROGRAM_RETRY_REASONS.join(", ")}.`);
|
|
33162
33629
|
ok = false;
|
|
33163
33630
|
}
|
|
33164
33631
|
});
|
|
33165
33632
|
} else {
|
|
33166
|
-
ctx.err([...
|
|
33633
|
+
ctx.err([...path8, "on"], `${stepLabel} "retry.on" is required and must be a non-empty list of failure reasons (${PROGRAM_RETRY_REASONS.join(", ")}).`);
|
|
33167
33634
|
ok = false;
|
|
33168
33635
|
}
|
|
33169
33636
|
return ok ? { max: raw.max, on } : undefined;
|
|
33170
33637
|
}
|
|
33171
|
-
function parseTimeoutField(ctx, raw,
|
|
33638
|
+
function parseTimeoutField(ctx, raw, path8, label) {
|
|
33172
33639
|
if (raw === undefined)
|
|
33173
33640
|
return;
|
|
33174
33641
|
if (typeof raw === "number") {
|
|
33175
33642
|
if (Number.isInteger(raw) && raw > 0)
|
|
33176
|
-
return raw;
|
|
33177
|
-
ctx.err(
|
|
33643
|
+
return checkTimeoutCeiling(ctx, raw, path8, label, String(raw));
|
|
33644
|
+
ctx.err(path8, `${label} has a non-positive timeout ${JSON.stringify(raw)}. ${TIMEOUT_HINT}.`);
|
|
33178
33645
|
return;
|
|
33179
33646
|
}
|
|
33180
33647
|
if (typeof raw !== "string") {
|
|
33181
|
-
ctx.err(
|
|
33648
|
+
ctx.err(path8, `${label} must be a duration string. ${TIMEOUT_HINT}.`);
|
|
33182
33649
|
return;
|
|
33183
33650
|
}
|
|
33184
33651
|
const value = raw.trim().toLowerCase();
|
|
@@ -33186,31 +33653,37 @@ function parseTimeoutField(ctx, raw, path7, label) {
|
|
|
33186
33653
|
return null;
|
|
33187
33654
|
const match = value.match(TIMEOUT_VALUE);
|
|
33188
33655
|
if (!match) {
|
|
33189
|
-
ctx.err(
|
|
33656
|
+
ctx.err(path8, `${label} has an invalid timeout "${raw}". ${TIMEOUT_HINT}.`);
|
|
33190
33657
|
return;
|
|
33191
33658
|
}
|
|
33192
33659
|
const n = Number.parseInt(match[1], 10);
|
|
33193
33660
|
const unit = match[2] ?? "ms";
|
|
33194
33661
|
const timeoutMs = unit === "m" ? n * 60000 : unit === "s" ? n * 1000 : n;
|
|
33195
33662
|
if (timeoutMs <= 0) {
|
|
33196
|
-
ctx.err(
|
|
33663
|
+
ctx.err(path8, `${label} has a non-positive timeout "${raw}". Use a positive duration or "none".`);
|
|
33197
33664
|
return;
|
|
33198
33665
|
}
|
|
33199
|
-
return timeoutMs;
|
|
33666
|
+
return checkTimeoutCeiling(ctx, timeoutMs, path8, label, raw);
|
|
33667
|
+
}
|
|
33668
|
+
function checkTimeoutCeiling(ctx, timeoutMs, path8, label, raw) {
|
|
33669
|
+
if (timeoutMs <= WORKFLOW_MAX_TIMEOUT_MS)
|
|
33670
|
+
return timeoutMs;
|
|
33671
|
+
ctx.err(path8, `${label} has a timeout "${raw}" above the maximum of ${WORKFLOW_MAX_TIMEOUT_MS} ms (about 24.8 days). ` + `Use a shorter duration or "none" for no timeout.`);
|
|
33672
|
+
return;
|
|
33200
33673
|
}
|
|
33201
|
-
function parseEnumField(ctx, raw,
|
|
33674
|
+
function parseEnumField(ctx, raw, path8, label, allowed) {
|
|
33202
33675
|
if (raw === undefined)
|
|
33203
33676
|
return;
|
|
33204
33677
|
if (typeof raw === "string" && allowed.includes(raw))
|
|
33205
33678
|
return raw;
|
|
33206
|
-
ctx.err(
|
|
33679
|
+
ctx.err(path8, `${label} must be one of: ${allowed.join(" | ")} (got ${JSON.stringify(raw)}).`);
|
|
33207
33680
|
return;
|
|
33208
33681
|
}
|
|
33209
|
-
function parseLlmOverrides(ctx, raw,
|
|
33682
|
+
function parseLlmOverrides(ctx, raw, path8, label) {
|
|
33210
33683
|
if (raw === undefined)
|
|
33211
33684
|
return;
|
|
33212
33685
|
if (!isPlainRecord(raw)) {
|
|
33213
|
-
ctx.err(
|
|
33686
|
+
ctx.err(path8, `${label} must be a mapping of LLM invocation overrides.`);
|
|
33214
33687
|
return;
|
|
33215
33688
|
}
|
|
33216
33689
|
const keys = [
|
|
@@ -33221,36 +33694,36 @@ function parseLlmOverrides(ctx, raw, path7, label) {
|
|
|
33221
33694
|
"context_length",
|
|
33222
33695
|
"enable_thinking"
|
|
33223
33696
|
];
|
|
33224
|
-
checkUnknownKeys(ctx, raw,
|
|
33697
|
+
checkUnknownKeys(ctx, raw, path8, keys, label);
|
|
33225
33698
|
const result = {};
|
|
33226
33699
|
if (raw.temperature !== undefined) {
|
|
33227
33700
|
if (typeof raw.temperature === "number" && Number.isFinite(raw.temperature))
|
|
33228
33701
|
result.temperature = raw.temperature;
|
|
33229
33702
|
else
|
|
33230
|
-
ctx.err([...
|
|
33703
|
+
ctx.err([...path8, "temperature"], `${label}.temperature must be a finite number.`);
|
|
33231
33704
|
}
|
|
33232
33705
|
if (raw.max_tokens !== undefined) {
|
|
33233
33706
|
if (typeof raw.max_tokens === "number" && Number.isInteger(raw.max_tokens) && raw.max_tokens > 0) {
|
|
33234
33707
|
result.maxTokens = raw.max_tokens;
|
|
33235
33708
|
} else
|
|
33236
|
-
ctx.err([...
|
|
33709
|
+
ctx.err([...path8, "max_tokens"], `${label}.max_tokens must be a positive integer.`);
|
|
33237
33710
|
}
|
|
33238
33711
|
if (raw.supports_json_schema !== undefined) {
|
|
33239
33712
|
if (typeof raw.supports_json_schema === "boolean")
|
|
33240
33713
|
result.supportsJsonSchema = raw.supports_json_schema;
|
|
33241
33714
|
else
|
|
33242
|
-
ctx.err([...
|
|
33715
|
+
ctx.err([...path8, "supports_json_schema"], `${label}.supports_json_schema must be a boolean.`);
|
|
33243
33716
|
}
|
|
33244
33717
|
if (raw.extra_params !== undefined) {
|
|
33245
33718
|
if (!isPlainRecord(raw.extra_params)) {
|
|
33246
|
-
ctx.err([...
|
|
33719
|
+
ctx.err([...path8, "extra_params"], `${label}.extra_params must be a JSON object.`);
|
|
33247
33720
|
} else {
|
|
33248
33721
|
const issues = validateExtraParams(raw.extra_params);
|
|
33249
33722
|
for (const issue of issues) {
|
|
33250
|
-
ctx.err([...
|
|
33723
|
+
ctx.err([...path8, "extra_params", ...issue.path], `${formatExtraParamsIssue(`${label}.extra_params`, issue)}.`);
|
|
33251
33724
|
}
|
|
33252
33725
|
if (jsonBytes(raw.extra_params) > WORKFLOW_MAX_EXTRA_PARAMS_BYTES) {
|
|
33253
|
-
ctx.err([...
|
|
33726
|
+
ctx.err([...path8, "extra_params"], `${label}.extra_params exceeds the 64 KiB resource limit.`);
|
|
33254
33727
|
}
|
|
33255
33728
|
if (issues.length === 0 && jsonBytes(raw.extra_params) <= WORKFLOW_MAX_EXTRA_PARAMS_BYTES) {
|
|
33256
33729
|
result.extraParams = raw.extra_params;
|
|
@@ -33261,37 +33734,48 @@ function parseLlmOverrides(ctx, raw, path7, label) {
|
|
|
33261
33734
|
if (typeof raw.context_length === "number" && Number.isInteger(raw.context_length) && raw.context_length > 0) {
|
|
33262
33735
|
result.contextLength = raw.context_length;
|
|
33263
33736
|
} else
|
|
33264
|
-
ctx.err([...
|
|
33737
|
+
ctx.err([...path8, "context_length"], `${label}.context_length must be a positive integer.`);
|
|
33265
33738
|
}
|
|
33266
33739
|
if (raw.enable_thinking !== undefined) {
|
|
33267
33740
|
if (typeof raw.enable_thinking === "boolean")
|
|
33268
33741
|
result.enableThinking = raw.enable_thinking;
|
|
33269
33742
|
else
|
|
33270
|
-
ctx.err([...
|
|
33743
|
+
ctx.err([...path8, "enable_thinking"], `${label}.enable_thinking must be a boolean.`);
|
|
33271
33744
|
}
|
|
33272
33745
|
return Object.keys(result).length > 0 ? result : undefined;
|
|
33273
33746
|
}
|
|
33274
|
-
function parseSchemaObject(ctx, raw,
|
|
33747
|
+
function parseSchemaObject(ctx, raw, path8, label) {
|
|
33275
33748
|
if (raw === undefined)
|
|
33276
33749
|
return;
|
|
33277
33750
|
if (!isPlainRecord(raw)) {
|
|
33278
|
-
ctx.err(
|
|
33751
|
+
ctx.err(path8, `${label} must be a JSON Schema object (e.g. { type: object, properties: { \u2026 } }).`);
|
|
33279
33752
|
return;
|
|
33280
33753
|
}
|
|
33281
33754
|
if (jsonBytes(raw) > WORKFLOW_MAX_SCHEMA_BYTES) {
|
|
33282
|
-
ctx.err(
|
|
33755
|
+
ctx.err(path8, `${label} exceeds the 256 KiB resource limit.`);
|
|
33283
33756
|
}
|
|
33757
|
+
checkSchemaDefinition(ctx, raw, path8, label);
|
|
33284
33758
|
return raw;
|
|
33285
33759
|
}
|
|
33286
|
-
function
|
|
33760
|
+
function checkSchemaDefinition(ctx, schema, path8, label) {
|
|
33761
|
+
for (const issue of checkJsonSchemaDefinition(schema)) {
|
|
33762
|
+
const issuePath = [...path8, ...issue.path];
|
|
33763
|
+
if (issue.kind === "unsupported") {
|
|
33764
|
+
ctx.err(issuePath, `${label} (at ${issue.pointer}): ${issue.message}. Supported JSON Schema keywords: ` + `${JSON_SCHEMA_SUBSET_SUPPORTED_KEYWORDS}.`);
|
|
33765
|
+
} else {
|
|
33766
|
+
ctx.err(issuePath, `${label} is not a valid JSON Schema (at ${issue.pointer}): ${issue.message}.`);
|
|
33767
|
+
}
|
|
33768
|
+
}
|
|
33769
|
+
}
|
|
33770
|
+
function checkReferenceSyntax(ctx, text, path8, label) {
|
|
33287
33771
|
const result = parseReference(text);
|
|
33288
33772
|
if (!result.ok)
|
|
33289
|
-
ctx.err(
|
|
33773
|
+
ctx.err(path8, `${label}: ${result.message}`);
|
|
33290
33774
|
}
|
|
33291
|
-
function checkUnknownKeys(ctx, obj,
|
|
33775
|
+
function checkUnknownKeys(ctx, obj, path8, allowed, label) {
|
|
33292
33776
|
for (const key of Object.keys(obj)) {
|
|
33293
33777
|
if (!allowed.includes(key)) {
|
|
33294
|
-
ctx.err([...
|
|
33778
|
+
ctx.err([...path8, key], `Unknown ${label} key "${key}". Allowed keys: ${allowed.join(", ")}.`);
|
|
33295
33779
|
}
|
|
33296
33780
|
}
|
|
33297
33781
|
}
|
|
@@ -33335,7 +33819,7 @@ function checkInvalidTypeValue(data, allowedTypes) {
|
|
|
33335
33819
|
return `type field has invalid value '${value}'; expected one of: ${allowedTypes.join(", ")}`;
|
|
33336
33820
|
}
|
|
33337
33821
|
function suggestSlug(filePath) {
|
|
33338
|
-
return
|
|
33822
|
+
return path8.basename(filePath, ".md").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
33339
33823
|
}
|
|
33340
33824
|
function nameOrTypeDiagnostics(relPath, data, frontmatter, allowedTypes) {
|
|
33341
33825
|
const missingFieldDetail = checkMissingNameOrType(data, frontmatter);
|
|
@@ -33391,7 +33875,7 @@ function collectSuppressedKeys(raw) {
|
|
|
33391
33875
|
function dangerousEnvKeyDiagnostics(type, relPath, raw) {
|
|
33392
33876
|
if (type !== "env" && type !== "secret")
|
|
33393
33877
|
return [];
|
|
33394
|
-
const baseNameWithExt =
|
|
33878
|
+
const baseNameWithExt = path8.basename(relPath);
|
|
33395
33879
|
if (!baseNameWithExt.endsWith(".env"))
|
|
33396
33880
|
return [];
|
|
33397
33881
|
const ref = conceptIdForStashFile(type, ".", relPath);
|
|
@@ -33412,9 +33896,10 @@ function dangerousEnvKeyDiagnostics(type, relPath, raw) {
|
|
|
33412
33896
|
}
|
|
33413
33897
|
return diagnostics;
|
|
33414
33898
|
}
|
|
33415
|
-
|
|
33899
|
+
var AKM_SKILL_DIRS = new Set(["skills"]);
|
|
33900
|
+
async function skillDirectoryDiagnostics(relPath, seen, ctx, skillDirs = AKM_SKILL_DIRS) {
|
|
33416
33901
|
const segments = relPath.replace(/\\/g, "/").split("/").filter((s) => s.length > 0);
|
|
33417
|
-
if (segments.length < 3 || segments[0]
|
|
33902
|
+
if (segments.length < 3 || !skillDirs.has(segments[0]))
|
|
33418
33903
|
return [];
|
|
33419
33904
|
const skillDir = `${segments[0]}/${segments[1]}`;
|
|
33420
33905
|
if (seen.has(skillDir))
|
|
@@ -33494,42 +33979,62 @@ function matchWorkflowPlaceholder(body) {
|
|
|
33494
33979
|
return PLACEHOLDER_STRINGS.find((p) => body.includes(p)) ?? null;
|
|
33495
33980
|
}
|
|
33496
33981
|
function workflowStructureDiagnostics(relPath, raw, parsePath2) {
|
|
33982
|
+
return workflowFrontendDiagnostics(relPath, raw, parsePath2).errors;
|
|
33983
|
+
}
|
|
33984
|
+
function lineOf(err) {
|
|
33985
|
+
return typeof err.line === "number" && Number.isFinite(err.line) && err.line > 0 ? { line: err.line } : {};
|
|
33986
|
+
}
|
|
33987
|
+
function workflowFrontendDiagnostics(relPath, raw, parsePath2) {
|
|
33988
|
+
const none = { errors: [], warnings: [] };
|
|
33497
33989
|
if (parsePath2.includes("/.cache/") || parsePath2.includes("/registry/"))
|
|
33498
|
-
return
|
|
33499
|
-
const
|
|
33990
|
+
return none;
|
|
33991
|
+
const errors2 = [];
|
|
33992
|
+
const warnings = [];
|
|
33500
33993
|
try {
|
|
33501
33994
|
const result = parseWorkflow(raw, { path: parsePath2 });
|
|
33502
33995
|
if (!result.ok) {
|
|
33503
33996
|
for (const err of result.errors ?? []) {
|
|
33504
|
-
|
|
33997
|
+
errors2.push({
|
|
33505
33998
|
file: relPath,
|
|
33506
33999
|
issue: "invalid-workflow-structure",
|
|
33507
34000
|
detail: err.message ?? String(err),
|
|
33508
|
-
fixed: false
|
|
34001
|
+
fixed: false,
|
|
34002
|
+
...lineOf(err)
|
|
33509
34003
|
});
|
|
33510
34004
|
}
|
|
33511
|
-
return
|
|
34005
|
+
return { errors: errors2, warnings };
|
|
33512
34006
|
}
|
|
33513
|
-
const compiled = compileWorkflowPlan(result.document,
|
|
34007
|
+
const compiled = compileWorkflowPlan(result.document, path8.basename(parsePath2, path8.extname(parsePath2)));
|
|
33514
34008
|
if (!compiled.ok) {
|
|
33515
34009
|
for (const err of compiled.errors) {
|
|
33516
|
-
|
|
34010
|
+
errors2.push({
|
|
33517
34011
|
file: relPath,
|
|
33518
34012
|
issue: "invalid-workflow-structure",
|
|
33519
34013
|
detail: err.message,
|
|
33520
|
-
fixed: false
|
|
34014
|
+
fixed: false,
|
|
34015
|
+
...lineOf(err)
|
|
33521
34016
|
});
|
|
33522
34017
|
}
|
|
34018
|
+
return { errors: errors2, warnings };
|
|
34019
|
+
}
|
|
34020
|
+
for (const warning of compiled.warnings) {
|
|
34021
|
+
warnings.push({
|
|
34022
|
+
file: relPath,
|
|
34023
|
+
issue: "workflow-warning",
|
|
34024
|
+
detail: warning.message,
|
|
34025
|
+
fixed: false,
|
|
34026
|
+
...lineOf(warning)
|
|
34027
|
+
});
|
|
33523
34028
|
}
|
|
33524
34029
|
} catch (e) {
|
|
33525
|
-
|
|
34030
|
+
errors2.push({
|
|
33526
34031
|
file: relPath,
|
|
33527
34032
|
issue: "invalid-workflow-structure",
|
|
33528
34033
|
detail: `workflow parser error: ${e instanceof Error ? e.message : String(e)}`,
|
|
33529
34034
|
fixed: false
|
|
33530
34035
|
});
|
|
33531
34036
|
}
|
|
33532
|
-
return
|
|
34037
|
+
return { errors: errors2, warnings };
|
|
33533
34038
|
}
|
|
33534
34039
|
function workflowDiagnostics(relPath, raw, body) {
|
|
33535
34040
|
const diagnostics = [];
|
|
@@ -33574,7 +34079,7 @@ init_errors();
|
|
|
33574
34079
|
init_file_lock();
|
|
33575
34080
|
init_paths();
|
|
33576
34081
|
import fs7 from "fs";
|
|
33577
|
-
import
|
|
34082
|
+
import path11 from "path";
|
|
33578
34083
|
function readConfigText(configPath) {
|
|
33579
34084
|
try {
|
|
33580
34085
|
return readTextFileWithLimit(configPath, MAX_CONFIG_FILE_BYTES, "Config file");
|
|
@@ -33613,7 +34118,7 @@ function describeJsonRoot(value) {
|
|
|
33613
34118
|
return typeof value;
|
|
33614
34119
|
}
|
|
33615
34120
|
function getConfigLockPath() {
|
|
33616
|
-
return
|
|
34121
|
+
return path11.join(getConfigDir(), "config.json.lck");
|
|
33617
34122
|
}
|
|
33618
34123
|
var CONFIG_LOCK_MAX_RETRIES = 40;
|
|
33619
34124
|
var CONFIG_LOCK_RETRY_DELAY_MS = 50;
|
|
@@ -33623,7 +34128,7 @@ function sleepSyncMs(ms) {
|
|
|
33623
34128
|
function acquireConfigLock() {
|
|
33624
34129
|
const lockPath = getConfigLockPath();
|
|
33625
34130
|
try {
|
|
33626
|
-
fs7.mkdirSync(
|
|
34131
|
+
fs7.mkdirSync(path11.dirname(lockPath), { recursive: true });
|
|
33627
34132
|
} catch {}
|
|
33628
34133
|
for (let attempt = 0;attempt < CONFIG_LOCK_MAX_RETRIES; attempt++) {
|
|
33629
34134
|
try {
|
|
@@ -34170,8 +34675,8 @@ function getErrorMap() {
|
|
|
34170
34675
|
}
|
|
34171
34676
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
34172
34677
|
var makeIssue = (params) => {
|
|
34173
|
-
const { data, path:
|
|
34174
|
-
const fullPath = [...
|
|
34678
|
+
const { data, path: path12, errorMaps, issueData } = params;
|
|
34679
|
+
const fullPath = [...path12, ...issueData.path || []];
|
|
34175
34680
|
const fullIssue = {
|
|
34176
34681
|
...issueData,
|
|
34177
34682
|
path: fullPath
|
|
@@ -34283,11 +34788,11 @@ var errorUtil;
|
|
|
34283
34788
|
|
|
34284
34789
|
// node_modules/zod/v3/types.js
|
|
34285
34790
|
class ParseInputLazyPath {
|
|
34286
|
-
constructor(parent, value,
|
|
34791
|
+
constructor(parent, value, path12, key) {
|
|
34287
34792
|
this._cachedPath = [];
|
|
34288
34793
|
this.parent = parent;
|
|
34289
34794
|
this.data = value;
|
|
34290
|
-
this._path =
|
|
34795
|
+
this._path = path12;
|
|
34291
34796
|
this._key = key;
|
|
34292
34797
|
}
|
|
34293
34798
|
get path() {
|
|
@@ -38337,6 +38842,7 @@ var BundlesConfigSchema = exports_external.record(exports_external.string().min(
|
|
|
38337
38842
|
// src/core/config/schema/workflow.ts
|
|
38338
38843
|
var WorkflowConfigSchema = exports_external.object({
|
|
38339
38844
|
maxConcurrency: positiveInt.optional(),
|
|
38845
|
+
defaultMapConcurrency: positiveInt.optional(),
|
|
38340
38846
|
judgeEngine: engineName.optional()
|
|
38341
38847
|
}).passthrough();
|
|
38342
38848
|
|
|
@@ -38633,7 +39139,7 @@ function normalizeInstalledGitRef(source, ref) {
|
|
|
38633
39139
|
|
|
38634
39140
|
// src/core/config/deep-merge.ts
|
|
38635
39141
|
var UNSAFE_KEYS = new Set(["__proto__", "constructor", "prototype"]);
|
|
38636
|
-
function
|
|
39142
|
+
function isPlainObject2(value) {
|
|
38637
39143
|
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
38638
39144
|
return false;
|
|
38639
39145
|
const prototype = Object.getPrototypeOf(value);
|
|
@@ -38642,7 +39148,7 @@ function isPlainObject(value) {
|
|
|
38642
39148
|
function copyConfigValue(value) {
|
|
38643
39149
|
if (Array.isArray(value))
|
|
38644
39150
|
return value.map(copyConfigValue);
|
|
38645
|
-
if (!
|
|
39151
|
+
if (!isPlainObject2(value))
|
|
38646
39152
|
return value;
|
|
38647
39153
|
const copy = {};
|
|
38648
39154
|
for (const key of Object.keys(value)) {
|
|
@@ -38661,7 +39167,7 @@ function deepMergeConfig(base, override) {
|
|
|
38661
39167
|
if (next === undefined)
|
|
38662
39168
|
continue;
|
|
38663
39169
|
const current = result[key];
|
|
38664
|
-
result[key] =
|
|
39170
|
+
result[key] = isPlainObject2(current) && isPlainObject2(next) ? deepMergeConfig(current, next) : copyConfigValue(next);
|
|
38665
39171
|
}
|
|
38666
39172
|
return result;
|
|
38667
39173
|
}
|
|
@@ -38803,9 +39309,10 @@ init_common();
|
|
|
38803
39309
|
init_errors();
|
|
38804
39310
|
init_file_lock();
|
|
38805
39311
|
init_maintenance_barrier();
|
|
39312
|
+
init_path_access();
|
|
38806
39313
|
init_paths();
|
|
38807
39314
|
import fs11 from "fs";
|
|
38808
|
-
import
|
|
39315
|
+
import path13 from "path";
|
|
38809
39316
|
function readLockfile() {
|
|
38810
39317
|
const lockfilePath = getLockfilePath();
|
|
38811
39318
|
try {
|
|
@@ -38818,6 +39325,12 @@ function readLockfile() {
|
|
|
38818
39325
|
return [];
|
|
38819
39326
|
}
|
|
38820
39327
|
}
|
|
39328
|
+
function assertLockfilePathReadable(target) {
|
|
39329
|
+
const { access, code } = classifyPathAccess(target);
|
|
39330
|
+
if (access !== "inaccessible")
|
|
39331
|
+
return;
|
|
39332
|
+
throw new ConfigError(`Refusing to modify the lockfile: ${describeInaccessiblePath(target, code)}. akm cannot read the existing lock ` + "records, and writing over them would destroy every bundle they track. Fix the ownership or mode of that " + "path (or point AKM_DATA_DIR / XDG_DATA_HOME somewhere this user owns) and retry.", "DATA_DIR_UNREADABLE");
|
|
39333
|
+
}
|
|
38821
39334
|
function lockContentRootFor(bundleId, type) {
|
|
38822
39335
|
if (!bundleId || type !== "git" && type !== "npm")
|
|
38823
39336
|
return;
|
|
@@ -38830,7 +39343,7 @@ function lockContentRootFor(bundleId, type) {
|
|
|
38830
39343
|
}
|
|
38831
39344
|
function writeLockfileUnlocked(entries) {
|
|
38832
39345
|
const lockfilePath = getLockfilePath();
|
|
38833
|
-
const dir =
|
|
39346
|
+
const dir = path13.dirname(lockfilePath);
|
|
38834
39347
|
fs11.mkdirSync(dir, { recursive: true });
|
|
38835
39348
|
writeFileAtomic(lockfilePath, `${JSON.stringify(entries, null, 2)}
|
|
38836
39349
|
`);
|
|
@@ -38838,6 +39351,7 @@ function writeLockfileUnlocked(entries) {
|
|
|
38838
39351
|
function readLockEntriesForMigration() {
|
|
38839
39352
|
let existing = [];
|
|
38840
39353
|
const lockfilePath = getLockfilePath();
|
|
39354
|
+
assertLockfilePathReadable(lockfilePath);
|
|
38841
39355
|
if (fs11.existsSync(lockfilePath)) {
|
|
38842
39356
|
let raw;
|
|
38843
39357
|
try {
|
|
@@ -38879,10 +39393,10 @@ init_database();
|
|
|
38879
39393
|
|
|
38880
39394
|
// src/core/bundle-id.ts
|
|
38881
39395
|
import crypto3 from "crypto";
|
|
38882
|
-
import
|
|
39396
|
+
import path14 from "path";
|
|
38883
39397
|
function slugForPath(sourcePath) {
|
|
38884
|
-
const resolved =
|
|
38885
|
-
const base =
|
|
39398
|
+
const resolved = path14.resolve(sourcePath);
|
|
39399
|
+
const base = path14.basename(resolved).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
38886
39400
|
if (base.length > 0)
|
|
38887
39401
|
return base;
|
|
38888
39402
|
return `bundle-${shortHash(resolved)}`;
|
|
@@ -38905,7 +39419,7 @@ function deriveBundleIds(sources) {
|
|
|
38905
39419
|
function ensureUniqueId(preferred, sourcePath, used) {
|
|
38906
39420
|
if (!used.has(preferred))
|
|
38907
39421
|
return preferred;
|
|
38908
|
-
const suffixed = `${preferred}-${shortHash(
|
|
39422
|
+
const suffixed = `${preferred}-${shortHash(path14.resolve(sourcePath))}`;
|
|
38909
39423
|
if (!used.has(suffixed))
|
|
38910
39424
|
return suffixed;
|
|
38911
39425
|
let n = 2;
|
|
@@ -38938,11 +39452,11 @@ function inferLegacyBundleIds(sources) {
|
|
|
38938
39452
|
// scripts/akm-migrate/migrate/legacy/config-source-migration.ts
|
|
38939
39453
|
import fs24 from "fs";
|
|
38940
39454
|
import os from "os";
|
|
38941
|
-
import
|
|
39455
|
+
import path28 from "path";
|
|
38942
39456
|
|
|
38943
39457
|
// src/core/adapter/adapters/agent-skills-adapter.ts
|
|
38944
39458
|
import fs12 from "fs";
|
|
38945
|
-
import
|
|
39459
|
+
import path15 from "path";
|
|
38946
39460
|
|
|
38947
39461
|
// src/core/adapter/adapters/shared.ts
|
|
38948
39462
|
import { createHash } from "crypto";
|
|
@@ -39185,6 +39699,36 @@ function skillFieldDiagnostics(relPath, dirName, data) {
|
|
|
39185
39699
|
}
|
|
39186
39700
|
return diagnostics;
|
|
39187
39701
|
}
|
|
39702
|
+
var MAX_PACKAGE_PROBE_DEPTH = 3;
|
|
39703
|
+
async function subtreeHasManifest(dir, entries, ctx, depth) {
|
|
39704
|
+
if (entries.includes(SKILL_MANIFEST))
|
|
39705
|
+
return true;
|
|
39706
|
+
if (depth >= MAX_PACKAGE_PROBE_DEPTH)
|
|
39707
|
+
return false;
|
|
39708
|
+
for (const entry of entries) {
|
|
39709
|
+
const child = `${dir}/${entry}`;
|
|
39710
|
+
const childEntries = await ctx.list(child);
|
|
39711
|
+
if (childEntries.length === 0)
|
|
39712
|
+
continue;
|
|
39713
|
+
if (await subtreeHasManifest(child, childEntries, ctx, depth + 1))
|
|
39714
|
+
return true;
|
|
39715
|
+
}
|
|
39716
|
+
return false;
|
|
39717
|
+
}
|
|
39718
|
+
async function missingManifestDiagnostics(ctx) {
|
|
39719
|
+
const diagnostics = [];
|
|
39720
|
+
for (const name of await ctx.list(".")) {
|
|
39721
|
+
if (name.startsWith("."))
|
|
39722
|
+
continue;
|
|
39723
|
+
const entries = await ctx.list(name);
|
|
39724
|
+
if (entries.length === 0)
|
|
39725
|
+
continue;
|
|
39726
|
+
if (await subtreeHasManifest(name, entries, ctx, 1))
|
|
39727
|
+
continue;
|
|
39728
|
+
diagnostics.push({ file: name, issue: "missing-skill-md", detail: `no SKILL.md in ${name}/`, fixed: false });
|
|
39729
|
+
}
|
|
39730
|
+
return diagnostics;
|
|
39731
|
+
}
|
|
39188
39732
|
async function validate(_c, changes, ctx) {
|
|
39189
39733
|
const diagnostics = [];
|
|
39190
39734
|
const seenDirs = new Set;
|
|
@@ -39202,6 +39746,7 @@ async function validate(_c, changes, ctx) {
|
|
|
39202
39746
|
seenDirs.add(pkg.conceptId);
|
|
39203
39747
|
diagnostics.push(...skillFieldDiagnostics(toPosix2(change.path), pkg.dirName, parseFrontmatter(raw).data));
|
|
39204
39748
|
}
|
|
39749
|
+
diagnostics.push(...await missingManifestDiagnostics(ctx));
|
|
39205
39750
|
return diagnostics;
|
|
39206
39751
|
}
|
|
39207
39752
|
var agentSkillsAdapter = {
|
|
@@ -39211,7 +39756,7 @@ var agentSkillsAdapter = {
|
|
|
39211
39756
|
recognize,
|
|
39212
39757
|
validate,
|
|
39213
39758
|
placeNew(c, conceptId) {
|
|
39214
|
-
return
|
|
39759
|
+
return path15.join(c.root, conceptId, SKILL_MANIFEST);
|
|
39215
39760
|
},
|
|
39216
39761
|
looksLikeRoot(root) {
|
|
39217
39762
|
let entries;
|
|
@@ -39224,7 +39769,7 @@ var agentSkillsAdapter = {
|
|
|
39224
39769
|
if (!entry.isDirectory())
|
|
39225
39770
|
return false;
|
|
39226
39771
|
try {
|
|
39227
|
-
return fs12.existsSync(
|
|
39772
|
+
return fs12.existsSync(path15.join(root, entry.name, SKILL_MANIFEST));
|
|
39228
39773
|
} catch {
|
|
39229
39774
|
return false;
|
|
39230
39775
|
}
|
|
@@ -39234,11 +39779,11 @@ var agentSkillsAdapter = {
|
|
|
39234
39779
|
|
|
39235
39780
|
// src/core/adapter/adapters/akm-adapter.ts
|
|
39236
39781
|
import fs15 from "fs";
|
|
39237
|
-
import
|
|
39782
|
+
import path17 from "path";
|
|
39238
39783
|
|
|
39239
39784
|
// src/indexer/passes/metadata.ts
|
|
39240
39785
|
import fs13 from "fs";
|
|
39241
|
-
import
|
|
39786
|
+
import path16 from "path";
|
|
39242
39787
|
init_common();
|
|
39243
39788
|
init_warn();
|
|
39244
39789
|
var SCOPE_KEYS = ["user", "agent", "run", "channel"];
|
|
@@ -39979,7 +40524,7 @@ function extractBodyOpening(body) {
|
|
|
39979
40524
|
return `${cut.trimEnd()}\u2026`;
|
|
39980
40525
|
}
|
|
39981
40526
|
function applyPreContributorFields(entry, file, ctx, pkgMeta) {
|
|
39982
|
-
const ext =
|
|
40527
|
+
const ext = path16.extname(file).toLowerCase();
|
|
39983
40528
|
if (pkgMeta) {
|
|
39984
40529
|
if (pkgMeta.description && !entry.description) {
|
|
39985
40530
|
entry.description = pkgMeta.description;
|
|
@@ -40019,8 +40564,8 @@ function applyPreContributorFields(entry, file, ctx, pkgMeta) {
|
|
|
40019
40564
|
}
|
|
40020
40565
|
}
|
|
40021
40566
|
function applyPostContributorFields(entry, file, canonicalName, dirPath) {
|
|
40022
|
-
const ext =
|
|
40023
|
-
const baseName =
|
|
40567
|
+
const ext = path16.extname(file).toLowerCase();
|
|
40568
|
+
const baseName = path16.basename(file, ext);
|
|
40024
40569
|
if (!entry.description) {
|
|
40025
40570
|
entry.description = fileNameToDescription(baseName);
|
|
40026
40571
|
entry.source = "filename";
|
|
@@ -40032,7 +40577,7 @@ function applyPostContributorFields(entry, file, canonicalName, dirPath) {
|
|
|
40032
40577
|
entry.tags = [...entry.tags ?? [], ...extractDirTagsFromName(canonicalName)];
|
|
40033
40578
|
entry.tags = normalizeTerms(entry.tags ?? []);
|
|
40034
40579
|
entry.aliases = mergeAliases(entry.aliases, buildAliases(canonicalName, entry.tags));
|
|
40035
|
-
entry.filename =
|
|
40580
|
+
entry.filename = path16.basename(file);
|
|
40036
40581
|
}
|
|
40037
40582
|
function normalizeTerms(values) {
|
|
40038
40583
|
const normalized = new Set;
|
|
@@ -40054,7 +40599,7 @@ function buildAliases(name, tags) {
|
|
|
40054
40599
|
return Array.from(aliases);
|
|
40055
40600
|
}
|
|
40056
40601
|
function extractPackageMetadata(dirPath) {
|
|
40057
|
-
const pkgPath =
|
|
40602
|
+
const pkgPath = path16.join(dirPath, "package.json");
|
|
40058
40603
|
if (!fs13.existsSync(pkgPath))
|
|
40059
40604
|
return null;
|
|
40060
40605
|
try {
|
|
@@ -40076,11 +40621,11 @@ function fileNameToDescription(fileName) {
|
|
|
40076
40621
|
return fileName.replace(/[-_]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase().trim();
|
|
40077
40622
|
}
|
|
40078
40623
|
function extractTagsFromPath(filePath, rootDir) {
|
|
40079
|
-
const rel =
|
|
40080
|
-
const parts = rel.split(
|
|
40624
|
+
const rel = path16.relative(rootDir, filePath);
|
|
40625
|
+
const parts = rel.split(path16.sep);
|
|
40081
40626
|
const tags = new Set;
|
|
40082
40627
|
for (const part of parts) {
|
|
40083
|
-
const name = part.replace(
|
|
40628
|
+
const name = part.replace(path16.extname(part), "");
|
|
40084
40629
|
for (const token of name.split(/[-_./\\]+/)) {
|
|
40085
40630
|
const clean = token.toLowerCase().trim();
|
|
40086
40631
|
if (clean && clean.length > 1)
|
|
@@ -40609,13 +41154,13 @@ function isReservedFileName(name) {
|
|
|
40609
41154
|
}
|
|
40610
41155
|
var WIKI_INFRA_FILES = new Set(["schema.md", "index.md", "log.md"]);
|
|
40611
41156
|
function akmStashAbstains(root, absPath) {
|
|
40612
|
-
const relPath =
|
|
40613
|
-
if (!relPath || relPath.startsWith("..") ||
|
|
41157
|
+
const relPath = path17.relative(root, absPath);
|
|
41158
|
+
if (!relPath || relPath.startsWith("..") || path17.isAbsolute(relPath))
|
|
40614
41159
|
return false;
|
|
40615
41160
|
const segments = relPath.split(/[\\/]+/).filter(Boolean);
|
|
40616
41161
|
if (segments.length === 0)
|
|
40617
41162
|
return false;
|
|
40618
|
-
if (segments[0] === "env" && (absPath.endsWith(".env") ||
|
|
41163
|
+
if (segments[0] === "env" && (absPath.endsWith(".env") || path17.basename(absPath) === ".env")) {
|
|
40619
41164
|
if (fs15.existsSync(absPath.replace(/\.env$/, ".sensitive")))
|
|
40620
41165
|
return true;
|
|
40621
41166
|
}
|
|
@@ -40713,7 +41258,7 @@ function recognize2(c, file) {
|
|
|
40713
41258
|
const canonicalName = derived;
|
|
40714
41259
|
const stashDir = stashDirFor(match.type);
|
|
40715
41260
|
const conceptId = stashDir !== undefined ? `${stashDir}/${canonicalName}` : canonicalName;
|
|
40716
|
-
const dirPath =
|
|
41261
|
+
const dirPath = path17.dirname(file.absPath);
|
|
40717
41262
|
const entry = {
|
|
40718
41263
|
name: canonicalName,
|
|
40719
41264
|
type: match.type,
|
|
@@ -40736,13 +41281,13 @@ function recognize2(c, file) {
|
|
|
40736
41281
|
}, match.renderer);
|
|
40737
41282
|
}
|
|
40738
41283
|
function buildOverlayContext(root, relPathInput, raw) {
|
|
40739
|
-
const absPath =
|
|
40740
|
-
const relPath =
|
|
40741
|
-
const ext =
|
|
40742
|
-
const fileName =
|
|
40743
|
-
const parentDirAbs =
|
|
40744
|
-
const parentDir =
|
|
40745
|
-
const relDir =
|
|
41284
|
+
const absPath = path17.join(root, relPathInput);
|
|
41285
|
+
const relPath = path17.relative(root, absPath).replace(/\\/g, "/");
|
|
41286
|
+
const ext = path17.extname(absPath).toLowerCase();
|
|
41287
|
+
const fileName = path17.basename(absPath);
|
|
41288
|
+
const parentDirAbs = path17.dirname(absPath);
|
|
41289
|
+
const parentDir = path17.basename(parentDirAbs);
|
|
41290
|
+
const relDir = path17.dirname(relPath).replace(/\\/g, "/");
|
|
40746
41291
|
const ancestorDirs = relDir === "." ? [] : relDir.split("/").filter((seg) => seg.length > 0);
|
|
40747
41292
|
let cachedFrontmatter;
|
|
40748
41293
|
let frontmatterComputed = false;
|
|
@@ -40783,15 +41328,16 @@ async function validate2(c, changes, ctx) {
|
|
|
40783
41328
|
const type = match?.type;
|
|
40784
41329
|
let parsed;
|
|
40785
41330
|
if (type === "task") {
|
|
40786
|
-
|
|
40787
|
-
|
|
40788
|
-
|
|
40789
|
-
|
|
40790
|
-
|
|
40791
|
-
|
|
40792
|
-
|
|
41331
|
+
const task = parseTaskYaml(raw);
|
|
41332
|
+
if (!task.ok) {
|
|
41333
|
+
diagnostics.push({
|
|
41334
|
+
file: change.path,
|
|
41335
|
+
issue: "invalid-task-yaml",
|
|
41336
|
+
detail: taskYamlParseDetail(task.error),
|
|
41337
|
+
fixed: false
|
|
41338
|
+
});
|
|
40793
41339
|
}
|
|
40794
|
-
parsed = { data, content: raw, frontmatter: null };
|
|
41340
|
+
parsed = { data: task.data, content: raw, frontmatter: null };
|
|
40795
41341
|
} else {
|
|
40796
41342
|
const p = parseFrontmatter(raw);
|
|
40797
41343
|
parsed = { data: p.data, content: p.content, frontmatter: p.frontmatter };
|
|
@@ -40846,18 +41392,18 @@ var akmAdapter = {
|
|
|
40846
41392
|
const rest = posix.slice(slash + 1);
|
|
40847
41393
|
const type = stashDirToType(head);
|
|
40848
41394
|
if (type !== undefined && rest.length > 0) {
|
|
40849
|
-
const typeDir =
|
|
41395
|
+
const typeDir = path17.join(c.root, head);
|
|
40850
41396
|
return assetPathForName(type, typeDir, rest);
|
|
40851
41397
|
}
|
|
40852
41398
|
}
|
|
40853
|
-
return
|
|
41399
|
+
return path17.join(c.root, `${posix}.md`);
|
|
40854
41400
|
},
|
|
40855
41401
|
directoryList(_c) {
|
|
40856
41402
|
return [...new Set(stashDirNames())];
|
|
40857
41403
|
},
|
|
40858
41404
|
looksLikeRoot(root) {
|
|
40859
41405
|
try {
|
|
40860
|
-
if (fs15.statSync(
|
|
41406
|
+
if (fs15.statSync(path17.join(root, ".stash")).isDirectory())
|
|
40861
41407
|
return true;
|
|
40862
41408
|
} catch {}
|
|
40863
41409
|
const ownedDirNames = new Set(stashDirNames());
|
|
@@ -40875,10 +41421,10 @@ var akmAdapter = {
|
|
|
40875
41421
|
return false;
|
|
40876
41422
|
const expectedType = stashDirToType(only.name);
|
|
40877
41423
|
try {
|
|
40878
|
-
const markdown = fs15.readdirSync(
|
|
41424
|
+
const markdown = fs15.readdirSync(path17.join(root, only.name), { withFileTypes: true }).find((entry) => entry.isFile() && entry.name.toLowerCase().endsWith(".md"));
|
|
40879
41425
|
if (!markdown)
|
|
40880
41426
|
return true;
|
|
40881
|
-
const data = parseFrontmatter(fs15.readFileSync(
|
|
41427
|
+
const data = parseFrontmatter(fs15.readFileSync(path17.join(root, only.name, markdown.name), "utf8")).data;
|
|
40882
41428
|
const declaredType = typeof data.type === "string" ? data.type.trim() : "";
|
|
40883
41429
|
return !declaredType || declaredType === expectedType;
|
|
40884
41430
|
} catch {
|
|
@@ -40889,9 +41435,9 @@ var akmAdapter = {
|
|
|
40889
41435
|
|
|
40890
41436
|
// src/core/adapter/adapters/akm-task-adapter.ts
|
|
40891
41437
|
import fs16 from "fs";
|
|
40892
|
-
import
|
|
41438
|
+
import path18 from "path";
|
|
40893
41439
|
var COMPONENT_ID2 = "main";
|
|
40894
|
-
var TASK_EXT =
|
|
41440
|
+
var TASK_EXT = TASK_EXTENSION;
|
|
40895
41441
|
var TARGET_KEYS = ["prompt", "workflow", "command"];
|
|
40896
41442
|
var MAX_CONTENT_CHARS2 = 1e5;
|
|
40897
41443
|
function toPosix3(p) {
|
|
@@ -40916,14 +41462,6 @@ function recognize3(c, file) {
|
|
|
40916
41462
|
content: raw.length > MAX_CONTENT_CHARS2 ? raw.slice(0, MAX_CONTENT_CHARS2) : raw
|
|
40917
41463
|
};
|
|
40918
41464
|
}
|
|
40919
|
-
function parseTaskYaml(raw) {
|
|
40920
|
-
try {
|
|
40921
|
-
const doc = $parse(raw);
|
|
40922
|
-
if (doc && typeof doc === "object" && !Array.isArray(doc))
|
|
40923
|
-
return doc;
|
|
40924
|
-
} catch {}
|
|
40925
|
-
return {};
|
|
40926
|
-
}
|
|
40927
41465
|
function taskDiagnostics2(relPath, data) {
|
|
40928
41466
|
if (Object.keys(data).length === 0)
|
|
40929
41467
|
return [];
|
|
@@ -40947,21 +41485,41 @@ async function validate3(_c, changes, ctx) {
|
|
|
40947
41485
|
const raw = change.after ?? await ctx.readFile(change.path);
|
|
40948
41486
|
if (typeof raw !== "string")
|
|
40949
41487
|
continue;
|
|
40950
|
-
|
|
41488
|
+
const ext = path18.extname(change.path).toLowerCase();
|
|
41489
|
+
if (ext !== TASK_EXT && ext !== TASK_NEAR_MISS_EXTENSION)
|
|
40951
41490
|
continue;
|
|
40952
|
-
|
|
41491
|
+
const relPath = toPosix3(change.path);
|
|
41492
|
+
if (ext === TASK_NEAR_MISS_EXTENSION) {
|
|
41493
|
+
diagnostics.push({
|
|
41494
|
+
file: relPath,
|
|
41495
|
+
issue: "invalid-task-yaml",
|
|
41496
|
+
detail: taskExtensionDetail(relPath),
|
|
41497
|
+
fixed: false
|
|
41498
|
+
});
|
|
41499
|
+
}
|
|
41500
|
+
const parsed = parseTaskYaml(raw);
|
|
41501
|
+
if (!parsed.ok) {
|
|
41502
|
+
diagnostics.push({
|
|
41503
|
+
file: relPath,
|
|
41504
|
+
issue: "invalid-task-yaml",
|
|
41505
|
+
detail: taskYamlParseDetail(parsed.error),
|
|
41506
|
+
fixed: false
|
|
41507
|
+
});
|
|
41508
|
+
continue;
|
|
41509
|
+
}
|
|
41510
|
+
diagnostics.push(...taskDiagnostics2(relPath, parsed.data));
|
|
40953
41511
|
}
|
|
40954
41512
|
return diagnostics;
|
|
40955
41513
|
}
|
|
40956
41514
|
var akmTaskAdapter = {
|
|
40957
41515
|
id: "akm-task",
|
|
40958
41516
|
version: "0.9.0",
|
|
40959
|
-
extensions: [TASK_EXT],
|
|
41517
|
+
extensions: [TASK_EXT, TASK_NEAR_MISS_EXTENSION],
|
|
40960
41518
|
recognize: recognize3,
|
|
40961
41519
|
validate: validate3,
|
|
40962
41520
|
placeNew(c, conceptId) {
|
|
40963
41521
|
const posix = toPosix3(conceptId);
|
|
40964
|
-
return
|
|
41522
|
+
return path18.join(c.root, /\.yml$/i.test(posix) ? posix : `${posix}.yml`);
|
|
40965
41523
|
},
|
|
40966
41524
|
directoryList() {
|
|
40967
41525
|
return ["."];
|
|
@@ -40974,15 +41532,15 @@ var akmTaskAdapter = {
|
|
|
40974
41532
|
return false;
|
|
40975
41533
|
}
|
|
40976
41534
|
for (const entry of entries) {
|
|
40977
|
-
if (!entry.isFile() ||
|
|
41535
|
+
if (!entry.isFile() || path18.extname(entry.name).toLowerCase() !== TASK_EXT)
|
|
40978
41536
|
continue;
|
|
40979
41537
|
let raw;
|
|
40980
41538
|
try {
|
|
40981
|
-
raw = fs16.readFileSync(
|
|
41539
|
+
raw = fs16.readFileSync(path18.join(root, entry.name), "utf8");
|
|
40982
41540
|
} catch {
|
|
40983
41541
|
continue;
|
|
40984
41542
|
}
|
|
40985
|
-
const data = parseTaskYaml(raw);
|
|
41543
|
+
const { data } = parseTaskYaml(raw);
|
|
40986
41544
|
if (typeof data.schedule === "string" && data.schedule.trim() !== "")
|
|
40987
41545
|
return true;
|
|
40988
41546
|
}
|
|
@@ -40992,7 +41550,7 @@ var akmTaskAdapter = {
|
|
|
40992
41550
|
|
|
40993
41551
|
// src/core/adapter/adapters/akm-workflow-adapter.ts
|
|
40994
41552
|
import fs17 from "fs";
|
|
40995
|
-
import
|
|
41553
|
+
import path19 from "path";
|
|
40996
41554
|
var COMPONENT_ID3 = "main";
|
|
40997
41555
|
var WORKFLOW_EXTS = new Set([".md"]);
|
|
40998
41556
|
var MAX_CONTENT_CHARS3 = 1e5;
|
|
@@ -41050,8 +41608,8 @@ async function validate4(c, changes, ctx) {
|
|
|
41050
41608
|
const raw = change.after ?? await ctx.readFile(change.path);
|
|
41051
41609
|
if (typeof raw !== "string")
|
|
41052
41610
|
continue;
|
|
41053
|
-
const ext =
|
|
41054
|
-
if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(
|
|
41611
|
+
const ext = path19.extname(change.path).toLowerCase();
|
|
41612
|
+
if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(path19.basename(change.path)) || !isWorkflowFile(raw))
|
|
41055
41613
|
continue;
|
|
41056
41614
|
const relPath = toPosix4(change.path);
|
|
41057
41615
|
const p = parseFrontmatter(raw);
|
|
@@ -41074,12 +41632,12 @@ function hasTopLevelWorkflowFile(root, entries) {
|
|
|
41074
41632
|
for (const entry of entries) {
|
|
41075
41633
|
if (!entry.isFile())
|
|
41076
41634
|
continue;
|
|
41077
|
-
const ext =
|
|
41635
|
+
const ext = path19.extname(entry.name).toLowerCase();
|
|
41078
41636
|
if (!WORKFLOW_EXTS.has(ext) || isReservedDocFile(entry.name))
|
|
41079
41637
|
continue;
|
|
41080
41638
|
let raw;
|
|
41081
41639
|
try {
|
|
41082
|
-
raw = fs17.readFileSync(
|
|
41640
|
+
raw = fs17.readFileSync(path19.join(root, entry.name), "utf8");
|
|
41083
41641
|
} catch {
|
|
41084
41642
|
continue;
|
|
41085
41643
|
}
|
|
@@ -41097,8 +41655,8 @@ var akmWorkflowAdapter = {
|
|
|
41097
41655
|
placeNew(c, conceptId) {
|
|
41098
41656
|
const posix = toPosix4(conceptId);
|
|
41099
41657
|
if (/\.md$/i.test(posix))
|
|
41100
|
-
return
|
|
41101
|
-
return
|
|
41658
|
+
return path19.join(c.root, posix);
|
|
41659
|
+
return path19.join(c.root, `${posix}.md`);
|
|
41102
41660
|
},
|
|
41103
41661
|
directoryList() {
|
|
41104
41662
|
return ["."];
|
|
@@ -41116,10 +41674,10 @@ var akmWorkflowAdapter = {
|
|
|
41116
41674
|
|
|
41117
41675
|
// src/core/adapter/adapters/claude-adapter.ts
|
|
41118
41676
|
import fs18 from "fs";
|
|
41119
|
-
import
|
|
41677
|
+
import path21 from "path";
|
|
41120
41678
|
|
|
41121
41679
|
// src/core/adapter/adapters/tool-dir-shared.ts
|
|
41122
|
-
import
|
|
41680
|
+
import path20 from "path";
|
|
41123
41681
|
var RESERVED_FILES2 = new Set(["index.md", "log.md"]);
|
|
41124
41682
|
var MAX_CONTENT_CHARS4 = 1e5;
|
|
41125
41683
|
var CANONICAL_COMMAND_DIR = "commands";
|
|
@@ -41144,7 +41702,7 @@ function classify(relPath, layout) {
|
|
|
41144
41702
|
return { type: "instruction", conceptId: layout.instructionConceptId, name: layout.instructionConceptId };
|
|
41145
41703
|
}
|
|
41146
41704
|
const head = segs[0];
|
|
41147
|
-
const ext =
|
|
41705
|
+
const ext = path20.extname(base).toLowerCase();
|
|
41148
41706
|
if (layout.skillDirs.has(head)) {
|
|
41149
41707
|
if (segs.length >= 3 && base === SKILL_MANIFEST2) {
|
|
41150
41708
|
return { type: "skill", conceptId: `${segs[0]}/${segs[1]}`, name: segs[1] };
|
|
@@ -41193,19 +41751,19 @@ function recognizeToolDir(layout, c, file) {
|
|
|
41193
41751
|
function placeNewToolDir(layout, c, conceptId) {
|
|
41194
41752
|
const posix = toPosix5(conceptId);
|
|
41195
41753
|
if (posix === layout.instructionConceptId)
|
|
41196
|
-
return
|
|
41754
|
+
return path20.join(c.root, layout.instructionFile);
|
|
41197
41755
|
const segs = posix.split("/").filter((s) => s.length > 0);
|
|
41198
41756
|
const head = segs[0];
|
|
41199
41757
|
const rest = segs.slice(1).join("/");
|
|
41200
41758
|
if (rest.length > 0) {
|
|
41201
41759
|
if (layout.skillDirs.has(head))
|
|
41202
|
-
return
|
|
41760
|
+
return path20.join(c.root, CANONICAL_SKILL_DIR, rest, SKILL_MANIFEST2);
|
|
41203
41761
|
if (layout.commandDirs.has(head))
|
|
41204
|
-
return
|
|
41762
|
+
return path20.join(c.root, CANONICAL_COMMAND_DIR, `${rest}.md`);
|
|
41205
41763
|
if (layout.agentDirs.has(head))
|
|
41206
|
-
return
|
|
41764
|
+
return path20.join(c.root, CANONICAL_AGENT_DIR, `${rest}.md`);
|
|
41207
41765
|
}
|
|
41208
|
-
return
|
|
41766
|
+
return path20.join(c.root, `${posix}.md`);
|
|
41209
41767
|
}
|
|
41210
41768
|
function nameOrSignalDiagnostics(type, relPath, data, body) {
|
|
41211
41769
|
if (nonEmptyString2(data.name) !== undefined || nonEmptyString2(data.description) !== undefined)
|
|
@@ -41232,7 +41790,7 @@ async function validateToolDir(layout, c, changes, ctx) {
|
|
|
41232
41790
|
if (typeof raw !== "string")
|
|
41233
41791
|
continue;
|
|
41234
41792
|
const relPath = toPosix5(change.path);
|
|
41235
|
-
diagnostics.push(...await skillDirectoryDiagnostics(relPath, seenSkillDirs, ctx));
|
|
41793
|
+
diagnostics.push(...await skillDirectoryDiagnostics(relPath, seenSkillDirs, ctx, layout.skillDirs));
|
|
41236
41794
|
const cls = classify(change.path, layout);
|
|
41237
41795
|
if (cls === null)
|
|
41238
41796
|
continue;
|
|
@@ -41277,18 +41835,18 @@ function dirExists(p) {
|
|
|
41277
41835
|
}
|
|
41278
41836
|
function claudeLooksLikeRoot(root) {
|
|
41279
41837
|
try {
|
|
41280
|
-
if (!fs18.existsSync(
|
|
41838
|
+
if (!fs18.existsSync(path21.join(root, "CLAUDE.md")))
|
|
41281
41839
|
return false;
|
|
41282
41840
|
} catch {
|
|
41283
41841
|
return false;
|
|
41284
41842
|
}
|
|
41285
|
-
return ["commands", "agents", "skills"].some((d) => dirExists(
|
|
41843
|
+
return ["commands", "agents", "skills"].some((d) => dirExists(path21.join(root, d)));
|
|
41286
41844
|
}
|
|
41287
41845
|
var claudeAdapter = makeToolDirAdapter(LAYOUT, claudeLooksLikeRoot);
|
|
41288
41846
|
|
|
41289
41847
|
// src/core/adapter/adapters/dotenv-adapter.ts
|
|
41290
41848
|
import fs19 from "fs";
|
|
41291
|
-
import
|
|
41849
|
+
import path22 from "path";
|
|
41292
41850
|
var COMPONENT_ID4 = "main";
|
|
41293
41851
|
var ENV_DIR = "env";
|
|
41294
41852
|
var SECRETS_DIR = "secrets";
|
|
@@ -41394,10 +41952,10 @@ var dotenvAdapter = {
|
|
|
41394
41952
|
const rest = posix.slice(slash + 1);
|
|
41395
41953
|
const type = typeForStashDir(head);
|
|
41396
41954
|
if ((type === "env" || type === "secret") && rest.length > 0) {
|
|
41397
|
-
return assetPathForName(type,
|
|
41955
|
+
return assetPathForName(type, path22.join(c.root, head), rest);
|
|
41398
41956
|
}
|
|
41399
41957
|
}
|
|
41400
|
-
return
|
|
41958
|
+
return path22.join(c.root, posix);
|
|
41401
41959
|
},
|
|
41402
41960
|
directoryList() {
|
|
41403
41961
|
return [ENV_DIR, SECRETS_DIR];
|
|
@@ -41419,7 +41977,7 @@ var dotenvAdapter = {
|
|
|
41419
41977
|
};
|
|
41420
41978
|
|
|
41421
41979
|
// src/core/adapter/adapters/generic-files-adapter.ts
|
|
41422
|
-
import
|
|
41980
|
+
import path23 from "path";
|
|
41423
41981
|
var COMPONENT_ID5 = "main";
|
|
41424
41982
|
var DOCUMENT_EXTENSIONS = new Set([".md", ".markdown", ".txt", ".text"]);
|
|
41425
41983
|
var RESERVED_FILES3 = new Set(["index.md", "log.md"]);
|
|
@@ -41490,8 +42048,8 @@ var genericFilesAdapter = {
|
|
|
41490
42048
|
validate: validate6,
|
|
41491
42049
|
placeNew(c, conceptId) {
|
|
41492
42050
|
const posix = toPosix7(conceptId);
|
|
41493
|
-
const hasExt =
|
|
41494
|
-
return
|
|
42051
|
+
const hasExt = path23.extname(posix) !== "";
|
|
42052
|
+
return path23.join(c.root, hasExt ? posix : `${posix}.md`);
|
|
41495
42053
|
},
|
|
41496
42054
|
looksLikeRoot() {
|
|
41497
42055
|
return false;
|
|
@@ -41500,7 +42058,7 @@ var genericFilesAdapter = {
|
|
|
41500
42058
|
|
|
41501
42059
|
// src/core/adapter/adapters/llm-wiki-adapter.ts
|
|
41502
42060
|
import fs20 from "fs";
|
|
41503
|
-
import
|
|
42061
|
+
import path24 from "path";
|
|
41504
42062
|
var WIKI_COMPONENT_ID = "main";
|
|
41505
42063
|
var WIKI_SOURCE_TYPE = "wiki-source";
|
|
41506
42064
|
var DEFAULT_PAGE_KIND = "note";
|
|
@@ -41562,7 +42120,7 @@ function resolveXref(xref, bundleId) {
|
|
|
41562
42120
|
return target.length > 0 ? target : null;
|
|
41563
42121
|
}
|
|
41564
42122
|
function resolveBodyLinks(body, fileRelPath) {
|
|
41565
|
-
const dir =
|
|
42123
|
+
const dir = path24.posix.dirname(toPosix8(fileRelPath));
|
|
41566
42124
|
const linkRe = /\[[^\]]*\]\(([^)]+)\)/g;
|
|
41567
42125
|
const out = [];
|
|
41568
42126
|
const seen = new Set;
|
|
@@ -41588,10 +42146,10 @@ function resolveBodyLinks(body, fileRelPath) {
|
|
|
41588
42146
|
continue;
|
|
41589
42147
|
let resolved;
|
|
41590
42148
|
if (target.startsWith("/")) {
|
|
41591
|
-
resolved =
|
|
42149
|
+
resolved = path24.posix.normalize(target.slice(1));
|
|
41592
42150
|
} else {
|
|
41593
42151
|
const base = dir === "." ? "" : dir;
|
|
41594
|
-
resolved =
|
|
42152
|
+
resolved = path24.posix.normalize(path24.posix.join(base, target));
|
|
41595
42153
|
}
|
|
41596
42154
|
if (resolved.startsWith("../") || resolved === ".." || resolved.startsWith("/"))
|
|
41597
42155
|
continue;
|
|
@@ -41772,16 +42330,16 @@ var llmWikiAdapter = {
|
|
|
41772
42330
|
recognize: recognize7,
|
|
41773
42331
|
validate: validate7,
|
|
41774
42332
|
placeNew(c, conceptId) {
|
|
41775
|
-
return
|
|
42333
|
+
return path24.join(c.root, `${conceptId}.md`);
|
|
41776
42334
|
},
|
|
41777
42335
|
directoryList(_c) {
|
|
41778
42336
|
return ["."];
|
|
41779
42337
|
},
|
|
41780
42338
|
looksLikeRoot(root) {
|
|
41781
42339
|
try {
|
|
41782
|
-
if (!fs20.existsSync(
|
|
42340
|
+
if (!fs20.existsSync(path24.join(root, "schema.md")))
|
|
41783
42341
|
return false;
|
|
41784
|
-
return fs20.statSync(
|
|
42342
|
+
return fs20.statSync(path24.join(root, PAGES_SUBDIR)).isDirectory();
|
|
41785
42343
|
} catch {
|
|
41786
42344
|
return false;
|
|
41787
42345
|
}
|
|
@@ -41790,7 +42348,7 @@ var llmWikiAdapter = {
|
|
|
41790
42348
|
|
|
41791
42349
|
// src/core/adapter/adapters/okf-adapter.ts
|
|
41792
42350
|
import fs21 from "fs";
|
|
41793
|
-
import
|
|
42351
|
+
import path25 from "path";
|
|
41794
42352
|
var CONSUMED_FRONTMATTER_KEYS = [
|
|
41795
42353
|
"type",
|
|
41796
42354
|
"title",
|
|
@@ -41804,11 +42362,11 @@ var CONSUMED_FRONTMATTER_KEYS = [
|
|
|
41804
42362
|
"stale_after",
|
|
41805
42363
|
"okf_version"
|
|
41806
42364
|
];
|
|
41807
|
-
function
|
|
42365
|
+
function isPlainObject3(value) {
|
|
41808
42366
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
41809
42367
|
}
|
|
41810
42368
|
function parseActorMapping(value) {
|
|
41811
|
-
if (!
|
|
42369
|
+
if (!isPlainObject3(value))
|
|
41812
42370
|
return;
|
|
41813
42371
|
const by = nonEmptyString2(value.by);
|
|
41814
42372
|
if (by === undefined)
|
|
@@ -41833,7 +42391,7 @@ function parseOkfSources(value) {
|
|
|
41833
42391
|
return;
|
|
41834
42392
|
const out = [];
|
|
41835
42393
|
for (const item of value) {
|
|
41836
|
-
if (!
|
|
42394
|
+
if (!isPlainObject3(item))
|
|
41837
42395
|
continue;
|
|
41838
42396
|
const resource = nonEmptyString2(item.resource);
|
|
41839
42397
|
if (resource === undefined)
|
|
@@ -41870,7 +42428,7 @@ function isReservedFileName2(name) {
|
|
|
41870
42428
|
return RESERVED_FILES4.has(name.toLowerCase());
|
|
41871
42429
|
}
|
|
41872
42430
|
function resolveOkfLinks(body, fileRelPath) {
|
|
41873
|
-
const dir =
|
|
42431
|
+
const dir = path25.posix.dirname(toPosix9(fileRelPath));
|
|
41874
42432
|
const definitions = new Map;
|
|
41875
42433
|
for (const match of body.matchAll(/^\s*\[([^\]]+)\]:\s*(\S+)/gm)) {
|
|
41876
42434
|
definitions.set(match[1].trim().toLowerCase(), match[2]);
|
|
@@ -41908,10 +42466,10 @@ function resolveOkfLinks(body, fileRelPath) {
|
|
|
41908
42466
|
continue;
|
|
41909
42467
|
let resolved;
|
|
41910
42468
|
if (target.startsWith("/")) {
|
|
41911
|
-
resolved =
|
|
42469
|
+
resolved = path25.posix.normalize(target.slice(1));
|
|
41912
42470
|
} else {
|
|
41913
42471
|
const base = dir === "." ? "" : dir;
|
|
41914
|
-
resolved =
|
|
42472
|
+
resolved = path25.posix.normalize(path25.posix.join(base, target));
|
|
41915
42473
|
}
|
|
41916
42474
|
if (resolved.startsWith("../") || resolved === ".." || resolved.startsWith("/"))
|
|
41917
42475
|
continue;
|
|
@@ -41939,7 +42497,7 @@ function recognize8(c, file) {
|
|
|
41939
42497
|
const description = nonEmptyString2(data.description);
|
|
41940
42498
|
const tags = readTags2(data.tags);
|
|
41941
42499
|
const links = resolveOkfLinks(body, file.relPath);
|
|
41942
|
-
const generatedMapping =
|
|
42500
|
+
const generatedMapping = isPlainObject3(data.generated) ? data.generated : undefined;
|
|
41943
42501
|
const generatedAt = generatedMapping ? nonEmptyString2(generatedMapping.at) : undefined;
|
|
41944
42502
|
const generatedBy = generatedMapping ? nonEmptyString2(generatedMapping.by) : undefined;
|
|
41945
42503
|
const legacyTimestamp = nonEmptyString2(data.timestamp);
|
|
@@ -42041,7 +42599,7 @@ var okfAdapter = {
|
|
|
42041
42599
|
return ["."];
|
|
42042
42600
|
},
|
|
42043
42601
|
looksLikeRoot(root) {
|
|
42044
|
-
if (fs21.existsSync(
|
|
42602
|
+
if (fs21.existsSync(path25.join(root, "index.md")))
|
|
42045
42603
|
return true;
|
|
42046
42604
|
const stack = [root];
|
|
42047
42605
|
while (stack.length > 0) {
|
|
@@ -42057,7 +42615,7 @@ var okfAdapter = {
|
|
|
42057
42615
|
for (const entry of entries) {
|
|
42058
42616
|
if (entry.isSymbolicLink() || entry.name === ".git")
|
|
42059
42617
|
continue;
|
|
42060
|
-
const absolute =
|
|
42618
|
+
const absolute = path25.join(current, entry.name);
|
|
42061
42619
|
if (entry.isDirectory()) {
|
|
42062
42620
|
stack.push(absolute);
|
|
42063
42621
|
continue;
|
|
@@ -42075,7 +42633,7 @@ var okfAdapter = {
|
|
|
42075
42633
|
|
|
42076
42634
|
// src/core/adapter/adapters/opencode-adapter.ts
|
|
42077
42635
|
import fs22 from "fs";
|
|
42078
|
-
import
|
|
42636
|
+
import path26 from "path";
|
|
42079
42637
|
var LAYOUT2 = {
|
|
42080
42638
|
adapterId: "opencode",
|
|
42081
42639
|
componentId: ".opencode",
|
|
@@ -42102,17 +42660,17 @@ function dirExists2(p) {
|
|
|
42102
42660
|
}
|
|
42103
42661
|
}
|
|
42104
42662
|
function opencodeLooksLikeRoot(root) {
|
|
42105
|
-
if (CONFIG_FILES.some((f) => fileExists(
|
|
42663
|
+
if (CONFIG_FILES.some((f) => fileExists(path26.join(root, f))))
|
|
42106
42664
|
return true;
|
|
42107
|
-
if (!fileExists(
|
|
42665
|
+
if (!fileExists(path26.join(root, "AGENTS.md")))
|
|
42108
42666
|
return false;
|
|
42109
|
-
return TOOL_DIRS.some((d) => dirExists2(
|
|
42667
|
+
return TOOL_DIRS.some((d) => dirExists2(path26.join(root, d)));
|
|
42110
42668
|
}
|
|
42111
42669
|
var opencodeAdapter = makeToolDirAdapter(LAYOUT2, opencodeLooksLikeRoot);
|
|
42112
42670
|
|
|
42113
42671
|
// src/core/adapter/adapters/website-snapshot-adapter.ts
|
|
42114
42672
|
import fs23 from "fs";
|
|
42115
|
-
import
|
|
42673
|
+
import path27 from "path";
|
|
42116
42674
|
var COMPONENT_ID6 = "main";
|
|
42117
42675
|
var PAGES_PREFIX = "stash/knowledge/";
|
|
42118
42676
|
var MANIFEST_FILE = "manifest.json";
|
|
@@ -42205,7 +42763,7 @@ var websiteSnapshotAdapter = {
|
|
|
42205
42763
|
looksLikeRoot(root) {
|
|
42206
42764
|
let raw;
|
|
42207
42765
|
try {
|
|
42208
|
-
raw = fs23.readFileSync(
|
|
42766
|
+
raw = fs23.readFileSync(path27.join(root, MANIFEST_FILE), "utf8");
|
|
42209
42767
|
} catch {
|
|
42210
42768
|
return false;
|
|
42211
42769
|
}
|
|
@@ -42247,7 +42805,7 @@ function expandTilde(p) {
|
|
|
42247
42805
|
if (p === "~")
|
|
42248
42806
|
return os.homedir();
|
|
42249
42807
|
if (p.startsWith("~/") || p.startsWith("~\\"))
|
|
42250
|
-
return
|
|
42808
|
+
return path28.join(os.homedir(), p.slice(2));
|
|
42251
42809
|
return p;
|
|
42252
42810
|
}
|
|
42253
42811
|
function readString(value) {
|
|
@@ -42292,7 +42850,7 @@ function oldConfigMigratableSources(raw, pathResolutionBase = process.cwd()) {
|
|
|
42292
42850
|
const p = readString(primaryEntry.path);
|
|
42293
42851
|
if (descriptor) {
|
|
42294
42852
|
out.push({
|
|
42295
|
-
derivationPath: p ?
|
|
42853
|
+
derivationPath: p ? path28.resolve(pathResolutionBase, expandTilde(p)) : readString(primaryEntry.url) ?? "",
|
|
42296
42854
|
registryId: readString(primaryEntry.name),
|
|
42297
42855
|
writable: typeof primaryEntry.writable === "boolean" ? primaryEntry.writable : undefined,
|
|
42298
42856
|
...typeof primaryEntry.enabled === "boolean" ? { enabled: primaryEntry.enabled } : {},
|
|
@@ -42303,7 +42861,7 @@ function oldConfigMigratableSources(raw, pathResolutionBase = process.cwd()) {
|
|
|
42303
42861
|
}
|
|
42304
42862
|
if (!out.some((source) => source.primary) && stashDir) {
|
|
42305
42863
|
out.push({
|
|
42306
|
-
derivationPath:
|
|
42864
|
+
derivationPath: path28.resolve(pathResolutionBase, expandTilde(stashDir)),
|
|
42307
42865
|
writable: true,
|
|
42308
42866
|
primary: true,
|
|
42309
42867
|
descriptor: { path: stashDir }
|
|
@@ -42317,7 +42875,7 @@ function oldConfigMigratableSources(raw, pathResolutionBase = process.cwd()) {
|
|
|
42317
42875
|
continue;
|
|
42318
42876
|
const p = readString(entry.path);
|
|
42319
42877
|
out.push({
|
|
42320
|
-
derivationPath: p ?
|
|
42878
|
+
derivationPath: p ? path28.resolve(pathResolutionBase, expandTilde(p)) : readString(entry.url) ?? "",
|
|
42321
42879
|
registryId: readString(entry.name),
|
|
42322
42880
|
writable: typeof entry.writable === "boolean" ? entry.writable : undefined,
|
|
42323
42881
|
...typeof entry.enabled === "boolean" ? { enabled: entry.enabled } : {},
|
|
@@ -42331,7 +42889,7 @@ function oldConfigMigratableSources(raw, pathResolutionBase = process.cwd()) {
|
|
|
42331
42889
|
const source = readString(entry.source);
|
|
42332
42890
|
const ref = readString(entry.ref);
|
|
42333
42891
|
const descriptor = source ? installedSourceDescriptor(source, ref, stashRoot) : { path: stashRoot };
|
|
42334
|
-
const resolvedRoot =
|
|
42892
|
+
const resolvedRoot = path28.resolve(pathResolutionBase, expandTilde(stashRoot));
|
|
42335
42893
|
const needsLock = (("git" in descriptor) || ("npm" in descriptor)) && !!source && !!ref;
|
|
42336
42894
|
out.push({
|
|
42337
42895
|
derivationPath: resolvedRoot,
|
|
@@ -42346,8 +42904,8 @@ function oldConfigMigratableSources(raw, pathResolutionBase = process.cwd()) {
|
|
|
42346
42904
|
const byPath = new Map;
|
|
42347
42905
|
for (const source of out) {
|
|
42348
42906
|
let pathIdentity;
|
|
42349
|
-
if (
|
|
42350
|
-
const resolved =
|
|
42907
|
+
if (path28.isAbsolute(source.derivationPath)) {
|
|
42908
|
+
const resolved = path28.resolve(source.derivationPath);
|
|
42351
42909
|
try {
|
|
42352
42910
|
pathIdentity = fs24.realpathSync(resolved);
|
|
42353
42911
|
} catch {
|
|
@@ -42479,14 +43037,14 @@ function generateTargetConfig(raw, currentConfigVersion) {
|
|
|
42479
43037
|
import { randomBytes } from "crypto";
|
|
42480
43038
|
import fs27 from "fs";
|
|
42481
43039
|
import os3 from "os";
|
|
42482
|
-
import
|
|
43040
|
+
import path31 from "path";
|
|
42483
43041
|
init_common();
|
|
42484
43042
|
init_warn();
|
|
42485
43043
|
|
|
42486
43044
|
// scripts/akm-migrate/migrate/legacy/legacy-layout.ts
|
|
42487
43045
|
import fs25 from "fs";
|
|
42488
43046
|
import os2 from "os";
|
|
42489
|
-
import
|
|
43047
|
+
import path29 from "path";
|
|
42490
43048
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
42491
43049
|
|
|
42492
43050
|
class LegacyResolverError extends Error {
|
|
@@ -42545,9 +43103,9 @@ function toPosix11(input) {
|
|
|
42545
43103
|
return input.replace(/\\/g, "/");
|
|
42546
43104
|
}
|
|
42547
43105
|
var workflowSpec2 = {
|
|
42548
|
-
isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS2.includes(
|
|
43106
|
+
isRelevantFile: (fileName) => WORKFLOW_EXTENSIONS2.includes(path29.extname(fileName).toLowerCase()),
|
|
42549
43107
|
toCanonicalName: (typeRoot, filePath) => {
|
|
42550
|
-
const rel = toPosix11(
|
|
43108
|
+
const rel = toPosix11(path29.relative(typeRoot, filePath));
|
|
42551
43109
|
for (const ext of WORKFLOW_EXTENSIONS2) {
|
|
42552
43110
|
if (rel.toLowerCase().endsWith(ext))
|
|
42553
43111
|
return rel.slice(0, -ext.length);
|
|
@@ -42558,43 +43116,43 @@ var workflowSpec2 = {
|
|
|
42558
43116
|
const lower = name.toLowerCase();
|
|
42559
43117
|
for (const ext of WORKFLOW_EXTENSIONS2) {
|
|
42560
43118
|
if (lower.endsWith(ext))
|
|
42561
|
-
return
|
|
43119
|
+
return path29.join(typeRoot, name);
|
|
42562
43120
|
}
|
|
42563
43121
|
for (const ext of WORKFLOW_EXTENSIONS2) {
|
|
42564
|
-
const candidate =
|
|
43122
|
+
const candidate = path29.join(typeRoot, `${name}${ext}`);
|
|
42565
43123
|
if (fs25.existsSync(candidate))
|
|
42566
43124
|
return candidate;
|
|
42567
43125
|
}
|
|
42568
|
-
return
|
|
43126
|
+
return path29.join(typeRoot, `${name}.md`);
|
|
42569
43127
|
}
|
|
42570
43128
|
};
|
|
42571
43129
|
var markdownSpec2 = {
|
|
42572
|
-
isRelevantFile: (fileName) =>
|
|
43130
|
+
isRelevantFile: (fileName) => path29.extname(fileName).toLowerCase() === ".md",
|
|
42573
43131
|
toCanonicalName: (typeRoot, filePath) => {
|
|
42574
|
-
const rel = toPosix11(
|
|
43132
|
+
const rel = toPosix11(path29.relative(typeRoot, filePath));
|
|
42575
43133
|
return rel.endsWith(".md") ? rel.slice(0, -3) : rel;
|
|
42576
43134
|
},
|
|
42577
43135
|
toAssetPath: (typeRoot, name) => {
|
|
42578
43136
|
const withExt = name.endsWith(".md") ? name : `${name}.md`;
|
|
42579
|
-
return
|
|
43137
|
+
return path29.join(typeRoot, withExt);
|
|
42580
43138
|
}
|
|
42581
43139
|
};
|
|
42582
43140
|
var scriptSpec2 = {
|
|
42583
|
-
isRelevantFile: (fileName) => SCRIPT_EXTENSIONS2.has(
|
|
42584
|
-
toCanonicalName: (typeRoot, filePath) => toPosix11(
|
|
42585
|
-
toAssetPath: (typeRoot, name) =>
|
|
43141
|
+
isRelevantFile: (fileName) => SCRIPT_EXTENSIONS2.has(path29.extname(fileName).toLowerCase()),
|
|
43142
|
+
toCanonicalName: (typeRoot, filePath) => toPosix11(path29.relative(typeRoot, filePath)),
|
|
43143
|
+
toAssetPath: (typeRoot, name) => path29.join(typeRoot, name)
|
|
42586
43144
|
};
|
|
42587
43145
|
var ASSET_SPECS_INTERNAL = {
|
|
42588
43146
|
skill: {
|
|
42589
43147
|
stashDir: "skills",
|
|
42590
43148
|
isRelevantFile: (fileName) => fileName === "SKILL.md",
|
|
42591
43149
|
toCanonicalName: (typeRoot, filePath) => {
|
|
42592
|
-
const relDir = toPosix11(
|
|
43150
|
+
const relDir = toPosix11(path29.dirname(path29.relative(typeRoot, filePath)));
|
|
42593
43151
|
if (!relDir || relDir === ".")
|
|
42594
43152
|
return;
|
|
42595
43153
|
return relDir;
|
|
42596
43154
|
},
|
|
42597
|
-
toAssetPath: (typeRoot, name) =>
|
|
43155
|
+
toAssetPath: (typeRoot, name) => path29.join(typeRoot, name, "SKILL.md")
|
|
42598
43156
|
},
|
|
42599
43157
|
command: { stashDir: "commands", ...markdownSpec2 },
|
|
42600
43158
|
agent: { stashDir: "agents", ...markdownSpec2 },
|
|
@@ -42606,10 +43164,10 @@ var ASSET_SPECS_INTERNAL = {
|
|
|
42606
43164
|
stashDir: "env",
|
|
42607
43165
|
isRelevantFile: (fileName) => fileName === ".env" || fileName.endsWith(".env"),
|
|
42608
43166
|
toCanonicalName: (typeRoot, filePath) => {
|
|
42609
|
-
const rel = toPosix11(
|
|
42610
|
-
const fileName =
|
|
43167
|
+
const rel = toPosix11(path29.relative(typeRoot, filePath));
|
|
43168
|
+
const fileName = path29.basename(rel);
|
|
42611
43169
|
if (fileName === ".env") {
|
|
42612
|
-
const dir =
|
|
43170
|
+
const dir = path29.dirname(rel);
|
|
42613
43171
|
return dir === "." || dir === "" ? "default" : `${dir}/default`;
|
|
42614
43172
|
}
|
|
42615
43173
|
const stripped = rel.endsWith(".env") ? rel.slice(0, -4) : rel;
|
|
@@ -42617,15 +43175,15 @@ var ASSET_SPECS_INTERNAL = {
|
|
|
42617
43175
|
},
|
|
42618
43176
|
toAssetPath: (typeRoot, name) => {
|
|
42619
43177
|
if (name === "default")
|
|
42620
|
-
return
|
|
42621
|
-
return
|
|
43178
|
+
return path29.join(typeRoot, ".env");
|
|
43179
|
+
return path29.join(typeRoot, name.endsWith(".env") ? name : `${name}.env`);
|
|
42622
43180
|
}
|
|
42623
43181
|
},
|
|
42624
43182
|
secret: {
|
|
42625
43183
|
stashDir: "secrets",
|
|
42626
43184
|
isRelevantFile: (fileName) => !fileName.endsWith(".lock") && !fileName.endsWith(".sensitive"),
|
|
42627
|
-
toCanonicalName: (typeRoot, filePath) => toPosix11(
|
|
42628
|
-
toAssetPath: (typeRoot, name) =>
|
|
43185
|
+
toCanonicalName: (typeRoot, filePath) => toPosix11(path29.relative(typeRoot, filePath)),
|
|
43186
|
+
toAssetPath: (typeRoot, name) => path29.join(typeRoot, name)
|
|
42629
43187
|
},
|
|
42630
43188
|
wiki: {
|
|
42631
43189
|
stashDir: "wikis",
|
|
@@ -42637,14 +43195,14 @@ var ASSET_SPECS_INTERNAL = {
|
|
|
42637
43195
|
},
|
|
42638
43196
|
task: {
|
|
42639
43197
|
stashDir: "tasks",
|
|
42640
|
-
isRelevantFile: (fileName) =>
|
|
43198
|
+
isRelevantFile: (fileName) => path29.extname(fileName).toLowerCase() === ".yml",
|
|
42641
43199
|
toCanonicalName: (typeRoot, filePath) => {
|
|
42642
|
-
const rel = toPosix11(
|
|
43200
|
+
const rel = toPosix11(path29.relative(typeRoot, filePath));
|
|
42643
43201
|
return rel.endsWith(".yml") ? rel.slice(0, -4) : rel;
|
|
42644
43202
|
},
|
|
42645
43203
|
toAssetPath: (typeRoot, name) => {
|
|
42646
43204
|
const withExt = name.endsWith(".yml") ? name : `${name}.yml`;
|
|
42647
|
-
return
|
|
43205
|
+
return path29.join(typeRoot, withExt);
|
|
42648
43206
|
}
|
|
42649
43207
|
},
|
|
42650
43208
|
session: {
|
|
@@ -42685,8 +43243,8 @@ function resolveSourcesForOrigin(origin, allSources) {
|
|
|
42685
43243
|
if (byParsedId.length > 0)
|
|
42686
43244
|
return byParsedId;
|
|
42687
43245
|
} catch {}
|
|
42688
|
-
const resolvedOrigin =
|
|
42689
|
-
const byPath = allSources.filter((s) =>
|
|
43246
|
+
const resolvedOrigin = path29.resolve(origin);
|
|
43247
|
+
const byPath = allSources.filter((s) => path29.resolve(s.path) === resolvedOrigin);
|
|
42690
43248
|
if (byPath.length > 0)
|
|
42691
43249
|
return byPath;
|
|
42692
43250
|
return [];
|
|
@@ -42827,7 +43385,7 @@ function parseGitUrl(input, originalRef) {
|
|
|
42827
43385
|
};
|
|
42828
43386
|
}
|
|
42829
43387
|
function tryParseLocalRef(rawRef, explicitPath) {
|
|
42830
|
-
const resolvedPath =
|
|
43388
|
+
const resolvedPath = path29.resolve(rawRef);
|
|
42831
43389
|
let stat;
|
|
42832
43390
|
try {
|
|
42833
43391
|
stat = fs25.statSync(resolvedPath);
|
|
@@ -42855,7 +43413,7 @@ function isPathLikeRef(ref) {
|
|
|
42855
43413
|
return false;
|
|
42856
43414
|
if (ref === "." || ref === "..")
|
|
42857
43415
|
return true;
|
|
42858
|
-
if (
|
|
43416
|
+
if (path29.isAbsolute(ref))
|
|
42859
43417
|
return true;
|
|
42860
43418
|
if (ref.startsWith("./") || ref.startsWith("../") || ref.startsWith(".\\") || ref.startsWith("..\\")) {
|
|
42861
43419
|
return true;
|
|
@@ -42924,7 +43482,7 @@ function toReadableLocalId(absolutePath) {
|
|
|
42924
43482
|
const home = os2.homedir();
|
|
42925
43483
|
if (absolutePath === home)
|
|
42926
43484
|
return "~";
|
|
42927
|
-
if (absolutePath.startsWith(home +
|
|
43485
|
+
if (absolutePath.startsWith(home + path29.sep)) {
|
|
42928
43486
|
return `~/${absolutePath.slice(home.length + 1)}`;
|
|
42929
43487
|
}
|
|
42930
43488
|
return absolutePath;
|
|
@@ -42934,10 +43492,10 @@ function toReadableLocalId(absolutePath) {
|
|
|
42934
43492
|
init_common();
|
|
42935
43493
|
init_warn();
|
|
42936
43494
|
import fs26 from "fs";
|
|
42937
|
-
import
|
|
43495
|
+
import path30 from "path";
|
|
42938
43496
|
var LEGACY_STASH_FILENAME = ".stash.json";
|
|
42939
43497
|
function legacyStashFilePath(dirPath) {
|
|
42940
|
-
return
|
|
43498
|
+
return path30.join(dirPath, LEGACY_STASH_FILENAME);
|
|
42941
43499
|
}
|
|
42942
43500
|
function inspectLegacyStashOverrides(dirPath, options) {
|
|
42943
43501
|
const filePath = legacyStashFilePath(dirPath);
|
|
@@ -43051,7 +43609,7 @@ function collectDirs(root) {
|
|
|
43051
43609
|
}
|
|
43052
43610
|
for (const entry of entries) {
|
|
43053
43611
|
if (entry.isDirectory() && !entry.name.startsWith("."))
|
|
43054
|
-
walk(
|
|
43612
|
+
walk(path31.join(dir, entry.name));
|
|
43055
43613
|
}
|
|
43056
43614
|
};
|
|
43057
43615
|
walk(root);
|
|
@@ -43062,7 +43620,7 @@ function runContentMigration(stashRoots, options = {}) {
|
|
|
43062
43620
|
const seen = new Set;
|
|
43063
43621
|
const roots = [];
|
|
43064
43622
|
for (const root of stashRoots) {
|
|
43065
|
-
const resolved =
|
|
43623
|
+
const resolved = path31.resolve(root);
|
|
43066
43624
|
if (seen.has(resolved) || !safeIsDir(resolved))
|
|
43067
43625
|
continue;
|
|
43068
43626
|
seen.add(resolved);
|
|
@@ -43076,7 +43634,7 @@ function runContentMigration(stashRoots, options = {}) {
|
|
|
43076
43634
|
rewriteSourceBackrefsInDir(dir, report);
|
|
43077
43635
|
}
|
|
43078
43636
|
const operationId = options.operationId ?? `direct-${process.pid}-${randomBytes(8).toString("hex")}`;
|
|
43079
|
-
const batchPath = options.renameBatchPath ??
|
|
43637
|
+
const batchPath = options.renameBatchPath ?? path31.join(os3.tmpdir(), `akm-reserved-renames-${operationId}-${randomBytes(8).toString("hex")}.json`);
|
|
43080
43638
|
let batch;
|
|
43081
43639
|
try {
|
|
43082
43640
|
batch = loadReservedRenameBatch(batchPath, operationId);
|
|
@@ -43101,9 +43659,9 @@ function rewriteSourceBackrefsInDir(dir, report) {
|
|
|
43101
43659
|
throw error2;
|
|
43102
43660
|
}
|
|
43103
43661
|
for (const entry of entries) {
|
|
43104
|
-
if (!entry.isFile() ||
|
|
43662
|
+
if (!entry.isFile() || path31.extname(entry.name).toLowerCase() !== ".md")
|
|
43105
43663
|
continue;
|
|
43106
|
-
const filePath =
|
|
43664
|
+
const filePath = path31.join(dir, entry.name);
|
|
43107
43665
|
try {
|
|
43108
43666
|
const source = asNonEmptyString(parseFrontmatter(fs27.readFileSync(filePath, "utf8")).data.source);
|
|
43109
43667
|
const rewritten = legacyMemoryBackrefToConceptId(source);
|
|
@@ -43159,9 +43717,9 @@ function foldEntry(dir, entry, report) {
|
|
|
43159
43717
|
report.entriesSkipped++;
|
|
43160
43718
|
return false;
|
|
43161
43719
|
}
|
|
43162
|
-
const target =
|
|
43163
|
-
const relative =
|
|
43164
|
-
if (relative.startsWith("..") ||
|
|
43720
|
+
const target = path31.resolve(dir, entry.filename);
|
|
43721
|
+
const relative = path31.relative(path31.resolve(dir), target);
|
|
43722
|
+
if (relative.startsWith("..") || path31.isAbsolute(relative)) {
|
|
43165
43723
|
report.entriesSkipped++;
|
|
43166
43724
|
return false;
|
|
43167
43725
|
}
|
|
@@ -43173,13 +43731,13 @@ function foldEntry(dir, entry, report) {
|
|
|
43173
43731
|
throw error2;
|
|
43174
43732
|
targetExists = false;
|
|
43175
43733
|
}
|
|
43176
|
-
if (!targetExists ||
|
|
43734
|
+
if (!targetExists || path31.extname(target).toLowerCase() !== ".md") {
|
|
43177
43735
|
report.entriesSkipped++;
|
|
43178
43736
|
return false;
|
|
43179
43737
|
}
|
|
43180
43738
|
try {
|
|
43181
|
-
const realRelative =
|
|
43182
|
-
if (realRelative.startsWith("..") ||
|
|
43739
|
+
const realRelative = path31.relative(fs27.realpathSync(dir), fs27.realpathSync(target));
|
|
43740
|
+
if (realRelative.startsWith("..") || path31.isAbsolute(realRelative)) {
|
|
43183
43741
|
report.entriesSkipped++;
|
|
43184
43742
|
return false;
|
|
43185
43743
|
}
|
|
@@ -43205,8 +43763,8 @@ function foldCuratedFields(existing, entry) {
|
|
|
43205
43763
|
return next;
|
|
43206
43764
|
}
|
|
43207
43765
|
function mutateFrontmatterAtomic(filePath, mutate) {
|
|
43208
|
-
const directory =
|
|
43209
|
-
const temporary =
|
|
43766
|
+
const directory = path31.dirname(filePath);
|
|
43767
|
+
const temporary = path31.join(directory, `.${path31.basename(filePath)}.akm-migrate-${process.pid}-${randomBytes(8).toString("hex")}`);
|
|
43210
43768
|
try {
|
|
43211
43769
|
const mode = fs27.statSync(filePath).mode & 511;
|
|
43212
43770
|
fs27.copyFileSync(filePath, temporary, fs27.constants.COPYFILE_EXCL);
|
|
@@ -43229,7 +43787,7 @@ function reservedConceptsInDir(root, dir) {
|
|
|
43229
43787
|
for (const entry of entries) {
|
|
43230
43788
|
if (!entry.isFile() || !RESERVED_BASENAMES.has(entry.name.toLowerCase()))
|
|
43231
43789
|
continue;
|
|
43232
|
-
const filePath =
|
|
43790
|
+
const filePath = path31.join(dir, entry.name);
|
|
43233
43791
|
const legacyType = legacyTypeForDirectory(root, dir);
|
|
43234
43792
|
if (legacyType === "wiki")
|
|
43235
43793
|
continue;
|
|
@@ -43241,13 +43799,13 @@ function reservedConceptsInDir(root, dir) {
|
|
|
43241
43799
|
}
|
|
43242
43800
|
function planReservedRenameBatch(stashRoots, batchPath, operationId) {
|
|
43243
43801
|
const entries = [];
|
|
43244
|
-
for (const root of stashRoots.map((value) =>
|
|
43802
|
+
for (const root of stashRoots.map((value) => path31.resolve(value))) {
|
|
43245
43803
|
for (const dir of collectDirs(root)) {
|
|
43246
43804
|
entries.push(...reservedConceptsInDir(root, dir));
|
|
43247
43805
|
}
|
|
43248
43806
|
}
|
|
43249
43807
|
const batch = { formatVersion: 1, operationId, entries };
|
|
43250
|
-
fs27.mkdirSync(
|
|
43808
|
+
fs27.mkdirSync(path31.dirname(batchPath), { recursive: true, mode: 448 });
|
|
43251
43809
|
writeFileAtomic(batchPath, `${JSON.stringify(batch, null, 2)}
|
|
43252
43810
|
`, 384);
|
|
43253
43811
|
return batch;
|
|
@@ -43287,21 +43845,21 @@ function applyReservedRenameBatch(batch, operationId) {
|
|
|
43287
43845
|
if (targetExists)
|
|
43288
43846
|
throw new Error(`Reserved rename target already exists: ${entry.to}`);
|
|
43289
43847
|
fs27.renameSync(entry.from, entry.to);
|
|
43290
|
-
syncRenameDirectory(
|
|
43848
|
+
syncRenameDirectory(path31.dirname(entry.to));
|
|
43291
43849
|
}
|
|
43292
43850
|
}
|
|
43293
43851
|
function legacyTypeForDirectory(root, dir) {
|
|
43294
|
-
const [top] =
|
|
43852
|
+
const [top] = path31.relative(root, dir).split(path31.sep);
|
|
43295
43853
|
if (!top || top === "..")
|
|
43296
43854
|
return;
|
|
43297
43855
|
const exact = Object.entries(TYPE_DIRS).find(([, typeDir]) => typeDir === top)?.[0];
|
|
43298
43856
|
if (exact)
|
|
43299
43857
|
return exact;
|
|
43300
|
-
const actualRoot =
|
|
43858
|
+
const actualRoot = path31.join(root, top);
|
|
43301
43859
|
try {
|
|
43302
43860
|
const actualIdentity = fs27.realpathSync(actualRoot);
|
|
43303
43861
|
return Object.entries(TYPE_DIRS).find(([, typeDir]) => {
|
|
43304
|
-
const canonicalRoot =
|
|
43862
|
+
const canonicalRoot = path31.join(root, typeDir);
|
|
43305
43863
|
return fs27.existsSync(canonicalRoot) && fs27.realpathSync(canonicalRoot) === actualIdentity;
|
|
43306
43864
|
})?.[0];
|
|
43307
43865
|
} catch (error2) {
|
|
@@ -43319,10 +43877,10 @@ function carriesAssetFrontmatter(filePath) {
|
|
|
43319
43877
|
}
|
|
43320
43878
|
function collisionSafeTarget(dir, basename) {
|
|
43321
43879
|
const stem = basename.slice(0, basename.length - ".md".length);
|
|
43322
|
-
let candidate =
|
|
43880
|
+
let candidate = path31.join(dir, `${stem}-content.md`);
|
|
43323
43881
|
let suffix = 2;
|
|
43324
43882
|
while (pathExists(candidate)) {
|
|
43325
|
-
candidate =
|
|
43883
|
+
candidate = path31.join(dir, `${stem}-content-${suffix}.md`);
|
|
43326
43884
|
suffix++;
|
|
43327
43885
|
}
|
|
43328
43886
|
return candidate;
|
|
@@ -43343,14 +43901,14 @@ function errMsg(error2) {
|
|
|
43343
43901
|
|
|
43344
43902
|
// scripts/akm-migrate/migrate/legacy/legacy-paths.ts
|
|
43345
43903
|
init_paths();
|
|
43346
|
-
import
|
|
43904
|
+
import path32 from "path";
|
|
43347
43905
|
function getLegacyWorkflowDbPath() {
|
|
43348
|
-
return
|
|
43906
|
+
return path32.join(getDataDir(), "workflow.db");
|
|
43349
43907
|
}
|
|
43350
43908
|
|
|
43351
43909
|
// scripts/akm-migrate/migrate/legacy/proposal-fs-import.ts
|
|
43352
43910
|
import fs29 from "fs";
|
|
43353
|
-
import
|
|
43911
|
+
import path35 from "path";
|
|
43354
43912
|
init_warn();
|
|
43355
43913
|
|
|
43356
43914
|
// src/registry/resolve.ts
|
|
@@ -43359,7 +43917,7 @@ init_errors();
|
|
|
43359
43917
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
43360
43918
|
import fs28 from "fs";
|
|
43361
43919
|
import os4 from "os";
|
|
43362
|
-
import
|
|
43920
|
+
import path33 from "path";
|
|
43363
43921
|
import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
|
|
43364
43922
|
|
|
43365
43923
|
// src/integrations/github.ts
|
|
@@ -43598,7 +44156,7 @@ function parseGitUrl2(input, originalRef) {
|
|
|
43598
44156
|
};
|
|
43599
44157
|
}
|
|
43600
44158
|
function tryParseLocalRef2(rawRef, explicitPath) {
|
|
43601
|
-
const resolvedPath =
|
|
44159
|
+
const resolvedPath = path33.resolve(rawRef);
|
|
43602
44160
|
let stat;
|
|
43603
44161
|
try {
|
|
43604
44162
|
stat = fs28.statSync(resolvedPath);
|
|
@@ -43628,7 +44186,7 @@ function isPathLikeRef2(ref) {
|
|
|
43628
44186
|
return false;
|
|
43629
44187
|
if (ref === "." || ref === "..")
|
|
43630
44188
|
return true;
|
|
43631
|
-
if (
|
|
44189
|
+
if (path33.isAbsolute(ref))
|
|
43632
44190
|
return true;
|
|
43633
44191
|
if (ref.startsWith("./") || ref.startsWith("../") || ref.startsWith(".\\") || ref.startsWith("..\\")) {
|
|
43634
44192
|
return true;
|
|
@@ -43881,18 +44439,18 @@ function toReadableLocalId2(absolutePath) {
|
|
|
43881
44439
|
const home = os4.homedir();
|
|
43882
44440
|
if (absolutePath === home)
|
|
43883
44441
|
return "~";
|
|
43884
|
-
if (absolutePath.startsWith(home +
|
|
44442
|
+
if (absolutePath.startsWith(home + path33.sep)) {
|
|
43885
44443
|
return `~/${absolutePath.slice(home.length + 1)}`;
|
|
43886
44444
|
}
|
|
43887
44445
|
return absolutePath;
|
|
43888
44446
|
}
|
|
43889
44447
|
function findGitRepoRoot(startDir) {
|
|
43890
|
-
let current =
|
|
44448
|
+
let current = path33.resolve(startDir);
|
|
43891
44449
|
while (true) {
|
|
43892
|
-
if (fs28.existsSync(
|
|
44450
|
+
if (fs28.existsSync(path33.join(current, ".git"))) {
|
|
43893
44451
|
return current;
|
|
43894
44452
|
}
|
|
43895
|
-
const parent =
|
|
44453
|
+
const parent = path33.dirname(current);
|
|
43896
44454
|
if (parent === current)
|
|
43897
44455
|
return;
|
|
43898
44456
|
current = parent;
|
|
@@ -43924,7 +44482,7 @@ async function tryFetchJson(url, headers) {
|
|
|
43924
44482
|
init_database();
|
|
43925
44483
|
|
|
43926
44484
|
// scripts/akm-migrate/migrate/legacy-ref-grammar.ts
|
|
43927
|
-
import
|
|
44485
|
+
import path34 from "path";
|
|
43928
44486
|
init_errors();
|
|
43929
44487
|
var TYPE_ALIASES = {
|
|
43930
44488
|
environment: "env"
|
|
@@ -43969,8 +44527,8 @@ function validateName2(name) {
|
|
|
43969
44527
|
throw new UsageError("Null byte in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
43970
44528
|
if (/^[A-Za-z]:/.test(name))
|
|
43971
44529
|
throw new UsageError("Windows drive path in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
43972
|
-
const normalized =
|
|
43973
|
-
if (
|
|
44530
|
+
const normalized = path34.posix.normalize(name.replace(/\\/g, "/"));
|
|
44531
|
+
if (path34.posix.isAbsolute(normalized))
|
|
43974
44532
|
throw new UsageError("Absolute path in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
43975
44533
|
if (normalized === ".." || normalized.startsWith("../")) {
|
|
43976
44534
|
throw new UsageError("Path traversal in asset name.", "MISSING_REQUIRED_ARGUMENT");
|
|
@@ -43981,7 +44539,7 @@ function validateName2(name) {
|
|
|
43981
44539
|
}
|
|
43982
44540
|
}
|
|
43983
44541
|
function normalizeName2(name) {
|
|
43984
|
-
return
|
|
44542
|
+
return path34.posix.normalize(name.replace(/\\/g, "/"));
|
|
43985
44543
|
}
|
|
43986
44544
|
function classifyRefGrammar(raw) {
|
|
43987
44545
|
const trimmed = raw.trim();
|
|
@@ -44029,8 +44587,8 @@ function parseStoredRef(raw) {
|
|
|
44029
44587
|
|
|
44030
44588
|
// scripts/akm-migrate/migrate/legacy/proposal-fs-import.ts
|
|
44031
44589
|
function legacyProposalsRoot(stashDir, archive) {
|
|
44032
|
-
const root =
|
|
44033
|
-
return archive ?
|
|
44590
|
+
const root = path35.join(stashDir, ".akm", "proposals");
|
|
44591
|
+
return archive ? path35.join(root, "archive") : root;
|
|
44034
44592
|
}
|
|
44035
44593
|
function importLegacyProposalsIntoState(stateDbPath, stashRoots, finalRefMap = new Map) {
|
|
44036
44594
|
try {
|
|
@@ -44055,7 +44613,7 @@ function importLegacyProposalsIntoState(stateDbPath, stashRoots, finalRefMap = n
|
|
|
44055
44613
|
aliasCandidates.set(alias, candidates);
|
|
44056
44614
|
};
|
|
44057
44615
|
for (const root of stashRoots) {
|
|
44058
|
-
const resolvedRoot =
|
|
44616
|
+
const resolvedRoot = path35.resolve(root.path);
|
|
44059
44617
|
const roots = bundleRootCandidates.get(root.bundleId) ?? new Set;
|
|
44060
44618
|
roots.add(resolvedRoot);
|
|
44061
44619
|
bundleRootCandidates.set(root.bundleId, roots);
|
|
@@ -44091,7 +44649,7 @@ function importLegacyProposalsIntoState(stateDbPath, stashRoots, finalRefMap = n
|
|
|
44091
44649
|
bundleAliases.set(alias, bundleId);
|
|
44092
44650
|
}
|
|
44093
44651
|
for (const root of stashRoots) {
|
|
44094
|
-
const resolved =
|
|
44652
|
+
const resolved = path35.resolve(root.path);
|
|
44095
44653
|
if (seen.has(resolved))
|
|
44096
44654
|
continue;
|
|
44097
44655
|
seen.add(resolved);
|
|
@@ -44125,7 +44683,7 @@ function importLegacyProposalsForStash(db, stash, bundleAliases, bundleRoots, fi
|
|
|
44125
44683
|
for (const entry of entries) {
|
|
44126
44684
|
if (!entry.isDirectory() || entry.name === "archive")
|
|
44127
44685
|
continue;
|
|
44128
|
-
const proposalDir =
|
|
44686
|
+
const proposalDir = path35.join(root, entry.name);
|
|
44129
44687
|
const proposal = readLegacyProposalFile(proposalDir, stash, bundleAliases, bundleRoots);
|
|
44130
44688
|
if (!proposal)
|
|
44131
44689
|
continue;
|
|
@@ -44192,7 +44750,7 @@ function insertProposalIfAbsent(db, proposal, stashDir) {
|
|
|
44192
44750
|
return false;
|
|
44193
44751
|
}
|
|
44194
44752
|
function readLegacyProposalFile(proposalDir, stash, bundleAliases, bundleRoots) {
|
|
44195
|
-
const filePath =
|
|
44753
|
+
const filePath = path35.join(proposalDir, "proposal.json");
|
|
44196
44754
|
let parsed;
|
|
44197
44755
|
let source;
|
|
44198
44756
|
try {
|
|
@@ -44227,7 +44785,7 @@ function readLegacyProposalFile(proposalDir, stash, bundleAliases, bundleRoots)
|
|
|
44227
44785
|
normalizedOrigin = parseRegistryRef2(legacyOrigin).id;
|
|
44228
44786
|
} catch {}
|
|
44229
44787
|
}
|
|
44230
|
-
const bundle = explicitOrigin ? bundleAliases.get(legacyOrigin) ?? (normalizedOrigin ? bundleAliases.get(normalizedOrigin) : undefined) ?? bundleAliases.get(
|
|
44788
|
+
const bundle = explicitOrigin ? bundleAliases.get(legacyOrigin) ?? (normalizedOrigin ? bundleAliases.get(normalizedOrigin) : undefined) ?? bundleAliases.get(path35.resolve(legacyOrigin)) : translated.bundle ? bundleAliases.get(translated.bundle) : stash.bundleId;
|
|
44231
44789
|
if (!bundle || !bundleRoots.has(bundle))
|
|
44232
44790
|
throw new Error(`unmapped legacy proposal origin: ${legacyOrigin}`);
|
|
44233
44791
|
migratedBundle = bundle;
|
|
@@ -44252,13 +44810,13 @@ function readLegacyProposalFile(proposalDir, stash, bundleAliases, bundleRoots)
|
|
|
44252
44810
|
let backupContent;
|
|
44253
44811
|
if (typeof backup === "string" && backup.length > 0) {
|
|
44254
44812
|
try {
|
|
44255
|
-
backupContent = fs29.readFileSync(
|
|
44813
|
+
backupContent = fs29.readFileSync(path35.join(proposalDir, backup), "utf8");
|
|
44256
44814
|
} catch (error2) {
|
|
44257
44815
|
if (error2.code !== "ENOENT")
|
|
44258
44816
|
throw error2;
|
|
44259
44817
|
}
|
|
44260
44818
|
}
|
|
44261
|
-
const migratedRoot =
|
|
44819
|
+
const migratedRoot = path35.resolve(bundleRoots.get(migratedBundle));
|
|
44262
44820
|
return {
|
|
44263
44821
|
...rest,
|
|
44264
44822
|
ref: migratedRef,
|
|
@@ -44284,12 +44842,12 @@ function errMsg2(error2) {
|
|
|
44284
44842
|
import crypto4 from "crypto";
|
|
44285
44843
|
import fs40 from "fs";
|
|
44286
44844
|
import os5 from "os";
|
|
44287
|
-
import
|
|
44845
|
+
import path46 from "path";
|
|
44288
44846
|
init_errors();
|
|
44289
44847
|
|
|
44290
44848
|
// src/core/write-source.ts
|
|
44291
44849
|
import fs35 from "fs";
|
|
44292
|
-
import
|
|
44850
|
+
import path40 from "path";
|
|
44293
44851
|
|
|
44294
44852
|
// src/indexer/index-writer-lock.ts
|
|
44295
44853
|
import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
|
|
@@ -44307,23 +44865,23 @@ init_paths();
|
|
|
44307
44865
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
44308
44866
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
44309
44867
|
import fs32 from "fs";
|
|
44310
|
-
import
|
|
44868
|
+
import path38 from "path";
|
|
44311
44869
|
|
|
44312
44870
|
// src/sources/providers/provider-utils.ts
|
|
44313
44871
|
import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
|
|
44314
44872
|
import fs31 from "fs";
|
|
44315
|
-
import
|
|
44873
|
+
import path37 from "path";
|
|
44316
44874
|
init_common();
|
|
44317
44875
|
init_runtime();
|
|
44318
44876
|
|
|
44319
44877
|
// src/sources/include.ts
|
|
44320
44878
|
init_common();
|
|
44321
44879
|
import fs30 from "fs";
|
|
44322
|
-
import
|
|
44880
|
+
import path36 from "path";
|
|
44323
44881
|
var INCLUDE_CONFIG_KEYS = ["akm"];
|
|
44324
44882
|
function readPackageJsonAt(dirPath) {
|
|
44325
44883
|
try {
|
|
44326
|
-
const raw = fs30.readFileSync(
|
|
44884
|
+
const raw = fs30.readFileSync(path36.join(dirPath, "package.json"), "utf8");
|
|
44327
44885
|
const parsed = JSON.parse(raw);
|
|
44328
44886
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
44329
44887
|
return parsed;
|
|
@@ -44350,8 +44908,8 @@ function extractIncludeList(pkg) {
|
|
|
44350
44908
|
return;
|
|
44351
44909
|
}
|
|
44352
44910
|
function findNearestIncludeConfig(startDir, boundary) {
|
|
44353
|
-
let current =
|
|
44354
|
-
const resolvedBoundary =
|
|
44911
|
+
let current = path36.resolve(startDir);
|
|
44912
|
+
const resolvedBoundary = path36.resolve(boundary);
|
|
44355
44913
|
while (isWithin(current, resolvedBoundary)) {
|
|
44356
44914
|
const pkg = readPackageJsonAt(current);
|
|
44357
44915
|
const include = extractIncludeList(pkg);
|
|
@@ -44360,7 +44918,7 @@ function findNearestIncludeConfig(startDir, boundary) {
|
|
|
44360
44918
|
}
|
|
44361
44919
|
if (current === resolvedBoundary)
|
|
44362
44920
|
break;
|
|
44363
|
-
const parent =
|
|
44921
|
+
const parent = path36.dirname(current);
|
|
44364
44922
|
if (parent === current)
|
|
44365
44923
|
break;
|
|
44366
44924
|
current = parent;
|
|
@@ -44369,29 +44927,29 @@ function findNearestIncludeConfig(startDir, boundary) {
|
|
|
44369
44927
|
}
|
|
44370
44928
|
function copyIncludedPaths(includeGlobs, sourceDir, destDir) {
|
|
44371
44929
|
for (const entry of includeGlobs) {
|
|
44372
|
-
const resolvedSource =
|
|
44930
|
+
const resolvedSource = path36.resolve(sourceDir, entry);
|
|
44373
44931
|
if (!isWithin(resolvedSource, sourceDir)) {
|
|
44374
44932
|
throw new Error(`Path in akm.include escapes the package root: ${entry}`);
|
|
44375
44933
|
}
|
|
44376
44934
|
if (!fs30.existsSync(resolvedSource)) {
|
|
44377
44935
|
throw new Error(`Path in akm.include does not exist: ${entry}`);
|
|
44378
44936
|
}
|
|
44379
|
-
if (
|
|
44937
|
+
if (path36.basename(resolvedSource) === ".git") {
|
|
44380
44938
|
continue;
|
|
44381
44939
|
}
|
|
44382
|
-
const relativePath =
|
|
44940
|
+
const relativePath = path36.relative(sourceDir, resolvedSource);
|
|
44383
44941
|
if (!relativePath || relativePath === ".") {
|
|
44384
44942
|
copyDirectoryContents(sourceDir, destDir);
|
|
44385
44943
|
continue;
|
|
44386
44944
|
}
|
|
44387
|
-
copyPath(resolvedSource,
|
|
44945
|
+
copyPath(resolvedSource, path36.join(destDir, relativePath));
|
|
44388
44946
|
}
|
|
44389
44947
|
}
|
|
44390
44948
|
function copyDirectoryContents(sourceDir, destinationDir) {
|
|
44391
44949
|
for (const entry of fs30.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
44392
44950
|
if (entry.name === ".git")
|
|
44393
44951
|
continue;
|
|
44394
|
-
copyPath(
|
|
44952
|
+
copyPath(path36.join(sourceDir, entry.name), path36.join(destinationDir, entry.name));
|
|
44395
44953
|
}
|
|
44396
44954
|
}
|
|
44397
44955
|
function copyPath(sourcePath, destinationPath) {
|
|
@@ -44399,7 +44957,7 @@ function copyPath(sourcePath, destinationPath) {
|
|
|
44399
44957
|
if (stat.isSymbolicLink()) {
|
|
44400
44958
|
throw new Error(`Path in akm.include must not be a symlink: ${sourcePath}`);
|
|
44401
44959
|
}
|
|
44402
|
-
fs30.mkdirSync(
|
|
44960
|
+
fs30.mkdirSync(path36.dirname(destinationPath), { recursive: true });
|
|
44403
44961
|
if (stat.isDirectory()) {
|
|
44404
44962
|
fs30.mkdirSync(destinationPath, { recursive: true });
|
|
44405
44963
|
copyDirectoryContents(sourcePath, destinationPath);
|
|
@@ -44428,7 +44986,7 @@ function looksLikeAnyBundleRoot(root) {
|
|
|
44428
44986
|
return false;
|
|
44429
44987
|
}
|
|
44430
44988
|
function detectStashRoot(extractedDir) {
|
|
44431
|
-
const root =
|
|
44989
|
+
const root = path37.resolve(extractedDir);
|
|
44432
44990
|
if (looksLikeAnyBundleRoot(root)) {
|
|
44433
44991
|
return root;
|
|
44434
44992
|
}
|
|
@@ -44445,13 +45003,13 @@ function buildInstallCacheDir(cacheRootDir, source, id, version) {
|
|
|
44445
45003
|
const identitySuffix = version === "writable" ? `-${createHash2("sha256").update(`${source}:${id}`).digest("hex").slice(0, 12)}` : "";
|
|
44446
45004
|
const slug = `${source}-${safeId}${identitySuffix}`;
|
|
44447
45005
|
const versionSlug = source === "local" ? uniqueSlug() : version?.replace(/[^a-zA-Z0-9_.-]+/g, "-") ?? uniqueSlug();
|
|
44448
|
-
return
|
|
45006
|
+
return path37.join(cacheRootDir, slug || source, versionSlug);
|
|
44449
45007
|
}
|
|
44450
45008
|
function applyAkmIncludeConfig(sourceRoot, cacheDir, searchRoot = sourceRoot) {
|
|
44451
45009
|
const includeConfig = findNearestIncludeConfig(sourceRoot, searchRoot);
|
|
44452
45010
|
if (!includeConfig)
|
|
44453
45011
|
return;
|
|
44454
|
-
const selectedDir =
|
|
45012
|
+
const selectedDir = path37.join(cacheDir, "selected");
|
|
44455
45013
|
fs31.rmSync(selectedDir, { recursive: true, force: true });
|
|
44456
45014
|
fs31.mkdirSync(selectedDir, { recursive: true });
|
|
44457
45015
|
copyIncludedPaths(includeConfig.include, includeConfig.baseDir, selectedDir);
|
|
@@ -44492,7 +45050,7 @@ function findShallowestStashRoot(root) {
|
|
|
44492
45050
|
}
|
|
44493
45051
|
const { dir: current, depth } = item;
|
|
44494
45052
|
if (current !== root) {
|
|
44495
|
-
if (isDirectory(
|
|
45053
|
+
if (isDirectory(path37.join(current, ".stash"))) {
|
|
44496
45054
|
return current;
|
|
44497
45055
|
}
|
|
44498
45056
|
if (countStashDirs(current) >= 2) {
|
|
@@ -44512,7 +45070,7 @@ function findShallowestStashRoot(root) {
|
|
|
44512
45070
|
continue;
|
|
44513
45071
|
if (child.name === ".git" || child.name === "node_modules")
|
|
44514
45072
|
continue;
|
|
44515
|
-
queue.push({ dir:
|
|
45073
|
+
queue.push({ dir: path37.join(current, child.name), depth: depth + 1 });
|
|
44516
45074
|
}
|
|
44517
45075
|
}
|
|
44518
45076
|
return;
|
|
@@ -44565,7 +45123,7 @@ function assertNoIgnoredPathOverwrite(repoDir, targetRevision) {
|
|
|
44565
45123
|
const changedPaths = changed.stdout.split("\x00").filter(Boolean);
|
|
44566
45124
|
const conflict = ignoredPaths.find((ignoredPath) => changedPaths.some((changedPath) => changedPath === ignoredPath || changedPath.startsWith(`${ignoredPath}/`) || ignoredPath.startsWith(`${changedPath}/`)));
|
|
44567
45125
|
if (conflict) {
|
|
44568
|
-
throw new UsageError(`Git update would overwrite ignored local path ${
|
|
45126
|
+
throw new UsageError(`Git update would overwrite ignored local path ${path38.join(repoDir, conflict)}; move or remove it before update.`);
|
|
44569
45127
|
}
|
|
44570
45128
|
}
|
|
44571
45129
|
function replaceDirectory(stagedDir, destination) {
|
|
@@ -44601,7 +45159,7 @@ function cloneRepo(cloneUrl, ref, destDir, writable = false) {
|
|
|
44601
45159
|
}
|
|
44602
45160
|
try {
|
|
44603
45161
|
if (!writable) {
|
|
44604
|
-
const gitDir =
|
|
45162
|
+
const gitDir = path38.join(tmpDir, ".git");
|
|
44605
45163
|
if (fs32.existsSync(gitDir))
|
|
44606
45164
|
fs32.rmSync(gitDir, { recursive: true, force: true });
|
|
44607
45165
|
}
|
|
@@ -44639,7 +45197,7 @@ function redactUrlUserinfo(text) {
|
|
|
44639
45197
|
// src/sources/providers/git-provider.ts
|
|
44640
45198
|
import { createHash as createHash3 } from "crypto";
|
|
44641
45199
|
import fs34 from "fs";
|
|
44642
|
-
import
|
|
45200
|
+
import path39 from "path";
|
|
44643
45201
|
init_errors();
|
|
44644
45202
|
init_paths();
|
|
44645
45203
|
|
|
@@ -44725,11 +45283,11 @@ registerSourceProvider("git", (config) => new GitSourceProvider(config));
|
|
|
44725
45283
|
function getCachePaths(repoUrl) {
|
|
44726
45284
|
const key = createHash3("sha256").update(repoUrl).digest("hex").slice(0, 16);
|
|
44727
45285
|
const cacheRoot = getRegistryIndexCacheDir();
|
|
44728
|
-
const rootDir =
|
|
45286
|
+
const rootDir = path39.join(cacheRoot, `git-${key}`);
|
|
44729
45287
|
return {
|
|
44730
45288
|
rootDir,
|
|
44731
|
-
repoDir:
|
|
44732
|
-
indexPath:
|
|
45289
|
+
repoDir: path39.join(rootDir, "repo"),
|
|
45290
|
+
indexPath: path39.join(rootDir, "index.json")
|
|
44733
45291
|
};
|
|
44734
45292
|
}
|
|
44735
45293
|
async function ensureGitMirror(repo, cachePaths, options) {
|
|
@@ -44744,7 +45302,7 @@ async function ensureGitMirror(repo, cachePaths, options) {
|
|
|
44744
45302
|
isUsable: () => !requireRepoDir || hasExtractedRepo(cachePaths.repoDir),
|
|
44745
45303
|
refresh: async () => {
|
|
44746
45304
|
fs34.mkdirSync(cachePaths.rootDir, { recursive: true });
|
|
44747
|
-
if (writable && fs34.existsSync(
|
|
45305
|
+
if (writable && fs34.existsSync(path39.join(cachePaths.repoDir, ".git"))) {
|
|
44748
45306
|
pullRepo(cachePaths.repoDir);
|
|
44749
45307
|
} else {
|
|
44750
45308
|
cloneRepo(repo.cloneUrl, repo.ref, cachePaths.repoDir, writable);
|
|
@@ -44805,14 +45363,14 @@ function hasExtractedRepo(repoDir) {
|
|
|
44805
45363
|
try {
|
|
44806
45364
|
if (!fs34.statSync(repoDir).isDirectory())
|
|
44807
45365
|
return false;
|
|
44808
|
-
if (fs34.statSync(
|
|
45366
|
+
if (fs34.statSync(path39.join(repoDir, "content")).isDirectory())
|
|
44809
45367
|
return true;
|
|
44810
45368
|
} catch {}
|
|
44811
45369
|
try {
|
|
44812
45370
|
if (!fs34.statSync(repoDir).isDirectory())
|
|
44813
45371
|
return false;
|
|
44814
45372
|
const ownedDirs = akmAdapter.directoryList?.({ id: "akm", adapter: "akm", root: repoDir, writable: false }) ?? stashDirNames();
|
|
44815
|
-
return ownedDirs.some((dirName) => fs34.existsSync(
|
|
45373
|
+
return ownedDirs.some((dirName) => fs34.existsSync(path39.join(repoDir, dirName)));
|
|
44816
45374
|
} catch {
|
|
44817
45375
|
return false;
|
|
44818
45376
|
}
|
|
@@ -44888,7 +45446,7 @@ function resolveWritable(entry) {
|
|
|
44888
45446
|
return entry.type === "filesystem";
|
|
44889
45447
|
}
|
|
44890
45448
|
function resolveGitContentRoot(repoPath) {
|
|
44891
|
-
const contentPath =
|
|
45449
|
+
const contentPath = path40.join(repoPath, "content");
|
|
44892
45450
|
return fs35.existsSync(contentPath) && fs35.statSync(contentPath).isDirectory() ? contentPath : repoPath;
|
|
44893
45451
|
}
|
|
44894
45452
|
|
|
@@ -44920,7 +45478,7 @@ registerSourceProvider("filesystem", (entry) => {
|
|
|
44920
45478
|
init_errors();
|
|
44921
45479
|
init_paths();
|
|
44922
45480
|
import fs37 from "fs";
|
|
44923
|
-
import
|
|
45481
|
+
import path42 from "path";
|
|
44924
45482
|
|
|
44925
45483
|
// src/sources/providers/tar-utils.ts
|
|
44926
45484
|
init_common();
|
|
@@ -44928,7 +45486,7 @@ init_warn();
|
|
|
44928
45486
|
init_runtime();
|
|
44929
45487
|
import { createHash as createHash4 } from "crypto";
|
|
44930
45488
|
import fs36 from "fs";
|
|
44931
|
-
import
|
|
45489
|
+
import path41 from "path";
|
|
44932
45490
|
function verifyArchiveIntegrity(archivePath, expected, source) {
|
|
44933
45491
|
if (!expected)
|
|
44934
45492
|
return;
|
|
@@ -44988,7 +45546,7 @@ function scanExtractedFiles(dir, root) {
|
|
|
44988
45546
|
return;
|
|
44989
45547
|
}
|
|
44990
45548
|
for (const entry of entries) {
|
|
44991
|
-
const fullPath =
|
|
45549
|
+
const fullPath = path41.join(dir, entry.name);
|
|
44992
45550
|
if (entry.name === ".." || entry.name === ".") {
|
|
44993
45551
|
throw new Error(`Post-extraction scan: suspicious entry name: ${fullPath}`);
|
|
44994
45552
|
}
|
|
@@ -44999,7 +45557,7 @@ function scanExtractedFiles(dir, root) {
|
|
|
44999
45557
|
}
|
|
45000
45558
|
}
|
|
45001
45559
|
if (!entry.isSymbolicLink()) {
|
|
45002
|
-
const resolved =
|
|
45560
|
+
const resolved = path41.resolve(fullPath);
|
|
45003
45561
|
if (!isWithin(resolved, root)) {
|
|
45004
45562
|
throw new Error(`Post-extraction scan: entry escapes destination directory: ${fullPath}`);
|
|
45005
45563
|
}
|
|
@@ -45019,7 +45577,7 @@ function validateTarEntries(listOutput) {
|
|
|
45019
45577
|
if (entry.startsWith("/")) {
|
|
45020
45578
|
throw new Error(`Archive contains an absolute path entry: ${entry}`);
|
|
45021
45579
|
}
|
|
45022
|
-
const normalized =
|
|
45580
|
+
const normalized = path41.posix.normalize(entry);
|
|
45023
45581
|
if (normalized === ".." || normalized.startsWith("../")) {
|
|
45024
45582
|
throw new Error(`Archive contains a path traversal entry: ${entry}`);
|
|
45025
45583
|
}
|
|
@@ -45027,8 +45585,8 @@ function validateTarEntries(listOutput) {
|
|
|
45027
45585
|
const stripped = parts.slice(1).join("/");
|
|
45028
45586
|
if (!stripped)
|
|
45029
45587
|
continue;
|
|
45030
|
-
const normalizedStripped =
|
|
45031
|
-
if (normalizedStripped === ".." || normalizedStripped.startsWith("../") ||
|
|
45588
|
+
const normalizedStripped = path41.posix.normalize(stripped);
|
|
45589
|
+
if (normalizedStripped === ".." || normalizedStripped.startsWith("../") || path41.posix.isAbsolute(normalizedStripped)) {
|
|
45032
45590
|
throw new Error(`Archive contains an unsafe entry after strip-components: ${entry}`);
|
|
45033
45591
|
}
|
|
45034
45592
|
}
|
|
@@ -45073,8 +45631,8 @@ async function doSyncNpm(parsed, options) {
|
|
|
45073
45631
|
const syncedAt = (options?.now ?? new Date).toISOString();
|
|
45074
45632
|
const cacheRootDir = options?.cacheRootDir ?? getRegistryCacheDir();
|
|
45075
45633
|
const cacheDir = buildInstallCacheDir(cacheRootDir, resolved.source, resolved.id, resolved.resolvedVersion ?? resolved.resolvedRevision);
|
|
45076
|
-
const archivePath =
|
|
45077
|
-
const extractedDir =
|
|
45634
|
+
const archivePath = path42.join(cacheDir, "artifact.tar.gz");
|
|
45635
|
+
const extractedDir = path42.join(cacheDir, "extracted");
|
|
45078
45636
|
if (!options?.force && isDirectory(extractedDir)) {
|
|
45079
45637
|
try {
|
|
45080
45638
|
const cachedStashRoot = detectStashRoot(extractedDir);
|
|
@@ -45145,9 +45703,9 @@ init_common();
|
|
|
45145
45703
|
init_errors();
|
|
45146
45704
|
init_paths();
|
|
45147
45705
|
init_warn();
|
|
45148
|
-
import { createHash as createHash5 } from "crypto";
|
|
45706
|
+
import { createHash as createHash5, randomBytes as randomBytes3 } from "crypto";
|
|
45149
45707
|
import fs39 from "fs";
|
|
45150
|
-
import
|
|
45708
|
+
import path44 from "path";
|
|
45151
45709
|
|
|
45152
45710
|
// node_modules/node-html-parser/dist/index.mjs
|
|
45153
45711
|
var __create2 = Object.create;
|
|
@@ -50635,7 +51193,7 @@ async function fetchPinnedJson(url, options) {
|
|
|
50635
51193
|
// src/sources/snapshot-fetchers/registry.ts
|
|
50636
51194
|
init_warn();
|
|
50637
51195
|
import fs38 from "fs";
|
|
50638
|
-
import
|
|
51196
|
+
import path43 from "path";
|
|
50639
51197
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
50640
51198
|
|
|
50641
51199
|
// src/sources/snapshot-fetchers/bluesky.ts
|
|
@@ -52571,24 +53129,24 @@ class MatcherView {
|
|
|
52571
53129
|
return this._matcher.separator;
|
|
52572
53130
|
}
|
|
52573
53131
|
getCurrentTag() {
|
|
52574
|
-
const
|
|
52575
|
-
return
|
|
53132
|
+
const path43 = this._matcher.path;
|
|
53133
|
+
return path43.length > 0 ? path43[path43.length - 1].tag : undefined;
|
|
52576
53134
|
}
|
|
52577
53135
|
getCurrentNamespace() {
|
|
52578
|
-
const
|
|
52579
|
-
return
|
|
53136
|
+
const path43 = this._matcher.path;
|
|
53137
|
+
return path43.length > 0 ? path43[path43.length - 1].namespace : undefined;
|
|
52580
53138
|
}
|
|
52581
53139
|
getAttrValue(attrName) {
|
|
52582
|
-
const
|
|
52583
|
-
if (
|
|
53140
|
+
const path43 = this._matcher.path;
|
|
53141
|
+
if (path43.length === 0)
|
|
52584
53142
|
return;
|
|
52585
|
-
return
|
|
53143
|
+
return path43[path43.length - 1].values?.[attrName];
|
|
52586
53144
|
}
|
|
52587
53145
|
hasAttr(attrName) {
|
|
52588
|
-
const
|
|
52589
|
-
if (
|
|
53146
|
+
const path43 = this._matcher.path;
|
|
53147
|
+
if (path43.length === 0)
|
|
52590
53148
|
return false;
|
|
52591
|
-
const current =
|
|
53149
|
+
const current = path43[path43.length - 1];
|
|
52592
53150
|
return current.values !== undefined && attrName in current.values;
|
|
52593
53151
|
}
|
|
52594
53152
|
getAnyParentAttr(attrName) {
|
|
@@ -52598,16 +53156,16 @@ class MatcherView {
|
|
|
52598
53156
|
return this._matcher.hasAnyParentAttr(attrName);
|
|
52599
53157
|
}
|
|
52600
53158
|
getPosition() {
|
|
52601
|
-
const
|
|
52602
|
-
if (
|
|
53159
|
+
const path43 = this._matcher.path;
|
|
53160
|
+
if (path43.length === 0)
|
|
52603
53161
|
return -1;
|
|
52604
|
-
return
|
|
53162
|
+
return path43[path43.length - 1].position ?? 0;
|
|
52605
53163
|
}
|
|
52606
53164
|
getCounter() {
|
|
52607
|
-
const
|
|
52608
|
-
if (
|
|
53165
|
+
const path43 = this._matcher.path;
|
|
53166
|
+
if (path43.length === 0)
|
|
52609
53167
|
return -1;
|
|
52610
|
-
return
|
|
53168
|
+
return path43[path43.length - 1].counter ?? 0;
|
|
52611
53169
|
}
|
|
52612
53170
|
getIndex() {
|
|
52613
53171
|
return this.getPosition();
|
|
@@ -55620,7 +56178,7 @@ var youtubeFetcher = {
|
|
|
55620
56178
|
var youtube_default = youtubeFetcher;
|
|
55621
56179
|
|
|
55622
56180
|
// src/sources/snapshot-fetchers/registry.ts
|
|
55623
|
-
var FETCHER_DIR =
|
|
56181
|
+
var FETCHER_DIR = path43.join("scripts", "wiki-fetchers");
|
|
55624
56182
|
var FETCHER_FILE_PATTERN = /\.(?:ts|js|mjs)$/i;
|
|
55625
56183
|
var BUILTIN_FETCHERS = [
|
|
55626
56184
|
github_default,
|
|
@@ -55638,14 +56196,14 @@ function isWikiSnapshotFetcher(value) {
|
|
|
55638
56196
|
async function loadWikiSnapshotFetchers(stashDir) {
|
|
55639
56197
|
const fetchers = [];
|
|
55640
56198
|
if (stashDir) {
|
|
55641
|
-
const fetcherDir =
|
|
56199
|
+
const fetcherDir = path43.join(stashDir, FETCHER_DIR);
|
|
55642
56200
|
try {
|
|
55643
56201
|
const entries = fs38.readdirSync(fetcherDir).sort();
|
|
55644
56202
|
for (const entry of entries) {
|
|
55645
56203
|
if (!FETCHER_FILE_PATTERN.test(entry))
|
|
55646
56204
|
continue;
|
|
55647
56205
|
try {
|
|
55648
|
-
const fileUrl = pathToFileURL2(
|
|
56206
|
+
const fileUrl = pathToFileURL2(path43.join(fetcherDir, entry)).toString();
|
|
55649
56207
|
const mod = await import(fileUrl);
|
|
55650
56208
|
if (isWikiSnapshotFetcher(mod.default)) {
|
|
55651
56209
|
fetchers.push(mod.default);
|
|
@@ -55924,11 +56482,11 @@ function resolveFetcherStashDir(explicitStashDir) {
|
|
|
55924
56482
|
}
|
|
55925
56483
|
function getWebsiteCachePaths(siteUrl) {
|
|
55926
56484
|
const key = createHash5("sha256").update(normalizeSiteUrl(siteUrl)).digest("hex").slice(0, 16);
|
|
55927
|
-
const rootDir =
|
|
56485
|
+
const rootDir = path44.join(getRegistryIndexCacheDir(), `website-${key}`);
|
|
55928
56486
|
return {
|
|
55929
56487
|
rootDir,
|
|
55930
|
-
stashDir:
|
|
55931
|
-
manifestPath:
|
|
56488
|
+
stashDir: path44.join(rootDir, "stash"),
|
|
56489
|
+
manifestPath: path44.join(rootDir, "manifest.json")
|
|
55932
56490
|
};
|
|
55933
56491
|
}
|
|
55934
56492
|
async function ensureWebsiteMirror(config, options) {
|
|
@@ -55963,7 +56521,7 @@ async function ensureWebsiteMirror(config, options) {
|
|
|
55963
56521
|
}
|
|
55964
56522
|
function hasExtractedSite(stashDir) {
|
|
55965
56523
|
try {
|
|
55966
|
-
const knowledgeDir =
|
|
56524
|
+
const knowledgeDir = path44.join(stashDir, "knowledge");
|
|
55967
56525
|
if (!fs39.statSync(stashDir).isDirectory() || !fs39.statSync(knowledgeDir).isDirectory())
|
|
55968
56526
|
return false;
|
|
55969
56527
|
const pending = [knowledgeDir];
|
|
@@ -55975,7 +56533,7 @@ function hasExtractedSite(stashDir) {
|
|
|
55975
56533
|
if (entry.isFile() && entry.name.endsWith(".md"))
|
|
55976
56534
|
return true;
|
|
55977
56535
|
if (entry.isDirectory())
|
|
55978
|
-
pending.push(
|
|
56536
|
+
pending.push(path44.join(dir, entry.name));
|
|
55979
56537
|
}
|
|
55980
56538
|
}
|
|
55981
56539
|
return false;
|
|
@@ -56014,18 +56572,79 @@ async function fetchSnapshotViaRegistry(startUrl, stashDir, allowPrivateHosts, r
|
|
|
56014
56572
|
};
|
|
56015
56573
|
return dispatchSnapshotFetchers(parsed, context, stashDir);
|
|
56016
56574
|
}
|
|
56575
|
+
var snapshotWriteHookForTests;
|
|
56576
|
+
function snapshotWriteHook(event) {
|
|
56577
|
+
snapshotWriteHookForTests?.(event);
|
|
56578
|
+
}
|
|
56579
|
+
function snapshotSiblingPrefix(stashDir, kind) {
|
|
56580
|
+
return `.${path44.basename(stashDir)}.${kind}-`;
|
|
56581
|
+
}
|
|
56582
|
+
function snapshotSiblingPath(stashDir, kind) {
|
|
56583
|
+
const unique = `${process.pid}-${randomBytes3(6).toString("hex")}`;
|
|
56584
|
+
return path44.join(path44.dirname(stashDir), `${snapshotSiblingPrefix(stashDir, kind)}${unique}`);
|
|
56585
|
+
}
|
|
56586
|
+
var SNAPSHOT_STAGING_SWEEP_AGE_MS = 60 * 60 * 1000;
|
|
56587
|
+
function sweepSnapshotStaging(stashDir) {
|
|
56588
|
+
const parent = path44.dirname(stashDir);
|
|
56589
|
+
let entries;
|
|
56590
|
+
try {
|
|
56591
|
+
entries = fs39.readdirSync(parent);
|
|
56592
|
+
} catch {
|
|
56593
|
+
return;
|
|
56594
|
+
}
|
|
56595
|
+
const prefixes = [snapshotSiblingPrefix(stashDir, "staging"), snapshotSiblingPrefix(stashDir, "retired")];
|
|
56596
|
+
const cutoff = Date.now() - SNAPSHOT_STAGING_SWEEP_AGE_MS;
|
|
56597
|
+
for (const entry of entries) {
|
|
56598
|
+
if (!prefixes.some((prefix) => entry.startsWith(prefix)))
|
|
56599
|
+
continue;
|
|
56600
|
+
const abandoned = path44.join(parent, entry);
|
|
56601
|
+
try {
|
|
56602
|
+
if (fs39.statSync(abandoned).mtimeMs > cutoff)
|
|
56603
|
+
continue;
|
|
56604
|
+
} catch {
|
|
56605
|
+
continue;
|
|
56606
|
+
}
|
|
56607
|
+
fs39.rmSync(abandoned, { recursive: true, force: true });
|
|
56608
|
+
}
|
|
56609
|
+
}
|
|
56610
|
+
function beginSnapshotStaging(stashDir) {
|
|
56611
|
+
fs39.mkdirSync(path44.dirname(stashDir), { recursive: true });
|
|
56612
|
+
sweepSnapshotStaging(stashDir);
|
|
56613
|
+
const dir = snapshotSiblingPath(stashDir, "staging");
|
|
56614
|
+
fs39.mkdirSync(dir, { recursive: true });
|
|
56615
|
+
return { dir, target: stashDir };
|
|
56616
|
+
}
|
|
56617
|
+
function publishSnapshotStaging(staging) {
|
|
56618
|
+
let retired;
|
|
56619
|
+
if (fs39.existsSync(staging.target)) {
|
|
56620
|
+
retired = snapshotSiblingPath(staging.target, "retired");
|
|
56621
|
+
fs39.renameSync(staging.target, retired);
|
|
56622
|
+
}
|
|
56623
|
+
fs39.renameSync(staging.dir, staging.target);
|
|
56624
|
+
if (retired)
|
|
56625
|
+
fs39.rmSync(retired, { recursive: true, force: true });
|
|
56626
|
+
}
|
|
56627
|
+
function discardSnapshotStaging(staging) {
|
|
56628
|
+
fs39.rmSync(staging.dir, { recursive: true, force: true });
|
|
56629
|
+
}
|
|
56017
56630
|
function writeSnapshotToStash(stashDir, snapshot) {
|
|
56018
56631
|
const preferredName = snapshot.preferredName ?? deriveImportPath(snapshot.url);
|
|
56019
56632
|
const relPath = avoidReservedBasename2(preferredName);
|
|
56020
|
-
const knowledgeDir =
|
|
56021
|
-
|
|
56022
|
-
if (!isWithin(filePath, knowledgeDir)) {
|
|
56633
|
+
const knowledgeDir = path44.join(stashDir, "knowledge");
|
|
56634
|
+
if (!isWithin(path44.resolve(knowledgeDir, `${relPath}.md`), knowledgeDir)) {
|
|
56023
56635
|
throw new UsageError(`Snapshot fetcher returned an unsafe preferred name: ${JSON.stringify(preferredName)}`);
|
|
56024
56636
|
}
|
|
56025
|
-
|
|
56026
|
-
|
|
56027
|
-
|
|
56028
|
-
|
|
56637
|
+
const staging = beginSnapshotStaging(stashDir);
|
|
56638
|
+
try {
|
|
56639
|
+
const filePath = path44.resolve(path44.join(staging.dir, "knowledge"), `${relPath}.md`);
|
|
56640
|
+
fs39.mkdirSync(path44.dirname(filePath), { recursive: true });
|
|
56641
|
+
const slug = relPath.split("/").pop() ?? "index";
|
|
56642
|
+
fs39.writeFileSync(filePath, buildMarkdownSnapshot({ url: snapshot.url, title: snapshot.title, markdown: snapshot.markdown }, slug, snapshot.tags), "utf8");
|
|
56643
|
+
snapshotWriteHook({ point: "page-written", index: 1, total: 1, relPath: `knowledge/${relPath}.md` });
|
|
56644
|
+
publishSnapshotStaging(staging);
|
|
56645
|
+
} finally {
|
|
56646
|
+
discardSnapshotStaging(staging);
|
|
56647
|
+
}
|
|
56029
56648
|
}
|
|
56030
56649
|
async function scrapeWebsiteToStash(startUrl, stashDir, options) {
|
|
56031
56650
|
const fetched = await fetchSnapshotViaRegistry(startUrl, options.fetcherStashDir ?? null, options.allowPrivateHosts, options.resolveSecret);
|
|
@@ -56037,19 +56656,32 @@ async function scrapeWebsiteToStash(startUrl, stashDir, options) {
|
|
|
56037
56656
|
if (pages.length === 0) {
|
|
56038
56657
|
throw new Error(`No content could be scraped from ${startUrl}`);
|
|
56039
56658
|
}
|
|
56040
|
-
|
|
56041
|
-
|
|
56042
|
-
|
|
56043
|
-
|
|
56044
|
-
|
|
56045
|
-
|
|
56046
|
-
const
|
|
56047
|
-
|
|
56048
|
-
|
|
56049
|
-
|
|
56050
|
-
|
|
56051
|
-
|
|
56052
|
-
|
|
56659
|
+
const staging = beginSnapshotStaging(stashDir);
|
|
56660
|
+
try {
|
|
56661
|
+
const knowledgeDir = path44.join(staging.dir, "knowledge");
|
|
56662
|
+
fs39.mkdirSync(knowledgeDir, { recursive: true });
|
|
56663
|
+
const usedPaths = new Set;
|
|
56664
|
+
let written = 0;
|
|
56665
|
+
for (const page of pages) {
|
|
56666
|
+
const relPath = avoidReservedBasename2(urlToRelativePath(page.url));
|
|
56667
|
+
const uniquePath = uniqueSlug2(relPath, usedPaths);
|
|
56668
|
+
const filePath = path44.join(knowledgeDir, `${uniquePath}.md`);
|
|
56669
|
+
const dir = path44.dirname(filePath);
|
|
56670
|
+
if (dir !== knowledgeDir)
|
|
56671
|
+
fs39.mkdirSync(dir, { recursive: true });
|
|
56672
|
+
const slug = uniquePath.split("/").pop() ?? "index";
|
|
56673
|
+
fs39.writeFileSync(filePath, buildMarkdownSnapshot(page, slug), "utf8");
|
|
56674
|
+
written++;
|
|
56675
|
+
snapshotWriteHook({
|
|
56676
|
+
point: "page-written",
|
|
56677
|
+
index: written,
|
|
56678
|
+
total: pages.length,
|
|
56679
|
+
relPath: `knowledge/${uniquePath}.md`
|
|
56680
|
+
});
|
|
56681
|
+
}
|
|
56682
|
+
publishSnapshotStaging(staging);
|
|
56683
|
+
} finally {
|
|
56684
|
+
discardSnapshotStaging(staging);
|
|
56053
56685
|
}
|
|
56054
56686
|
}
|
|
56055
56687
|
function sleep(ms) {
|
|
@@ -56593,7 +57225,7 @@ function resolveEntryContentDir(entry) {
|
|
|
56593
57225
|
var SUSPICIOUS_ROOTS = new Set(["/", "/etc", "/bin", "/sbin", "/usr", "/var", "/tmp", "/dev", "/proc", "/sys"]);
|
|
56594
57226
|
|
|
56595
57227
|
// src/tasks/parser.ts
|
|
56596
|
-
import
|
|
57228
|
+
import path45 from "path";
|
|
56597
57229
|
init_errors();
|
|
56598
57230
|
|
|
56599
57231
|
// src/tasks/task-id.ts
|
|
@@ -56666,15 +57298,21 @@ function parseTaskDocument(input) {
|
|
|
56666
57298
|
}
|
|
56667
57299
|
let target;
|
|
56668
57300
|
if (hasWorkflow) {
|
|
56669
|
-
rejectTargetFields(data, ["params"], id, filePath);
|
|
57301
|
+
rejectTargetFields(data, ["params", "timeoutMs", "maxSteps", "maxRetries"], id, filePath);
|
|
56670
57302
|
const ref = requireString(data.workflow, "workflow", filePath);
|
|
56671
57303
|
if (!ref) {
|
|
56672
57304
|
throw new UsageError(`Task "${id}" has empty \`workflow\`. File: ${filePath}`, "INVALID_FLAG_VALUE");
|
|
56673
57305
|
}
|
|
57306
|
+
const workflowTimeoutMs = readTimeout(data.timeoutMs, filePath);
|
|
57307
|
+
const maxSteps = readBoundedInteger(data.maxSteps, "maxSteps", 1, undefined, filePath);
|
|
57308
|
+
const maxRetries = readBoundedInteger(data.maxRetries, "maxRetries", 0, WORKFLOW_MAX_RETRIES, filePath);
|
|
56674
57309
|
target = {
|
|
56675
57310
|
kind: "workflow",
|
|
56676
57311
|
ref,
|
|
56677
|
-
params: readParams(data.params, filePath)
|
|
57312
|
+
params: readParams(data.params, filePath),
|
|
57313
|
+
...workflowTimeoutMs !== undefined ? { timeoutMs: workflowTimeoutMs } : {},
|
|
57314
|
+
...maxSteps !== undefined ? { maxSteps } : {},
|
|
57315
|
+
...maxRetries !== undefined ? { maxRetries } : {}
|
|
56678
57316
|
};
|
|
56679
57317
|
} else if (hasCommand) {
|
|
56680
57318
|
rejectTargetFields(data, ["timeoutMs"], id, filePath);
|
|
@@ -56699,6 +57337,7 @@ function parseTaskDocument(input) {
|
|
|
56699
57337
|
};
|
|
56700
57338
|
}
|
|
56701
57339
|
const timeoutMs = hasCommand ? readTimeout(data.timeoutMs, filePath) : undefined;
|
|
57340
|
+
const redact = readRedactNames(data.redact, filePath);
|
|
56702
57341
|
return {
|
|
56703
57342
|
version: TASK_SCHEMA_VERSION,
|
|
56704
57343
|
schemaVersion: TASK_SCHEMA_VERSION,
|
|
@@ -56711,7 +57350,8 @@ function parseTaskDocument(input) {
|
|
|
56711
57350
|
...when_to_use ? { when_to_use } : {},
|
|
56712
57351
|
...tags ? { tags } : {},
|
|
56713
57352
|
source: { path: filePath },
|
|
56714
|
-
timeoutMs
|
|
57353
|
+
timeoutMs,
|
|
57354
|
+
...redact ? { redact } : {}
|
|
56715
57355
|
};
|
|
56716
57356
|
}
|
|
56717
57357
|
var TASK_KEYS = new Set([
|
|
@@ -56729,9 +57369,21 @@ var TASK_KEYS = new Set([
|
|
|
56729
57369
|
"engine",
|
|
56730
57370
|
"model",
|
|
56731
57371
|
"timeoutMs",
|
|
56732
|
-
"
|
|
57372
|
+
"maxSteps",
|
|
57373
|
+
"maxRetries",
|
|
57374
|
+
"llm",
|
|
57375
|
+
"redact"
|
|
57376
|
+
]);
|
|
57377
|
+
var SHARED_KEYS = new Set([
|
|
57378
|
+
"version",
|
|
57379
|
+
"name",
|
|
57380
|
+
"description",
|
|
57381
|
+
"when_to_use",
|
|
57382
|
+
"tags",
|
|
57383
|
+
"schedule",
|
|
57384
|
+
"enabled",
|
|
57385
|
+
"redact"
|
|
56733
57386
|
]);
|
|
56734
|
-
var SHARED_KEYS = new Set(["version", "name", "description", "when_to_use", "tags", "schedule", "enabled"]);
|
|
56735
57387
|
function requireVersion(data, id, filePath) {
|
|
56736
57388
|
if (data.version === TASK_SCHEMA_VERSION)
|
|
56737
57389
|
return;
|
|
@@ -56755,7 +57407,7 @@ function resolvePromptSource(raw, filePath, id) {
|
|
|
56755
57407
|
if (!trimmed) {
|
|
56756
57408
|
throw new UsageError(`Task "${id}" has empty \`prompt\`. File: ${filePath}`, "MISSING_REQUIRED_ARGUMENT");
|
|
56757
57409
|
}
|
|
56758
|
-
if (trimmed.startsWith("./") || trimmed.startsWith("../") ||
|
|
57410
|
+
if (trimmed.startsWith("./") || trimmed.startsWith("../") || path45.isAbsolute(trimmed)) {
|
|
56759
57411
|
return { kind: "file", path: trimmed };
|
|
56760
57412
|
}
|
|
56761
57413
|
if (/^[A-Za-z]:[\\/]/.test(trimmed)) {
|
|
@@ -56831,9 +57483,39 @@ function readTimeout(value, filePath) {
|
|
|
56831
57483
|
return;
|
|
56832
57484
|
if (value === null)
|
|
56833
57485
|
return null;
|
|
56834
|
-
if (typeof value === "number" && Number.isInteger(value) && value > 0)
|
|
57486
|
+
if (typeof value === "number" && Number.isInteger(value) && value > 0 && value <= TASK_MAX_TIMEOUT_MS)
|
|
56835
57487
|
return value;
|
|
56836
|
-
throw new UsageError(`Key "timeoutMs" must be
|
|
57488
|
+
throw new UsageError(`Key "timeoutMs" must be an integer from 1 through ${TASK_MAX_TIMEOUT_MS}, or null. File: ${filePath}`, "INVALID_FLAG_VALUE");
|
|
57489
|
+
}
|
|
57490
|
+
function readRedactNames(value, filePath) {
|
|
57491
|
+
if (value === undefined || value === null)
|
|
57492
|
+
return;
|
|
57493
|
+
const invalid = (detail) => {
|
|
57494
|
+
throw new UsageError(`Key "redact" ${detail}. File: ${filePath}`, "INVALID_FLAG_VALUE");
|
|
57495
|
+
};
|
|
57496
|
+
if (!Array.isArray(value))
|
|
57497
|
+
return invalid("must be a list of environment variable names");
|
|
57498
|
+
if (value.length > TASK_MAX_REDACT_NAMES) {
|
|
57499
|
+
return invalid(`accepts at most ${TASK_MAX_REDACT_NAMES} names (got ${value.length})`);
|
|
57500
|
+
}
|
|
57501
|
+
const names = [];
|
|
57502
|
+
for (const entry of value) {
|
|
57503
|
+
if (typeof entry !== "string" || !WORKFLOW_ENV_VAR_NAME_PATTERN.test(entry)) {
|
|
57504
|
+
return invalid(`takes environment variable NAMES only (matching ${WORKFLOW_ENV_VAR_NAME_PATTERN.source}), not values \u2014 ` + `got ${JSON.stringify(entry)}. A secret written here would be indexed and printed by \`akm show\``);
|
|
57505
|
+
}
|
|
57506
|
+
if (!names.includes(entry))
|
|
57507
|
+
names.push(entry);
|
|
57508
|
+
}
|
|
57509
|
+
return names.length > 0 ? names : undefined;
|
|
57510
|
+
}
|
|
57511
|
+
function readBoundedInteger(value, key, minimum, maximum, filePath) {
|
|
57512
|
+
if (value === undefined || value === null)
|
|
57513
|
+
return;
|
|
57514
|
+
if (typeof value === "number" && Number.isSafeInteger(value) && value >= minimum && (maximum === undefined || value <= maximum)) {
|
|
57515
|
+
return value;
|
|
57516
|
+
}
|
|
57517
|
+
const range = maximum === undefined ? `at least ${minimum}` : `from ${minimum} through ${maximum}`;
|
|
57518
|
+
throw new UsageError(`Key "${key}" must be an integer ${range}. File: ${filePath}`, "INVALID_FLAG_VALUE");
|
|
56837
57519
|
}
|
|
56838
57520
|
function readLlmOverrides(value, filePath) {
|
|
56839
57521
|
if (value === undefined)
|
|
@@ -57099,7 +57781,7 @@ function expandTilde2(value) {
|
|
|
57099
57781
|
if (value === "~")
|
|
57100
57782
|
return os5.homedir();
|
|
57101
57783
|
if (value.startsWith("~/") || value.startsWith("~\\"))
|
|
57102
|
-
return
|
|
57784
|
+
return path46.join(os5.homedir(), value.slice(2));
|
|
57103
57785
|
return value;
|
|
57104
57786
|
}
|
|
57105
57787
|
function bundlesFromConfig(config, pathResolutionBase, migrationLockEntries) {
|
|
@@ -57118,7 +57800,7 @@ function bundlesFromConfig(config, pathResolutionBase, migrationLockEntries) {
|
|
|
57118
57800
|
const contentDir = lockRoots.get(id) ?? resolveEntryContentDir(sourceEntry);
|
|
57119
57801
|
if (!contentDir)
|
|
57120
57802
|
continue;
|
|
57121
|
-
const root2 =
|
|
57803
|
+
const root2 = path46.resolve(pathResolutionBase, expandTilde2(contentDir));
|
|
57122
57804
|
const rootIdentity = fs40.existsSync(root2) ? fs40.realpathSync(root2) : root2;
|
|
57123
57805
|
const prior = roots.get(rootIdentity);
|
|
57124
57806
|
if (prior && prior !== id) {
|
|
@@ -57163,21 +57845,21 @@ function resolveOrigin(origin, bundles, filePath) {
|
|
|
57163
57845
|
return candidate;
|
|
57164
57846
|
}
|
|
57165
57847
|
function assertWorkflowPathSafe(bundle, name, rawRef, filePath) {
|
|
57166
|
-
const candidate = resolveAssetPathFromName("workflow",
|
|
57848
|
+
const candidate = resolveAssetPathFromName("workflow", path46.join(bundle.root, "workflows"), name);
|
|
57167
57849
|
if (!fs40.existsSync(candidate))
|
|
57168
57850
|
return;
|
|
57169
57851
|
if (!fs40.statSync(candidate).isFile())
|
|
57170
57852
|
throw migrationError(filePath, `legacy target "${rawRef}" is not a file in bundle "${bundle.id}".`);
|
|
57171
57853
|
const realRoot = fs40.realpathSync(bundle.root);
|
|
57172
57854
|
const realCandidate = fs40.realpathSync(candidate);
|
|
57173
|
-
const relative =
|
|
57174
|
-
if (relative.startsWith("..") ||
|
|
57855
|
+
const relative = path46.relative(realRoot, realCandidate);
|
|
57856
|
+
if (relative.startsWith("..") || path46.isAbsolute(relative)) {
|
|
57175
57857
|
throw migrationError(filePath, `legacy target "${rawRef}" resolves outside bundle "${bundle.id}".`);
|
|
57176
57858
|
}
|
|
57177
57859
|
}
|
|
57178
57860
|
function assertRealPathWithin(root2, candidate, filePath, detail) {
|
|
57179
|
-
const relative =
|
|
57180
|
-
if (relative.startsWith("..") ||
|
|
57861
|
+
const relative = path46.relative(fs40.realpathSync(root2), fs40.realpathSync(candidate));
|
|
57862
|
+
if (relative.startsWith("..") || path46.isAbsolute(relative))
|
|
57181
57863
|
throw migrationError(filePath, detail);
|
|
57182
57864
|
}
|
|
57183
57865
|
function planTaskFile(filePath, containing, bundles) {
|
|
@@ -57228,7 +57910,7 @@ function planTaskFile(filePath, containing, bundles) {
|
|
|
57228
57910
|
}
|
|
57229
57911
|
const after = Buffer.from($stringify(normalized));
|
|
57230
57912
|
try {
|
|
57231
|
-
parseTaskDocument({ yaml: after.toString("utf8"), filePath, id:
|
|
57913
|
+
parseTaskDocument({ yaml: after.toString("utf8"), filePath, id: path46.basename(filePath, ".yml") });
|
|
57232
57914
|
} catch (error2) {
|
|
57233
57915
|
throw migrationError(filePath, `the converted v2 task is invalid (${error2 instanceof Error ? error2.message : String(error2)}).`);
|
|
57234
57916
|
}
|
|
@@ -57254,7 +57936,7 @@ function planTaskTargetRefMigration(config, pathResolutionBase = process.cwd(),
|
|
|
57254
57936
|
}
|
|
57255
57937
|
continue;
|
|
57256
57938
|
}
|
|
57257
|
-
const tasksDir =
|
|
57939
|
+
const tasksDir = path46.join(bundle.root, "tasks");
|
|
57258
57940
|
if (!fs40.existsSync(tasksDir))
|
|
57259
57941
|
continue;
|
|
57260
57942
|
const tasksStat = fs40.lstatSync(tasksDir);
|
|
@@ -57268,7 +57950,7 @@ function planTaskTargetRefMigration(config, pathResolutionBase = process.cwd(),
|
|
|
57268
57950
|
for (const entry of fs40.readdirSync(tasksDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
57269
57951
|
if (!entry.name.endsWith(".yml"))
|
|
57270
57952
|
continue;
|
|
57271
|
-
const filePath =
|
|
57953
|
+
const filePath = path46.join(tasksDir, entry.name);
|
|
57272
57954
|
if (!entry.isFile())
|
|
57273
57955
|
throw migrationError(filePath, "task migration does not follow symbolic links or special files.");
|
|
57274
57956
|
assertRealPathWithin(bundle.root, filePath, filePath, "the task file resolves outside its bundle.");
|
|
@@ -57280,7 +57962,7 @@ function planTaskTargetRefMigration(config, pathResolutionBase = process.cwd(),
|
|
|
57280
57962
|
return { rewrites, durabilityPaths, readOnlyLegacyTasks };
|
|
57281
57963
|
}
|
|
57282
57964
|
function legacyTaskFilesIn(bundle) {
|
|
57283
|
-
const tasksDir =
|
|
57965
|
+
const tasksDir = path46.join(bundle.root, "tasks");
|
|
57284
57966
|
let entries;
|
|
57285
57967
|
try {
|
|
57286
57968
|
entries = fs40.readdirSync(tasksDir, { withFileTypes: true });
|
|
@@ -57292,7 +57974,7 @@ function legacyTaskFilesIn(bundle) {
|
|
|
57292
57974
|
if (!entry.isFile() || !entry.name.endsWith(".yml"))
|
|
57293
57975
|
continue;
|
|
57294
57976
|
try {
|
|
57295
|
-
const doc = $parseDocument(fs40.readFileSync(
|
|
57977
|
+
const doc = $parseDocument(fs40.readFileSync(path46.join(tasksDir, entry.name), "utf8"), { uniqueKeys: true });
|
|
57296
57978
|
if (doc.errors.length > 0 || !$isMap(doc.contents)) {
|
|
57297
57979
|
legacy.push(entry.name);
|
|
57298
57980
|
continue;
|
|
@@ -57307,7 +57989,7 @@ function legacyTaskFilesIn(bundle) {
|
|
|
57307
57989
|
return legacy;
|
|
57308
57990
|
}
|
|
57309
57991
|
function syncParentDirectory(filePath) {
|
|
57310
|
-
const fd = fs40.openSync(
|
|
57992
|
+
const fd = fs40.openSync(path46.dirname(filePath), "r");
|
|
57311
57993
|
try {
|
|
57312
57994
|
fs40.fsyncSync(fd);
|
|
57313
57995
|
} finally {
|
|
@@ -57367,7 +58049,7 @@ init_database();
|
|
|
57367
58049
|
init_sqlite_pragmas();
|
|
57368
58050
|
import crypto5 from "crypto";
|
|
57369
58051
|
import fs41 from "fs";
|
|
57370
|
-
import
|
|
58052
|
+
import path47 from "path";
|
|
57371
58053
|
class CutoverIntegrityError extends Error {
|
|
57372
58054
|
constructor(message) {
|
|
57373
58055
|
super(message);
|
|
@@ -57431,7 +58113,7 @@ function walkLegacyLayoutInto(map, root2) {
|
|
|
57431
58113
|
else
|
|
57432
58114
|
return;
|
|
57433
58115
|
for (const [type, dirName] of Object.entries(TYPE_DIRS)) {
|
|
57434
|
-
const typeRoot =
|
|
58116
|
+
const typeRoot = path47.join(root2.path, dirName);
|
|
57435
58117
|
let files;
|
|
57436
58118
|
try {
|
|
57437
58119
|
files = listFilesRecursive(typeRoot);
|
|
@@ -57468,14 +58150,14 @@ function safeDerive(type, typeRoot, filePath) {
|
|
|
57468
58150
|
}
|
|
57469
58151
|
}
|
|
57470
58152
|
function basenameSlug(sourcePath) {
|
|
57471
|
-
const base =
|
|
58153
|
+
const base = path47.basename(path47.resolve(sourcePath)).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
57472
58154
|
return base.length > 0 ? base : "bundle";
|
|
57473
58155
|
}
|
|
57474
58156
|
function listFilesRecursive(dir) {
|
|
57475
58157
|
const out = [];
|
|
57476
58158
|
const walk = (current) => {
|
|
57477
58159
|
for (const entry of fs41.readdirSync(current, { withFileTypes: true })) {
|
|
57478
|
-
const abs =
|
|
58160
|
+
const abs = path47.join(current, entry.name);
|
|
57479
58161
|
if (entry.isDirectory())
|
|
57480
58162
|
walk(abs);
|
|
57481
58163
|
else if (entry.isFile())
|
|
@@ -57488,10 +58170,10 @@ function listFilesRecursive(dir) {
|
|
|
57488
58170
|
function samePath(a, b) {
|
|
57489
58171
|
if (!b)
|
|
57490
58172
|
return false;
|
|
57491
|
-
return
|
|
58173
|
+
return path47.resolve(a) === path47.resolve(b);
|
|
57492
58174
|
}
|
|
57493
58175
|
function persistRefMapJson(outputPath, map) {
|
|
57494
|
-
fs41.mkdirSync(
|
|
58176
|
+
fs41.mkdirSync(path47.dirname(outputPath), { recursive: true, mode: 448 });
|
|
57495
58177
|
const entries = Object.fromEntries([...map.entries()].sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
|
|
57496
58178
|
const payload = { formatVersion: CUTOVER_REFMAP_FORMAT, entries };
|
|
57497
58179
|
writeFileAtomic(outputPath, `${JSON.stringify(payload, null, 2)}
|
|
@@ -57529,7 +58211,7 @@ function completeCutoverRefMap(inputPath, outputPath) {
|
|
|
57529
58211
|
function loadCompletedCutoverRefMap(inputPath) {
|
|
57530
58212
|
return { map: loadCutoverRefMap(inputPath) };
|
|
57531
58213
|
}
|
|
57532
|
-
var PILOT_TREATMENT_FILE =
|
|
58214
|
+
var PILOT_TREATMENT_FILE = path47.join(".akm", "measurement", "treatment-pilot-2026-06-14.txt");
|
|
57533
58215
|
function fsyncPilotTreatmentDirectory(directory) {
|
|
57534
58216
|
let fd;
|
|
57535
58217
|
try {
|
|
@@ -57548,8 +58230,8 @@ function migratePilotTreatmentFiles(stashRoots, refMap) {
|
|
|
57548
58230
|
let migrated = 0;
|
|
57549
58231
|
const seen = new Set;
|
|
57550
58232
|
for (const root2 of stashRoots) {
|
|
57551
|
-
const file =
|
|
57552
|
-
const resolved =
|
|
58233
|
+
const file = path47.join(root2.path, PILOT_TREATMENT_FILE);
|
|
58234
|
+
const resolved = path47.resolve(file);
|
|
57553
58235
|
if (seen.has(resolved) || !fs41.existsSync(file))
|
|
57554
58236
|
continue;
|
|
57555
58237
|
seen.add(resolved);
|
|
@@ -57568,7 +58250,7 @@ function migratePilotTreatmentFiles(stashRoots, refMap) {
|
|
|
57568
58250
|
}).join(`
|
|
57569
58251
|
`);
|
|
57570
58252
|
if (rewritten === original) {
|
|
57571
|
-
fsyncPilotTreatmentDirectory(
|
|
58253
|
+
fsyncPilotTreatmentDirectory(path47.dirname(file));
|
|
57572
58254
|
continue;
|
|
57573
58255
|
}
|
|
57574
58256
|
const mode = fs41.statSync(file).mode & 511;
|
|
@@ -57586,7 +58268,7 @@ function migratePilotTreatmentFiles(stashRoots, refMap) {
|
|
|
57586
58268
|
}
|
|
57587
58269
|
fs41.renameSync(tmp, file);
|
|
57588
58270
|
ownsTmp = false;
|
|
57589
|
-
fsyncPilotTreatmentDirectory(
|
|
58271
|
+
fsyncPilotTreatmentDirectory(path47.dirname(file));
|
|
57590
58272
|
} catch (error2) {
|
|
57591
58273
|
if (ownsTmp)
|
|
57592
58274
|
fs41.rmSync(tmp, { force: true });
|
|
@@ -57677,7 +58359,7 @@ function rekeyStateDbCore(db, refMap) {
|
|
|
57677
58359
|
function rekeyStateDb(dbPath, refMap) {
|
|
57678
58360
|
const db = openDatabaseFinalizing(dbPath);
|
|
57679
58361
|
try {
|
|
57680
|
-
applyStandardPragmas(db, { dataDir:
|
|
58362
|
+
applyStandardPragmas(db, { dataDir: path47.dirname(dbPath) });
|
|
57681
58363
|
let report = emptyReport2();
|
|
57682
58364
|
db.transaction(() => {
|
|
57683
58365
|
report = rekeyStateDbCore(db, refMap);
|
|
@@ -58174,7 +58856,7 @@ assertMigrationRegistry(FROZEN_WORKFLOW_MIGRATIONS);
|
|
|
58174
58856
|
// scripts/akm-migrate/migration-backup.ts
|
|
58175
58857
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
58176
58858
|
import fs42 from "fs";
|
|
58177
|
-
import
|
|
58859
|
+
import path48 from "path";
|
|
58178
58860
|
init_common();
|
|
58179
58861
|
|
|
58180
58862
|
// src/core/config/config-version.ts
|
|
@@ -58225,7 +58907,7 @@ function getMigrationBackupDir(runId) {
|
|
|
58225
58907
|
if (!/^[A-Za-z0-9._-]+$/.test(runId)) {
|
|
58226
58908
|
throw new ConfigError(`Invalid migration backup run ID ${JSON.stringify(runId)}.`, "INVALID_CONFIG_FILE");
|
|
58227
58909
|
}
|
|
58228
|
-
return
|
|
58910
|
+
return path48.join(getMigrationBackupRoot(), runId);
|
|
58229
58911
|
}
|
|
58230
58912
|
function expectedSourcePaths() {
|
|
58231
58913
|
return {
|
|
@@ -58260,7 +58942,7 @@ function fsyncDirectory(directory) {
|
|
|
58260
58942
|
}
|
|
58261
58943
|
}
|
|
58262
58944
|
function copyFileDurable(source, destination) {
|
|
58263
|
-
fs42.mkdirSync(
|
|
58945
|
+
fs42.mkdirSync(path48.dirname(destination), { recursive: true, mode: 448 });
|
|
58264
58946
|
fs42.copyFileSync(source, destination, fs42.constants.COPYFILE_EXCL);
|
|
58265
58947
|
fs42.chmodSync(destination, 384);
|
|
58266
58948
|
fsyncFile(destination);
|
|
@@ -58386,8 +59068,8 @@ function sqliteQuote2(value) {
|
|
|
58386
59068
|
return `'${value.replaceAll("'", "''")}'`;
|
|
58387
59069
|
}
|
|
58388
59070
|
function backupSqlite(source, destination) {
|
|
58389
|
-
const resolved =
|
|
58390
|
-
const releaseActivity = resolved ===
|
|
59071
|
+
const resolved = path48.resolve(source);
|
|
59072
|
+
const releaseActivity = resolved === path48.resolve(getStateDbPathInDataDir()) ? acquireMaintenanceActivitySync("state-db") : resolved === path48.resolve(getLegacyWorkflowDbPath()) ? acquireMaintenanceActivitySync("workflow-db") : undefined;
|
|
58391
59073
|
let db;
|
|
58392
59074
|
try {
|
|
58393
59075
|
db = openDatabaseFinalizing(source);
|
|
@@ -58404,8 +59086,8 @@ function backupSqlite(source, destination) {
|
|
|
58404
59086
|
fsyncFile(destination);
|
|
58405
59087
|
}
|
|
58406
59088
|
function acquireBackupLock() {
|
|
58407
|
-
const lockPath =
|
|
58408
|
-
fs42.mkdirSync(
|
|
59089
|
+
const lockPath = path48.join(getMigrationBackupRoot(), ".lock");
|
|
59090
|
+
fs42.mkdirSync(path48.dirname(lockPath), { recursive: true, mode: 448 });
|
|
58409
59091
|
for (let attempt = 0;attempt < 50; attempt += 1) {
|
|
58410
59092
|
const ownership = tryAcquireLockSync(lockPath, createLockPayload());
|
|
58411
59093
|
if (ownership)
|
|
@@ -58435,8 +59117,8 @@ function createMigrationBackupUnlocked(options = {}) {
|
|
|
58435
59117
|
fs42.mkdirSync(root2, { recursive: true, mode: 448 });
|
|
58436
59118
|
fs42.chmodSync(root2, 448);
|
|
58437
59119
|
const runId = newRunId();
|
|
58438
|
-
const bundlePath =
|
|
58439
|
-
const temporary =
|
|
59120
|
+
const bundlePath = path48.join(root2, runId);
|
|
59121
|
+
const temporary = path48.join(root2, `.${runId}.tmp`);
|
|
58440
59122
|
fs42.mkdirSync(temporary, { mode: 448 });
|
|
58441
59123
|
const createdAt = new Date().toISOString();
|
|
58442
59124
|
const sources = expectedSourcePaths();
|
|
@@ -58446,7 +59128,7 @@ function createMigrationBackupUnlocked(options = {}) {
|
|
|
58446
59128
|
const sourcePath = sources[name];
|
|
58447
59129
|
const sourceState = stateForName(state, name);
|
|
58448
59130
|
const present = sourceState.status !== "missing";
|
|
58449
|
-
const destination =
|
|
59131
|
+
const destination = path48.join(temporary, name);
|
|
58450
59132
|
if (present) {
|
|
58451
59133
|
if (name === "config.json" || name === "index.db" && sourceState.status === "corrupt") {
|
|
58452
59134
|
copyFileDurable(sourcePath, destination);
|
|
@@ -58464,13 +59146,13 @@ function createMigrationBackupUnlocked(options = {}) {
|
|
|
58464
59146
|
formatVersion: MANIFEST_FORMAT_VERSION,
|
|
58465
59147
|
version: MIGRATION_BACKUP_VERSION,
|
|
58466
59148
|
targetVersion: MIGRATION_BACKUP_VERSION,
|
|
58467
|
-
installationId:
|
|
59149
|
+
installationId: path48.basename(getMigrationOperationRoot()),
|
|
58468
59150
|
runId,
|
|
58469
59151
|
createdAt,
|
|
58470
59152
|
complete: true,
|
|
58471
59153
|
artifacts
|
|
58472
59154
|
};
|
|
58473
|
-
writeFileAtomic(
|
|
59155
|
+
writeFileAtomic(path48.join(temporary, "manifest.json"), `${JSON.stringify(manifest, null, 2)}
|
|
58474
59156
|
`, 384);
|
|
58475
59157
|
fsyncDirectory(temporary);
|
|
58476
59158
|
fs42.renameSync(temporary, bundlePath);
|
|
@@ -58482,7 +59164,7 @@ function createMigrationBackupUnlocked(options = {}) {
|
|
|
58482
59164
|
}
|
|
58483
59165
|
}
|
|
58484
59166
|
function parseManifest(bundlePath) {
|
|
58485
|
-
const manifestPath =
|
|
59167
|
+
const manifestPath = path48.join(bundlePath, "manifest.json");
|
|
58486
59168
|
let value;
|
|
58487
59169
|
try {
|
|
58488
59170
|
value = JSON.parse(readTextFileWithLimit(manifestPath, MAX_LOCAL_METADATA_BYTES, "Migration manifest"));
|
|
@@ -58490,7 +59172,7 @@ function parseManifest(bundlePath) {
|
|
|
58490
59172
|
throw new ConfigError(`Migration backup at ${bundlePath} is incomplete or unreadable: ${error2 instanceof Error ? error2.message : String(error2)}.`, "INVALID_CONFIG_FILE");
|
|
58491
59173
|
}
|
|
58492
59174
|
const manifest = value;
|
|
58493
|
-
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || manifest.formatVersion !== MANIFEST_FORMAT_VERSION || manifest.version !== MIGRATION_BACKUP_VERSION || manifest.targetVersion !== MIGRATION_BACKUP_VERSION || manifest.installationId !==
|
|
59175
|
+
if (!manifest || typeof manifest !== "object" || Array.isArray(manifest) || manifest.formatVersion !== MANIFEST_FORMAT_VERSION || manifest.version !== MIGRATION_BACKUP_VERSION || manifest.targetVersion !== MIGRATION_BACKUP_VERSION || manifest.installationId !== path48.basename(getMigrationOperationRoot()) || typeof manifest.runId !== "string" || path48.basename(bundlePath) !== manifest.runId || typeof manifest.createdAt !== "string" || manifest.complete !== true) {
|
|
58494
59176
|
throw new ConfigError(`Migration backup manifest at ${manifestPath} is invalid.`, "INVALID_CONFIG_FILE");
|
|
58495
59177
|
}
|
|
58496
59178
|
const sources = expectedSourcePaths();
|
|
@@ -58514,7 +59196,7 @@ function verifyMigrationBackup(bundlePath = resolveBackupRun()) {
|
|
|
58514
59196
|
const expectedFiles = new Set(["manifest.json"]);
|
|
58515
59197
|
for (const name of ARTIFACT_NAMES) {
|
|
58516
59198
|
const artifact = manifest.artifacts[name];
|
|
58517
|
-
const artifactPath =
|
|
59199
|
+
const artifactPath = path48.join(bundlePath, name);
|
|
58518
59200
|
if (!artifact.present) {
|
|
58519
59201
|
if (fs42.existsSync(artifactPath)) {
|
|
58520
59202
|
throw new ConfigError(`Migration backup contains unexpected ${name}.`, "INVALID_CONFIG_FILE");
|
|
@@ -58530,7 +59212,7 @@ function verifyMigrationBackup(bundlePath = resolveBackupRun()) {
|
|
|
58530
59212
|
throw new ConfigError(`Migration backup artifact ${name} failed semantic verification: expected ${artifact.status}, got ${inspected.status}.`, "INVALID_CONFIG_FILE");
|
|
58531
59213
|
}
|
|
58532
59214
|
}
|
|
58533
|
-
if (!ownerOnlyMode(
|
|
59215
|
+
if (!ownerOnlyMode(path48.join(bundlePath, "manifest.json"), false)) {
|
|
58534
59216
|
throw new ConfigError("Migration backup manifest must have mode 0600.", "INVALID_CONFIG_FILE");
|
|
58535
59217
|
}
|
|
58536
59218
|
const extras = fs42.readdirSync(bundlePath).filter((name) => !expectedFiles.has(name));
|
|
@@ -58552,17 +59234,17 @@ function expandTilde3(value) {
|
|
|
58552
59234
|
if (value === "~")
|
|
58553
59235
|
return process.env.HOME ?? value;
|
|
58554
59236
|
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
58555
|
-
return
|
|
59237
|
+
return path48.join(process.env.HOME ?? "~", value.slice(2));
|
|
58556
59238
|
}
|
|
58557
59239
|
return value;
|
|
58558
59240
|
}
|
|
58559
59241
|
function resolveStashRoot(value, pathResolutionBase = process.cwd()) {
|
|
58560
|
-
return
|
|
59242
|
+
return path48.resolve(pathResolutionBase, expandTilde3(value));
|
|
58561
59243
|
}
|
|
58562
59244
|
function configStashRoots(configPath, pathResolutionBase = process.cwd()) {
|
|
58563
59245
|
try {
|
|
58564
59246
|
const raw = parseConfigText(readTextFileWithLimit(configPath, MAX_CONFIG_FILE_BYTES, "Migration config"), configPath);
|
|
58565
|
-
const roots = new Set(oldConfigToSearchSources(raw, pathResolutionBase).map((source) =>
|
|
59247
|
+
const roots = new Set(oldConfigToSearchSources(raw, pathResolutionBase).map((source) => path48.resolve(source.path)));
|
|
58566
59248
|
const migrated = migrateConfigSourcesToBundles(raw);
|
|
58567
59249
|
const bundles = migrated.bundles;
|
|
58568
59250
|
if (bundles && typeof bundles === "object" && !Array.isArray(bundles)) {
|
|
@@ -58605,7 +59287,7 @@ function currentStashRoots() {
|
|
|
58605
59287
|
}
|
|
58606
59288
|
function lockFiles(directory) {
|
|
58607
59289
|
try {
|
|
58608
|
-
const paths = fs42.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".lock")).map((entry) =>
|
|
59290
|
+
const paths = fs42.readdirSync(directory, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".lock")).map((entry) => path48.join(directory, entry.name));
|
|
58609
59291
|
return { paths: paths.slice(0, LOCK_FILE_SAMPLE_LIMIT), overflow: paths.length > LOCK_FILE_SAMPLE_LIMIT };
|
|
58610
59292
|
} catch (error2) {
|
|
58611
59293
|
if (error2.code === "ENOENT")
|
|
@@ -58615,19 +59297,19 @@ function lockFiles(directory) {
|
|
|
58615
59297
|
}
|
|
58616
59298
|
function activeLockPaths(stashRoots = []) {
|
|
58617
59299
|
const dataDir = getDataDir();
|
|
58618
|
-
const configLock =
|
|
58619
|
-
const roots = new Set([...currentStashRoots(), ...stashRoots.map((root2) =>
|
|
58620
|
-
const lockBases = [dataDir, ...[...roots].map((root2) =>
|
|
59300
|
+
const configLock = path48.join(path48.dirname(getConfigPath()), "config.json.lck");
|
|
59301
|
+
const roots = new Set([...currentStashRoots(), ...stashRoots.map((root2) => path48.resolve(root2))]);
|
|
59302
|
+
const lockBases = [dataDir, ...[...roots].map((root2) => path48.join(root2, ".akm"))];
|
|
58621
59303
|
const lockDirectories = lockBases.flatMap((base) => [
|
|
58622
|
-
|
|
58623
|
-
|
|
59304
|
+
path48.join(base, "extract-locks"),
|
|
59305
|
+
path48.join(base, "maintenance-activities")
|
|
58624
59306
|
]);
|
|
58625
59307
|
const samples = lockDirectories.map((directory) => ({ directory, ...lockFiles(directory) }));
|
|
58626
59308
|
const candidates = new Set([
|
|
58627
59309
|
configLock,
|
|
58628
59310
|
getLockfileLockPath(),
|
|
58629
59311
|
getIndexWriterLockPath(),
|
|
58630
|
-
...lockBases.flatMap((base) => STATIC_OPERATION_LOCKS.map((name) =>
|
|
59312
|
+
...lockBases.flatMap((base) => STATIC_OPERATION_LOCKS.map((name) => path48.join(base, name))),
|
|
58631
59313
|
...samples.flatMap((sample) => sample.paths)
|
|
58632
59314
|
]);
|
|
58633
59315
|
const blockers = [...candidates].filter((lockPath) => {
|
|
@@ -58715,7 +59397,7 @@ function resolveBackupRun(runId) {
|
|
|
58715
59397
|
if (runId)
|
|
58716
59398
|
return getMigrationBackupDir(runId);
|
|
58717
59399
|
const root2 = getMigrationBackupRoot();
|
|
58718
|
-
const runs = fs42.existsSync(root2) ? fs42.readdirSync(root2, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => ({ name: entry.name, mtime: fs42.statSync(
|
|
59400
|
+
const runs = fs42.existsSync(root2) ? fs42.readdirSync(root2, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => ({ name: entry.name, mtime: fs42.statSync(path48.join(root2, entry.name)).mtimeMs })).sort((left, right) => left.mtime - right.mtime || left.name.localeCompare(right.name)) : [];
|
|
58719
59401
|
const latest = runs.at(-1)?.name;
|
|
58720
59402
|
if (!latest)
|
|
58721
59403
|
throw new ConfigError(`No migration backup runs exist under ${root2}.`, "INVALID_CONFIG_FILE");
|
|
@@ -58739,13 +59421,13 @@ function readRestoreSentinel() {
|
|
|
58739
59421
|
return value;
|
|
58740
59422
|
}
|
|
58741
59423
|
function writeRestoreSentinel(sentinel) {
|
|
58742
|
-
fs42.mkdirSync(
|
|
59424
|
+
fs42.mkdirSync(path48.dirname(restoreSentinelPath()), { recursive: true, mode: 448 });
|
|
58743
59425
|
writeFileAtomic(restoreSentinelPath(), `${JSON.stringify(sentinel, null, 2)}
|
|
58744
59426
|
`, 384);
|
|
58745
59427
|
}
|
|
58746
59428
|
function clearRestoreSentinel() {
|
|
58747
59429
|
fs42.rmSync(restoreSentinelPath(), { force: true });
|
|
58748
|
-
fsyncDirectory(
|
|
59430
|
+
fsyncDirectory(path48.dirname(restoreSentinelPath()));
|
|
58749
59431
|
}
|
|
58750
59432
|
function failRestoreAfterForTests(name) {
|
|
58751
59433
|
if (process.env.AKM_TEST_MIGRATION_FAIL_RESTORE_AFTER === name) {
|
|
@@ -58758,18 +59440,18 @@ function publishBackup(bundlePath, manifest) {
|
|
|
58758
59440
|
const artifact = manifest.artifacts[name];
|
|
58759
59441
|
const destination = artifact.sourcePath;
|
|
58760
59442
|
const sidecars = name === "config.json" ? [] : [`${destination}-wal`, `${destination}-shm`];
|
|
58761
|
-
fs42.mkdirSync(
|
|
59443
|
+
fs42.mkdirSync(path48.dirname(destination), { recursive: true, mode: 448 });
|
|
58762
59444
|
for (const sidecar of sidecars)
|
|
58763
59445
|
fs42.rmSync(sidecar, { force: true });
|
|
58764
59446
|
if (!artifact.present) {
|
|
58765
59447
|
fs42.rmSync(destination, { force: true });
|
|
58766
|
-
fsyncDirectory(
|
|
59448
|
+
fsyncDirectory(path48.dirname(destination));
|
|
58767
59449
|
failRestoreAfterForTests(name);
|
|
58768
59450
|
continue;
|
|
58769
59451
|
}
|
|
58770
59452
|
const stage = `${destination}.restore-stage`;
|
|
58771
59453
|
fs42.rmSync(stage, { force: true });
|
|
58772
|
-
copyFileDurable(
|
|
59454
|
+
copyFileDurable(path48.join(bundlePath, name), stage);
|
|
58773
59455
|
const staged = inspectArtifact(name, stage);
|
|
58774
59456
|
if (!sameState(staged, artifact)) {
|
|
58775
59457
|
throw new ConfigError(`Staged restore artifact ${name} failed semantic verification.`, "INVALID_CONFIG_FILE");
|
|
@@ -58777,7 +59459,7 @@ function publishBackup(bundlePath, manifest) {
|
|
|
58777
59459
|
fs42.rmSync(destination, { force: true });
|
|
58778
59460
|
fs42.renameSync(stage, destination);
|
|
58779
59461
|
fs42.chmodSync(destination, 384);
|
|
58780
|
-
fsyncDirectory(
|
|
59462
|
+
fsyncDirectory(path48.dirname(destination));
|
|
58781
59463
|
failRestoreAfterForTests(name);
|
|
58782
59464
|
}
|
|
58783
59465
|
for (const name of ARTIFACT_NAMES) {
|
|
@@ -58804,7 +59486,7 @@ function recoverInterruptedRestoreWithLocksHeld() {
|
|
|
58804
59486
|
if (!pending)
|
|
58805
59487
|
return;
|
|
58806
59488
|
assertNoArtifactReplacementBlockers(undefined, {
|
|
58807
|
-
stashRoots: configStashRoots(
|
|
59489
|
+
stashRoots: configStashRoots(path48.join(getMigrationBackupDir(pending.sourceRunId), "config.json"))
|
|
58808
59490
|
});
|
|
58809
59491
|
recoverInterruptedRestore();
|
|
58810
59492
|
}
|
|
@@ -58819,7 +59501,7 @@ function restoreMigrationBackup(confirm, runId) {
|
|
|
58819
59501
|
const pending = readRestoreSentinel();
|
|
58820
59502
|
if (pending) {
|
|
58821
59503
|
assertNoArtifactReplacementBlockers(undefined, {
|
|
58822
|
-
stashRoots: configStashRoots(
|
|
59504
|
+
stashRoots: configStashRoots(path48.join(getMigrationBackupDir(pending.sourceRunId), "config.json"))
|
|
58823
59505
|
});
|
|
58824
59506
|
recoverInterruptedRestore();
|
|
58825
59507
|
const backupPath = getMigrationBackupDir(pending.sourceRunId);
|
|
@@ -58833,7 +59515,7 @@ function restoreMigrationBackup(confirm, runId) {
|
|
|
58833
59515
|
const bundlePath = resolveBackupRun(runId);
|
|
58834
59516
|
const manifest = verifyMigrationBackup(bundlePath);
|
|
58835
59517
|
assertNoArtifactReplacementBlockers(undefined, {
|
|
58836
|
-
stashRoots: configStashRoots(
|
|
59518
|
+
stashRoots: configStashRoots(path48.join(bundlePath, "config.json"))
|
|
58837
59519
|
});
|
|
58838
59520
|
const rescue = createMigrationBackupUnlocked({ allowCorruptIndex: true });
|
|
58839
59521
|
writeRestoreSentinel({
|
|
@@ -58862,7 +59544,7 @@ function readApplySentinel() {
|
|
|
58862
59544
|
let sentinel;
|
|
58863
59545
|
try {
|
|
58864
59546
|
const value = JSON.parse(readTextFileWithLimit(sentinelPath, MAX_LOCAL_METADATA_BYTES, "Migration apply sentinel"));
|
|
58865
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || value.formatVersion !== APPLY_SENTINEL_FORMAT || value.version !== MIGRATION_BACKUP_VERSION || typeof value.operationId !== "string" || !/^[A-Za-z0-9._-]+$/.test(value.operationId) || value.installationId !==
|
|
59547
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || value.formatVersion !== APPLY_SENTINEL_FORMAT || value.version !== MIGRATION_BACKUP_VERSION || typeof value.operationId !== "string" || !/^[A-Za-z0-9._-]+$/.test(value.operationId) || value.installationId !== path49.basename(getMigrationBackupRoot()) || typeof value.backupRunId !== "string" || !/^[A-Za-z0-9._-]+$/.test(value.backupRunId) || value.backupPath !== getMigrationBackupDir(value.backupRunId) || !value.targetConfig || typeof value.targetConfig !== "object" || Array.isArray(value.targetConfig) || !isMigrationLockEntries(value.migrationLockEntries) || typeof value.pathResolutionBase !== "string" || !path49.isAbsolute(value.pathResolutionBase)) {
|
|
58866
59548
|
return { error: `Invalid migration apply sentinel at ${sentinelPath}.` };
|
|
58867
59549
|
}
|
|
58868
59550
|
sentinel = value;
|
|
@@ -58873,7 +59555,7 @@ function readApplySentinel() {
|
|
|
58873
59555
|
}
|
|
58874
59556
|
try {
|
|
58875
59557
|
const backupStat = fs43.lstatSync(sentinel.backupPath);
|
|
58876
|
-
if (backupStat.isSymbolicLink() || !backupStat.isDirectory() || fs43.realpathSync(
|
|
59558
|
+
if (backupStat.isSymbolicLink() || !backupStat.isDirectory() || fs43.realpathSync(path49.dirname(sentinel.backupPath)) !== fs43.realpathSync(getMigrationBackupRoot())) {
|
|
58877
59559
|
throw new ConfigError("Migration apply backup is not a canonical installation run directory.", "INVALID_CONFIG_FILE");
|
|
58878
59560
|
}
|
|
58879
59561
|
const config = parseMigrationTargetConfig(JSON.stringify(sentinel.targetConfig), sentinelPath);
|
|
@@ -58891,7 +59573,7 @@ function readApplySentinel() {
|
|
|
58891
59573
|
}
|
|
58892
59574
|
function writeApplySentinel(sentinel) {
|
|
58893
59575
|
const sentinelPath = getMigrationApplyJournalPath();
|
|
58894
|
-
fs43.mkdirSync(
|
|
59576
|
+
fs43.mkdirSync(path49.dirname(sentinelPath), { recursive: true, mode: 448 });
|
|
58895
59577
|
const serialized = `${JSON.stringify(sentinel, null, 2)}
|
|
58896
59578
|
`;
|
|
58897
59579
|
if (Buffer.byteLength(serialized) > MAX_LOCAL_METADATA_BYTES) {
|
|
@@ -58968,7 +59650,7 @@ function unsafeArtifact(name, state) {
|
|
|
58968
59650
|
return `${name} is ${state.status}${state.detail ? `: ${state.detail}` : ""}`;
|
|
58969
59651
|
}
|
|
58970
59652
|
function completedCutoverRefMapPath() {
|
|
58971
|
-
return
|
|
59653
|
+
return path49.join(path49.dirname(getMigrationApplyJournalPath()), "completed-cutover-refmap.json");
|
|
58972
59654
|
}
|
|
58973
59655
|
function loadCompletedProposalRefMap() {
|
|
58974
59656
|
const mapPath = completedCutoverRefMapPath();
|
|
@@ -59072,7 +59754,7 @@ function expandTilde4(value) {
|
|
|
59072
59754
|
if (value === "~")
|
|
59073
59755
|
return os6.homedir();
|
|
59074
59756
|
if (value.startsWith("~/") || value.startsWith("~\\"))
|
|
59075
|
-
return
|
|
59757
|
+
return path49.join(os6.homedir(), value.slice(2));
|
|
59076
59758
|
return value;
|
|
59077
59759
|
}
|
|
59078
59760
|
function migrationLockMatchesBundle(lock, bundle) {
|
|
@@ -59104,12 +59786,12 @@ function cutoverStashRootsFromConfig(config, migrationLockEntries = [], legacySo
|
|
|
59104
59786
|
const bundlePath = bundle.path;
|
|
59105
59787
|
const lock = locksById.get(id);
|
|
59106
59788
|
const lockRoot = lock && migrationLockMatchesBundle(lock, bundle) ? lock.localRoot : undefined;
|
|
59107
|
-
const materializedRoot = typeof bundlePath === "string" && bundlePath.length > 0 ?
|
|
59789
|
+
const materializedRoot = typeof bundlePath === "string" && bundlePath.length > 0 ? path49.resolve(pathResolutionBase, expandTilde4(bundlePath)) : lockRoot ? path49.resolve(pathResolutionBase, expandTilde4(lockRoot)) : undefined;
|
|
59108
59790
|
const registryId = typeof bundle.registryId === "string" ? bundle.registryId : undefined;
|
|
59109
59791
|
const identityIndex = identitySources.length;
|
|
59110
59792
|
identitySources.push({
|
|
59111
59793
|
id,
|
|
59112
|
-
path: materializedRoot ??
|
|
59794
|
+
path: materializedRoot ?? path49.resolve(pathResolutionBase, ".akm", "unresolved-sources", id),
|
|
59113
59795
|
...registryId ? { registryId } : materializedRoot === undefined ? { registryId: id } : {}
|
|
59114
59796
|
});
|
|
59115
59797
|
if (!materializedRoot || seenRoots.has(materializedRoot))
|
|
@@ -59127,7 +59809,7 @@ function cutoverStashRootsFromConfig(config, migrationLockEntries = [], legacySo
|
|
|
59127
59809
|
const configured = bundles[lock.id];
|
|
59128
59810
|
if (!configured || !migrationLockMatchesBundle(lock, configured) || !lock.localRoot)
|
|
59129
59811
|
continue;
|
|
59130
|
-
const materializedRoot =
|
|
59812
|
+
const materializedRoot = path49.resolve(pathResolutionBase, expandTilde4(lock.localRoot));
|
|
59131
59813
|
if (seenRoots.has(materializedRoot))
|
|
59132
59814
|
continue;
|
|
59133
59815
|
seenRoots.add(materializedRoot);
|
|
@@ -59149,7 +59831,7 @@ function cutoverStashRootsFromConfig(config, migrationLockEntries = [], legacySo
|
|
|
59149
59831
|
if (legacySources.length > 0) {
|
|
59150
59832
|
const exactLegacyIds = deriveLegacyBundleIds(legacySources);
|
|
59151
59833
|
legacySources.forEach((source, index) => {
|
|
59152
|
-
const root2 =
|
|
59834
|
+
const root2 = path49.resolve(pathResolutionBase, source.path);
|
|
59153
59835
|
const legacyId = exactLegacyIds[index];
|
|
59154
59836
|
const existing = legacyIdsByRoot.get(root2);
|
|
59155
59837
|
if (!legacyId || existing !== undefined && existing !== legacyId) {
|
|
@@ -59163,32 +59845,32 @@ function cutoverStashRootsFromConfig(config, migrationLockEntries = [], legacySo
|
|
|
59163
59845
|
return candidates.map((candidate) => ({
|
|
59164
59846
|
path: candidate.path,
|
|
59165
59847
|
bundleId: candidate.bundleId,
|
|
59166
|
-
legacyBundleId: legacyIdsByRoot.get(
|
|
59848
|
+
legacyBundleId: legacyIdsByRoot.get(path49.resolve(candidate.path)) ?? inferredLegacyBundleIds[candidate.identityIndex],
|
|
59167
59849
|
registryId: candidate.registryId,
|
|
59168
59850
|
primary: candidate.primary
|
|
59169
59851
|
}));
|
|
59170
59852
|
}
|
|
59171
59853
|
function legacyCutoverSources(sentinel) {
|
|
59172
|
-
const backupConfigPath =
|
|
59854
|
+
const backupConfigPath = path49.join(sentinel.backupPath, "config.json");
|
|
59173
59855
|
if (!fs43.existsSync(backupConfigPath))
|
|
59174
59856
|
return [];
|
|
59175
59857
|
const text2 = readTextFileWithLimit(backupConfigPath, MAX_CONFIG_FILE_BYTES, "Migration backup config");
|
|
59176
59858
|
return oldConfigToSearchSources(parseConfigText(text2, backupConfigPath), sentinel.pathResolutionBase);
|
|
59177
59859
|
}
|
|
59178
59860
|
function cutoverRefMapPath(sentinel) {
|
|
59179
|
-
return
|
|
59861
|
+
return path49.join(path49.dirname(getMigrationApplyJournalPath()), `cutover-refmap-${sentinel.operationId}.json`);
|
|
59180
59862
|
}
|
|
59181
59863
|
function contentMigrationReportPath() {
|
|
59182
|
-
return
|
|
59864
|
+
return path49.join(path49.dirname(getMigrationApplyJournalPath()), "content-migration-report.json");
|
|
59183
59865
|
}
|
|
59184
59866
|
function persistContentMigrationReport(report) {
|
|
59185
|
-
fs43.mkdirSync(
|
|
59867
|
+
fs43.mkdirSync(path49.dirname(contentMigrationReportPath()), { recursive: true, mode: 448 });
|
|
59186
59868
|
writeFileAtomic(contentMigrationReportPath(), `${JSON.stringify(report, null, 2)}
|
|
59187
59869
|
`, 384);
|
|
59188
59870
|
}
|
|
59189
59871
|
function isPathWithin(root2, candidate) {
|
|
59190
|
-
const relative =
|
|
59191
|
-
return relative.length > 0 && !relative.startsWith(`..${
|
|
59872
|
+
const relative = path49.relative(path49.resolve(root2), path49.resolve(candidate));
|
|
59873
|
+
return relative.length > 0 && !relative.startsWith(`..${path49.sep}`) && relative !== ".." && !path49.isAbsolute(relative);
|
|
59192
59874
|
}
|
|
59193
59875
|
function priorReservedRenames(roots) {
|
|
59194
59876
|
const reportPath = contentMigrationReportPath();
|
|
@@ -59212,15 +59894,15 @@ function priorReservedRenames(roots) {
|
|
|
59212
59894
|
if (!entry || typeof entry.from !== "string" || typeof entry.to !== "string") {
|
|
59213
59895
|
throw new ConfigError(`Invalid reserved-file rename history at ${reportPath}.`, "INVALID_CONFIG_FILE");
|
|
59214
59896
|
}
|
|
59215
|
-
const from =
|
|
59216
|
-
const to =
|
|
59897
|
+
const from = path49.resolve(entry.from);
|
|
59898
|
+
const to = path49.resolve(entry.to);
|
|
59217
59899
|
const owner = roots.find((root2) => isPathWithin(root2.path, from) && isPathWithin(root2.path, to));
|
|
59218
59900
|
if (!owner)
|
|
59219
59901
|
continue;
|
|
59220
|
-
const fromName =
|
|
59902
|
+
const fromName = path49.basename(from).toLowerCase();
|
|
59221
59903
|
const stem = fromName.endsWith(".md") ? fromName.slice(0, -3) : "";
|
|
59222
59904
|
const targetPattern = new RegExp(`^${stem}-content(?:-(?:[2-9]|[1-9][0-9]+))?\\.md$`, "i");
|
|
59223
|
-
if (
|
|
59905
|
+
if (path49.dirname(from) !== path49.dirname(to) || fromName !== "index.md" && fromName !== "log.md" || !targetPattern.test(path49.basename(to))) {
|
|
59224
59906
|
throw new ConfigError(`Invalid reserved-file rename history at ${reportPath}.`, "INVALID_CONFIG_FILE");
|
|
59225
59907
|
}
|
|
59226
59908
|
if (fs43.existsSync(from) || !fs43.existsSync(to))
|
|
@@ -59233,7 +59915,7 @@ function priorReservedRenames(roots) {
|
|
|
59233
59915
|
return reusable;
|
|
59234
59916
|
}
|
|
59235
59917
|
function mergePriorReservedRenames(report, roots) {
|
|
59236
|
-
const bySource = new Map(report.reservedRenames.map((entry) => [
|
|
59918
|
+
const bySource = new Map(report.reservedRenames.map((entry) => [path49.resolve(entry.from), entry]));
|
|
59237
59919
|
for (const entry of priorReservedRenames(roots)) {
|
|
59238
59920
|
if (!bySource.has(entry.from))
|
|
59239
59921
|
bySource.set(entry.from, entry);
|
|
@@ -59244,11 +59926,11 @@ function mergePriorReservedRenames(report, roots) {
|
|
|
59244
59926
|
function reservedRenameRefMap(renames, roots) {
|
|
59245
59927
|
const map = new Map;
|
|
59246
59928
|
for (const rename of renames) {
|
|
59247
|
-
const owner = roots.find((root2) => rename.from.startsWith(`${
|
|
59929
|
+
const owner = roots.find((root2) => rename.from.startsWith(`${path49.resolve(root2.path)}${path49.sep}`));
|
|
59248
59930
|
if (!owner)
|
|
59249
59931
|
continue;
|
|
59250
59932
|
const conceptId = (absolute) => {
|
|
59251
|
-
const relative =
|
|
59933
|
+
const relative = path49.relative(path49.resolve(owner.path), absolute).split(path49.sep).join("/");
|
|
59252
59934
|
return relative.endsWith(".md") ? relative.slice(0, -3) : undefined;
|
|
59253
59935
|
};
|
|
59254
59936
|
const oldId = conceptId(rename.from);
|
|
@@ -59264,7 +59946,7 @@ function reservedRenameRefMap(renames, roots) {
|
|
|
59264
59946
|
function runContentMigrationStep(sentinel, roots) {
|
|
59265
59947
|
const report = mergePriorReservedRenames(runContentMigration(roots.map((root2) => root2.path), {
|
|
59266
59948
|
operationId: sentinel.operationId,
|
|
59267
|
-
renameBatchPath:
|
|
59949
|
+
renameBatchPath: path49.join(path49.dirname(getMigrationApplyJournalPath()), `reserved-renames-${sentinel.operationId}.json`)
|
|
59268
59950
|
}), roots);
|
|
59269
59951
|
const renameMap = reservedRenameRefMap(report.reservedRenames, roots);
|
|
59270
59952
|
const proposalRoots = roots.flatMap((root2) => root2.bundleId ? [
|
|
@@ -59434,7 +60116,7 @@ function warnOrphanedActiveWorkflowRuns(statePath, roots, defaultBundle) {
|
|
|
59434
60116
|
const root2 = rootById.get(parsed.bundle ?? defaultBundle ?? "");
|
|
59435
60117
|
if (!root2)
|
|
59436
60118
|
continue;
|
|
59437
|
-
const typeRoot =
|
|
60119
|
+
const typeRoot = path49.join(root2.path, stashDirFor("workflow") ?? "workflows");
|
|
59438
60120
|
const filePath = assetPathForName("workflow", typeRoot, parts.name);
|
|
59439
60121
|
if (!fs43.existsSync(filePath))
|
|
59440
60122
|
continue;
|
|
@@ -59444,7 +60126,7 @@ function warnOrphanedActiveWorkflowRuns(statePath, roots, defaultBundle) {
|
|
|
59444
60126
|
} catch {
|
|
59445
60127
|
continue;
|
|
59446
60128
|
}
|
|
59447
|
-
const diagnostics = workflowStructureDiagnostics(
|
|
60129
|
+
const diagnostics = workflowStructureDiagnostics(path49.relative(root2.path, filePath) || filePath, raw, filePath);
|
|
59448
60130
|
if (diagnostics.length === 0)
|
|
59449
60131
|
continue;
|
|
59450
60132
|
warn(`WORKFLOW ACTIVE run ${row.id} targets "${row.workflow_ref}" (${filePath}), which fails 0.9 workflow ` + `structural validation and can no longer be run: ${diagnostics.map((d) => d.detail).join("; ")}. ` + "AKM does not auto-translate workflow definitions between formats \u2014 update the asset to declare " + `frontmatter \`steps:\`, or run \`akm workflow abandon ${row.id}\` to clear the stale run.`);
|
|
@@ -59455,7 +60137,7 @@ function writeGeneratedTargetConfig(raw) {
|
|
|
59455
60137
|
const { config, droppedKeys } = generateTargetConfig(raw, CURRENT_CONFIG_VERSION);
|
|
59456
60138
|
const generatedPath = getMigrationGeneratedConfigPath();
|
|
59457
60139
|
parseAndValidateConfigText(JSON.stringify(config), generatedPath);
|
|
59458
|
-
fs43.mkdirSync(
|
|
60140
|
+
fs43.mkdirSync(path49.dirname(generatedPath), { recursive: true, mode: 448 });
|
|
59459
60141
|
writeFileAtomic(generatedPath, `${JSON.stringify(config, null, 2)}
|
|
59460
60142
|
`, 384);
|
|
59461
60143
|
return { path: generatedPath, status: "written", droppedKeys };
|
|
@@ -59496,7 +60178,7 @@ async function runMigrationApply(options = {}) {
|
|
|
59496
60178
|
const { plan, target, migrationLockEntries } = requireEligiblePlan(options.preparedConfigPath, existing);
|
|
59497
60179
|
if (plan.status === "current" && !existing.sentinel)
|
|
59498
60180
|
return { plan };
|
|
59499
|
-
const pathResolutionBase = existing.sentinel?.pathResolutionBase ??
|
|
60181
|
+
const pathResolutionBase = existing.sentinel?.pathResolutionBase ?? path49.resolve(process.cwd());
|
|
59500
60182
|
const stashRoots = cutoverStashRootsFromConfig(target, migrationLockEntries, [], pathResolutionBase);
|
|
59501
60183
|
assertNoArtifactReplacementBlockers(undefined, { stashRoots: stashRoots.map((root2) => root2.path) });
|
|
59502
60184
|
assertMigrationLockfileReadable();
|
|
@@ -59510,7 +60192,7 @@ async function runMigrationApply(options = {}) {
|
|
|
59510
60192
|
backupPath: backup.path,
|
|
59511
60193
|
targetConfig: sanitizeConfigForWrite(target),
|
|
59512
60194
|
migrationLockEntries,
|
|
59513
|
-
pathResolutionBase:
|
|
60195
|
+
pathResolutionBase: path49.resolve(process.cwd())
|
|
59514
60196
|
};
|
|
59515
60197
|
if (!existing.sentinel)
|
|
59516
60198
|
writeApplySentinel(sentinel);
|