@pleri/olam-cli 0.1.169 → 0.1.173
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/README.md +38 -0
- package/dist/agent-stream/driver-runner.js +13 -0
- package/dist/commands/auth-status.d.ts +1 -0
- package/dist/commands/auth-status.d.ts.map +1 -1
- package/dist/commands/auth-status.js +45 -4
- package/dist/commands/auth-status.js.map +1 -1
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +26 -0
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/enter.d.ts.map +1 -1
- package/dist/commands/enter.js +5 -0
- package/dist/commands/enter.js.map +1 -1
- package/dist/commands/resume.d.ts +63 -0
- package/dist/commands/resume.d.ts.map +1 -0
- package/dist/commands/resume.js +174 -0
- package/dist/commands/resume.js.map +1 -0
- package/dist/commands/setup.d.ts +19 -0
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +157 -19
- package/dist/commands/setup.js.map +1 -1
- package/dist/image-digests.json +8 -8
- package/dist/index.js +1025 -577
- package/dist/index.js.map +1 -1
- package/dist/lib/health-probes.d.ts +28 -0
- package/dist/lib/health-probes.d.ts.map +1 -1
- package/dist/lib/health-probes.js +75 -0
- package/dist/lib/health-probes.js.map +1 -1
- package/dist/lib/k8s-context-discovery.d.ts +80 -0
- package/dist/lib/k8s-context-discovery.d.ts.map +1 -0
- package/dist/lib/k8s-context-discovery.js +102 -0
- package/dist/lib/k8s-context-discovery.js.map +1 -0
- package/dist/mcp-server.js +2417 -1060
- package/dist/spawn/home-override.d.ts +82 -0
- package/dist/spawn/home-override.d.ts.map +1 -0
- package/dist/spawn/home-override.js +107 -0
- package/dist/spawn/home-override.js.map +1 -0
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/30-configmap.yaml +5 -0
- package/host-cp/k8s/manifests/50-deployment.yaml +9 -2
- package/host-cp/k8s/manifests/auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/kg-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/mcp-auth-service/50-deployment.yaml +1 -1
- package/host-cp/k8s/manifests/memory-service/50-deployment.yaml +1 -1
- package/host-cp/lifecycle/classify.mjs +110 -0
- package/host-cp/lifecycle/emit.mjs +119 -0
- package/host-cp/lifecycle/evidence.mjs +45 -0
- package/host-cp/lifecycle/failure-kinds.mjs +56 -0
- package/host-cp/lifecycle/index.mjs +22 -0
- package/host-cp/lifecycle/phases.mjs +52 -0
- package/host-cp/observability/grafana-port-forward.sh +1 -1
- package/host-cp/observability/kyverno-cardinality-mutate.sh +2 -2
- package/host-cp/observability/loki-ingest.sh +1 -1
- package/host-cp/observability/ndjson-span-sink.mjs +183 -0
- package/host-cp/observability/prom-no-double-grafana.sh +4 -4
- package/host-cp/observability/redactor.mjs +72 -0
- package/host-cp/recovery/engine.mjs +148 -0
- package/host-cp/recovery/index.mjs +16 -0
- package/host-cp/recovery/ledger.mjs +105 -0
- package/host-cp/recovery/recipes.mjs +46 -0
- package/host-cp/recovery/scenarios.mjs +124 -0
- package/host-cp/recovery/step-runners.mjs +263 -0
- package/host-cp/src/docker-events.mjs +30 -6
- package/host-cp/src/linear-sync.mjs +43 -0
- package/host-cp/src/plan-chat-service.mjs +129 -1
- package/host-cp/src/pr-nanny.mjs +55 -3
- package/host-cp/src/server.mjs +261 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -492,8 +492,8 @@ var init_parseUtil = __esm({
|
|
|
492
492
|
init_errors();
|
|
493
493
|
init_en();
|
|
494
494
|
makeIssue = (params) => {
|
|
495
|
-
const { data, path:
|
|
496
|
-
const fullPath = [...
|
|
495
|
+
const { data, path: path96, errorMaps, issueData } = params;
|
|
496
|
+
const fullPath = [...path96, ...issueData.path || []];
|
|
497
497
|
const fullIssue = {
|
|
498
498
|
...issueData,
|
|
499
499
|
path: fullPath
|
|
@@ -801,11 +801,11 @@ var init_types = __esm({
|
|
|
801
801
|
init_parseUtil();
|
|
802
802
|
init_util();
|
|
803
803
|
ParseInputLazyPath = class {
|
|
804
|
-
constructor(parent, value,
|
|
804
|
+
constructor(parent, value, path96, key) {
|
|
805
805
|
this._cachedPath = [];
|
|
806
806
|
this.parent = parent;
|
|
807
807
|
this.data = value;
|
|
808
|
-
this._path =
|
|
808
|
+
this._path = path96;
|
|
809
809
|
this._key = key;
|
|
810
810
|
}
|
|
811
811
|
get path() {
|
|
@@ -4286,7 +4286,7 @@ import YAML from "yaml";
|
|
|
4286
4286
|
function bootstrapStepCmd(entry) {
|
|
4287
4287
|
return typeof entry === "string" ? entry : entry.cmd;
|
|
4288
4288
|
}
|
|
4289
|
-
function refineForbiddenKeys(value,
|
|
4289
|
+
function refineForbiddenKeys(value, path96, ctx, rejectSource) {
|
|
4290
4290
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4291
4291
|
return;
|
|
4292
4292
|
}
|
|
@@ -4294,12 +4294,12 @@ function refineForbiddenKeys(value, path95, ctx, rejectSource) {
|
|
|
4294
4294
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4295
4295
|
ctx.addIssue({
|
|
4296
4296
|
code: external_exports.ZodIssueCode.custom,
|
|
4297
|
-
path: [...
|
|
4297
|
+
path: [...path96, key],
|
|
4298
4298
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4299
4299
|
});
|
|
4300
4300
|
continue;
|
|
4301
4301
|
}
|
|
4302
|
-
if (rejectSource &&
|
|
4302
|
+
if (rejectSource && path96.length === 0 && key === "source") {
|
|
4303
4303
|
ctx.addIssue({
|
|
4304
4304
|
code: external_exports.ZodIssueCode.custom,
|
|
4305
4305
|
path: ["source"],
|
|
@@ -4307,21 +4307,21 @@ function refineForbiddenKeys(value, path95, ctx, rejectSource) {
|
|
|
4307
4307
|
});
|
|
4308
4308
|
continue;
|
|
4309
4309
|
}
|
|
4310
|
-
refineForbiddenKeys(value[key], [...
|
|
4310
|
+
refineForbiddenKeys(value[key], [...path96, key], ctx, false);
|
|
4311
4311
|
}
|
|
4312
4312
|
}
|
|
4313
|
-
function rejectForbiddenKeys(value,
|
|
4313
|
+
function rejectForbiddenKeys(value, path96, rejectSource) {
|
|
4314
4314
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
4315
4315
|
return;
|
|
4316
4316
|
}
|
|
4317
4317
|
for (const key of Object.keys(value)) {
|
|
4318
4318
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4319
|
-
throw new Error(`[manifest] ${
|
|
4319
|
+
throw new Error(`[manifest] ${path96}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
4320
4320
|
}
|
|
4321
4321
|
if (rejectSource && key === "source") {
|
|
4322
|
-
throw new Error(`[manifest] ${
|
|
4322
|
+
throw new Error(`[manifest] ${path96}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
4323
4323
|
}
|
|
4324
|
-
rejectForbiddenKeys(value[key], `${
|
|
4324
|
+
rejectForbiddenKeys(value[key], `${path96}.${key}`, false);
|
|
4325
4325
|
}
|
|
4326
4326
|
}
|
|
4327
4327
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -4860,7 +4860,13 @@ var init_schema2 = __esm({
|
|
|
4860
4860
|
user: external_exports.string().min(1),
|
|
4861
4861
|
key: external_exports.string().optional()
|
|
4862
4862
|
});
|
|
4863
|
-
computeProviderType = external_exports.enum([
|
|
4863
|
+
computeProviderType = external_exports.enum([
|
|
4864
|
+
"docker",
|
|
4865
|
+
"ssh",
|
|
4866
|
+
"e2b",
|
|
4867
|
+
"cloudflare",
|
|
4868
|
+
"cloudflare-isolate"
|
|
4869
|
+
]);
|
|
4864
4870
|
stackImageSchema = external_exports.object({
|
|
4865
4871
|
enabled: external_exports.boolean().optional().default(true),
|
|
4866
4872
|
auto_commit: external_exports.boolean().optional().default(true),
|
|
@@ -4872,6 +4878,15 @@ var init_schema2 = __esm({
|
|
|
4872
4878
|
}).optional(),
|
|
4873
4879
|
ssh: external_exports.object({ hosts: external_exports.array(sshHostSchema).optional() }).optional(),
|
|
4874
4880
|
e2b: external_exports.object({ template: external_exports.string().optional() }).optional(),
|
|
4881
|
+
// V8-isolate runtime tier per ADR 022. Pure isolate, no DO, no Container.
|
|
4882
|
+
// worker_url points at the deployed olam-worker-runner-isolate Worker.
|
|
4883
|
+
// Same https-or-localhost guard as the cloudflare profile — bearer token
|
|
4884
|
+
// in cleartext would leak the OLAM_TASK_TOKEN.
|
|
4885
|
+
"cloudflare-isolate": external_exports.object({
|
|
4886
|
+
worker_url: external_exports.string().url("worker_url must be a valid URL").refine(isSecureOrLocalhost, {
|
|
4887
|
+
message: "worker_url must use https:// (or http://localhost for dev)"
|
|
4888
|
+
}).optional()
|
|
4889
|
+
}).optional(),
|
|
4875
4890
|
cloudflare: external_exports.object({
|
|
4876
4891
|
account_id: external_exports.string().optional(),
|
|
4877
4892
|
// https-only refine: bare http:// would send the operator's Pylon
|
|
@@ -5500,8 +5515,8 @@ var init_client = __esm({
|
|
|
5500
5515
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
5501
5516
|
}
|
|
5502
5517
|
}
|
|
5503
|
-
async request(method,
|
|
5504
|
-
const url2 = `${this.baseUrl}${
|
|
5518
|
+
async request(method, path96, body, attempt = 0) {
|
|
5519
|
+
const url2 = `${this.baseUrl}${path96}`;
|
|
5505
5520
|
const controller = new AbortController();
|
|
5506
5521
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
5507
5522
|
const headers = {};
|
|
@@ -5519,7 +5534,7 @@ var init_client = __esm({
|
|
|
5519
5534
|
} catch (err) {
|
|
5520
5535
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
5521
5536
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
5522
|
-
return this.request(method,
|
|
5537
|
+
return this.request(method, path96, body, attempt + 1);
|
|
5523
5538
|
}
|
|
5524
5539
|
throw err;
|
|
5525
5540
|
} finally {
|
|
@@ -7322,8 +7337,8 @@ var init_provider3 = __esm({
|
|
|
7322
7337
|
// -----------------------------------------------------------------------
|
|
7323
7338
|
// Internal fetch helper
|
|
7324
7339
|
// -----------------------------------------------------------------------
|
|
7325
|
-
async request(
|
|
7326
|
-
const url2 = `${this.config.workerUrl}${
|
|
7340
|
+
async request(path96, method, body) {
|
|
7341
|
+
const url2 = `${this.config.workerUrl}${path96}`;
|
|
7327
7342
|
const bearer = await this.config.mintToken();
|
|
7328
7343
|
const headers = {
|
|
7329
7344
|
Authorization: `Bearer ${bearer}`
|
|
@@ -7884,6 +7899,46 @@ function hasImageRef(present, ref) {
|
|
|
7884
7899
|
const variants = [`docker.io/library/${ref}`, `docker.io/${ref}`];
|
|
7885
7900
|
return variants.some((v) => present.has(v));
|
|
7886
7901
|
}
|
|
7902
|
+
function probeColimaKubernetesEnabled(opts) {
|
|
7903
|
+
const { platform: platform2, home } = opts;
|
|
7904
|
+
const colimaProfile = opts.colimaProfile ?? process.env.COLIMA_PROFILE ?? "default";
|
|
7905
|
+
const readFileFn = opts.readFileFn ?? ((p, enc) => readFileSync13(p, enc));
|
|
7906
|
+
const existsFn = opts.existsFn ?? existsSync13;
|
|
7907
|
+
if (platform2 !== "darwin") {
|
|
7908
|
+
return { ok: true, message: "colima k8s lint: not darwin, skip" };
|
|
7909
|
+
}
|
|
7910
|
+
const colimaYamlPath = path12.join(home, ".colima", colimaProfile, "colima.yaml");
|
|
7911
|
+
if (!existsFn(colimaYamlPath)) {
|
|
7912
|
+
return { ok: true, message: `colima k8s lint: ${colimaYamlPath} not found, skip` };
|
|
7913
|
+
}
|
|
7914
|
+
let yaml;
|
|
7915
|
+
try {
|
|
7916
|
+
yaml = readFileFn(colimaYamlPath, "utf8");
|
|
7917
|
+
} catch {
|
|
7918
|
+
return { ok: true, message: `colima k8s lint: could not read ${colimaYamlPath}` };
|
|
7919
|
+
}
|
|
7920
|
+
const kubernetesSection = yaml.split(/^kubernetes:/m)[1];
|
|
7921
|
+
if (!kubernetesSection) {
|
|
7922
|
+
return { ok: true, message: "colima k8s lint: no kubernetes section found" };
|
|
7923
|
+
}
|
|
7924
|
+
const sectionLines = kubernetesSection.split("\n");
|
|
7925
|
+
const sectionBody2 = [];
|
|
7926
|
+
for (const line of sectionLines) {
|
|
7927
|
+
if (line.length > 0 && !/^\s/.test(line)) break;
|
|
7928
|
+
sectionBody2.push(line);
|
|
7929
|
+
}
|
|
7930
|
+
const section = sectionBody2.join("\n");
|
|
7931
|
+
const enabled = /^\s+enabled:\s*true\s*$/m.test(section);
|
|
7932
|
+
if (!enabled) {
|
|
7933
|
+
return { ok: true, message: "colima k8s lint: kubernetes.enabled is not true" };
|
|
7934
|
+
}
|
|
7935
|
+
return {
|
|
7936
|
+
ok: true,
|
|
7937
|
+
warn: true,
|
|
7938
|
+
message: `Colima has Kubernetes mode enabled at profile '${colimaProfile}'`,
|
|
7939
|
+
remedy: `Colima has Kubernetes mode enabled at profile '${colimaProfile}'. k3d will attempt to coexist but may fail to start with 'context deadline exceeded' due to port conflicts. To fix: \`colima stop && colima start --kubernetes=false\`, OR re-run \`olam setup --reuse-cluster=colima\` to use Colima's existing k3s.`
|
|
7940
|
+
};
|
|
7941
|
+
}
|
|
7887
7942
|
async function probeKubectl(exec = defaultDockerExec) {
|
|
7888
7943
|
const r = exec("kubectl", ["version", "--client", "--output=json"]);
|
|
7889
7944
|
if (r.status === 0 && r.stdout.length > 0) {
|
|
@@ -8104,7 +8159,8 @@ function rowToMetadata(row) {
|
|
|
8104
8159
|
...expectedServices !== void 0 ? { expectedServices } : {},
|
|
8105
8160
|
...appPortUrls !== void 0 ? { appPortUrls } : {},
|
|
8106
8161
|
...worldDbNames !== void 0 ? { worldDbNames } : {},
|
|
8107
|
-
...row.world_role_name ? { worldRoleName: row.world_role_name } : {}
|
|
8162
|
+
...row.world_role_name ? { worldRoleName: row.world_role_name } : {},
|
|
8163
|
+
...row.claude_home ? { claudeHome: row.claude_home } : {}
|
|
8108
8164
|
};
|
|
8109
8165
|
}
|
|
8110
8166
|
var _require, _Database, SCHEMA_VERSION, CREATE_TABLE, CREATE_META, WorldRegistry;
|
|
@@ -8165,7 +8221,9 @@ CREATE TABLE IF NOT EXISTS meta (
|
|
|
8165
8221
|
// world_db_names (SQLite has no native array; matches repos column shape).
|
|
8166
8222
|
// TEXT[] would fail at DDL time (closes OQ13/OQ22 / FS-03).
|
|
8167
8223
|
"world_db_names TEXT",
|
|
8168
|
-
"world_role_name TEXT"
|
|
8224
|
+
"world_role_name TEXT",
|
|
8225
|
+
// ADR 045 — per-world Claude Code HOME path. Additive migration.
|
|
8226
|
+
"claude_home TEXT"
|
|
8169
8227
|
]) {
|
|
8170
8228
|
try {
|
|
8171
8229
|
this.db.exec(`ALTER TABLE worlds ADD COLUMN ${col}`);
|
|
@@ -8196,8 +8254,8 @@ CREATE TABLE IF NOT EXISTS meta (
|
|
|
8196
8254
|
compute_provider, total_cost_usd, thought_count, created_at, updated_at,
|
|
8197
8255
|
pr_url, pr_number, pr_repo, pr_created_at, pr_state, pr_merged_at, auto_destroy_on_merge,
|
|
8198
8256
|
readiness_chain, expected_services, app_port_urls,
|
|
8199
|
-
world_db_names, world_role_name)
|
|
8200
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(world.id, world.name, world.status, JSON.stringify(world.repos), world.branch, world.portOffset, world.workspacePath, world.computeProvider, world.totalCostUsd, world.thoughtCount, world.createdAt, world.updatedAt, world.prUrl ?? null, world.prNumber ?? null, world.prRepo ?? null, world.prCreatedAt ?? null, world.prState ?? "none", world.prMergedAt ?? null, world.autoDestroyOnMerge === false ? 0 : 1, world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null, world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null, world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null, world.worldDbNames !== void 0 ? JSON.stringify(world.worldDbNames) : null, world.worldRoleName ?? null);
|
|
8257
|
+
world_db_names, world_role_name, claude_home)
|
|
8258
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(world.id, world.name, world.status, JSON.stringify(world.repos), world.branch, world.portOffset, world.workspacePath, world.computeProvider, world.totalCostUsd, world.thoughtCount, world.createdAt, world.updatedAt, world.prUrl ?? null, world.prNumber ?? null, world.prRepo ?? null, world.prCreatedAt ?? null, world.prState ?? "none", world.prMergedAt ?? null, world.autoDestroyOnMerge === false ? 0 : 1, world.readinessChain !== void 0 ? JSON.stringify(world.readinessChain) : null, world.expectedServices !== void 0 ? JSON.stringify(world.expectedServices) : null, world.appPortUrls !== void 0 ? JSON.stringify(world.appPortUrls) : null, world.worldDbNames !== void 0 ? JSON.stringify(world.worldDbNames) : null, world.worldRoleName ?? null, world.claudeHome ?? null);
|
|
8201
8259
|
}
|
|
8202
8260
|
update(worldId, updates) {
|
|
8203
8261
|
const setClauses = [];
|
|
@@ -8225,7 +8283,9 @@ CREATE TABLE IF NOT EXISTS meta (
|
|
|
8225
8283
|
appPortUrls: "app_port_urls",
|
|
8226
8284
|
// olam-hybrid-shared-postgres Phase A task A7.
|
|
8227
8285
|
worldDbNames: "world_db_names",
|
|
8228
|
-
worldRoleName: "world_role_name"
|
|
8286
|
+
worldRoleName: "world_role_name",
|
|
8287
|
+
// ADR 045 — per-world Claude Code HOME (multi-account isolation).
|
|
8288
|
+
claudeHome: "claude_home"
|
|
8229
8289
|
};
|
|
8230
8290
|
const jsonColumns = /* @__PURE__ */ new Set(["repos", "readinessChain", "expectedServices", "appPortUrls", "worldDbNames"]);
|
|
8231
8291
|
for (const [key, col] of Object.entries(columnMap)) {
|
|
@@ -8709,6 +8769,8 @@ function stripMcpServers(mcpServers) {
|
|
|
8709
8769
|
stripped.type = value;
|
|
8710
8770
|
} else if (key === "url" && typeof value === "string") {
|
|
8711
8771
|
stripped.url = value;
|
|
8772
|
+
} else if (key === "alwaysLoad" && typeof value === "boolean") {
|
|
8773
|
+
stripped.alwaysLoad = value;
|
|
8712
8774
|
}
|
|
8713
8775
|
}
|
|
8714
8776
|
out[svc] = stripped;
|
|
@@ -8922,9 +8984,9 @@ function buildRepoEnvBundle(repoName, serviceEnv, crossRepoEnv, envOverrides) {
|
|
|
8922
8984
|
const merged = { ...serviceEnv, ...injectables };
|
|
8923
8985
|
return { merged, injectables };
|
|
8924
8986
|
}
|
|
8925
|
-
function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, configCtx) {
|
|
8987
|
+
function setupWorldEnv(repos, workspacePath, serviceEnv, crossRepoEnv = {}, configCtx, claudeHomeOverride) {
|
|
8926
8988
|
try {
|
|
8927
|
-
copyClaudeConfig(workspacePath,
|
|
8989
|
+
copyClaudeConfig(workspacePath, claudeHomeOverride, configCtx);
|
|
8928
8990
|
} catch {
|
|
8929
8991
|
}
|
|
8930
8992
|
if (configCtx) {
|
|
@@ -9026,7 +9088,8 @@ var init_env_setup = __esm({
|
|
|
9026
9088
|
"command",
|
|
9027
9089
|
"args",
|
|
9028
9090
|
"type",
|
|
9029
|
-
"url"
|
|
9091
|
+
"url",
|
|
9092
|
+
"alwaysLoad"
|
|
9030
9093
|
]);
|
|
9031
9094
|
SKIP_FILES = /* @__PURE__ */ new Set([
|
|
9032
9095
|
".credentials.json",
|
|
@@ -9124,17 +9187,17 @@ function kgRoot() {
|
|
|
9124
9187
|
function worldsRoot() {
|
|
9125
9188
|
return join17(olamHome(), "worlds");
|
|
9126
9189
|
}
|
|
9127
|
-
function assertWithinPrefix(
|
|
9128
|
-
if (!
|
|
9129
|
-
throw new Error(`${label} escape: ${
|
|
9190
|
+
function assertWithinPrefix(path96, prefix, label) {
|
|
9191
|
+
if (!path96.startsWith(prefix + "/")) {
|
|
9192
|
+
throw new Error(`${label} escape: ${path96} not under ${prefix}/`);
|
|
9130
9193
|
}
|
|
9131
9194
|
}
|
|
9132
9195
|
function kgPristinePath(workspace) {
|
|
9133
9196
|
validateWorkspaceName(workspace);
|
|
9134
9197
|
const root = kgRoot();
|
|
9135
|
-
const
|
|
9136
|
-
assertWithinPrefix(
|
|
9137
|
-
return
|
|
9198
|
+
const path96 = resolve6(join17(root, workspace));
|
|
9199
|
+
assertWithinPrefix(path96, root, "kgPristinePath");
|
|
9200
|
+
return path96;
|
|
9138
9201
|
}
|
|
9139
9202
|
var KG_PATHS_INTERNALS;
|
|
9140
9203
|
var init_storage_paths = __esm({
|
|
@@ -9249,8 +9312,8 @@ import { execFileSync as execFileSync4 } from "node:child_process";
|
|
|
9249
9312
|
import * as fs15 from "node:fs";
|
|
9250
9313
|
import * as os9 from "node:os";
|
|
9251
9314
|
import * as path17 from "node:path";
|
|
9252
|
-
function expandHome2(p,
|
|
9253
|
-
return p.replace(/^~(?=$|\/|\\)/,
|
|
9315
|
+
function expandHome2(p, homedir64) {
|
|
9316
|
+
return p.replace(/^~(?=$|\/|\\)/, homedir64());
|
|
9254
9317
|
}
|
|
9255
9318
|
function sanitizeRepoFilename(name) {
|
|
9256
9319
|
const sanitized = name.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
@@ -9273,7 +9336,7 @@ ${stderr}`;
|
|
|
9273
9336
|
}
|
|
9274
9337
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
9275
9338
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
|
|
9276
|
-
const
|
|
9339
|
+
const homedir64 = deps.homedir ?? (() => os9.homedir());
|
|
9277
9340
|
const baselineDir = path17.join(workspacePath, ".olam", "baseline");
|
|
9278
9341
|
try {
|
|
9279
9342
|
fs15.mkdirSync(baselineDir, { recursive: true });
|
|
@@ -9289,7 +9352,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
9289
9352
|
continue;
|
|
9290
9353
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
9291
9354
|
const outPath = path17.join(baselineDir, filename);
|
|
9292
|
-
const repoPath = expandHome2(repo.path,
|
|
9355
|
+
const repoPath = expandHome2(repo.path, homedir64);
|
|
9293
9356
|
if (!fs15.existsSync(repoPath)) {
|
|
9294
9357
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
9295
9358
|
# (skipped: path ${repoPath} does not exist)
|
|
@@ -9409,7 +9472,7 @@ function extractStderr(err) {
|
|
|
9409
9472
|
}
|
|
9410
9473
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
9411
9474
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync4(cmd, args, opts));
|
|
9412
|
-
const
|
|
9475
|
+
const homedir64 = deps.homedir ?? (() => os9.homedir());
|
|
9413
9476
|
const existsSync113 = deps.existsSync ?? ((p) => fs15.existsSync(p));
|
|
9414
9477
|
const copyFileSync16 = deps.copyFileSync ?? ((src, dest) => fs15.copyFileSync(src, dest));
|
|
9415
9478
|
const mkdirSync67 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
@@ -9419,7 +9482,7 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
9419
9482
|
for (const repo of repos) {
|
|
9420
9483
|
if (!repo.path)
|
|
9421
9484
|
continue;
|
|
9422
|
-
const repoPath = expandHome2(repo.path,
|
|
9485
|
+
const repoPath = expandHome2(repo.path, homedir64);
|
|
9423
9486
|
const worktreePath = path17.join(workspacePath, repo.name);
|
|
9424
9487
|
if (!existsSync113(repoPath))
|
|
9425
9488
|
continue;
|
|
@@ -12692,7 +12755,8 @@ ${detail}`);
|
|
|
12692
12755
|
createdAt: now,
|
|
12693
12756
|
updatedAt: now,
|
|
12694
12757
|
readinessChain,
|
|
12695
|
-
expectedServices
|
|
12758
|
+
expectedServices,
|
|
12759
|
+
...opts.claudeHome ? { claudeHome: opts.claudeHome } : {}
|
|
12696
12760
|
};
|
|
12697
12761
|
const sm = new WorldStateMachine(worldId, "creating");
|
|
12698
12762
|
this.registry.register(metadata);
|
|
@@ -12830,7 +12894,7 @@ ${detail}`);
|
|
|
12830
12894
|
worlds_default: this.config.worlds_default,
|
|
12831
12895
|
repos: enrichedRepos
|
|
12832
12896
|
};
|
|
12833
|
-
setupWorldEnv(enrichedRepos, workspacePath, serviceEnv, crossRepoEnv, configCtx);
|
|
12897
|
+
setupWorldEnv(enrichedRepos, workspacePath, serviceEnv, crossRepoEnv, configCtx, opts.claudeHome);
|
|
12834
12898
|
} catch (err) {
|
|
12835
12899
|
const msg = err instanceof Error ? err.message : String(err);
|
|
12836
12900
|
console.warn(`[WorldManager] env setup failed: ${msg}`);
|
|
@@ -15704,10 +15768,10 @@ async function readHostCpToken2() {
|
|
|
15704
15768
|
if (!fs26.existsSync(tp)) return null;
|
|
15705
15769
|
return fs26.readFileSync(tp, "utf-8").trim();
|
|
15706
15770
|
}
|
|
15707
|
-
async function callHostCpProxy(method, worldId,
|
|
15771
|
+
async function callHostCpProxy(method, worldId, path96, body) {
|
|
15708
15772
|
const token = await readHostCpToken2();
|
|
15709
15773
|
if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
|
|
15710
|
-
const url2 = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${
|
|
15774
|
+
const url2 = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path96}`;
|
|
15711
15775
|
try {
|
|
15712
15776
|
const headers = {
|
|
15713
15777
|
Authorization: `Bearer ${token}`
|
|
@@ -16174,17 +16238,75 @@ var init_registry_allowlist = __esm({
|
|
|
16174
16238
|
}
|
|
16175
16239
|
});
|
|
16176
16240
|
|
|
16241
|
+
// src/spawn/home-override.ts
|
|
16242
|
+
var home_override_exports = {};
|
|
16243
|
+
__export(home_override_exports, {
|
|
16244
|
+
CLAUDE_HOMES_BASE: () => CLAUDE_HOMES_BASE,
|
|
16245
|
+
HOME_ID_RE: () => HOME_ID_RE,
|
|
16246
|
+
SENTINEL_FILENAME: () => SENTINEL_FILENAME,
|
|
16247
|
+
ensureClaudeHomeDir: () => ensureClaudeHomeDir,
|
|
16248
|
+
resolveClaudeHome: () => resolveClaudeHome
|
|
16249
|
+
});
|
|
16250
|
+
import { mkdir, writeFile, access } from "node:fs/promises";
|
|
16251
|
+
import { homedir as homedir22 } from "node:os";
|
|
16252
|
+
import path36 from "node:path";
|
|
16253
|
+
function resolveClaudeHome(args) {
|
|
16254
|
+
const home = args.homeDir ?? homedir22();
|
|
16255
|
+
if (args.flag !== void 0 && args.flag.length > 0) {
|
|
16256
|
+
return resolveSpec(args.flag, home);
|
|
16257
|
+
}
|
|
16258
|
+
const stored = args.existingWorldConfig?.claudeHome;
|
|
16259
|
+
if (stored !== void 0 && stored.length > 0) {
|
|
16260
|
+
return resolveSpec(stored, home);
|
|
16261
|
+
}
|
|
16262
|
+
return args.envHome ?? home;
|
|
16263
|
+
}
|
|
16264
|
+
function resolveSpec(spec, home) {
|
|
16265
|
+
if (path36.isAbsolute(spec)) {
|
|
16266
|
+
return spec;
|
|
16267
|
+
}
|
|
16268
|
+
if (!HOME_ID_RE.test(spec)) {
|
|
16269
|
+
throw new Error(
|
|
16270
|
+
`--claude-home value "${spec}" must be either an absolute path or a bare id matching ${HOME_ID_RE} (alphanumeric, underscore, dash; starts with alphanumeric; max 64 chars). Rejected: relative paths, parent refs, uppercase, whitespace.`
|
|
16271
|
+
);
|
|
16272
|
+
}
|
|
16273
|
+
return path36.join(home, CLAUDE_HOMES_BASE, spec);
|
|
16274
|
+
}
|
|
16275
|
+
async function ensureClaudeHomeDir(targetPath) {
|
|
16276
|
+
await mkdir(targetPath, { recursive: true });
|
|
16277
|
+
const sentinelPath2 = path36.join(targetPath, SENTINEL_FILENAME);
|
|
16278
|
+
try {
|
|
16279
|
+
await access(sentinelPath2);
|
|
16280
|
+
return;
|
|
16281
|
+
} catch {
|
|
16282
|
+
}
|
|
16283
|
+
await writeFile(
|
|
16284
|
+
sentinelPath2,
|
|
16285
|
+
"# olam claude-home \u2014 managed by `olam create --claude-home`.\n# Do not delete. Re-create by running `olam create --claude-home <id>` again.\n",
|
|
16286
|
+
"utf-8"
|
|
16287
|
+
);
|
|
16288
|
+
}
|
|
16289
|
+
var CLAUDE_HOMES_BASE, SENTINEL_FILENAME, HOME_ID_RE;
|
|
16290
|
+
var init_home_override = __esm({
|
|
16291
|
+
"src/spawn/home-override.ts"() {
|
|
16292
|
+
"use strict";
|
|
16293
|
+
CLAUDE_HOMES_BASE = path36.join(".olam", "claude-homes");
|
|
16294
|
+
SENTINEL_FILENAME = ".olam-claude-home";
|
|
16295
|
+
HOME_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
16296
|
+
}
|
|
16297
|
+
});
|
|
16298
|
+
|
|
16177
16299
|
// ../core/dist/world/world-yaml.js
|
|
16178
16300
|
import * as fs35 from "node:fs";
|
|
16179
|
-
import * as
|
|
16301
|
+
import * as path37 from "node:path";
|
|
16180
16302
|
import { parse as parseYaml4, stringify as stringifyYaml4 } from "yaml";
|
|
16181
16303
|
function writeWorldYaml(worldPath, data) {
|
|
16182
|
-
const olamDir =
|
|
16304
|
+
const olamDir = path37.join(worldPath, ".olam");
|
|
16183
16305
|
fs35.mkdirSync(olamDir, { recursive: true });
|
|
16184
|
-
fs35.writeFileSync(
|
|
16306
|
+
fs35.writeFileSync(path37.join(olamDir, "world.yaml"), stringifyYaml4(data), "utf-8");
|
|
16185
16307
|
}
|
|
16186
16308
|
function readWorldYaml(worldPath) {
|
|
16187
|
-
const yamlPath =
|
|
16309
|
+
const yamlPath = path37.join(worldPath, ".olam", "world.yaml");
|
|
16188
16310
|
if (!fs35.existsSync(yamlPath))
|
|
16189
16311
|
return null;
|
|
16190
16312
|
try {
|
|
@@ -16313,14 +16435,14 @@ var init_checksum = __esm({
|
|
|
16313
16435
|
|
|
16314
16436
|
// ../core/dist/skill-sources/trust-audit-log.js
|
|
16315
16437
|
import * as fs52 from "node:fs";
|
|
16316
|
-
import * as
|
|
16438
|
+
import * as path55 from "node:path";
|
|
16317
16439
|
import * as os28 from "node:os";
|
|
16318
16440
|
function skillSourcesAuditLogPath() {
|
|
16319
16441
|
const override = process.env["OLAM_SKILL_SOURCES_AUDIT_LOG_PATH"];
|
|
16320
16442
|
if (override && override.length > 0)
|
|
16321
16443
|
return override;
|
|
16322
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
16323
|
-
return
|
|
16444
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path55.join(os28.homedir(), ".olam", "state");
|
|
16445
|
+
return path55.join(stateDir, SKILL_SOURCES_AUDIT_LOG_FILENAME);
|
|
16324
16446
|
}
|
|
16325
16447
|
function appendTrustAudit(entry) {
|
|
16326
16448
|
const candidate = {
|
|
@@ -16329,7 +16451,7 @@ function appendTrustAudit(entry) {
|
|
|
16329
16451
|
};
|
|
16330
16452
|
const validated = TrustAuditEntrySchema.parse(candidate);
|
|
16331
16453
|
const filePath = skillSourcesAuditLogPath();
|
|
16332
|
-
fs52.mkdirSync(
|
|
16454
|
+
fs52.mkdirSync(path55.dirname(filePath), { recursive: true, mode: 448 });
|
|
16333
16455
|
const fd = fs52.openSync(filePath, "a", 384);
|
|
16334
16456
|
try {
|
|
16335
16457
|
fs52.writeSync(fd, JSON.stringify(validated) + "\n");
|
|
@@ -16542,22 +16664,22 @@ var init_store3 = __esm({
|
|
|
16542
16664
|
});
|
|
16543
16665
|
|
|
16544
16666
|
// ../core/dist/skill-sources/clone.js
|
|
16545
|
-
import { execFileSync as
|
|
16667
|
+
import { execFileSync as execFileSync14 } from "node:child_process";
|
|
16546
16668
|
import * as fs53 from "node:fs";
|
|
16547
16669
|
import * as os29 from "node:os";
|
|
16548
|
-
import * as
|
|
16670
|
+
import * as path56 from "node:path";
|
|
16549
16671
|
function skillSourcesRootDir() {
|
|
16550
16672
|
const override = process.env["OLAM_SKILL_SOURCES_DIR"];
|
|
16551
16673
|
if (override && override.length > 0)
|
|
16552
16674
|
return override;
|
|
16553
|
-
return
|
|
16675
|
+
return path56.join(os29.homedir(), ".olam", "state", "skill-sources");
|
|
16554
16676
|
}
|
|
16555
16677
|
function skillSourceClonePath(id) {
|
|
16556
|
-
return
|
|
16678
|
+
return path56.join(skillSourcesRootDir(), id);
|
|
16557
16679
|
}
|
|
16558
16680
|
function runGit(args, cwd) {
|
|
16559
16681
|
try {
|
|
16560
|
-
return
|
|
16682
|
+
return execFileSync14("git", args, {
|
|
16561
16683
|
cwd,
|
|
16562
16684
|
encoding: "utf-8",
|
|
16563
16685
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -16715,7 +16837,7 @@ var init_hook_template = __esm({
|
|
|
16715
16837
|
|
|
16716
16838
|
// ../core/dist/world/merge-settings.js
|
|
16717
16839
|
import * as fs55 from "node:fs";
|
|
16718
|
-
import * as
|
|
16840
|
+
import * as path57 from "node:path";
|
|
16719
16841
|
import * as crypto8 from "node:crypto";
|
|
16720
16842
|
function mergeHomeSettingsJson(filePath, options) {
|
|
16721
16843
|
let settings;
|
|
@@ -16799,7 +16921,7 @@ function isHookSentinelPresent(matchers, sentinel) {
|
|
|
16799
16921
|
return false;
|
|
16800
16922
|
}
|
|
16801
16923
|
function atomicWriteJson(filePath, data) {
|
|
16802
|
-
const dir =
|
|
16924
|
+
const dir = path57.dirname(filePath);
|
|
16803
16925
|
fs55.mkdirSync(dir, { recursive: true });
|
|
16804
16926
|
const rand = crypto8.randomBytes(6).toString("hex");
|
|
16805
16927
|
const tmp = `${filePath}.tmp.${process.pid}.${rand}`;
|
|
@@ -16815,13 +16937,13 @@ var init_merge_settings = __esm({
|
|
|
16815
16937
|
|
|
16816
16938
|
// ../core/dist/skill-sources/hook-install.js
|
|
16817
16939
|
import * as fs56 from "node:fs";
|
|
16818
|
-
import * as
|
|
16940
|
+
import * as path58 from "node:path";
|
|
16819
16941
|
import * as os30 from "node:os";
|
|
16820
16942
|
function settingsPathFor(scope, cwd) {
|
|
16821
16943
|
if (scope === "user") {
|
|
16822
|
-
return
|
|
16944
|
+
return path58.join(os30.homedir(), ".claude", "settings.json");
|
|
16823
16945
|
}
|
|
16824
|
-
return
|
|
16946
|
+
return path58.join(cwd ?? process.cwd(), ".claude", "settings.json");
|
|
16825
16947
|
}
|
|
16826
16948
|
function backupFile(filePath) {
|
|
16827
16949
|
if (!fs56.existsSync(filePath))
|
|
@@ -16832,7 +16954,7 @@ function backupFile(filePath) {
|
|
|
16832
16954
|
return backupPath;
|
|
16833
16955
|
}
|
|
16834
16956
|
function installSkillsHookToFile(filePath) {
|
|
16835
|
-
fs56.mkdirSync(
|
|
16957
|
+
fs56.mkdirSync(path58.dirname(filePath), { recursive: true });
|
|
16836
16958
|
const backupPath = backupFile(filePath);
|
|
16837
16959
|
const result = mergeHomeSettingsJson(filePath, {
|
|
16838
16960
|
ensureHook: {
|
|
@@ -16895,29 +17017,29 @@ var init_hook_install = __esm({
|
|
|
16895
17017
|
// ../core/dist/skill-sources/migration-snapshot.js
|
|
16896
17018
|
import * as fs57 from "node:fs";
|
|
16897
17019
|
import * as os31 from "node:os";
|
|
16898
|
-
import * as
|
|
17020
|
+
import * as path59 from "node:path";
|
|
16899
17021
|
function claudeDirInternal() {
|
|
16900
17022
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
16901
17023
|
if (override && override.length > 0)
|
|
16902
17024
|
return override;
|
|
16903
|
-
return
|
|
17025
|
+
return path59.join(os31.homedir(), ".claude");
|
|
16904
17026
|
}
|
|
16905
17027
|
function migrationSnapshotsDir() {
|
|
16906
17028
|
const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
|
|
16907
17029
|
if (override && override.length > 0)
|
|
16908
17030
|
return override;
|
|
16909
|
-
return
|
|
17031
|
+
return path59.join(os31.homedir(), ".olam", "state", "migration-snapshots");
|
|
16910
17032
|
}
|
|
16911
17033
|
function listToolboxManagedSymlinks(toolboxPath) {
|
|
16912
17034
|
const claude = claudeDirInternal();
|
|
16913
17035
|
const out = [];
|
|
16914
17036
|
const BUCKETS2 = ["skills", "agents", "scripts", "rules", "commands"];
|
|
16915
17037
|
for (const bucket of BUCKETS2) {
|
|
16916
|
-
const dir =
|
|
17038
|
+
const dir = path59.join(claude, bucket);
|
|
16917
17039
|
if (!fs57.existsSync(dir))
|
|
16918
17040
|
continue;
|
|
16919
17041
|
for (const name of fs57.readdirSync(dir)) {
|
|
16920
|
-
const link =
|
|
17042
|
+
const link = path59.join(dir, name);
|
|
16921
17043
|
try {
|
|
16922
17044
|
const stat = fs57.lstatSync(link);
|
|
16923
17045
|
if (!stat.isSymbolicLink())
|
|
@@ -16935,12 +17057,12 @@ function listToolboxManagedSymlinks(toolboxPath) {
|
|
|
16935
17057
|
function detectToolboxState(opts) {
|
|
16936
17058
|
const claude = claudeDirInternal();
|
|
16937
17059
|
const toolboxPath = opts.toolboxPath;
|
|
16938
|
-
const namespace = opts.namespace ??
|
|
16939
|
-
const atlasUserFile =
|
|
17060
|
+
const namespace = opts.namespace ?? path59.basename(toolboxPath);
|
|
17061
|
+
const atlasUserFile = path59.join(claude, ".atlas-user");
|
|
16940
17062
|
const atlasUser = fs57.existsSync(atlasUserFile) ? fs57.readFileSync(atlasUserFile, "utf-8").trim() || void 0 : void 0;
|
|
16941
17063
|
let subscriptionsJson;
|
|
16942
17064
|
if (atlasUser) {
|
|
16943
|
-
const sp =
|
|
17065
|
+
const sp = path59.join(toolboxPath, "members", atlasUser, "subscriptions.json");
|
|
16944
17066
|
if (fs57.existsSync(sp)) {
|
|
16945
17067
|
try {
|
|
16946
17068
|
subscriptionsJson = JSON.parse(fs57.readFileSync(sp, "utf-8"));
|
|
@@ -16950,7 +17072,7 @@ function detectToolboxState(opts) {
|
|
|
16950
17072
|
}
|
|
16951
17073
|
const atlasManagedSymlinks = listToolboxManagedSymlinks(toolboxPath);
|
|
16952
17074
|
let originalSessionStartHook;
|
|
16953
|
-
const settingsPath =
|
|
17075
|
+
const settingsPath = path59.join(claude, "settings.json");
|
|
16954
17076
|
if (fs57.existsSync(settingsPath)) {
|
|
16955
17077
|
try {
|
|
16956
17078
|
const settings = JSON.parse(fs57.readFileSync(settingsPath, "utf-8"));
|
|
@@ -16978,7 +17100,7 @@ function writeMigrationSnapshot(snapshot) {
|
|
|
16978
17100
|
const dir = migrationSnapshotsDir();
|
|
16979
17101
|
fs57.mkdirSync(dir, { recursive: true });
|
|
16980
17102
|
const stamp = snapshot.takenAt.replace(/[:.]/g, "-");
|
|
16981
|
-
const file =
|
|
17103
|
+
const file = path59.join(dir, `${snapshot.namespace}-${stamp}.json`);
|
|
16982
17104
|
fs57.writeFileSync(file, JSON.stringify(snapshot, null, 2) + "\n", { mode: 420 });
|
|
16983
17105
|
return file;
|
|
16984
17106
|
}
|
|
@@ -16988,7 +17110,7 @@ function readLatestMigrationSnapshot(opts = {}) {
|
|
|
16988
17110
|
return void 0;
|
|
16989
17111
|
const files = fs57.readdirSync(dir).filter((f) => f.endsWith(".json")).sort().reverse();
|
|
16990
17112
|
for (const f of files) {
|
|
16991
|
-
const full =
|
|
17113
|
+
const full = path59.join(dir, f);
|
|
16992
17114
|
try {
|
|
16993
17115
|
const snapshot = JSON.parse(fs57.readFileSync(full, "utf-8"));
|
|
16994
17116
|
if (snapshot.schemaVersion !== MIGRATION_SNAPSHOT_SCHEMA_VERSION)
|
|
@@ -17015,11 +17137,11 @@ var init_migration_snapshot = __esm({
|
|
|
17015
17137
|
|
|
17016
17138
|
// ../core/dist/skill-sync/artifact-resolver.js
|
|
17017
17139
|
import * as fs58 from "node:fs";
|
|
17018
|
-
import * as
|
|
17140
|
+
import * as path60 from "node:path";
|
|
17019
17141
|
function resolveSubscriptions(opts) {
|
|
17020
17142
|
const { clonePath, atlasUser } = opts;
|
|
17021
17143
|
if (atlasUser) {
|
|
17022
|
-
const subsPath =
|
|
17144
|
+
const subsPath = path60.join(clonePath, "members", atlasUser, "subscriptions.json");
|
|
17023
17145
|
if (fs58.existsSync(subsPath)) {
|
|
17024
17146
|
try {
|
|
17025
17147
|
const parsed = JSON.parse(fs58.readFileSync(subsPath, "utf-8"));
|
|
@@ -17034,7 +17156,7 @@ function resolveSubscriptions(opts) {
|
|
|
17034
17156
|
}
|
|
17035
17157
|
}
|
|
17036
17158
|
}
|
|
17037
|
-
const catsPath =
|
|
17159
|
+
const catsPath = path60.join(clonePath, "shared", "categories.json");
|
|
17038
17160
|
if (fs58.existsSync(catsPath)) {
|
|
17039
17161
|
try {
|
|
17040
17162
|
const parsed = JSON.parse(fs58.readFileSync(catsPath, "utf-8"));
|
|
@@ -17048,14 +17170,14 @@ function resolveSubscriptions(opts) {
|
|
|
17048
17170
|
} catch {
|
|
17049
17171
|
}
|
|
17050
17172
|
}
|
|
17051
|
-
const sharedDir =
|
|
17173
|
+
const sharedDir = path60.join(clonePath, "shared");
|
|
17052
17174
|
const cats = [];
|
|
17053
17175
|
if (fs58.existsSync(sharedDir)) {
|
|
17054
17176
|
for (const name of fs58.readdirSync(sharedDir)) {
|
|
17055
|
-
const dir =
|
|
17177
|
+
const dir = path60.join(sharedDir, name);
|
|
17056
17178
|
if (!fs58.statSync(dir).isDirectory())
|
|
17057
17179
|
continue;
|
|
17058
|
-
if (fs58.existsSync(
|
|
17180
|
+
if (fs58.existsSync(path60.join(dir, "skills")) || fs58.existsSync(path60.join(dir, "agents"))) {
|
|
17059
17181
|
cats.push(name);
|
|
17060
17182
|
}
|
|
17061
17183
|
}
|
|
@@ -17071,13 +17193,13 @@ function resolveSkillsDir(opts) {
|
|
|
17071
17193
|
const { sourceId, baseDir } = opts;
|
|
17072
17194
|
const out = [];
|
|
17073
17195
|
for (const name of listDirSafe(baseDir)) {
|
|
17074
|
-
const subdir =
|
|
17196
|
+
const subdir = path60.join(baseDir, name);
|
|
17075
17197
|
if (!fs58.statSync(subdir).isDirectory())
|
|
17076
17198
|
continue;
|
|
17077
|
-
if (!fs58.existsSync(
|
|
17199
|
+
if (!fs58.existsSync(path60.join(subdir, "SKILL.md")))
|
|
17078
17200
|
continue;
|
|
17079
17201
|
out.push({ kind: "skill", sourceId, sourcePath: subdir, deployBasename: name });
|
|
17080
|
-
const subagentsDir =
|
|
17202
|
+
const subagentsDir = path60.join(subdir, "references", "agents");
|
|
17081
17203
|
if (fs58.existsSync(subagentsDir) && fs58.statSync(subagentsDir).isDirectory()) {
|
|
17082
17204
|
for (const f of listDirSafe(subagentsDir)) {
|
|
17083
17205
|
if (!f.endsWith(".md"))
|
|
@@ -17085,7 +17207,7 @@ function resolveSkillsDir(opts) {
|
|
|
17085
17207
|
out.push({
|
|
17086
17208
|
kind: "subagent",
|
|
17087
17209
|
sourceId,
|
|
17088
|
-
sourcePath:
|
|
17210
|
+
sourcePath: path60.join(subagentsDir, f),
|
|
17089
17211
|
deployBasename: f,
|
|
17090
17212
|
parentSkill: name
|
|
17091
17213
|
});
|
|
@@ -17098,7 +17220,7 @@ function resolveAgentsDir(opts) {
|
|
|
17098
17220
|
const { sourceId, baseDir } = opts;
|
|
17099
17221
|
const out = [];
|
|
17100
17222
|
for (const name of listDirSafe(baseDir)) {
|
|
17101
|
-
const full =
|
|
17223
|
+
const full = path60.join(baseDir, name);
|
|
17102
17224
|
const stat = fs58.statSync(full);
|
|
17103
17225
|
if (stat.isFile() && name.endsWith(".md")) {
|
|
17104
17226
|
out.push({ kind: "agent", sourceId, sourcePath: full, deployBasename: name });
|
|
@@ -17109,7 +17231,7 @@ function resolveAgentsDir(opts) {
|
|
|
17109
17231
|
out.push({
|
|
17110
17232
|
kind: "agent",
|
|
17111
17233
|
sourceId,
|
|
17112
|
-
sourcePath:
|
|
17234
|
+
sourcePath: path60.join(full, f),
|
|
17113
17235
|
deployBasename: `${name}-${f}`
|
|
17114
17236
|
});
|
|
17115
17237
|
}
|
|
@@ -17121,7 +17243,7 @@ function resolveScriptsDir(opts) {
|
|
|
17121
17243
|
const { sourceId, baseDir } = opts;
|
|
17122
17244
|
const out = [];
|
|
17123
17245
|
for (const name of listDirSafe(baseDir)) {
|
|
17124
|
-
const full =
|
|
17246
|
+
const full = path60.join(baseDir, name);
|
|
17125
17247
|
const stat = fs58.statSync(full);
|
|
17126
17248
|
if (stat.isFile() && name.endsWith(".sh")) {
|
|
17127
17249
|
out.push({ kind: "script", sourceId, sourcePath: full, deployBasename: name });
|
|
@@ -17137,7 +17259,7 @@ function resolveRulesDir(opts) {
|
|
|
17137
17259
|
for (const name of listDirSafe(baseDir)) {
|
|
17138
17260
|
if (!name.endsWith(".md"))
|
|
17139
17261
|
continue;
|
|
17140
|
-
const full =
|
|
17262
|
+
const full = path60.join(baseDir, name);
|
|
17141
17263
|
if (!fs58.statSync(full).isFile())
|
|
17142
17264
|
continue;
|
|
17143
17265
|
out.push({ kind: "rule", sourceId, sourcePath: full, deployBasename: name });
|
|
@@ -17150,7 +17272,7 @@ function resolveJsonDir(opts) {
|
|
|
17150
17272
|
for (const name of listDirSafe(baseDir)) {
|
|
17151
17273
|
if (!name.endsWith(".json"))
|
|
17152
17274
|
continue;
|
|
17153
|
-
const full =
|
|
17275
|
+
const full = path60.join(baseDir, name);
|
|
17154
17276
|
if (!fs58.statSync(full).isFile())
|
|
17155
17277
|
continue;
|
|
17156
17278
|
out.push({ kind, sourceId, sourcePath: full, deployBasename: name });
|
|
@@ -17163,7 +17285,7 @@ function resolveOverlaysDir(opts) {
|
|
|
17163
17285
|
for (const name of listDirSafe(baseDir)) {
|
|
17164
17286
|
if (!name.endsWith(".md"))
|
|
17165
17287
|
continue;
|
|
17166
|
-
const full =
|
|
17288
|
+
const full = path60.join(baseDir, name);
|
|
17167
17289
|
if (!fs58.statSync(full).isFile())
|
|
17168
17290
|
continue;
|
|
17169
17291
|
const deployBasename = name.replace(/\.md$/, "");
|
|
@@ -17182,33 +17304,33 @@ function resolveSourceArtifacts(opts) {
|
|
|
17182
17304
|
const subscription = resolveSubscriptions({ clonePath, atlasUser });
|
|
17183
17305
|
const artifacts = [];
|
|
17184
17306
|
for (const cat of subscription.categories) {
|
|
17185
|
-
const catDir =
|
|
17307
|
+
const catDir = path60.join(clonePath, "shared", cat);
|
|
17186
17308
|
if (!fs58.existsSync(catDir))
|
|
17187
17309
|
continue;
|
|
17188
|
-
artifacts.push(...resolveSkillsDir({ sourceId, baseDir:
|
|
17189
|
-
artifacts.push(...resolveAgentsDir({ sourceId, baseDir:
|
|
17190
|
-
artifacts.push(...resolveScriptsDir({ sourceId, baseDir:
|
|
17191
|
-
artifacts.push(...resolveRulesDir({ sourceId, baseDir:
|
|
17192
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
17193
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
17310
|
+
artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path60.join(catDir, "skills") }));
|
|
17311
|
+
artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path60.join(catDir, "agents") }));
|
|
17312
|
+
artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path60.join(catDir, "scripts") }));
|
|
17313
|
+
artifacts.push(...resolveRulesDir({ sourceId, baseDir: path60.join(catDir, "rules") }));
|
|
17314
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path60.join(catDir, "hooks"), kind: "hook" }));
|
|
17315
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path60.join(catDir, "permissions"), kind: "permission" }));
|
|
17194
17316
|
}
|
|
17195
17317
|
if (atlasUser) {
|
|
17196
|
-
const memberRoot =
|
|
17318
|
+
const memberRoot = path60.join(clonePath, "members", atlasUser);
|
|
17197
17319
|
if (fs58.existsSync(memberRoot)) {
|
|
17198
|
-
artifacts.push(...resolveSkillsDir({ sourceId, baseDir:
|
|
17199
|
-
artifacts.push(...resolveAgentsDir({ sourceId, baseDir:
|
|
17200
|
-
artifacts.push(...resolveScriptsDir({ sourceId, baseDir:
|
|
17201
|
-
artifacts.push(...resolveRulesDir({ sourceId, baseDir:
|
|
17202
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
17203
|
-
artifacts.push(...resolveJsonDir({ sourceId, baseDir:
|
|
17320
|
+
artifacts.push(...resolveSkillsDir({ sourceId, baseDir: path60.join(memberRoot, "skills") }));
|
|
17321
|
+
artifacts.push(...resolveAgentsDir({ sourceId, baseDir: path60.join(memberRoot, "agents") }));
|
|
17322
|
+
artifacts.push(...resolveScriptsDir({ sourceId, baseDir: path60.join(memberRoot, "scripts") }));
|
|
17323
|
+
artifacts.push(...resolveRulesDir({ sourceId, baseDir: path60.join(memberRoot, "rules") }));
|
|
17324
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path60.join(memberRoot, "hooks"), kind: "hook" }));
|
|
17325
|
+
artifacts.push(...resolveJsonDir({ sourceId, baseDir: path60.join(memberRoot, "permissions"), kind: "permission" }));
|
|
17204
17326
|
artifacts.push(...resolveOverlaysDir({
|
|
17205
17327
|
sourceId,
|
|
17206
|
-
baseDir:
|
|
17328
|
+
baseDir: path60.join(memberRoot, "skills.overrides"),
|
|
17207
17329
|
targetKind: "skill"
|
|
17208
17330
|
}));
|
|
17209
17331
|
artifacts.push(...resolveOverlaysDir({
|
|
17210
17332
|
sourceId,
|
|
17211
|
-
baseDir:
|
|
17333
|
+
baseDir: path60.join(memberRoot, "agents.overrides"),
|
|
17212
17334
|
targetKind: "agent"
|
|
17213
17335
|
}));
|
|
17214
17336
|
}
|
|
@@ -17275,12 +17397,12 @@ var init_shim_targets = __esm({
|
|
|
17275
17397
|
// ../core/dist/skill-sync/symlink-deployer.js
|
|
17276
17398
|
import * as fs59 from "node:fs";
|
|
17277
17399
|
import * as os32 from "node:os";
|
|
17278
|
-
import * as
|
|
17400
|
+
import * as path61 from "node:path";
|
|
17279
17401
|
function claudeDir() {
|
|
17280
17402
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
17281
17403
|
if (override && override.length > 0)
|
|
17282
17404
|
return override;
|
|
17283
|
-
return
|
|
17405
|
+
return path61.join(os32.homedir(), ".claude");
|
|
17284
17406
|
}
|
|
17285
17407
|
function bucketFor(kind) {
|
|
17286
17408
|
switch (kind) {
|
|
@@ -17340,13 +17462,13 @@ function detectCollisions(artifacts) {
|
|
|
17340
17462
|
function cleanManagedSymlinks(claude, installedOlamVersion, overlayReferences, expectedAgentWinnerNames) {
|
|
17341
17463
|
const shadowBackups = [];
|
|
17342
17464
|
for (const bucket of BUCKETS) {
|
|
17343
|
-
const dir =
|
|
17465
|
+
const dir = path61.join(claude, bucket);
|
|
17344
17466
|
if (!fs59.existsSync(dir))
|
|
17345
17467
|
continue;
|
|
17346
17468
|
for (const name of fs59.readdirSync(dir)) {
|
|
17347
17469
|
if (name === ".olam-merged")
|
|
17348
17470
|
continue;
|
|
17349
|
-
const p =
|
|
17471
|
+
const p = path61.join(dir, name);
|
|
17350
17472
|
try {
|
|
17351
17473
|
const stat = fs59.lstatSync(p);
|
|
17352
17474
|
if (stat.isSymbolicLink()) {
|
|
@@ -17413,7 +17535,7 @@ function linkIfNeeded(target, link) {
|
|
|
17413
17535
|
function deployArtifacts(artifacts, opts) {
|
|
17414
17536
|
const claude = claudeDir();
|
|
17415
17537
|
for (const bucket of BUCKETS) {
|
|
17416
|
-
fs59.mkdirSync(
|
|
17538
|
+
fs59.mkdirSync(path61.join(claude, bucket), { recursive: true });
|
|
17417
17539
|
}
|
|
17418
17540
|
const { winners, collisions } = detectCollisions(artifacts);
|
|
17419
17541
|
const expectedAgentWinnerNames = new Set(winners.filter((a) => a.kind === "agent").map((a) => a.deployBasename));
|
|
@@ -17423,7 +17545,7 @@ function deployArtifacts(artifacts, opts) {
|
|
|
17423
17545
|
const bucket = bucketFor(artifact.kind);
|
|
17424
17546
|
if (!bucket)
|
|
17425
17547
|
continue;
|
|
17426
|
-
const linkPath =
|
|
17548
|
+
const linkPath = path61.join(claude, bucket, artifact.deployBasename);
|
|
17427
17549
|
if (artifact.kind === "agent" && artifact.resolvedContent !== void 0) {
|
|
17428
17550
|
const tmpPath = `${linkPath}.tmp-${process.pid}-${Date.now()}`;
|
|
17429
17551
|
fs59.writeFileSync(tmpPath, artifact.resolvedContent);
|
|
@@ -17610,24 +17732,24 @@ var init_meta_hooks = __esm({
|
|
|
17610
17732
|
// ../core/dist/skill-sync/settings-merger.js
|
|
17611
17733
|
import * as fs62 from "node:fs";
|
|
17612
17734
|
import * as os33 from "node:os";
|
|
17613
|
-
import * as
|
|
17735
|
+
import * as path62 from "node:path";
|
|
17614
17736
|
function claudeSettingsPath() {
|
|
17615
17737
|
const override = process.env["OLAM_CLAUDE_SETTINGS_PATH"];
|
|
17616
17738
|
if (override && override.length > 0)
|
|
17617
17739
|
return override;
|
|
17618
|
-
return
|
|
17740
|
+
return path62.join(claudeDirInternal2(), "settings.json");
|
|
17619
17741
|
}
|
|
17620
17742
|
function claudeDirInternal2() {
|
|
17621
17743
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
17622
17744
|
if (override && override.length > 0)
|
|
17623
17745
|
return override;
|
|
17624
|
-
return
|
|
17746
|
+
return path62.join(os33.homedir(), ".claude");
|
|
17625
17747
|
}
|
|
17626
17748
|
function settingsBackupDir() {
|
|
17627
17749
|
const override = process.env["OLAM_SETTINGS_BACKUP_DIR"];
|
|
17628
17750
|
if (override && override.length > 0)
|
|
17629
17751
|
return override;
|
|
17630
|
-
return
|
|
17752
|
+
return path62.join(os33.homedir(), ".olam", "state", "settings-backups");
|
|
17631
17753
|
}
|
|
17632
17754
|
function dedupeByMatcher(entries) {
|
|
17633
17755
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -17679,7 +17801,7 @@ function readJson(file) {
|
|
|
17679
17801
|
function rotateBackups(backupDir) {
|
|
17680
17802
|
if (!fs62.existsSync(backupDir))
|
|
17681
17803
|
return;
|
|
17682
|
-
const files = fs62.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full:
|
|
17804
|
+
const files = fs62.readdirSync(backupDir).filter((f) => f.endsWith(".json")).map((f) => ({ name: f, full: path62.join(backupDir, f), mtime: fs62.statSync(path62.join(backupDir, f)).mtimeMs })).sort((a, b) => b.mtime - a.mtime);
|
|
17683
17805
|
for (const f of files.slice(BACKUP_RETENTION)) {
|
|
17684
17806
|
try {
|
|
17685
17807
|
fs62.unlinkSync(f.full);
|
|
@@ -17694,7 +17816,7 @@ function backupSettings() {
|
|
|
17694
17816
|
const dir = settingsBackupDir();
|
|
17695
17817
|
fs62.mkdirSync(dir, { recursive: true });
|
|
17696
17818
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
17697
|
-
const dest =
|
|
17819
|
+
const dest = path62.join(dir, `settings-${stamp}.json`);
|
|
17698
17820
|
fs62.copyFileSync(src, dest);
|
|
17699
17821
|
rotateBackups(dir);
|
|
17700
17822
|
return dest;
|
|
@@ -17771,7 +17893,7 @@ function mergeSettings(input2) {
|
|
|
17771
17893
|
...input2.permissionFiles.length > 0 ? { allow: [...permSet] } : {}
|
|
17772
17894
|
}
|
|
17773
17895
|
};
|
|
17774
|
-
fs62.mkdirSync(
|
|
17896
|
+
fs62.mkdirSync(path62.dirname(settingsPath), { recursive: true });
|
|
17775
17897
|
const tmp = `${settingsPath}.tmp-${process.pid}`;
|
|
17776
17898
|
fs62.writeFileSync(tmp, JSON.stringify(next, null, 2) + "\n", { mode: 420 });
|
|
17777
17899
|
fs62.renameSync(tmp, settingsPath);
|
|
@@ -17830,15 +17952,15 @@ var init_schema5 = __esm({
|
|
|
17830
17952
|
});
|
|
17831
17953
|
|
|
17832
17954
|
// ../core/dist/skill-sync/per-project-override.js
|
|
17833
|
-
import { execFileSync as
|
|
17955
|
+
import { execFileSync as execFileSync15 } from "node:child_process";
|
|
17834
17956
|
import * as fs63 from "node:fs";
|
|
17835
|
-
import * as
|
|
17957
|
+
import * as path63 from "node:path";
|
|
17836
17958
|
import { parse as parseYaml5 } from "yaml";
|
|
17837
17959
|
function findProjectOverride(startDir) {
|
|
17838
|
-
let dir =
|
|
17839
|
-
const root =
|
|
17960
|
+
let dir = path63.resolve(startDir);
|
|
17961
|
+
const root = path63.parse(dir).root;
|
|
17840
17962
|
while (true) {
|
|
17841
|
-
const candidate =
|
|
17963
|
+
const candidate = path63.join(dir, PROJECT_OVERRIDE_RELATIVE_PATH);
|
|
17842
17964
|
if (fs63.existsSync(candidate) && fs63.statSync(candidate).isFile()) {
|
|
17843
17965
|
const raw = fs63.readFileSync(candidate, "utf-8");
|
|
17844
17966
|
let parsed;
|
|
@@ -17853,7 +17975,7 @@ function findProjectOverride(startDir) {
|
|
|
17853
17975
|
}
|
|
17854
17976
|
if (dir === root)
|
|
17855
17977
|
return void 0;
|
|
17856
|
-
dir =
|
|
17978
|
+
dir = path63.dirname(dir);
|
|
17857
17979
|
}
|
|
17858
17980
|
}
|
|
17859
17981
|
function applyOverrideToArtifacts(artifacts, override) {
|
|
@@ -17873,7 +17995,7 @@ function applyPinToClone(opts) {
|
|
|
17873
17995
|
if (ref.startsWith("-")) {
|
|
17874
17996
|
throw new Error(`refuses ref "${ref}" \u2014 must not start with "-" (would be parsed as a git option)`);
|
|
17875
17997
|
}
|
|
17876
|
-
|
|
17998
|
+
execFileSync15("git", ["-C", clonePath, "checkout", "-q", ref], {
|
|
17877
17999
|
stdio: ["ignore", "ignore", "pipe"]
|
|
17878
18000
|
});
|
|
17879
18001
|
}
|
|
@@ -17883,7 +18005,7 @@ function restoreCloneToBranchHead(opts) {
|
|
|
17883
18005
|
return;
|
|
17884
18006
|
}
|
|
17885
18007
|
try {
|
|
17886
|
-
|
|
18008
|
+
execFileSync15("git", ["-C", clonePath, "checkout", "-q", branch], {
|
|
17887
18009
|
stdio: ["ignore", "ignore", "pipe"]
|
|
17888
18010
|
});
|
|
17889
18011
|
} catch {
|
|
@@ -17894,14 +18016,14 @@ var init_per_project_override = __esm({
|
|
|
17894
18016
|
"../core/dist/skill-sync/per-project-override.js"() {
|
|
17895
18017
|
"use strict";
|
|
17896
18018
|
init_schema5();
|
|
17897
|
-
PROJECT_OVERRIDE_RELATIVE_PATH =
|
|
18019
|
+
PROJECT_OVERRIDE_RELATIVE_PATH = path63.join(".olam", "skill-overrides.yaml");
|
|
17898
18020
|
}
|
|
17899
18021
|
});
|
|
17900
18022
|
|
|
17901
18023
|
// ../core/dist/lib/file-lock.js
|
|
17902
18024
|
import * as fs64 from "node:fs";
|
|
17903
18025
|
import * as os34 from "node:os";
|
|
17904
|
-
import * as
|
|
18026
|
+
import * as path64 from "node:path";
|
|
17905
18027
|
function defaultIsPidAlive(pid) {
|
|
17906
18028
|
try {
|
|
17907
18029
|
process.kill(pid, 0);
|
|
@@ -17935,7 +18057,7 @@ function isLockStale(meta, opts) {
|
|
|
17935
18057
|
}
|
|
17936
18058
|
function tryAcquireOnce(lockPath, meta, opts) {
|
|
17937
18059
|
try {
|
|
17938
|
-
fs64.mkdirSync(
|
|
18060
|
+
fs64.mkdirSync(path64.dirname(lockPath), { recursive: true });
|
|
17939
18061
|
const fd = fs64.openSync(lockPath, "wx", 384);
|
|
17940
18062
|
try {
|
|
17941
18063
|
fs64.writeSync(fd, JSON.stringify(meta));
|
|
@@ -17967,7 +18089,7 @@ function tryAcquireOnce(lockPath, meta, opts) {
|
|
|
17967
18089
|
}
|
|
17968
18090
|
async function acquireFileLock(lockDir, options = {}) {
|
|
17969
18091
|
const lockFilename = options.lockFilename ?? DEFAULT_LOCK_FILENAME;
|
|
17970
|
-
const lockPath =
|
|
18092
|
+
const lockPath = path64.join(lockDir, lockFilename);
|
|
17971
18093
|
const acquireTimeoutMs = options.acquireTimeoutMs ?? DEFAULT_ACQUIRE_TIMEOUT_MS;
|
|
17972
18094
|
const staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS;
|
|
17973
18095
|
const now = options.now ?? Date.now;
|
|
@@ -18092,7 +18214,7 @@ var init_min_version_filter = __esm({
|
|
|
18092
18214
|
|
|
18093
18215
|
// ../core/dist/skill-sync/overlay-scan.js
|
|
18094
18216
|
import * as fs65 from "node:fs";
|
|
18095
|
-
import * as
|
|
18217
|
+
import * as path65 from "node:path";
|
|
18096
18218
|
function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
18097
18219
|
const result = /* @__PURE__ */ new Map();
|
|
18098
18220
|
if (!fs65.existsSync(overlayRoot)) {
|
|
@@ -18109,7 +18231,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
18109
18231
|
return result;
|
|
18110
18232
|
}
|
|
18111
18233
|
for (const subdir of OVERRIDE_SUBDIRS) {
|
|
18112
|
-
const dir =
|
|
18234
|
+
const dir = path65.join(overlayRoot, subdir);
|
|
18113
18235
|
if (!fs65.existsSync(dir))
|
|
18114
18236
|
continue;
|
|
18115
18237
|
walkMarkdown(dir, mdFiles, caps.maxFiles);
|
|
@@ -18125,8 +18247,8 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
18125
18247
|
continue;
|
|
18126
18248
|
throw err;
|
|
18127
18249
|
}
|
|
18128
|
-
const rel =
|
|
18129
|
-
if (rel.startsWith("..") ||
|
|
18250
|
+
const rel = path65.relative(overlayRootReal, realFile);
|
|
18251
|
+
if (rel.startsWith("..") || path65.isAbsolute(rel)) {
|
|
18130
18252
|
continue;
|
|
18131
18253
|
}
|
|
18132
18254
|
let content;
|
|
@@ -18144,7 +18266,7 @@ function scanOverlayReferences(overlayRoot, basenames, caps = DEFAULT_CAPS) {
|
|
|
18144
18266
|
}
|
|
18145
18267
|
throw err;
|
|
18146
18268
|
}
|
|
18147
|
-
const relpath =
|
|
18269
|
+
const relpath = path65.relative(overlayRoot, filepath).split(path65.sep).join("/");
|
|
18148
18270
|
for (const basename16 of basenames) {
|
|
18149
18271
|
if (content.includes(basename16)) {
|
|
18150
18272
|
const list = result.get(basename16) ?? [];
|
|
@@ -18168,7 +18290,7 @@ function walkMarkdown(dir, out, cap) {
|
|
|
18168
18290
|
if (out.length >= cap) {
|
|
18169
18291
|
throw new Error(`[overlay-scan] aborted: overlay tree contains > ${cap} markdown files. Check OLAM_CLAUDE_DIR / overlay paths are correctly scoped.`);
|
|
18170
18292
|
}
|
|
18171
|
-
const full =
|
|
18293
|
+
const full = path65.join(dir, entry.name);
|
|
18172
18294
|
if (entry.isSymbolicLink())
|
|
18173
18295
|
continue;
|
|
18174
18296
|
if (entry.isDirectory()) {
|
|
@@ -18195,10 +18317,10 @@ var init_overlay_scan = __esm({
|
|
|
18195
18317
|
// ../core/dist/skill-sync/settings-json-lock.js
|
|
18196
18318
|
import * as fs66 from "node:fs";
|
|
18197
18319
|
import * as os35 from "node:os";
|
|
18198
|
-
import * as
|
|
18320
|
+
import * as path66 from "node:path";
|
|
18199
18321
|
function defaultSettingsJsonLockPath() {
|
|
18200
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
18201
|
-
return
|
|
18322
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path66.join(os35.homedir(), ".olam", "state");
|
|
18323
|
+
return path66.join(stateDir, SETTINGS_JSON_LOCK_FILENAME);
|
|
18202
18324
|
}
|
|
18203
18325
|
function defaultIsPidAlive2(pid) {
|
|
18204
18326
|
try {
|
|
@@ -18237,7 +18359,7 @@ function isLockStale2(meta, opts) {
|
|
|
18237
18359
|
function tryAcquireOnce2(lockPath, meta, opts) {
|
|
18238
18360
|
for (let attempt = 0; attempt <= MAX_STEAL_ATTEMPTS; attempt += 1) {
|
|
18239
18361
|
try {
|
|
18240
|
-
fs66.mkdirSync(
|
|
18362
|
+
fs66.mkdirSync(path66.dirname(lockPath), { recursive: true });
|
|
18241
18363
|
const fd = fs66.openSync(lockPath, "wx", 384);
|
|
18242
18364
|
try {
|
|
18243
18365
|
fs66.writeSync(fd, JSON.stringify(meta));
|
|
@@ -18399,12 +18521,12 @@ var init_services_status = __esm({
|
|
|
18399
18521
|
import * as crypto9 from "node:crypto";
|
|
18400
18522
|
import * as fs67 from "node:fs";
|
|
18401
18523
|
import * as os36 from "node:os";
|
|
18402
|
-
import * as
|
|
18524
|
+
import * as path67 from "node:path";
|
|
18403
18525
|
function migrationSnapshotsDir2() {
|
|
18404
18526
|
const override = process.env["OLAM_MIGRATION_SNAPSHOTS_DIR"];
|
|
18405
18527
|
if (override && override.length > 0)
|
|
18406
18528
|
return override;
|
|
18407
|
-
return
|
|
18529
|
+
return path67.join(os36.homedir(), ".olam", "state", "migration-snapshots");
|
|
18408
18530
|
}
|
|
18409
18531
|
function writeMetaHooksSnapshot(originalSettings) {
|
|
18410
18532
|
const snapshot = {
|
|
@@ -18418,7 +18540,7 @@ function writeMetaHooksSnapshot(originalSettings) {
|
|
|
18418
18540
|
fs67.mkdirSync(dir, { recursive: true });
|
|
18419
18541
|
const stamp = validated.takenAt.replace(/[:.]/g, "-");
|
|
18420
18542
|
const rand = crypto9.randomBytes(3).toString("hex");
|
|
18421
|
-
const file =
|
|
18543
|
+
const file = path67.join(dir, `${META_HOOKS_SNAPSHOT_PREFIX}${stamp}-${process.pid}-${rand}.json`);
|
|
18422
18544
|
fs67.writeFileSync(file, JSON.stringify(validated, null, 2) + "\n", { mode: 384 });
|
|
18423
18545
|
return file;
|
|
18424
18546
|
}
|
|
@@ -18437,7 +18559,7 @@ function findLatestMetaHooksSnapshot() {
|
|
|
18437
18559
|
const candidates2 = fs67.readdirSync(dir).filter((n) => n.startsWith(META_HOOKS_SNAPSHOT_PREFIX) && n.endsWith(".json")).sort().reverse();
|
|
18438
18560
|
if (candidates2.length === 0)
|
|
18439
18561
|
return void 0;
|
|
18440
|
-
return
|
|
18562
|
+
return path67.join(dir, candidates2[0]);
|
|
18441
18563
|
}
|
|
18442
18564
|
function restoreSettingsFromSnapshot(snapshot, settingsPath) {
|
|
18443
18565
|
if (snapshot.originalSettings === null) {
|
|
@@ -18446,7 +18568,7 @@ function restoreSettingsFromSnapshot(snapshot, settingsPath) {
|
|
|
18446
18568
|
}
|
|
18447
18569
|
return;
|
|
18448
18570
|
}
|
|
18449
|
-
fs67.mkdirSync(
|
|
18571
|
+
fs67.mkdirSync(path67.dirname(settingsPath), { recursive: true });
|
|
18450
18572
|
const tmp = `${settingsPath}.tmp-restore-${process.pid}-${Date.now()}`;
|
|
18451
18573
|
fs67.writeFileSync(tmp, JSON.stringify(snapshot.originalSettings, null, 2) + "\n");
|
|
18452
18574
|
fs67.renameSync(tmp, settingsPath);
|
|
@@ -18816,17 +18938,17 @@ var init_markdown_merger = __esm({
|
|
|
18816
18938
|
|
|
18817
18939
|
// ../core/dist/skill-sync/managed-merge.js
|
|
18818
18940
|
import * as fs68 from "node:fs";
|
|
18819
|
-
import * as
|
|
18941
|
+
import * as path68 from "node:path";
|
|
18820
18942
|
function materializeMergedSkill(opts) {
|
|
18821
18943
|
const { sourceId, sourcePath, deployBasename, mergedContent, claudeDir: claudeDir2 } = opts;
|
|
18822
|
-
const managedDir =
|
|
18823
|
-
const sourceRoot =
|
|
18824
|
-
const managedResolved =
|
|
18825
|
-
if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot +
|
|
18944
|
+
const managedDir = path68.join(claudeDir2, ".olam-merged", sourceId, deployBasename);
|
|
18945
|
+
const sourceRoot = path68.resolve(path68.join(claudeDir2, ".olam-merged", sourceId));
|
|
18946
|
+
const managedResolved = path68.resolve(managedDir);
|
|
18947
|
+
if (!(managedResolved === sourceRoot || managedResolved.startsWith(sourceRoot + path68.sep))) {
|
|
18826
18948
|
throw new Error(`[managed-merge] refusing to materialize: deployBasename "${deployBasename}" escapes managed root "${sourceRoot}" (resolved to "${managedResolved}")`);
|
|
18827
18949
|
}
|
|
18828
18950
|
fs68.mkdirSync(managedDir, { recursive: true });
|
|
18829
|
-
const skillMdPath =
|
|
18951
|
+
const skillMdPath = path68.join(managedDir, "SKILL.md");
|
|
18830
18952
|
const tmpPath = `${skillMdPath}.tmp-${process.pid}-${Date.now()}`;
|
|
18831
18953
|
fs68.writeFileSync(tmpPath, mergedContent);
|
|
18832
18954
|
fs68.renameSync(tmpPath, skillMdPath);
|
|
@@ -18834,9 +18956,9 @@ function materializeMergedSkill(opts) {
|
|
|
18834
18956
|
for (const entry of baseEntries) {
|
|
18835
18957
|
if (entry === "SKILL.md")
|
|
18836
18958
|
continue;
|
|
18837
|
-
const linkPath =
|
|
18838
|
-
const targetAbsolute =
|
|
18839
|
-
const targetRelative =
|
|
18959
|
+
const linkPath = path68.join(managedDir, entry);
|
|
18960
|
+
const targetAbsolute = path68.join(sourcePath, entry);
|
|
18961
|
+
const targetRelative = path68.relative(managedDir, targetAbsolute);
|
|
18840
18962
|
try {
|
|
18841
18963
|
fs68.lstatSync(linkPath);
|
|
18842
18964
|
fs68.rmSync(linkPath, { recursive: true, force: true });
|
|
@@ -18850,7 +18972,7 @@ function materializeMergedSkill(opts) {
|
|
|
18850
18972
|
if (entry === "SKILL.md")
|
|
18851
18973
|
continue;
|
|
18852
18974
|
if (!baseEntrySet.has(entry)) {
|
|
18853
|
-
const stalePath =
|
|
18975
|
+
const stalePath = path68.join(managedDir, entry);
|
|
18854
18976
|
try {
|
|
18855
18977
|
fs68.rmSync(stalePath, { recursive: true, force: true });
|
|
18856
18978
|
} catch {
|
|
@@ -18860,7 +18982,7 @@ function materializeMergedSkill(opts) {
|
|
|
18860
18982
|
return managedDir;
|
|
18861
18983
|
}
|
|
18862
18984
|
function cleanMergedDir(claudeDir2) {
|
|
18863
|
-
fs68.rmSync(
|
|
18985
|
+
fs68.rmSync(path68.join(claudeDir2, ".olam-merged"), { recursive: true, force: true });
|
|
18864
18986
|
}
|
|
18865
18987
|
var init_managed_merge = __esm({
|
|
18866
18988
|
"../core/dist/skill-sync/managed-merge.js"() {
|
|
@@ -18949,7 +19071,7 @@ var init_prefix_rules = __esm({
|
|
|
18949
19071
|
|
|
18950
19072
|
// ../core/dist/skill-sync/prefix-deploy.js
|
|
18951
19073
|
import * as fs69 from "node:fs";
|
|
18952
|
-
import * as
|
|
19074
|
+
import * as path69 from "node:path";
|
|
18953
19075
|
function buildSourcePrefixMap(sources) {
|
|
18954
19076
|
const byId = /* @__PURE__ */ new Map();
|
|
18955
19077
|
const scopeById = /* @__PURE__ */ new Map();
|
|
@@ -18997,7 +19119,7 @@ function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
|
18997
19119
|
continue;
|
|
18998
19120
|
}
|
|
18999
19121
|
if (artifact.kind === "skill") {
|
|
19000
|
-
const skillMdPath =
|
|
19122
|
+
const skillMdPath = path69.join(artifact.sourcePath, "SKILL.md");
|
|
19001
19123
|
const content = fs69.readFileSync(skillMdPath);
|
|
19002
19124
|
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
19003
19125
|
const managedDir = materializeMergedSkill({
|
|
@@ -19062,12 +19184,12 @@ function sourceConfigPath(clonePath) {
|
|
|
19062
19184
|
return join76(clonePath, "shared", "source-config.yaml");
|
|
19063
19185
|
}
|
|
19064
19186
|
function readSourceConfig(clonePath, sourceId) {
|
|
19065
|
-
const
|
|
19066
|
-
if (!existsSync77(
|
|
19187
|
+
const path96 = sourceConfigPath(clonePath);
|
|
19188
|
+
if (!existsSync77(path96))
|
|
19067
19189
|
return void 0;
|
|
19068
19190
|
let raw;
|
|
19069
19191
|
try {
|
|
19070
|
-
raw = readFileSync66(
|
|
19192
|
+
raw = readFileSync66(path96, "utf-8");
|
|
19071
19193
|
} catch (err) {
|
|
19072
19194
|
emitMalformedWarning(sourceId, `read failed: ${errToMsg(err)}`);
|
|
19073
19195
|
return void 0;
|
|
@@ -19148,12 +19270,12 @@ var init_resolve_source_config = __esm({
|
|
|
19148
19270
|
// ../core/dist/skill-sync/engine.js
|
|
19149
19271
|
import * as fs70 from "node:fs";
|
|
19150
19272
|
import * as os37 from "node:os";
|
|
19151
|
-
import * as
|
|
19273
|
+
import * as path70 from "node:path";
|
|
19152
19274
|
function resolveAtlasUser(override) {
|
|
19153
19275
|
if (override)
|
|
19154
19276
|
return override;
|
|
19155
|
-
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] ||
|
|
19156
|
-
const f =
|
|
19277
|
+
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path70.join(os37.homedir(), ".claude");
|
|
19278
|
+
const f = path70.join(claudeDir2, ".atlas-user");
|
|
19157
19279
|
if (fs70.existsSync(f)) {
|
|
19158
19280
|
return fs70.readFileSync(f, "utf-8").trim() || void 0;
|
|
19159
19281
|
}
|
|
@@ -19310,7 +19432,7 @@ async function syncSkills(opts = {}) {
|
|
|
19310
19432
|
let baseContent;
|
|
19311
19433
|
let basePath;
|
|
19312
19434
|
if (overlay.targetKind === "skill") {
|
|
19313
|
-
basePath =
|
|
19435
|
+
basePath = path70.join(base.sourcePath, "SKILL.md");
|
|
19314
19436
|
baseContent = fs70.readFileSync(basePath, "utf-8");
|
|
19315
19437
|
} else {
|
|
19316
19438
|
basePath = base.sourcePath;
|
|
@@ -19377,7 +19499,7 @@ async function syncSkills(opts = {}) {
|
|
|
19377
19499
|
summary2.collisions = detectCollisions(baseArtifacts).collisions;
|
|
19378
19500
|
return summary2;
|
|
19379
19501
|
}
|
|
19380
|
-
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] ||
|
|
19502
|
+
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path70.join(os37.homedir(), ".claude");
|
|
19381
19503
|
const overlayReferences = scanOverlayReferences(claudeDirPath, SHIM_TARGETS.map((t) => t.basename));
|
|
19382
19504
|
summary2.deploy = deployArtifacts(baseArtifacts, {
|
|
19383
19505
|
installedOlamVersion,
|
|
@@ -19411,10 +19533,10 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
19411
19533
|
} catch {
|
|
19412
19534
|
try {
|
|
19413
19535
|
const raw = fs70.readFileSync(settingsFile);
|
|
19414
|
-
const bakDir =
|
|
19536
|
+
const bakDir = path70.join(path70.dirname(settingsFile), ".malformed-backups");
|
|
19415
19537
|
fs70.mkdirSync(bakDir, { recursive: true });
|
|
19416
19538
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
19417
|
-
const bakFile =
|
|
19539
|
+
const bakFile = path70.join(bakDir, `settings.json.malformed.${stamp}.bak`);
|
|
19418
19540
|
fs70.writeFileSync(bakFile, raw, { mode: 384 });
|
|
19419
19541
|
snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
|
|
19420
19542
|
} catch (bakErr) {
|
|
@@ -19465,7 +19587,7 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
19465
19587
|
} catch {
|
|
19466
19588
|
}
|
|
19467
19589
|
}
|
|
19468
|
-
fs70.mkdirSync(
|
|
19590
|
+
fs70.mkdirSync(path70.dirname(settingsFile), { recursive: true });
|
|
19469
19591
|
const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
|
|
19470
19592
|
fs70.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
|
|
19471
19593
|
fs70.renameSync(tmpPath, settingsFile);
|
|
@@ -19510,13 +19632,13 @@ var init_engine = __esm({
|
|
|
19510
19632
|
|
|
19511
19633
|
// ../core/dist/skill-sync/shadow-backup-manager.js
|
|
19512
19634
|
import * as fs71 from "node:fs";
|
|
19513
|
-
import * as
|
|
19635
|
+
import * as path71 from "node:path";
|
|
19514
19636
|
function listShadowBackups(opts = {}) {
|
|
19515
19637
|
const claude = opts.claudeDirOverride ?? claudeDir();
|
|
19516
19638
|
const now = opts.now ?? Date.now();
|
|
19517
19639
|
const out = [];
|
|
19518
19640
|
for (const bucket of SHADOW_BACKUP_BUCKETS) {
|
|
19519
|
-
const bucketDir =
|
|
19641
|
+
const bucketDir = path71.join(claude, bucket);
|
|
19520
19642
|
if (!fs71.existsSync(bucketDir))
|
|
19521
19643
|
continue;
|
|
19522
19644
|
let entries;
|
|
@@ -19532,7 +19654,7 @@ function listShadowBackups(opts = {}) {
|
|
|
19532
19654
|
const epochSeconds = Number.parseInt(match2[1], 10);
|
|
19533
19655
|
if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
|
|
19534
19656
|
continue;
|
|
19535
|
-
const full =
|
|
19657
|
+
const full = path71.join(bucketDir, name);
|
|
19536
19658
|
let sizeBytes = 0;
|
|
19537
19659
|
try {
|
|
19538
19660
|
const st = fs71.statSync(full);
|
|
@@ -19548,7 +19670,7 @@ function listShadowBackups(opts = {}) {
|
|
|
19548
19670
|
bucket,
|
|
19549
19671
|
basename: name,
|
|
19550
19672
|
originalBasename,
|
|
19551
|
-
originalPath:
|
|
19673
|
+
originalPath: path71.join(bucketDir, originalBasename),
|
|
19552
19674
|
epochSeconds,
|
|
19553
19675
|
ageMs: now - epochSeconds * 1e3,
|
|
19554
19676
|
sizeBytes
|
|
@@ -19602,17 +19724,17 @@ function pruneShadowBackups(opts) {
|
|
|
19602
19724
|
return { deleted, skipped };
|
|
19603
19725
|
}
|
|
19604
19726
|
function restoreShadowBackup(opts) {
|
|
19605
|
-
const abs =
|
|
19727
|
+
const abs = path71.resolve(opts.backupPath);
|
|
19606
19728
|
if (!fs71.existsSync(abs)) {
|
|
19607
19729
|
throw new Error(`backup file not found: ${abs}`);
|
|
19608
19730
|
}
|
|
19609
|
-
const basename16 =
|
|
19731
|
+
const basename16 = path71.basename(abs);
|
|
19610
19732
|
const match2 = SHADOW_BACKUP_SUFFIX_RE.exec(basename16);
|
|
19611
19733
|
if (!match2) {
|
|
19612
19734
|
throw new Error(`not a shadow-backup file (basename "${basename16}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
|
|
19613
19735
|
}
|
|
19614
19736
|
const originalBasename = basename16.slice(0, basename16.length - match2[0].length);
|
|
19615
|
-
const originalPath =
|
|
19737
|
+
const originalPath = path71.join(path71.dirname(abs), originalBasename);
|
|
19616
19738
|
if (fs71.existsSync(originalPath) && !opts.force) {
|
|
19617
19739
|
throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
|
|
19618
19740
|
}
|
|
@@ -19635,10 +19757,10 @@ var init_shadow_backup_manager = __esm({
|
|
|
19635
19757
|
// ../core/dist/global-config/repos.js
|
|
19636
19758
|
import * as fs72 from "node:fs";
|
|
19637
19759
|
import * as os38 from "node:os";
|
|
19638
|
-
import * as
|
|
19760
|
+
import * as path72 from "node:path";
|
|
19639
19761
|
function expandPath(p) {
|
|
19640
19762
|
if (p === "~" || p.startsWith("~/")) {
|
|
19641
|
-
return
|
|
19763
|
+
return path72.join(os38.homedir(), p.slice(1));
|
|
19642
19764
|
}
|
|
19643
19765
|
return p;
|
|
19644
19766
|
}
|
|
@@ -19750,13 +19872,13 @@ var init_global_config = __esm({
|
|
|
19750
19872
|
|
|
19751
19873
|
// ../core/dist/skill-sources/doctor-checks.js
|
|
19752
19874
|
import * as fs73 from "node:fs";
|
|
19753
|
-
import * as
|
|
19875
|
+
import * as path73 from "node:path";
|
|
19754
19876
|
import * as os39 from "node:os";
|
|
19755
19877
|
function claudeDirInternal3() {
|
|
19756
19878
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
19757
19879
|
if (override && override.length > 0)
|
|
19758
19880
|
return override;
|
|
19759
|
-
return
|
|
19881
|
+
return path73.join(os39.homedir(), ".claude");
|
|
19760
19882
|
}
|
|
19761
19883
|
function checkStateFileParse() {
|
|
19762
19884
|
const filePath = globalConfigPath();
|
|
@@ -19811,11 +19933,11 @@ function checkDanglingSymlinks() {
|
|
|
19811
19933
|
const buckets = ["commands", "agents", "skills", "scripts", "rules"];
|
|
19812
19934
|
const dangling = [];
|
|
19813
19935
|
for (const bucket of buckets) {
|
|
19814
|
-
const dir =
|
|
19936
|
+
const dir = path73.join(claude, bucket);
|
|
19815
19937
|
if (!fs73.existsSync(dir))
|
|
19816
19938
|
continue;
|
|
19817
19939
|
for (const name of fs73.readdirSync(dir)) {
|
|
19818
|
-
const linkPath =
|
|
19940
|
+
const linkPath = path73.join(dir, name);
|
|
19819
19941
|
try {
|
|
19820
19942
|
const lst = fs73.lstatSync(linkPath);
|
|
19821
19943
|
if (!lst.isSymbolicLink())
|
|
@@ -19860,7 +19982,7 @@ function checkOrphanedSnapshots() {
|
|
|
19860
19982
|
for (const name of fs73.readdirSync(dir)) {
|
|
19861
19983
|
if (!name.endsWith(".json"))
|
|
19862
19984
|
continue;
|
|
19863
|
-
const full =
|
|
19985
|
+
const full = path73.join(dir, name);
|
|
19864
19986
|
try {
|
|
19865
19987
|
const stat = fs73.statSync(full);
|
|
19866
19988
|
if (!stat.isFile())
|
|
@@ -19998,7 +20120,7 @@ function checkMemberNameMissing() {
|
|
|
19998
20120
|
return result;
|
|
19999
20121
|
}
|
|
20000
20122
|
const claudeDir2 = claudeDirInternal3();
|
|
20001
|
-
const atlasUserPath =
|
|
20123
|
+
const atlasUserPath = path73.join(claudeDir2, ".atlas-user");
|
|
20002
20124
|
const value = fs73.existsSync(atlasUserPath) ? fs73.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
20003
20125
|
if (value.length > 0) {
|
|
20004
20126
|
result.details = [`atlas-user: ${value}`];
|
|
@@ -20007,10 +20129,10 @@ function checkMemberNameMissing() {
|
|
|
20007
20129
|
result.healthy = false;
|
|
20008
20130
|
result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
|
|
20009
20131
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
20010
|
-
const membersDir =
|
|
20132
|
+
const membersDir = path73.join(clonePath, "members");
|
|
20011
20133
|
const existing = fs73.existsSync(membersDir) ? fs73.readdirSync(membersDir).filter((e) => {
|
|
20012
20134
|
try {
|
|
20013
|
-
return fs73.statSync(
|
|
20135
|
+
return fs73.statSync(path73.join(membersDir, e)).isDirectory();
|
|
20014
20136
|
} catch {
|
|
20015
20137
|
return false;
|
|
20016
20138
|
}
|
|
@@ -20024,7 +20146,7 @@ function checkMemberNameMissing() {
|
|
|
20024
20146
|
}
|
|
20025
20147
|
function checkMemberOverlayDrift() {
|
|
20026
20148
|
const claudeDir2 = claudeDirInternal3();
|
|
20027
|
-
const atlasUserPath =
|
|
20149
|
+
const atlasUserPath = path73.join(claudeDir2, ".atlas-user");
|
|
20028
20150
|
const atlasUser = fs73.existsSync(atlasUserPath) ? fs73.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
20029
20151
|
if (atlasUser.length === 0) {
|
|
20030
20152
|
return [];
|
|
@@ -20041,7 +20163,7 @@ function checkMemberOverlayDrift() {
|
|
|
20041
20163
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
20042
20164
|
const results = [];
|
|
20043
20165
|
for (const kind of ["skills", "agents"]) {
|
|
20044
|
-
const localRoot =
|
|
20166
|
+
const localRoot = path73.join(claudeDir2, `${kind}.overrides`);
|
|
20045
20167
|
if (!fs73.existsSync(localRoot))
|
|
20046
20168
|
continue;
|
|
20047
20169
|
let entries;
|
|
@@ -20051,7 +20173,7 @@ function checkMemberOverlayDrift() {
|
|
|
20051
20173
|
continue;
|
|
20052
20174
|
}
|
|
20053
20175
|
for (const entry of entries) {
|
|
20054
|
-
const localFile =
|
|
20176
|
+
const localFile = path73.join(localRoot, entry);
|
|
20055
20177
|
let stat;
|
|
20056
20178
|
try {
|
|
20057
20179
|
stat = fs73.statSync(localFile);
|
|
@@ -20060,7 +20182,7 @@ function checkMemberOverlayDrift() {
|
|
|
20060
20182
|
}
|
|
20061
20183
|
if (!stat.isFile())
|
|
20062
20184
|
continue;
|
|
20063
|
-
const cloneFile =
|
|
20185
|
+
const cloneFile = path73.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
|
|
20064
20186
|
const localSha = sha256OfPath(localFile);
|
|
20065
20187
|
const cloneSha = sha256OfPath(cloneFile);
|
|
20066
20188
|
if (localSha === cloneSha) {
|
|
@@ -20229,7 +20351,7 @@ var project_sweep_exports = {};
|
|
|
20229
20351
|
__export(project_sweep_exports, {
|
|
20230
20352
|
walkProjectRoot: () => walkProjectRoot
|
|
20231
20353
|
});
|
|
20232
|
-
import * as
|
|
20354
|
+
import * as path74 from "node:path";
|
|
20233
20355
|
import { readdirSync as readdirSync25, lstatSync as lstatSync6, statSync as statSync25, existsSync as existsSync82 } from "node:fs";
|
|
20234
20356
|
function isSkipped(basename16, extra) {
|
|
20235
20357
|
if (DEFAULT_SKIP.has(basename16))
|
|
@@ -20241,7 +20363,7 @@ function isSkipped(basename16, extra) {
|
|
|
20241
20363
|
return false;
|
|
20242
20364
|
}
|
|
20243
20365
|
function resolveMtime(dirPath, manifestFile, fsAdapter) {
|
|
20244
|
-
const gitHead =
|
|
20366
|
+
const gitHead = path74.join(dirPath, ".git", "HEAD");
|
|
20245
20367
|
if (fsAdapter.existsSync(gitHead)) {
|
|
20246
20368
|
try {
|
|
20247
20369
|
return fsAdapter.statSync(gitHead).mtimeMs;
|
|
@@ -20255,8 +20377,8 @@ function resolveMtime(dirPath, manifestFile, fsAdapter) {
|
|
|
20255
20377
|
}
|
|
20256
20378
|
}
|
|
20257
20379
|
function walk2(currentPath, depth, maxDepth, extraExclude, fsAdapter, results) {
|
|
20258
|
-
const adbManifest =
|
|
20259
|
-
const olamManifest =
|
|
20380
|
+
const adbManifest = path74.join(currentPath, ".adb.yaml");
|
|
20381
|
+
const olamManifest = path74.join(currentPath, ".olam.yaml");
|
|
20260
20382
|
if (fsAdapter.existsSync(adbManifest)) {
|
|
20261
20383
|
const mtime = resolveMtime(currentPath, adbManifest, fsAdapter);
|
|
20262
20384
|
results.push({ path: currentPath, manifestType: "adb", mtime });
|
|
@@ -20278,7 +20400,7 @@ function walk2(currentPath, depth, maxDepth, extraExclude, fsAdapter, results) {
|
|
|
20278
20400
|
for (const entry of entries) {
|
|
20279
20401
|
if (isSkipped(entry, extraExclude))
|
|
20280
20402
|
continue;
|
|
20281
|
-
const childPath =
|
|
20403
|
+
const childPath = path74.join(currentPath, entry);
|
|
20282
20404
|
let stat;
|
|
20283
20405
|
try {
|
|
20284
20406
|
stat = fsAdapter.lstatSync(childPath);
|
|
@@ -20336,11 +20458,11 @@ __export(kg_eager_exports, {
|
|
|
20336
20458
|
writeQueue: () => writeQueue
|
|
20337
20459
|
});
|
|
20338
20460
|
import * as fs74 from "node:fs";
|
|
20339
|
-
import * as
|
|
20461
|
+
import * as path75 from "node:path";
|
|
20340
20462
|
import * as os40 from "node:os";
|
|
20341
20463
|
function defaultQueuePath() {
|
|
20342
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
20343
|
-
return
|
|
20464
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path75.join(os40.homedir(), ".olam", "state");
|
|
20465
|
+
return path75.join(stateDir, "kg-pending.jsonl");
|
|
20344
20466
|
}
|
|
20345
20467
|
function readQueue(queuePath) {
|
|
20346
20468
|
if (!fs74.existsSync(queuePath))
|
|
@@ -20359,14 +20481,14 @@ function readQueue(queuePath) {
|
|
|
20359
20481
|
return entries;
|
|
20360
20482
|
}
|
|
20361
20483
|
function writeQueue(queuePath, entries) {
|
|
20362
|
-
fs74.mkdirSync(
|
|
20484
|
+
fs74.mkdirSync(path75.dirname(queuePath), { recursive: true });
|
|
20363
20485
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
20364
20486
|
fs74.writeFileSync(queuePath, content, "utf-8");
|
|
20365
20487
|
}
|
|
20366
20488
|
function appendQueue(queuePath, repos, nowMs) {
|
|
20367
20489
|
if (repos.length === 0)
|
|
20368
20490
|
return;
|
|
20369
|
-
fs74.mkdirSync(
|
|
20491
|
+
fs74.mkdirSync(path75.dirname(queuePath), { recursive: true });
|
|
20370
20492
|
const lines = repos.map((r) => JSON.stringify({ path: r.path, addedAt: nowMs })).join("\n") + "\n";
|
|
20371
20493
|
fs74.appendFileSync(queuePath, lines, "utf-8");
|
|
20372
20494
|
}
|
|
@@ -20422,7 +20544,7 @@ __export(machine_schema_exports, {
|
|
|
20422
20544
|
writeMachineConfig: () => writeMachineConfig
|
|
20423
20545
|
});
|
|
20424
20546
|
import * as fs77 from "node:fs";
|
|
20425
|
-
import * as
|
|
20547
|
+
import * as path79 from "node:path";
|
|
20426
20548
|
import * as os41 from "node:os";
|
|
20427
20549
|
import { parse as parseYaml7, stringify as stringifyYaml5 } from "yaml";
|
|
20428
20550
|
function readMachineConfig(configPath) {
|
|
@@ -20439,7 +20561,7 @@ function readMachineConfig(configPath) {
|
|
|
20439
20561
|
}
|
|
20440
20562
|
function writeMachineConfig(config, configPath) {
|
|
20441
20563
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
20442
|
-
fs77.mkdirSync(
|
|
20564
|
+
fs77.mkdirSync(path79.dirname(p), { recursive: true });
|
|
20443
20565
|
fs77.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
|
|
20444
20566
|
}
|
|
20445
20567
|
function initMachineConfig(opts = {}) {
|
|
@@ -20463,9 +20585,9 @@ var init_machine_schema = __esm({
|
|
|
20463
20585
|
channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
|
|
20464
20586
|
auto_update: external_exports.boolean().default(true),
|
|
20465
20587
|
telemetry: external_exports.boolean().default(true),
|
|
20466
|
-
worlds_dir: external_exports.string().default(() =>
|
|
20588
|
+
worlds_dir: external_exports.string().default(() => path79.join(os41.homedir(), ".olam", "worlds"))
|
|
20467
20589
|
});
|
|
20468
|
-
DEFAULT_CONFIG_PATH =
|
|
20590
|
+
DEFAULT_CONFIG_PATH = path79.join(os41.homedir(), ".olam", "config.yaml");
|
|
20469
20591
|
}
|
|
20470
20592
|
});
|
|
20471
20593
|
|
|
@@ -20660,16 +20782,16 @@ function isValidConfig(value) {
|
|
|
20660
20782
|
if (typeof v.install_id !== "string" || v.install_id.length === 0) return false;
|
|
20661
20783
|
return true;
|
|
20662
20784
|
}
|
|
20663
|
-
function atomicWriteJSON(
|
|
20785
|
+
function atomicWriteJSON(path96, value, stderr = process.stderr) {
|
|
20664
20786
|
ensureStateDir();
|
|
20665
|
-
const dir = dirname3(
|
|
20787
|
+
const dir = dirname3(path96);
|
|
20666
20788
|
if (!existsSync6(dir)) {
|
|
20667
20789
|
mkdirSync2(dir, { recursive: true });
|
|
20668
20790
|
}
|
|
20669
|
-
const tmp = `${
|
|
20791
|
+
const tmp = `${path96}.tmp.${process.pid}`;
|
|
20670
20792
|
try {
|
|
20671
20793
|
writeFileSync2(tmp, JSON.stringify(value, null, 2) + "\n", { encoding: "utf8" });
|
|
20672
|
-
renameSync2(tmp,
|
|
20794
|
+
renameSync2(tmp, path96);
|
|
20673
20795
|
} catch (err) {
|
|
20674
20796
|
if (existsSync6(tmp)) {
|
|
20675
20797
|
try {
|
|
@@ -21030,9 +21152,9 @@ var UnknownArchetypeError = class extends Error {
|
|
|
21030
21152
|
};
|
|
21031
21153
|
var ArchetypeCycleError = class extends Error {
|
|
21032
21154
|
path;
|
|
21033
|
-
constructor(
|
|
21034
|
-
super(`Archetype inheritance cycle detected: ${
|
|
21035
|
-
this.path =
|
|
21155
|
+
constructor(path96) {
|
|
21156
|
+
super(`Archetype inheritance cycle detected: ${path96.join(" \u2192 ")} \u2192 ${path96[0] ?? "?"}`);
|
|
21157
|
+
this.path = path96;
|
|
21036
21158
|
this.name = "ArchetypeCycleError";
|
|
21037
21159
|
}
|
|
21038
21160
|
};
|
|
@@ -21520,7 +21642,7 @@ function substitutePlaceholders(templateYaml, values) {
|
|
|
21520
21642
|
function renderOneSecret(binding, templatesRoot, reuse, deps = {}, rotate = false) {
|
|
21521
21643
|
const olamHome5 = deps.olamHome ?? OLAM_HOME;
|
|
21522
21644
|
const readFile = deps.readFile ?? defaultReadFile;
|
|
21523
|
-
const
|
|
21645
|
+
const writeFile2 = deps.writeFile ?? defaultWriteFile;
|
|
21524
21646
|
const fileExists = deps.fileExists ?? defaultFileExists;
|
|
21525
21647
|
const genRandomHex = deps.genRandomHex ?? defaultGenRandomHex;
|
|
21526
21648
|
const runGhTokenCmd = deps.runGhTokenCmd ?? defaultRunGhTokenCmd;
|
|
@@ -21535,7 +21657,7 @@ function renderOneSecret(binding, templatesRoot, reuse, deps = {}, rotate = fals
|
|
|
21535
21657
|
olamHome5,
|
|
21536
21658
|
reuse?.keys[p.key],
|
|
21537
21659
|
rotate,
|
|
21538
|
-
{ readFile, writeFile, fileExists, genRandomHex, runGhTokenCmd }
|
|
21660
|
+
{ readFile, writeFile: writeFile2, fileExists, genRandomHex, runGhTokenCmd }
|
|
21539
21661
|
);
|
|
21540
21662
|
if (!resolved.ok) {
|
|
21541
21663
|
missingSources.push(`${p.key}: ${resolved.reason}`);
|
|
@@ -21831,14 +21953,14 @@ function ensureSecrets() {
|
|
|
21831
21953
|
step("1/6 \u2014 operator secrets");
|
|
21832
21954
|
mkdirSync19(OLAM_HOME3, { recursive: true });
|
|
21833
21955
|
for (const name of SECRET_FILES) {
|
|
21834
|
-
const
|
|
21835
|
-
if (existsSync29(
|
|
21956
|
+
const path96 = join34(OLAM_HOME3, name);
|
|
21957
|
+
if (existsSync29(path96)) {
|
|
21836
21958
|
printInfo("skip", `~/.olam/${name} already exists`);
|
|
21837
21959
|
continue;
|
|
21838
21960
|
}
|
|
21839
21961
|
const hex = randomBytes7(32).toString("hex");
|
|
21840
|
-
writeFileSync15(
|
|
21841
|
-
chmodSync4(
|
|
21962
|
+
writeFileSync15(path96, hex + "\n", { encoding: "utf8", mode: 384 });
|
|
21963
|
+
chmodSync4(path96, 384);
|
|
21842
21964
|
printSuccess(`generated ~/.olam/${name}`);
|
|
21843
21965
|
}
|
|
21844
21966
|
}
|
|
@@ -21961,13 +22083,13 @@ function installObservability(opts) {
|
|
|
21961
22083
|
scriptEnv.OLAM_BUNDLE_ROOT = bundleRoot;
|
|
21962
22084
|
}
|
|
21963
22085
|
for (const script of OBSERVABILITY_SCRIPTS) {
|
|
21964
|
-
const
|
|
21965
|
-
if (!existsSync29(
|
|
22086
|
+
const path96 = join34(observabilityDir, script);
|
|
22087
|
+
if (!existsSync29(path96)) {
|
|
21966
22088
|
printWarning(`observability script missing: ${script} \u2014 skipping`);
|
|
21967
22089
|
continue;
|
|
21968
22090
|
}
|
|
21969
22091
|
printInfo("run", script);
|
|
21970
|
-
const result = spawnSync10("bash", [
|
|
22092
|
+
const result = spawnSync10("bash", [path96], {
|
|
21971
22093
|
stdio: "inherit",
|
|
21972
22094
|
env: scriptEnv
|
|
21973
22095
|
});
|
|
@@ -22976,56 +23098,56 @@ var SECRET_LEN_BYTES = 32;
|
|
|
22976
23098
|
function generateSecret() {
|
|
22977
23099
|
return randomBytes8(SECRET_LEN_BYTES).toString("hex");
|
|
22978
23100
|
}
|
|
22979
|
-
function writeSecretAtPath(
|
|
22980
|
-
mkdirSync21(dirname22(
|
|
22981
|
-
const tmp = `${
|
|
23101
|
+
function writeSecretAtPath(path96, value) {
|
|
23102
|
+
mkdirSync21(dirname22(path96), { recursive: true });
|
|
23103
|
+
const tmp = `${path96}.tmp.${process.pid}`;
|
|
22982
23104
|
writeFileSync16(tmp, value, { mode: 384 });
|
|
22983
23105
|
chmodSync5(tmp, 384);
|
|
22984
|
-
renameSync6(tmp,
|
|
23106
|
+
renameSync6(tmp, path96);
|
|
22985
23107
|
}
|
|
22986
|
-
function readSecretAtPathOrNull(
|
|
22987
|
-
if (!existsSync32(
|
|
22988
|
-
const mode = statSync8(
|
|
23108
|
+
function readSecretAtPathOrNull(path96) {
|
|
23109
|
+
if (!existsSync32(path96)) return null;
|
|
23110
|
+
const mode = statSync8(path96).mode & 511;
|
|
22989
23111
|
if (mode !== 384) {
|
|
22990
23112
|
process.stderr.write(
|
|
22991
|
-
`warn: ${
|
|
23113
|
+
`warn: ${path96} has mode 0${mode.toString(8)}; expected 0600. Run 'olam memory secret rotate' to regenerate.
|
|
22992
23114
|
`
|
|
22993
23115
|
);
|
|
22994
23116
|
}
|
|
22995
|
-
return readFileSync25(
|
|
23117
|
+
return readFileSync25(path96, "utf8").trim();
|
|
22996
23118
|
}
|
|
22997
|
-
function readSecretAtPath(
|
|
22998
|
-
const v = readSecretAtPathOrNull(
|
|
23119
|
+
function readSecretAtPath(path96) {
|
|
23120
|
+
const v = readSecretAtPathOrNull(path96);
|
|
22999
23121
|
if (v === null) {
|
|
23000
23122
|
throw new Error(
|
|
23001
|
-
`Secret not found at ${
|
|
23123
|
+
`Secret not found at ${path96}. Run 'olam memory start' to generate it.`
|
|
23002
23124
|
);
|
|
23003
23125
|
}
|
|
23004
23126
|
return v;
|
|
23005
23127
|
}
|
|
23006
|
-
function ensureMemorySecret(
|
|
23007
|
-
const existing = readSecretAtPathOrNull(
|
|
23128
|
+
function ensureMemorySecret(path96 = MEMORY_SECRET_PATH) {
|
|
23129
|
+
const existing = readSecretAtPathOrNull(path96);
|
|
23008
23130
|
if (existing) return existing;
|
|
23009
23131
|
const fresh = generateSecret();
|
|
23010
|
-
writeSecretAtPath(
|
|
23132
|
+
writeSecretAtPath(path96, fresh);
|
|
23011
23133
|
return fresh;
|
|
23012
23134
|
}
|
|
23013
|
-
function readMemorySecretOrNull(
|
|
23014
|
-
return readSecretAtPathOrNull(
|
|
23135
|
+
function readMemorySecretOrNull(path96 = MEMORY_SECRET_PATH) {
|
|
23136
|
+
return readSecretAtPathOrNull(path96);
|
|
23015
23137
|
}
|
|
23016
|
-
function readMemorySecret(
|
|
23017
|
-
return readSecretAtPath(
|
|
23138
|
+
function readMemorySecret(path96 = MEMORY_SECRET_PATH) {
|
|
23139
|
+
return readSecretAtPath(path96);
|
|
23018
23140
|
}
|
|
23019
|
-
function rotateMemorySecret(
|
|
23141
|
+
function rotateMemorySecret(path96 = MEMORY_SECRET_PATH) {
|
|
23020
23142
|
const fresh = generateSecret();
|
|
23021
|
-
writeSecretAtPath(
|
|
23143
|
+
writeSecretAtPath(path96, fresh);
|
|
23022
23144
|
return fresh;
|
|
23023
23145
|
}
|
|
23024
|
-
function hasMemorySecret(
|
|
23025
|
-
return existsSync32(
|
|
23146
|
+
function hasMemorySecret(path96 = MEMORY_SECRET_PATH) {
|
|
23147
|
+
return existsSync32(path96);
|
|
23026
23148
|
}
|
|
23027
|
-
function writeCloudMemorySecret(value,
|
|
23028
|
-
writeSecretAtPath(
|
|
23149
|
+
function writeCloudMemorySecret(value, path96 = CLOUD_MEMORY_SECRET_PATH) {
|
|
23150
|
+
writeSecretAtPath(path96, value);
|
|
23029
23151
|
}
|
|
23030
23152
|
|
|
23031
23153
|
// src/commands/memory-service-container.ts
|
|
@@ -25194,9 +25316,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
25194
25316
|
"These source files have changed since the image was built; the",
|
|
25195
25317
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
25196
25318
|
];
|
|
25197
|
-
for (const { path:
|
|
25319
|
+
for (const { path: path96, mtimeMs } of result.newerSources) {
|
|
25198
25320
|
const when = new Date(mtimeMs).toISOString();
|
|
25199
|
-
lines.push(` \u2022 ${
|
|
25321
|
+
lines.push(` \u2022 ${path96} (modified ${when})`);
|
|
25200
25322
|
}
|
|
25201
25323
|
lines.push("");
|
|
25202
25324
|
lines.push("Rebuild with:");
|
|
@@ -25577,9 +25699,9 @@ async function readHostCpTokenForCreate() {
|
|
|
25577
25699
|
try {
|
|
25578
25700
|
const { default: fs96 } = await import("node:fs");
|
|
25579
25701
|
const { default: os50 } = await import("node:os");
|
|
25580
|
-
const { default:
|
|
25581
|
-
const tp =
|
|
25582
|
-
process.env.OLAM_HOME ??
|
|
25702
|
+
const { default: path96 } = await import("node:path");
|
|
25703
|
+
const tp = path96.join(
|
|
25704
|
+
process.env.OLAM_HOME ?? path96.join(os50.homedir(), ".olam"),
|
|
25583
25705
|
"host-cp.token"
|
|
25584
25706
|
);
|
|
25585
25707
|
if (!fs96.existsSync(tp)) return null;
|
|
@@ -25592,7 +25714,10 @@ function registerCreate(program2) {
|
|
|
25592
25714
|
program2.command("create").description("Create a new development world").option("--name <name>", "World name (required unless --from-prompt is set; auto-derived in that case)").option("--repos <repos...>", "Repos to include (names from .olam/config.yaml; wins over --workspace)").option("--workspace <name>", "Named workspace from the host catalog (~/.olam/workspaces/<name>.yaml)").option("--task <task>", "Initial task to dispatch").option("--branch <branch>", "Override default branch name").option("--plan <file>", "Path to a plan file to inject").option("--no-auth", "Skip auto-injecting host credentials").option("--no-host-cp", 'Suppress the host CP "you might want to start it" hint').option("--auto-codex-review", "Spawn a parallel codex-review lane that critiques main as it works").option("--no-open", "Suppress auto-opening the Host CP UI in the browser on success").option("--rebuild-base", "Rebuild olam-devbox:latest before creating (slow)").option("--no-freshness-check", "Skip the devbox image freshness check").option("--from-prompt <prompt>", "NL prompt \u2192 infer workspace + dispatch (CLI parity for olam_create_from_prompt MCP tool)").option("--keep-after-merge", "Disable auto-destroy when the world's PR merges (useful for inspection/debugging)").option("--carry-uncommitted", "Preserve operator's uncommitted edits in the world's worktree").option(
|
|
25593
25715
|
"--allow-bootstrap-failure",
|
|
25594
25716
|
"Treat bootstrap step failures as warnings instead of destroying the world (dogfood escape hatch for cross-repo seed coupling)"
|
|
25595
|
-
).option("--devbox-image <ref>", "Override the default devbox image (full registry/name:tag or @sha256: ref)").option("--allow-custom-registry", "Allow --devbox-image refs outside ghcr.io/pleri/* (logs a warning)").option("--runbook <name>", "Named runbook profile from ~/.olam/config.json").
|
|
25717
|
+
).option("--devbox-image <ref>", "Override the default devbox image (full registry/name:tag or @sha256: ref)").option("--allow-custom-registry", "Allow --devbox-image refs outside ghcr.io/pleri/* (logs a warning)").option("--runbook <name>", "Named runbook profile from ~/.olam/config.json").option(
|
|
25718
|
+
"--claude-home <id-or-path>",
|
|
25719
|
+
"Use a per-world Claude Code HOME (multi-account isolation; see docs/decisions/045-claude-home-override.md)"
|
|
25720
|
+
).action(async (opts) => {
|
|
25596
25721
|
const { resolveDevboxImageOverride: resolveDevboxImageOverride2, decideAllowlist: decideAllowlist2 } = await Promise.resolve().then(() => (init_registry_allowlist(), registry_allowlist_exports));
|
|
25597
25722
|
const overrideRef = resolveDevboxImageOverride2(opts.devboxImage);
|
|
25598
25723
|
if (overrideRef) {
|
|
@@ -25770,6 +25895,25 @@ function registerCreate(program2) {
|
|
|
25770
25895
|
throw err;
|
|
25771
25896
|
}
|
|
25772
25897
|
}
|
|
25898
|
+
let resolvedClaudeHome;
|
|
25899
|
+
if (opts.claudeHome !== void 0 && opts.claudeHome.length > 0) {
|
|
25900
|
+
try {
|
|
25901
|
+
const { resolveClaudeHome: resolveClaudeHome2, ensureClaudeHomeDir: ensureClaudeHomeDir2 } = await Promise.resolve().then(() => (init_home_override(), home_override_exports));
|
|
25902
|
+
const target = resolveClaudeHome2({ flag: opts.claudeHome });
|
|
25903
|
+
await ensureClaudeHomeDir2(target);
|
|
25904
|
+
resolvedClaudeHome = target;
|
|
25905
|
+
printInfo(
|
|
25906
|
+
"Claude home",
|
|
25907
|
+
`${target} (per-world Claude Code instance \u2014 see ADR 045)`
|
|
25908
|
+
);
|
|
25909
|
+
} catch (err) {
|
|
25910
|
+
printError(
|
|
25911
|
+
`Invalid --claude-home: ${err instanceof Error ? err.message : String(err)}`
|
|
25912
|
+
);
|
|
25913
|
+
process.exitCode = 1;
|
|
25914
|
+
return;
|
|
25915
|
+
}
|
|
25916
|
+
}
|
|
25773
25917
|
const spinner = ora5("Creating world...").start();
|
|
25774
25918
|
try {
|
|
25775
25919
|
const world = await ctx.worldManager.createWorld({
|
|
@@ -25788,7 +25932,8 @@ function registerCreate(program2) {
|
|
|
25788
25932
|
// manager, matching the manager's strict `if (!opts.carryUncommitted)`.
|
|
25789
25933
|
carryUncommitted: opts.carryUncommitted === true,
|
|
25790
25934
|
allowBootstrapFailure: opts.allowBootstrapFailure === true,
|
|
25791
|
-
...opts.runbook ? { runbookName: opts.runbook } : {}
|
|
25935
|
+
...opts.runbook ? { runbookName: opts.runbook } : {},
|
|
25936
|
+
...resolvedClaudeHome ? { claudeHome: resolvedClaudeHome } : {}
|
|
25792
25937
|
});
|
|
25793
25938
|
spinner.succeed("World created");
|
|
25794
25939
|
try {
|
|
@@ -26022,8 +26167,8 @@ async function readHostCpToken3() {
|
|
|
26022
26167
|
try {
|
|
26023
26168
|
const { default: fs96 } = await import("node:fs");
|
|
26024
26169
|
const { default: os50 } = await import("node:os");
|
|
26025
|
-
const { default:
|
|
26026
|
-
const tp =
|
|
26170
|
+
const { default: path96 } = await import("node:path");
|
|
26171
|
+
const tp = path96.join(os50.homedir(), ".olam", "host-cp.token");
|
|
26027
26172
|
if (!fs96.existsSync(tp)) return null;
|
|
26028
26173
|
const raw = fs96.readFileSync(tp, "utf-8").trim();
|
|
26029
26174
|
return raw.length > 0 ? raw : null;
|
|
@@ -26240,7 +26385,7 @@ init_output();
|
|
|
26240
26385
|
import * as fs36 from "node:fs";
|
|
26241
26386
|
import * as http3 from "node:http";
|
|
26242
26387
|
import * as os18 from "node:os";
|
|
26243
|
-
import * as
|
|
26388
|
+
import * as path38 from "node:path";
|
|
26244
26389
|
var CLI_VERSION2 = process.env["OLAM_CLI_VERSION"] ?? "0.0.0";
|
|
26245
26390
|
var HOST_CP_PORT2 = 19e3;
|
|
26246
26391
|
var STATE_ENUM = [
|
|
@@ -26331,7 +26476,7 @@ async function getMachineStatus(_probe, _loadCtx, _readToken) {
|
|
|
26331
26476
|
}
|
|
26332
26477
|
} catch {
|
|
26333
26478
|
}
|
|
26334
|
-
const manifestPath2 =
|
|
26479
|
+
const manifestPath2 = path38.join(os18.homedir(), ".olam", "cache", "manifest.json");
|
|
26335
26480
|
let updateAvailable = null;
|
|
26336
26481
|
let lastUpdateCheck = null;
|
|
26337
26482
|
if (fs36.existsSync(manifestPath2)) {
|
|
@@ -26477,7 +26622,7 @@ init_context();
|
|
|
26477
26622
|
init_output();
|
|
26478
26623
|
import fs37 from "node:fs";
|
|
26479
26624
|
import os19 from "node:os";
|
|
26480
|
-
import
|
|
26625
|
+
import path39 from "node:path";
|
|
26481
26626
|
import { execFileSync as execFileSync9 } from "node:child_process";
|
|
26482
26627
|
function registerClean(program2) {
|
|
26483
26628
|
program2.command("clean").description("Reap orphan world filesystem state under ~/.olam/worlds/").option("--apply", "Actually delete the orphans (default is dry-run)", false).option(
|
|
@@ -26501,7 +26646,7 @@ async function runClean(opts) {
|
|
|
26501
26646
|
printError(error?.message ?? "Olam is not configured. Run `olam init` first.");
|
|
26502
26647
|
return 1;
|
|
26503
26648
|
}
|
|
26504
|
-
const worldsDir =
|
|
26649
|
+
const worldsDir = path39.join(os19.homedir(), ".olam", "worlds");
|
|
26505
26650
|
if (!fs37.existsSync(worldsDir)) {
|
|
26506
26651
|
if (opts.json) {
|
|
26507
26652
|
process.stdout.write(`${JSON.stringify({ worldsDir, entries: [] })}
|
|
@@ -26518,7 +26663,7 @@ async function runClean(opts) {
|
|
|
26518
26663
|
const worktreeMap = collectWorktrees(worldsDir);
|
|
26519
26664
|
const entries = [];
|
|
26520
26665
|
for (const id of fs37.readdirSync(worldsDir).sort()) {
|
|
26521
|
-
const fullPath =
|
|
26666
|
+
const fullPath = path39.join(worldsDir, id);
|
|
26522
26667
|
const stat = safeStat(fullPath);
|
|
26523
26668
|
if (!stat || !stat.isDirectory()) continue;
|
|
26524
26669
|
entries.push(classifyWorld({ id, fullPath, liveIds, worktreeMap }));
|
|
@@ -26584,7 +26729,7 @@ function classifyWorld(args) {
|
|
|
26584
26729
|
if (liveIds.has(id)) {
|
|
26585
26730
|
return { id, path: fullPath, bytes, category: "active", note: "in registry" };
|
|
26586
26731
|
}
|
|
26587
|
-
const worktreeChild =
|
|
26732
|
+
const worktreeChild = path39.join(fullPath, "olam");
|
|
26588
26733
|
const worktreeInfo = worktreeMap.get(worktreeChild);
|
|
26589
26734
|
if (worktreeInfo) {
|
|
26590
26735
|
if (worktreeInfo.dirty > 0 || worktreeInfo.unpushed > 0) {
|
|
@@ -26641,8 +26786,8 @@ function reapEntry(entry) {
|
|
|
26641
26786
|
function collectWorktrees(worldsDir) {
|
|
26642
26787
|
const out = /* @__PURE__ */ new Map();
|
|
26643
26788
|
for (const id of fs37.readdirSync(worldsDir)) {
|
|
26644
|
-
const child =
|
|
26645
|
-
const gitMarker =
|
|
26789
|
+
const child = path39.join(worldsDir, id, "olam");
|
|
26790
|
+
const gitMarker = path39.join(child, ".git");
|
|
26646
26791
|
if (!fs37.existsSync(gitMarker)) continue;
|
|
26647
26792
|
const gitDir = resolveGitDirForWorktree(child);
|
|
26648
26793
|
if (!gitDir) continue;
|
|
@@ -26654,7 +26799,7 @@ function collectWorktrees(worldsDir) {
|
|
|
26654
26799
|
return out;
|
|
26655
26800
|
}
|
|
26656
26801
|
function resolveGitDirForWorktree(worktreePath) {
|
|
26657
|
-
const gitMarker =
|
|
26802
|
+
const gitMarker = path39.join(worktreePath, ".git");
|
|
26658
26803
|
try {
|
|
26659
26804
|
const top = execFileSync9("git", ["rev-parse", "--show-toplevel"], {
|
|
26660
26805
|
cwd: worktreePath,
|
|
@@ -26668,7 +26813,7 @@ function resolveGitDirForWorktree(worktreePath) {
|
|
|
26668
26813
|
stdio: "pipe"
|
|
26669
26814
|
}).trim();
|
|
26670
26815
|
if (!common) return top;
|
|
26671
|
-
return
|
|
26816
|
+
return path39.dirname(path39.resolve(worktreePath, common));
|
|
26672
26817
|
} catch {
|
|
26673
26818
|
return null;
|
|
26674
26819
|
}
|
|
@@ -26735,7 +26880,7 @@ function computeBytes(p) {
|
|
|
26735
26880
|
} catch {
|
|
26736
26881
|
continue;
|
|
26737
26882
|
}
|
|
26738
|
-
for (const name of entries) stack.push(
|
|
26883
|
+
for (const name of entries) stack.push(path39.join(cur, name));
|
|
26739
26884
|
} else {
|
|
26740
26885
|
total += st.size;
|
|
26741
26886
|
}
|
|
@@ -26789,7 +26934,7 @@ init_output();
|
|
|
26789
26934
|
import { execFileSync as execFileSync10 } from "node:child_process";
|
|
26790
26935
|
import * as fs38 from "node:fs";
|
|
26791
26936
|
import * as os20 from "node:os";
|
|
26792
|
-
import * as
|
|
26937
|
+
import * as path40 from "node:path";
|
|
26793
26938
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
26794
26939
|
import pc17 from "picocolors";
|
|
26795
26940
|
var NPM_PACKAGE = "@pleri/olam-cli";
|
|
@@ -26811,7 +26956,7 @@ var realExec = (cmd, args) => {
|
|
|
26811
26956
|
};
|
|
26812
26957
|
function surveyOlam(opts = {}) {
|
|
26813
26958
|
const exec = opts.exec ?? realExec;
|
|
26814
|
-
const home = opts.olamHome ??
|
|
26959
|
+
const home = opts.olamHome ?? path40.join(os20.homedir(), ".olam");
|
|
26815
26960
|
const containers = listDocker(exec, ["ps", "-a", "--format", "{{.Names}}"]).filter(
|
|
26816
26961
|
(n) => n.startsWith("olam-")
|
|
26817
26962
|
);
|
|
@@ -26825,11 +26970,11 @@ function surveyOlam(opts = {}) {
|
|
|
26825
26970
|
(n) => n.startsWith("olam-") && n !== "olam-host-cp-internal-default"
|
|
26826
26971
|
);
|
|
26827
26972
|
const worlds = [];
|
|
26828
|
-
const worldsDir =
|
|
26973
|
+
const worldsDir = path40.join(home, "worlds");
|
|
26829
26974
|
if (fs38.existsSync(worldsDir)) {
|
|
26830
26975
|
for (const entry of fs38.readdirSync(worldsDir, { withFileTypes: true })) {
|
|
26831
26976
|
if (!entry.isDirectory()) continue;
|
|
26832
|
-
const wPath =
|
|
26977
|
+
const wPath = path40.join(worldsDir, entry.name);
|
|
26833
26978
|
const bytes = dirSize(wPath);
|
|
26834
26979
|
const { dirty, note } = inspectWorldGitState(wPath);
|
|
26835
26980
|
worlds.push({ id: entry.name, bytes, dirty, note, path: wPath });
|
|
@@ -26838,7 +26983,7 @@ function surveyOlam(opts = {}) {
|
|
|
26838
26983
|
const homeBytesNonWorld = fs38.existsSync(home) ? Math.max(0, dirSize(home) - worlds.reduce((acc, w) => acc + w.bytes, 0)) : 0;
|
|
26839
26984
|
const npmRoot = exec("npm", ["root", "-g"]);
|
|
26840
26985
|
const npmGlobalRoot = npmRoot.exitCode === 0 ? npmRoot.stdout.trim() : null;
|
|
26841
|
-
const npmInstalled = npmGlobalRoot !== null && fs38.existsSync(
|
|
26986
|
+
const npmInstalled = npmGlobalRoot !== null && fs38.existsSync(path40.join(npmGlobalRoot, NPM_PACKAGE));
|
|
26842
26987
|
return {
|
|
26843
26988
|
containers,
|
|
26844
26989
|
images,
|
|
@@ -26868,7 +27013,7 @@ function dirSize(p) {
|
|
|
26868
27013
|
continue;
|
|
26869
27014
|
}
|
|
26870
27015
|
for (const e of entries) {
|
|
26871
|
-
const full =
|
|
27016
|
+
const full = path40.join(cur, e.name);
|
|
26872
27017
|
try {
|
|
26873
27018
|
if (e.isDirectory()) stack.push(full);
|
|
26874
27019
|
else if (e.isFile()) total += fs38.statSync(full).size;
|
|
@@ -26886,8 +27031,8 @@ function inspectWorldGitState(worldPath) {
|
|
|
26886
27031
|
try {
|
|
26887
27032
|
for (const entry of fs38.readdirSync(worldPath, { withFileTypes: true })) {
|
|
26888
27033
|
if (!entry.isDirectory()) continue;
|
|
26889
|
-
const repo =
|
|
26890
|
-
const gitDir =
|
|
27034
|
+
const repo = path40.join(worldPath, entry.name);
|
|
27035
|
+
const gitDir = path40.join(repo, ".git");
|
|
26891
27036
|
if (!fs38.existsSync(gitDir)) continue;
|
|
26892
27037
|
try {
|
|
26893
27038
|
const status2 = execFileSync10("git", ["status", "--porcelain"], {
|
|
@@ -26981,7 +27126,7 @@ function formatBytes3(n) {
|
|
|
26981
27126
|
}
|
|
26982
27127
|
async function executeImplode(survey, opts) {
|
|
26983
27128
|
const exec = opts.exec ?? realExec;
|
|
26984
|
-
const home = opts.olamHome ??
|
|
27129
|
+
const home = opts.olamHome ?? path40.join(os20.homedir(), ".olam");
|
|
26985
27130
|
const removed = [];
|
|
26986
27131
|
const skipped = [];
|
|
26987
27132
|
const errors = [];
|
|
@@ -27045,7 +27190,7 @@ async function executeImplode(survey, opts) {
|
|
|
27045
27190
|
skipped.push(`fs:~/.olam/auth-data (--keep-vault)`);
|
|
27046
27191
|
continue;
|
|
27047
27192
|
}
|
|
27048
|
-
const target =
|
|
27193
|
+
const target = path40.join(home, entry.name);
|
|
27049
27194
|
try {
|
|
27050
27195
|
fs38.rmSync(target, { recursive: true, force: true });
|
|
27051
27196
|
removed.push(`fs:${target}`);
|
|
@@ -27220,6 +27365,11 @@ function registerEnter(program2) {
|
|
|
27220
27365
|
if (worldMeta) {
|
|
27221
27366
|
const { checkVersionPin: checkVersionPin2 } = await Promise.resolve().then(() => (init_version_pin(), version_pin_exports));
|
|
27222
27367
|
checkVersionPin2(worldId, worldMeta.workspacePath);
|
|
27368
|
+
if (worldMeta.claudeHome) {
|
|
27369
|
+
console.log(
|
|
27370
|
+
pc18.dim(`# claude-home: ${worldMeta.claudeHome} (per-world Claude Code instance, ADR 045)`)
|
|
27371
|
+
);
|
|
27372
|
+
}
|
|
27223
27373
|
}
|
|
27224
27374
|
const computeWorld = await ctx.computeProvider.getWorld(worldId);
|
|
27225
27375
|
if (!computeWorld) {
|
|
@@ -27308,6 +27458,138 @@ ${pc18.dim(`Observe dispatch: docker exec -it ${containerName} tmux attach -t ol
|
|
|
27308
27458
|
});
|
|
27309
27459
|
}
|
|
27310
27460
|
|
|
27461
|
+
// src/commands/resume.ts
|
|
27462
|
+
init_context();
|
|
27463
|
+
init_output();
|
|
27464
|
+
import { execFileSync as execFileSync11 } from "node:child_process";
|
|
27465
|
+
function looksLikePrIdentifier(input2) {
|
|
27466
|
+
if (/^\d+$/.test(input2.trim())) return true;
|
|
27467
|
+
if (/^https?:\/\/[^\s]*\/pull\/\d+(?:[/?#].*)?$/i.test(input2.trim())) return true;
|
|
27468
|
+
return false;
|
|
27469
|
+
}
|
|
27470
|
+
async function runResume(input2, deps) {
|
|
27471
|
+
const trimmed = input2.trim();
|
|
27472
|
+
if (trimmed.length === 0) {
|
|
27473
|
+
deps.stderr("resume: argument <pr> is required (PR number, URL, or branch name).");
|
|
27474
|
+
return 1;
|
|
27475
|
+
}
|
|
27476
|
+
let resolved;
|
|
27477
|
+
try {
|
|
27478
|
+
resolved = await deps.resolveInput(trimmed);
|
|
27479
|
+
} catch (err) {
|
|
27480
|
+
deps.stderr(
|
|
27481
|
+
`resume: could not resolve "${trimmed}" via gh pr view \u2014 ` + (err instanceof Error ? err.message : String(err))
|
|
27482
|
+
);
|
|
27483
|
+
return 1;
|
|
27484
|
+
}
|
|
27485
|
+
const { branch, prNumber } = resolved;
|
|
27486
|
+
const worlds = deps.listWorlds();
|
|
27487
|
+
const matches2 = worlds.filter((w) => w.branch === branch);
|
|
27488
|
+
const prLabel = prNumber !== void 0 ? `PR #${prNumber}` : `branch ${branch}`;
|
|
27489
|
+
if (matches2.length === 0) {
|
|
27490
|
+
deps.stderr(
|
|
27491
|
+
`No active world found for ${prLabel} (branch ${branch}). Worlds visible via olam list.`
|
|
27492
|
+
);
|
|
27493
|
+
return 1;
|
|
27494
|
+
}
|
|
27495
|
+
if (matches2.length > 1) {
|
|
27496
|
+
deps.stderr(
|
|
27497
|
+
`Multiple worlds match ${prLabel} (branch ${branch}); operator decides:`
|
|
27498
|
+
);
|
|
27499
|
+
for (const w of matches2) {
|
|
27500
|
+
deps.stderr(` - ${w.name} (${w.id})`);
|
|
27501
|
+
}
|
|
27502
|
+
return 1;
|
|
27503
|
+
}
|
|
27504
|
+
const match2 = matches2[0];
|
|
27505
|
+
deps.stdout(
|
|
27506
|
+
`Found world ${match2.name} (${match2.id}) for ${prLabel}. Entering...`
|
|
27507
|
+
);
|
|
27508
|
+
try {
|
|
27509
|
+
deps.enterWorld(match2.id);
|
|
27510
|
+
} catch (err) {
|
|
27511
|
+
deps.stderr(
|
|
27512
|
+
`resume: olam enter ${match2.id} failed \u2014 ` + (err instanceof Error ? err.message : String(err))
|
|
27513
|
+
);
|
|
27514
|
+
return 1;
|
|
27515
|
+
}
|
|
27516
|
+
return 0;
|
|
27517
|
+
}
|
|
27518
|
+
function resolveInputViaGh(input2) {
|
|
27519
|
+
if (!looksLikePrIdentifier(input2)) {
|
|
27520
|
+
if (input2.length === 0) {
|
|
27521
|
+
return Promise.reject(new Error("empty branch name"));
|
|
27522
|
+
}
|
|
27523
|
+
return Promise.resolve({ branch: input2 });
|
|
27524
|
+
}
|
|
27525
|
+
let stdout;
|
|
27526
|
+
try {
|
|
27527
|
+
stdout = execFileSync11("gh", ["pr", "view", input2, "--json", "number,headRefName"], {
|
|
27528
|
+
encoding: "utf-8",
|
|
27529
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
27530
|
+
timeout: 1e4
|
|
27531
|
+
});
|
|
27532
|
+
} catch (err) {
|
|
27533
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
27534
|
+
return Promise.reject(new Error(`gh pr view failed: ${msg}`));
|
|
27535
|
+
}
|
|
27536
|
+
let parsed;
|
|
27537
|
+
try {
|
|
27538
|
+
parsed = JSON.parse(stdout);
|
|
27539
|
+
} catch (err) {
|
|
27540
|
+
return Promise.reject(
|
|
27541
|
+
new Error(`gh pr view returned non-JSON output: ${err instanceof Error ? err.message : String(err)}`)
|
|
27542
|
+
);
|
|
27543
|
+
}
|
|
27544
|
+
if (typeof parsed.headRefName !== "string" || parsed.headRefName.length === 0) {
|
|
27545
|
+
return Promise.reject(new Error("gh pr view response missing headRefName"));
|
|
27546
|
+
}
|
|
27547
|
+
const prNumber = typeof parsed.number === "number" ? parsed.number : void 0;
|
|
27548
|
+
return Promise.resolve({ branch: parsed.headRefName, prNumber });
|
|
27549
|
+
}
|
|
27550
|
+
function registerResume(program2) {
|
|
27551
|
+
program2.command("resume").description(
|
|
27552
|
+
"Resume a world by PR number, URL, or branch \u2014 finds the world that opened the PR and enters it."
|
|
27553
|
+
).argument("<pr>", "PR number (876), PR URL, or branch name").addHelpText(
|
|
27554
|
+
"after",
|
|
27555
|
+
`
|
|
27556
|
+
Examples:
|
|
27557
|
+
$ olam resume 876
|
|
27558
|
+
$ olam resume https://github.com/pleri/olam/pull/876
|
|
27559
|
+
$ olam resume night/feat/foo
|
|
27560
|
+
`
|
|
27561
|
+
).action(async (pr) => {
|
|
27562
|
+
const { ctx, error } = await loadContext();
|
|
27563
|
+
if (!ctx) {
|
|
27564
|
+
printError(error?.message ?? "Olam is not configured. Run `olam init` first.");
|
|
27565
|
+
process.exitCode = 1;
|
|
27566
|
+
return;
|
|
27567
|
+
}
|
|
27568
|
+
const code = await runResume(pr, {
|
|
27569
|
+
resolveInput: resolveInputViaGh,
|
|
27570
|
+
listWorlds: () => ctx.worldManager.listWorlds().map((w) => ({
|
|
27571
|
+
id: w.id,
|
|
27572
|
+
name: w.name,
|
|
27573
|
+
branch: w.branch
|
|
27574
|
+
})),
|
|
27575
|
+
enterWorld: (worldId) => {
|
|
27576
|
+
const entry = process.argv[1];
|
|
27577
|
+
if (!entry) {
|
|
27578
|
+
throw new Error("cannot locate CLI entry script (process.argv[1] missing)");
|
|
27579
|
+
}
|
|
27580
|
+
execFileSync11(process.execPath, [entry, "enter", worldId, "--exec"], {
|
|
27581
|
+
stdio: "inherit"
|
|
27582
|
+
});
|
|
27583
|
+
},
|
|
27584
|
+
stdout: (line) => console.log(line),
|
|
27585
|
+
stderr: (line) => printError(line)
|
|
27586
|
+
});
|
|
27587
|
+
if (code !== 0) {
|
|
27588
|
+
process.exitCode = code;
|
|
27589
|
+
}
|
|
27590
|
+
});
|
|
27591
|
+
}
|
|
27592
|
+
|
|
27311
27593
|
// src/commands/crystallize.ts
|
|
27312
27594
|
init_context();
|
|
27313
27595
|
init_output();
|
|
@@ -27573,7 +27855,7 @@ init_host_cp();
|
|
|
27573
27855
|
// src/lib/plans-client.ts
|
|
27574
27856
|
import * as fs40 from "node:fs";
|
|
27575
27857
|
import * as os21 from "node:os";
|
|
27576
|
-
import * as
|
|
27858
|
+
import * as path42 from "node:path";
|
|
27577
27859
|
var PlansClientError = class extends Error {
|
|
27578
27860
|
constructor(status2, message, body) {
|
|
27579
27861
|
super(message);
|
|
@@ -27584,7 +27866,7 @@ var PlansClientError = class extends Error {
|
|
|
27584
27866
|
status;
|
|
27585
27867
|
body;
|
|
27586
27868
|
};
|
|
27587
|
-
var OLAM_HOME4 =
|
|
27869
|
+
var OLAM_HOME4 = path42.join(os21.homedir(), ".olam");
|
|
27588
27870
|
function readFileOrNull(p) {
|
|
27589
27871
|
try {
|
|
27590
27872
|
return fs40.readFileSync(p, "utf8").trim();
|
|
@@ -27593,9 +27875,9 @@ function readFileOrNull(p) {
|
|
|
27593
27875
|
}
|
|
27594
27876
|
}
|
|
27595
27877
|
function resolveCloudConfig() {
|
|
27596
|
-
const cloudUrl = process.env.OLAM_CLOUD_URL ?? readFileOrNull(
|
|
27878
|
+
const cloudUrl = process.env.OLAM_CLOUD_URL ?? readFileOrNull(path42.join(OLAM_HOME4, "cloud-url"));
|
|
27597
27879
|
if (!cloudUrl) return null;
|
|
27598
|
-
const bearer = process.env.OLAM_SHOWCASE_PASSWORD ?? readFileOrNull(
|
|
27880
|
+
const bearer = process.env.OLAM_SHOWCASE_PASSWORD ?? readFileOrNull(path42.join(OLAM_HOME4, "showcase-password"));
|
|
27599
27881
|
if (!bearer) return null;
|
|
27600
27882
|
return { cloudUrl: cloudUrl.replace(/\/+$/, ""), bearer };
|
|
27601
27883
|
}
|
|
@@ -27609,13 +27891,13 @@ var PlansClient = class {
|
|
|
27609
27891
|
const credentials = Buffer.from(`operator:${this.cfg.bearer}`).toString("base64");
|
|
27610
27892
|
return `Basic ${credentials}`;
|
|
27611
27893
|
}
|
|
27612
|
-
async request(
|
|
27894
|
+
async request(path96, init) {
|
|
27613
27895
|
const headers = {
|
|
27614
27896
|
Authorization: this.authHeader()
|
|
27615
27897
|
};
|
|
27616
27898
|
if (init.body) headers["content-type"] = "application/json";
|
|
27617
27899
|
if (init.adminSecret) headers["X-Admin-Secret"] = init.adminSecret;
|
|
27618
|
-
return fetch(`${this.cfg.cloudUrl}${
|
|
27900
|
+
return fetch(`${this.cfg.cloudUrl}${path96}`, {
|
|
27619
27901
|
method: init.method,
|
|
27620
27902
|
headers,
|
|
27621
27903
|
body: init.body ? JSON.stringify(init.body) : void 0
|
|
@@ -28987,11 +29269,11 @@ var qmarksTestNoExtDot = ([$0]) => {
|
|
|
28987
29269
|
return (f) => f.length === len && f !== "." && f !== "..";
|
|
28988
29270
|
};
|
|
28989
29271
|
var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
|
|
28990
|
-
var
|
|
29272
|
+
var path43 = {
|
|
28991
29273
|
win32: { sep: "\\" },
|
|
28992
29274
|
posix: { sep: "/" }
|
|
28993
29275
|
};
|
|
28994
|
-
var sep2 = defaultPlatform === "win32" ?
|
|
29276
|
+
var sep2 = defaultPlatform === "win32" ? path43.win32.sep : path43.posix.sep;
|
|
28995
29277
|
minimatch.sep = sep2;
|
|
28996
29278
|
var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
|
|
28997
29279
|
minimatch.GLOBSTAR = GLOBSTAR;
|
|
@@ -30100,11 +30382,11 @@ function zodIssueToError(issue, doc, lineCounter) {
|
|
|
30100
30382
|
suggestion: deriveSuggestion(issue)
|
|
30101
30383
|
};
|
|
30102
30384
|
}
|
|
30103
|
-
function formatJsonPath(
|
|
30104
|
-
if (
|
|
30385
|
+
function formatJsonPath(path96) {
|
|
30386
|
+
if (path96.length === 0)
|
|
30105
30387
|
return "<root>";
|
|
30106
30388
|
let out = "";
|
|
30107
|
-
for (const seg of
|
|
30389
|
+
for (const seg of path96) {
|
|
30108
30390
|
if (typeof seg === "number") {
|
|
30109
30391
|
out += `[${seg}]`;
|
|
30110
30392
|
} else {
|
|
@@ -30113,11 +30395,11 @@ function formatJsonPath(path95) {
|
|
|
30113
30395
|
}
|
|
30114
30396
|
return out;
|
|
30115
30397
|
}
|
|
30116
|
-
function resolveYamlLocation(
|
|
30398
|
+
function resolveYamlLocation(path96, doc, lineCounter) {
|
|
30117
30399
|
let bestLine = 0;
|
|
30118
30400
|
let bestColumn = 0;
|
|
30119
|
-
for (let depth =
|
|
30120
|
-
const segment =
|
|
30401
|
+
for (let depth = path96.length; depth >= 0; depth -= 1) {
|
|
30402
|
+
const segment = path96.slice(0, depth);
|
|
30121
30403
|
try {
|
|
30122
30404
|
const node = doc.getIn(segment, true);
|
|
30123
30405
|
if (node && typeof node === "object" && "range" in node) {
|
|
@@ -30335,11 +30617,11 @@ function topoSort(nodes) {
|
|
|
30335
30617
|
}
|
|
30336
30618
|
function traceCycle(start, byId) {
|
|
30337
30619
|
const seen = /* @__PURE__ */ new Set();
|
|
30338
|
-
const
|
|
30620
|
+
const path96 = [];
|
|
30339
30621
|
let current = start;
|
|
30340
30622
|
while (current && !seen.has(current)) {
|
|
30341
30623
|
seen.add(current);
|
|
30342
|
-
|
|
30624
|
+
path96.push(current);
|
|
30343
30625
|
const node = byId.get(current);
|
|
30344
30626
|
const next = node?.dependsOn[0];
|
|
30345
30627
|
if (next === void 0)
|
|
@@ -30347,10 +30629,10 @@ function traceCycle(start, byId) {
|
|
|
30347
30629
|
current = next;
|
|
30348
30630
|
}
|
|
30349
30631
|
if (current && seen.has(current)) {
|
|
30350
|
-
const idx =
|
|
30351
|
-
return [...
|
|
30632
|
+
const idx = path96.indexOf(current);
|
|
30633
|
+
return [...path96.slice(idx), current];
|
|
30352
30634
|
}
|
|
30353
|
-
return
|
|
30635
|
+
return path96;
|
|
30354
30636
|
}
|
|
30355
30637
|
|
|
30356
30638
|
// ../core/dist/executor/types.js
|
|
@@ -30574,11 +30856,11 @@ async function resolveDigests(lockfile, resolver) {
|
|
|
30574
30856
|
}
|
|
30575
30857
|
|
|
30576
30858
|
// ../core/dist/worldspec/image-digest.js
|
|
30577
|
-
import { execFileSync as
|
|
30859
|
+
import { execFileSync as execFileSync12 } from "node:child_process";
|
|
30578
30860
|
var DOCKER_SUBPROCESS_TIMEOUT_MS = 3e4;
|
|
30579
30861
|
var dockerDigestResolver = async (image, source) => {
|
|
30580
30862
|
if (source === "local") {
|
|
30581
|
-
const out =
|
|
30863
|
+
const out = execFileSync12("docker", ["inspect", image, "--format", "{{.Id}}"], {
|
|
30582
30864
|
encoding: "utf8",
|
|
30583
30865
|
stdio: ["ignore", "pipe", "pipe"],
|
|
30584
30866
|
timeout: DOCKER_SUBPROCESS_TIMEOUT_MS,
|
|
@@ -30589,7 +30871,7 @@ var dockerDigestResolver = async (image, source) => {
|
|
|
30589
30871
|
}
|
|
30590
30872
|
return out;
|
|
30591
30873
|
}
|
|
30592
|
-
const raw =
|
|
30874
|
+
const raw = execFileSync12("docker", ["buildx", "imagetools", "inspect", image], {
|
|
30593
30875
|
encoding: "utf8",
|
|
30594
30876
|
stdio: ["ignore", "pipe", "pipe"],
|
|
30595
30877
|
timeout: DOCKER_SUBPROCESS_TIMEOUT_MS,
|
|
@@ -32250,7 +32532,7 @@ function registerWorldspec(program2) {
|
|
|
32250
32532
|
init_output();
|
|
32251
32533
|
init_host_cp();
|
|
32252
32534
|
import * as fs43 from "node:fs";
|
|
32253
|
-
import * as
|
|
32535
|
+
import * as path46 from "node:path";
|
|
32254
32536
|
import { spawnSync as spawnSync22 } from "node:child_process";
|
|
32255
32537
|
import ora9 from "ora";
|
|
32256
32538
|
import pc21 from "picocolors";
|
|
@@ -32258,9 +32540,9 @@ import pc21 from "picocolors";
|
|
|
32258
32540
|
// src/commands/upgrade-lock.ts
|
|
32259
32541
|
import * as fs41 from "node:fs";
|
|
32260
32542
|
import * as os22 from "node:os";
|
|
32261
|
-
import * as
|
|
32543
|
+
import * as path44 from "node:path";
|
|
32262
32544
|
import { spawnSync as spawnSync21 } from "node:child_process";
|
|
32263
|
-
var LOCK_FILE_PATH =
|
|
32545
|
+
var LOCK_FILE_PATH = path44.join(os22.homedir(), ".olam", ".upgrade.lock");
|
|
32264
32546
|
var STALE_LOCK_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
32265
32547
|
function readLockFile(lockPath) {
|
|
32266
32548
|
try {
|
|
@@ -32310,7 +32592,7 @@ function isStaleLock(content, nowMs = Date.now()) {
|
|
|
32310
32592
|
return false;
|
|
32311
32593
|
}
|
|
32312
32594
|
function acquireLock(lockPath = LOCK_FILE_PATH, nowMs = Date.now()) {
|
|
32313
|
-
const dir =
|
|
32595
|
+
const dir = path44.dirname(lockPath);
|
|
32314
32596
|
fs41.mkdirSync(dir, { recursive: true });
|
|
32315
32597
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
32316
32598
|
try {
|
|
@@ -32373,15 +32655,15 @@ function formatRefusalMessage(result, lockPath = LOCK_FILE_PATH) {
|
|
|
32373
32655
|
// src/commands/upgrade-log.ts
|
|
32374
32656
|
import * as fs42 from "node:fs";
|
|
32375
32657
|
import * as os23 from "node:os";
|
|
32376
|
-
import * as
|
|
32658
|
+
import * as path45 from "node:path";
|
|
32377
32659
|
function getUpgradeLogPath() {
|
|
32378
32660
|
const home = process.env["HOME"] ?? os23.homedir();
|
|
32379
|
-
return
|
|
32661
|
+
return path45.join(home, ".olam", "upgrade.log");
|
|
32380
32662
|
}
|
|
32381
32663
|
var UPGRADE_LOG_PATH = getUpgradeLogPath();
|
|
32382
32664
|
function appendUpgradeLog(row, logPath = getUpgradeLogPath()) {
|
|
32383
32665
|
try {
|
|
32384
|
-
fs42.mkdirSync(
|
|
32666
|
+
fs42.mkdirSync(path45.dirname(logPath), { recursive: true });
|
|
32385
32667
|
const line = JSON.stringify(row) + "\n";
|
|
32386
32668
|
fs42.appendFileSync(logPath, line, { mode: 420 });
|
|
32387
32669
|
} catch (err) {
|
|
@@ -32488,8 +32770,8 @@ init_protocol_version();
|
|
|
32488
32770
|
init_install_root();
|
|
32489
32771
|
var AUTH_HEALTH_URL2 = "http://127.0.0.1:9999/health";
|
|
32490
32772
|
function isNodeModulesInSync(cwd) {
|
|
32491
|
-
const lockPath =
|
|
32492
|
-
const markerPath =
|
|
32773
|
+
const lockPath = path46.join(cwd, "package-lock.json");
|
|
32774
|
+
const markerPath = path46.join(cwd, "node_modules", ".package-lock.json");
|
|
32493
32775
|
if (!fs43.existsSync(lockPath) || !fs43.existsSync(markerPath)) return false;
|
|
32494
32776
|
try {
|
|
32495
32777
|
const lockStat = fs43.statSync(lockPath);
|
|
@@ -32509,7 +32791,7 @@ function shouldSkipInstall(opts, cwd) {
|
|
|
32509
32791
|
return { skip: false };
|
|
32510
32792
|
}
|
|
32511
32793
|
function validateRepoRoot(cwd) {
|
|
32512
|
-
const marker =
|
|
32794
|
+
const marker = path46.join(cwd, "packages/host-cp/compose.yaml");
|
|
32513
32795
|
if (!fs43.existsSync(marker)) {
|
|
32514
32796
|
return {
|
|
32515
32797
|
ok: false,
|
|
@@ -32870,7 +33152,7 @@ async function recreateAuthService() {
|
|
|
32870
33152
|
}
|
|
32871
33153
|
}
|
|
32872
33154
|
function readBundleHash(cwd) {
|
|
32873
|
-
const indexPath =
|
|
33155
|
+
const indexPath = path46.join(cwd, "packages/control-plane/public/index.html");
|
|
32874
33156
|
if (!fs43.existsSync(indexPath)) return null;
|
|
32875
33157
|
return extractBundleHash(fs43.readFileSync(indexPath, "utf-8"));
|
|
32876
33158
|
}
|
|
@@ -33476,7 +33758,7 @@ ${buildResult.stderr}`);
|
|
|
33476
33758
|
return;
|
|
33477
33759
|
}
|
|
33478
33760
|
const authSecret = readAuthSecret2();
|
|
33479
|
-
const spaDir =
|
|
33761
|
+
const spaDir = path46.join(cwd, "packages/control-plane/app");
|
|
33480
33762
|
const spaResult = runStep2(
|
|
33481
33763
|
"vite build (SPA)",
|
|
33482
33764
|
"npx",
|
|
@@ -34019,13 +34301,13 @@ ${pc23.dim(`world: ${worldId} sort: ${sortKey} refresh: 5s Ctrl-C to exit`)}
|
|
|
34019
34301
|
init_output();
|
|
34020
34302
|
import * as fs44 from "node:fs";
|
|
34021
34303
|
import * as os24 from "node:os";
|
|
34022
|
-
import * as
|
|
34304
|
+
import * as path47 from "node:path";
|
|
34023
34305
|
import YAML6 from "yaml";
|
|
34024
34306
|
function olamHome3() {
|
|
34025
|
-
return process.env.OLAM_HOME ??
|
|
34307
|
+
return process.env.OLAM_HOME ?? path47.join(os24.homedir(), ".olam");
|
|
34026
34308
|
}
|
|
34027
34309
|
function keysFilePath() {
|
|
34028
|
-
return
|
|
34310
|
+
return path47.join(olamHome3(), "keys.yaml");
|
|
34029
34311
|
}
|
|
34030
34312
|
function readKeysFile() {
|
|
34031
34313
|
const filePath = keysFilePath();
|
|
@@ -34121,7 +34403,7 @@ function registerKeys(program2) {
|
|
|
34121
34403
|
init_snapshot();
|
|
34122
34404
|
init_output();
|
|
34123
34405
|
import * as fs45 from "node:fs";
|
|
34124
|
-
import * as
|
|
34406
|
+
import * as path48 from "node:path";
|
|
34125
34407
|
import { execSync as execSync11 } from "node:child_process";
|
|
34126
34408
|
import pc24 from "picocolors";
|
|
34127
34409
|
|
|
@@ -34144,9 +34426,9 @@ function emitDeprecationWarning(subcommand) {
|
|
|
34144
34426
|
}
|
|
34145
34427
|
function bumpDeprecationCounter() {
|
|
34146
34428
|
if (process.env[INTERNAL_SENTINEL_ENV] === "1") return;
|
|
34147
|
-
const counterPath =
|
|
34429
|
+
const counterPath = path48.join(snapshotsDir(), ".deprecation-counter");
|
|
34148
34430
|
try {
|
|
34149
|
-
fs45.mkdirSync(
|
|
34431
|
+
fs45.mkdirSync(path48.dirname(counterPath), { recursive: true });
|
|
34150
34432
|
let current = 0;
|
|
34151
34433
|
if (fs45.existsSync(counterPath)) {
|
|
34152
34434
|
const raw = fs45.readFileSync(counterPath, "utf-8").trim();
|
|
@@ -34229,13 +34511,13 @@ function resolveKinds(arg) {
|
|
|
34229
34511
|
return [];
|
|
34230
34512
|
}
|
|
34231
34513
|
async function captureGems(worldId, workspacePath, repo) {
|
|
34232
|
-
const repoDir =
|
|
34514
|
+
const repoDir = path48.join(workspacePath, repo);
|
|
34233
34515
|
const fingerprint = computeGemsFingerprint(repoDir);
|
|
34234
34516
|
if (!fingerprint) {
|
|
34235
34517
|
return { ok: false, tarPath: "", msg: "no Gemfile.lock \u2014 layer does not apply" };
|
|
34236
34518
|
}
|
|
34237
34519
|
const tarPath = snapshotTarPath(worldId, "gems", repo, fingerprint);
|
|
34238
|
-
const vendorBundle =
|
|
34520
|
+
const vendorBundle = path48.join(repoDir, "vendor", "bundle");
|
|
34239
34521
|
if (fs45.existsSync(vendorBundle)) {
|
|
34240
34522
|
try {
|
|
34241
34523
|
packTarball(vendorBundle, tarPath);
|
|
@@ -34272,7 +34554,7 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
34272
34554
|
`docker exec ${containerName} sh -c 'mkdir -p "$(dirname ${tmpTar})" && tar -czf ${tmpTar}.tmp -C ${bundlePath} . && mv ${tmpTar}.tmp ${tmpTar}'`,
|
|
34273
34555
|
{ stdio: "pipe", timeout: 12e4 }
|
|
34274
34556
|
);
|
|
34275
|
-
fs45.mkdirSync(
|
|
34557
|
+
fs45.mkdirSync(path48.dirname(tarPath), { recursive: true });
|
|
34276
34558
|
execSync11(`docker cp ${containerName}:${tmpTar} "${tarPath}"`, { stdio: "pipe", timeout: 12e4 });
|
|
34277
34559
|
execSync11(`docker exec ${containerName} rm -f ${tmpTar}`, { stdio: "pipe" });
|
|
34278
34560
|
const stat = fs45.statSync(tarPath);
|
|
@@ -34292,12 +34574,12 @@ async function captureGems(worldId, workspacePath, repo) {
|
|
|
34292
34574
|
}
|
|
34293
34575
|
}
|
|
34294
34576
|
async function captureNode(worldId, workspacePath, repo) {
|
|
34295
|
-
const repoDir =
|
|
34577
|
+
const repoDir = path48.join(workspacePath, repo);
|
|
34296
34578
|
const fingerprint = computeNodeFingerprint(repoDir);
|
|
34297
34579
|
if (!fingerprint) {
|
|
34298
34580
|
return { ok: false, tarPath: "", msg: "no lockfile \u2014 layer does not apply" };
|
|
34299
34581
|
}
|
|
34300
|
-
const nodeModules =
|
|
34582
|
+
const nodeModules = path48.join(repoDir, "node_modules");
|
|
34301
34583
|
if (!fs45.existsSync(nodeModules)) {
|
|
34302
34584
|
return { ok: false, tarPath: "", msg: "node_modules not installed yet" };
|
|
34303
34585
|
}
|
|
@@ -34321,7 +34603,7 @@ async function captureNode(worldId, workspacePath, repo) {
|
|
|
34321
34603
|
}
|
|
34322
34604
|
}
|
|
34323
34605
|
async function capturePg(worldId, workspacePath, repoNames) {
|
|
34324
|
-
const repoDirs = repoNames.map((r) =>
|
|
34606
|
+
const repoDirs = repoNames.map((r) => path48.join(workspacePath, r));
|
|
34325
34607
|
const fingerprint = computePgFingerprint(repoDirs);
|
|
34326
34608
|
if (!fingerprint) {
|
|
34327
34609
|
return { ok: false, tarPath: "", msg: "no Gemfile.lock / schema.rb \u2014 layer does not apply" };
|
|
@@ -34336,9 +34618,9 @@ async function capturePg(worldId, workspacePath, repoNames) {
|
|
|
34336
34618
|
}
|
|
34337
34619
|
try {
|
|
34338
34620
|
execSync11(`docker stop ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
34339
|
-
fs45.mkdirSync(
|
|
34621
|
+
fs45.mkdirSync(path48.dirname(tarPath), { recursive: true });
|
|
34340
34622
|
execSync11(
|
|
34341
|
-
`docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${
|
|
34623
|
+
`docker run --rm -v "${volumeName2}:/pgdata:ro" -v "${path48.dirname(tarPath)}:/dest" alpine sh -c 'tar -czf /dest/${path48.basename(tarPath)}.tmp -C /pgdata . && mv /dest/${path48.basename(tarPath)}.tmp /dest/${path48.basename(tarPath)}'`,
|
|
34342
34624
|
{ stdio: "pipe", timeout: 18e4 }
|
|
34343
34625
|
);
|
|
34344
34626
|
execSync11(`docker start ${containerName}`, { stdio: "pipe", timeout: 3e4 });
|
|
@@ -34373,7 +34655,7 @@ async function handleEvict(opts) {
|
|
|
34373
34655
|
const allTars = [];
|
|
34374
34656
|
const walk3 = (d) => {
|
|
34375
34657
|
for (const entry of fs45.readdirSync(d, { withFileTypes: true })) {
|
|
34376
|
-
const full =
|
|
34658
|
+
const full = path48.join(d, entry.name);
|
|
34377
34659
|
if (entry.isDirectory()) {
|
|
34378
34660
|
walk3(full);
|
|
34379
34661
|
} else if (entry.name.endsWith(".tar.gz")) {
|
|
@@ -34472,33 +34754,33 @@ init_context();
|
|
|
34472
34754
|
init_output();
|
|
34473
34755
|
import * as fs47 from "node:fs";
|
|
34474
34756
|
import * as os25 from "node:os";
|
|
34475
|
-
import * as
|
|
34757
|
+
import * as path50 from "node:path";
|
|
34476
34758
|
import { spawnSync as spawnSync24 } from "node:child_process";
|
|
34477
34759
|
import ora10 from "ora";
|
|
34478
34760
|
|
|
34479
34761
|
// src/commands/refresh-helpers.ts
|
|
34480
34762
|
import * as fs46 from "node:fs";
|
|
34481
|
-
import * as
|
|
34763
|
+
import * as path49 from "node:path";
|
|
34482
34764
|
function collectCpSourceFiles(standaloneDir) {
|
|
34483
34765
|
if (!fs46.existsSync(standaloneDir)) {
|
|
34484
34766
|
throw new Error(`CP standalone dir not found: ${standaloneDir}`);
|
|
34485
34767
|
}
|
|
34486
34768
|
const entries = [];
|
|
34487
34769
|
const topLevel = fs46.readdirSync(standaloneDir).filter((f) => {
|
|
34488
|
-
const stat = fs46.statSync(
|
|
34770
|
+
const stat = fs46.statSync(path49.join(standaloneDir, f));
|
|
34489
34771
|
return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
|
|
34490
34772
|
}).sort();
|
|
34491
34773
|
for (const f of topLevel) {
|
|
34492
|
-
entries.push({ srcPath:
|
|
34774
|
+
entries.push({ srcPath: path49.join(standaloneDir, f), destRelPath: f });
|
|
34493
34775
|
}
|
|
34494
|
-
const libDir =
|
|
34776
|
+
const libDir = path49.join(standaloneDir, "lib");
|
|
34495
34777
|
if (fs46.existsSync(libDir) && fs46.statSync(libDir).isDirectory()) {
|
|
34496
34778
|
const libFiles = fs46.readdirSync(libDir).filter((f) => {
|
|
34497
|
-
const stat = fs46.statSync(
|
|
34779
|
+
const stat = fs46.statSync(path49.join(libDir, f));
|
|
34498
34780
|
return stat.isFile() && f.endsWith(".mjs") && !f.endsWith(".test.mjs");
|
|
34499
34781
|
}).sort();
|
|
34500
34782
|
for (const f of libFiles) {
|
|
34501
|
-
entries.push({ srcPath:
|
|
34783
|
+
entries.push({ srcPath: path49.join(libDir, f), destRelPath: `lib/${f}` });
|
|
34502
34784
|
}
|
|
34503
34785
|
}
|
|
34504
34786
|
return entries;
|
|
@@ -34557,15 +34839,15 @@ async function refreshWorld(worldId, portOffset, standaloneDir, opts) {
|
|
|
34557
34839
|
};
|
|
34558
34840
|
}
|
|
34559
34841
|
const stagingDir = fs47.mkdtempSync(
|
|
34560
|
-
|
|
34842
|
+
path50.join(os25.tmpdir(), `olam-refresh-${worldId}-`)
|
|
34561
34843
|
);
|
|
34562
34844
|
try {
|
|
34563
34845
|
const hasLib = entries.some((e) => e.destRelPath.startsWith("lib/"));
|
|
34564
34846
|
if (hasLib) {
|
|
34565
|
-
fs47.mkdirSync(
|
|
34847
|
+
fs47.mkdirSync(path50.join(stagingDir, "lib"), { recursive: true });
|
|
34566
34848
|
}
|
|
34567
34849
|
for (const { srcPath, destRelPath } of entries) {
|
|
34568
|
-
fs47.copyFileSync(srcPath,
|
|
34850
|
+
fs47.copyFileSync(srcPath, path50.join(stagingDir, destRelPath));
|
|
34569
34851
|
}
|
|
34570
34852
|
const cpResult = docker([
|
|
34571
34853
|
"cp",
|
|
@@ -34617,7 +34899,7 @@ function registerRefresh(program2) {
|
|
|
34617
34899
|
process.exitCode = 1;
|
|
34618
34900
|
return;
|
|
34619
34901
|
}
|
|
34620
|
-
const standaloneDir =
|
|
34902
|
+
const standaloneDir = path50.join(
|
|
34621
34903
|
process.cwd(),
|
|
34622
34904
|
"packages/control-plane/standalone"
|
|
34623
34905
|
);
|
|
@@ -34785,8 +35067,8 @@ function registerRestart(program2) {
|
|
|
34785
35067
|
// src/commands/diagnose.ts
|
|
34786
35068
|
import * as fs48 from "node:fs";
|
|
34787
35069
|
import * as os26 from "node:os";
|
|
34788
|
-
import * as
|
|
34789
|
-
import { execFileSync as
|
|
35070
|
+
import * as path51 from "node:path";
|
|
35071
|
+
import { execFileSync as execFileSync13, execSync as execSync12 } from "node:child_process";
|
|
34790
35072
|
import pc25 from "picocolors";
|
|
34791
35073
|
|
|
34792
35074
|
// ../core/dist/diagnose/secret-stripper.js
|
|
@@ -34820,9 +35102,9 @@ function stripSecrets(input2) {
|
|
|
34820
35102
|
}
|
|
34821
35103
|
|
|
34822
35104
|
// src/commands/diagnose.ts
|
|
34823
|
-
var DIAGNOSTICS_DIR =
|
|
34824
|
-
var LOG_DIR =
|
|
34825
|
-
var CACHE_DIR =
|
|
35105
|
+
var DIAGNOSTICS_DIR = path51.join(os26.homedir(), ".olam", "diagnostics");
|
|
35106
|
+
var LOG_DIR = path51.join(os26.homedir(), ".olam", "log");
|
|
35107
|
+
var CACHE_DIR = path51.join(os26.homedir(), ".olam", "cache");
|
|
34826
35108
|
var LOG_TAIL_LINES = 200;
|
|
34827
35109
|
function safeExec(cmd) {
|
|
34828
35110
|
try {
|
|
@@ -34832,12 +35114,12 @@ function safeExec(cmd) {
|
|
|
34832
35114
|
}
|
|
34833
35115
|
}
|
|
34834
35116
|
function defaultZip(zipPath, files) {
|
|
34835
|
-
|
|
35117
|
+
execFileSync13("zip", ["-j", zipPath, ...files]);
|
|
34836
35118
|
}
|
|
34837
35119
|
async function buildDiagnosticsZip(_exec = (cmd) => safeExec(cmd), _outDir = DIAGNOSTICS_DIR, _logDir = LOG_DIR, _zip = defaultZip) {
|
|
34838
35120
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 23);
|
|
34839
|
-
const zipPath =
|
|
34840
|
-
const tmpDir = fs48.mkdtempSync(
|
|
35121
|
+
const zipPath = path51.join(_outDir, `olam-diag-${ts}.zip`);
|
|
35122
|
+
const tmpDir = fs48.mkdtempSync(path51.join(os26.tmpdir(), "olam-diag-"));
|
|
34841
35123
|
try {
|
|
34842
35124
|
fs48.mkdirSync(_outDir, { recursive: true });
|
|
34843
35125
|
const entries = [];
|
|
@@ -34855,7 +35137,7 @@ platform: ${platform2}
|
|
|
34855
35137
|
`uptime: ${os26.uptime()}s`
|
|
34856
35138
|
].join("\n") + "\n";
|
|
34857
35139
|
_writeEntry(tmpDir, "os-info.txt", stripSecrets(osContent), entries);
|
|
34858
|
-
const depsFile =
|
|
35140
|
+
const depsFile = path51.join(CACHE_DIR, "deps.json");
|
|
34859
35141
|
if (fs48.existsSync(depsFile)) {
|
|
34860
35142
|
const deps = fs48.readFileSync(depsFile, "utf-8");
|
|
34861
35143
|
_writeEntry(tmpDir, "deps.json", stripSecrets(deps), entries);
|
|
@@ -34874,7 +35156,7 @@ platform: ${platform2}
|
|
|
34874
35156
|
if (authAudit) {
|
|
34875
35157
|
_writeEntry(tmpDir, "audit-auth-callers.txt", stripSecrets(authAudit), entries);
|
|
34876
35158
|
}
|
|
34877
|
-
const fileArgs = entries.map((e) =>
|
|
35159
|
+
const fileArgs = entries.map((e) => path51.join(tmpDir, e));
|
|
34878
35160
|
try {
|
|
34879
35161
|
_zip(zipPath, fileArgs);
|
|
34880
35162
|
} catch (err) {
|
|
@@ -34892,17 +35174,17 @@ platform: ${platform2}
|
|
|
34892
35174
|
}
|
|
34893
35175
|
}
|
|
34894
35176
|
function _writeEntry(dir, name, content, entries) {
|
|
34895
|
-
fs48.writeFileSync(
|
|
35177
|
+
fs48.writeFileSync(path51.join(dir, name), content, { mode: 420 });
|
|
34896
35178
|
entries.push(name);
|
|
34897
35179
|
}
|
|
34898
35180
|
function _latestLog(logDir) {
|
|
34899
35181
|
if (!fs48.existsSync(logDir)) return null;
|
|
34900
35182
|
const files = fs48.readdirSync(logDir).filter((f) => f.startsWith("host-")).sort().reverse();
|
|
34901
|
-
return files.length > 0 ?
|
|
35183
|
+
return files.length > 0 ? path51.join(logDir, files[0]) : null;
|
|
34902
35184
|
}
|
|
34903
35185
|
async function buildTelemetryPayload() {
|
|
34904
35186
|
const channel = "stable";
|
|
34905
|
-
const manifestFile =
|
|
35187
|
+
const manifestFile = path51.join(CACHE_DIR, "manifest.json");
|
|
34906
35188
|
let manifestAgeHours = null;
|
|
34907
35189
|
if (fs48.existsSync(manifestFile)) {
|
|
34908
35190
|
const mtime = fs48.statSync(manifestFile).mtime.getTime();
|
|
@@ -35057,8 +35339,8 @@ function checkWorld(container, hostShas, dockerExec) {
|
|
|
35057
35339
|
const m = shaLine.match(/^([a-f0-9]{64})\s+(.+)$/);
|
|
35058
35340
|
if (!m) continue;
|
|
35059
35341
|
const sha = m[1];
|
|
35060
|
-
const
|
|
35061
|
-
const filename =
|
|
35342
|
+
const path96 = m[2];
|
|
35343
|
+
const filename = path96?.split("/").pop();
|
|
35062
35344
|
if (!filename) continue;
|
|
35063
35345
|
const mtimeSecs = parseInt(mtimeLine.trim(), 10);
|
|
35064
35346
|
if (Number.isNaN(mtimeSecs) || !sha) continue;
|
|
@@ -35106,28 +35388,28 @@ function resolveRepoRootBestEffort() {
|
|
|
35106
35388
|
init_output();
|
|
35107
35389
|
import * as fs50 from "node:fs";
|
|
35108
35390
|
import * as net4 from "node:net";
|
|
35109
|
-
import * as
|
|
35391
|
+
import * as path53 from "node:path";
|
|
35110
35392
|
import * as os27 from "node:os";
|
|
35111
35393
|
|
|
35112
35394
|
// src/commands/hermes-kg-hook.ts
|
|
35113
35395
|
import * as fs49 from "node:fs";
|
|
35114
|
-
import * as
|
|
35396
|
+
import * as path52 from "node:path";
|
|
35115
35397
|
import { createHash as createHash5 } from "node:crypto";
|
|
35116
35398
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
35117
35399
|
var HERMES_KG_HOOK_SENTINEL = "OLAM_KG_HOOK";
|
|
35118
35400
|
function bundleDir() {
|
|
35119
35401
|
const thisFile = fileURLToPath6(import.meta.url);
|
|
35120
|
-
return
|
|
35402
|
+
return path52.resolve(path52.dirname(thisFile), "..", "..", "hermes-bundle");
|
|
35121
35403
|
}
|
|
35122
35404
|
function templateContent() {
|
|
35123
|
-
const templatePath =
|
|
35405
|
+
const templatePath = path52.join(bundleDir(), "kg-first.sh");
|
|
35124
35406
|
return fs49.readFileSync(templatePath);
|
|
35125
35407
|
}
|
|
35126
35408
|
function sha256(buf) {
|
|
35127
35409
|
return createHash5("sha256").update(buf).digest("hex");
|
|
35128
35410
|
}
|
|
35129
35411
|
function installKgFirstHookForHermes(hooksDir, dryRun) {
|
|
35130
|
-
const destPath2 =
|
|
35412
|
+
const destPath2 = path52.join(hooksDir, "kg-first.sh");
|
|
35131
35413
|
const template = templateContent();
|
|
35132
35414
|
if (fs49.existsSync(destPath2)) {
|
|
35133
35415
|
const existing = fs49.readFileSync(destPath2);
|
|
@@ -35203,7 +35485,7 @@ async function runDoctor(opts, deps = {}) {
|
|
|
35203
35485
|
if (isK8s) {
|
|
35204
35486
|
const wrapImpl = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
35205
35487
|
const k8sCtx = deps.kubectlContext;
|
|
35206
|
-
const manifestsDir = deps.manifestsDir ??
|
|
35488
|
+
const manifestsDir = deps.manifestsDir ?? path53.join(OLAM_HOME, "k8s", "manifests");
|
|
35207
35489
|
const readFileSyncImpl = deps.readFileSyncImpl ?? fs50.readFileSync;
|
|
35208
35490
|
const sortedPeripherals = [...PERIPHERALS].sort((a, b) => a.name.localeCompare(b.name));
|
|
35209
35491
|
let peripheralPosition = 14;
|
|
@@ -35340,7 +35622,7 @@ async function probeStorageClassMatch(peripherals, kubectlContext, manifestsDir,
|
|
|
35340
35622
|
const ctxArgs = kubectlContext ? ["--context", kubectlContext] : [];
|
|
35341
35623
|
const mismatches = [];
|
|
35342
35624
|
for (const peripheral of peripherals) {
|
|
35343
|
-
const pvcManifestPath =
|
|
35625
|
+
const pvcManifestPath = path53.join(manifestsDir, peripheral.name, "45-pvc.yaml");
|
|
35344
35626
|
let declaredClass;
|
|
35345
35627
|
try {
|
|
35346
35628
|
const raw = readFileSyncImpl(pvcManifestPath, "utf8");
|
|
@@ -35453,7 +35735,7 @@ function probeNodeMemory(dockerExec, kubectlContext) {
|
|
|
35453
35735
|
function defaultResolveHostSideProxyComposePath() {
|
|
35454
35736
|
const root = resolveK8sAssetsRoot();
|
|
35455
35737
|
if (root === null) return null;
|
|
35456
|
-
const candidate =
|
|
35738
|
+
const candidate = path53.join(root, "host-side", "docker-socket-proxy.compose.yaml");
|
|
35457
35739
|
return fs50.existsSync(candidate) ? candidate : null;
|
|
35458
35740
|
}
|
|
35459
35741
|
async function defaultDockerSocketCheck(composePath) {
|
|
@@ -35590,8 +35872,8 @@ function renderHuman(report) {
|
|
|
35590
35872
|
}
|
|
35591
35873
|
}
|
|
35592
35874
|
function probeHermesIntegration(hermesDir) {
|
|
35593
|
-
const configPath =
|
|
35594
|
-
const hookPath =
|
|
35875
|
+
const configPath = path53.join(hermesDir, "config.yaml");
|
|
35876
|
+
const hookPath = path53.join(hermesDir, "hooks", "kg-first.sh");
|
|
35595
35877
|
const issues = [];
|
|
35596
35878
|
if (!fs50.existsSync(configPath)) {
|
|
35597
35879
|
issues.push("~/.hermes/config.yaml not found");
|
|
@@ -35632,7 +35914,7 @@ function registerDoctor(program2) {
|
|
|
35632
35914
|
program2.command("doctor").description(
|
|
35633
35915
|
"Pass/fail host-health check. Exits 0 on a healthy host (including WARN-only); 1 on any FAIL probe. Auto-detects substrate from ~/.olam/config.yaml (host.substrate) \u2014 runs 28 probes on kubernetes, 7 on docker/compose. Override with OLAM_HOST_CP_ENGINE env var."
|
|
35634
35916
|
).option("--json", "emit the report as JSON instead of a human-readable table").action(async (opts) => {
|
|
35635
|
-
const hermesDir =
|
|
35917
|
+
const hermesDir = path53.join(os27.homedir(), ".hermes");
|
|
35636
35918
|
const r = await runDoctor(opts, {
|
|
35637
35919
|
// Pass hermesHomeOverride so the probe fires when ~/.hermes/ exists.
|
|
35638
35920
|
// When the dir is absent the probe is skipped; when present it WARNs
|
|
@@ -35907,7 +36189,7 @@ function registerSubstrate(program2) {
|
|
|
35907
36189
|
|
|
35908
36190
|
// ../cli-plugin-tasks/dist/client.js
|
|
35909
36191
|
import { readFileSync as readFileSync46 } from "node:fs";
|
|
35910
|
-
import { homedir as
|
|
36192
|
+
import { homedir as homedir31 } from "node:os";
|
|
35911
36193
|
import { join as join61 } from "node:path";
|
|
35912
36194
|
var TasksClient = class {
|
|
35913
36195
|
baseUrl;
|
|
@@ -35916,7 +36198,7 @@ var TasksClient = class {
|
|
|
35916
36198
|
sessionId;
|
|
35917
36199
|
constructor(opts) {
|
|
35918
36200
|
this.baseUrl = (opts.hostCpUrl ?? process.env.OLAM_HOST_CP_URL ?? "http://localhost:19000").replace(/\/$/, "");
|
|
35919
|
-
const tokenPath2 = opts.tokenPath ?? join61(
|
|
36201
|
+
const tokenPath2 = opts.tokenPath ?? join61(homedir31(), ".olam", "host-cp.token");
|
|
35920
36202
|
try {
|
|
35921
36203
|
this.token = readFileSync46(tokenPath2, "utf8").trim();
|
|
35922
36204
|
} catch (e) {
|
|
@@ -35925,9 +36207,9 @@ var TasksClient = class {
|
|
|
35925
36207
|
this.olamNodeId = opts.olamNodeId;
|
|
35926
36208
|
this.sessionId = opts.sessionId;
|
|
35927
36209
|
}
|
|
35928
|
-
async call(method,
|
|
36210
|
+
async call(method, path96, scopes, body, query) {
|
|
35929
36211
|
const qs = query ? "?" + new URLSearchParams(Object.entries(query).filter(([, v]) => v !== void 0)).toString() : "";
|
|
35930
|
-
const url2 = `${this.baseUrl}${
|
|
36212
|
+
const url2 = `${this.baseUrl}${path96}${qs}`;
|
|
35931
36213
|
const res = await fetch(url2, {
|
|
35932
36214
|
method,
|
|
35933
36215
|
headers: {
|
|
@@ -35978,8 +36260,8 @@ function parseFrontmatter2(raw) {
|
|
|
35978
36260
|
}
|
|
35979
36261
|
return { frontmatter: fm, body };
|
|
35980
36262
|
}
|
|
35981
|
-
function parseTracker(
|
|
35982
|
-
const raw = readFileSync47(
|
|
36263
|
+
function parseTracker(path96) {
|
|
36264
|
+
const raw = readFileSync47(path96, "utf8");
|
|
35983
36265
|
const { frontmatter, body } = parseFrontmatter2(raw);
|
|
35984
36266
|
const lines = body.split("\n");
|
|
35985
36267
|
const tasks = [];
|
|
@@ -36216,8 +36498,8 @@ function registerTasks(program2) {
|
|
|
36216
36498
|
`);
|
|
36217
36499
|
}
|
|
36218
36500
|
});
|
|
36219
|
-
tasks.command("sync-tracker <path>").description("Parse /10x:commit-plan tracker.md + upsert each task via POST /api/tasks (B2.4; dual-emit pattern, olam-side per cross-ownership decoupling)").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--dry-run", "Parse + print task records; do not POST").option("--json", "Output raw JSON envelope").action(async (
|
|
36220
|
-
const parsed = parseTracker(
|
|
36501
|
+
tasks.command("sync-tracker <path>").description("Parse /10x:commit-plan tracker.md + upsert each task via POST /api/tasks (B2.4; dual-emit pattern, olam-side per cross-ownership decoupling)").option("--node-id <uuid>", "Olam node ID").option("--session-id <uuid>", "Session ID").option("--dry-run", "Parse + print task records; do not POST").option("--json", "Output raw JSON envelope").action(async (path96, opts) => {
|
|
36502
|
+
const parsed = parseTracker(path96);
|
|
36221
36503
|
if (opts.dryRun) {
|
|
36222
36504
|
process.stdout.write(JSON.stringify(parsed, null, 2) + "\n");
|
|
36223
36505
|
return;
|
|
@@ -36371,15 +36653,76 @@ function registerCompletion(program2) {
|
|
|
36371
36653
|
// src/commands/setup.ts
|
|
36372
36654
|
init_cli_version();
|
|
36373
36655
|
init_health_probes();
|
|
36374
|
-
import { spawn as spawn7, spawnSync as
|
|
36656
|
+
import { spawn as spawn7, spawnSync as spawnSync27 } from "node:child_process";
|
|
36375
36657
|
import { existsSync as existsSync85, readFileSync as readFileSync70 } from "node:fs";
|
|
36376
|
-
import { homedir as
|
|
36377
|
-
import
|
|
36658
|
+
import { homedir as homedir45 } from "node:os";
|
|
36659
|
+
import path77 from "node:path";
|
|
36378
36660
|
import { createInterface as createInterface3 } from "node:readline";
|
|
36379
36661
|
|
|
36662
|
+
// src/lib/k8s-context-discovery.ts
|
|
36663
|
+
import { spawnSync as spawnSync26 } from "node:child_process";
|
|
36664
|
+
var OLAM_MANAGED_CONTEXT_PREFIX = "k3d-olam-";
|
|
36665
|
+
function isOlamManagedContext(name) {
|
|
36666
|
+
return name.startsWith(OLAM_MANAGED_CONTEXT_PREFIX);
|
|
36667
|
+
}
|
|
36668
|
+
function defaultGetContexts() {
|
|
36669
|
+
const r = spawnSync26(
|
|
36670
|
+
"kubectl",
|
|
36671
|
+
["config", "get-contexts", "-o", "name"],
|
|
36672
|
+
{ encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }
|
|
36673
|
+
);
|
|
36674
|
+
if (r.status !== 0 || !r.stdout) return [];
|
|
36675
|
+
return r.stdout.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
36676
|
+
}
|
|
36677
|
+
function defaultClusterInfo(context) {
|
|
36678
|
+
const r = spawnSync26(
|
|
36679
|
+
"kubectl",
|
|
36680
|
+
["--context", context, "cluster-info", "--request-timeout=3s"],
|
|
36681
|
+
{ encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }
|
|
36682
|
+
);
|
|
36683
|
+
if (r.status === 0) {
|
|
36684
|
+
const match2 = r.stdout.match(/running at (https?:\/\/\S+)/i);
|
|
36685
|
+
return { reachable: true, serverUrl: match2?.[1] };
|
|
36686
|
+
}
|
|
36687
|
+
const err = (r.stderr || "").trim().slice(0, 200);
|
|
36688
|
+
return { reachable: false, error: err || "cluster-info failed" };
|
|
36689
|
+
}
|
|
36690
|
+
function defaultIsIdle(context) {
|
|
36691
|
+
const nsResult = spawnSync26(
|
|
36692
|
+
"kubectl",
|
|
36693
|
+
["--context", context, "get", "namespace", "olam", "--ignore-not-found", "-o", "name"],
|
|
36694
|
+
{ encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }
|
|
36695
|
+
);
|
|
36696
|
+
const nsLine = (nsResult.stdout || "").trim();
|
|
36697
|
+
if (!nsLine) {
|
|
36698
|
+
return true;
|
|
36699
|
+
}
|
|
36700
|
+
const podsResult = spawnSync26(
|
|
36701
|
+
"kubectl",
|
|
36702
|
+
["--context", context, "get", "pods", "-n", "olam", "--no-headers"],
|
|
36703
|
+
{ encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] }
|
|
36704
|
+
);
|
|
36705
|
+
const podsOut = (podsResult.stdout || "").trim();
|
|
36706
|
+
return !podsOut || /no resources found/i.test(podsOut);
|
|
36707
|
+
}
|
|
36708
|
+
function discoverOfferableContexts(deps = {}) {
|
|
36709
|
+
const getContextsFn = deps.getContexts ?? defaultGetContexts;
|
|
36710
|
+
const clusterInfoFn = deps.clusterInfo ?? defaultClusterInfo;
|
|
36711
|
+
const isIdleFn = deps.isIdle ?? defaultIsIdle;
|
|
36712
|
+
const allContexts = getContextsFn();
|
|
36713
|
+
const offerable = [];
|
|
36714
|
+
for (const ctx of allContexts) {
|
|
36715
|
+
if (isOlamManagedContext(ctx)) continue;
|
|
36716
|
+
const probe2 = clusterInfoFn(ctx);
|
|
36717
|
+
if (!probe2.reachable) continue;
|
|
36718
|
+
if (isIdleFn(ctx)) offerable.push(ctx);
|
|
36719
|
+
}
|
|
36720
|
+
return { offerable, allContexts };
|
|
36721
|
+
}
|
|
36722
|
+
|
|
36380
36723
|
// src/lib/shell-rc.ts
|
|
36381
36724
|
import { copyFileSync as copyFileSync5, existsSync as existsSync60, readFileSync as readFileSync48, renameSync as renameSync8, writeFileSync as writeFileSync29 } from "node:fs";
|
|
36382
|
-
import
|
|
36725
|
+
import path54 from "node:path";
|
|
36383
36726
|
function appendIdempotent(opts) {
|
|
36384
36727
|
const { rcPath, marker, contentLine, clock = () => /* @__PURE__ */ new Date() } = opts;
|
|
36385
36728
|
if (!existsSync60(rcPath)) {
|
|
@@ -36402,9 +36745,9 @@ function appendIdempotent(opts) {
|
|
|
36402
36745
|
}
|
|
36403
36746
|
function resolveShellRc(home, shellEnv) {
|
|
36404
36747
|
if (!shellEnv) return null;
|
|
36405
|
-
const basename16 =
|
|
36406
|
-
if (basename16 === "zsh") return
|
|
36407
|
-
if (basename16 === "bash") return
|
|
36748
|
+
const basename16 = path54.basename(shellEnv);
|
|
36749
|
+
if (basename16 === "zsh") return path54.join(home, ".zshrc");
|
|
36750
|
+
if (basename16 === "bash") return path54.join(home, ".bashrc");
|
|
36408
36751
|
return null;
|
|
36409
36752
|
}
|
|
36410
36753
|
|
|
@@ -36563,8 +36906,8 @@ async function pickSkillSourcePhase(opts, deps) {
|
|
|
36563
36906
|
}
|
|
36564
36907
|
|
|
36565
36908
|
// src/commands/setup-phase-5b-project-sweep.ts
|
|
36566
|
-
import { homedir as
|
|
36567
|
-
import * as
|
|
36909
|
+
import { homedir as homedir44 } from "node:os";
|
|
36910
|
+
import * as path76 from "node:path";
|
|
36568
36911
|
import * as fs75 from "node:fs";
|
|
36569
36912
|
async function loadWalkFn() {
|
|
36570
36913
|
const m = await Promise.resolve().then(() => (init_project_sweep(), project_sweep_exports));
|
|
@@ -36583,9 +36926,9 @@ async function loadAppendTrustAuditFn() {
|
|
|
36583
36926
|
return m.appendTrustAudit;
|
|
36584
36927
|
}
|
|
36585
36928
|
function deriveRepoName(repoPath, existingNames) {
|
|
36586
|
-
const base =
|
|
36929
|
+
const base = path76.basename(repoPath).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
36587
36930
|
if (!existingNames.has(base)) return base;
|
|
36588
|
-
const parent =
|
|
36931
|
+
const parent = path76.basename(path76.dirname(repoPath)).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
36589
36932
|
const composite = `${parent}-${base}`;
|
|
36590
36933
|
if (!existingNames.has(composite)) return composite;
|
|
36591
36934
|
let suffix = 2;
|
|
@@ -36596,8 +36939,8 @@ async function runProjectSweepPhase(opts, deps, sweepDeps = {}) {
|
|
|
36596
36939
|
if (opts.skipProjectSweep) {
|
|
36597
36940
|
return { ok: true, skipped: true, message: "skipped via --skip-project-sweep" };
|
|
36598
36941
|
}
|
|
36599
|
-
const home = deps.home ??
|
|
36600
|
-
const projectsRoot = opts.projects ??
|
|
36942
|
+
const home = deps.home ?? homedir44();
|
|
36943
|
+
const projectsRoot = opts.projects ?? path76.join(home, "Projects");
|
|
36601
36944
|
const existsSyncFn = sweepDeps.existsSync ?? fs75.existsSync;
|
|
36602
36945
|
if (!existsSyncFn(projectsRoot)) {
|
|
36603
36946
|
return {
|
|
@@ -36771,6 +37114,67 @@ function resolveSubstrate(opts, deps) {
|
|
|
36771
37114
|
}
|
|
36772
37115
|
return "kubernetes";
|
|
36773
37116
|
}
|
|
37117
|
+
async function phase0_5DetectExistingContext(substrate, opts, deps) {
|
|
37118
|
+
if (substrate !== "kubernetes") {
|
|
37119
|
+
return { ok: true, skipped: true, message: "no-op for docker substrate" };
|
|
37120
|
+
}
|
|
37121
|
+
if (opts.reuseCluster) {
|
|
37122
|
+
const name = opts.reuseCluster;
|
|
37123
|
+
const clusterInfoFn = deps.kubectlClusterInfo ?? defaultClusterInfo;
|
|
37124
|
+
const probe2 = clusterInfoFn(name);
|
|
37125
|
+
if (!probe2.reachable) {
|
|
37126
|
+
return {
|
|
37127
|
+
ok: false,
|
|
37128
|
+
message: `--reuse-cluster=${name} but context is not reachable: ${probe2.error ?? "unknown error"}`,
|
|
37129
|
+
remedy: `Verify the context exists (\`kubectl config get-contexts\`) and is reachable (\`kubectl --context=${name} cluster-info\`), then re-run \`olam setup --reuse-cluster=${name}\`.`,
|
|
37130
|
+
reuseContext: void 0
|
|
37131
|
+
};
|
|
37132
|
+
}
|
|
37133
|
+
return {
|
|
37134
|
+
ok: true,
|
|
37135
|
+
message: `will reuse context ${name}${probe2.serverUrl ? ` (${probe2.serverUrl})` : ""}`,
|
|
37136
|
+
reuseContext: name
|
|
37137
|
+
};
|
|
37138
|
+
}
|
|
37139
|
+
const { offerable } = discoverOfferableContexts(deps.kubeContextDeps);
|
|
37140
|
+
if (offerable.length === 0) {
|
|
37141
|
+
return {
|
|
37142
|
+
ok: true,
|
|
37143
|
+
skipped: true,
|
|
37144
|
+
message: "no idle reachable contexts detected; will provision k3d cluster"
|
|
37145
|
+
};
|
|
37146
|
+
}
|
|
37147
|
+
if (opts.yes) {
|
|
37148
|
+
process.stdout.write(
|
|
37149
|
+
` Detected ${offerable.length} existing Kubernetes context(s): ${offerable.join(", ")}. To reuse one, pass --reuse-cluster=<name>. Provisioning k3d (--yes default).
|
|
37150
|
+
`
|
|
37151
|
+
);
|
|
37152
|
+
return {
|
|
37153
|
+
ok: true,
|
|
37154
|
+
skipped: true,
|
|
37155
|
+
message: `idle context(s) available but --yes defaults to k3d provision; use --reuse-cluster=<name> to opt in`
|
|
37156
|
+
};
|
|
37157
|
+
}
|
|
37158
|
+
const promptFn = deps.prompt ?? defaultPrompt;
|
|
37159
|
+
for (const ctx of offerable) {
|
|
37160
|
+
const reuse = await promptFn(
|
|
37161
|
+
`Detected existing Kubernetes context \`${ctx}\`. Use this cluster instead of provisioning a new k3d cluster?`,
|
|
37162
|
+
false
|
|
37163
|
+
);
|
|
37164
|
+
if (reuse) {
|
|
37165
|
+
return {
|
|
37166
|
+
ok: true,
|
|
37167
|
+
message: `operator chose to reuse context ${ctx}`,
|
|
37168
|
+
reuseContext: ctx
|
|
37169
|
+
};
|
|
37170
|
+
}
|
|
37171
|
+
}
|
|
37172
|
+
return {
|
|
37173
|
+
ok: true,
|
|
37174
|
+
skipped: true,
|
|
37175
|
+
message: "operator declined reuse; will provision k3d cluster"
|
|
37176
|
+
};
|
|
37177
|
+
}
|
|
36774
37178
|
async function phase1SystemCheck(substrate, deps) {
|
|
36775
37179
|
const nodeVersion = deps.nodeVersion ?? process.version;
|
|
36776
37180
|
const nodeMajor = parseNodeMajor(nodeVersion);
|
|
@@ -36795,6 +37199,13 @@ async function phase1SystemCheck(substrate, deps) {
|
|
|
36795
37199
|
remedy: `Install Node.js ${REQUIRED_NODE_MAJOR}+ LTS via nvm/fnm/asdf and re-run \`olam setup\`.`
|
|
36796
37200
|
};
|
|
36797
37201
|
}
|
|
37202
|
+
const platform2 = String(deps.osPlatform ?? process.platform);
|
|
37203
|
+
const home = deps.home ?? homedir45();
|
|
37204
|
+
const colimaLint = probeColimaKubernetesEnabled({ platform: platform2, home });
|
|
37205
|
+
if (colimaLint.ok && "warn" in colimaLint && colimaLint.warn === true) {
|
|
37206
|
+
const lintWithWarn = colimaLint;
|
|
37207
|
+
printWarning(` \u26A0 ${lintWithWarn.remedy}`);
|
|
37208
|
+
}
|
|
36798
37209
|
return { ok: true, message: `kubectl on PATH; docker ready; node ${nodeVersion}` };
|
|
36799
37210
|
}
|
|
36800
37211
|
const dockerProbe = await probeDockerDaemon(deps.dockerExec);
|
|
@@ -36817,17 +37228,24 @@ async function phase1SystemCheck(substrate, deps) {
|
|
|
36817
37228
|
message: `${dockerProbe.message}; ${composeProbe.message}; node ${nodeVersion}`
|
|
36818
37229
|
};
|
|
36819
37230
|
}
|
|
36820
|
-
async function phase1_5InstallSubstrate(substrate, opts, deps) {
|
|
37231
|
+
async function phase1_5InstallSubstrate(substrate, opts, deps, reuseContext) {
|
|
36821
37232
|
if (substrate === "docker") {
|
|
36822
37233
|
return { ok: true, skipped: true, message: "no-op for docker substrate" };
|
|
36823
37234
|
}
|
|
37235
|
+
if (reuseContext) {
|
|
37236
|
+
return {
|
|
37237
|
+
ok: true,
|
|
37238
|
+
skipped: true,
|
|
37239
|
+
message: `skipped k3d install (reusing context ${reuseContext})`
|
|
37240
|
+
};
|
|
37241
|
+
}
|
|
36824
37242
|
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
36825
37243
|
const promptFn = deps.prompt ?? defaultPrompt;
|
|
36826
37244
|
const k3dProbe = await probeK3d(deps.dockerExec);
|
|
36827
37245
|
if (k3dProbe.ok) {
|
|
36828
37246
|
return { ok: true, message: `k3d already present: ${k3dProbe.message}` };
|
|
36829
37247
|
}
|
|
36830
|
-
const hasBrew =
|
|
37248
|
+
const hasBrew = spawnSync27("command", ["-v", "brew"], { shell: true, stdio: "pipe" }).status === 0;
|
|
36831
37249
|
const useBrewMsg = hasBrew ? "Homebrew" : "upstream install script";
|
|
36832
37250
|
if (!opts.yes) {
|
|
36833
37251
|
const confirmed = await promptFn(
|
|
@@ -36886,10 +37304,17 @@ function phaseFromProbe(probe2) {
|
|
|
36886
37304
|
if (probe2.ok) return { ok: true, message: probe2.message };
|
|
36887
37305
|
return { ok: false, message: probe2.message, remedy: probe2.remedy };
|
|
36888
37306
|
}
|
|
36889
|
-
async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps) {
|
|
37307
|
+
async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reuseContext) {
|
|
36890
37308
|
if (substrate === "docker") {
|
|
36891
37309
|
return { ok: true, skipped: true, message: "no-op for docker substrate" };
|
|
36892
37310
|
}
|
|
37311
|
+
if (reuseContext) {
|
|
37312
|
+
return {
|
|
37313
|
+
ok: true,
|
|
37314
|
+
skipped: true,
|
|
37315
|
+
message: `skipped k3d cluster provision (reusing context ${reuseContext})`
|
|
37316
|
+
};
|
|
37317
|
+
}
|
|
36893
37318
|
const spawnFn = deps.spawnSubprocess ?? defaultSpawn;
|
|
36894
37319
|
const listResult = await captureSpawn("k3d", ["cluster", "list", "--output", "json"], deps.dockerExec);
|
|
36895
37320
|
if (listResult.ok) {
|
|
@@ -36903,7 +37328,7 @@ async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps) {
|
|
|
36903
37328
|
}
|
|
36904
37329
|
process.stdout.write(`Creating k3d cluster ${clusterName}...
|
|
36905
37330
|
`);
|
|
36906
|
-
const ghConfigBind = `${
|
|
37331
|
+
const ghConfigBind = `${homedir45()}/.config/gh:/host/.config/gh`;
|
|
36907
37332
|
const createResult = await spawnFn("k3d", [
|
|
36908
37333
|
"cluster",
|
|
36909
37334
|
"create",
|
|
@@ -36927,14 +37352,14 @@ async function phase2_5ProvisionCluster(substrate, clusterName, opts, deps) {
|
|
|
36927
37352
|
}
|
|
36928
37353
|
async function captureSpawn(cmd, args, dockerExec) {
|
|
36929
37354
|
const exec = dockerExec ?? ((c, a) => {
|
|
36930
|
-
const r2 =
|
|
37355
|
+
const r2 = spawnSync27(c, [...a], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
36931
37356
|
return { status: r2.status, stdout: r2.stdout ?? "", stderr: r2.stderr ?? "" };
|
|
36932
37357
|
});
|
|
36933
37358
|
const r = exec(cmd, args);
|
|
36934
37359
|
return { ok: r.status === 0, stdout: r.stdout, stderr: r.stderr };
|
|
36935
37360
|
}
|
|
36936
37361
|
function captureSpawnSync(cmd, args) {
|
|
36937
|
-
const r =
|
|
37362
|
+
const r = spawnSync27(cmd, [...args], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
36938
37363
|
return { ok: r.status === 0, stdout: r.stdout ?? "" };
|
|
36939
37364
|
}
|
|
36940
37365
|
function clusterExistsInList(json, clusterName) {
|
|
@@ -36963,11 +37388,11 @@ function safeReadCliVersion() {
|
|
|
36963
37388
|
return null;
|
|
36964
37389
|
}
|
|
36965
37390
|
}
|
|
36966
|
-
async function phase2_6PinKubectlContext(substrate, clusterName, deps) {
|
|
37391
|
+
async function phase2_6PinKubectlContext(substrate, clusterName, deps, reuseContext) {
|
|
36967
37392
|
if (substrate !== "kubernetes") {
|
|
36968
37393
|
return { ok: true, skipped: true, message: "no-op for docker substrate" };
|
|
36969
37394
|
}
|
|
36970
|
-
const expectedContext = `k3d-${clusterName}`;
|
|
37395
|
+
const expectedContext = reuseContext ?? `k3d-${clusterName}`;
|
|
36971
37396
|
writeConfig({ host: { substrate: "kubernetes" } }, { configPath: deps.configPath });
|
|
36972
37397
|
const result = applyKubectlContextPin([expectedContext], {
|
|
36973
37398
|
configPath: deps.configPath
|
|
@@ -37004,7 +37429,7 @@ async function phase4ShellInit(opts, deps) {
|
|
|
37004
37429
|
if (opts.skipShellInit) {
|
|
37005
37430
|
return { ok: true, skipped: true, message: "skipped via --skip-shell-init" };
|
|
37006
37431
|
}
|
|
37007
|
-
const home = deps.home ??
|
|
37432
|
+
const home = deps.home ?? homedir45();
|
|
37008
37433
|
const shellEnv = deps.shellEnv ?? process.env.SHELL;
|
|
37009
37434
|
const rcPath = resolveShellRc(home, shellEnv);
|
|
37010
37435
|
if (rcPath === null) {
|
|
@@ -37014,7 +37439,7 @@ async function phase4ShellInit(opts, deps) {
|
|
|
37014
37439
|
message: `unsupported $SHELL (${shellEnv ?? "unset"}); add \`eval "$(olam completion <shell>)"\` to your shell rc manually`
|
|
37015
37440
|
};
|
|
37016
37441
|
}
|
|
37017
|
-
const shellBasename =
|
|
37442
|
+
const shellBasename = path77.basename(shellEnv);
|
|
37018
37443
|
const evalLine = `eval "$(olam completion ${shellBasename})"`;
|
|
37019
37444
|
const result = appendIdempotent({
|
|
37020
37445
|
rcPath,
|
|
@@ -37040,7 +37465,7 @@ async function phase4ShellInit(opts, deps) {
|
|
|
37040
37465
|
async function phase5InitProject(opts, deps) {
|
|
37041
37466
|
const cwd = deps.cwd ?? process.cwd();
|
|
37042
37467
|
const projectRoot = findProjectRoot(cwd);
|
|
37043
|
-
const configPath =
|
|
37468
|
+
const configPath = path77.join(projectRoot, ".olam", "config.yaml");
|
|
37044
37469
|
if (existsSync85(configPath)) {
|
|
37045
37470
|
return { ok: true, message: `${configPath} present (no change)` };
|
|
37046
37471
|
}
|
|
@@ -37119,7 +37544,8 @@ async function phase7Verify(opts, deps) {
|
|
|
37119
37544
|
remedy: "Inspect doctor output above; the specific failing probe names its remedy."
|
|
37120
37545
|
};
|
|
37121
37546
|
}
|
|
37122
|
-
var
|
|
37547
|
+
var PHASE_TITLES = [
|
|
37548
|
+
"Phase 0.5: Detect existing k8s context",
|
|
37123
37549
|
"Phase 1: System check",
|
|
37124
37550
|
"Phase 1.5: Substrate tools install",
|
|
37125
37551
|
"Phase 2: olam CLI sanity",
|
|
@@ -37157,12 +37583,32 @@ async function runSetup(opts, deps = {}) {
|
|
|
37157
37583
|
process.stdout.write(`cluster: ${clusterName}
|
|
37158
37584
|
`);
|
|
37159
37585
|
}
|
|
37586
|
+
const results = [];
|
|
37587
|
+
let failureAt = null;
|
|
37588
|
+
const phase0_5Title = PHASE_TITLES[0];
|
|
37589
|
+
process.stdout.write(`
|
|
37590
|
+
${phase0_5Title}
|
|
37591
|
+
`);
|
|
37592
|
+
const phase0_5Result = await phase0_5DetectExistingContext(substrate, opts, deps);
|
|
37593
|
+
results.push({ name: phase0_5Title, result: phase0_5Result });
|
|
37594
|
+
if (phase0_5Result.ok && phase0_5Result.skipped) {
|
|
37595
|
+
printWarning(` \u2298 ${phase0_5Result.message}`);
|
|
37596
|
+
} else if (phase0_5Result.ok) {
|
|
37597
|
+
printSuccess(` \u2713 ${phase0_5Result.message}`);
|
|
37598
|
+
} else {
|
|
37599
|
+
printError(` \u2717 ${phase0_5Result.message}`);
|
|
37600
|
+
if (phase0_5Result.remedy) printWarning(` remedy: ${phase0_5Result.remedy}`);
|
|
37601
|
+
process.stdout.write("\n");
|
|
37602
|
+
printError("Setup FAILED at Phase 1");
|
|
37603
|
+
return { phases: results, failureAt: 1, exitCode: 1 };
|
|
37604
|
+
}
|
|
37605
|
+
const reuseContext = phase0_5Result.reuseContext;
|
|
37160
37606
|
const phaseFns = [
|
|
37161
37607
|
() => phase1SystemCheck(substrate, deps),
|
|
37162
|
-
() => phase1_5InstallSubstrate(substrate, opts, deps),
|
|
37608
|
+
() => phase1_5InstallSubstrate(substrate, opts, deps, reuseContext),
|
|
37163
37609
|
() => phase2CliSanity(deps),
|
|
37164
|
-
() => phase2_5ProvisionCluster(substrate, clusterName, opts, deps),
|
|
37165
|
-
() => phase2_6PinKubectlContext(substrate, clusterName, deps),
|
|
37610
|
+
() => phase2_5ProvisionCluster(substrate, clusterName, opts, deps, reuseContext),
|
|
37611
|
+
() => phase2_6PinKubectlContext(substrate, clusterName, deps, reuseContext),
|
|
37166
37612
|
() => phase3Bootstrap(substrate, deps),
|
|
37167
37613
|
() => phase4ShellInit(opts, deps),
|
|
37168
37614
|
() => phase5InitProject(opts, deps),
|
|
@@ -37171,10 +37617,8 @@ async function runSetup(opts, deps = {}) {
|
|
|
37171
37617
|
() => phase6Auth(opts, deps),
|
|
37172
37618
|
() => phase7Verify(opts, deps)
|
|
37173
37619
|
];
|
|
37174
|
-
const results = [];
|
|
37175
|
-
let failureAt = null;
|
|
37176
37620
|
for (let i = 0; i < phaseFns.length; i += 1) {
|
|
37177
|
-
const name =
|
|
37621
|
+
const name = PHASE_TITLES[i + 1];
|
|
37178
37622
|
process.stdout.write(`
|
|
37179
37623
|
${name}
|
|
37180
37624
|
`);
|
|
@@ -37187,7 +37631,7 @@ ${name}
|
|
|
37187
37631
|
} else {
|
|
37188
37632
|
printError(` \u2717 ${result.message}`);
|
|
37189
37633
|
if (result.remedy) printWarning(` remedy: ${result.remedy}`);
|
|
37190
|
-
failureAt = i +
|
|
37634
|
+
failureAt = i + 2;
|
|
37191
37635
|
break;
|
|
37192
37636
|
}
|
|
37193
37637
|
}
|
|
@@ -37214,6 +37658,9 @@ function registerSetup(program2) {
|
|
|
37214
37658
|
).option(
|
|
37215
37659
|
"--cluster-name <name>",
|
|
37216
37660
|
"k3d cluster name to create/use (kubernetes substrate only; default: olam-dev). Use a different name to avoid colliding with a pre-existing olam-dev cluster, to run multiple olam stacks side-by-side, or for per-run unique names in CI smoke. Must be DNS-compatible: lowercase alphanumeric, hyphens allowed in the middle."
|
|
37661
|
+
).option(
|
|
37662
|
+
"--reuse-cluster <name>",
|
|
37663
|
+
"Reuse an existing kubeconfig context instead of provisioning a new k3d cluster. Pair with --substrate=kubernetes. Skips Phase 1.5 (k3d install) and Phase 2.5 (cluster provision); Phase 2.6 pins to this context. Operator owns the cluster lifecycle (teardown not handled by olam setup). Example: --reuse-cluster=colima (for Colima k8s users)."
|
|
37217
37664
|
).option("--skip-shell-init", "Skip Phase 4 (do not append to ~/.zshrc / ~/.bashrc)").option("--skip-auth", "Skip Phase 6 (do not prompt for `olam auth login`)").option("--skip-skill-source", "Skip Phase 5a (do not pick a skill source; run `olam skills source add` later)").option("--skill-source <id-or-url>", "Non-interactive Phase 5a: curated name (e.g. atlas-toolbox) or git URL").option("--skip-project-sweep", "Skip Phase 5b (do not walk projects directory for repo discovery)").option("--projects <path>", "Phase 5b: project root path to walk (default: ~/Projects)").option("--dry-run", "Phase 5b: print matches without registering or building (no side effects)").option("--exclude <glob...>", "Phase 5b: additional skip patterns for project sweep").option("--skip-kg", "Phase 5b: skip KG eager-build sub-step (sources still registered)").option(
|
|
37218
37665
|
"--skip-doctor",
|
|
37219
37666
|
"Skip Phase 7 final `olam doctor` verification (for CI or minimal setups)"
|
|
@@ -37412,13 +37859,13 @@ function registerSetupLinuxGate(program2) {
|
|
|
37412
37859
|
// src/commands/update.ts
|
|
37413
37860
|
import * as fs78 from "node:fs";
|
|
37414
37861
|
import * as os42 from "node:os";
|
|
37415
|
-
import * as
|
|
37862
|
+
import * as path80 from "node:path";
|
|
37416
37863
|
import { execSync as execSync14 } from "node:child_process";
|
|
37417
37864
|
import pc28 from "picocolors";
|
|
37418
37865
|
|
|
37419
37866
|
// src/lib/symlink-reconcile.ts
|
|
37420
37867
|
import * as fs76 from "node:fs";
|
|
37421
|
-
import * as
|
|
37868
|
+
import * as path78 from "node:path";
|
|
37422
37869
|
var realFs = {
|
|
37423
37870
|
readdirSync: (p) => fs76.readdirSync(p),
|
|
37424
37871
|
existsSync: (p) => fs76.existsSync(p),
|
|
@@ -37437,8 +37884,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
|
37437
37884
|
_fs.mkdirSync(claudeSkillsDir2, { recursive: true });
|
|
37438
37885
|
const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
37439
37886
|
for (const skill of sourceSkills) {
|
|
37440
|
-
const linkPath =
|
|
37441
|
-
const target =
|
|
37887
|
+
const linkPath = path78.join(claudeSkillsDir2, skill);
|
|
37888
|
+
const target = path78.join(npmSkillsDir, skill);
|
|
37442
37889
|
if (!_fs.existsSync(linkPath)) {
|
|
37443
37890
|
try {
|
|
37444
37891
|
_fs.symlinkSync(target, linkPath);
|
|
@@ -37451,7 +37898,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
|
37451
37898
|
}
|
|
37452
37899
|
const deployedEntries = _fs.existsSync(claudeSkillsDir2) ? _fs.readdirSync(claudeSkillsDir2).filter((d) => d.startsWith("olam-")) : [];
|
|
37453
37900
|
for (const entry of deployedEntries) {
|
|
37454
|
-
const linkPath =
|
|
37901
|
+
const linkPath = path78.join(claudeSkillsDir2, entry);
|
|
37455
37902
|
let isSymlink = false;
|
|
37456
37903
|
try {
|
|
37457
37904
|
isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
|
|
@@ -37476,9 +37923,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
|
37476
37923
|
|
|
37477
37924
|
// src/commands/update.ts
|
|
37478
37925
|
var PACKAGE_NAME = "@pleri/olam-cli";
|
|
37479
|
-
var CACHE_DIR2 =
|
|
37480
|
-
var LOG_DIR2 =
|
|
37481
|
-
var LAST_STABLE_FILE =
|
|
37926
|
+
var CACHE_DIR2 = path80.join(os42.homedir(), ".olam", "cache");
|
|
37927
|
+
var LOG_DIR2 = path80.join(os42.homedir(), ".olam", "log");
|
|
37928
|
+
var LAST_STABLE_FILE = path80.join(CACHE_DIR2, "last-stable.txt");
|
|
37482
37929
|
function defaultExec(cmd) {
|
|
37483
37930
|
try {
|
|
37484
37931
|
const stdout = execSync14(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -37507,12 +37954,12 @@ function readLastStable(file = LAST_STABLE_FILE) {
|
|
|
37507
37954
|
}
|
|
37508
37955
|
}
|
|
37509
37956
|
function writeLastStable(version, file = LAST_STABLE_FILE) {
|
|
37510
|
-
fs78.mkdirSync(
|
|
37957
|
+
fs78.mkdirSync(path80.dirname(file), { recursive: true });
|
|
37511
37958
|
fs78.writeFileSync(file, version, { mode: 420 });
|
|
37512
37959
|
}
|
|
37513
37960
|
function logUpdateFailure(stderr) {
|
|
37514
37961
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
37515
|
-
const logFile =
|
|
37962
|
+
const logFile = path80.join(LOG_DIR2, `update-${ts}.log`);
|
|
37516
37963
|
try {
|
|
37517
37964
|
fs78.mkdirSync(LOG_DIR2, { recursive: true });
|
|
37518
37965
|
fs78.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
@@ -37602,8 +38049,8 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
|
|
|
37602
38049
|
let symlinkResult = { added: [], removed: [] };
|
|
37603
38050
|
if (npmRootResult.exitCode === 0) {
|
|
37604
38051
|
const npmRoot = npmRootResult.stdout.trim();
|
|
37605
|
-
const npmSkillsDir =
|
|
37606
|
-
const claudeSkillsDir2 =
|
|
38052
|
+
const npmSkillsDir = path80.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
|
|
38053
|
+
const claudeSkillsDir2 = path80.join(os42.homedir(), ".claude", "skills");
|
|
37607
38054
|
const rec = _reconcile(npmSkillsDir, claudeSkillsDir2);
|
|
37608
38055
|
symlinkResult = { added: rec.added, removed: rec.removed };
|
|
37609
38056
|
if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
|
|
@@ -37649,8 +38096,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
|
|
|
37649
38096
|
if (npmRootResult.exitCode === 0) {
|
|
37650
38097
|
const npmRoot = npmRootResult.stdout.trim();
|
|
37651
38098
|
_reconcile(
|
|
37652
|
-
|
|
37653
|
-
|
|
38099
|
+
path80.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
|
|
38100
|
+
path80.join(os42.homedir(), ".claude", "skills")
|
|
37654
38101
|
);
|
|
37655
38102
|
}
|
|
37656
38103
|
return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
|
|
@@ -38007,7 +38454,7 @@ import pc32 from "picocolors";
|
|
|
38007
38454
|
|
|
38008
38455
|
// src/commands/flywheel/install-shims.ts
|
|
38009
38456
|
import { copyFileSync as copyFileSync9, existsSync as existsSync89, mkdirSync as mkdirSync53, readFileSync as readFileSync74, writeFileSync as writeFileSync44 } from "node:fs";
|
|
38010
|
-
import { homedir as
|
|
38457
|
+
import { homedir as homedir48 } from "node:os";
|
|
38011
38458
|
import { dirname as dirname48, join as join87 } from "node:path";
|
|
38012
38459
|
|
|
38013
38460
|
// src/lib/shim-generator.ts
|
|
@@ -38071,7 +38518,7 @@ ${argsBlock}
|
|
|
38071
38518
|
// src/commands/flywheel/install-shims.ts
|
|
38072
38519
|
var SHIM_HEADER_MARKER = "# AUTO-GENERATED by `olam flywheel install-shims`";
|
|
38073
38520
|
function refreshShims(opts = {}) {
|
|
38074
|
-
const targetDir = opts.targetDir ?? join87(
|
|
38521
|
+
const targetDir = opts.targetDir ?? join87(homedir48(), ".claude", "scripts");
|
|
38075
38522
|
const results = [];
|
|
38076
38523
|
let written = 0;
|
|
38077
38524
|
let overwritten = 0;
|
|
@@ -38132,7 +38579,7 @@ function installOne(spec, targetDir, opts) {
|
|
|
38132
38579
|
}
|
|
38133
38580
|
function registerFlywheelInstallShims(parent) {
|
|
38134
38581
|
parent.command("install-shims").description("Install backwards-compat bash shims under ~/.claude/scripts/ that delegate to olam flywheel <subcmd>").option("--force", "overwrite existing non-shim files (backs them up to .shim-backup-<ts>)").option("--dry-run", "preview which shims would be written without modifying disk").option("--target-dir <path>", "override target directory (default: ~/.claude/scripts/); for tests").action((opts) => {
|
|
38135
|
-
const targetDir = opts.targetDir ?? join87(
|
|
38582
|
+
const targetDir = opts.targetDir ?? join87(homedir48(), ".claude", "scripts");
|
|
38136
38583
|
const summary2 = refreshShims(opts);
|
|
38137
38584
|
const lines = [];
|
|
38138
38585
|
const dryRunSuffix = opts.dryRun === true ? " (dry-run)" : "";
|
|
@@ -38757,7 +39204,7 @@ init_skill_sources();
|
|
|
38757
39204
|
init_output();
|
|
38758
39205
|
import * as fs80 from "node:fs";
|
|
38759
39206
|
import * as os43 from "node:os";
|
|
38760
|
-
import * as
|
|
39207
|
+
import * as path81 from "node:path";
|
|
38761
39208
|
import * as readline3 from "node:readline";
|
|
38762
39209
|
import pc33 from "picocolors";
|
|
38763
39210
|
|
|
@@ -38776,7 +39223,7 @@ import {
|
|
|
38776
39223
|
statSync as statSync27,
|
|
38777
39224
|
writeFileSync as writeFileSync45
|
|
38778
39225
|
} from "node:fs";
|
|
38779
|
-
import { homedir as
|
|
39226
|
+
import { homedir as homedir49 } from "node:os";
|
|
38780
39227
|
import { basename as basename8, dirname as dirname49, isAbsolute as isAbsolute4, join as join88, relative as relative5, resolve as resolve21 } from "node:path";
|
|
38781
39228
|
|
|
38782
39229
|
// src/commands/flywheel/sanitize-persona-output.ts
|
|
@@ -38839,7 +39286,7 @@ function registerFlywheelSanitizePersonaOutput(parent) {
|
|
|
38839
39286
|
|
|
38840
39287
|
// src/lib/skills-apply-overlays.ts
|
|
38841
39288
|
function claudeRoot(opts) {
|
|
38842
|
-
return opts.claudeDir ?? opts.fixtureRoot ?? join88(
|
|
39289
|
+
return opts.claudeDir ?? opts.fixtureRoot ?? join88(homedir49(), ".claude");
|
|
38843
39290
|
}
|
|
38844
39291
|
function ensureRealDir(p) {
|
|
38845
39292
|
if (!existsSync90(p)) {
|
|
@@ -39036,12 +39483,12 @@ function asMessage4(err) {
|
|
|
39036
39483
|
}
|
|
39037
39484
|
var ATLAS_USER_PICKER_RE = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
39038
39485
|
function listMemberNames(clonePath) {
|
|
39039
|
-
const membersDir =
|
|
39486
|
+
const membersDir = path81.join(clonePath, "members");
|
|
39040
39487
|
if (!fs80.existsSync(membersDir)) return [];
|
|
39041
39488
|
try {
|
|
39042
39489
|
return fs80.readdirSync(membersDir).filter((e) => {
|
|
39043
39490
|
try {
|
|
39044
|
-
return fs80.statSync(
|
|
39491
|
+
return fs80.statSync(path81.join(membersDir, e)).isDirectory();
|
|
39045
39492
|
} catch {
|
|
39046
39493
|
return false;
|
|
39047
39494
|
}
|
|
@@ -39090,8 +39537,8 @@ function defaultAtlasUserPrompt(question) {
|
|
|
39090
39537
|
async function resolveAtlasUserWithPicker(cliOverride, opts) {
|
|
39091
39538
|
if (cliOverride !== void 0) return cliOverride;
|
|
39092
39539
|
const ATLAS_USER_RE2 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
39093
|
-
const claudeDirPathForRead = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ??
|
|
39094
|
-
const atlasUserFile =
|
|
39540
|
+
const claudeDirPathForRead = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path81.join(os43.homedir(), ".claude"));
|
|
39541
|
+
const atlasUserFile = path81.join(claudeDirPathForRead, ".atlas-user");
|
|
39095
39542
|
if (fs80.existsSync(atlasUserFile)) {
|
|
39096
39543
|
const existing = fs80.readFileSync(atlasUserFile, "utf-8").trim();
|
|
39097
39544
|
if (existing.length > 0) {
|
|
@@ -39152,10 +39599,10 @@ async function resolveAtlasUserWithPicker(cliOverride, opts) {
|
|
|
39152
39599
|
);
|
|
39153
39600
|
return void 0;
|
|
39154
39601
|
}
|
|
39155
|
-
const claudeDirPath = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ??
|
|
39602
|
+
const claudeDirPath = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path81.join(os43.homedir(), ".claude"));
|
|
39156
39603
|
fs80.mkdirSync(claudeDirPath, { recursive: true });
|
|
39157
|
-
fs80.writeFileSync(
|
|
39158
|
-
process.stdout.write(pc33.green(`\u2713 atlas-user set to "${picked}" (written to ${
|
|
39604
|
+
fs80.writeFileSync(path81.join(claudeDirPath, ".atlas-user"), picked + "\n", "utf8");
|
|
39605
|
+
process.stdout.write(pc33.green(`\u2713 atlas-user set to "${picked}" (written to ${path81.join(claudeDirPath, ".atlas-user")})
|
|
39159
39606
|
`));
|
|
39160
39607
|
return picked;
|
|
39161
39608
|
}
|
|
@@ -39167,10 +39614,10 @@ function listDeployed() {
|
|
|
39167
39614
|
);
|
|
39168
39615
|
const entries = [];
|
|
39169
39616
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
39170
|
-
const bucketDir =
|
|
39617
|
+
const bucketDir = path81.join(dir, bucket);
|
|
39171
39618
|
if (!fs80.existsSync(bucketDir)) continue;
|
|
39172
39619
|
for (const name of fs80.readdirSync(bucketDir)) {
|
|
39173
|
-
const full =
|
|
39620
|
+
const full = path81.join(bucketDir, name);
|
|
39174
39621
|
try {
|
|
39175
39622
|
const stat = fs80.lstatSync(full);
|
|
39176
39623
|
if (!stat.isSymbolicLink()) continue;
|
|
@@ -39621,7 +40068,7 @@ init_merge_settings();
|
|
|
39621
40068
|
init_skill_sources();
|
|
39622
40069
|
init_output();
|
|
39623
40070
|
import * as fs82 from "node:fs";
|
|
39624
|
-
import * as
|
|
40071
|
+
import * as path82 from "node:path";
|
|
39625
40072
|
var MIGRATE_FROM_TOOLBOX_COMMAND = "migrate-from-toolbox";
|
|
39626
40073
|
function asMessage6(err) {
|
|
39627
40074
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -39689,7 +40136,7 @@ function registerSkillsMigrate(program2) {
|
|
|
39689
40136
|
return;
|
|
39690
40137
|
}
|
|
39691
40138
|
const toolboxPath = opts.path;
|
|
39692
|
-
const namespace = opts.namespace ??
|
|
40139
|
+
const namespace = opts.namespace ?? path82.basename(toolboxPath);
|
|
39693
40140
|
const sourceName = opts.sourceName ?? namespace;
|
|
39694
40141
|
const snapshot = detectToolboxState({ toolboxPath, namespace });
|
|
39695
40142
|
if (!snapshot) {
|
|
@@ -39743,9 +40190,9 @@ function registerSkillsMigrate(program2) {
|
|
|
39743
40190
|
printWarning(`legacy hook removal failed: ${asMessage6(err)}; proceeding`);
|
|
39744
40191
|
}
|
|
39745
40192
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
39746
|
-
const olamHookPath = scope === "user" ? settingsFile :
|
|
40193
|
+
const olamHookPath = scope === "user" ? settingsFile : path82.join(process.cwd(), ".claude", "settings.json");
|
|
39747
40194
|
try {
|
|
39748
|
-
fs82.mkdirSync(
|
|
40195
|
+
fs82.mkdirSync(path82.dirname(olamHookPath), { recursive: true });
|
|
39749
40196
|
const result = mergeHomeSettingsJson(olamHookPath, {
|
|
39750
40197
|
ensureHook: {
|
|
39751
40198
|
stage: OLAM_SKILLS_HOOK_STAGE,
|
|
@@ -39779,7 +40226,7 @@ function registerSkillsMigrate(program2) {
|
|
|
39779
40226
|
init_skill_sources();
|
|
39780
40227
|
init_output();
|
|
39781
40228
|
import * as fs83 from "node:fs";
|
|
39782
|
-
import * as
|
|
40229
|
+
import * as path83 from "node:path";
|
|
39783
40230
|
var MIGRATE_BACK_TO_TOOLBOX_COMMAND = "migrate-back-to-toolbox";
|
|
39784
40231
|
function asMessage7(err) {
|
|
39785
40232
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -39787,7 +40234,7 @@ function asMessage7(err) {
|
|
|
39787
40234
|
function claudeDirInternal4() {
|
|
39788
40235
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
39789
40236
|
if (override && override.length > 0) return override;
|
|
39790
|
-
return
|
|
40237
|
+
return path83.join(process.env["HOME"] ?? "", ".claude");
|
|
39791
40238
|
}
|
|
39792
40239
|
function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
|
|
39793
40240
|
if (!originalSessionStartHook || originalSessionStartHook.length === 0) {
|
|
@@ -39812,7 +40259,7 @@ function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
|
|
|
39812
40259
|
SessionStart: originalSessionStartHook
|
|
39813
40260
|
}
|
|
39814
40261
|
};
|
|
39815
|
-
fs83.mkdirSync(
|
|
40262
|
+
fs83.mkdirSync(path83.dirname(filePath), { recursive: true });
|
|
39816
40263
|
fs83.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
39817
40264
|
return { restored: true };
|
|
39818
40265
|
}
|
|
@@ -39822,10 +40269,10 @@ function removeOlamManagedSymlinks() {
|
|
|
39822
40269
|
const olamClonePaths = sources.map((s) => skillSourceClonePath(s.id));
|
|
39823
40270
|
let removed = 0;
|
|
39824
40271
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
39825
|
-
const dir =
|
|
40272
|
+
const dir = path83.join(claude, bucket);
|
|
39826
40273
|
if (!fs83.existsSync(dir)) continue;
|
|
39827
40274
|
for (const name of fs83.readdirSync(dir)) {
|
|
39828
|
-
const linkPath =
|
|
40275
|
+
const linkPath = path83.join(dir, name);
|
|
39829
40276
|
try {
|
|
39830
40277
|
const stat = fs83.lstatSync(linkPath);
|
|
39831
40278
|
if (!stat.isSymbolicLink()) continue;
|
|
@@ -39844,7 +40291,7 @@ function restoreToolboxSymlinks(symlinks) {
|
|
|
39844
40291
|
let restored = 0;
|
|
39845
40292
|
for (const { link, target } of symlinks) {
|
|
39846
40293
|
try {
|
|
39847
|
-
fs83.mkdirSync(
|
|
40294
|
+
fs83.mkdirSync(path83.dirname(link), { recursive: true });
|
|
39848
40295
|
if (fs83.existsSync(link) || (() => {
|
|
39849
40296
|
try {
|
|
39850
40297
|
fs83.lstatSync(link);
|
|
@@ -39864,8 +40311,8 @@ function restoreToolboxSymlinks(symlinks) {
|
|
|
39864
40311
|
}
|
|
39865
40312
|
function restoreAtlasUserMarker(atlasUser) {
|
|
39866
40313
|
if (!atlasUser) return false;
|
|
39867
|
-
const file =
|
|
39868
|
-
fs83.mkdirSync(
|
|
40314
|
+
const file = path83.join(claudeDirInternal4(), ".atlas-user");
|
|
40315
|
+
fs83.mkdirSync(path83.dirname(file), { recursive: true });
|
|
39869
40316
|
fs83.writeFileSync(file, atlasUser);
|
|
39870
40317
|
return true;
|
|
39871
40318
|
}
|
|
@@ -39879,7 +40326,7 @@ function registerSkillsMigrateBack(program2) {
|
|
|
39879
40326
|
let snapshot;
|
|
39880
40327
|
try {
|
|
39881
40328
|
if (opts.snapshot) {
|
|
39882
|
-
snapshotPath =
|
|
40329
|
+
snapshotPath = path83.resolve(opts.snapshot);
|
|
39883
40330
|
if (!fs83.existsSync(snapshotPath)) {
|
|
39884
40331
|
printError(`snapshot not found at ${snapshotPath}`);
|
|
39885
40332
|
process.exitCode = 1;
|
|
@@ -39887,7 +40334,7 @@ function registerSkillsMigrateBack(program2) {
|
|
|
39887
40334
|
}
|
|
39888
40335
|
snapshot = readMigrationSnapshotFromPath(snapshotPath);
|
|
39889
40336
|
} else {
|
|
39890
|
-
const filterNamespace = opts.namespace ?? (opts.path ?
|
|
40337
|
+
const filterNamespace = opts.namespace ?? (opts.path ? path83.basename(opts.path) : void 0);
|
|
39891
40338
|
const latest = readLatestMigrationSnapshot({ namespace: filterNamespace });
|
|
39892
40339
|
if (!latest) {
|
|
39893
40340
|
const where = filterNamespace ? ` for namespace "${filterNamespace}"` : "";
|
|
@@ -39965,7 +40412,7 @@ init_trust_audit_log();
|
|
|
39965
40412
|
init_atlas_hook_strip();
|
|
39966
40413
|
init_output();
|
|
39967
40414
|
import * as fs84 from "node:fs";
|
|
39968
|
-
import * as
|
|
40415
|
+
import * as path84 from "node:path";
|
|
39969
40416
|
import pc35 from "picocolors";
|
|
39970
40417
|
var MIGRATE_HOOKS_COMMAND = "migrate-hooks";
|
|
39971
40418
|
function settingsHasOlamMetaSentinel(settings) {
|
|
@@ -39992,7 +40439,7 @@ function readSettings2(filePath) {
|
|
|
39992
40439
|
return JSON.parse(raw);
|
|
39993
40440
|
}
|
|
39994
40441
|
function writeSettings(filePath, settings) {
|
|
39995
|
-
fs84.mkdirSync(
|
|
40442
|
+
fs84.mkdirSync(path84.dirname(filePath), { recursive: true });
|
|
39996
40443
|
const tmp = `${filePath}.tmp-migrate-hooks-${process.pid}-${Date.now()}`;
|
|
39997
40444
|
fs84.writeFileSync(tmp, JSON.stringify(settings, null, 2) + "\n");
|
|
39998
40445
|
fs84.renameSync(tmp, filePath);
|
|
@@ -40075,7 +40522,7 @@ function registerSkillsMigrateHooks(program2) {
|
|
|
40075
40522
|
init_meta_hooks_migration_snapshot();
|
|
40076
40523
|
init_skill_sources();
|
|
40077
40524
|
init_output();
|
|
40078
|
-
import * as
|
|
40525
|
+
import * as path85 from "node:path";
|
|
40079
40526
|
function asMessage9(err) {
|
|
40080
40527
|
return err instanceof Error ? err.message : String(err);
|
|
40081
40528
|
}
|
|
@@ -40092,16 +40539,16 @@ function registerSkillsMigrateHooksBack(program2) {
|
|
|
40092
40539
|
return;
|
|
40093
40540
|
}
|
|
40094
40541
|
if (opts.snapshot) {
|
|
40095
|
-
const resolved =
|
|
40096
|
-
const allowedDir =
|
|
40097
|
-
if (!resolved.startsWith(allowedDir +
|
|
40542
|
+
const resolved = path85.resolve(opts.snapshot);
|
|
40543
|
+
const allowedDir = path85.resolve(migrationSnapshotsDir2());
|
|
40544
|
+
if (!resolved.startsWith(allowedDir + path85.sep)) {
|
|
40098
40545
|
printError(
|
|
40099
40546
|
`--snapshot path must be inside ${allowedDir} (got "${resolved}"). Refusing to restore from an arbitrary path \u2014 settings.json would land operator-chosen content.`
|
|
40100
40547
|
);
|
|
40101
40548
|
process.exitCode = 1;
|
|
40102
40549
|
return;
|
|
40103
40550
|
}
|
|
40104
|
-
const basename16 =
|
|
40551
|
+
const basename16 = path85.basename(resolved);
|
|
40105
40552
|
if (!basename16.startsWith(META_HOOKS_SNAPSHOT_PREFIX)) {
|
|
40106
40553
|
printError(
|
|
40107
40554
|
`--snapshot filename must start with "${META_HOOKS_SNAPSHOT_PREFIX}" (got "${basename16}"). Cross-namespace snapshots (atlas-toolbox-*) are not valid restore targets for olam-meta hooks.`
|
|
@@ -40335,9 +40782,9 @@ function registerSkillsDoctor(program2) {
|
|
|
40335
40782
|
init_skill_sources();
|
|
40336
40783
|
init_cli_version();
|
|
40337
40784
|
init_output();
|
|
40338
|
-
import { execFileSync as
|
|
40785
|
+
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
40339
40786
|
import * as fs86 from "node:fs";
|
|
40340
|
-
import * as
|
|
40787
|
+
import * as path86 from "node:path";
|
|
40341
40788
|
var CHAIN_SKILL_NAMES = [
|
|
40342
40789
|
"10x:brainstorm",
|
|
40343
40790
|
"10x:plan-hard",
|
|
@@ -40353,17 +40800,17 @@ function asMessage12(err) {
|
|
|
40353
40800
|
}
|
|
40354
40801
|
function hasBeadsCli() {
|
|
40355
40802
|
try {
|
|
40356
|
-
|
|
40803
|
+
execFileSync16("bd", ["--version"], { stdio: "ignore" });
|
|
40357
40804
|
return true;
|
|
40358
40805
|
} catch {
|
|
40359
40806
|
return false;
|
|
40360
40807
|
}
|
|
40361
40808
|
}
|
|
40362
40809
|
function hasBeadsProjectInit(cwd) {
|
|
40363
|
-
return fs86.existsSync(
|
|
40810
|
+
return fs86.existsSync(path86.join(cwd, ".beads"));
|
|
40364
40811
|
}
|
|
40365
40812
|
function hasBeadsClaudeSetup() {
|
|
40366
|
-
const settingsPath =
|
|
40813
|
+
const settingsPath = path86.join(claudeDir(), "settings.json");
|
|
40367
40814
|
if (!fs86.existsSync(settingsPath)) return false;
|
|
40368
40815
|
try {
|
|
40369
40816
|
const content = fs86.readFileSync(settingsPath, "utf8");
|
|
@@ -40382,7 +40829,7 @@ async function bootstrapBeads(cwd) {
|
|
|
40382
40829
|
if (!hasBeadsProjectInit(cwd)) {
|
|
40383
40830
|
console.log("bd init \u2014 initializing beads in current project");
|
|
40384
40831
|
try {
|
|
40385
|
-
|
|
40832
|
+
execFileSync16("bd", ["init", "--quiet", "--stealth"], {
|
|
40386
40833
|
cwd,
|
|
40387
40834
|
stdio: "inherit"
|
|
40388
40835
|
});
|
|
@@ -40395,7 +40842,7 @@ async function bootstrapBeads(cwd) {
|
|
|
40395
40842
|
if (!hasBeadsClaudeSetup()) {
|
|
40396
40843
|
console.log("bd setup claude \u2014 installing beads Claude Code hooks");
|
|
40397
40844
|
try {
|
|
40398
|
-
|
|
40845
|
+
execFileSync16("bd", ["setup", "claude"], { cwd, stdio: "inherit" });
|
|
40399
40846
|
} catch (err) {
|
|
40400
40847
|
printWarning(`bd setup claude failed (continuing): ${asMessage12(err)}`);
|
|
40401
40848
|
}
|
|
@@ -40431,12 +40878,12 @@ function shortSha(sha) {
|
|
|
40431
40878
|
return sha.slice(0, 8);
|
|
40432
40879
|
}
|
|
40433
40880
|
function listInstalledClaudeSkills() {
|
|
40434
|
-
const skillsDir =
|
|
40881
|
+
const skillsDir = path86.join(claudeDir(), "skills");
|
|
40435
40882
|
if (!fs86.existsSync(skillsDir)) return [];
|
|
40436
40883
|
try {
|
|
40437
40884
|
return fs86.readdirSync(skillsDir).filter((name) => {
|
|
40438
40885
|
try {
|
|
40439
|
-
const stat = fs86.lstatSync(
|
|
40886
|
+
const stat = fs86.lstatSync(path86.join(skillsDir, name));
|
|
40440
40887
|
return stat.isSymbolicLink() || stat.isDirectory();
|
|
40441
40888
|
} catch {
|
|
40442
40889
|
return false;
|
|
@@ -40511,14 +40958,14 @@ function registerSkills10x(program2) {
|
|
|
40511
40958
|
tenx.command("uninstall").description(
|
|
40512
40959
|
"Remove /10x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)"
|
|
40513
40960
|
).action(() => {
|
|
40514
|
-
const skillsDir =
|
|
40961
|
+
const skillsDir = path86.join(claudeDir(), "skills");
|
|
40515
40962
|
if (!fs86.existsSync(skillsDir)) {
|
|
40516
40963
|
printWarning("No ~/.claude/skills/ directory found; nothing to uninstall");
|
|
40517
40964
|
return;
|
|
40518
40965
|
}
|
|
40519
40966
|
let removed = 0;
|
|
40520
40967
|
for (const name of fs86.readdirSync(skillsDir)) {
|
|
40521
|
-
const full =
|
|
40968
|
+
const full = path86.join(skillsDir, name);
|
|
40522
40969
|
try {
|
|
40523
40970
|
const stat = fs86.lstatSync(full);
|
|
40524
40971
|
if (!stat.isSymbolicLink()) continue;
|
|
@@ -40594,17 +41041,17 @@ function registerSkills10x(program2) {
|
|
|
40594
41041
|
init_output();
|
|
40595
41042
|
import * as fs87 from "node:fs";
|
|
40596
41043
|
import * as os44 from "node:os";
|
|
40597
|
-
import * as
|
|
41044
|
+
import * as path87 from "node:path";
|
|
40598
41045
|
import * as child_process from "node:child_process";
|
|
40599
41046
|
import { parse as yamlParse2, stringify as yamlStringify3 } from "yaml";
|
|
40600
41047
|
function hermesConfigPath() {
|
|
40601
|
-
return
|
|
41048
|
+
return path87.join(os44.homedir(), ".hermes", "config.yaml");
|
|
40602
41049
|
}
|
|
40603
41050
|
function hermesSkillsDir() {
|
|
40604
|
-
return
|
|
41051
|
+
return path87.join(os44.homedir(), ".hermes", "skills");
|
|
40605
41052
|
}
|
|
40606
41053
|
function claudeSkillsDir() {
|
|
40607
|
-
return
|
|
41054
|
+
return path87.join(os44.homedir(), ".claude", "skills");
|
|
40608
41055
|
}
|
|
40609
41056
|
function readHermesConfig(configPath) {
|
|
40610
41057
|
const raw = fs87.readFileSync(configPath, "utf-8");
|
|
@@ -40716,8 +41163,8 @@ function mirrorSkillSymlinks(dryRun, summary2) {
|
|
|
40716
41163
|
let mirrored = 0;
|
|
40717
41164
|
let collisions = 0;
|
|
40718
41165
|
for (const entry of entries) {
|
|
40719
|
-
const srcPath =
|
|
40720
|
-
const destPath2 =
|
|
41166
|
+
const srcPath = path87.join(srcDir, entry);
|
|
41167
|
+
const destPath2 = path87.join(destDir, entry);
|
|
40721
41168
|
if (fs87.existsSync(destPath2) || fs87.lstatSync(srcPath).isFile()) {
|
|
40722
41169
|
if (fs87.existsSync(destPath2)) collisions++;
|
|
40723
41170
|
continue;
|
|
@@ -40772,7 +41219,7 @@ async function runHermesBootstrap(opts, deps = {}) {
|
|
|
40772
41219
|
} else {
|
|
40773
41220
|
summary2.skipped.push("mcp_servers.agentmemory-atlas (AGENTMEMORY_BRIDGE_URL/SECRET not set; use --bridge-url/--bridge-secret to add)");
|
|
40774
41221
|
}
|
|
40775
|
-
const hooksDir =
|
|
41222
|
+
const hooksDir = path87.join(path87.dirname(configPath), "hooks");
|
|
40776
41223
|
const hookResult = installHookFn(hooksDir, dryRun);
|
|
40777
41224
|
switch (hookResult.status) {
|
|
40778
41225
|
case "installed":
|
|
@@ -40819,7 +41266,7 @@ async function runHermesBootstrap(opts, deps = {}) {
|
|
|
40819
41266
|
}
|
|
40820
41267
|
var HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
|
|
40821
41268
|
function ensureHermesHookEntry(config, hooksDir, dryRun, summary2) {
|
|
40822
|
-
const hookScriptPath =
|
|
41269
|
+
const hookScriptPath = path87.join(hooksDir, "kg-first.sh");
|
|
40823
41270
|
const hooks = config["hooks"] ?? {};
|
|
40824
41271
|
const preToolCall = Array.isArray(hooks["pre_tool_call"]) ? hooks["pre_tool_call"] : [];
|
|
40825
41272
|
const alreadyPresent = preToolCall.some(
|
|
@@ -40957,9 +41404,9 @@ function registerMcpServe(cmd) {
|
|
|
40957
41404
|
init_output();
|
|
40958
41405
|
|
|
40959
41406
|
// src/commands/mcp/install-shared.ts
|
|
40960
|
-
import { spawnSync as
|
|
41407
|
+
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
40961
41408
|
var DEFAULT_CLAUDE_SHELL_DEPS = {
|
|
40962
|
-
spawn:
|
|
41409
|
+
spawn: spawnSync29,
|
|
40963
41410
|
log: (msg) => console.log(msg)
|
|
40964
41411
|
};
|
|
40965
41412
|
function isOnPath(deps, bin) {
|
|
@@ -41092,8 +41539,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
41092
41539
|
function authHeaders() {
|
|
41093
41540
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
41094
41541
|
}
|
|
41095
|
-
async function apiFetch(
|
|
41096
|
-
const res = await fetch(`${BASE_URL}${
|
|
41542
|
+
async function apiFetch(path96, init = {}) {
|
|
41543
|
+
const res = await fetch(`${BASE_URL}${path96}`, {
|
|
41097
41544
|
...init,
|
|
41098
41545
|
headers: {
|
|
41099
41546
|
"Content-Type": "application/json",
|
|
@@ -41355,7 +41802,7 @@ import pc40 from "picocolors";
|
|
|
41355
41802
|
// src/commands/mcp/import-discovery.ts
|
|
41356
41803
|
import * as fs88 from "node:fs";
|
|
41357
41804
|
import * as os45 from "node:os";
|
|
41358
|
-
import * as
|
|
41805
|
+
import * as path88 from "node:path";
|
|
41359
41806
|
function readJsonFile(filePath) {
|
|
41360
41807
|
try {
|
|
41361
41808
|
const raw = fs88.readFileSync(filePath, "utf-8");
|
|
@@ -41387,18 +41834,18 @@ function extractMcpServers(obj, source, sourceLabel) {
|
|
|
41387
41834
|
}
|
|
41388
41835
|
function getClaudeDesktopPath() {
|
|
41389
41836
|
if (process.platform === "darwin") {
|
|
41390
|
-
return
|
|
41837
|
+
return path88.join(os45.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
41391
41838
|
}
|
|
41392
41839
|
if (process.platform === "win32") {
|
|
41393
|
-
const appData = process.env["APPDATA"] ??
|
|
41394
|
-
return
|
|
41840
|
+
const appData = process.env["APPDATA"] ?? path88.join(os45.homedir(), "AppData", "Roaming");
|
|
41841
|
+
return path88.join(appData, "Claude", "claude_desktop_config.json");
|
|
41395
41842
|
}
|
|
41396
|
-
return
|
|
41843
|
+
return path88.join(os45.homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
41397
41844
|
}
|
|
41398
41845
|
function getOlamRepoPaths() {
|
|
41399
41846
|
const configPaths = [
|
|
41400
|
-
|
|
41401
|
-
|
|
41847
|
+
path88.join(os45.homedir(), ".olam", "config.yaml"),
|
|
41848
|
+
path88.join(process.cwd(), ".olam", "config.yaml")
|
|
41402
41849
|
];
|
|
41403
41850
|
const paths = [];
|
|
41404
41851
|
for (const configPath of configPaths) {
|
|
@@ -41420,7 +41867,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
41420
41867
|
const sources = [];
|
|
41421
41868
|
const sourceDefs = [
|
|
41422
41869
|
{
|
|
41423
|
-
path:
|
|
41870
|
+
path: path88.join(os45.homedir(), ".claude.json"),
|
|
41424
41871
|
label: "Claude Code (~/.claude.json)"
|
|
41425
41872
|
},
|
|
41426
41873
|
{
|
|
@@ -41428,19 +41875,19 @@ async function discoverMcpSources(repoPaths) {
|
|
|
41428
41875
|
label: "Claude Desktop"
|
|
41429
41876
|
},
|
|
41430
41877
|
{
|
|
41431
|
-
path:
|
|
41878
|
+
path: path88.join(os45.homedir(), ".cursor", "mcp.json"),
|
|
41432
41879
|
label: "Cursor (~/.cursor/mcp.json)"
|
|
41433
41880
|
},
|
|
41434
41881
|
{
|
|
41435
|
-
path:
|
|
41882
|
+
path: path88.join(os45.homedir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
41436
41883
|
label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
|
|
41437
41884
|
}
|
|
41438
41885
|
];
|
|
41439
41886
|
const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
|
|
41440
41887
|
for (const repoPath of resolvedRepoPaths) {
|
|
41441
41888
|
sourceDefs.push({
|
|
41442
|
-
path:
|
|
41443
|
-
label: `.mcp.json (${
|
|
41889
|
+
path: path88.join(repoPath, ".mcp.json"),
|
|
41890
|
+
label: `.mcp.json (${path88.basename(repoPath)})`
|
|
41444
41891
|
});
|
|
41445
41892
|
}
|
|
41446
41893
|
const reads = await Promise.all(
|
|
@@ -41677,13 +42124,13 @@ init_output();
|
|
|
41677
42124
|
|
|
41678
42125
|
// src/lib/memory-host-process-migration.ts
|
|
41679
42126
|
import { existsSync as existsSync101, readFileSync as readFileSync83, unlinkSync as unlinkSync23 } from "node:fs";
|
|
41680
|
-
import { spawnSync as
|
|
42127
|
+
import { spawnSync as spawnSync30 } from "node:child_process";
|
|
41681
42128
|
|
|
41682
42129
|
// src/commands/memory/_paths.ts
|
|
41683
|
-
import { homedir as
|
|
42130
|
+
import { homedir as homedir53 } from "node:os";
|
|
41684
42131
|
import { join as join95, dirname as dirname55 } from "node:path";
|
|
41685
42132
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
41686
|
-
var OLAM_HOME5 = join95(
|
|
42133
|
+
var OLAM_HOME5 = join95(homedir53(), ".olam");
|
|
41687
42134
|
var MEMORY_PID_PATH = join95(OLAM_HOME5, "memory.pid");
|
|
41688
42135
|
var MEMORY_LOG_PATH = join95(OLAM_HOME5, "memory-service.log");
|
|
41689
42136
|
var MEMORY_DATA_DIR = join95(OLAM_HOME5, "memory-data");
|
|
@@ -41762,7 +42209,7 @@ function isProcessAlive(pid) {
|
|
|
41762
42209
|
}
|
|
41763
42210
|
}
|
|
41764
42211
|
function processCommName(pid) {
|
|
41765
|
-
const r =
|
|
42212
|
+
const r = spawnSync30("ps", ["-p", String(pid), "-o", "comm="], { encoding: "utf-8" });
|
|
41766
42213
|
if (r.status !== 0) return null;
|
|
41767
42214
|
const comm = r.stdout.trim();
|
|
41768
42215
|
return comm.split("/").pop() ?? null;
|
|
@@ -41776,7 +42223,7 @@ function terminateProcess(pid) {
|
|
|
41776
42223
|
const deadline = Date.now() + KILL_TIMEOUT_MS;
|
|
41777
42224
|
while (Date.now() < deadline) {
|
|
41778
42225
|
if (!isProcessAlive(pid)) return true;
|
|
41779
|
-
|
|
42226
|
+
spawnSync30("sleep", ["0.1"]);
|
|
41780
42227
|
}
|
|
41781
42228
|
try {
|
|
41782
42229
|
process.kill(pid, "SIGKILL");
|
|
@@ -42333,13 +42780,13 @@ function resolveMemoryServiceDir() {
|
|
|
42333
42780
|
);
|
|
42334
42781
|
}
|
|
42335
42782
|
function resolveLocalBridgeScript(serviceDir) {
|
|
42336
|
-
const
|
|
42337
|
-
if (!existsSync105(
|
|
42783
|
+
const path96 = join97(serviceDir, "scripts", "local-bridge-server.mjs");
|
|
42784
|
+
if (!existsSync105(path96)) {
|
|
42338
42785
|
throw new Error(
|
|
42339
|
-
`Could not find local-bridge-server.mjs at ${
|
|
42786
|
+
`Could not find local-bridge-server.mjs at ${path96}. Verify packages/memory-service ships the scripts/ directory.`
|
|
42340
42787
|
);
|
|
42341
42788
|
}
|
|
42342
|
-
return
|
|
42789
|
+
return path96;
|
|
42343
42790
|
}
|
|
42344
42791
|
function validateBridgeOpts(opts) {
|
|
42345
42792
|
const local = opts.local ?? false;
|
|
@@ -42681,7 +43128,7 @@ function registerMemoryStats(cmd) {
|
|
|
42681
43128
|
|
|
42682
43129
|
// src/commands/memory/install-hooks.ts
|
|
42683
43130
|
import { copyFileSync as copyFileSync12, existsSync as existsSync106, mkdirSync as mkdirSync60, readFileSync as readFileSync85, writeFileSync as writeFileSync52 } from "node:fs";
|
|
42684
|
-
import { homedir as
|
|
43131
|
+
import { homedir as homedir54 } from "node:os";
|
|
42685
43132
|
import { dirname as dirname56, join as join98, resolve as resolve25 } from "node:path";
|
|
42686
43133
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
42687
43134
|
var HOOK_BASENAMES = [
|
|
@@ -42750,7 +43197,7 @@ If existing entries already point at the same paths, no edit needed.
|
|
|
42750
43197
|
}
|
|
42751
43198
|
function registerMemoryInstallHooks(parent) {
|
|
42752
43199
|
parent.command("install-hooks").description("Install agentmemory hooks (PreToolUse + PostToolUse + SessionStart) to ~/.claude/scripts/hooks/").option("--force", "overwrite existing non-canonical files (backs them up to .agentmemory-hook-backup-<ts>)").option("--dry-run", "preview which hooks would be written without modifying disk").option("--target-dir <path>", "override target directory (default: ~/.claude/scripts/hooks/); for tests").option("--source-dir <path>", "override source directory (default: packages/memory-service/hooks/); for tests").action((opts) => {
|
|
42753
|
-
const targetDir = opts.targetDir ?? join98(
|
|
43200
|
+
const targetDir = opts.targetDir ?? join98(homedir54(), ".claude", "scripts", "hooks");
|
|
42754
43201
|
const sourceDir = opts.sourceDir ?? defaultSourceDir();
|
|
42755
43202
|
let written = 0;
|
|
42756
43203
|
let unchanged = 0;
|
|
@@ -42830,7 +43277,7 @@ init_storage_paths();
|
|
|
42830
43277
|
init_workspace_name();
|
|
42831
43278
|
import * as fs93 from "node:fs";
|
|
42832
43279
|
import * as os48 from "node:os";
|
|
42833
|
-
import * as
|
|
43280
|
+
import * as path93 from "node:path";
|
|
42834
43281
|
|
|
42835
43282
|
// ../core/dist/kg/kg-service-client.js
|
|
42836
43283
|
var KG_SERVICE_PORT_DEFAULT = 9997;
|
|
@@ -42841,8 +43288,8 @@ function port() {
|
|
|
42841
43288
|
const n = Number.parseInt(env, 10);
|
|
42842
43289
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
42843
43290
|
}
|
|
42844
|
-
function url(
|
|
42845
|
-
return `http://127.0.0.1:${port()}${
|
|
43291
|
+
function url(path96) {
|
|
43292
|
+
return `http://127.0.0.1:${port()}${path96}`;
|
|
42846
43293
|
}
|
|
42847
43294
|
function kgServiceHealthUrl() {
|
|
42848
43295
|
return url("/health");
|
|
@@ -42923,16 +43370,16 @@ init_workspace_name();
|
|
|
42923
43370
|
init_kg_caps();
|
|
42924
43371
|
init_output();
|
|
42925
43372
|
import fs89 from "node:fs";
|
|
42926
|
-
import { homedir as
|
|
42927
|
-
import
|
|
43373
|
+
import { homedir as homedir55 } from "node:os";
|
|
43374
|
+
import path89 from "node:path";
|
|
42928
43375
|
function olamHome4() {
|
|
42929
|
-
return process.env.OLAM_HOME ??
|
|
43376
|
+
return process.env.OLAM_HOME ?? path89.join(homedir55(), ".olam");
|
|
42930
43377
|
}
|
|
42931
43378
|
function kgRoot2() {
|
|
42932
|
-
return
|
|
43379
|
+
return path89.join(olamHome4(), "kg");
|
|
42933
43380
|
}
|
|
42934
43381
|
function worldsRoot2() {
|
|
42935
|
-
return
|
|
43382
|
+
return path89.join(olamHome4(), "worlds");
|
|
42936
43383
|
}
|
|
42937
43384
|
function dirSizeBytes2(dir) {
|
|
42938
43385
|
if (!fs89.existsSync(dir)) return 0;
|
|
@@ -42947,7 +43394,7 @@ function dirSizeBytes2(dir) {
|
|
|
42947
43394
|
continue;
|
|
42948
43395
|
}
|
|
42949
43396
|
for (const entry of entries) {
|
|
42950
|
-
const full =
|
|
43397
|
+
const full = path89.join(cur, entry.name);
|
|
42951
43398
|
if (entry.isSymbolicLink()) continue;
|
|
42952
43399
|
if (entry.isDirectory()) {
|
|
42953
43400
|
stack.push(full);
|
|
@@ -42968,7 +43415,7 @@ function formatBytes5(n) {
|
|
|
42968
43415
|
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
42969
43416
|
}
|
|
42970
43417
|
function readFreshness(workspace) {
|
|
42971
|
-
const file =
|
|
43418
|
+
const file = path89.join(kgPristinePath(workspace), "freshness.json");
|
|
42972
43419
|
if (!fs89.existsSync(file)) return null;
|
|
42973
43420
|
try {
|
|
42974
43421
|
const raw = JSON.parse(fs89.readFileSync(file, "utf-8"));
|
|
@@ -42979,7 +43426,7 @@ function readFreshness(workspace) {
|
|
|
42979
43426
|
}
|
|
42980
43427
|
}
|
|
42981
43428
|
function readOverlayNodeCount(graphifyOutDir) {
|
|
42982
|
-
const graphPath =
|
|
43429
|
+
const graphPath = path89.join(graphifyOutDir, "graph.json");
|
|
42983
43430
|
if (!fs89.existsSync(graphPath)) return null;
|
|
42984
43431
|
try {
|
|
42985
43432
|
const raw = JSON.parse(fs89.readFileSync(graphPath, "utf-8"));
|
|
@@ -43005,7 +43452,7 @@ function listOverlays() {
|
|
|
43005
43452
|
for (const worldEntry of worldDirs) {
|
|
43006
43453
|
if (!worldEntry.isDirectory()) continue;
|
|
43007
43454
|
const worldId = worldEntry.name;
|
|
43008
|
-
const worldDir =
|
|
43455
|
+
const worldDir = path89.join(root, worldId);
|
|
43009
43456
|
let cloneDirs;
|
|
43010
43457
|
try {
|
|
43011
43458
|
cloneDirs = fs89.readdirSync(worldDir, { withFileTypes: true });
|
|
@@ -43014,7 +43461,7 @@ function listOverlays() {
|
|
|
43014
43461
|
}
|
|
43015
43462
|
for (const cloneEntry of cloneDirs) {
|
|
43016
43463
|
if (!cloneEntry.isDirectory()) continue;
|
|
43017
|
-
const graphifyOut =
|
|
43464
|
+
const graphifyOut = path89.join(worldDir, cloneEntry.name, "graphify-out");
|
|
43018
43465
|
if (!fs89.existsSync(graphifyOut)) continue;
|
|
43019
43466
|
records.push({
|
|
43020
43467
|
world_id: worldId,
|
|
@@ -43046,7 +43493,7 @@ function listPristines(overlays) {
|
|
|
43046
43493
|
continue;
|
|
43047
43494
|
}
|
|
43048
43495
|
const fresh = readFreshness(workspace);
|
|
43049
|
-
const graphifyOut =
|
|
43496
|
+
const graphifyOut = path89.join(kgPristinePath(workspace), "graphify-out");
|
|
43050
43497
|
const size = dirSizeBytes2(graphifyOut);
|
|
43051
43498
|
const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
|
|
43052
43499
|
records.push({
|
|
@@ -43183,9 +43630,9 @@ init_workspace_name();
|
|
|
43183
43630
|
init_output();
|
|
43184
43631
|
import { spawn as spawn12 } from "node:child_process";
|
|
43185
43632
|
import fs90 from "node:fs";
|
|
43186
|
-
import
|
|
43633
|
+
import path90 from "node:path";
|
|
43187
43634
|
function pidFilePath2(workspace) {
|
|
43188
|
-
return
|
|
43635
|
+
return path90.join(kgPristinePath(workspace), ".watch.pid");
|
|
43189
43636
|
}
|
|
43190
43637
|
function isPidAlive3(pid) {
|
|
43191
43638
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -43219,7 +43666,7 @@ function readAndClassifyPid(workspace) {
|
|
|
43219
43666
|
}
|
|
43220
43667
|
function writePidFile2(workspace, pid) {
|
|
43221
43668
|
const file = pidFilePath2(workspace);
|
|
43222
|
-
const dir =
|
|
43669
|
+
const dir = path90.dirname(file);
|
|
43223
43670
|
fs90.mkdirSync(dir, { recursive: true });
|
|
43224
43671
|
fs90.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
43225
43672
|
}
|
|
@@ -43232,7 +43679,7 @@ function removePidFile(workspace) {
|
|
|
43232
43679
|
}
|
|
43233
43680
|
async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
43234
43681
|
const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
|
|
43235
|
-
const name = workspaceArg ??
|
|
43682
|
+
const name = workspaceArg ?? path90.basename(cwd).toLowerCase();
|
|
43236
43683
|
try {
|
|
43237
43684
|
validateWorkspaceName(name);
|
|
43238
43685
|
} catch (err) {
|
|
@@ -43240,7 +43687,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
43240
43687
|
return { exitCode: 1, pidWritten: false };
|
|
43241
43688
|
}
|
|
43242
43689
|
const pristinePath = kgPristinePath(name);
|
|
43243
|
-
const graphPath =
|
|
43690
|
+
const graphPath = path90.join(pristinePath, "graphify-out", "graph.json");
|
|
43244
43691
|
const pidState = readAndClassifyPid(name);
|
|
43245
43692
|
if (pidState.status === "active") {
|
|
43246
43693
|
printError(
|
|
@@ -43479,7 +43926,7 @@ function registerKgDoctorCommand(kg) {
|
|
|
43479
43926
|
// src/commands/kg-install-hook.ts
|
|
43480
43927
|
init_merge_settings();
|
|
43481
43928
|
import * as fs91 from "node:fs";
|
|
43482
|
-
import * as
|
|
43929
|
+
import * as path91 from "node:path";
|
|
43483
43930
|
import * as os46 from "node:os";
|
|
43484
43931
|
import { parse as yamlParse3, stringify as yamlStringify4 } from "yaml";
|
|
43485
43932
|
|
|
@@ -43532,9 +43979,9 @@ function buildHookMatcherEntry(opts) {
|
|
|
43532
43979
|
init_output();
|
|
43533
43980
|
function settingsPathFor2(scope) {
|
|
43534
43981
|
if (scope === "user") {
|
|
43535
|
-
return
|
|
43982
|
+
return path91.join(os46.homedir(), ".claude", "settings.json");
|
|
43536
43983
|
}
|
|
43537
|
-
return
|
|
43984
|
+
return path91.join(process.cwd(), ".claude", "settings.json");
|
|
43538
43985
|
}
|
|
43539
43986
|
function backup2(filePath) {
|
|
43540
43987
|
if (!fs91.existsSync(filePath)) return null;
|
|
@@ -43545,10 +43992,10 @@ function backup2(filePath) {
|
|
|
43545
43992
|
}
|
|
43546
43993
|
var HERMES_HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
|
|
43547
43994
|
function hermesConfigPath2() {
|
|
43548
|
-
return
|
|
43995
|
+
return path91.join(os46.homedir(), ".hermes", "config.yaml");
|
|
43549
43996
|
}
|
|
43550
43997
|
function hermesHooksDir() {
|
|
43551
|
-
return
|
|
43998
|
+
return path91.join(os46.homedir(), ".hermes", "hooks");
|
|
43552
43999
|
}
|
|
43553
44000
|
function patchHermesConfigForHook(action) {
|
|
43554
44001
|
const configPath = hermesConfigPath2();
|
|
@@ -43561,7 +44008,7 @@ function patchHermesConfigForHook(action) {
|
|
|
43561
44008
|
(e) => typeof e["command"] === "string" && e["command"].includes(HERMES_KG_HOOK_SENTINEL)
|
|
43562
44009
|
);
|
|
43563
44010
|
if (alreadyPresent) return "already-present";
|
|
43564
|
-
const hookScriptPath =
|
|
44011
|
+
const hookScriptPath = path91.join(hermesHooksDir(), "kg-first.sh");
|
|
43565
44012
|
const entry = {
|
|
43566
44013
|
matcher: HERMES_HOOK_MATCHERS.join("|"),
|
|
43567
44014
|
command: `${hookScriptPath} # ${HERMES_KG_HOOK_SENTINEL}`
|
|
@@ -43615,7 +44062,7 @@ function doInstallForHermes() {
|
|
|
43615
44062
|
function doUninstallForHermes() {
|
|
43616
44063
|
const configPath = hermesConfigPath2();
|
|
43617
44064
|
const hooksDir = hermesHooksDir();
|
|
43618
|
-
const hookScriptPath =
|
|
44065
|
+
const hookScriptPath = path91.join(hooksDir, "kg-first.sh");
|
|
43619
44066
|
let scriptRemoved = false;
|
|
43620
44067
|
if (fs91.existsSync(hookScriptPath)) {
|
|
43621
44068
|
const content = fs91.readFileSync(hookScriptPath, "utf-8");
|
|
@@ -43650,9 +44097,9 @@ function registerKgInstallHookCommand(kg) {
|
|
|
43650
44097
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
43651
44098
|
const filePath = settingsPathFor2(scope);
|
|
43652
44099
|
try {
|
|
43653
|
-
fs91.mkdirSync(
|
|
44100
|
+
fs91.mkdirSync(path91.dirname(filePath), { recursive: true });
|
|
43654
44101
|
} catch (err) {
|
|
43655
|
-
printError(`could not create ${
|
|
44102
|
+
printError(`could not create ${path91.dirname(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
43656
44103
|
process.exitCode = 1;
|
|
43657
44104
|
return;
|
|
43658
44105
|
}
|
|
@@ -43695,14 +44142,14 @@ function registerKgInstallHookCommand(kg) {
|
|
|
43695
44142
|
|
|
43696
44143
|
// src/commands/kg-uninstall-hook.ts
|
|
43697
44144
|
import * as fs92 from "node:fs";
|
|
43698
|
-
import * as
|
|
44145
|
+
import * as path92 from "node:path";
|
|
43699
44146
|
import * as os47 from "node:os";
|
|
43700
44147
|
init_output();
|
|
43701
44148
|
function settingsPathFor3(scope) {
|
|
43702
44149
|
if (scope === "user") {
|
|
43703
|
-
return
|
|
44150
|
+
return path92.join(os47.homedir(), ".claude", "settings.json");
|
|
43704
44151
|
}
|
|
43705
|
-
return
|
|
44152
|
+
return path92.join(process.cwd(), ".claude", "settings.json");
|
|
43706
44153
|
}
|
|
43707
44154
|
function dropSentinel(matchers) {
|
|
43708
44155
|
let changed = false;
|
|
@@ -43864,14 +44311,14 @@ function readQueueFromDisk(queuePath) {
|
|
|
43864
44311
|
return entries;
|
|
43865
44312
|
}
|
|
43866
44313
|
function writeQueueToDisk(queuePath, entries) {
|
|
43867
|
-
fs93.mkdirSync(
|
|
44314
|
+
fs93.mkdirSync(path93.dirname(queuePath), { recursive: true });
|
|
43868
44315
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
43869
44316
|
fs93.writeFileSync(queuePath, content, "utf-8");
|
|
43870
44317
|
}
|
|
43871
44318
|
async function runKgBuildPending(opts = {}) {
|
|
43872
44319
|
const queuePath = opts.queuePath ?? (() => {
|
|
43873
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
43874
|
-
return
|
|
44320
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path93.join(os48.homedir(), ".olam", "state");
|
|
44321
|
+
return path93.join(stateDir, "kg-pending.jsonl");
|
|
43875
44322
|
})();
|
|
43876
44323
|
const readQueue2 = opts.readQueueFn ?? readQueueFromDisk;
|
|
43877
44324
|
const writeQueue2 = opts.writeQueueFn ?? writeQueueToDisk;
|
|
@@ -43887,7 +44334,7 @@ async function runKgBuildPending(opts = {}) {
|
|
|
43887
44334
|
const remaining = [];
|
|
43888
44335
|
for (const entry of deduped) {
|
|
43889
44336
|
const repoPath = entry.path;
|
|
43890
|
-
const workspaceName =
|
|
44337
|
+
const workspaceName = path93.basename(repoPath).toLowerCase();
|
|
43891
44338
|
printInfo("kg build --pending", `building ${repoPath} (workspace=${workspaceName})`);
|
|
43892
44339
|
let containerPath;
|
|
43893
44340
|
try {
|
|
@@ -43925,20 +44372,20 @@ async function runKgBuildPending(opts = {}) {
|
|
|
43925
44372
|
}
|
|
43926
44373
|
function resolveWorkspace(arg) {
|
|
43927
44374
|
const cwd = process.cwd();
|
|
43928
|
-
const name = arg ??
|
|
44375
|
+
const name = arg ?? path93.basename(cwd).toLowerCase();
|
|
43929
44376
|
validateWorkspaceName(name);
|
|
43930
44377
|
return { name, sourcePath: cwd };
|
|
43931
44378
|
}
|
|
43932
44379
|
function toContainerPath(hostPath) {
|
|
43933
44380
|
const home = os48.homedir();
|
|
43934
|
-
const resolved =
|
|
43935
|
-
if (!resolved.startsWith(home +
|
|
44381
|
+
const resolved = path93.resolve(hostPath);
|
|
44382
|
+
if (!resolved.startsWith(home + path93.sep) && resolved !== home) {
|
|
43936
44383
|
throw new Error(
|
|
43937
44384
|
`source path "${resolved}" is not under $HOME (${home}). kg-service can only build repos that live under your home dir (it bind-mounts $HOME:/host-home:ro at start). Move the repo or set OLAM_HOME if you need a different root.`
|
|
43938
44385
|
);
|
|
43939
44386
|
}
|
|
43940
|
-
const rel =
|
|
43941
|
-
return rel === "" ? "/host-home" :
|
|
44387
|
+
const rel = path93.relative(home, resolved);
|
|
44388
|
+
return rel === "" ? "/host-home" : path93.posix.join("/host-home", rel.split(path93.sep).join("/"));
|
|
43942
44389
|
}
|
|
43943
44390
|
async function runKgBuild(workspaceArg, options = {}) {
|
|
43944
44391
|
let workspace;
|
|
@@ -43990,11 +44437,11 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
43990
44437
|
graphify_path: "container"
|
|
43991
44438
|
};
|
|
43992
44439
|
fs93.writeFileSync(
|
|
43993
|
-
|
|
44440
|
+
path93.join(outDir, "freshness.json"),
|
|
43994
44441
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
43995
44442
|
"utf-8"
|
|
43996
44443
|
);
|
|
43997
|
-
const finalOut =
|
|
44444
|
+
const finalOut = path93.join(outDir, "graphify-out");
|
|
43998
44445
|
if (options.json) {
|
|
43999
44446
|
process.stdout.write(JSON.stringify(freshness) + "\n");
|
|
44000
44447
|
} else {
|
|
@@ -44036,12 +44483,12 @@ function registerKg(program2) {
|
|
|
44036
44483
|
// src/commands/flywheel/emit-breadcrumb.ts
|
|
44037
44484
|
init_file_lock();
|
|
44038
44485
|
import { mkdirSync as mkdirSync63, appendFileSync as appendFileSync6 } from "node:fs";
|
|
44039
|
-
import { homedir as
|
|
44486
|
+
import { homedir as homedir59 } from "node:os";
|
|
44040
44487
|
import { dirname as dirname59, join as join102 } from "node:path";
|
|
44041
44488
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
44042
44489
|
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info", "warn"]);
|
|
44043
44490
|
var PROMPT_FEEDING_FIELDS = ["extracted_pattern", "severity", "affected_persona", "proposed_edit"];
|
|
44044
|
-
var BREADCRUMBS_BASE = join102(
|
|
44491
|
+
var BREADCRUMBS_BASE = join102(homedir59(), ".local", "share", "claude", "breadcrumbs");
|
|
44045
44492
|
var LOCK_FILENAME = ".flywheel-emit.lock";
|
|
44046
44493
|
function buildRecord(opts) {
|
|
44047
44494
|
const rec = {
|
|
@@ -44107,14 +44554,14 @@ async function emitBreadcrumb(opts) {
|
|
|
44107
44554
|
);
|
|
44108
44555
|
process.exit(2);
|
|
44109
44556
|
}
|
|
44110
|
-
const
|
|
44111
|
-
const lockDir = dirname59(
|
|
44557
|
+
const path96 = destPath(rec.project_slug);
|
|
44558
|
+
const lockDir = dirname59(path96);
|
|
44112
44559
|
mkdirSync63(lockDir, { recursive: true });
|
|
44113
44560
|
const line = JSON.stringify(rec) + "\n";
|
|
44114
44561
|
await withFileLock(
|
|
44115
44562
|
lockDir,
|
|
44116
44563
|
() => {
|
|
44117
|
-
appendFileSync6(
|
|
44564
|
+
appendFileSync6(path96, line, "utf8");
|
|
44118
44565
|
},
|
|
44119
44566
|
{
|
|
44120
44567
|
lockFilename: LOCK_FILENAME,
|
|
@@ -44124,7 +44571,7 @@ async function emitBreadcrumb(opts) {
|
|
|
44124
44571
|
acquireTimeoutMs: 5e3
|
|
44125
44572
|
}
|
|
44126
44573
|
);
|
|
44127
|
-
process.stdout.write(`[K7-emit] ${
|
|
44574
|
+
process.stdout.write(`[K7-emit] ${path96}: ${rec.extracted_pattern} (${rec.severity})
|
|
44128
44575
|
`);
|
|
44129
44576
|
}
|
|
44130
44577
|
function registerFlywheelEmitBreadcrumb(parent) {
|
|
@@ -44247,38 +44694,38 @@ function validateK5ScoredAt(scoredAt) {
|
|
|
44247
44694
|
}
|
|
44248
44695
|
return null;
|
|
44249
44696
|
}
|
|
44250
|
-
function validatePlan(
|
|
44697
|
+
function validatePlan(path96) {
|
|
44251
44698
|
let stat;
|
|
44252
44699
|
try {
|
|
44253
|
-
stat = statSync30(
|
|
44700
|
+
stat = statSync30(path96);
|
|
44254
44701
|
} catch (err) {
|
|
44255
|
-
return { ok: false, message: `FAIL cannot stat ${
|
|
44702
|
+
return { ok: false, message: `FAIL cannot stat ${path96}: ${err instanceof Error ? err.message : "unknown"}` };
|
|
44256
44703
|
}
|
|
44257
44704
|
if (stat.size > MAX_PLAN_BYTES) {
|
|
44258
|
-
return { ok: false, message: `FAIL ${
|
|
44705
|
+
return { ok: false, message: `FAIL ${path96}: plan file exceeds 1MB (${stat.size} bytes); refusing to parse` };
|
|
44259
44706
|
}
|
|
44260
44707
|
let text;
|
|
44261
44708
|
try {
|
|
44262
|
-
text = readFileSync89(
|
|
44709
|
+
text = readFileSync89(path96, "utf8");
|
|
44263
44710
|
} catch (err) {
|
|
44264
|
-
return { ok: false, message: `FAIL cannot read ${
|
|
44711
|
+
return { ok: false, message: `FAIL cannot read ${path96}: ${err instanceof Error ? err.message : "unknown"}` };
|
|
44265
44712
|
}
|
|
44266
44713
|
if (!text.replace(/^/, "").startsWith("---")) {
|
|
44267
|
-
return { ok: false, message: `FAIL ${
|
|
44714
|
+
return { ok: false, message: `FAIL ${path96}: no YAML frontmatter (missing opening --- marker)` };
|
|
44268
44715
|
}
|
|
44269
44716
|
if (!text.includes("\n---", 3)) {
|
|
44270
|
-
return { ok: false, message: `FAIL ${
|
|
44717
|
+
return { ok: false, message: `FAIL ${path96}: frontmatter block never closed (missing closing --- marker)` };
|
|
44271
44718
|
}
|
|
44272
44719
|
const fm = extractFrontmatter(text);
|
|
44273
44720
|
if (fm === null) {
|
|
44274
|
-
return { ok: false, message: `FAIL ${
|
|
44721
|
+
return { ok: false, message: `FAIL ${path96}: frontmatter could not be parsed as YAML` };
|
|
44275
44722
|
}
|
|
44276
44723
|
const hasScores = "k5_scores" in fm;
|
|
44277
44724
|
const hasBoost = "k5_boost" in fm;
|
|
44278
44725
|
const hasComposite = "k5_composite" in fm;
|
|
44279
44726
|
const hasScoredAt = "k5_scored_at" in fm;
|
|
44280
44727
|
if (!hasScores && !hasBoost && !hasComposite && !hasScoredAt) {
|
|
44281
|
-
return { ok: true, message: `PASS ${
|
|
44728
|
+
return { ok: true, message: `PASS ${path96}: k5_scores absent (acceptable \u2014 legacy plan)` };
|
|
44282
44729
|
}
|
|
44283
44730
|
const errors = [];
|
|
44284
44731
|
if (hasScores) {
|
|
@@ -44298,9 +44745,9 @@ function validatePlan(path95) {
|
|
|
44298
44745
|
if (err !== null) errors.push(err);
|
|
44299
44746
|
}
|
|
44300
44747
|
if (errors.length > 0) {
|
|
44301
|
-
return { ok: false, message: `FAIL ${
|
|
44748
|
+
return { ok: false, message: `FAIL ${path96}: ${errors.join("; ")}` };
|
|
44302
44749
|
}
|
|
44303
|
-
const lines = [`PASS ${
|
|
44750
|
+
const lines = [`PASS ${path96}: k5_scores valid`];
|
|
44304
44751
|
if (hasScores && typeof fm.k5_scores === "object" && fm.k5_scores !== null) {
|
|
44305
44752
|
const scoresObj = fm.k5_scores;
|
|
44306
44753
|
const vals = [];
|
|
@@ -44445,12 +44892,12 @@ function registerFlywheelK10Measure(parent) {
|
|
|
44445
44892
|
|
|
44446
44893
|
// src/commands/flywheel/check-persona-skeleton.ts
|
|
44447
44894
|
import { existsSync as existsSync110, readFileSync as readFileSync91, statSync as statSync31 } from "node:fs";
|
|
44448
|
-
import { homedir as
|
|
44895
|
+
import { homedir as homedir60 } from "node:os";
|
|
44449
44896
|
import { basename as basename14, join as join103 } from "node:path";
|
|
44450
44897
|
import { parse as parseYAML2 } from "yaml";
|
|
44451
44898
|
var CHARS_PER_TOKEN3 = 4;
|
|
44452
44899
|
var K10_TOKEN_CAP2 = 6e3;
|
|
44453
|
-
var AGENTS_DIR = join103(
|
|
44900
|
+
var AGENTS_DIR = join103(homedir60(), ".claude", "agents");
|
|
44454
44901
|
var REQUIRED_FRONTMATTER_KEYS = ["name", "description", "allowed-tools"];
|
|
44455
44902
|
var REQUIRED_SECTIONS = [
|
|
44456
44903
|
"## Role",
|
|
@@ -44700,7 +45147,7 @@ ${formatRedivergencePrompt(persona_a, persona_b, score, void 0, void 0, threshol
|
|
|
44700
45147
|
|
|
44701
45148
|
// src/commands/flywheel/ping.ts
|
|
44702
45149
|
import { mkdirSync as mkdirSync64, writeFileSync as writeFileSync56 } from "node:fs";
|
|
44703
|
-
import { homedir as
|
|
45150
|
+
import { homedir as homedir61 } from "node:os";
|
|
44704
45151
|
import { dirname as dirname60, join as join104 } from "node:path";
|
|
44705
45152
|
var COLD_START_BUDGET_GOOD_MS = 200;
|
|
44706
45153
|
var COLD_START_BUDGET_FAIR_MS = 500;
|
|
@@ -44717,7 +45164,7 @@ function readOlamVersion() {
|
|
|
44717
45164
|
}
|
|
44718
45165
|
}
|
|
44719
45166
|
function writeBaseline(record) {
|
|
44720
|
-
const baselinePath = join104(
|
|
45167
|
+
const baselinePath = join104(homedir61(), ".local", "share", "olam", "flywheel-baseline.json");
|
|
44721
45168
|
mkdirSync64(dirname60(baselinePath), { recursive: true });
|
|
44722
45169
|
writeFileSync56(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
|
|
44723
45170
|
return baselinePath;
|
|
@@ -44766,8 +45213,8 @@ import {
|
|
|
44766
45213
|
statSync as statSync32,
|
|
44767
45214
|
writeFileSync as writeFileSync57
|
|
44768
45215
|
} from "node:fs";
|
|
44769
|
-
import { spawnSync as
|
|
44770
|
-
import { homedir as
|
|
45216
|
+
import { spawnSync as spawnSync31 } from "node:child_process";
|
|
45217
|
+
import { homedir as homedir62 } from "node:os";
|
|
44771
45218
|
import { dirname as dirname61, join as join105, relative as relative7 } from "node:path";
|
|
44772
45219
|
function escapeRegex(s) {
|
|
44773
45220
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -44844,7 +45291,7 @@ function resolveAtlasUser2(opts) {
|
|
|
44844
45291
|
assertValidAtlasUser(v);
|
|
44845
45292
|
return v;
|
|
44846
45293
|
}
|
|
44847
|
-
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join105(
|
|
45294
|
+
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join105(homedir62(), ".claude");
|
|
44848
45295
|
const f = join105(claudeDir2, ".atlas-user");
|
|
44849
45296
|
if (existsSync111(f)) {
|
|
44850
45297
|
const v = readFileSync93(f, "utf-8").trim();
|
|
@@ -44855,7 +45302,7 @@ function resolveAtlasUser2(opts) {
|
|
|
44855
45302
|
return null;
|
|
44856
45303
|
}
|
|
44857
45304
|
function runGit2(args, cwd) {
|
|
44858
|
-
const result =
|
|
45305
|
+
const result = spawnSync31("git", args, {
|
|
44859
45306
|
cwd,
|
|
44860
45307
|
encoding: "utf-8",
|
|
44861
45308
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -44981,7 +45428,7 @@ function pushOverlays(opts) {
|
|
|
44981
45428
|
Run \`olam skills atlas-user set <name>\` to configure your atlas user.`
|
|
44982
45429
|
);
|
|
44983
45430
|
}
|
|
44984
|
-
const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join105(
|
|
45431
|
+
const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join105(homedir62(), ".claude");
|
|
44985
45432
|
const sourceFiles = walkPushSourceFiles(claudeDir2);
|
|
44986
45433
|
const registeredPrefixes = (opts._testSkillSources ?? listSkillSources()).map((s) => s.prefix).filter((p) => typeof p === "string" && p.length > 0);
|
|
44987
45434
|
if (registeredPrefixes.length > 0) {
|
|
@@ -45289,7 +45736,7 @@ Next steps (run in ${clonePath}):`,
|
|
|
45289
45736
|
};
|
|
45290
45737
|
}
|
|
45291
45738
|
function migrateOverlays(opts = {}) {
|
|
45292
|
-
const root = opts.targetDir ?? join105(
|
|
45739
|
+
const root = opts.targetDir ?? join105(homedir62(), ".claude");
|
|
45293
45740
|
const overrideRoots = [
|
|
45294
45741
|
join105(root, "skills.overrides"),
|
|
45295
45742
|
join105(root, "agents.overrides")
|
|
@@ -45411,7 +45858,7 @@ function registerFlywheelMigrateOverlays(parent) {
|
|
|
45411
45858
|
}
|
|
45412
45859
|
return;
|
|
45413
45860
|
}
|
|
45414
|
-
const root = opts.targetDir ?? join105(
|
|
45861
|
+
const root = opts.targetDir ?? join105(homedir62(), ".claude");
|
|
45415
45862
|
const summary2 = migrateOverlays(opts);
|
|
45416
45863
|
if (opts.json === true) {
|
|
45417
45864
|
process.stdout.write(JSON.stringify(summary2, null, 2) + "\n");
|
|
@@ -45468,7 +45915,7 @@ function registerFlywheel(program2) {
|
|
|
45468
45915
|
|
|
45469
45916
|
// src/commands/seed.ts
|
|
45470
45917
|
init_output();
|
|
45471
|
-
import { spawnSync as
|
|
45918
|
+
import { spawnSync as spawnSync32, spawn as spawnAsync2 } from "node:child_process";
|
|
45472
45919
|
var DEFAULT_SINGLETON_CONTAINER = "olam-postgres";
|
|
45473
45920
|
var DEFAULT_SINGLETON_USER = "development";
|
|
45474
45921
|
function assertValidSeedName(name) {
|
|
@@ -45479,7 +45926,7 @@ function assertValidSeedName(name) {
|
|
|
45479
45926
|
}
|
|
45480
45927
|
}
|
|
45481
45928
|
function singletonDocker(container, user, args, stdin) {
|
|
45482
|
-
return
|
|
45929
|
+
return spawnSync32(
|
|
45483
45930
|
"docker",
|
|
45484
45931
|
["exec", "-i", container, "psql", "-U", user, ...args],
|
|
45485
45932
|
{ encoding: "utf-8", input: stdin }
|
|
@@ -45534,7 +45981,7 @@ async function handleBake(opts) {
|
|
|
45534
45981
|
if (sources.length > 1) {
|
|
45535
45982
|
throw new Error("multiple sources specified \u2014 pass exactly one of --source-container, --source-url, --source-local");
|
|
45536
45983
|
}
|
|
45537
|
-
const ping =
|
|
45984
|
+
const ping = spawnSync32("docker", ["inspect", "--format", "{{.State.Status}}", singleton], { encoding: "utf-8" });
|
|
45538
45985
|
if (ping.status !== 0 || (ping.stdout || "").trim() !== "running") {
|
|
45539
45986
|
throw new Error(`singleton container "${singleton}" not running \u2014 run \`olam bootstrap\` first`);
|
|
45540
45987
|
}
|
|
@@ -45717,12 +46164,12 @@ init_output();
|
|
|
45717
46164
|
import { spawnSync as defaultSpawnSync } from "node:child_process";
|
|
45718
46165
|
import * as fs94 from "node:fs";
|
|
45719
46166
|
import * as os49 from "node:os";
|
|
45720
|
-
import * as
|
|
46167
|
+
import * as path94 from "node:path";
|
|
45721
46168
|
function devboxContainerName(worldId) {
|
|
45722
46169
|
return `olam-${worldId}-devbox`;
|
|
45723
46170
|
}
|
|
45724
46171
|
function olamHomeDir() {
|
|
45725
|
-
return process.env["OLAM_HOME"] ??
|
|
46172
|
+
return process.env["OLAM_HOME"] ?? path94.join(os49.homedir(), ".olam");
|
|
45726
46173
|
}
|
|
45727
46174
|
function defaultRestartContainer(name, spawn13 = defaultSpawnSync) {
|
|
45728
46175
|
const r = spawn13("docker", ["restart", "--time", "30", name], {
|
|
@@ -45736,7 +46183,7 @@ function defaultRestartContainer(name, spawn13 = defaultSpawnSync) {
|
|
|
45736
46183
|
}
|
|
45737
46184
|
function defaultAppendAuditLog(homeDir, line) {
|
|
45738
46185
|
fs94.mkdirSync(homeDir, { recursive: true });
|
|
45739
|
-
fs94.appendFileSync(
|
|
46186
|
+
fs94.appendFileSync(path94.join(homeDir, "usage.log"), line.endsWith("\n") ? line : line + "\n", {
|
|
45740
46187
|
encoding: "utf-8"
|
|
45741
46188
|
});
|
|
45742
46189
|
}
|
|
@@ -45781,9 +46228,9 @@ async function doRekey(worldId, deps) {
|
|
|
45781
46228
|
);
|
|
45782
46229
|
const rotatedAt = deps.now().toISOString();
|
|
45783
46230
|
const homeDir = deps.olamHomeDir();
|
|
45784
|
-
const worldDir =
|
|
46231
|
+
const worldDir = path94.join(homeDir, "worlds", worldId);
|
|
45785
46232
|
fs94.mkdirSync(worldDir, { recursive: true });
|
|
45786
|
-
const credentialsPath =
|
|
46233
|
+
const credentialsPath = path94.join(worldDir, "credentials.json");
|
|
45787
46234
|
const payload = {
|
|
45788
46235
|
worldRoleName,
|
|
45789
46236
|
password,
|
|
@@ -45858,12 +46305,12 @@ function registerRekey(program2) {
|
|
|
45858
46305
|
|
|
45859
46306
|
// src/pleri-config.ts
|
|
45860
46307
|
import * as fs95 from "node:fs";
|
|
45861
|
-
import * as
|
|
46308
|
+
import * as path95 from "node:path";
|
|
45862
46309
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
45863
46310
|
if (process.env.PLERI_BASE_URL) {
|
|
45864
46311
|
return true;
|
|
45865
46312
|
}
|
|
45866
|
-
const configPath =
|
|
46313
|
+
const configPath = path95.join(configDir, "config.yaml");
|
|
45867
46314
|
if (!fs95.existsSync(configPath)) {
|
|
45868
46315
|
return false;
|
|
45869
46316
|
}
|
|
@@ -45902,6 +46349,7 @@ registerDestroy(program);
|
|
|
45902
46349
|
registerClean(program);
|
|
45903
46350
|
registerImplode(program);
|
|
45904
46351
|
registerEnter(program);
|
|
46352
|
+
registerResume(program);
|
|
45905
46353
|
registerCrystallize(program, { hidden: !isPleriConfigured() });
|
|
45906
46354
|
registerPr(program);
|
|
45907
46355
|
registerWorkspace(program);
|