@pleri/olam-cli 0.1.161 → 0.1.162
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 +4 -4
- package/dist/agent-stream/agent-sdk-to-chunks.js +20 -2
- package/dist/commands/bootstrap.d.ts.map +1 -1
- package/dist/commands/bootstrap.js +35 -11
- package/dist/commands/bootstrap.js.map +1 -1
- package/dist/commands/flywheel/migrate-overlays.d.ts +1 -0
- package/dist/commands/flywheel/migrate-overlays.d.ts.map +1 -1
- package/dist/commands/flywheel/migrate-overlays.js +29 -3
- package/dist/commands/flywheel/migrate-overlays.js.map +1 -1
- package/dist/commands/skills-source.d.ts.map +1 -1
- package/dist/commands/skills-source.js +57 -2
- package/dist/commands/skills-source.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +14 -0
- package/dist/commands/skills.js.map +1 -1
- package/dist/image-digests.json +7 -7
- package/dist/index.js +996 -618
- package/dist/lib/bootstrap-kubernetes.d.ts.map +1 -1
- package/dist/lib/bootstrap-kubernetes.js +93 -13
- package/dist/lib/bootstrap-kubernetes.js.map +1 -1
- package/dist/mcp-server.js +568 -368
- package/hermes-bundle/version.json +1 -1
- package/host-cp/k8s/manifests/50-deployment.yaml +1 -1
- 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/observability/grafana-port-forward.sh +12 -2
- package/host-cp/observability/kyverno-cardinality-mutate.sh +12 -2
- package/host-cp/observability/loki-ingest.sh +12 -2
- package/host-cp/observability/prom-no-double-grafana.sh +15 -5
- package/host-cp/peripheral-services/helm-values/grafana-values.yaml +159 -0
- package/host-cp/peripheral-services/helm-values/kube-prom-stack-values.yaml +229 -0
- package/host-cp/peripheral-services/helm-values/kyverno-values.yaml +85 -0
- package/host-cp/peripheral-services/helm-values/loki-values.yaml +166 -0
- package/host-cp/peripheral-services/helm-values/promtail-staging.yaml +92 -0
- package/host-cp/peripheral-services/helm-values/promtail-values.yaml +102 -0
- package/host-cp/peripheral-services/helm-values/traefik-values.yaml +73 -0
- package/host-cp/peripheral-services/manifests/20-namespace.yaml +6 -0
- package/host-cp/peripheral-services/manifests/24-deploy-kg-service.yaml +245 -0
- package/host-cp/peripheral-services/manifests/30-traefik-ingressroute-host-cp.yaml +22 -0
- package/host-cp/peripheral-services/manifests/40-traefik-ingressroute-kg.yaml +29 -0
- package/host-cp/peripheral-services/manifests/50-traefik-ingressroute-agent-memory.yaml +29 -0
- package/host-cp/peripheral-services/manifests/60-networkpolicy-ingress.yaml +80 -0
- package/host-cp/peripheral-services/manifests/65-networkpolicy-loki-prom-deny.yaml +67 -0
- package/host-cp/peripheral-services/manifests/80-grafana-dashboard-configmap.yaml +1349 -0
- package/host-cp/peripheral-services/manifests/90-prom-alert-cardinality.yaml +50 -0
- package/host-cp/peripheral-services/manifests/91-servicemonitor-host-cp.yaml +70 -0
- package/host-cp/peripheral-services/manifests/92-servicemonitor-kg-service.yaml +70 -0
- package/host-cp/peripheral-services/manifests/93-servicemonitor-memory-service.yaml +87 -0
- package/host-cp/peripheral-services/manifests/95-prom-recording-rules.yaml +108 -0
- package/host-cp/peripheral-services/manifests/96-kyverno-cardinality-mutate.yaml +195 -0
- package/host-cp/src/plan-chat-service.mjs +147 -1
- 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: path94, errorMaps, issueData } = params;
|
|
496
|
+
const fullPath = [...path94, ...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, path94, key) {
|
|
805
805
|
this._cachedPath = [];
|
|
806
806
|
this.parent = parent;
|
|
807
807
|
this.data = value;
|
|
808
|
-
this._path =
|
|
808
|
+
this._path = path94;
|
|
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, path94, 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, path93, ctx, rejectSource) {
|
|
|
4294
4294
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
4295
4295
|
ctx.addIssue({
|
|
4296
4296
|
code: external_exports.ZodIssueCode.custom,
|
|
4297
|
-
path: [...
|
|
4297
|
+
path: [...path94, key],
|
|
4298
4298
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
4299
4299
|
});
|
|
4300
4300
|
continue;
|
|
4301
4301
|
}
|
|
4302
|
-
if (rejectSource &&
|
|
4302
|
+
if (rejectSource && path94.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, path93, ctx, rejectSource) {
|
|
|
4307
4307
|
});
|
|
4308
4308
|
continue;
|
|
4309
4309
|
}
|
|
4310
|
-
refineForbiddenKeys(value[key], [...
|
|
4310
|
+
refineForbiddenKeys(value[key], [...path94, key], ctx, false);
|
|
4311
4311
|
}
|
|
4312
4312
|
}
|
|
4313
|
-
function rejectForbiddenKeys(value,
|
|
4313
|
+
function rejectForbiddenKeys(value, path94, 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] ${path94}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
4320
4320
|
}
|
|
4321
4321
|
if (rejectSource && key === "source") {
|
|
4322
|
-
throw new Error(`[manifest] ${
|
|
4322
|
+
throw new Error(`[manifest] ${path94}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
4323
4323
|
}
|
|
4324
|
-
rejectForbiddenKeys(value[key], `${
|
|
4324
|
+
rejectForbiddenKeys(value[key], `${path94}.${key}`, false);
|
|
4325
4325
|
}
|
|
4326
4326
|
}
|
|
4327
4327
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -5500,8 +5500,8 @@ var init_client = __esm({
|
|
|
5500
5500
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
5501
5501
|
}
|
|
5502
5502
|
}
|
|
5503
|
-
async request(method,
|
|
5504
|
-
const url2 = `${this.baseUrl}${
|
|
5503
|
+
async request(method, path94, body, attempt = 0) {
|
|
5504
|
+
const url2 = `${this.baseUrl}${path94}`;
|
|
5505
5505
|
const controller = new AbortController();
|
|
5506
5506
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
5507
5507
|
const headers = {};
|
|
@@ -5519,7 +5519,7 @@ var init_client = __esm({
|
|
|
5519
5519
|
} catch (err) {
|
|
5520
5520
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
5521
5521
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
5522
|
-
return this.request(method,
|
|
5522
|
+
return this.request(method, path94, body, attempt + 1);
|
|
5523
5523
|
}
|
|
5524
5524
|
throw err;
|
|
5525
5525
|
} finally {
|
|
@@ -7322,8 +7322,8 @@ var init_provider3 = __esm({
|
|
|
7322
7322
|
// -----------------------------------------------------------------------
|
|
7323
7323
|
// Internal fetch helper
|
|
7324
7324
|
// -----------------------------------------------------------------------
|
|
7325
|
-
async request(
|
|
7326
|
-
const url2 = `${this.config.workerUrl}${
|
|
7325
|
+
async request(path94, method, body) {
|
|
7326
|
+
const url2 = `${this.config.workerUrl}${path94}`;
|
|
7327
7327
|
const bearer = await this.config.mintToken();
|
|
7328
7328
|
const headers = {
|
|
7329
7329
|
Authorization: `Bearer ${bearer}`
|
|
@@ -9092,17 +9092,17 @@ function kgRoot() {
|
|
|
9092
9092
|
function worldsRoot() {
|
|
9093
9093
|
return join17(olamHome(), "worlds");
|
|
9094
9094
|
}
|
|
9095
|
-
function assertWithinPrefix(
|
|
9096
|
-
if (!
|
|
9097
|
-
throw new Error(`${label} escape: ${
|
|
9095
|
+
function assertWithinPrefix(path94, prefix, label) {
|
|
9096
|
+
if (!path94.startsWith(prefix + "/")) {
|
|
9097
|
+
throw new Error(`${label} escape: ${path94} not under ${prefix}/`);
|
|
9098
9098
|
}
|
|
9099
9099
|
}
|
|
9100
9100
|
function kgPristinePath(workspace) {
|
|
9101
9101
|
validateWorkspaceName(workspace);
|
|
9102
9102
|
const root = kgRoot();
|
|
9103
|
-
const
|
|
9104
|
-
assertWithinPrefix(
|
|
9105
|
-
return
|
|
9103
|
+
const path94 = resolve6(join17(root, workspace));
|
|
9104
|
+
assertWithinPrefix(path94, root, "kgPristinePath");
|
|
9105
|
+
return path94;
|
|
9106
9106
|
}
|
|
9107
9107
|
var KG_PATHS_INTERNALS;
|
|
9108
9108
|
var init_storage_paths = __esm({
|
|
@@ -11042,7 +11042,7 @@ var init_auto_dispatch_task = __esm({
|
|
|
11042
11042
|
});
|
|
11043
11043
|
|
|
11044
11044
|
// ../core/dist/skill-sources/schema.js
|
|
11045
|
-
var SKILL_SOURCE_ID_LENGTH, NAME_PATTERN, URL_PATTERN, SkillSourceSchema;
|
|
11045
|
+
var SKILL_SOURCE_ID_LENGTH, NAME_PATTERN, URL_PATTERN, PREFIX_PATTERN, SkillSourceSchema;
|
|
11046
11046
|
var init_schema3 = __esm({
|
|
11047
11047
|
"../core/dist/skill-sources/schema.js"() {
|
|
11048
11048
|
"use strict";
|
|
@@ -11050,13 +11050,24 @@ var init_schema3 = __esm({
|
|
|
11050
11050
|
SKILL_SOURCE_ID_LENGTH = 12;
|
|
11051
11051
|
NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
11052
11052
|
URL_PATTERN = /^(?:https?:\/\/|git@|ssh:\/\/|file:\/\/|\/).+/;
|
|
11053
|
+
PREFIX_PATTERN = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
11053
11054
|
SkillSourceSchema = external_exports.object({
|
|
11054
11055
|
id: external_exports.string().length(SKILL_SOURCE_ID_LENGTH, `skill-source id must be exactly ${SKILL_SOURCE_ID_LENGTH} chars (sha256-of-url prefix)`).regex(/^[a-f0-9]+$/, "skill-source id must be lowercase hex"),
|
|
11055
11056
|
name: external_exports.string().regex(NAME_PATTERN, "skill-source name must be ASCII lowercase + digits + dash (1-64 chars, no leading/trailing dash)"),
|
|
11056
11057
|
gitUrl: external_exports.string().min(1, "gitUrl must not be empty").regex(URL_PATTERN, "gitUrl must look like a git URL (https://, git@, ssh://, file://, or absolute path)"),
|
|
11057
11058
|
branch: external_exports.string().min(1, "branch must not be empty").default("main"),
|
|
11058
11059
|
addedAt: external_exports.number().int().nonnegative(),
|
|
11059
|
-
lastPulledSha: external_exports.string().regex(/^[a-f0-9]{40}$/, "lastPulledSha must be a 40-char lowercase hex git SHA").optional()
|
|
11060
|
+
lastPulledSha: external_exports.string().regex(/^[a-f0-9]{40}$/, "lastPulledSha must be a 40-char lowercase hex git SHA").optional(),
|
|
11061
|
+
/**
|
|
11062
|
+
* Optional rename prefix. When set, skills+agents from this source are
|
|
11063
|
+
* deployed under `<prefix>:<canonical-name>` (both filename + frontmatter
|
|
11064
|
+
* `name:` rewritten). Source clone + atlas-toolbox member overlays remain
|
|
11065
|
+
* canonical-named on disk; the rename is purely a deploy-time view.
|
|
11066
|
+
* Operator overlay files (`~/.claude/{skills,agents}.overrides/`) MUST
|
|
11067
|
+
* use canonical names; `olam flywheel migrate-overlays --push` enforces
|
|
11068
|
+
* this via the reverse validator.
|
|
11069
|
+
*/
|
|
11070
|
+
prefix: external_exports.string().regex(PREFIX_PATTERN, "skill-source prefix must be ASCII lowercase + digits + dash/underscore (1-39 chars, no leading/trailing dash)").optional()
|
|
11060
11071
|
});
|
|
11061
11072
|
}
|
|
11062
11073
|
});
|
|
@@ -15613,10 +15624,10 @@ async function readHostCpToken2() {
|
|
|
15613
15624
|
if (!fs26.existsSync(tp)) return null;
|
|
15614
15625
|
return fs26.readFileSync(tp, "utf-8").trim();
|
|
15615
15626
|
}
|
|
15616
|
-
async function callHostCpProxy(method, worldId,
|
|
15627
|
+
async function callHostCpProxy(method, worldId, path94, body) {
|
|
15617
15628
|
const token = await readHostCpToken2();
|
|
15618
15629
|
if (!token) return { ok: false, status: 0, error: "no token (host CP not started)" };
|
|
15619
|
-
const url2 = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${
|
|
15630
|
+
const url2 = `http://127.0.0.1:${HOST_CP_PORT}/api/world/${encodeURIComponent(worldId)}${path94}`;
|
|
15620
15631
|
try {
|
|
15621
15632
|
const headers = {
|
|
15622
15633
|
Authorization: `Bearer ${token}`
|
|
@@ -16282,7 +16293,8 @@ var init_trust_audit_log = __esm({
|
|
|
16282
16293
|
"removed",
|
|
16283
16294
|
"meta-hook-stripped",
|
|
16284
16295
|
"setup-skill-source-picked",
|
|
16285
|
-
"setup-project-sweep-completed"
|
|
16296
|
+
"setup-project-sweep-completed",
|
|
16297
|
+
"prefix-collision"
|
|
16286
16298
|
]);
|
|
16287
16299
|
TrustMethodSchema = external_exports.enum(["flag", "interactive", "auto-reject-tty", "none"]);
|
|
16288
16300
|
TrustAuditEntrySchema = external_exports.object({
|
|
@@ -16395,24 +16407,49 @@ function updateSkillSource(id, patch) {
|
|
|
16395
16407
|
throw new Error(`skill-source name "${patch.name}" already in use by id "${collision.id}".`);
|
|
16396
16408
|
}
|
|
16397
16409
|
}
|
|
16410
|
+
if (patch.prefix !== void 0 && patch.prefix !== null) {
|
|
16411
|
+
if (!PREFIX_PATTERN2.test(patch.prefix)) {
|
|
16412
|
+
throw new Error(`prefix must match /^[a-z0-9][a-z0-9_-]{0,38}$/ \u2014 got "${patch.prefix}"`);
|
|
16413
|
+
}
|
|
16414
|
+
}
|
|
16398
16415
|
const existing = config.skillSources[idx];
|
|
16416
|
+
let prefixUpdate = {};
|
|
16417
|
+
if (patch.prefix === null) {
|
|
16418
|
+
const { prefix: _dropped, ...rest } = existing;
|
|
16419
|
+
void _dropped;
|
|
16420
|
+
const updated2 = {
|
|
16421
|
+
...rest,
|
|
16422
|
+
...patch.name !== void 0 ? { name: patch.name } : {},
|
|
16423
|
+
...patch.branch !== void 0 ? { branch: patch.branch } : {},
|
|
16424
|
+
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
16425
|
+
};
|
|
16426
|
+
const next2 = [...config.skillSources];
|
|
16427
|
+
next2[idx] = updated2;
|
|
16428
|
+
writeGlobalConfig({ ...config, skillSources: next2 });
|
|
16429
|
+
return updated2;
|
|
16430
|
+
} else if (patch.prefix !== void 0) {
|
|
16431
|
+
prefixUpdate = { prefix: patch.prefix };
|
|
16432
|
+
}
|
|
16399
16433
|
const updated = {
|
|
16400
16434
|
...existing,
|
|
16401
16435
|
...patch.name !== void 0 ? { name: patch.name } : {},
|
|
16402
16436
|
...patch.branch !== void 0 ? { branch: patch.branch } : {},
|
|
16403
|
-
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
16437
|
+
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {},
|
|
16438
|
+
...prefixUpdate
|
|
16404
16439
|
};
|
|
16405
16440
|
const next = [...config.skillSources];
|
|
16406
16441
|
next[idx] = updated;
|
|
16407
16442
|
writeGlobalConfig({ ...config, skillSources: next });
|
|
16408
16443
|
return updated;
|
|
16409
16444
|
}
|
|
16445
|
+
var PREFIX_PATTERN2;
|
|
16410
16446
|
var init_store3 = __esm({
|
|
16411
16447
|
"../core/dist/skill-sources/store.js"() {
|
|
16412
16448
|
"use strict";
|
|
16413
16449
|
init_store2();
|
|
16414
16450
|
init_schema3();
|
|
16415
16451
|
init_trust_audit_log();
|
|
16452
|
+
PREFIX_PATTERN2 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
16416
16453
|
}
|
|
16417
16454
|
});
|
|
16418
16455
|
|
|
@@ -18739,17 +18776,195 @@ var init_managed_merge = __esm({
|
|
|
18739
18776
|
}
|
|
18740
18777
|
});
|
|
18741
18778
|
|
|
18742
|
-
// ../core/dist/skill-sync/
|
|
18779
|
+
// ../core/dist/skill-sync/prefix-rules.js
|
|
18780
|
+
function applyPrefix(name, prefix, otherKnownPrefixes = []) {
|
|
18781
|
+
if (prefix.length === 0) {
|
|
18782
|
+
throw new Error("applyPrefix: prefix must be non-empty");
|
|
18783
|
+
}
|
|
18784
|
+
if (prefix.includes(":")) {
|
|
18785
|
+
throw new Error(`applyPrefix: prefix must not contain ':' (got "${prefix}")`);
|
|
18786
|
+
}
|
|
18787
|
+
if (name.startsWith(`${prefix}:`))
|
|
18788
|
+
return name;
|
|
18789
|
+
for (const other of otherKnownPrefixes) {
|
|
18790
|
+
if (other.length > 0 && name.startsWith(`${other}:`))
|
|
18791
|
+
return name;
|
|
18792
|
+
}
|
|
18793
|
+
return `${prefix}:${name}`;
|
|
18794
|
+
}
|
|
18795
|
+
function rewriteFrontmatterName(content, rewriter) {
|
|
18796
|
+
const text = content.toString("utf-8");
|
|
18797
|
+
const parsed = parseFrontmatter3(text);
|
|
18798
|
+
if (Object.keys(parsed.fm).length === 0)
|
|
18799
|
+
return content;
|
|
18800
|
+
const currentName = parsed.fm["name"];
|
|
18801
|
+
if (currentName === void 0)
|
|
18802
|
+
return content;
|
|
18803
|
+
const newName = rewriter(currentName);
|
|
18804
|
+
if (newName === currentName)
|
|
18805
|
+
return content;
|
|
18806
|
+
const nextFm = { ...parsed.fm, name: newName };
|
|
18807
|
+
const rebuilt = serializeFrontmatter(nextFm) + parsed.body;
|
|
18808
|
+
return Buffer.from(rebuilt, "utf-8");
|
|
18809
|
+
}
|
|
18810
|
+
function validateCanonical(filenameBasename, content, registeredPrefixes) {
|
|
18811
|
+
if (registeredPrefixes.length === 0)
|
|
18812
|
+
return { ok: true };
|
|
18813
|
+
const bareName = filenameBasename.replace(/\.md$/, "");
|
|
18814
|
+
for (const prefix of registeredPrefixes) {
|
|
18815
|
+
if (prefix.length === 0)
|
|
18816
|
+
continue;
|
|
18817
|
+
if (bareName.startsWith(`${prefix}:`)) {
|
|
18818
|
+
return {
|
|
18819
|
+
ok: false,
|
|
18820
|
+
violation: { kind: "filename", prefix, value: filenameBasename }
|
|
18821
|
+
};
|
|
18822
|
+
}
|
|
18823
|
+
}
|
|
18824
|
+
const text = content.toString("utf-8");
|
|
18825
|
+
const parsed = parseFrontmatter3(text);
|
|
18826
|
+
const fmName = parsed.fm["name"];
|
|
18827
|
+
if (fmName === void 0)
|
|
18828
|
+
return { ok: true };
|
|
18829
|
+
for (const prefix of registeredPrefixes) {
|
|
18830
|
+
if (prefix.length === 0)
|
|
18831
|
+
continue;
|
|
18832
|
+
if (fmName.startsWith(`${prefix}:`)) {
|
|
18833
|
+
return {
|
|
18834
|
+
ok: false,
|
|
18835
|
+
violation: { kind: "frontmatter", prefix, value: fmName }
|
|
18836
|
+
};
|
|
18837
|
+
}
|
|
18838
|
+
}
|
|
18839
|
+
return { ok: true };
|
|
18840
|
+
}
|
|
18841
|
+
function formatCanonicalViolation(filePath, violation) {
|
|
18842
|
+
const surface = violation.kind === "filename" ? "filename" : "frontmatter `name:` field";
|
|
18843
|
+
const stripped = violation.value.replace(new RegExp(`^${violation.prefix}:`), "");
|
|
18844
|
+
return [
|
|
18845
|
+
`overlay ${filePath} carries registered prefix "${violation.prefix}:" in its ${surface} ("${violation.value}").`,
|
|
18846
|
+
`Overlays MUST use canonical names \u2014 renaming is a deploy-time view, not a content rewrite.`,
|
|
18847
|
+
`Fix: rename to "${stripped}" (also strip from frontmatter name: if present).`,
|
|
18848
|
+
`See docs/plans/skill-prefix-rules/README.md \xA7 Bidirectional invariant.`
|
|
18849
|
+
].join("\n ");
|
|
18850
|
+
}
|
|
18851
|
+
var init_prefix_rules = __esm({
|
|
18852
|
+
"../core/dist/skill-sync/prefix-rules.js"() {
|
|
18853
|
+
"use strict";
|
|
18854
|
+
init_markdown_merger();
|
|
18855
|
+
}
|
|
18856
|
+
});
|
|
18857
|
+
|
|
18858
|
+
// ../core/dist/skill-sync/prefix-deploy.js
|
|
18743
18859
|
import * as fs68 from "node:fs";
|
|
18744
|
-
import * as os36 from "node:os";
|
|
18745
18860
|
import * as path67 from "node:path";
|
|
18861
|
+
function buildSourcePrefixMap(sources) {
|
|
18862
|
+
const byId = /* @__PURE__ */ new Map();
|
|
18863
|
+
const prefixes = /* @__PURE__ */ new Set();
|
|
18864
|
+
for (const s of sources) {
|
|
18865
|
+
if (s.prefix !== void 0 && s.prefix.length > 0) {
|
|
18866
|
+
byId.set(s.id, s.prefix);
|
|
18867
|
+
prefixes.add(s.prefix);
|
|
18868
|
+
}
|
|
18869
|
+
}
|
|
18870
|
+
return {
|
|
18871
|
+
get: (sourceId) => byId.get(sourceId),
|
|
18872
|
+
registeredPrefixes: Array.from(prefixes)
|
|
18873
|
+
};
|
|
18874
|
+
}
|
|
18875
|
+
function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
18876
|
+
const result = { rewrittenCount: 0, entries: [] };
|
|
18877
|
+
for (const artifact of baseArtifacts) {
|
|
18878
|
+
if (artifact.kind !== "skill" && artifact.kind !== "agent")
|
|
18879
|
+
continue;
|
|
18880
|
+
const prefix = sourceMap.get(artifact.sourceId);
|
|
18881
|
+
if (prefix === void 0)
|
|
18882
|
+
continue;
|
|
18883
|
+
const canonical = artifact.deployBasename;
|
|
18884
|
+
const otherPrefixes = sourceMap.registeredPrefixes.filter((p) => p !== prefix);
|
|
18885
|
+
const renamed = applyPrefix(canonical, prefix, otherPrefixes);
|
|
18886
|
+
if (renamed === canonical)
|
|
18887
|
+
continue;
|
|
18888
|
+
const renamedFrontmatterName = renamed.replace(/\.md$/, "");
|
|
18889
|
+
if (dryRun) {
|
|
18890
|
+
artifact.deployBasename = renamed;
|
|
18891
|
+
result.rewrittenCount += 1;
|
|
18892
|
+
result.entries.push({
|
|
18893
|
+
sourceId: artifact.sourceId,
|
|
18894
|
+
kind: artifact.kind,
|
|
18895
|
+
canonicalBasename: canonical,
|
|
18896
|
+
renamedBasename: renamed,
|
|
18897
|
+
prefix
|
|
18898
|
+
});
|
|
18899
|
+
continue;
|
|
18900
|
+
}
|
|
18901
|
+
if (artifact.kind === "skill") {
|
|
18902
|
+
const skillMdPath = path67.join(artifact.sourcePath, "SKILL.md");
|
|
18903
|
+
const content = fs68.readFileSync(skillMdPath);
|
|
18904
|
+
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
18905
|
+
const managedDir = materializeMergedSkill({
|
|
18906
|
+
sourceId: artifact.sourceId,
|
|
18907
|
+
sourcePath: artifact.sourcePath,
|
|
18908
|
+
deployBasename: renamed,
|
|
18909
|
+
mergedContent: rewritten,
|
|
18910
|
+
claudeDir: claudeDir2
|
|
18911
|
+
});
|
|
18912
|
+
artifact.sourcePath = managedDir;
|
|
18913
|
+
artifact.deployBasename = renamed;
|
|
18914
|
+
} else {
|
|
18915
|
+
const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs68.readFileSync(artifact.sourcePath);
|
|
18916
|
+
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
18917
|
+
artifact.resolvedContent = rewritten;
|
|
18918
|
+
artifact.deployBasename = renamed;
|
|
18919
|
+
}
|
|
18920
|
+
result.rewrittenCount += 1;
|
|
18921
|
+
result.entries.push({
|
|
18922
|
+
sourceId: artifact.sourceId,
|
|
18923
|
+
kind: artifact.kind,
|
|
18924
|
+
canonicalBasename: canonical,
|
|
18925
|
+
renamedBasename: renamed,
|
|
18926
|
+
prefix
|
|
18927
|
+
});
|
|
18928
|
+
}
|
|
18929
|
+
return result;
|
|
18930
|
+
}
|
|
18931
|
+
function detectPrefixCollisions(sources) {
|
|
18932
|
+
const byPrefix = /* @__PURE__ */ new Map();
|
|
18933
|
+
for (const s of sources) {
|
|
18934
|
+
if (s.prefix === void 0 || s.prefix.length === 0)
|
|
18935
|
+
continue;
|
|
18936
|
+
const ids = byPrefix.get(s.prefix) ?? [];
|
|
18937
|
+
ids.push(s.id);
|
|
18938
|
+
byPrefix.set(s.prefix, ids);
|
|
18939
|
+
}
|
|
18940
|
+
const collisions = [];
|
|
18941
|
+
for (const [prefix, ids] of byPrefix.entries()) {
|
|
18942
|
+
if (ids.length < 2)
|
|
18943
|
+
continue;
|
|
18944
|
+
const [winner, ...losers] = ids;
|
|
18945
|
+
collisions.push({ prefix, winnerSourceId: winner, loserSourceIds: losers });
|
|
18946
|
+
}
|
|
18947
|
+
return collisions;
|
|
18948
|
+
}
|
|
18949
|
+
var init_prefix_deploy = __esm({
|
|
18950
|
+
"../core/dist/skill-sync/prefix-deploy.js"() {
|
|
18951
|
+
"use strict";
|
|
18952
|
+
init_prefix_rules();
|
|
18953
|
+
init_managed_merge();
|
|
18954
|
+
}
|
|
18955
|
+
});
|
|
18956
|
+
|
|
18957
|
+
// ../core/dist/skill-sync/engine.js
|
|
18958
|
+
import * as fs69 from "node:fs";
|
|
18959
|
+
import * as os36 from "node:os";
|
|
18960
|
+
import * as path68 from "node:path";
|
|
18746
18961
|
function resolveAtlasUser(override) {
|
|
18747
18962
|
if (override)
|
|
18748
18963
|
return override;
|
|
18749
|
-
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] ||
|
|
18750
|
-
const f =
|
|
18751
|
-
if (
|
|
18752
|
-
return
|
|
18964
|
+
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path68.join(os36.homedir(), ".claude");
|
|
18965
|
+
const f = path68.join(claudeDir2, ".atlas-user");
|
|
18966
|
+
if (fs69.existsSync(f)) {
|
|
18967
|
+
return fs69.readFileSync(f, "utf-8").trim() || void 0;
|
|
18753
18968
|
}
|
|
18754
18969
|
return void 0;
|
|
18755
18970
|
}
|
|
@@ -18761,7 +18976,7 @@ async function syncSkills(opts = {}) {
|
|
|
18761
18976
|
const perSource = [];
|
|
18762
18977
|
for (const source of sources) {
|
|
18763
18978
|
const clonePath = skillSourceClonePath(source.id);
|
|
18764
|
-
if (!
|
|
18979
|
+
if (!fs69.existsSync(clonePath))
|
|
18765
18980
|
continue;
|
|
18766
18981
|
const { artifacts, subscription } = await withFileLock(clonePath, () => {
|
|
18767
18982
|
const pinRef = projectOverride?.override.pin?.[source.id];
|
|
@@ -18799,9 +19014,15 @@ async function syncSkills(opts = {}) {
|
|
|
18799
19014
|
const memberOverlaysEnabled = process.env["OLAM_MEMBER_OVERLAYS"] === "1";
|
|
18800
19015
|
const baseArtifacts = projectFilteredArtifacts.filter((a) => a.kind !== "overlay");
|
|
18801
19016
|
const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
|
|
18802
|
-
|
|
19017
|
+
const sourcePrefixMap = buildSourcePrefixMap(sources);
|
|
19018
|
+
const hasPrefixRewrites = sources.some((s) => s.prefix !== void 0 && s.prefix.length > 0);
|
|
19019
|
+
const willMutateManagedDir = !opts.dryRun && (memberOverlaysEnabled && overlayArtifacts.length > 0 || hasPrefixRewrites);
|
|
19020
|
+
if (willMutateManagedDir) {
|
|
18803
19021
|
const claude = claudeDir();
|
|
18804
19022
|
cleanMergedDir(claude);
|
|
19023
|
+
}
|
|
19024
|
+
if (memberOverlaysEnabled && overlayArtifacts.length > 0 && !opts.dryRun) {
|
|
19025
|
+
const claude = claudeDir();
|
|
18805
19026
|
for (const overlay of overlayArtifacts) {
|
|
18806
19027
|
if (!overlay.targetKind)
|
|
18807
19028
|
continue;
|
|
@@ -18811,13 +19032,13 @@ async function syncSkills(opts = {}) {
|
|
|
18811
19032
|
let baseContent;
|
|
18812
19033
|
let basePath;
|
|
18813
19034
|
if (overlay.targetKind === "skill") {
|
|
18814
|
-
basePath =
|
|
18815
|
-
baseContent =
|
|
19035
|
+
basePath = path68.join(base.sourcePath, "SKILL.md");
|
|
19036
|
+
baseContent = fs69.readFileSync(basePath, "utf-8");
|
|
18816
19037
|
} else {
|
|
18817
19038
|
basePath = base.sourcePath;
|
|
18818
|
-
baseContent =
|
|
19039
|
+
baseContent = fs69.readFileSync(basePath, "utf-8");
|
|
18819
19040
|
}
|
|
18820
|
-
const overlayContent =
|
|
19041
|
+
const overlayContent = fs69.readFileSync(overlay.sourcePath, "utf-8");
|
|
18821
19042
|
const label = `${overlay.sourceId}/${overlay.deployBasename}`;
|
|
18822
19043
|
const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
|
|
18823
19044
|
if ("error" in mergeResult) {
|
|
@@ -18841,6 +19062,23 @@ async function syncSkills(opts = {}) {
|
|
|
18841
19062
|
}
|
|
18842
19063
|
const hookFiles = projectFilteredArtifacts.filter((a) => a.kind === "hook").map((a) => a.sourcePath);
|
|
18843
19064
|
const permissionFiles = projectFilteredArtifacts.filter((a) => a.kind === "permission").map((a) => a.sourcePath);
|
|
19065
|
+
const claudeDirForRewrites = claudeDir();
|
|
19066
|
+
const prefixRewriteResult = applyPrefixRewrites(baseArtifacts, sourcePrefixMap, claudeDirForRewrites, opts.dryRun === true);
|
|
19067
|
+
const prefixCollisions = detectPrefixCollisions(sources);
|
|
19068
|
+
if (!opts.dryRun) {
|
|
19069
|
+
for (const collision of prefixCollisions) {
|
|
19070
|
+
try {
|
|
19071
|
+
appendTrustAudit({
|
|
19072
|
+
gitUrl: "internal:prefix-collision",
|
|
19073
|
+
action: "prefix-collision",
|
|
19074
|
+
trustMethod: "none",
|
|
19075
|
+
sourceId: collision.winnerSourceId,
|
|
19076
|
+
note: `prefix="${collision.prefix}"; winner=${collision.winnerSourceId}; losers=${collision.loserSourceIds.join(",")}`
|
|
19077
|
+
});
|
|
19078
|
+
} catch {
|
|
19079
|
+
}
|
|
19080
|
+
}
|
|
19081
|
+
}
|
|
18844
19082
|
const summary2 = {
|
|
18845
19083
|
sourceCount: sources.length,
|
|
18846
19084
|
artifactCount: projectFilteredArtifacts.length,
|
|
@@ -18851,13 +19089,15 @@ async function syncSkills(opts = {}) {
|
|
|
18851
19089
|
deploy: void 0,
|
|
18852
19090
|
merge: void 0,
|
|
18853
19091
|
metaHooks: void 0,
|
|
18854
|
-
perSource
|
|
19092
|
+
perSource,
|
|
19093
|
+
prefixRewrites: prefixRewriteResult.entries,
|
|
19094
|
+
prefixCollisions
|
|
18855
19095
|
};
|
|
18856
19096
|
if (opts.dryRun) {
|
|
18857
19097
|
summary2.collisions = detectCollisions(baseArtifacts).collisions;
|
|
18858
19098
|
return summary2;
|
|
18859
19099
|
}
|
|
18860
|
-
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] ||
|
|
19100
|
+
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path68.join(os36.homedir(), ".claude");
|
|
18861
19101
|
const overlayReferences = scanOverlayReferences(claudeDirPath, SHIM_TARGETS.map((t) => t.basename));
|
|
18862
19102
|
summary2.deploy = deployArtifacts(baseArtifacts, {
|
|
18863
19103
|
installedOlamVersion,
|
|
@@ -18883,19 +19123,19 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
18883
19123
|
const result = await withSettingsJsonLock(() => {
|
|
18884
19124
|
let currentSettings = {};
|
|
18885
19125
|
let settingsExisted = false;
|
|
18886
|
-
if (
|
|
19126
|
+
if (fs69.existsSync(settingsFile)) {
|
|
18887
19127
|
settingsExisted = true;
|
|
18888
19128
|
try {
|
|
18889
|
-
const raw =
|
|
19129
|
+
const raw = fs69.readFileSync(settingsFile, "utf-8");
|
|
18890
19130
|
currentSettings = raw.trim() ? JSON.parse(raw) : {};
|
|
18891
19131
|
} catch {
|
|
18892
19132
|
try {
|
|
18893
|
-
const raw =
|
|
18894
|
-
const bakDir =
|
|
18895
|
-
|
|
19133
|
+
const raw = fs69.readFileSync(settingsFile);
|
|
19134
|
+
const bakDir = path68.join(path68.dirname(settingsFile), ".malformed-backups");
|
|
19135
|
+
fs69.mkdirSync(bakDir, { recursive: true });
|
|
18896
19136
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
18897
|
-
const bakFile =
|
|
18898
|
-
|
|
19137
|
+
const bakFile = path68.join(bakDir, `settings.json.malformed.${stamp}.bak`);
|
|
19138
|
+
fs69.writeFileSync(bakFile, raw, { mode: 384 });
|
|
18899
19139
|
snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
|
|
18900
19140
|
} catch (bakErr) {
|
|
18901
19141
|
snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
|
|
@@ -18945,10 +19185,10 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
18945
19185
|
} catch {
|
|
18946
19186
|
}
|
|
18947
19187
|
}
|
|
18948
|
-
|
|
19188
|
+
fs69.mkdirSync(path68.dirname(settingsFile), { recursive: true });
|
|
18949
19189
|
const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
|
|
18950
|
-
|
|
18951
|
-
|
|
19190
|
+
fs69.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
|
|
19191
|
+
fs69.renameSync(tmpPath, settingsFile);
|
|
18952
19192
|
return inject;
|
|
18953
19193
|
}, { reason: `syncSkills meta-hook injection (mode=${mode})` });
|
|
18954
19194
|
return {
|
|
@@ -18982,23 +19222,24 @@ var init_engine = __esm({
|
|
|
18982
19222
|
init_meta_hook_injector();
|
|
18983
19223
|
init_markdown_merger();
|
|
18984
19224
|
init_managed_merge();
|
|
19225
|
+
init_prefix_deploy();
|
|
18985
19226
|
}
|
|
18986
19227
|
});
|
|
18987
19228
|
|
|
18988
19229
|
// ../core/dist/skill-sync/shadow-backup-manager.js
|
|
18989
|
-
import * as
|
|
18990
|
-
import * as
|
|
19230
|
+
import * as fs70 from "node:fs";
|
|
19231
|
+
import * as path69 from "node:path";
|
|
18991
19232
|
function listShadowBackups(opts = {}) {
|
|
18992
19233
|
const claude = opts.claudeDirOverride ?? claudeDir();
|
|
18993
19234
|
const now = opts.now ?? Date.now();
|
|
18994
19235
|
const out = [];
|
|
18995
19236
|
for (const bucket of SHADOW_BACKUP_BUCKETS) {
|
|
18996
|
-
const bucketDir =
|
|
18997
|
-
if (!
|
|
19237
|
+
const bucketDir = path69.join(claude, bucket);
|
|
19238
|
+
if (!fs70.existsSync(bucketDir))
|
|
18998
19239
|
continue;
|
|
18999
19240
|
let entries;
|
|
19000
19241
|
try {
|
|
19001
|
-
entries =
|
|
19242
|
+
entries = fs70.readdirSync(bucketDir);
|
|
19002
19243
|
} catch {
|
|
19003
19244
|
continue;
|
|
19004
19245
|
}
|
|
@@ -19009,10 +19250,10 @@ function listShadowBackups(opts = {}) {
|
|
|
19009
19250
|
const epochSeconds = Number.parseInt(match2[1], 10);
|
|
19010
19251
|
if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
|
|
19011
19252
|
continue;
|
|
19012
|
-
const full =
|
|
19253
|
+
const full = path69.join(bucketDir, name);
|
|
19013
19254
|
let sizeBytes = 0;
|
|
19014
19255
|
try {
|
|
19015
|
-
const st =
|
|
19256
|
+
const st = fs70.statSync(full);
|
|
19016
19257
|
if (st.isDirectory())
|
|
19017
19258
|
continue;
|
|
19018
19259
|
sizeBytes = st.size;
|
|
@@ -19025,7 +19266,7 @@ function listShadowBackups(opts = {}) {
|
|
|
19025
19266
|
bucket,
|
|
19026
19267
|
basename: name,
|
|
19027
19268
|
originalBasename,
|
|
19028
|
-
originalPath:
|
|
19269
|
+
originalPath: path69.join(bucketDir, originalBasename),
|
|
19029
19270
|
epochSeconds,
|
|
19030
19271
|
ageMs: now - epochSeconds * 1e3,
|
|
19031
19272
|
sizeBytes
|
|
@@ -19068,7 +19309,7 @@ function pruneShadowBackups(opts) {
|
|
|
19068
19309
|
}
|
|
19069
19310
|
if (!opts.dryRun) {
|
|
19070
19311
|
try {
|
|
19071
|
-
|
|
19312
|
+
fs70.unlinkSync(b.path);
|
|
19072
19313
|
} catch {
|
|
19073
19314
|
skipped.push(b);
|
|
19074
19315
|
continue;
|
|
@@ -19079,24 +19320,24 @@ function pruneShadowBackups(opts) {
|
|
|
19079
19320
|
return { deleted, skipped };
|
|
19080
19321
|
}
|
|
19081
19322
|
function restoreShadowBackup(opts) {
|
|
19082
|
-
const abs =
|
|
19083
|
-
if (!
|
|
19323
|
+
const abs = path69.resolve(opts.backupPath);
|
|
19324
|
+
if (!fs70.existsSync(abs)) {
|
|
19084
19325
|
throw new Error(`backup file not found: ${abs}`);
|
|
19085
19326
|
}
|
|
19086
|
-
const basename16 =
|
|
19327
|
+
const basename16 = path69.basename(abs);
|
|
19087
19328
|
const match2 = SHADOW_BACKUP_SUFFIX_RE.exec(basename16);
|
|
19088
19329
|
if (!match2) {
|
|
19089
19330
|
throw new Error(`not a shadow-backup file (basename "${basename16}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
|
|
19090
19331
|
}
|
|
19091
19332
|
const originalBasename = basename16.slice(0, basename16.length - match2[0].length);
|
|
19092
|
-
const originalPath =
|
|
19093
|
-
if (
|
|
19333
|
+
const originalPath = path69.join(path69.dirname(abs), originalBasename);
|
|
19334
|
+
if (fs70.existsSync(originalPath) && !opts.force) {
|
|
19094
19335
|
throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
|
|
19095
19336
|
}
|
|
19096
|
-
if (opts.force &&
|
|
19097
|
-
|
|
19337
|
+
if (opts.force && fs70.existsSync(originalPath)) {
|
|
19338
|
+
fs70.unlinkSync(originalPath);
|
|
19098
19339
|
}
|
|
19099
|
-
|
|
19340
|
+
fs70.renameSync(abs, originalPath);
|
|
19100
19341
|
return { restoredTo: originalPath };
|
|
19101
19342
|
}
|
|
19102
19343
|
var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
|
|
@@ -19110,12 +19351,12 @@ var init_shadow_backup_manager = __esm({
|
|
|
19110
19351
|
});
|
|
19111
19352
|
|
|
19112
19353
|
// ../core/dist/global-config/repos.js
|
|
19113
|
-
import * as
|
|
19354
|
+
import * as fs71 from "node:fs";
|
|
19114
19355
|
import * as os37 from "node:os";
|
|
19115
|
-
import * as
|
|
19356
|
+
import * as path70 from "node:path";
|
|
19116
19357
|
function expandPath(p) {
|
|
19117
19358
|
if (p === "~" || p.startsWith("~/")) {
|
|
19118
|
-
return
|
|
19359
|
+
return path70.join(os37.homedir(), p.slice(1));
|
|
19119
19360
|
}
|
|
19120
19361
|
return p;
|
|
19121
19362
|
}
|
|
@@ -19128,7 +19369,7 @@ function addRepo(entry) {
|
|
|
19128
19369
|
throw new Error(`repo "${entry.name}" already registered. Use "olam repos update" to change its path.`);
|
|
19129
19370
|
}
|
|
19130
19371
|
const resolvedPath = expandPath(entry.path);
|
|
19131
|
-
if (!
|
|
19372
|
+
if (!fs71.existsSync(resolvedPath)) {
|
|
19132
19373
|
throw new Error(`path "${entry.path}" does not exist. Verify the path is correct.`);
|
|
19133
19374
|
}
|
|
19134
19375
|
const now = Date.now();
|
|
@@ -19157,7 +19398,7 @@ function updateRepo(name, updates) {
|
|
|
19157
19398
|
throw new Error(`repo "${name}" is not registered. Run "olam repos list" to see registered repos.`);
|
|
19158
19399
|
}
|
|
19159
19400
|
const resolvedUpdatePath = updates.path !== void 0 ? expandPath(updates.path) : void 0;
|
|
19160
|
-
if (resolvedUpdatePath !== void 0 && !
|
|
19401
|
+
if (resolvedUpdatePath !== void 0 && !fs71.existsSync(resolvedUpdatePath)) {
|
|
19161
19402
|
throw new Error(`path "${updates.path}" does not exist. Verify the path is correct.`);
|
|
19162
19403
|
}
|
|
19163
19404
|
const existing = config.repos[idx];
|
|
@@ -19226,14 +19467,14 @@ var init_global_config = __esm({
|
|
|
19226
19467
|
});
|
|
19227
19468
|
|
|
19228
19469
|
// ../core/dist/skill-sources/doctor-checks.js
|
|
19229
|
-
import * as
|
|
19230
|
-
import * as
|
|
19470
|
+
import * as fs72 from "node:fs";
|
|
19471
|
+
import * as path71 from "node:path";
|
|
19231
19472
|
import * as os38 from "node:os";
|
|
19232
19473
|
function claudeDirInternal3() {
|
|
19233
19474
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
19234
19475
|
if (override && override.length > 0)
|
|
19235
19476
|
return override;
|
|
19236
|
-
return
|
|
19477
|
+
return path71.join(os38.homedir(), ".claude");
|
|
19237
19478
|
}
|
|
19238
19479
|
function checkStateFileParse() {
|
|
19239
19480
|
const filePath = globalConfigPath();
|
|
@@ -19242,11 +19483,11 @@ function checkStateFileParse() {
|
|
|
19242
19483
|
healthy: true,
|
|
19243
19484
|
description: `~/.olam state file (${filePath})`
|
|
19244
19485
|
};
|
|
19245
|
-
if (!
|
|
19486
|
+
if (!fs72.existsSync(filePath)) {
|
|
19246
19487
|
result.details = ["(file does not yet exist \u2014 will be created on first write)"];
|
|
19247
19488
|
return result;
|
|
19248
19489
|
}
|
|
19249
|
-
const raw =
|
|
19490
|
+
const raw = fs72.readFileSync(filePath, "utf-8");
|
|
19250
19491
|
let parsed;
|
|
19251
19492
|
try {
|
|
19252
19493
|
parsed = JSON.parse(raw);
|
|
@@ -19256,8 +19497,8 @@ function checkStateFileParse() {
|
|
|
19256
19497
|
result.details = [err instanceof Error ? err.message : String(err)];
|
|
19257
19498
|
result.repair = () => {
|
|
19258
19499
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
19259
|
-
|
|
19260
|
-
|
|
19500
|
+
fs72.renameSync(filePath, aside);
|
|
19501
|
+
fs72.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
|
|
19261
19502
|
};
|
|
19262
19503
|
return result;
|
|
19263
19504
|
}
|
|
@@ -19268,7 +19509,7 @@ function checkStateFileParse() {
|
|
|
19268
19509
|
result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
|
|
19269
19510
|
result.repair = () => {
|
|
19270
19511
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
19271
|
-
|
|
19512
|
+
fs72.copyFileSync(filePath, aside);
|
|
19272
19513
|
const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
19273
19514
|
const next = {
|
|
19274
19515
|
...base,
|
|
@@ -19277,7 +19518,7 @@ function checkStateFileParse() {
|
|
|
19277
19518
|
runbooks: [],
|
|
19278
19519
|
skillSources: []
|
|
19279
19520
|
};
|
|
19280
|
-
|
|
19521
|
+
fs72.writeFileSync(filePath, JSON.stringify(next, null, 2));
|
|
19281
19522
|
};
|
|
19282
19523
|
return result;
|
|
19283
19524
|
}
|
|
@@ -19288,16 +19529,16 @@ function checkDanglingSymlinks() {
|
|
|
19288
19529
|
const buckets = ["commands", "agents", "skills", "scripts", "rules"];
|
|
19289
19530
|
const dangling = [];
|
|
19290
19531
|
for (const bucket of buckets) {
|
|
19291
|
-
const dir =
|
|
19292
|
-
if (!
|
|
19532
|
+
const dir = path71.join(claude, bucket);
|
|
19533
|
+
if (!fs72.existsSync(dir))
|
|
19293
19534
|
continue;
|
|
19294
|
-
for (const name of
|
|
19295
|
-
const linkPath =
|
|
19535
|
+
for (const name of fs72.readdirSync(dir)) {
|
|
19536
|
+
const linkPath = path71.join(dir, name);
|
|
19296
19537
|
try {
|
|
19297
|
-
const lst =
|
|
19538
|
+
const lst = fs72.lstatSync(linkPath);
|
|
19298
19539
|
if (!lst.isSymbolicLink())
|
|
19299
19540
|
continue;
|
|
19300
|
-
if (!
|
|
19541
|
+
if (!fs72.existsSync(linkPath)) {
|
|
19301
19542
|
dangling.push(linkPath);
|
|
19302
19543
|
}
|
|
19303
19544
|
} catch {
|
|
@@ -19315,7 +19556,7 @@ function checkDanglingSymlinks() {
|
|
|
19315
19556
|
result.repair = () => {
|
|
19316
19557
|
for (const p of dangling) {
|
|
19317
19558
|
try {
|
|
19318
|
-
|
|
19559
|
+
fs72.unlinkSync(p);
|
|
19319
19560
|
} catch {
|
|
19320
19561
|
}
|
|
19321
19562
|
}
|
|
@@ -19330,19 +19571,19 @@ function checkOrphanedSnapshots() {
|
|
|
19330
19571
|
healthy: true,
|
|
19331
19572
|
description: `orphaned migration snapshots under ${dir}`
|
|
19332
19573
|
};
|
|
19333
|
-
if (!
|
|
19574
|
+
if (!fs72.existsSync(dir)) {
|
|
19334
19575
|
return result;
|
|
19335
19576
|
}
|
|
19336
19577
|
const orphans = [];
|
|
19337
|
-
for (const name of
|
|
19578
|
+
for (const name of fs72.readdirSync(dir)) {
|
|
19338
19579
|
if (!name.endsWith(".json"))
|
|
19339
19580
|
continue;
|
|
19340
|
-
const full =
|
|
19581
|
+
const full = path71.join(dir, name);
|
|
19341
19582
|
try {
|
|
19342
|
-
const stat =
|
|
19583
|
+
const stat = fs72.statSync(full);
|
|
19343
19584
|
if (!stat.isFile())
|
|
19344
19585
|
continue;
|
|
19345
|
-
const raw =
|
|
19586
|
+
const raw = fs72.readFileSync(full, "utf-8");
|
|
19346
19587
|
let parsed;
|
|
19347
19588
|
try {
|
|
19348
19589
|
parsed = JSON.parse(raw);
|
|
@@ -19367,7 +19608,7 @@ function checkOrphanedSnapshots() {
|
|
|
19367
19608
|
result.repair = () => {
|
|
19368
19609
|
for (const o of orphans) {
|
|
19369
19610
|
try {
|
|
19370
|
-
|
|
19611
|
+
fs72.unlinkSync(o.path);
|
|
19371
19612
|
} catch {
|
|
19372
19613
|
}
|
|
19373
19614
|
}
|
|
@@ -19382,12 +19623,12 @@ function checkSentinelDrift() {
|
|
|
19382
19623
|
healthy: true,
|
|
19383
19624
|
description: `olam-skills sentinel block in ${filePath}`
|
|
19384
19625
|
};
|
|
19385
|
-
if (!
|
|
19626
|
+
if (!fs72.existsSync(filePath)) {
|
|
19386
19627
|
return result;
|
|
19387
19628
|
}
|
|
19388
19629
|
let parsed;
|
|
19389
19630
|
try {
|
|
19390
|
-
parsed = JSON.parse(
|
|
19631
|
+
parsed = JSON.parse(fs72.readFileSync(filePath, "utf-8"));
|
|
19391
19632
|
} catch {
|
|
19392
19633
|
return result;
|
|
19393
19634
|
}
|
|
@@ -19428,7 +19669,7 @@ function checkSentinelDrift() {
|
|
|
19428
19669
|
backupSettings();
|
|
19429
19670
|
} catch {
|
|
19430
19671
|
}
|
|
19431
|
-
const next = JSON.parse(
|
|
19672
|
+
const next = JSON.parse(fs72.readFileSync(filePath, "utf-8"));
|
|
19432
19673
|
if (!next.hooks)
|
|
19433
19674
|
return;
|
|
19434
19675
|
for (const stage of Object.keys(next.hooks)) {
|
|
@@ -19451,7 +19692,7 @@ function checkSentinelDrift() {
|
|
|
19451
19692
|
return bad === void 0;
|
|
19452
19693
|
});
|
|
19453
19694
|
}
|
|
19454
|
-
|
|
19695
|
+
fs72.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
19455
19696
|
};
|
|
19456
19697
|
}
|
|
19457
19698
|
return result;
|
|
@@ -19475,8 +19716,8 @@ function checkMemberNameMissing() {
|
|
|
19475
19716
|
return result;
|
|
19476
19717
|
}
|
|
19477
19718
|
const claudeDir2 = claudeDirInternal3();
|
|
19478
|
-
const atlasUserPath =
|
|
19479
|
-
const value =
|
|
19719
|
+
const atlasUserPath = path71.join(claudeDir2, ".atlas-user");
|
|
19720
|
+
const value = fs72.existsSync(atlasUserPath) ? fs72.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
19480
19721
|
if (value.length > 0) {
|
|
19481
19722
|
result.details = [`atlas-user: ${value}`];
|
|
19482
19723
|
return result;
|
|
@@ -19484,10 +19725,10 @@ function checkMemberNameMissing() {
|
|
|
19484
19725
|
result.healthy = false;
|
|
19485
19726
|
result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
|
|
19486
19727
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
19487
|
-
const membersDir =
|
|
19488
|
-
const existing =
|
|
19728
|
+
const membersDir = path71.join(clonePath, "members");
|
|
19729
|
+
const existing = fs72.existsSync(membersDir) ? fs72.readdirSync(membersDir).filter((e) => {
|
|
19489
19730
|
try {
|
|
19490
|
-
return
|
|
19731
|
+
return fs72.statSync(path71.join(membersDir, e)).isDirectory();
|
|
19491
19732
|
} catch {
|
|
19492
19733
|
return false;
|
|
19493
19734
|
}
|
|
@@ -19501,8 +19742,8 @@ function checkMemberNameMissing() {
|
|
|
19501
19742
|
}
|
|
19502
19743
|
function checkMemberOverlayDrift() {
|
|
19503
19744
|
const claudeDir2 = claudeDirInternal3();
|
|
19504
|
-
const atlasUserPath =
|
|
19505
|
-
const atlasUser =
|
|
19745
|
+
const atlasUserPath = path71.join(claudeDir2, ".atlas-user");
|
|
19746
|
+
const atlasUser = fs72.existsSync(atlasUserPath) ? fs72.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
19506
19747
|
if (atlasUser.length === 0) {
|
|
19507
19748
|
return [];
|
|
19508
19749
|
}
|
|
@@ -19518,26 +19759,26 @@ function checkMemberOverlayDrift() {
|
|
|
19518
19759
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
19519
19760
|
const results = [];
|
|
19520
19761
|
for (const kind of ["skills", "agents"]) {
|
|
19521
|
-
const localRoot =
|
|
19522
|
-
if (!
|
|
19762
|
+
const localRoot = path71.join(claudeDir2, `${kind}.overrides`);
|
|
19763
|
+
if (!fs72.existsSync(localRoot))
|
|
19523
19764
|
continue;
|
|
19524
19765
|
let entries;
|
|
19525
19766
|
try {
|
|
19526
|
-
entries =
|
|
19767
|
+
entries = fs72.readdirSync(localRoot);
|
|
19527
19768
|
} catch {
|
|
19528
19769
|
continue;
|
|
19529
19770
|
}
|
|
19530
19771
|
for (const entry of entries) {
|
|
19531
|
-
const localFile =
|
|
19772
|
+
const localFile = path71.join(localRoot, entry);
|
|
19532
19773
|
let stat;
|
|
19533
19774
|
try {
|
|
19534
|
-
stat =
|
|
19775
|
+
stat = fs72.statSync(localFile);
|
|
19535
19776
|
} catch {
|
|
19536
19777
|
continue;
|
|
19537
19778
|
}
|
|
19538
19779
|
if (!stat.isFile())
|
|
19539
19780
|
continue;
|
|
19540
|
-
const cloneFile =
|
|
19781
|
+
const cloneFile = path71.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
|
|
19541
19782
|
const localSha = sha256OfPath(localFile);
|
|
19542
19783
|
const cloneSha = sha256OfPath(cloneFile);
|
|
19543
19784
|
if (localSha === cloneSha) {
|
|
@@ -19698,7 +19939,7 @@ var project_sweep_exports = {};
|
|
|
19698
19939
|
__export(project_sweep_exports, {
|
|
19699
19940
|
walkProjectRoot: () => walkProjectRoot
|
|
19700
19941
|
});
|
|
19701
|
-
import * as
|
|
19942
|
+
import * as path72 from "node:path";
|
|
19702
19943
|
import { readdirSync as readdirSync24, lstatSync as lstatSync6, statSync as statSync25, existsSync as existsSync81 } from "node:fs";
|
|
19703
19944
|
function isSkipped(basename16, extra) {
|
|
19704
19945
|
if (DEFAULT_SKIP.has(basename16))
|
|
@@ -19710,7 +19951,7 @@ function isSkipped(basename16, extra) {
|
|
|
19710
19951
|
return false;
|
|
19711
19952
|
}
|
|
19712
19953
|
function resolveMtime(dirPath, manifestFile, fsAdapter) {
|
|
19713
|
-
const gitHead =
|
|
19954
|
+
const gitHead = path72.join(dirPath, ".git", "HEAD");
|
|
19714
19955
|
if (fsAdapter.existsSync(gitHead)) {
|
|
19715
19956
|
try {
|
|
19716
19957
|
return fsAdapter.statSync(gitHead).mtimeMs;
|
|
@@ -19724,8 +19965,8 @@ function resolveMtime(dirPath, manifestFile, fsAdapter) {
|
|
|
19724
19965
|
}
|
|
19725
19966
|
}
|
|
19726
19967
|
function walk2(currentPath, depth, maxDepth, extraExclude, fsAdapter, results) {
|
|
19727
|
-
const adbManifest =
|
|
19728
|
-
const olamManifest =
|
|
19968
|
+
const adbManifest = path72.join(currentPath, ".adb.yaml");
|
|
19969
|
+
const olamManifest = path72.join(currentPath, ".olam.yaml");
|
|
19729
19970
|
if (fsAdapter.existsSync(adbManifest)) {
|
|
19730
19971
|
const mtime = resolveMtime(currentPath, adbManifest, fsAdapter);
|
|
19731
19972
|
results.push({ path: currentPath, manifestType: "adb", mtime });
|
|
@@ -19747,7 +19988,7 @@ function walk2(currentPath, depth, maxDepth, extraExclude, fsAdapter, results) {
|
|
|
19747
19988
|
for (const entry of entries) {
|
|
19748
19989
|
if (isSkipped(entry, extraExclude))
|
|
19749
19990
|
continue;
|
|
19750
|
-
const childPath =
|
|
19991
|
+
const childPath = path72.join(currentPath, entry);
|
|
19751
19992
|
let stat;
|
|
19752
19993
|
try {
|
|
19753
19994
|
stat = fsAdapter.lstatSync(childPath);
|
|
@@ -19804,17 +20045,17 @@ __export(kg_eager_exports, {
|
|
|
19804
20045
|
runEagerKgBuild: () => runEagerKgBuild,
|
|
19805
20046
|
writeQueue: () => writeQueue
|
|
19806
20047
|
});
|
|
19807
|
-
import * as
|
|
19808
|
-
import * as
|
|
20048
|
+
import * as fs73 from "node:fs";
|
|
20049
|
+
import * as path73 from "node:path";
|
|
19809
20050
|
import * as os39 from "node:os";
|
|
19810
20051
|
function defaultQueuePath() {
|
|
19811
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
19812
|
-
return
|
|
20052
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path73.join(os39.homedir(), ".olam", "state");
|
|
20053
|
+
return path73.join(stateDir, "kg-pending.jsonl");
|
|
19813
20054
|
}
|
|
19814
20055
|
function readQueue(queuePath) {
|
|
19815
|
-
if (!
|
|
20056
|
+
if (!fs73.existsSync(queuePath))
|
|
19816
20057
|
return [];
|
|
19817
|
-
const raw =
|
|
20058
|
+
const raw = fs73.readFileSync(queuePath, "utf-8");
|
|
19818
20059
|
const entries = [];
|
|
19819
20060
|
for (const line of raw.split("\n")) {
|
|
19820
20061
|
const trimmed = line.trim();
|
|
@@ -19828,16 +20069,16 @@ function readQueue(queuePath) {
|
|
|
19828
20069
|
return entries;
|
|
19829
20070
|
}
|
|
19830
20071
|
function writeQueue(queuePath, entries) {
|
|
19831
|
-
|
|
20072
|
+
fs73.mkdirSync(path73.dirname(queuePath), { recursive: true });
|
|
19832
20073
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
19833
|
-
|
|
20074
|
+
fs73.writeFileSync(queuePath, content, "utf-8");
|
|
19834
20075
|
}
|
|
19835
20076
|
function appendQueue(queuePath, repos, nowMs) {
|
|
19836
20077
|
if (repos.length === 0)
|
|
19837
20078
|
return;
|
|
19838
|
-
|
|
20079
|
+
fs73.mkdirSync(path73.dirname(queuePath), { recursive: true });
|
|
19839
20080
|
const lines = repos.map((r) => JSON.stringify({ path: r.path, addedAt: nowMs })).join("\n") + "\n";
|
|
19840
|
-
|
|
20081
|
+
fs73.appendFileSync(queuePath, lines, "utf-8");
|
|
19841
20082
|
}
|
|
19842
20083
|
async function defaultBuildOne(_repo) {
|
|
19843
20084
|
return { ok: true, ms: 0 };
|
|
@@ -19890,16 +20131,16 @@ __export(machine_schema_exports, {
|
|
|
19890
20131
|
readMachineConfig: () => readMachineConfig,
|
|
19891
20132
|
writeMachineConfig: () => writeMachineConfig
|
|
19892
20133
|
});
|
|
19893
|
-
import * as
|
|
19894
|
-
import * as
|
|
20134
|
+
import * as fs76 from "node:fs";
|
|
20135
|
+
import * as path77 from "node:path";
|
|
19895
20136
|
import * as os40 from "node:os";
|
|
19896
20137
|
import { parse as parseYaml6, stringify as stringifyYaml5 } from "yaml";
|
|
19897
20138
|
function readMachineConfig(configPath) {
|
|
19898
20139
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
19899
|
-
if (!
|
|
20140
|
+
if (!fs76.existsSync(p))
|
|
19900
20141
|
return null;
|
|
19901
20142
|
try {
|
|
19902
|
-
const raw =
|
|
20143
|
+
const raw = fs76.readFileSync(p, "utf-8");
|
|
19903
20144
|
const parsed = parseYaml6(raw);
|
|
19904
20145
|
return MachineConfigSchema.parse(parsed);
|
|
19905
20146
|
} catch {
|
|
@@ -19908,8 +20149,8 @@ function readMachineConfig(configPath) {
|
|
|
19908
20149
|
}
|
|
19909
20150
|
function writeMachineConfig(config, configPath) {
|
|
19910
20151
|
const p = configPath ?? DEFAULT_CONFIG_PATH;
|
|
19911
|
-
|
|
19912
|
-
|
|
20152
|
+
fs76.mkdirSync(path77.dirname(p), { recursive: true });
|
|
20153
|
+
fs76.writeFileSync(p, stringifyYaml5({ ...config }), { mode: 420 });
|
|
19913
20154
|
}
|
|
19914
20155
|
function initMachineConfig(opts = {}) {
|
|
19915
20156
|
const configPath = opts.configPath ?? DEFAULT_CONFIG_PATH;
|
|
@@ -19932,9 +20173,9 @@ var init_machine_schema = __esm({
|
|
|
19932
20173
|
channel: external_exports.enum(["stable", "beta", "edge"]).default("stable"),
|
|
19933
20174
|
auto_update: external_exports.boolean().default(true),
|
|
19934
20175
|
telemetry: external_exports.boolean().default(true),
|
|
19935
|
-
worlds_dir: external_exports.string().default(() =>
|
|
20176
|
+
worlds_dir: external_exports.string().default(() => path77.join(os40.homedir(), ".olam", "worlds"))
|
|
19936
20177
|
});
|
|
19937
|
-
DEFAULT_CONFIG_PATH =
|
|
20178
|
+
DEFAULT_CONFIG_PATH = path77.join(os40.homedir(), ".olam", "config.yaml");
|
|
19938
20179
|
}
|
|
19939
20180
|
});
|
|
19940
20181
|
|
|
@@ -20128,16 +20369,16 @@ function isValidConfig(value) {
|
|
|
20128
20369
|
if (typeof v.install_id !== "string" || v.install_id.length === 0) return false;
|
|
20129
20370
|
return true;
|
|
20130
20371
|
}
|
|
20131
|
-
function atomicWriteJSON(
|
|
20372
|
+
function atomicWriteJSON(path94, value, stderr = process.stderr) {
|
|
20132
20373
|
ensureStateDir();
|
|
20133
|
-
const dir = dirname3(
|
|
20374
|
+
const dir = dirname3(path94);
|
|
20134
20375
|
if (!existsSync6(dir)) {
|
|
20135
20376
|
mkdirSync2(dir, { recursive: true });
|
|
20136
20377
|
}
|
|
20137
|
-
const tmp = `${
|
|
20378
|
+
const tmp = `${path94}.tmp.${process.pid}`;
|
|
20138
20379
|
try {
|
|
20139
20380
|
writeFileSync2(tmp, JSON.stringify(value, null, 2) + "\n", { encoding: "utf8" });
|
|
20140
|
-
renameSync2(tmp,
|
|
20381
|
+
renameSync2(tmp, path94);
|
|
20141
20382
|
} catch (err) {
|
|
20142
20383
|
if (existsSync6(tmp)) {
|
|
20143
20384
|
try {
|
|
@@ -20473,9 +20714,9 @@ var UnknownArchetypeError = class extends Error {
|
|
|
20473
20714
|
};
|
|
20474
20715
|
var ArchetypeCycleError = class extends Error {
|
|
20475
20716
|
path;
|
|
20476
|
-
constructor(
|
|
20477
|
-
super(`Archetype inheritance cycle detected: ${
|
|
20478
|
-
this.path =
|
|
20717
|
+
constructor(path94) {
|
|
20718
|
+
super(`Archetype inheritance cycle detected: ${path94.join(" \u2192 ")} \u2192 ${path94[0] ?? "?"}`);
|
|
20719
|
+
this.path = path94;
|
|
20479
20720
|
this.name = "ArchetypeCycleError";
|
|
20480
20721
|
}
|
|
20481
20722
|
};
|
|
@@ -21197,7 +21438,7 @@ function step(label) {
|
|
|
21197
21438
|
process.stdout.write("\n" + pc6.bold(pc6.cyan(`==> ${label}`)) + "\n");
|
|
21198
21439
|
}
|
|
21199
21440
|
function preflight(opts) {
|
|
21200
|
-
step("0/
|
|
21441
|
+
step("0/6 \u2014 preflight (tool detection)");
|
|
21201
21442
|
const missing = detectMissingTools();
|
|
21202
21443
|
if (missing.length === 0) {
|
|
21203
21444
|
printSuccess("all required tools present");
|
|
@@ -21239,23 +21480,23 @@ function preflight(opts) {
|
|
|
21239
21480
|
printSuccess("docker daemon reachable");
|
|
21240
21481
|
}
|
|
21241
21482
|
function ensureSecrets() {
|
|
21242
|
-
step("1/
|
|
21483
|
+
step("1/6 \u2014 operator secrets");
|
|
21243
21484
|
mkdirSync19(OLAM_HOME3, { recursive: true });
|
|
21244
21485
|
for (const name of SECRET_FILES) {
|
|
21245
|
-
const
|
|
21246
|
-
if (existsSync29(
|
|
21486
|
+
const path94 = join34(OLAM_HOME3, name);
|
|
21487
|
+
if (existsSync29(path94)) {
|
|
21247
21488
|
printInfo("skip", `~/.olam/${name} already exists`);
|
|
21248
21489
|
continue;
|
|
21249
21490
|
}
|
|
21250
21491
|
const hex = randomBytes7(32).toString("hex");
|
|
21251
|
-
writeFileSync15(
|
|
21252
|
-
chmodSync4(
|
|
21492
|
+
writeFileSync15(path94, hex + "\n", { encoding: "utf8", mode: 384 });
|
|
21493
|
+
chmodSync4(path94, 384);
|
|
21253
21494
|
printSuccess(`generated ~/.olam/${name}`);
|
|
21254
21495
|
}
|
|
21255
21496
|
}
|
|
21256
21497
|
function ensureColima() {
|
|
21257
21498
|
if (platform() !== "darwin") return;
|
|
21258
|
-
step("2/
|
|
21499
|
+
step("2/6 \u2014 colima (macOS)");
|
|
21259
21500
|
if (!runCapture("colima", ["status"]).ok) {
|
|
21260
21501
|
printWarning("colima not running \u2014 starting");
|
|
21261
21502
|
runOrFail(
|
|
@@ -21274,10 +21515,10 @@ function ensureColima() {
|
|
|
21274
21515
|
}
|
|
21275
21516
|
function ensureCluster(opts) {
|
|
21276
21517
|
if (opts.skipClusterCreate) {
|
|
21277
|
-
step("3/
|
|
21518
|
+
step("3/6 \u2014 cluster (skipped via --skip-cluster-create)");
|
|
21278
21519
|
return;
|
|
21279
21520
|
}
|
|
21280
|
-
step(`3/
|
|
21521
|
+
step(`3/6 \u2014 k3d cluster create (${opts.cluster})`);
|
|
21281
21522
|
if (runCapture("k3d", ["cluster", "list", opts.cluster]).ok) {
|
|
21282
21523
|
printInfo("cluster", `'${opts.cluster}' already exists`);
|
|
21283
21524
|
return;
|
|
@@ -21304,26 +21545,51 @@ function resolveObservabilityScriptsDir() {
|
|
|
21304
21545
|
}
|
|
21305
21546
|
return null;
|
|
21306
21547
|
}
|
|
21548
|
+
function resolvePeripheralServicesDir() {
|
|
21549
|
+
const installed = join34(installRoot(), "host-cp", "peripheral-services");
|
|
21550
|
+
if (existsSync29(installed)) return installed;
|
|
21551
|
+
const k8sRoot = resolveK8sAssetsRoot();
|
|
21552
|
+
if (k8sRoot) {
|
|
21553
|
+
const dev = join34(k8sRoot, "..", "..", "peripheral-services");
|
|
21554
|
+
if (existsSync29(dev)) return dev;
|
|
21555
|
+
}
|
|
21556
|
+
return null;
|
|
21557
|
+
}
|
|
21558
|
+
function resolveBundleRoot() {
|
|
21559
|
+
const installed = join34(installRoot(), "host-cp");
|
|
21560
|
+
if (existsSync29(join34(installed, "peripheral-services"))) return installed;
|
|
21561
|
+
const k8sRoot = resolveK8sAssetsRoot();
|
|
21562
|
+
if (k8sRoot) {
|
|
21563
|
+
const dev = join34(k8sRoot, "..", "..");
|
|
21564
|
+
if (existsSync29(join34(dev, "peripheral-services"))) return dev;
|
|
21565
|
+
}
|
|
21566
|
+
return null;
|
|
21567
|
+
}
|
|
21307
21568
|
function installObservability(opts) {
|
|
21308
21569
|
if (opts.skipObservability) {
|
|
21309
|
-
step("4/
|
|
21570
|
+
step("4/6 \u2014 observability (skipped via --skip-observability)");
|
|
21310
21571
|
return;
|
|
21311
21572
|
}
|
|
21312
|
-
step("4/
|
|
21573
|
+
step("4/6 \u2014 observability stack (Loki + Promtail + Grafana + Prometheus + Kyverno)");
|
|
21313
21574
|
const observabilityDir = resolveObservabilityScriptsDir();
|
|
21314
21575
|
if (!observabilityDir) {
|
|
21315
21576
|
printWarning("bundled observability scripts not found \u2014 skipping");
|
|
21316
21577
|
printWarning(" (expected in published CLI installs; missing only in dev tarballs without bundling)");
|
|
21317
21578
|
return;
|
|
21318
21579
|
}
|
|
21580
|
+
const bundleRoot = resolveBundleRoot();
|
|
21581
|
+
const scriptEnv = { ...process.env };
|
|
21582
|
+
if (bundleRoot) {
|
|
21583
|
+
scriptEnv.OLAM_BUNDLE_ROOT = bundleRoot;
|
|
21584
|
+
}
|
|
21319
21585
|
for (const script of OBSERVABILITY_SCRIPTS) {
|
|
21320
|
-
const
|
|
21321
|
-
if (!existsSync29(
|
|
21586
|
+
const path94 = join34(observabilityDir, script);
|
|
21587
|
+
if (!existsSync29(path94)) {
|
|
21322
21588
|
printWarning(`observability script missing: ${script} \u2014 skipping`);
|
|
21323
21589
|
continue;
|
|
21324
21590
|
}
|
|
21325
21591
|
printInfo("run", script);
|
|
21326
|
-
const result = spawnSync10("bash", [
|
|
21592
|
+
const result = spawnSync10("bash", [path94], { stdio: "inherit", env: scriptEnv });
|
|
21327
21593
|
if (result.status !== 0) {
|
|
21328
21594
|
if (script === "loki-ingest.sh") {
|
|
21329
21595
|
printWarning("loki-ingest non-zero \u2014 likely Promtail scrub-wait flake; continuing");
|
|
@@ -21336,8 +21602,28 @@ function installObservability(opts) {
|
|
|
21336
21602
|
}
|
|
21337
21603
|
}
|
|
21338
21604
|
}
|
|
21605
|
+
function applyPeripheralServicesManifests() {
|
|
21606
|
+
step("5/6 \u2014 peripheral-services manifests (IngressRoutes + ServiceMonitors + recording rules + dashboards + Kyverno)");
|
|
21607
|
+
const dir = resolvePeripheralServicesDir();
|
|
21608
|
+
if (!dir) {
|
|
21609
|
+
printWarning("bundled peripheral-services manifests not found \u2014 skipping");
|
|
21610
|
+
return;
|
|
21611
|
+
}
|
|
21612
|
+
const manifestsDir = join34(dir, "manifests");
|
|
21613
|
+
if (!existsSync29(manifestsDir)) {
|
|
21614
|
+
printWarning(`peripheral-services/manifests not found at ${manifestsDir} \u2014 skipping`);
|
|
21615
|
+
return;
|
|
21616
|
+
}
|
|
21617
|
+
printInfo("apply", manifestsDir);
|
|
21618
|
+
const result = spawnSync10("kubectl", ["apply", "-f", manifestsDir], { stdio: "inherit" });
|
|
21619
|
+
if (result.status !== 0) {
|
|
21620
|
+
printError("kubectl apply failed \u2014 peripheral-services manifests not applied");
|
|
21621
|
+
process.exit(result.status ?? 1);
|
|
21622
|
+
}
|
|
21623
|
+
printSuccess("peripheral-services manifests applied");
|
|
21624
|
+
}
|
|
21339
21625
|
function delegateToUpgrade() {
|
|
21340
|
-
step("
|
|
21626
|
+
step("6/6 \u2014 apply host-cp + peripherals + rollout (olam upgrade)");
|
|
21341
21627
|
const olamBin = process.argv[1] ?? "olam";
|
|
21342
21628
|
const result = spawnSync10(process.execPath, [olamBin, "upgrade", "-y"], { stdio: "inherit" });
|
|
21343
21629
|
if (result.status !== 0) {
|
|
@@ -21363,23 +21649,25 @@ function summary(opts) {
|
|
|
21363
21649
|
`);
|
|
21364
21650
|
}
|
|
21365
21651
|
async function runBootstrapKubernetes(rawOpts) {
|
|
21652
|
+
const defaultAutoInstall = platform() === "darwin";
|
|
21366
21653
|
const opts = {
|
|
21367
21654
|
cluster: rawOpts.cluster ?? DEFAULT_K3S_CLUSTER,
|
|
21368
|
-
autoInstall: rawOpts.autoInstall ??
|
|
21655
|
+
autoInstall: rawOpts.autoInstall ?? defaultAutoInstall,
|
|
21369
21656
|
skipObservability: rawOpts.skipObservability ?? false,
|
|
21370
21657
|
skipClusterCreate: rawOpts.skipClusterCreate ?? false
|
|
21371
21658
|
};
|
|
21372
|
-
printHeader("olam
|
|
21659
|
+
printHeader("olam setup \u2014 k3s mode");
|
|
21373
21660
|
printInfo("mode", "one-command bring-up of olam peripherals + observability on a local k3d cluster");
|
|
21374
21661
|
preflight(opts);
|
|
21375
21662
|
ensureSecrets();
|
|
21376
21663
|
ensureColima();
|
|
21377
21664
|
ensureCluster(opts);
|
|
21378
21665
|
installObservability(opts);
|
|
21666
|
+
applyPeripheralServicesManifests();
|
|
21379
21667
|
delegateToUpgrade();
|
|
21380
21668
|
summary(opts);
|
|
21381
|
-
printSuccess("
|
|
21382
|
-
return { exitCode: 0, summary: `
|
|
21669
|
+
printSuccess("setup complete");
|
|
21670
|
+
return { exitCode: 0, summary: `setup complete on cluster ${opts.cluster}` };
|
|
21383
21671
|
}
|
|
21384
21672
|
|
|
21385
21673
|
// src/commands/bootstrap.ts
|
|
@@ -21673,13 +21961,13 @@ async function runBootstrap2(opts, deps = {}) {
|
|
|
21673
21961
|
printInfo("next", '`olam create --task "your task"` to spawn a world');
|
|
21674
21962
|
return { exitCode: 0, summary: "stack ready" };
|
|
21675
21963
|
}
|
|
21676
|
-
function
|
|
21677
|
-
program2.command(
|
|
21678
|
-
"
|
|
21679
|
-
).option("--with-smoke", "After
|
|
21964
|
+
function buildSetupCommand(program2, name) {
|
|
21965
|
+
return program2.command(name).description(
|
|
21966
|
+
"Bring up the olam substrate. Substrate-aware: on kubernetes (default), detects tools, auto-installs missing brew formulae on macOS, generates secrets, creates a k3d cluster, installs observability (Loki + Promtail + Grafana + Prometheus + Kyverno), applies peripheral-services manifests (IngressRoutes + ServiceMonitors + dashboards), and runs the `olam upgrade` flow for host-cp + peripherals + rollout. On compose, pulls 3 images by digest + starts host-cp + auth. The full operator-onboarding wizard is `olam setup` \u2014 this command is the substrate primitive it calls."
|
|
21967
|
+
).option("--with-smoke", "After setup, create a smoke-test world to verify end-to-end").option("--skip-auth-login", "Skip the interactive PKCE step (CI / scripted use only)").option("--skip-postgres-singleton", "Skip the olam-postgres singleton bring-up (operators with host postgres opt-out, or CI)").option("--skip-memory", "Skip the agent-memory Docker container bring-up (CI / scripted use, or hosts without Docker)").option("--skip-kg-service", "Skip the olam-kg-service container pull + start (classifier-augmented retrieval; v2 feature)").option(
|
|
21680
21968
|
"--registry <ref>",
|
|
21681
21969
|
"Override the registry prefix (default: read from image-digests.json or fall back to ghcr.io/pleri)"
|
|
21682
|
-
).option("--k3s-cluster <name>", `[k3s] k3d cluster name (default: ${DEFAULT_K3S_CLUSTER})`, DEFAULT_K3S_CLUSTER).option("--auto-install", "[k3s] auto-install missing tools via brew on macOS",
|
|
21970
|
+
).option("--k3s-cluster <name>", `[k3s] k3d cluster name (default: ${DEFAULT_K3S_CLUSTER})`, DEFAULT_K3S_CLUSTER).option("--auto-install", "[k3s] auto-install missing tools via brew on macOS (default: ON for macOS)", void 0).option("--no-auto-install", "[k3s] disable auto-install (operator runs brew themselves)").option("--skip-observability", "[k3s] skip Loki/Promtail/Grafana/Prom install (already in place)", false).option("--skip-cluster-create", "[k3s] cluster already exists; install substrate only", false).action(async (opts) => {
|
|
21683
21971
|
try {
|
|
21684
21972
|
const result = await runBootstrap2({
|
|
21685
21973
|
withSmoke: opts.withSmoke === true,
|
|
@@ -21689,7 +21977,10 @@ function registerBootstrap(program2) {
|
|
|
21689
21977
|
skipKgService: opts.skipKgService === true,
|
|
21690
21978
|
registry: opts.registry,
|
|
21691
21979
|
k3sCluster: opts.k3sCluster,
|
|
21692
|
-
|
|
21980
|
+
// Tri-state: undefined = let runBootstrapKubernetes apply the
|
|
21981
|
+
// platform-default (ON for macOS, OFF otherwise). `--no-auto-install`
|
|
21982
|
+
// sets autoInstall=false explicitly.
|
|
21983
|
+
autoInstall: opts.autoInstall,
|
|
21693
21984
|
skipObservability: opts.skipObservability === true,
|
|
21694
21985
|
skipClusterCreate: opts.skipClusterCreate === true
|
|
21695
21986
|
});
|
|
@@ -21700,6 +21991,9 @@ function registerBootstrap(program2) {
|
|
|
21700
21991
|
}
|
|
21701
21992
|
});
|
|
21702
21993
|
}
|
|
21994
|
+
function registerBootstrap(program2) {
|
|
21995
|
+
buildSetupCommand(program2, "bootstrap");
|
|
21996
|
+
}
|
|
21703
21997
|
|
|
21704
21998
|
// src/commands/auth-upgrade.ts
|
|
21705
21999
|
init_exit_codes();
|
|
@@ -22270,56 +22564,56 @@ var SECRET_LEN_BYTES = 32;
|
|
|
22270
22564
|
function generateSecret() {
|
|
22271
22565
|
return randomBytes8(SECRET_LEN_BYTES).toString("hex");
|
|
22272
22566
|
}
|
|
22273
|
-
function writeSecretAtPath(
|
|
22274
|
-
mkdirSync21(dirname22(
|
|
22275
|
-
const tmp = `${
|
|
22567
|
+
function writeSecretAtPath(path94, value) {
|
|
22568
|
+
mkdirSync21(dirname22(path94), { recursive: true });
|
|
22569
|
+
const tmp = `${path94}.tmp.${process.pid}`;
|
|
22276
22570
|
writeFileSync16(tmp, value, { mode: 384 });
|
|
22277
22571
|
chmodSync5(tmp, 384);
|
|
22278
|
-
renameSync6(tmp,
|
|
22572
|
+
renameSync6(tmp, path94);
|
|
22279
22573
|
}
|
|
22280
|
-
function readSecretAtPathOrNull(
|
|
22281
|
-
if (!existsSync32(
|
|
22282
|
-
const mode = statSync8(
|
|
22574
|
+
function readSecretAtPathOrNull(path94) {
|
|
22575
|
+
if (!existsSync32(path94)) return null;
|
|
22576
|
+
const mode = statSync8(path94).mode & 511;
|
|
22283
22577
|
if (mode !== 384) {
|
|
22284
22578
|
process.stderr.write(
|
|
22285
|
-
`warn: ${
|
|
22579
|
+
`warn: ${path94} has mode 0${mode.toString(8)}; expected 0600. Run 'olam memory secret rotate' to regenerate.
|
|
22286
22580
|
`
|
|
22287
22581
|
);
|
|
22288
22582
|
}
|
|
22289
|
-
return readFileSync25(
|
|
22583
|
+
return readFileSync25(path94, "utf8").trim();
|
|
22290
22584
|
}
|
|
22291
|
-
function readSecretAtPath(
|
|
22292
|
-
const v = readSecretAtPathOrNull(
|
|
22585
|
+
function readSecretAtPath(path94) {
|
|
22586
|
+
const v = readSecretAtPathOrNull(path94);
|
|
22293
22587
|
if (v === null) {
|
|
22294
22588
|
throw new Error(
|
|
22295
|
-
`Secret not found at ${
|
|
22589
|
+
`Secret not found at ${path94}. Run 'olam memory start' to generate it.`
|
|
22296
22590
|
);
|
|
22297
22591
|
}
|
|
22298
22592
|
return v;
|
|
22299
22593
|
}
|
|
22300
|
-
function ensureMemorySecret(
|
|
22301
|
-
const existing = readSecretAtPathOrNull(
|
|
22594
|
+
function ensureMemorySecret(path94 = MEMORY_SECRET_PATH) {
|
|
22595
|
+
const existing = readSecretAtPathOrNull(path94);
|
|
22302
22596
|
if (existing) return existing;
|
|
22303
22597
|
const fresh = generateSecret();
|
|
22304
|
-
writeSecretAtPath(
|
|
22598
|
+
writeSecretAtPath(path94, fresh);
|
|
22305
22599
|
return fresh;
|
|
22306
22600
|
}
|
|
22307
|
-
function readMemorySecretOrNull(
|
|
22308
|
-
return readSecretAtPathOrNull(
|
|
22601
|
+
function readMemorySecretOrNull(path94 = MEMORY_SECRET_PATH) {
|
|
22602
|
+
return readSecretAtPathOrNull(path94);
|
|
22309
22603
|
}
|
|
22310
|
-
function readMemorySecret(
|
|
22311
|
-
return readSecretAtPath(
|
|
22604
|
+
function readMemorySecret(path94 = MEMORY_SECRET_PATH) {
|
|
22605
|
+
return readSecretAtPath(path94);
|
|
22312
22606
|
}
|
|
22313
|
-
function rotateMemorySecret(
|
|
22607
|
+
function rotateMemorySecret(path94 = MEMORY_SECRET_PATH) {
|
|
22314
22608
|
const fresh = generateSecret();
|
|
22315
|
-
writeSecretAtPath(
|
|
22609
|
+
writeSecretAtPath(path94, fresh);
|
|
22316
22610
|
return fresh;
|
|
22317
22611
|
}
|
|
22318
|
-
function hasMemorySecret(
|
|
22319
|
-
return existsSync32(
|
|
22612
|
+
function hasMemorySecret(path94 = MEMORY_SECRET_PATH) {
|
|
22613
|
+
return existsSync32(path94);
|
|
22320
22614
|
}
|
|
22321
|
-
function writeCloudMemorySecret(value,
|
|
22322
|
-
writeSecretAtPath(
|
|
22615
|
+
function writeCloudMemorySecret(value, path94 = CLOUD_MEMORY_SECRET_PATH) {
|
|
22616
|
+
writeSecretAtPath(path94, value);
|
|
22323
22617
|
}
|
|
22324
22618
|
|
|
22325
22619
|
// src/commands/memory-service-container.ts
|
|
@@ -23361,7 +23655,7 @@ function appendAuditEntry(entry, auditLogPath, writeFileSyncImpl) {
|
|
|
23361
23655
|
async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, peripheral) {
|
|
23362
23656
|
const auditLogPath = deps.auditLogPath ?? MANIFEST_REFRESH_AUDIT_LOG;
|
|
23363
23657
|
const readdirSync32 = deps.readdirSync ?? fs31.readdirSync;
|
|
23364
|
-
const
|
|
23658
|
+
const readFileSync92 = deps.readFileSync ?? fs31.readFileSync;
|
|
23365
23659
|
const writeFileSyncImpl = deps.writeFileSync ?? fs31.writeFileSync;
|
|
23366
23660
|
const existsSync112 = deps.existsSync ?? fs31.existsSync;
|
|
23367
23661
|
const now = deps.now ? deps.now() : /* @__PURE__ */ new Date();
|
|
@@ -23387,7 +23681,7 @@ async function runManifestRefresh(manifestsDir, acceptRegression, deps = {}, per
|
|
|
23387
23681
|
const filePath = path32.join(targetDir, file);
|
|
23388
23682
|
let content;
|
|
23389
23683
|
try {
|
|
23390
|
-
content =
|
|
23684
|
+
content = readFileSync92(filePath, "utf8");
|
|
23391
23685
|
} catch {
|
|
23392
23686
|
continue;
|
|
23393
23687
|
}
|
|
@@ -23639,11 +23933,11 @@ async function checkSecretPreCondition(context, deps) {
|
|
|
23639
23933
|
}
|
|
23640
23934
|
async function applyConfigMapSubstitution(context, manifestsDir, deps) {
|
|
23641
23935
|
const wrap = deps.kubectlWrapImpl ?? kubectlWrap;
|
|
23642
|
-
const
|
|
23936
|
+
const readFileSync92 = deps.readFileSyncImpl ?? fs32.readFileSync;
|
|
23643
23937
|
const configMapPath = path33.join(manifestsDir, "30-configmap.yaml");
|
|
23644
23938
|
let rawYaml;
|
|
23645
23939
|
try {
|
|
23646
|
-
rawYaml =
|
|
23940
|
+
rawYaml = readFileSync92(configMapPath, "utf8");
|
|
23647
23941
|
} catch (err) {
|
|
23648
23942
|
return `Failed to read ConfigMap at ${configMapPath}: ${err instanceof Error ? err.message : String(err)}`;
|
|
23649
23943
|
}
|
|
@@ -24464,9 +24758,9 @@ function formatFreshnessWarning(result, image = DEFAULT_DEVBOX_IMAGE) {
|
|
|
24464
24758
|
"These source files have changed since the image was built; the",
|
|
24465
24759
|
"changes will NOT take effect in fresh worlds until you rebuild:"
|
|
24466
24760
|
];
|
|
24467
|
-
for (const { path:
|
|
24761
|
+
for (const { path: path94, mtimeMs } of result.newerSources) {
|
|
24468
24762
|
const when = new Date(mtimeMs).toISOString();
|
|
24469
|
-
lines.push(` \u2022 ${
|
|
24763
|
+
lines.push(` \u2022 ${path94} (modified ${when})`);
|
|
24470
24764
|
}
|
|
24471
24765
|
lines.push("");
|
|
24472
24766
|
lines.push("Rebuild with:");
|
|
@@ -24845,15 +25139,15 @@ var AGENTMEMORY_LOCAL_URL = "http://host.docker.internal:3111";
|
|
|
24845
25139
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
24846
25140
|
async function readHostCpTokenForCreate() {
|
|
24847
25141
|
try {
|
|
24848
|
-
const { default:
|
|
25142
|
+
const { default: fs95 } = await import("node:fs");
|
|
24849
25143
|
const { default: os49 } = await import("node:os");
|
|
24850
|
-
const { default:
|
|
24851
|
-
const tp =
|
|
24852
|
-
process.env.OLAM_HOME ??
|
|
25144
|
+
const { default: path94 } = await import("node:path");
|
|
25145
|
+
const tp = path94.join(
|
|
25146
|
+
process.env.OLAM_HOME ?? path94.join(os49.homedir(), ".olam"),
|
|
24853
25147
|
"host-cp.token"
|
|
24854
25148
|
);
|
|
24855
|
-
if (!
|
|
24856
|
-
return
|
|
25149
|
+
if (!fs95.existsSync(tp)) return null;
|
|
25150
|
+
return fs95.readFileSync(tp, "utf-8").trim();
|
|
24857
25151
|
} catch {
|
|
24858
25152
|
return null;
|
|
24859
25153
|
}
|
|
@@ -25290,12 +25584,12 @@ function defaultNameFromPrompt(prompt) {
|
|
|
25290
25584
|
}
|
|
25291
25585
|
async function readHostCpToken3() {
|
|
25292
25586
|
try {
|
|
25293
|
-
const { default:
|
|
25587
|
+
const { default: fs95 } = await import("node:fs");
|
|
25294
25588
|
const { default: os49 } = await import("node:os");
|
|
25295
|
-
const { default:
|
|
25296
|
-
const tp =
|
|
25297
|
-
if (!
|
|
25298
|
-
const raw =
|
|
25589
|
+
const { default: path94 } = await import("node:path");
|
|
25590
|
+
const tp = path94.join(os49.homedir(), ".olam", "host-cp.token");
|
|
25591
|
+
if (!fs95.existsSync(tp)) return null;
|
|
25592
|
+
const raw = fs95.readFileSync(tp, "utf-8").trim();
|
|
25299
25593
|
return raw.length > 0 ? raw : null;
|
|
25300
25594
|
} catch {
|
|
25301
25595
|
return null;
|
|
@@ -29102,11 +29396,11 @@ function zodIssueToError(issue, doc, lineCounter) {
|
|
|
29102
29396
|
suggestion: deriveSuggestion(issue)
|
|
29103
29397
|
};
|
|
29104
29398
|
}
|
|
29105
|
-
function formatJsonPath(
|
|
29106
|
-
if (
|
|
29399
|
+
function formatJsonPath(path94) {
|
|
29400
|
+
if (path94.length === 0)
|
|
29107
29401
|
return "<root>";
|
|
29108
29402
|
let out = "";
|
|
29109
|
-
for (const seg of
|
|
29403
|
+
for (const seg of path94) {
|
|
29110
29404
|
if (typeof seg === "number") {
|
|
29111
29405
|
out += `[${seg}]`;
|
|
29112
29406
|
} else {
|
|
@@ -29115,11 +29409,11 @@ function formatJsonPath(path93) {
|
|
|
29115
29409
|
}
|
|
29116
29410
|
return out;
|
|
29117
29411
|
}
|
|
29118
|
-
function resolveYamlLocation(
|
|
29412
|
+
function resolveYamlLocation(path94, doc, lineCounter) {
|
|
29119
29413
|
let bestLine = 0;
|
|
29120
29414
|
let bestColumn = 0;
|
|
29121
|
-
for (let depth =
|
|
29122
|
-
const segment =
|
|
29415
|
+
for (let depth = path94.length; depth >= 0; depth -= 1) {
|
|
29416
|
+
const segment = path94.slice(0, depth);
|
|
29123
29417
|
try {
|
|
29124
29418
|
const node = doc.getIn(segment, true);
|
|
29125
29419
|
if (node && typeof node === "object" && "range" in node) {
|
|
@@ -29337,11 +29631,11 @@ function topoSort(nodes) {
|
|
|
29337
29631
|
}
|
|
29338
29632
|
function traceCycle(start, byId) {
|
|
29339
29633
|
const seen = /* @__PURE__ */ new Set();
|
|
29340
|
-
const
|
|
29634
|
+
const path94 = [];
|
|
29341
29635
|
let current = start;
|
|
29342
29636
|
while (current && !seen.has(current)) {
|
|
29343
29637
|
seen.add(current);
|
|
29344
|
-
|
|
29638
|
+
path94.push(current);
|
|
29345
29639
|
const node = byId.get(current);
|
|
29346
29640
|
const next = node?.dependsOn[0];
|
|
29347
29641
|
if (next === void 0)
|
|
@@ -29349,10 +29643,10 @@ function traceCycle(start, byId) {
|
|
|
29349
29643
|
current = next;
|
|
29350
29644
|
}
|
|
29351
29645
|
if (current && seen.has(current)) {
|
|
29352
|
-
const idx =
|
|
29353
|
-
return [...
|
|
29646
|
+
const idx = path94.indexOf(current);
|
|
29647
|
+
return [...path94.slice(idx), current];
|
|
29354
29648
|
}
|
|
29355
|
-
return
|
|
29649
|
+
return path94;
|
|
29356
29650
|
}
|
|
29357
29651
|
|
|
29358
29652
|
// ../core/dist/executor/types.js
|
|
@@ -34059,8 +34353,8 @@ function checkWorld(container, hostShas, dockerExec) {
|
|
|
34059
34353
|
const m = shaLine.match(/^([a-f0-9]{64})\s+(.+)$/);
|
|
34060
34354
|
if (!m) continue;
|
|
34061
34355
|
const sha = m[1];
|
|
34062
|
-
const
|
|
34063
|
-
const filename =
|
|
34356
|
+
const path94 = m[2];
|
|
34357
|
+
const filename = path94?.split("/").pop();
|
|
34064
34358
|
if (!filename) continue;
|
|
34065
34359
|
const mtimeSecs = parseInt(mtimeLine.trim(), 10);
|
|
34066
34360
|
if (Number.isNaN(mtimeSecs) || !sha) continue;
|
|
@@ -34927,9 +35221,9 @@ var TasksClient = class {
|
|
|
34927
35221
|
this.olamNodeId = opts.olamNodeId;
|
|
34928
35222
|
this.sessionId = opts.sessionId;
|
|
34929
35223
|
}
|
|
34930
|
-
async call(method,
|
|
35224
|
+
async call(method, path94, scopes, body, query) {
|
|
34931
35225
|
const qs = query ? "?" + new URLSearchParams(Object.entries(query).filter(([, v]) => v !== void 0)).toString() : "";
|
|
34932
|
-
const url2 = `${this.baseUrl}${
|
|
35226
|
+
const url2 = `${this.baseUrl}${path94}${qs}`;
|
|
34933
35227
|
const res = await fetch(url2, {
|
|
34934
35228
|
method,
|
|
34935
35229
|
headers: {
|
|
@@ -34980,8 +35274,8 @@ function parseFrontmatter2(raw) {
|
|
|
34980
35274
|
}
|
|
34981
35275
|
return { frontmatter: fm, body };
|
|
34982
35276
|
}
|
|
34983
|
-
function parseTracker(
|
|
34984
|
-
const raw = readFileSync46(
|
|
35277
|
+
function parseTracker(path94) {
|
|
35278
|
+
const raw = readFileSync46(path94, "utf8");
|
|
34985
35279
|
const { frontmatter, body } = parseFrontmatter2(raw);
|
|
34986
35280
|
const lines = body.split("\n");
|
|
34987
35281
|
const tasks = [];
|
|
@@ -35218,8 +35512,8 @@ function registerTasks(program2) {
|
|
|
35218
35512
|
`);
|
|
35219
35513
|
}
|
|
35220
35514
|
});
|
|
35221
|
-
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 (
|
|
35222
|
-
const parsed = parseTracker(
|
|
35515
|
+
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 (path94, opts) => {
|
|
35516
|
+
const parsed = parseTracker(path94);
|
|
35223
35517
|
if (opts.dryRun) {
|
|
35224
35518
|
process.stdout.write(JSON.stringify(parsed, null, 2) + "\n");
|
|
35225
35519
|
return;
|
|
@@ -35376,7 +35670,7 @@ init_health_probes();
|
|
|
35376
35670
|
import { spawn as spawn7 } from "node:child_process";
|
|
35377
35671
|
import { existsSync as existsSync84 } from "node:fs";
|
|
35378
35672
|
import { homedir as homedir43 } from "node:os";
|
|
35379
|
-
import
|
|
35673
|
+
import path75 from "node:path";
|
|
35380
35674
|
import { createInterface as createInterface3 } from "node:readline";
|
|
35381
35675
|
|
|
35382
35676
|
// src/lib/shell-rc.ts
|
|
@@ -35566,8 +35860,8 @@ async function pickSkillSourcePhase(opts, deps) {
|
|
|
35566
35860
|
|
|
35567
35861
|
// src/commands/setup-phase-5b-project-sweep.ts
|
|
35568
35862
|
import { homedir as homedir42 } from "node:os";
|
|
35569
|
-
import * as
|
|
35570
|
-
import * as
|
|
35863
|
+
import * as path74 from "node:path";
|
|
35864
|
+
import * as fs74 from "node:fs";
|
|
35571
35865
|
async function loadWalkFn() {
|
|
35572
35866
|
const m = await Promise.resolve().then(() => (init_project_sweep(), project_sweep_exports));
|
|
35573
35867
|
return m.walkProjectRoot;
|
|
@@ -35585,9 +35879,9 @@ async function loadAppendTrustAuditFn() {
|
|
|
35585
35879
|
return m.appendTrustAudit;
|
|
35586
35880
|
}
|
|
35587
35881
|
function deriveRepoName(repoPath, existingNames) {
|
|
35588
|
-
const base =
|
|
35882
|
+
const base = path74.basename(repoPath).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
35589
35883
|
if (!existingNames.has(base)) return base;
|
|
35590
|
-
const parent =
|
|
35884
|
+
const parent = path74.basename(path74.dirname(repoPath)).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
35591
35885
|
const composite = `${parent}-${base}`;
|
|
35592
35886
|
if (!existingNames.has(composite)) return composite;
|
|
35593
35887
|
let suffix = 2;
|
|
@@ -35599,8 +35893,8 @@ async function runProjectSweepPhase(opts, deps, sweepDeps = {}) {
|
|
|
35599
35893
|
return { ok: true, skipped: true, message: "skipped via --skip-project-sweep" };
|
|
35600
35894
|
}
|
|
35601
35895
|
const home = deps.home ?? homedir42();
|
|
35602
|
-
const projectsRoot = opts.projects ??
|
|
35603
|
-
const existsSyncFn = sweepDeps.existsSync ??
|
|
35896
|
+
const projectsRoot = opts.projects ?? path74.join(home, "Projects");
|
|
35897
|
+
const existsSyncFn = sweepDeps.existsSync ?? fs74.existsSync;
|
|
35604
35898
|
if (!existsSyncFn(projectsRoot)) {
|
|
35605
35899
|
return {
|
|
35606
35900
|
ok: true,
|
|
@@ -35807,7 +36101,7 @@ async function phase4ShellInit(opts, deps) {
|
|
|
35807
36101
|
message: `unsupported $SHELL (${shellEnv ?? "unset"}); add \`eval "$(olam completion <shell>)"\` to your shell rc manually`
|
|
35808
36102
|
};
|
|
35809
36103
|
}
|
|
35810
|
-
const shellBasename =
|
|
36104
|
+
const shellBasename = path75.basename(shellEnv);
|
|
35811
36105
|
const evalLine = `eval "$(olam completion ${shellBasename})"`;
|
|
35812
36106
|
const result = appendIdempotent({
|
|
35813
36107
|
rcPath,
|
|
@@ -35833,7 +36127,7 @@ async function phase4ShellInit(opts, deps) {
|
|
|
35833
36127
|
async function phase5InitProject(opts, deps) {
|
|
35834
36128
|
const cwd = deps.cwd ?? process.cwd();
|
|
35835
36129
|
const projectRoot = findProjectRoot(cwd);
|
|
35836
|
-
const configPath =
|
|
36130
|
+
const configPath = path75.join(projectRoot, ".olam", "config.yaml");
|
|
35837
36131
|
if (existsSync84(configPath)) {
|
|
35838
36132
|
return { ok: true, message: `${configPath} present (no change)` };
|
|
35839
36133
|
}
|
|
@@ -36146,24 +36440,24 @@ function registerSetupLinuxGate(program2) {
|
|
|
36146
36440
|
}
|
|
36147
36441
|
|
|
36148
36442
|
// src/commands/update.ts
|
|
36149
|
-
import * as
|
|
36443
|
+
import * as fs77 from "node:fs";
|
|
36150
36444
|
import * as os41 from "node:os";
|
|
36151
|
-
import * as
|
|
36445
|
+
import * as path78 from "node:path";
|
|
36152
36446
|
import { execSync as execSync14 } from "node:child_process";
|
|
36153
36447
|
import pc28 from "picocolors";
|
|
36154
36448
|
|
|
36155
36449
|
// src/lib/symlink-reconcile.ts
|
|
36156
|
-
import * as
|
|
36157
|
-
import * as
|
|
36450
|
+
import * as fs75 from "node:fs";
|
|
36451
|
+
import * as path76 from "node:path";
|
|
36158
36452
|
var realFs = {
|
|
36159
|
-
readdirSync: (p) =>
|
|
36160
|
-
existsSync: (p) =>
|
|
36161
|
-
lstatSync: (p) =>
|
|
36162
|
-
readlinkSync: (p) =>
|
|
36163
|
-
symlinkSync: (t, l) =>
|
|
36164
|
-
unlinkSync: (p) =>
|
|
36453
|
+
readdirSync: (p) => fs75.readdirSync(p),
|
|
36454
|
+
existsSync: (p) => fs75.existsSync(p),
|
|
36455
|
+
lstatSync: (p) => fs75.lstatSync(p),
|
|
36456
|
+
readlinkSync: (p) => fs75.readlinkSync(p),
|
|
36457
|
+
symlinkSync: (t, l) => fs75.symlinkSync(t, l),
|
|
36458
|
+
unlinkSync: (p) => fs75.unlinkSync(p),
|
|
36165
36459
|
mkdirSync: (p, o) => {
|
|
36166
|
-
|
|
36460
|
+
fs75.mkdirSync(p, o);
|
|
36167
36461
|
}
|
|
36168
36462
|
};
|
|
36169
36463
|
function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
@@ -36173,8 +36467,8 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
|
36173
36467
|
_fs.mkdirSync(claudeSkillsDir2, { recursive: true });
|
|
36174
36468
|
const sourceSkills = _fs.existsSync(npmSkillsDir) ? _fs.readdirSync(npmSkillsDir).filter((d) => d.startsWith("olam-")) : [];
|
|
36175
36469
|
for (const skill of sourceSkills) {
|
|
36176
|
-
const linkPath =
|
|
36177
|
-
const target =
|
|
36470
|
+
const linkPath = path76.join(claudeSkillsDir2, skill);
|
|
36471
|
+
const target = path76.join(npmSkillsDir, skill);
|
|
36178
36472
|
if (!_fs.existsSync(linkPath)) {
|
|
36179
36473
|
try {
|
|
36180
36474
|
_fs.symlinkSync(target, linkPath);
|
|
@@ -36187,7 +36481,7 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
|
36187
36481
|
}
|
|
36188
36482
|
const deployedEntries = _fs.existsSync(claudeSkillsDir2) ? _fs.readdirSync(claudeSkillsDir2).filter((d) => d.startsWith("olam-")) : [];
|
|
36189
36483
|
for (const entry of deployedEntries) {
|
|
36190
|
-
const linkPath =
|
|
36484
|
+
const linkPath = path76.join(claudeSkillsDir2, entry);
|
|
36191
36485
|
let isSymlink = false;
|
|
36192
36486
|
try {
|
|
36193
36487
|
isSymlink = _fs.lstatSync(linkPath).isSymbolicLink();
|
|
@@ -36212,9 +36506,9 @@ function reconcileSkillSymlinks(npmSkillsDir, claudeSkillsDir2, _fs = realFs) {
|
|
|
36212
36506
|
|
|
36213
36507
|
// src/commands/update.ts
|
|
36214
36508
|
var PACKAGE_NAME = "@pleri/olam-cli";
|
|
36215
|
-
var CACHE_DIR2 =
|
|
36216
|
-
var LOG_DIR2 =
|
|
36217
|
-
var LAST_STABLE_FILE =
|
|
36509
|
+
var CACHE_DIR2 = path78.join(os41.homedir(), ".olam", "cache");
|
|
36510
|
+
var LOG_DIR2 = path78.join(os41.homedir(), ".olam", "log");
|
|
36511
|
+
var LAST_STABLE_FILE = path78.join(CACHE_DIR2, "last-stable.txt");
|
|
36218
36512
|
function defaultExec(cmd) {
|
|
36219
36513
|
try {
|
|
36220
36514
|
const stdout = execSync14(cmd, { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
@@ -36236,22 +36530,22 @@ function getCurrentVersion(_exec = defaultExec) {
|
|
|
36236
36530
|
}
|
|
36237
36531
|
function readLastStable(file = LAST_STABLE_FILE) {
|
|
36238
36532
|
try {
|
|
36239
|
-
const v =
|
|
36533
|
+
const v = fs77.readFileSync(file, "utf-8").trim();
|
|
36240
36534
|
return v || null;
|
|
36241
36535
|
} catch {
|
|
36242
36536
|
return null;
|
|
36243
36537
|
}
|
|
36244
36538
|
}
|
|
36245
36539
|
function writeLastStable(version, file = LAST_STABLE_FILE) {
|
|
36246
|
-
|
|
36247
|
-
|
|
36540
|
+
fs77.mkdirSync(path78.dirname(file), { recursive: true });
|
|
36541
|
+
fs77.writeFileSync(file, version, { mode: 420 });
|
|
36248
36542
|
}
|
|
36249
36543
|
function logUpdateFailure(stderr) {
|
|
36250
36544
|
const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
36251
|
-
const logFile =
|
|
36545
|
+
const logFile = path78.join(LOG_DIR2, `update-${ts}.log`);
|
|
36252
36546
|
try {
|
|
36253
|
-
|
|
36254
|
-
|
|
36547
|
+
fs77.mkdirSync(LOG_DIR2, { recursive: true });
|
|
36548
|
+
fs77.appendFileSync(logFile, `[update-failure ${(/* @__PURE__ */ new Date()).toISOString()}]
|
|
36255
36549
|
${stderr}
|
|
36256
36550
|
`, "utf-8");
|
|
36257
36551
|
} catch {
|
|
@@ -36338,8 +36632,8 @@ async function doUpdate(opts, _exec = defaultExec, _reconcile = reconcileSkillSy
|
|
|
36338
36632
|
let symlinkResult = { added: [], removed: [] };
|
|
36339
36633
|
if (npmRootResult.exitCode === 0) {
|
|
36340
36634
|
const npmRoot = npmRootResult.stdout.trim();
|
|
36341
|
-
const npmSkillsDir =
|
|
36342
|
-
const claudeSkillsDir2 =
|
|
36635
|
+
const npmSkillsDir = path78.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills");
|
|
36636
|
+
const claudeSkillsDir2 = path78.join(os41.homedir(), ".claude", "skills");
|
|
36343
36637
|
const rec = _reconcile(npmSkillsDir, claudeSkillsDir2);
|
|
36344
36638
|
symlinkResult = { added: rec.added, removed: rec.removed };
|
|
36345
36639
|
if (!quiet && (rec.added.length > 0 || rec.removed.length > 0)) {
|
|
@@ -36385,8 +36679,8 @@ async function doRollback(_exec = defaultExec, _reconcile = reconcileSkillSymlin
|
|
|
36385
36679
|
if (npmRootResult.exitCode === 0) {
|
|
36386
36680
|
const npmRoot = npmRootResult.stdout.trim();
|
|
36387
36681
|
_reconcile(
|
|
36388
|
-
|
|
36389
|
-
|
|
36682
|
+
path78.join(npmRoot, "@pleri", "olam-cli", "plugin", "skills"),
|
|
36683
|
+
path78.join(os41.homedir(), ".claude", "skills")
|
|
36390
36684
|
);
|
|
36391
36685
|
}
|
|
36392
36686
|
return { action: "rolled-back", restoredVersion: prev, exitCode: 0 };
|
|
@@ -36469,7 +36763,7 @@ function registerBegin(program2) {
|
|
|
36469
36763
|
// src/commands/config.ts
|
|
36470
36764
|
init_global_config();
|
|
36471
36765
|
init_store2();
|
|
36472
|
-
import * as
|
|
36766
|
+
import * as fs78 from "node:fs";
|
|
36473
36767
|
import { createRequire as createRequire4 } from "node:module";
|
|
36474
36768
|
var _require4 = createRequire4(import.meta.url);
|
|
36475
36769
|
var { parse: parseWithMap } = _require4("json-source-map");
|
|
@@ -36477,14 +36771,14 @@ function registerConfig(program2) {
|
|
|
36477
36771
|
const config = program2.command("config").description("Manage global olam configuration");
|
|
36478
36772
|
config.command("validate [path]").description("Validate ~/.olam/config.json (or a custom path) against the schema").action((filePath) => {
|
|
36479
36773
|
const resolvedPath = filePath ?? globalConfigPath();
|
|
36480
|
-
if (!
|
|
36774
|
+
if (!fs78.existsSync(resolvedPath)) {
|
|
36481
36775
|
process.stderr.write(`config file not found: ${resolvedPath}
|
|
36482
36776
|
`);
|
|
36483
36777
|
process.exit(1);
|
|
36484
36778
|
}
|
|
36485
36779
|
let raw;
|
|
36486
36780
|
try {
|
|
36487
|
-
raw =
|
|
36781
|
+
raw = fs78.readFileSync(resolvedPath, "utf-8");
|
|
36488
36782
|
} catch (err) {
|
|
36489
36783
|
const msg = err instanceof Error ? err.message : String(err);
|
|
36490
36784
|
process.stderr.write(`cannot read ${resolvedPath}: ${msg}
|
|
@@ -36742,9 +37036,9 @@ import * as readline2 from "node:readline";
|
|
|
36742
37036
|
import pc32 from "picocolors";
|
|
36743
37037
|
|
|
36744
37038
|
// src/commands/flywheel/install-shims.ts
|
|
36745
|
-
import { copyFileSync as copyFileSync9, existsSync as existsSync88, mkdirSync as mkdirSync53, readFileSync as
|
|
37039
|
+
import { copyFileSync as copyFileSync9, existsSync as existsSync88, mkdirSync as mkdirSync53, readFileSync as readFileSync71, writeFileSync as writeFileSync44 } from "node:fs";
|
|
36746
37040
|
import { homedir as homedir46 } from "node:os";
|
|
36747
|
-
import { dirname as dirname48, join as
|
|
37041
|
+
import { dirname as dirname48, join as join85 } from "node:path";
|
|
36748
37042
|
|
|
36749
37043
|
// src/lib/shim-generator.ts
|
|
36750
37044
|
var SHIM_SPECS = Object.freeze([
|
|
@@ -36807,7 +37101,7 @@ ${argsBlock}
|
|
|
36807
37101
|
// src/commands/flywheel/install-shims.ts
|
|
36808
37102
|
var SHIM_HEADER_MARKER = "# AUTO-GENERATED by `olam flywheel install-shims`";
|
|
36809
37103
|
function refreshShims(opts = {}) {
|
|
36810
|
-
const targetDir = opts.targetDir ??
|
|
37104
|
+
const targetDir = opts.targetDir ?? join85(homedir46(), ".claude", "scripts");
|
|
36811
37105
|
const results = [];
|
|
36812
37106
|
let written = 0;
|
|
36813
37107
|
let overwritten = 0;
|
|
@@ -36837,7 +37131,7 @@ function isOlamGeneratedShim(text) {
|
|
|
36837
37131
|
return text.includes(SHIM_HEADER_MARKER);
|
|
36838
37132
|
}
|
|
36839
37133
|
function installOne(spec, targetDir, opts) {
|
|
36840
|
-
const targetPath =
|
|
37134
|
+
const targetPath = join85(targetDir, spec.basename);
|
|
36841
37135
|
const newContent = generateShim(spec);
|
|
36842
37136
|
if (!existsSync88(targetPath)) {
|
|
36843
37137
|
if (opts.dryRun !== true) {
|
|
@@ -36846,7 +37140,7 @@ function installOne(spec, targetDir, opts) {
|
|
|
36846
37140
|
}
|
|
36847
37141
|
return { basename: spec.basename, action: "written", targetPath };
|
|
36848
37142
|
}
|
|
36849
|
-
const existing =
|
|
37143
|
+
const existing = readFileSync71(targetPath, "utf8");
|
|
36850
37144
|
if (existing === newContent) {
|
|
36851
37145
|
return { basename: spec.basename, action: "unchanged", targetPath };
|
|
36852
37146
|
}
|
|
@@ -36868,7 +37162,7 @@ function installOne(spec, targetDir, opts) {
|
|
|
36868
37162
|
}
|
|
36869
37163
|
function registerFlywheelInstallShims(parent) {
|
|
36870
37164
|
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) => {
|
|
36871
|
-
const targetDir = opts.targetDir ??
|
|
37165
|
+
const targetDir = opts.targetDir ?? join85(homedir46(), ".claude", "scripts");
|
|
36872
37166
|
const summary2 = refreshShims(opts);
|
|
36873
37167
|
const lines = [];
|
|
36874
37168
|
const dryRunSuffix = opts.dryRun === true ? " (dry-run)" : "";
|
|
@@ -36975,16 +37269,28 @@ function registerSkillsSource(program2) {
|
|
|
36975
37269
|
const when = new Date(s.addedAt).toISOString().slice(0, 10);
|
|
36976
37270
|
const sha = s.lastPulledSha ? s.lastPulledSha.slice(0, 8) : pc32.dim("(unpulled)");
|
|
36977
37271
|
const ord = pc32.dim(`[${i + 1}]`);
|
|
37272
|
+
const prefixCol = s.prefix ? pc32.cyan(s.prefix.padEnd(12)) : pc32.dim("\u2014".padEnd(12));
|
|
36978
37273
|
console.log(
|
|
36979
|
-
` ${ord} ${pc32.bold(s.id.padEnd(14))} ${s.name.padEnd(24)} ${s.branch.padEnd(12)} ${sha.padEnd(12)} ${pc32.dim(when)} ${pc32.dim(s.gitUrl)}`
|
|
37274
|
+
` ${ord} ${pc32.bold(s.id.padEnd(14))} ${s.name.padEnd(24)} ${s.branch.padEnd(12)} ${sha.padEnd(12)} ${prefixCol} ${pc32.dim(when)} ${pc32.dim(s.gitUrl)}`
|
|
36980
37275
|
);
|
|
36981
37276
|
}
|
|
36982
37277
|
});
|
|
36983
|
-
source.command("add").description("Register and clone a skill source (T6 capability-class: requires --trust OR interactive ack)").requiredOption("--name <name>", "Display name (lowercase, digits, dash)").requiredOption("--git-url <url>", "git URL (https://, git@, ssh://, file://, or absolute path)").option("--branch <branch>", "Branch to track", "main").option(
|
|
37278
|
+
source.command("add").description("Register and clone a skill source (T6 capability-class: requires --trust OR interactive ack)").requiredOption("--name <name>", "Display name (lowercase, digits, dash)").requiredOption("--git-url <url>", "git URL (https://, git@, ssh://, file://, or absolute path)").option("--branch <branch>", "Branch to track", "main").option(
|
|
37279
|
+
"--prefix <prefix>",
|
|
37280
|
+
'Deploy prefix: skills+agents from this source deploy as <prefix>:<canonical-name> (e.g. "atl", "pln"). Must match /^[a-z0-9][a-z0-9_-]{0,38}$/'
|
|
37281
|
+
).option("--trust", "Acknowledge that registering grants symlink-into-~/.claude permission (skips interactive picker)").option("--sync-now", "Run `olam skills sync` immediately after add (skips interactive prompt)").option("--no-sync-now", "Skip the post-add sync (skips interactive prompt)").option("--install-hook", "Install the SessionStart hook after add (skips interactive prompt)").option("--no-install-hook", "Skip installing the SessionStart hook (skips interactive prompt)").option(
|
|
36984
37282
|
"--hook-scope <scope>",
|
|
36985
37283
|
"When installing the hook (post-add): project (<cwd>/.claude) or user (~/.claude)",
|
|
36986
37284
|
"project"
|
|
36987
37285
|
).action(async (opts) => {
|
|
37286
|
+
const PREFIX_PATTERN3 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
37287
|
+
if (opts.prefix !== void 0 && !PREFIX_PATTERN3.test(opts.prefix)) {
|
|
37288
|
+
printError(
|
|
37289
|
+
`prefix must match /^[a-z0-9][a-z0-9_-]{0,38}$/ \u2014 got "${opts.prefix}"`
|
|
37290
|
+
);
|
|
37291
|
+
process.exitCode = 1;
|
|
37292
|
+
return;
|
|
37293
|
+
}
|
|
36988
37294
|
const isTTY = Boolean(process.stdout.isTTY);
|
|
36989
37295
|
const testPromptFn = globalThis.__olamTestTrustPrompt;
|
|
36990
37296
|
let decision;
|
|
@@ -37022,6 +37328,9 @@ function registerSkillsSource(program2) {
|
|
|
37022
37328
|
branch: opts.branch,
|
|
37023
37329
|
trustMethod: decision.method
|
|
37024
37330
|
});
|
|
37331
|
+
if (opts.prefix !== void 0) {
|
|
37332
|
+
updateSkillSource(entry.id, { prefix: opts.prefix });
|
|
37333
|
+
}
|
|
37025
37334
|
} catch (err) {
|
|
37026
37335
|
try {
|
|
37027
37336
|
appendTrustAudit({
|
|
@@ -37231,14 +37540,50 @@ function registerSkillsSource(program2) {
|
|
|
37231
37540
|
console.log(`${pc32.bold("lastPulledSha:")} ${entry.lastPulledSha ?? pc32.dim("(unpulled)")}`);
|
|
37232
37541
|
console.log(`${pc32.bold("clonePath:")} ${skillSourceClonePath(entry.id)}`);
|
|
37233
37542
|
});
|
|
37543
|
+
source.command("set-prefix").description(
|
|
37544
|
+
"Set the deploy prefix for a registered skill source (skills+agents deploy as <prefix>:<canonical-name>)"
|
|
37545
|
+
).argument("<name>", 'Display name of the skill source (from "olam skills source list")').argument("<prefix>", "Prefix value (must match /^[a-z0-9][a-z0-9_-]{0,38}$/)").action((name, prefix) => {
|
|
37546
|
+
const entry = getSkillSourceByName(name);
|
|
37547
|
+
if (entry === null) {
|
|
37548
|
+
printError(
|
|
37549
|
+
`skill source "${name}" is not registered. Run "olam skills source list" to see registered sources.`
|
|
37550
|
+
);
|
|
37551
|
+
process.exitCode = 1;
|
|
37552
|
+
return;
|
|
37553
|
+
}
|
|
37554
|
+
try {
|
|
37555
|
+
updateSkillSource(entry.id, { prefix });
|
|
37556
|
+
printSuccess(`set prefix "${prefix}" on source "${name}" (${entry.id})`);
|
|
37557
|
+
} catch (err) {
|
|
37558
|
+
printError(asMessage3(err));
|
|
37559
|
+
process.exitCode = 1;
|
|
37560
|
+
}
|
|
37561
|
+
});
|
|
37562
|
+
source.command("unset-prefix").description("Remove the deploy prefix from a registered skill source (reverts to canonical deploy names)").argument("<name>", 'Display name of the skill source (from "olam skills source list")').action((name) => {
|
|
37563
|
+
const entry = getSkillSourceByName(name);
|
|
37564
|
+
if (entry === null) {
|
|
37565
|
+
printError(
|
|
37566
|
+
`skill source "${name}" is not registered. Run "olam skills source list" to see registered sources.`
|
|
37567
|
+
);
|
|
37568
|
+
process.exitCode = 1;
|
|
37569
|
+
return;
|
|
37570
|
+
}
|
|
37571
|
+
try {
|
|
37572
|
+
updateSkillSource(entry.id, { prefix: null });
|
|
37573
|
+
printSuccess(`unset prefix on source "${name}" (${entry.id})`);
|
|
37574
|
+
} catch (err) {
|
|
37575
|
+
printError(asMessage3(err));
|
|
37576
|
+
process.exitCode = 1;
|
|
37577
|
+
}
|
|
37578
|
+
});
|
|
37234
37579
|
}
|
|
37235
37580
|
|
|
37236
37581
|
// src/commands/skills.ts
|
|
37237
37582
|
init_skill_sources();
|
|
37238
37583
|
init_output();
|
|
37239
|
-
import * as
|
|
37584
|
+
import * as fs79 from "node:fs";
|
|
37240
37585
|
import * as os42 from "node:os";
|
|
37241
|
-
import * as
|
|
37586
|
+
import * as path79 from "node:path";
|
|
37242
37587
|
import * as readline3 from "node:readline";
|
|
37243
37588
|
import pc33 from "picocolors";
|
|
37244
37589
|
|
|
@@ -37251,14 +37596,14 @@ import {
|
|
|
37251
37596
|
lstatSync as lstatSync8,
|
|
37252
37597
|
mkdirSync as mkdirSync54,
|
|
37253
37598
|
readdirSync as readdirSync26,
|
|
37254
|
-
readFileSync as
|
|
37599
|
+
readFileSync as readFileSync72,
|
|
37255
37600
|
readlinkSync as readlinkSync4,
|
|
37256
37601
|
rmSync as rmSync9,
|
|
37257
37602
|
statSync as statSync27,
|
|
37258
37603
|
writeFileSync as writeFileSync45
|
|
37259
37604
|
} from "node:fs";
|
|
37260
37605
|
import { homedir as homedir47 } from "node:os";
|
|
37261
|
-
import { basename as basename8, dirname as dirname49, isAbsolute as isAbsolute4, join as
|
|
37606
|
+
import { basename as basename8, dirname as dirname49, isAbsolute as isAbsolute4, join as join86, relative as relative5, resolve as resolve21 } from "node:path";
|
|
37262
37607
|
|
|
37263
37608
|
// src/commands/flywheel/sanitize-persona-output.ts
|
|
37264
37609
|
var FORBIDDEN_HEADERS = [
|
|
@@ -37320,7 +37665,7 @@ function registerFlywheelSanitizePersonaOutput(parent) {
|
|
|
37320
37665
|
|
|
37321
37666
|
// src/lib/skills-apply-overlays.ts
|
|
37322
37667
|
function claudeRoot(opts) {
|
|
37323
|
-
return opts.claudeDir ?? opts.fixtureRoot ??
|
|
37668
|
+
return opts.claudeDir ?? opts.fixtureRoot ?? join86(homedir47(), ".claude");
|
|
37324
37669
|
}
|
|
37325
37670
|
function ensureRealDir(p) {
|
|
37326
37671
|
if (!existsSync89(p)) {
|
|
@@ -37335,8 +37680,8 @@ function ensureRealDir(p) {
|
|
|
37335
37680
|
mkdirSync54(p, { recursive: true });
|
|
37336
37681
|
if (existsSync89(target) && statSync27(target).isDirectory()) {
|
|
37337
37682
|
for (const entry of readdirSync26(target)) {
|
|
37338
|
-
const src =
|
|
37339
|
-
const dest =
|
|
37683
|
+
const src = join86(target, entry);
|
|
37684
|
+
const dest = join86(p, entry);
|
|
37340
37685
|
const srcStat = lstatSync8(src);
|
|
37341
37686
|
if (srcStat.isDirectory()) {
|
|
37342
37687
|
try {
|
|
@@ -37358,8 +37703,8 @@ function postMergeSanitize(mergedText, label) {
|
|
|
37358
37703
|
return { ok: false, reason: `[post-merge-sanitize] ${label} merged output failed sanitizer: ${result.reason}` };
|
|
37359
37704
|
}
|
|
37360
37705
|
function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages) {
|
|
37361
|
-
const upstreamText =
|
|
37362
|
-
const overlayText =
|
|
37706
|
+
const upstreamText = readFileSync72(upstreamPath, "utf8");
|
|
37707
|
+
const overlayText = readFileSync72(overlayPath, "utf8");
|
|
37363
37708
|
const result = mergeMarkdown(upstreamText, overlayText, label, upstreamPath, overlayPath);
|
|
37364
37709
|
if ("error" in result) {
|
|
37365
37710
|
messages.push(`ERROR ${result.error.reason}`);
|
|
@@ -37379,7 +37724,7 @@ function mergeOne(upstreamPath, overlayPath, destPath2, label, dryRun, messages)
|
|
|
37379
37724
|
}
|
|
37380
37725
|
function isNewAgentOverlay(overlayPath) {
|
|
37381
37726
|
try {
|
|
37382
|
-
const text =
|
|
37727
|
+
const text = readFileSync72(overlayPath, "utf8");
|
|
37383
37728
|
const { fm } = parseFrontmatter3(text);
|
|
37384
37729
|
return fm["overlay-intent"] === "new-agent";
|
|
37385
37730
|
} catch {
|
|
@@ -37396,9 +37741,9 @@ function copyNewAgent(overlayPath, destPath2, label, dryRun, messages) {
|
|
|
37396
37741
|
function walkSkillsOverlays(skillsOverridesDir, skillsDir, opts, result) {
|
|
37397
37742
|
if (!existsSync89(skillsOverridesDir)) return;
|
|
37398
37743
|
for (const skillName of readdirSync26(skillsOverridesDir)) {
|
|
37399
|
-
const overlaySkillDir =
|
|
37744
|
+
const overlaySkillDir = join86(skillsOverridesDir, skillName);
|
|
37400
37745
|
if (!statSync27(overlaySkillDir).isDirectory()) continue;
|
|
37401
|
-
const upstreamSkillDir =
|
|
37746
|
+
const upstreamSkillDir = join86(skillsDir, skillName);
|
|
37402
37747
|
if (!existsSync89(upstreamSkillDir)) {
|
|
37403
37748
|
result.messages.push(`SKIP ${skillName}: no upstream skill at ${upstreamSkillDir} (skill overlays require an upstream skill dir)`);
|
|
37404
37749
|
continue;
|
|
@@ -37412,7 +37757,7 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
|
|
|
37412
37757
|
while (stack.length > 0) {
|
|
37413
37758
|
const current = stack.pop();
|
|
37414
37759
|
for (const entry of readdirSync26(current)) {
|
|
37415
|
-
const overlayPath =
|
|
37760
|
+
const overlayPath = join86(current, entry);
|
|
37416
37761
|
const stat = lstatSync8(overlayPath);
|
|
37417
37762
|
if (stat.isDirectory()) {
|
|
37418
37763
|
stack.push(overlayPath);
|
|
@@ -37420,7 +37765,7 @@ function walkOverlayTree(overlayRoot, upstreamRoot, labelPrefix, opts, result, i
|
|
|
37420
37765
|
}
|
|
37421
37766
|
if (!stat.isFile() && !stat.isSymbolicLink()) continue;
|
|
37422
37767
|
const rel = relative5(overlayRoot, overlayPath);
|
|
37423
|
-
const upstreamPath =
|
|
37768
|
+
const upstreamPath = join86(upstreamRoot, rel);
|
|
37424
37769
|
const label = `${labelPrefix} ${rel}`;
|
|
37425
37770
|
if (!entry.endsWith(".md")) {
|
|
37426
37771
|
if (!opts.dryRun) {
|
|
@@ -37465,10 +37810,10 @@ function walkAgentsOverlays(agentsOverridesDir, agentsDir, opts, result) {
|
|
|
37465
37810
|
}
|
|
37466
37811
|
async function applyOverlays(opts = {}) {
|
|
37467
37812
|
const root = claudeRoot(opts);
|
|
37468
|
-
const skillsDir =
|
|
37469
|
-
const agentsDir =
|
|
37470
|
-
const skillsOverridesDir =
|
|
37471
|
-
const agentsOverridesDir =
|
|
37813
|
+
const skillsDir = join86(root, "skills");
|
|
37814
|
+
const agentsDir = join86(root, "agents");
|
|
37815
|
+
const skillsOverridesDir = join86(root, "skills.overrides");
|
|
37816
|
+
const agentsOverridesDir = join86(root, "agents.overrides");
|
|
37472
37817
|
const result = {
|
|
37473
37818
|
rc: 0,
|
|
37474
37819
|
skillsMerged: 0,
|
|
@@ -37517,12 +37862,12 @@ function asMessage4(err) {
|
|
|
37517
37862
|
}
|
|
37518
37863
|
var ATLAS_USER_PICKER_RE = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
37519
37864
|
function listMemberNames(clonePath) {
|
|
37520
|
-
const membersDir =
|
|
37521
|
-
if (!
|
|
37865
|
+
const membersDir = path79.join(clonePath, "members");
|
|
37866
|
+
if (!fs79.existsSync(membersDir)) return [];
|
|
37522
37867
|
try {
|
|
37523
|
-
return
|
|
37868
|
+
return fs79.readdirSync(membersDir).filter((e) => {
|
|
37524
37869
|
try {
|
|
37525
|
-
return
|
|
37870
|
+
return fs79.statSync(path79.join(membersDir, e)).isDirectory();
|
|
37526
37871
|
} catch {
|
|
37527
37872
|
return false;
|
|
37528
37873
|
}
|
|
@@ -37543,10 +37888,10 @@ function defaultAtlasUserPrompt(question) {
|
|
|
37543
37888
|
async function resolveAtlasUserWithPicker(cliOverride, opts) {
|
|
37544
37889
|
if (cliOverride !== void 0) return cliOverride;
|
|
37545
37890
|
const ATLAS_USER_RE2 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
37546
|
-
const claudeDirPathForRead = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ??
|
|
37547
|
-
const atlasUserFile =
|
|
37548
|
-
if (
|
|
37549
|
-
const existing =
|
|
37891
|
+
const claudeDirPathForRead = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path79.join(os42.homedir(), ".claude"));
|
|
37892
|
+
const atlasUserFile = path79.join(claudeDirPathForRead, ".atlas-user");
|
|
37893
|
+
if (fs79.existsSync(atlasUserFile)) {
|
|
37894
|
+
const existing = fs79.readFileSync(atlasUserFile, "utf-8").trim();
|
|
37550
37895
|
if (existing.length > 0) {
|
|
37551
37896
|
if (ATLAS_USER_RE2.test(existing)) {
|
|
37552
37897
|
return existing;
|
|
@@ -37605,10 +37950,10 @@ async function resolveAtlasUserWithPicker(cliOverride, opts) {
|
|
|
37605
37950
|
);
|
|
37606
37951
|
return void 0;
|
|
37607
37952
|
}
|
|
37608
|
-
const claudeDirPath = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ??
|
|
37609
|
-
|
|
37610
|
-
|
|
37611
|
-
process.stdout.write(pc33.green(`\u2713 atlas-user set to "${picked}" (written to ${
|
|
37953
|
+
const claudeDirPath = opts?._testClaudeDir ?? (process.env["OLAM_CLAUDE_DIR"] ?? path79.join(os42.homedir(), ".claude"));
|
|
37954
|
+
fs79.mkdirSync(claudeDirPath, { recursive: true });
|
|
37955
|
+
fs79.writeFileSync(path79.join(claudeDirPath, ".atlas-user"), picked + "\n", "utf8");
|
|
37956
|
+
process.stdout.write(pc33.green(`\u2713 atlas-user set to "${picked}" (written to ${path79.join(claudeDirPath, ".atlas-user")})
|
|
37612
37957
|
`));
|
|
37613
37958
|
return picked;
|
|
37614
37959
|
}
|
|
@@ -37620,14 +37965,14 @@ function listDeployed() {
|
|
|
37620
37965
|
);
|
|
37621
37966
|
const entries = [];
|
|
37622
37967
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
37623
|
-
const bucketDir =
|
|
37624
|
-
if (!
|
|
37625
|
-
for (const name of
|
|
37626
|
-
const full =
|
|
37968
|
+
const bucketDir = path79.join(dir, bucket);
|
|
37969
|
+
if (!fs79.existsSync(bucketDir)) continue;
|
|
37970
|
+
for (const name of fs79.readdirSync(bucketDir)) {
|
|
37971
|
+
const full = path79.join(bucketDir, name);
|
|
37627
37972
|
try {
|
|
37628
|
-
const stat =
|
|
37973
|
+
const stat = fs79.lstatSync(full);
|
|
37629
37974
|
if (!stat.isSymbolicLink()) continue;
|
|
37630
|
-
const target =
|
|
37975
|
+
const target = fs79.readlinkSync(full);
|
|
37631
37976
|
let sourceId;
|
|
37632
37977
|
for (const [clonePath, id] of sourcePaths.entries()) {
|
|
37633
37978
|
if (target.startsWith(clonePath)) {
|
|
@@ -37702,6 +38047,19 @@ function printSyncSummary(summary2, dryRun) {
|
|
|
37702
38047
|
console.log(` ${pc33.red(" (migrate-hooks-back will not be able to undo this sync)")}`);
|
|
37703
38048
|
}
|
|
37704
38049
|
}
|
|
38050
|
+
if (summary2.prefixRewrites.length > 0) {
|
|
38051
|
+
console.log(` prefix rewrites: ${summary2.prefixRewrites.length}`);
|
|
38052
|
+
}
|
|
38053
|
+
if (summary2.prefixCollisions.length > 0) {
|
|
38054
|
+
const allSources = summary2.perSource;
|
|
38055
|
+
for (const col of summary2.prefixCollisions) {
|
|
38056
|
+
const winnerName = allSources.find((s) => s.sourceId === col.winnerSourceId)?.name ?? col.winnerSourceId.slice(0, 8);
|
|
38057
|
+
const loserNames = col.loserSourceIds.map((id) => allSources.find((s) => s.sourceId === id)?.name ?? id.slice(0, 8)).join(", ");
|
|
38058
|
+
console.log(
|
|
38059
|
+
` ${pc33.yellow(`\u26A0 prefix collision: '${col.prefix}' used by ${winnerName} (winner) + ${loserNames}; first-registered wins`)}`
|
|
38060
|
+
);
|
|
38061
|
+
}
|
|
38062
|
+
}
|
|
37705
38063
|
console.log();
|
|
37706
38064
|
for (const s of summary2.perSource) {
|
|
37707
38065
|
const sub = s.fromSubscriptionsFile ? "(subscribed)" : "(all categories)";
|
|
@@ -37813,12 +38171,12 @@ function registerSkills(program2) {
|
|
|
37813
38171
|
// src/commands/skills-hook.ts
|
|
37814
38172
|
init_skill_sources();
|
|
37815
38173
|
init_output();
|
|
37816
|
-
import * as
|
|
38174
|
+
import * as fs80 from "node:fs";
|
|
37817
38175
|
function backup(filePath) {
|
|
37818
|
-
if (!
|
|
38176
|
+
if (!fs80.existsSync(filePath)) return null;
|
|
37819
38177
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
37820
38178
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
37821
|
-
|
|
38179
|
+
fs80.copyFileSync(filePath, backupPath);
|
|
37822
38180
|
return backupPath;
|
|
37823
38181
|
}
|
|
37824
38182
|
function registerSkillsHook(program2) {
|
|
@@ -37866,7 +38224,7 @@ function registerSkillsHook(program2) {
|
|
|
37866
38224
|
printInfo("olam-skills hook", `not found in ${filePath} \u2014 already uninstalled`);
|
|
37867
38225
|
if (backupPath) {
|
|
37868
38226
|
try {
|
|
37869
|
-
|
|
38227
|
+
fs80.unlinkSync(backupPath);
|
|
37870
38228
|
} catch {
|
|
37871
38229
|
}
|
|
37872
38230
|
}
|
|
@@ -38048,24 +38406,24 @@ init_skill_sources();
|
|
|
38048
38406
|
init_merge_settings();
|
|
38049
38407
|
init_skill_sources();
|
|
38050
38408
|
init_output();
|
|
38051
|
-
import * as
|
|
38052
|
-
import * as
|
|
38409
|
+
import * as fs81 from "node:fs";
|
|
38410
|
+
import * as path80 from "node:path";
|
|
38053
38411
|
var MIGRATE_FROM_TOOLBOX_COMMAND = "migrate-from-toolbox";
|
|
38054
38412
|
function asMessage6(err) {
|
|
38055
38413
|
return err instanceof Error ? err.message : String(err);
|
|
38056
38414
|
}
|
|
38057
38415
|
function isOlamSkillsHookPresent(filePath) {
|
|
38058
|
-
if (!
|
|
38416
|
+
if (!fs81.existsSync(filePath)) return false;
|
|
38059
38417
|
try {
|
|
38060
|
-
const raw =
|
|
38418
|
+
const raw = fs81.readFileSync(filePath, "utf-8");
|
|
38061
38419
|
return raw.includes(OLAM_SKILLS_HOOK_SENTINEL);
|
|
38062
38420
|
} catch {
|
|
38063
38421
|
return false;
|
|
38064
38422
|
}
|
|
38065
38423
|
}
|
|
38066
38424
|
function uninstallLegacyToolboxSessionStartHook(filePath, toolboxPath) {
|
|
38067
|
-
if (!
|
|
38068
|
-
const raw =
|
|
38425
|
+
if (!fs81.existsSync(filePath)) return { removed: 0 };
|
|
38426
|
+
const raw = fs81.readFileSync(filePath, "utf-8");
|
|
38069
38427
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
38070
38428
|
const ss = settings?.hooks?.SessionStart;
|
|
38071
38429
|
if (!Array.isArray(ss)) return { removed: 0 };
|
|
@@ -38094,7 +38452,7 @@ function uninstallLegacyToolboxSessionStartHook(filePath, toolboxPath) {
|
|
|
38094
38452
|
if (otherStages.length === 0) delete next.hooks;
|
|
38095
38453
|
else delete next.hooks.SessionStart;
|
|
38096
38454
|
}
|
|
38097
|
-
|
|
38455
|
+
fs81.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
38098
38456
|
return { removed };
|
|
38099
38457
|
}
|
|
38100
38458
|
function registerSkillsMigrate(program2) {
|
|
@@ -38117,7 +38475,7 @@ function registerSkillsMigrate(program2) {
|
|
|
38117
38475
|
return;
|
|
38118
38476
|
}
|
|
38119
38477
|
const toolboxPath = opts.path;
|
|
38120
|
-
const namespace = opts.namespace ??
|
|
38478
|
+
const namespace = opts.namespace ?? path80.basename(toolboxPath);
|
|
38121
38479
|
const sourceName = opts.sourceName ?? namespace;
|
|
38122
38480
|
const snapshot = detectToolboxState({ toolboxPath, namespace });
|
|
38123
38481
|
if (!snapshot) {
|
|
@@ -38171,9 +38529,9 @@ function registerSkillsMigrate(program2) {
|
|
|
38171
38529
|
printWarning(`legacy hook removal failed: ${asMessage6(err)}; proceeding`);
|
|
38172
38530
|
}
|
|
38173
38531
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
38174
|
-
const olamHookPath = scope === "user" ? settingsFile :
|
|
38532
|
+
const olamHookPath = scope === "user" ? settingsFile : path80.join(process.cwd(), ".claude", "settings.json");
|
|
38175
38533
|
try {
|
|
38176
|
-
|
|
38534
|
+
fs81.mkdirSync(path80.dirname(olamHookPath), { recursive: true });
|
|
38177
38535
|
const result = mergeHomeSettingsJson(olamHookPath, {
|
|
38178
38536
|
ensureHook: {
|
|
38179
38537
|
stage: OLAM_SKILLS_HOOK_STAGE,
|
|
@@ -38206,8 +38564,8 @@ function registerSkillsMigrate(program2) {
|
|
|
38206
38564
|
// src/commands/skills-migrate-back.ts
|
|
38207
38565
|
init_skill_sources();
|
|
38208
38566
|
init_output();
|
|
38209
|
-
import * as
|
|
38210
|
-
import * as
|
|
38567
|
+
import * as fs82 from "node:fs";
|
|
38568
|
+
import * as path81 from "node:path";
|
|
38211
38569
|
var MIGRATE_BACK_TO_TOOLBOX_COMMAND = "migrate-back-to-toolbox";
|
|
38212
38570
|
function asMessage7(err) {
|
|
38213
38571
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -38215,16 +38573,16 @@ function asMessage7(err) {
|
|
|
38215
38573
|
function claudeDirInternal4() {
|
|
38216
38574
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
38217
38575
|
if (override && override.length > 0) return override;
|
|
38218
|
-
return
|
|
38576
|
+
return path81.join(process.env["HOME"] ?? "", ".claude");
|
|
38219
38577
|
}
|
|
38220
38578
|
function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
|
|
38221
38579
|
if (!originalSessionStartHook || originalSessionStartHook.length === 0) {
|
|
38222
38580
|
return { restored: false };
|
|
38223
38581
|
}
|
|
38224
38582
|
let settings;
|
|
38225
|
-
if (
|
|
38583
|
+
if (fs82.existsSync(filePath)) {
|
|
38226
38584
|
try {
|
|
38227
|
-
const raw =
|
|
38585
|
+
const raw = fs82.readFileSync(filePath, "utf-8");
|
|
38228
38586
|
settings = raw.trim() ? JSON.parse(raw) : {};
|
|
38229
38587
|
} catch {
|
|
38230
38588
|
settings = {};
|
|
@@ -38240,8 +38598,8 @@ function restoreSessionStartFromSnapshot(filePath, originalSessionStartHook) {
|
|
|
38240
38598
|
SessionStart: originalSessionStartHook
|
|
38241
38599
|
}
|
|
38242
38600
|
};
|
|
38243
|
-
|
|
38244
|
-
|
|
38601
|
+
fs82.mkdirSync(path81.dirname(filePath), { recursive: true });
|
|
38602
|
+
fs82.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
38245
38603
|
return { restored: true };
|
|
38246
38604
|
}
|
|
38247
38605
|
function removeOlamManagedSymlinks() {
|
|
@@ -38250,16 +38608,16 @@ function removeOlamManagedSymlinks() {
|
|
|
38250
38608
|
const olamClonePaths = sources.map((s) => skillSourceClonePath(s.id));
|
|
38251
38609
|
let removed = 0;
|
|
38252
38610
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
38253
|
-
const dir =
|
|
38254
|
-
if (!
|
|
38255
|
-
for (const name of
|
|
38256
|
-
const linkPath =
|
|
38611
|
+
const dir = path81.join(claude, bucket);
|
|
38612
|
+
if (!fs82.existsSync(dir)) continue;
|
|
38613
|
+
for (const name of fs82.readdirSync(dir)) {
|
|
38614
|
+
const linkPath = path81.join(dir, name);
|
|
38257
38615
|
try {
|
|
38258
|
-
const stat =
|
|
38616
|
+
const stat = fs82.lstatSync(linkPath);
|
|
38259
38617
|
if (!stat.isSymbolicLink()) continue;
|
|
38260
|
-
const target =
|
|
38618
|
+
const target = fs82.readlinkSync(linkPath);
|
|
38261
38619
|
if (olamClonePaths.some((cp) => target.startsWith(cp))) {
|
|
38262
|
-
|
|
38620
|
+
fs82.unlinkSync(linkPath);
|
|
38263
38621
|
removed += 1;
|
|
38264
38622
|
}
|
|
38265
38623
|
} catch {
|
|
@@ -38272,18 +38630,18 @@ function restoreToolboxSymlinks(symlinks) {
|
|
|
38272
38630
|
let restored = 0;
|
|
38273
38631
|
for (const { link, target } of symlinks) {
|
|
38274
38632
|
try {
|
|
38275
|
-
|
|
38276
|
-
if (
|
|
38633
|
+
fs82.mkdirSync(path81.dirname(link), { recursive: true });
|
|
38634
|
+
if (fs82.existsSync(link) || (() => {
|
|
38277
38635
|
try {
|
|
38278
|
-
|
|
38636
|
+
fs82.lstatSync(link);
|
|
38279
38637
|
return true;
|
|
38280
38638
|
} catch {
|
|
38281
38639
|
return false;
|
|
38282
38640
|
}
|
|
38283
38641
|
})()) {
|
|
38284
|
-
|
|
38642
|
+
fs82.unlinkSync(link);
|
|
38285
38643
|
}
|
|
38286
|
-
|
|
38644
|
+
fs82.symlinkSync(target, link);
|
|
38287
38645
|
restored += 1;
|
|
38288
38646
|
} catch {
|
|
38289
38647
|
}
|
|
@@ -38292,9 +38650,9 @@ function restoreToolboxSymlinks(symlinks) {
|
|
|
38292
38650
|
}
|
|
38293
38651
|
function restoreAtlasUserMarker(atlasUser) {
|
|
38294
38652
|
if (!atlasUser) return false;
|
|
38295
|
-
const file =
|
|
38296
|
-
|
|
38297
|
-
|
|
38653
|
+
const file = path81.join(claudeDirInternal4(), ".atlas-user");
|
|
38654
|
+
fs82.mkdirSync(path81.dirname(file), { recursive: true });
|
|
38655
|
+
fs82.writeFileSync(file, atlasUser);
|
|
38298
38656
|
return true;
|
|
38299
38657
|
}
|
|
38300
38658
|
function registerSkillsMigrateBack(program2) {
|
|
@@ -38307,15 +38665,15 @@ function registerSkillsMigrateBack(program2) {
|
|
|
38307
38665
|
let snapshot;
|
|
38308
38666
|
try {
|
|
38309
38667
|
if (opts.snapshot) {
|
|
38310
|
-
snapshotPath =
|
|
38311
|
-
if (!
|
|
38668
|
+
snapshotPath = path81.resolve(opts.snapshot);
|
|
38669
|
+
if (!fs82.existsSync(snapshotPath)) {
|
|
38312
38670
|
printError(`snapshot not found at ${snapshotPath}`);
|
|
38313
38671
|
process.exitCode = 1;
|
|
38314
38672
|
return;
|
|
38315
38673
|
}
|
|
38316
38674
|
snapshot = readMigrationSnapshotFromPath(snapshotPath);
|
|
38317
38675
|
} else {
|
|
38318
|
-
const filterNamespace = opts.namespace ?? (opts.path ?
|
|
38676
|
+
const filterNamespace = opts.namespace ?? (opts.path ? path81.basename(opts.path) : void 0);
|
|
38319
38677
|
const latest = readLatestMigrationSnapshot({ namespace: filterNamespace });
|
|
38320
38678
|
if (!latest) {
|
|
38321
38679
|
const where = filterNamespace ? ` for namespace "${filterNamespace}"` : "";
|
|
@@ -38392,8 +38750,8 @@ init_meta_hooks_migration_snapshot();
|
|
|
38392
38750
|
init_trust_audit_log();
|
|
38393
38751
|
init_atlas_hook_strip();
|
|
38394
38752
|
init_output();
|
|
38395
|
-
import * as
|
|
38396
|
-
import * as
|
|
38753
|
+
import * as fs83 from "node:fs";
|
|
38754
|
+
import * as path82 from "node:path";
|
|
38397
38755
|
import pc35 from "picocolors";
|
|
38398
38756
|
var MIGRATE_HOOKS_COMMAND = "migrate-hooks";
|
|
38399
38757
|
function settingsHasOlamMetaSentinel(settings) {
|
|
@@ -38414,16 +38772,16 @@ function settingsHasOlamMetaSentinel(settings) {
|
|
|
38414
38772
|
return false;
|
|
38415
38773
|
}
|
|
38416
38774
|
function readSettings2(filePath) {
|
|
38417
|
-
if (!
|
|
38418
|
-
const raw =
|
|
38775
|
+
if (!fs83.existsSync(filePath)) return null;
|
|
38776
|
+
const raw = fs83.readFileSync(filePath, "utf-8");
|
|
38419
38777
|
if (raw.trim().length === 0) return {};
|
|
38420
38778
|
return JSON.parse(raw);
|
|
38421
38779
|
}
|
|
38422
38780
|
function writeSettings(filePath, settings) {
|
|
38423
|
-
|
|
38781
|
+
fs83.mkdirSync(path82.dirname(filePath), { recursive: true });
|
|
38424
38782
|
const tmp = `${filePath}.tmp-migrate-hooks-${process.pid}-${Date.now()}`;
|
|
38425
|
-
|
|
38426
|
-
|
|
38783
|
+
fs83.writeFileSync(tmp, JSON.stringify(settings, null, 2) + "\n");
|
|
38784
|
+
fs83.renameSync(tmp, filePath);
|
|
38427
38785
|
}
|
|
38428
38786
|
function printSummary(candidates2, opts) {
|
|
38429
38787
|
if (candidates2.length === 0) {
|
|
@@ -38503,7 +38861,7 @@ function registerSkillsMigrateHooks(program2) {
|
|
|
38503
38861
|
init_meta_hooks_migration_snapshot();
|
|
38504
38862
|
init_skill_sources();
|
|
38505
38863
|
init_output();
|
|
38506
|
-
import * as
|
|
38864
|
+
import * as path83 from "node:path";
|
|
38507
38865
|
function asMessage9(err) {
|
|
38508
38866
|
return err instanceof Error ? err.message : String(err);
|
|
38509
38867
|
}
|
|
@@ -38520,16 +38878,16 @@ function registerSkillsMigrateHooksBack(program2) {
|
|
|
38520
38878
|
return;
|
|
38521
38879
|
}
|
|
38522
38880
|
if (opts.snapshot) {
|
|
38523
|
-
const resolved =
|
|
38524
|
-
const allowedDir =
|
|
38525
|
-
if (!resolved.startsWith(allowedDir +
|
|
38881
|
+
const resolved = path83.resolve(opts.snapshot);
|
|
38882
|
+
const allowedDir = path83.resolve(migrationSnapshotsDir2());
|
|
38883
|
+
if (!resolved.startsWith(allowedDir + path83.sep)) {
|
|
38526
38884
|
printError(
|
|
38527
38885
|
`--snapshot path must be inside ${allowedDir} (got "${resolved}"). Refusing to restore from an arbitrary path \u2014 settings.json would land operator-chosen content.`
|
|
38528
38886
|
);
|
|
38529
38887
|
process.exitCode = 1;
|
|
38530
38888
|
return;
|
|
38531
38889
|
}
|
|
38532
|
-
const basename16 =
|
|
38890
|
+
const basename16 = path83.basename(resolved);
|
|
38533
38891
|
if (!basename16.startsWith(META_HOOKS_SNAPSHOT_PREFIX)) {
|
|
38534
38892
|
printError(
|
|
38535
38893
|
`--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.`
|
|
@@ -38558,7 +38916,7 @@ function registerSkillsMigrateHooksBack(program2) {
|
|
|
38558
38916
|
// src/commands/skills-shadow-backups.ts
|
|
38559
38917
|
init_skill_sources();
|
|
38560
38918
|
init_output();
|
|
38561
|
-
import * as
|
|
38919
|
+
import * as fs84 from "node:fs";
|
|
38562
38920
|
import pc36 from "picocolors";
|
|
38563
38921
|
function asMessage10(err) {
|
|
38564
38922
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -38641,7 +38999,7 @@ function registerSkillsShadowBackups(program2) {
|
|
|
38641
38999
|
});
|
|
38642
39000
|
sb.command("restore").description("Move a shadow-backup file back to its original path").argument("<path>", "Absolute path to the .shadow-backup-<epoch> file").option("--force", "Overwrite the original path if it already exists").action((p, opts) => {
|
|
38643
39001
|
try {
|
|
38644
|
-
if (!
|
|
39002
|
+
if (!fs84.existsSync(p)) {
|
|
38645
39003
|
printError(`backup file not found: ${p}`);
|
|
38646
39004
|
process.exitCode = 1;
|
|
38647
39005
|
return;
|
|
@@ -38764,8 +39122,8 @@ init_skill_sources();
|
|
|
38764
39122
|
init_cli_version();
|
|
38765
39123
|
init_output();
|
|
38766
39124
|
import { execFileSync as execFileSync15 } from "node:child_process";
|
|
38767
|
-
import * as
|
|
38768
|
-
import * as
|
|
39125
|
+
import * as fs85 from "node:fs";
|
|
39126
|
+
import * as path84 from "node:path";
|
|
38769
39127
|
var CHAIN_SKILL_NAMES = [
|
|
38770
39128
|
"10x:brainstorm",
|
|
38771
39129
|
"10x:plan-hard",
|
|
@@ -38788,13 +39146,13 @@ function hasBeadsCli() {
|
|
|
38788
39146
|
}
|
|
38789
39147
|
}
|
|
38790
39148
|
function hasBeadsProjectInit(cwd) {
|
|
38791
|
-
return
|
|
39149
|
+
return fs85.existsSync(path84.join(cwd, ".beads"));
|
|
38792
39150
|
}
|
|
38793
39151
|
function hasBeadsClaudeSetup() {
|
|
38794
|
-
const settingsPath =
|
|
38795
|
-
if (!
|
|
39152
|
+
const settingsPath = path84.join(claudeDir(), "settings.json");
|
|
39153
|
+
if (!fs85.existsSync(settingsPath)) return false;
|
|
38796
39154
|
try {
|
|
38797
|
-
const content =
|
|
39155
|
+
const content = fs85.readFileSync(settingsPath, "utf8");
|
|
38798
39156
|
return /"command"\s*:\s*"bd\b/.test(content) || /"bd setup\b/.test(content);
|
|
38799
39157
|
} catch {
|
|
38800
39158
|
return false;
|
|
@@ -38859,12 +39217,12 @@ function shortSha(sha) {
|
|
|
38859
39217
|
return sha.slice(0, 8);
|
|
38860
39218
|
}
|
|
38861
39219
|
function listInstalledClaudeSkills() {
|
|
38862
|
-
const skillsDir =
|
|
38863
|
-
if (!
|
|
39220
|
+
const skillsDir = path84.join(claudeDir(), "skills");
|
|
39221
|
+
if (!fs85.existsSync(skillsDir)) return [];
|
|
38864
39222
|
try {
|
|
38865
|
-
return
|
|
39223
|
+
return fs85.readdirSync(skillsDir).filter((name) => {
|
|
38866
39224
|
try {
|
|
38867
|
-
const stat =
|
|
39225
|
+
const stat = fs85.lstatSync(path84.join(skillsDir, name));
|
|
38868
39226
|
return stat.isSymbolicLink() || stat.isDirectory();
|
|
38869
39227
|
} catch {
|
|
38870
39228
|
return false;
|
|
@@ -38939,20 +39297,20 @@ function registerSkills10x(program2) {
|
|
|
38939
39297
|
tenx.command("uninstall").description(
|
|
38940
39298
|
"Remove /10x: chain skill symlinks from ~/.claude/skills (preserves user-authored skills + non-chain skill sources)"
|
|
38941
39299
|
).action(() => {
|
|
38942
|
-
const skillsDir =
|
|
38943
|
-
if (!
|
|
39300
|
+
const skillsDir = path84.join(claudeDir(), "skills");
|
|
39301
|
+
if (!fs85.existsSync(skillsDir)) {
|
|
38944
39302
|
printWarning("No ~/.claude/skills/ directory found; nothing to uninstall");
|
|
38945
39303
|
return;
|
|
38946
39304
|
}
|
|
38947
39305
|
let removed = 0;
|
|
38948
|
-
for (const name of
|
|
38949
|
-
const full =
|
|
39306
|
+
for (const name of fs85.readdirSync(skillsDir)) {
|
|
39307
|
+
const full = path84.join(skillsDir, name);
|
|
38950
39308
|
try {
|
|
38951
|
-
const stat =
|
|
39309
|
+
const stat = fs85.lstatSync(full);
|
|
38952
39310
|
if (!stat.isSymbolicLink()) continue;
|
|
38953
|
-
const target =
|
|
39311
|
+
const target = fs85.readlinkSync(full);
|
|
38954
39312
|
if (isChainSkill(name) || /\/10x[-:]/.test(target)) {
|
|
38955
|
-
|
|
39313
|
+
fs85.unlinkSync(full);
|
|
38956
39314
|
removed += 1;
|
|
38957
39315
|
}
|
|
38958
39316
|
} catch {
|
|
@@ -39020,22 +39378,22 @@ function registerSkills10x(program2) {
|
|
|
39020
39378
|
|
|
39021
39379
|
// src/commands/hermes.ts
|
|
39022
39380
|
init_output();
|
|
39023
|
-
import * as
|
|
39381
|
+
import * as fs86 from "node:fs";
|
|
39024
39382
|
import * as os43 from "node:os";
|
|
39025
|
-
import * as
|
|
39383
|
+
import * as path85 from "node:path";
|
|
39026
39384
|
import * as child_process from "node:child_process";
|
|
39027
39385
|
import { parse as yamlParse2, stringify as yamlStringify3 } from "yaml";
|
|
39028
39386
|
function hermesConfigPath() {
|
|
39029
|
-
return
|
|
39387
|
+
return path85.join(os43.homedir(), ".hermes", "config.yaml");
|
|
39030
39388
|
}
|
|
39031
39389
|
function hermesSkillsDir() {
|
|
39032
|
-
return
|
|
39390
|
+
return path85.join(os43.homedir(), ".hermes", "skills");
|
|
39033
39391
|
}
|
|
39034
39392
|
function claudeSkillsDir() {
|
|
39035
|
-
return
|
|
39393
|
+
return path85.join(os43.homedir(), ".claude", "skills");
|
|
39036
39394
|
}
|
|
39037
39395
|
function readHermesConfig(configPath) {
|
|
39038
|
-
const raw =
|
|
39396
|
+
const raw = fs86.readFileSync(configPath, "utf-8");
|
|
39039
39397
|
const parsed = yamlParse2(raw);
|
|
39040
39398
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
39041
39399
|
throw new Error(`${configPath} is not a YAML mapping`);
|
|
@@ -39043,13 +39401,13 @@ function readHermesConfig(configPath) {
|
|
|
39043
39401
|
return parsed;
|
|
39044
39402
|
}
|
|
39045
39403
|
function writeHermesConfig(configPath, config) {
|
|
39046
|
-
|
|
39404
|
+
fs86.writeFileSync(configPath, yamlStringify3(config), "utf-8");
|
|
39047
39405
|
}
|
|
39048
39406
|
function resolveOlamBinary() {
|
|
39049
39407
|
try {
|
|
39050
39408
|
const result = child_process.spawnSync("which", ["olam"], { encoding: "utf-8" });
|
|
39051
39409
|
const found = result.stdout.trim();
|
|
39052
|
-
if (found &&
|
|
39410
|
+
if (found && fs86.existsSync(found)) return found;
|
|
39053
39411
|
} catch {
|
|
39054
39412
|
}
|
|
39055
39413
|
return process.argv[1] ?? "olam";
|
|
@@ -39062,7 +39420,7 @@ function resolveWorkspaceDir() {
|
|
|
39062
39420
|
{ encoding: "utf-8" }
|
|
39063
39421
|
);
|
|
39064
39422
|
const out = result.stdout.trim();
|
|
39065
|
-
if (out &&
|
|
39423
|
+
if (out && fs86.existsSync(out)) return out;
|
|
39066
39424
|
} catch {
|
|
39067
39425
|
}
|
|
39068
39426
|
return process.cwd();
|
|
@@ -39132,22 +39490,22 @@ function ensureTerminalBackendLocal(config, dryRun, summary2) {
|
|
|
39132
39490
|
}
|
|
39133
39491
|
function mirrorSkillSymlinks(dryRun, summary2) {
|
|
39134
39492
|
const srcDir = claudeSkillsDir();
|
|
39135
|
-
if (!
|
|
39493
|
+
if (!fs86.existsSync(srcDir)) {
|
|
39136
39494
|
summary2.skipped.push("skills mirror (no ~/.claude/skills/ found)");
|
|
39137
39495
|
return;
|
|
39138
39496
|
}
|
|
39139
39497
|
const destDir = hermesSkillsDir();
|
|
39140
39498
|
if (!dryRun) {
|
|
39141
|
-
|
|
39499
|
+
fs86.mkdirSync(destDir, { recursive: true });
|
|
39142
39500
|
}
|
|
39143
|
-
const entries =
|
|
39501
|
+
const entries = fs86.readdirSync(srcDir);
|
|
39144
39502
|
let mirrored = 0;
|
|
39145
39503
|
let collisions = 0;
|
|
39146
39504
|
for (const entry of entries) {
|
|
39147
|
-
const srcPath =
|
|
39148
|
-
const destPath2 =
|
|
39149
|
-
if (
|
|
39150
|
-
if (
|
|
39505
|
+
const srcPath = path85.join(srcDir, entry);
|
|
39506
|
+
const destPath2 = path85.join(destDir, entry);
|
|
39507
|
+
if (fs86.existsSync(destPath2) || fs86.lstatSync(srcPath).isFile()) {
|
|
39508
|
+
if (fs86.existsSync(destPath2)) collisions++;
|
|
39151
39509
|
continue;
|
|
39152
39510
|
}
|
|
39153
39511
|
if (dryRun) {
|
|
@@ -39155,7 +39513,7 @@ function mirrorSkillSymlinks(dryRun, summary2) {
|
|
|
39155
39513
|
continue;
|
|
39156
39514
|
}
|
|
39157
39515
|
try {
|
|
39158
|
-
|
|
39516
|
+
fs86.symlinkSync(srcPath, destPath2);
|
|
39159
39517
|
mirrored++;
|
|
39160
39518
|
} catch (err) {
|
|
39161
39519
|
printWarning(`skills mirror: skipping ${entry} \u2014 ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -39174,7 +39532,7 @@ async function runHermesBootstrap(opts, deps = {}) {
|
|
|
39174
39532
|
const writeConfig2 = deps.writeConfig ?? writeHermesConfig;
|
|
39175
39533
|
const mirrorSkillsFn = deps.mirrorSkills ?? mirrorSkillSymlinks;
|
|
39176
39534
|
const installHookFn = deps.installHook ?? installKgFirstHookForHermes;
|
|
39177
|
-
if (!
|
|
39535
|
+
if (!fs86.existsSync(configPath)) {
|
|
39178
39536
|
printError(`~/.hermes/config.yaml not found at ${configPath}`);
|
|
39179
39537
|
printInfo(
|
|
39180
39538
|
"remedy",
|
|
@@ -39200,7 +39558,7 @@ async function runHermesBootstrap(opts, deps = {}) {
|
|
|
39200
39558
|
} else {
|
|
39201
39559
|
summary2.skipped.push("mcp_servers.agentmemory-atlas (AGENTMEMORY_BRIDGE_URL/SECRET not set; use --bridge-url/--bridge-secret to add)");
|
|
39202
39560
|
}
|
|
39203
|
-
const hooksDir =
|
|
39561
|
+
const hooksDir = path85.join(path85.dirname(configPath), "hooks");
|
|
39204
39562
|
const hookResult = installHookFn(hooksDir, dryRun);
|
|
39205
39563
|
switch (hookResult.status) {
|
|
39206
39564
|
case "installed":
|
|
@@ -39247,7 +39605,7 @@ async function runHermesBootstrap(opts, deps = {}) {
|
|
|
39247
39605
|
}
|
|
39248
39606
|
var HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
|
|
39249
39607
|
function ensureHermesHookEntry(config, hooksDir, dryRun, summary2) {
|
|
39250
|
-
const hookScriptPath =
|
|
39608
|
+
const hookScriptPath = path85.join(hooksDir, "kg-first.sh");
|
|
39251
39609
|
const hooks = config["hooks"] ?? {};
|
|
39252
39610
|
const preToolCall = Array.isArray(hooks["pre_tool_call"]) ? hooks["pre_tool_call"] : [];
|
|
39253
39611
|
const alreadyPresent = preToolCall.some(
|
|
@@ -39520,8 +39878,8 @@ var SECRET = process.env["OLAM_MCP_AUTH_SECRET"] ?? "";
|
|
|
39520
39878
|
function authHeaders() {
|
|
39521
39879
|
return SECRET ? { "X-Olam-Mcp-Secret": SECRET } : {};
|
|
39522
39880
|
}
|
|
39523
|
-
async function apiFetch(
|
|
39524
|
-
const res = await fetch(`${BASE_URL}${
|
|
39881
|
+
async function apiFetch(path94, init = {}) {
|
|
39882
|
+
const res = await fetch(`${BASE_URL}${path94}`, {
|
|
39525
39883
|
...init,
|
|
39526
39884
|
headers: {
|
|
39527
39885
|
"Content-Type": "application/json",
|
|
@@ -39781,12 +40139,12 @@ import * as readline6 from "node:readline";
|
|
|
39781
40139
|
import pc40 from "picocolors";
|
|
39782
40140
|
|
|
39783
40141
|
// src/commands/mcp/import-discovery.ts
|
|
39784
|
-
import * as
|
|
40142
|
+
import * as fs87 from "node:fs";
|
|
39785
40143
|
import * as os44 from "node:os";
|
|
39786
|
-
import * as
|
|
40144
|
+
import * as path86 from "node:path";
|
|
39787
40145
|
function readJsonFile(filePath) {
|
|
39788
40146
|
try {
|
|
39789
|
-
const raw =
|
|
40147
|
+
const raw = fs87.readFileSync(filePath, "utf-8");
|
|
39790
40148
|
return JSON.parse(raw);
|
|
39791
40149
|
} catch {
|
|
39792
40150
|
return null;
|
|
@@ -39815,24 +40173,24 @@ function extractMcpServers(obj, source, sourceLabel) {
|
|
|
39815
40173
|
}
|
|
39816
40174
|
function getClaudeDesktopPath() {
|
|
39817
40175
|
if (process.platform === "darwin") {
|
|
39818
|
-
return
|
|
40176
|
+
return path86.join(os44.homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
39819
40177
|
}
|
|
39820
40178
|
if (process.platform === "win32") {
|
|
39821
|
-
const appData = process.env["APPDATA"] ??
|
|
39822
|
-
return
|
|
40179
|
+
const appData = process.env["APPDATA"] ?? path86.join(os44.homedir(), "AppData", "Roaming");
|
|
40180
|
+
return path86.join(appData, "Claude", "claude_desktop_config.json");
|
|
39823
40181
|
}
|
|
39824
|
-
return
|
|
40182
|
+
return path86.join(os44.homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
39825
40183
|
}
|
|
39826
40184
|
function getOlamRepoPaths() {
|
|
39827
40185
|
const configPaths = [
|
|
39828
|
-
|
|
39829
|
-
|
|
40186
|
+
path86.join(os44.homedir(), ".olam", "config.yaml"),
|
|
40187
|
+
path86.join(process.cwd(), ".olam", "config.yaml")
|
|
39830
40188
|
];
|
|
39831
40189
|
const paths = [];
|
|
39832
40190
|
for (const configPath of configPaths) {
|
|
39833
|
-
if (!
|
|
40191
|
+
if (!fs87.existsSync(configPath)) continue;
|
|
39834
40192
|
try {
|
|
39835
|
-
const raw =
|
|
40193
|
+
const raw = fs87.readFileSync(configPath, "utf-8");
|
|
39836
40194
|
const repoMatches = [...raw.matchAll(/path:\s*["']?([^\s"'\n]+)/g)];
|
|
39837
40195
|
for (const m of repoMatches) {
|
|
39838
40196
|
if (m[1]) paths.push(m[1]);
|
|
@@ -39848,7 +40206,7 @@ async function discoverMcpSources(repoPaths) {
|
|
|
39848
40206
|
const sources = [];
|
|
39849
40207
|
const sourceDefs = [
|
|
39850
40208
|
{
|
|
39851
|
-
path:
|
|
40209
|
+
path: path86.join(os44.homedir(), ".claude.json"),
|
|
39852
40210
|
label: "Claude Code (~/.claude.json)"
|
|
39853
40211
|
},
|
|
39854
40212
|
{
|
|
@@ -39856,19 +40214,19 @@ async function discoverMcpSources(repoPaths) {
|
|
|
39856
40214
|
label: "Claude Desktop"
|
|
39857
40215
|
},
|
|
39858
40216
|
{
|
|
39859
|
-
path:
|
|
40217
|
+
path: path86.join(os44.homedir(), ".cursor", "mcp.json"),
|
|
39860
40218
|
label: "Cursor (~/.cursor/mcp.json)"
|
|
39861
40219
|
},
|
|
39862
40220
|
{
|
|
39863
|
-
path:
|
|
40221
|
+
path: path86.join(os44.homedir(), ".codeium", "windsurf", "mcp_config.json"),
|
|
39864
40222
|
label: "Windsurf (~/.codeium/windsurf/mcp_config.json)"
|
|
39865
40223
|
}
|
|
39866
40224
|
];
|
|
39867
40225
|
const resolvedRepoPaths = repoPaths ?? getOlamRepoPaths();
|
|
39868
40226
|
for (const repoPath of resolvedRepoPaths) {
|
|
39869
40227
|
sourceDefs.push({
|
|
39870
|
-
path:
|
|
39871
|
-
label: `.mcp.json (${
|
|
40228
|
+
path: path86.join(repoPath, ".mcp.json"),
|
|
40229
|
+
label: `.mcp.json (${path86.basename(repoPath)})`
|
|
39872
40230
|
});
|
|
39873
40231
|
}
|
|
39874
40232
|
const reads = await Promise.all(
|
|
@@ -40104,27 +40462,27 @@ function registerMcp(program2) {
|
|
|
40104
40462
|
init_output();
|
|
40105
40463
|
|
|
40106
40464
|
// src/lib/memory-host-process-migration.ts
|
|
40107
|
-
import { existsSync as existsSync100, readFileSync as
|
|
40465
|
+
import { existsSync as existsSync100, readFileSync as readFileSync80, unlinkSync as unlinkSync23 } from "node:fs";
|
|
40108
40466
|
import { spawnSync as spawnSync28 } from "node:child_process";
|
|
40109
40467
|
|
|
40110
40468
|
// src/commands/memory/_paths.ts
|
|
40111
40469
|
import { homedir as homedir51 } from "node:os";
|
|
40112
|
-
import { join as
|
|
40470
|
+
import { join as join93, dirname as dirname55 } from "node:path";
|
|
40113
40471
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
40114
|
-
var OLAM_HOME4 =
|
|
40115
|
-
var MEMORY_PID_PATH =
|
|
40116
|
-
var MEMORY_LOG_PATH =
|
|
40117
|
-
var MEMORY_DATA_DIR =
|
|
40472
|
+
var OLAM_HOME4 = join93(homedir51(), ".olam");
|
|
40473
|
+
var MEMORY_PID_PATH = join93(OLAM_HOME4, "memory.pid");
|
|
40474
|
+
var MEMORY_LOG_PATH = join93(OLAM_HOME4, "memory-service.log");
|
|
40475
|
+
var MEMORY_DATA_DIR = join93(OLAM_HOME4, "memory-data");
|
|
40118
40476
|
var MEMORY_REST_PORT = 3111;
|
|
40119
40477
|
var MEMORY_LIVEZ_URL = `http://localhost:${MEMORY_REST_PORT}/agentmemory/livez`;
|
|
40120
40478
|
var here2 = dirname55(fileURLToPath8(import.meta.url));
|
|
40121
40479
|
var candidates = [
|
|
40122
40480
|
// 1. Workspace dev (built): packages/cli/dist/commands/memory/_paths.js → packages/cli → packages/memory-service
|
|
40123
|
-
|
|
40481
|
+
join93(here2, "..", "..", "..", "..", "memory-service"),
|
|
40124
40482
|
// 2. Workspace bundled: packages/cli/dist/index.js → packages/cli → packages/memory-service
|
|
40125
|
-
|
|
40483
|
+
join93(here2, "..", "..", "memory-service"),
|
|
40126
40484
|
// 3. CWD fallback
|
|
40127
|
-
|
|
40485
|
+
join93(process.cwd(), "packages", "memory-service")
|
|
40128
40486
|
];
|
|
40129
40487
|
var MEMORY_SERVICE_CANDIDATES = candidates;
|
|
40130
40488
|
|
|
@@ -40173,7 +40531,7 @@ function migrateFromHostProcess(opts = {}) {
|
|
|
40173
40531
|
}
|
|
40174
40532
|
function readPidFromFile(pidPath2) {
|
|
40175
40533
|
try {
|
|
40176
|
-
const raw =
|
|
40534
|
+
const raw = readFileSync80(pidPath2, "utf8").trim();
|
|
40177
40535
|
const pid = parseInt(raw, 10);
|
|
40178
40536
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
40179
40537
|
return pid;
|
|
@@ -40606,13 +40964,13 @@ function registerMemoryUninstall(cmd) {
|
|
|
40606
40964
|
// src/commands/memory/mode.ts
|
|
40607
40965
|
init_schema2();
|
|
40608
40966
|
init_output();
|
|
40609
|
-
import { existsSync as existsSync103, readFileSync as
|
|
40610
|
-
import { join as
|
|
40967
|
+
import { existsSync as existsSync103, readFileSync as readFileSync81, writeFileSync as writeFileSync51 } from "node:fs";
|
|
40968
|
+
import { join as join94 } from "node:path";
|
|
40611
40969
|
import * as readline7 from "node:readline/promises";
|
|
40612
40970
|
import { parse as parseYaml7, stringify as stringifyYaml6 } from "yaml";
|
|
40613
40971
|
var CONFIG_REL = ".olam/config.yaml";
|
|
40614
40972
|
function locateConfig(cwd) {
|
|
40615
|
-
const absPath =
|
|
40973
|
+
const absPath = join94(cwd, CONFIG_REL);
|
|
40616
40974
|
if (!existsSync103(absPath)) {
|
|
40617
40975
|
throw new Error(
|
|
40618
40976
|
`No ${CONFIG_REL} at ${cwd}. Run \`olam init\` in your workspace root first.`
|
|
@@ -40621,7 +40979,7 @@ function locateConfig(cwd) {
|
|
|
40621
40979
|
return { absPath };
|
|
40622
40980
|
}
|
|
40623
40981
|
function readConfigYaml(absPath) {
|
|
40624
|
-
const raw =
|
|
40982
|
+
const raw = readFileSync81(absPath, "utf-8");
|
|
40625
40983
|
const parsed = parseYaml7(raw) ?? {};
|
|
40626
40984
|
if (typeof parsed !== "object" || parsed === null) {
|
|
40627
40985
|
throw new Error(`${absPath} is not a YAML object`);
|
|
@@ -40750,7 +41108,7 @@ function registerMemoryMode(cmd) {
|
|
|
40750
41108
|
init_output();
|
|
40751
41109
|
import { spawn as spawn11 } from "node:child_process";
|
|
40752
41110
|
import { existsSync as existsSync104 } from "node:fs";
|
|
40753
|
-
import { join as
|
|
41111
|
+
import { join as join95 } from "node:path";
|
|
40754
41112
|
var DEFAULT_PORT2 = 8788;
|
|
40755
41113
|
function resolveMemoryServiceDir() {
|
|
40756
41114
|
for (const c of MEMORY_SERVICE_CANDIDATES) {
|
|
@@ -40761,13 +41119,13 @@ function resolveMemoryServiceDir() {
|
|
|
40761
41119
|
);
|
|
40762
41120
|
}
|
|
40763
41121
|
function resolveLocalBridgeScript(serviceDir) {
|
|
40764
|
-
const
|
|
40765
|
-
if (!existsSync104(
|
|
41122
|
+
const path94 = join95(serviceDir, "scripts", "local-bridge-server.mjs");
|
|
41123
|
+
if (!existsSync104(path94)) {
|
|
40766
41124
|
throw new Error(
|
|
40767
|
-
`Could not find local-bridge-server.mjs at ${
|
|
41125
|
+
`Could not find local-bridge-server.mjs at ${path94}. Verify packages/memory-service ships the scripts/ directory.`
|
|
40768
41126
|
);
|
|
40769
41127
|
}
|
|
40770
|
-
return
|
|
41128
|
+
return path94;
|
|
40771
41129
|
}
|
|
40772
41130
|
function validateBridgeOpts(opts) {
|
|
40773
41131
|
const local = opts.local ?? false;
|
|
@@ -41108,9 +41466,9 @@ function registerMemoryStats(cmd) {
|
|
|
41108
41466
|
}
|
|
41109
41467
|
|
|
41110
41468
|
// src/commands/memory/install-hooks.ts
|
|
41111
|
-
import { copyFileSync as copyFileSync12, existsSync as existsSync105, mkdirSync as mkdirSync60, readFileSync as
|
|
41469
|
+
import { copyFileSync as copyFileSync12, existsSync as existsSync105, mkdirSync as mkdirSync60, readFileSync as readFileSync82, writeFileSync as writeFileSync52 } from "node:fs";
|
|
41112
41470
|
import { homedir as homedir52 } from "node:os";
|
|
41113
|
-
import { dirname as dirname56, join as
|
|
41471
|
+
import { dirname as dirname56, join as join96, resolve as resolve25 } from "node:path";
|
|
41114
41472
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
41115
41473
|
var HOOK_BASENAMES = [
|
|
41116
41474
|
"agentmemory-session-recall.js",
|
|
@@ -41126,12 +41484,12 @@ function defaultSourceDir() {
|
|
|
41126
41484
|
return candidate;
|
|
41127
41485
|
}
|
|
41128
41486
|
function installOne2(basename16, sourceDir, targetDir, opts) {
|
|
41129
|
-
const sourcePath =
|
|
41130
|
-
const targetPath =
|
|
41487
|
+
const sourcePath = join96(sourceDir, basename16);
|
|
41488
|
+
const targetPath = join96(targetDir, basename16);
|
|
41131
41489
|
if (!existsSync105(sourcePath)) {
|
|
41132
41490
|
throw new Error(`canonical hook source missing at ${sourcePath} \u2014 olam install corrupt or sourceDir is wrong`);
|
|
41133
41491
|
}
|
|
41134
|
-
const newContent =
|
|
41492
|
+
const newContent = readFileSync82(sourcePath, "utf8");
|
|
41135
41493
|
if (!existsSync105(targetPath)) {
|
|
41136
41494
|
if (opts.dryRun !== true) {
|
|
41137
41495
|
mkdirSync60(dirname56(targetPath), { recursive: true });
|
|
@@ -41139,7 +41497,7 @@ function installOne2(basename16, sourceDir, targetDir, opts) {
|
|
|
41139
41497
|
}
|
|
41140
41498
|
return { basename: basename16, action: "written", targetPath };
|
|
41141
41499
|
}
|
|
41142
|
-
const existing =
|
|
41500
|
+
const existing = readFileSync82(targetPath, "utf8");
|
|
41143
41501
|
if (existing === newContent) {
|
|
41144
41502
|
return { basename: basename16, action: "unchanged", targetPath };
|
|
41145
41503
|
}
|
|
@@ -41162,13 +41520,13 @@ Add these hook entries to ~/.claude/settings.json:
|
|
|
41162
41520
|
{
|
|
41163
41521
|
"hooks": {
|
|
41164
41522
|
"SessionStart": [
|
|
41165
|
-
{ "command": "node ${
|
|
41523
|
+
{ "command": "node ${join96(targetDir, "agentmemory-session-recall.js")}" }
|
|
41166
41524
|
],
|
|
41167
41525
|
"PreToolUse": [
|
|
41168
|
-
{ "command": "node ${
|
|
41526
|
+
{ "command": "node ${join96(targetDir, "agentmemory-recall-trigger.mjs")}" }
|
|
41169
41527
|
],
|
|
41170
41528
|
"PostToolUse": [
|
|
41171
|
-
{ "command": "node ${
|
|
41529
|
+
{ "command": "node ${join96(targetDir, "agentmemory-classify-queue.mjs")}" }
|
|
41172
41530
|
]
|
|
41173
41531
|
}
|
|
41174
41532
|
}
|
|
@@ -41178,7 +41536,7 @@ If existing entries already point at the same paths, no edit needed.
|
|
|
41178
41536
|
}
|
|
41179
41537
|
function registerMemoryInstallHooks(parent) {
|
|
41180
41538
|
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) => {
|
|
41181
|
-
const targetDir = opts.targetDir ??
|
|
41539
|
+
const targetDir = opts.targetDir ?? join96(homedir52(), ".claude", "scripts", "hooks");
|
|
41182
41540
|
const sourceDir = opts.sourceDir ?? defaultSourceDir();
|
|
41183
41541
|
let written = 0;
|
|
41184
41542
|
let unchanged = 0;
|
|
@@ -41256,9 +41614,9 @@ function registerMemory(program2) {
|
|
|
41256
41614
|
// src/commands/kg-build.ts
|
|
41257
41615
|
init_storage_paths();
|
|
41258
41616
|
init_workspace_name();
|
|
41259
|
-
import * as
|
|
41617
|
+
import * as fs92 from "node:fs";
|
|
41260
41618
|
import * as os47 from "node:os";
|
|
41261
|
-
import * as
|
|
41619
|
+
import * as path91 from "node:path";
|
|
41262
41620
|
|
|
41263
41621
|
// ../core/dist/kg/kg-service-client.js
|
|
41264
41622
|
var KG_SERVICE_PORT_DEFAULT = 9997;
|
|
@@ -41269,8 +41627,8 @@ function port() {
|
|
|
41269
41627
|
const n = Number.parseInt(env, 10);
|
|
41270
41628
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
41271
41629
|
}
|
|
41272
|
-
function url(
|
|
41273
|
-
return `http://127.0.0.1:${port()}${
|
|
41630
|
+
function url(path94) {
|
|
41631
|
+
return `http://127.0.0.1:${port()}${path94}`;
|
|
41274
41632
|
}
|
|
41275
41633
|
function kgServiceHealthUrl() {
|
|
41276
41634
|
return url("/health");
|
|
@@ -41350,39 +41708,39 @@ init_storage_paths();
|
|
|
41350
41708
|
init_workspace_name();
|
|
41351
41709
|
init_kg_caps();
|
|
41352
41710
|
init_output();
|
|
41353
|
-
import
|
|
41711
|
+
import fs88 from "node:fs";
|
|
41354
41712
|
import { homedir as homedir53 } from "node:os";
|
|
41355
|
-
import
|
|
41713
|
+
import path87 from "node:path";
|
|
41356
41714
|
function olamHome4() {
|
|
41357
|
-
return process.env.OLAM_HOME ??
|
|
41715
|
+
return process.env.OLAM_HOME ?? path87.join(homedir53(), ".olam");
|
|
41358
41716
|
}
|
|
41359
41717
|
function kgRoot2() {
|
|
41360
|
-
return
|
|
41718
|
+
return path87.join(olamHome4(), "kg");
|
|
41361
41719
|
}
|
|
41362
41720
|
function worldsRoot2() {
|
|
41363
|
-
return
|
|
41721
|
+
return path87.join(olamHome4(), "worlds");
|
|
41364
41722
|
}
|
|
41365
41723
|
function dirSizeBytes2(dir) {
|
|
41366
|
-
if (!
|
|
41724
|
+
if (!fs88.existsSync(dir)) return 0;
|
|
41367
41725
|
let total = 0;
|
|
41368
41726
|
const stack = [dir];
|
|
41369
41727
|
while (stack.length > 0) {
|
|
41370
41728
|
const cur = stack.pop();
|
|
41371
41729
|
let entries;
|
|
41372
41730
|
try {
|
|
41373
|
-
entries =
|
|
41731
|
+
entries = fs88.readdirSync(cur, { withFileTypes: true });
|
|
41374
41732
|
} catch {
|
|
41375
41733
|
continue;
|
|
41376
41734
|
}
|
|
41377
41735
|
for (const entry of entries) {
|
|
41378
|
-
const full =
|
|
41736
|
+
const full = path87.join(cur, entry.name);
|
|
41379
41737
|
if (entry.isSymbolicLink()) continue;
|
|
41380
41738
|
if (entry.isDirectory()) {
|
|
41381
41739
|
stack.push(full);
|
|
41382
41740
|
continue;
|
|
41383
41741
|
}
|
|
41384
41742
|
try {
|
|
41385
|
-
total +=
|
|
41743
|
+
total += fs88.statSync(full).size;
|
|
41386
41744
|
} catch {
|
|
41387
41745
|
}
|
|
41388
41746
|
}
|
|
@@ -41396,10 +41754,10 @@ function formatBytes5(n) {
|
|
|
41396
41754
|
return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
41397
41755
|
}
|
|
41398
41756
|
function readFreshness(workspace) {
|
|
41399
|
-
const file =
|
|
41400
|
-
if (!
|
|
41757
|
+
const file = path87.join(kgPristinePath(workspace), "freshness.json");
|
|
41758
|
+
if (!fs88.existsSync(file)) return null;
|
|
41401
41759
|
try {
|
|
41402
|
-
const raw = JSON.parse(
|
|
41760
|
+
const raw = JSON.parse(fs88.readFileSync(file, "utf-8"));
|
|
41403
41761
|
if (raw && typeof raw === "object") return raw;
|
|
41404
41762
|
return null;
|
|
41405
41763
|
} catch {
|
|
@@ -41407,10 +41765,10 @@ function readFreshness(workspace) {
|
|
|
41407
41765
|
}
|
|
41408
41766
|
}
|
|
41409
41767
|
function readOverlayNodeCount(graphifyOutDir) {
|
|
41410
|
-
const graphPath =
|
|
41411
|
-
if (!
|
|
41768
|
+
const graphPath = path87.join(graphifyOutDir, "graph.json");
|
|
41769
|
+
if (!fs88.existsSync(graphPath)) return null;
|
|
41412
41770
|
try {
|
|
41413
|
-
const raw = JSON.parse(
|
|
41771
|
+
const raw = JSON.parse(fs88.readFileSync(graphPath, "utf-8"));
|
|
41414
41772
|
if (raw && typeof raw === "object") {
|
|
41415
41773
|
const nodes = raw.nodes;
|
|
41416
41774
|
if (Array.isArray(nodes)) return nodes.length;
|
|
@@ -41422,28 +41780,28 @@ function readOverlayNodeCount(graphifyOutDir) {
|
|
|
41422
41780
|
}
|
|
41423
41781
|
function listOverlays() {
|
|
41424
41782
|
const root = worldsRoot2();
|
|
41425
|
-
if (!
|
|
41783
|
+
if (!fs88.existsSync(root)) return [];
|
|
41426
41784
|
const records = [];
|
|
41427
41785
|
let worldDirs;
|
|
41428
41786
|
try {
|
|
41429
|
-
worldDirs =
|
|
41787
|
+
worldDirs = fs88.readdirSync(root, { withFileTypes: true });
|
|
41430
41788
|
} catch {
|
|
41431
41789
|
return [];
|
|
41432
41790
|
}
|
|
41433
41791
|
for (const worldEntry of worldDirs) {
|
|
41434
41792
|
if (!worldEntry.isDirectory()) continue;
|
|
41435
41793
|
const worldId = worldEntry.name;
|
|
41436
|
-
const worldDir =
|
|
41794
|
+
const worldDir = path87.join(root, worldId);
|
|
41437
41795
|
let cloneDirs;
|
|
41438
41796
|
try {
|
|
41439
|
-
cloneDirs =
|
|
41797
|
+
cloneDirs = fs88.readdirSync(worldDir, { withFileTypes: true });
|
|
41440
41798
|
} catch {
|
|
41441
41799
|
continue;
|
|
41442
41800
|
}
|
|
41443
41801
|
for (const cloneEntry of cloneDirs) {
|
|
41444
41802
|
if (!cloneEntry.isDirectory()) continue;
|
|
41445
|
-
const graphifyOut =
|
|
41446
|
-
if (!
|
|
41803
|
+
const graphifyOut = path87.join(worldDir, cloneEntry.name, "graphify-out");
|
|
41804
|
+
if (!fs88.existsSync(graphifyOut)) continue;
|
|
41447
41805
|
records.push({
|
|
41448
41806
|
world_id: worldId,
|
|
41449
41807
|
clone_dir: cloneEntry.name,
|
|
@@ -41457,11 +41815,11 @@ function listOverlays() {
|
|
|
41457
41815
|
}
|
|
41458
41816
|
function listPristines(overlays) {
|
|
41459
41817
|
const root = kgRoot2();
|
|
41460
|
-
if (!
|
|
41818
|
+
if (!fs88.existsSync(root)) return [];
|
|
41461
41819
|
const records = [];
|
|
41462
41820
|
let entries;
|
|
41463
41821
|
try {
|
|
41464
|
-
entries =
|
|
41822
|
+
entries = fs88.readdirSync(root, { withFileTypes: true });
|
|
41465
41823
|
} catch {
|
|
41466
41824
|
return [];
|
|
41467
41825
|
}
|
|
@@ -41474,7 +41832,7 @@ function listPristines(overlays) {
|
|
|
41474
41832
|
continue;
|
|
41475
41833
|
}
|
|
41476
41834
|
const fresh = readFreshness(workspace);
|
|
41477
|
-
const graphifyOut =
|
|
41835
|
+
const graphifyOut = path87.join(kgPristinePath(workspace), "graphify-out");
|
|
41478
41836
|
const size = dirSizeBytes2(graphifyOut);
|
|
41479
41837
|
const worldCount = overlays.filter((o) => o.clone_dir === workspace).length;
|
|
41480
41838
|
records.push({
|
|
@@ -41610,10 +41968,10 @@ init_storage_paths();
|
|
|
41610
41968
|
init_workspace_name();
|
|
41611
41969
|
init_output();
|
|
41612
41970
|
import { spawn as spawn12 } from "node:child_process";
|
|
41613
|
-
import
|
|
41614
|
-
import
|
|
41971
|
+
import fs89 from "node:fs";
|
|
41972
|
+
import path88 from "node:path";
|
|
41615
41973
|
function pidFilePath2(workspace) {
|
|
41616
|
-
return
|
|
41974
|
+
return path88.join(kgPristinePath(workspace), ".watch.pid");
|
|
41617
41975
|
}
|
|
41618
41976
|
function isPidAlive3(pid) {
|
|
41619
41977
|
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
@@ -41628,39 +41986,39 @@ function isPidAlive3(pid) {
|
|
|
41628
41986
|
}
|
|
41629
41987
|
function readAndClassifyPid(workspace) {
|
|
41630
41988
|
const file = pidFilePath2(workspace);
|
|
41631
|
-
if (!
|
|
41989
|
+
if (!fs89.existsSync(file)) return { status: "no-pidfile", pid: null };
|
|
41632
41990
|
let pid;
|
|
41633
41991
|
try {
|
|
41634
|
-
const raw =
|
|
41992
|
+
const raw = fs89.readFileSync(file, "utf-8").trim();
|
|
41635
41993
|
pid = Number.parseInt(raw, 10);
|
|
41636
41994
|
} catch {
|
|
41637
|
-
|
|
41995
|
+
fs89.rmSync(file, { force: true });
|
|
41638
41996
|
return { status: "stale-reclaimed", pid: null };
|
|
41639
41997
|
}
|
|
41640
41998
|
if (!Number.isInteger(pid) || pid <= 0) {
|
|
41641
|
-
|
|
41999
|
+
fs89.rmSync(file, { force: true });
|
|
41642
42000
|
return { status: "stale-reclaimed", pid: null };
|
|
41643
42001
|
}
|
|
41644
42002
|
if (isPidAlive3(pid)) return { status: "active", pid };
|
|
41645
|
-
|
|
42003
|
+
fs89.rmSync(file, { force: true });
|
|
41646
42004
|
return { status: "stale-reclaimed", pid: null };
|
|
41647
42005
|
}
|
|
41648
42006
|
function writePidFile2(workspace, pid) {
|
|
41649
42007
|
const file = pidFilePath2(workspace);
|
|
41650
|
-
const dir =
|
|
41651
|
-
|
|
41652
|
-
|
|
42008
|
+
const dir = path88.dirname(file);
|
|
42009
|
+
fs89.mkdirSync(dir, { recursive: true });
|
|
42010
|
+
fs89.writeFileSync(file, String(pid), { encoding: "utf-8" });
|
|
41653
42011
|
}
|
|
41654
42012
|
function removePidFile(workspace) {
|
|
41655
42013
|
const file = pidFilePath2(workspace);
|
|
41656
42014
|
try {
|
|
41657
|
-
|
|
42015
|
+
fs89.rmSync(file, { force: true });
|
|
41658
42016
|
} catch {
|
|
41659
42017
|
}
|
|
41660
42018
|
}
|
|
41661
42019
|
async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
41662
42020
|
const cwd = deps.cwd ?? opts.cwd ?? process.cwd();
|
|
41663
|
-
const name = workspaceArg ??
|
|
42021
|
+
const name = workspaceArg ?? path88.basename(cwd).toLowerCase();
|
|
41664
42022
|
try {
|
|
41665
42023
|
validateWorkspaceName(name);
|
|
41666
42024
|
} catch (err) {
|
|
@@ -41668,7 +42026,7 @@ async function runKgWatch(workspaceArg, opts, deps = {}) {
|
|
|
41668
42026
|
return { exitCode: 1, pidWritten: false };
|
|
41669
42027
|
}
|
|
41670
42028
|
const pristinePath = kgPristinePath(name);
|
|
41671
|
-
const graphPath =
|
|
42029
|
+
const graphPath = path88.join(pristinePath, "graphify-out", "graph.json");
|
|
41672
42030
|
const pidState = readAndClassifyPid(name);
|
|
41673
42031
|
if (pidState.status === "active") {
|
|
41674
42032
|
printError(
|
|
@@ -41906,8 +42264,8 @@ function registerKgDoctorCommand(kg) {
|
|
|
41906
42264
|
|
|
41907
42265
|
// src/commands/kg-install-hook.ts
|
|
41908
42266
|
init_merge_settings();
|
|
41909
|
-
import * as
|
|
41910
|
-
import * as
|
|
42267
|
+
import * as fs90 from "node:fs";
|
|
42268
|
+
import * as path89 from "node:path";
|
|
41911
42269
|
import * as os45 from "node:os";
|
|
41912
42270
|
import { parse as yamlParse3, stringify as yamlStringify4 } from "yaml";
|
|
41913
42271
|
|
|
@@ -41960,27 +42318,27 @@ function buildHookMatcherEntry(opts) {
|
|
|
41960
42318
|
init_output();
|
|
41961
42319
|
function settingsPathFor2(scope) {
|
|
41962
42320
|
if (scope === "user") {
|
|
41963
|
-
return
|
|
42321
|
+
return path89.join(os45.homedir(), ".claude", "settings.json");
|
|
41964
42322
|
}
|
|
41965
|
-
return
|
|
42323
|
+
return path89.join(process.cwd(), ".claude", "settings.json");
|
|
41966
42324
|
}
|
|
41967
42325
|
function backup2(filePath) {
|
|
41968
|
-
if (!
|
|
42326
|
+
if (!fs90.existsSync(filePath)) return null;
|
|
41969
42327
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
41970
42328
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
41971
|
-
|
|
42329
|
+
fs90.copyFileSync(filePath, backupPath);
|
|
41972
42330
|
return backupPath;
|
|
41973
42331
|
}
|
|
41974
42332
|
var HERMES_HOOK_MATCHERS = ["terminal", "bash", "shell", "search_files", "grep", "ripgrep"];
|
|
41975
42333
|
function hermesConfigPath2() {
|
|
41976
|
-
return
|
|
42334
|
+
return path89.join(os45.homedir(), ".hermes", "config.yaml");
|
|
41977
42335
|
}
|
|
41978
42336
|
function hermesHooksDir() {
|
|
41979
|
-
return
|
|
42337
|
+
return path89.join(os45.homedir(), ".hermes", "hooks");
|
|
41980
42338
|
}
|
|
41981
42339
|
function patchHermesConfigForHook(action) {
|
|
41982
42340
|
const configPath = hermesConfigPath2();
|
|
41983
|
-
const raw =
|
|
42341
|
+
const raw = fs90.readFileSync(configPath, "utf-8");
|
|
41984
42342
|
const config = yamlParse3(raw);
|
|
41985
42343
|
const hooks = config["hooks"] ?? {};
|
|
41986
42344
|
const preToolCall = Array.isArray(hooks["pre_tool_call"]) ? hooks["pre_tool_call"] : [];
|
|
@@ -41989,7 +42347,7 @@ function patchHermesConfigForHook(action) {
|
|
|
41989
42347
|
(e) => typeof e["command"] === "string" && e["command"].includes(HERMES_KG_HOOK_SENTINEL)
|
|
41990
42348
|
);
|
|
41991
42349
|
if (alreadyPresent) return "already-present";
|
|
41992
|
-
const hookScriptPath =
|
|
42350
|
+
const hookScriptPath = path89.join(hermesHooksDir(), "kg-first.sh");
|
|
41993
42351
|
const entry = {
|
|
41994
42352
|
matcher: HERMES_HOOK_MATCHERS.join("|"),
|
|
41995
42353
|
command: `${hookScriptPath} # ${HERMES_KG_HOOK_SENTINEL}`
|
|
@@ -41999,7 +42357,7 @@ function patchHermesConfigForHook(action) {
|
|
|
41999
42357
|
hooks: { ...hooks, pre_tool_call: [...preToolCall, entry] },
|
|
42000
42358
|
hooks_auto_accept: true
|
|
42001
42359
|
};
|
|
42002
|
-
|
|
42360
|
+
fs90.writeFileSync(configPath, yamlStringify4(updated2), "utf-8");
|
|
42003
42361
|
return "patched";
|
|
42004
42362
|
}
|
|
42005
42363
|
const filtered = preToolCall.filter(
|
|
@@ -42010,12 +42368,12 @@ function patchHermesConfigForHook(action) {
|
|
|
42010
42368
|
...config,
|
|
42011
42369
|
hooks: { ...hooks, pre_tool_call: filtered }
|
|
42012
42370
|
};
|
|
42013
|
-
|
|
42371
|
+
fs90.writeFileSync(configPath, yamlStringify4(updated), "utf-8");
|
|
42014
42372
|
return "patched";
|
|
42015
42373
|
}
|
|
42016
42374
|
function doInstallForHermes() {
|
|
42017
42375
|
const configPath = hermesConfigPath2();
|
|
42018
|
-
if (!
|
|
42376
|
+
if (!fs90.existsSync(configPath)) {
|
|
42019
42377
|
printError(`~/.hermes/config.yaml not found at ${configPath}`);
|
|
42020
42378
|
printInfo("remedy", "Install Hermes first, then re-run `olam kg install-hook --for hermes`");
|
|
42021
42379
|
process.exitCode = 1;
|
|
@@ -42043,17 +42401,17 @@ function doInstallForHermes() {
|
|
|
42043
42401
|
function doUninstallForHermes() {
|
|
42044
42402
|
const configPath = hermesConfigPath2();
|
|
42045
42403
|
const hooksDir = hermesHooksDir();
|
|
42046
|
-
const hookScriptPath =
|
|
42404
|
+
const hookScriptPath = path89.join(hooksDir, "kg-first.sh");
|
|
42047
42405
|
let scriptRemoved = false;
|
|
42048
|
-
if (
|
|
42049
|
-
const content =
|
|
42406
|
+
if (fs90.existsSync(hookScriptPath)) {
|
|
42407
|
+
const content = fs90.readFileSync(hookScriptPath, "utf-8");
|
|
42050
42408
|
if (content.includes(HERMES_KG_HOOK_SENTINEL)) {
|
|
42051
|
-
|
|
42409
|
+
fs90.unlinkSync(hookScriptPath);
|
|
42052
42410
|
scriptRemoved = true;
|
|
42053
42411
|
}
|
|
42054
42412
|
}
|
|
42055
42413
|
let configPatched = false;
|
|
42056
|
-
if (
|
|
42414
|
+
if (fs90.existsSync(configPath)) {
|
|
42057
42415
|
const result = patchHermesConfigForHook("uninstall");
|
|
42058
42416
|
configPatched = result === "patched";
|
|
42059
42417
|
}
|
|
@@ -42078,9 +42436,9 @@ function registerKgInstallHookCommand(kg) {
|
|
|
42078
42436
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
42079
42437
|
const filePath = settingsPathFor2(scope);
|
|
42080
42438
|
try {
|
|
42081
|
-
|
|
42439
|
+
fs90.mkdirSync(path89.dirname(filePath), { recursive: true });
|
|
42082
42440
|
} catch (err) {
|
|
42083
|
-
printError(`could not create ${
|
|
42441
|
+
printError(`could not create ${path89.dirname(filePath)}: ${err instanceof Error ? err.message : String(err)}`);
|
|
42084
42442
|
process.exitCode = 1;
|
|
42085
42443
|
return;
|
|
42086
42444
|
}
|
|
@@ -42104,7 +42462,7 @@ function registerKgInstallHookCommand(kg) {
|
|
|
42104
42462
|
printInfo("kg-service hook", `already installed at ${filePath}`);
|
|
42105
42463
|
if (backupPath) {
|
|
42106
42464
|
try {
|
|
42107
|
-
|
|
42465
|
+
fs90.unlinkSync(backupPath);
|
|
42108
42466
|
} catch {
|
|
42109
42467
|
}
|
|
42110
42468
|
}
|
|
@@ -42122,15 +42480,15 @@ function registerKgInstallHookCommand(kg) {
|
|
|
42122
42480
|
}
|
|
42123
42481
|
|
|
42124
42482
|
// src/commands/kg-uninstall-hook.ts
|
|
42125
|
-
import * as
|
|
42126
|
-
import * as
|
|
42483
|
+
import * as fs91 from "node:fs";
|
|
42484
|
+
import * as path90 from "node:path";
|
|
42127
42485
|
import * as os46 from "node:os";
|
|
42128
42486
|
init_output();
|
|
42129
42487
|
function settingsPathFor3(scope) {
|
|
42130
42488
|
if (scope === "user") {
|
|
42131
|
-
return
|
|
42489
|
+
return path90.join(os46.homedir(), ".claude", "settings.json");
|
|
42132
42490
|
}
|
|
42133
|
-
return
|
|
42491
|
+
return path90.join(process.cwd(), ".claude", "settings.json");
|
|
42134
42492
|
}
|
|
42135
42493
|
function dropSentinel(matchers) {
|
|
42136
42494
|
let changed = false;
|
|
@@ -42160,13 +42518,13 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
42160
42518
|
kg.command("uninstall-hook").description("Remove kg-service PreToolUse hook from .claude/settings.json (sentinel-matched; surgical)").option("--scope <scope>", "project (default) or user", "project").action((opts) => {
|
|
42161
42519
|
const scope = opts.scope === "user" ? "user" : "project";
|
|
42162
42520
|
const filePath = settingsPathFor3(scope);
|
|
42163
|
-
if (!
|
|
42521
|
+
if (!fs91.existsSync(filePath)) {
|
|
42164
42522
|
printInfo("kg-service hook", `no settings.json at ${filePath} \u2014 nothing to remove`);
|
|
42165
42523
|
return;
|
|
42166
42524
|
}
|
|
42167
42525
|
let settings;
|
|
42168
42526
|
try {
|
|
42169
|
-
const raw =
|
|
42527
|
+
const raw = fs91.readFileSync(filePath, "utf-8");
|
|
42170
42528
|
settings = raw.trim() ? JSON.parse(raw) : {};
|
|
42171
42529
|
} catch (err) {
|
|
42172
42530
|
printError(`could not parse ${filePath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -42186,7 +42544,7 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
42186
42544
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
42187
42545
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
42188
42546
|
try {
|
|
42189
|
-
|
|
42547
|
+
fs91.copyFileSync(filePath, backupPath);
|
|
42190
42548
|
} catch {
|
|
42191
42549
|
}
|
|
42192
42550
|
const next = {
|
|
@@ -42205,7 +42563,7 @@ function registerKgUninstallHookCommand(kg) {
|
|
|
42205
42563
|
}
|
|
42206
42564
|
}
|
|
42207
42565
|
try {
|
|
42208
|
-
|
|
42566
|
+
fs91.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
42209
42567
|
printSuccess(`kg-service hook removed from ${filePath}`);
|
|
42210
42568
|
printInfo("backup", backupPath);
|
|
42211
42569
|
} catch (err) {
|
|
@@ -42278,8 +42636,8 @@ function registerKgSavingsCommand(kg) {
|
|
|
42278
42636
|
|
|
42279
42637
|
// src/commands/kg-build.ts
|
|
42280
42638
|
function readQueueFromDisk(queuePath) {
|
|
42281
|
-
if (!
|
|
42282
|
-
const raw =
|
|
42639
|
+
if (!fs92.existsSync(queuePath)) return [];
|
|
42640
|
+
const raw = fs92.readFileSync(queuePath, "utf-8");
|
|
42283
42641
|
const entries = [];
|
|
42284
42642
|
for (const line of raw.split("\n")) {
|
|
42285
42643
|
const t = line.trim();
|
|
@@ -42292,14 +42650,14 @@ function readQueueFromDisk(queuePath) {
|
|
|
42292
42650
|
return entries;
|
|
42293
42651
|
}
|
|
42294
42652
|
function writeQueueToDisk(queuePath, entries) {
|
|
42295
|
-
|
|
42653
|
+
fs92.mkdirSync(path91.dirname(queuePath), { recursive: true });
|
|
42296
42654
|
const content = entries.map((e) => JSON.stringify(e)).join("\n") + (entries.length > 0 ? "\n" : "");
|
|
42297
|
-
|
|
42655
|
+
fs92.writeFileSync(queuePath, content, "utf-8");
|
|
42298
42656
|
}
|
|
42299
42657
|
async function runKgBuildPending(opts = {}) {
|
|
42300
42658
|
const queuePath = opts.queuePath ?? (() => {
|
|
42301
|
-
const stateDir = process.env["OLAM_STATE_DIR"] ??
|
|
42302
|
-
return
|
|
42659
|
+
const stateDir = process.env["OLAM_STATE_DIR"] ?? path91.join(os47.homedir(), ".olam", "state");
|
|
42660
|
+
return path91.join(stateDir, "kg-pending.jsonl");
|
|
42303
42661
|
})();
|
|
42304
42662
|
const readQueue2 = opts.readQueueFn ?? readQueueFromDisk;
|
|
42305
42663
|
const writeQueue2 = opts.writeQueueFn ?? writeQueueToDisk;
|
|
@@ -42315,7 +42673,7 @@ async function runKgBuildPending(opts = {}) {
|
|
|
42315
42673
|
const remaining = [];
|
|
42316
42674
|
for (const entry of deduped) {
|
|
42317
42675
|
const repoPath = entry.path;
|
|
42318
|
-
const workspaceName =
|
|
42676
|
+
const workspaceName = path91.basename(repoPath).toLowerCase();
|
|
42319
42677
|
printInfo("kg build --pending", `building ${repoPath} (workspace=${workspaceName})`);
|
|
42320
42678
|
let containerPath;
|
|
42321
42679
|
try {
|
|
@@ -42353,20 +42711,20 @@ async function runKgBuildPending(opts = {}) {
|
|
|
42353
42711
|
}
|
|
42354
42712
|
function resolveWorkspace(arg) {
|
|
42355
42713
|
const cwd = process.cwd();
|
|
42356
|
-
const name = arg ??
|
|
42714
|
+
const name = arg ?? path91.basename(cwd).toLowerCase();
|
|
42357
42715
|
validateWorkspaceName(name);
|
|
42358
42716
|
return { name, sourcePath: cwd };
|
|
42359
42717
|
}
|
|
42360
42718
|
function toContainerPath(hostPath) {
|
|
42361
42719
|
const home = os47.homedir();
|
|
42362
|
-
const resolved =
|
|
42363
|
-
if (!resolved.startsWith(home +
|
|
42720
|
+
const resolved = path91.resolve(hostPath);
|
|
42721
|
+
if (!resolved.startsWith(home + path91.sep) && resolved !== home) {
|
|
42364
42722
|
throw new Error(
|
|
42365
42723
|
`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.`
|
|
42366
42724
|
);
|
|
42367
42725
|
}
|
|
42368
|
-
const rel =
|
|
42369
|
-
return rel === "" ? "/host-home" :
|
|
42726
|
+
const rel = path91.relative(home, resolved);
|
|
42727
|
+
return rel === "" ? "/host-home" : path91.posix.join("/host-home", rel.split(path91.sep).join("/"));
|
|
42370
42728
|
}
|
|
42371
42729
|
async function runKgBuild(workspaceArg, options = {}) {
|
|
42372
42730
|
let workspace;
|
|
@@ -42384,7 +42742,7 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
42384
42742
|
return { exitCode: 2 };
|
|
42385
42743
|
}
|
|
42386
42744
|
const outDir = kgPristinePath(workspace.name);
|
|
42387
|
-
|
|
42745
|
+
fs92.mkdirSync(outDir, { recursive: true });
|
|
42388
42746
|
const human = !options.json;
|
|
42389
42747
|
if (human) {
|
|
42390
42748
|
printInfo("kg build", `workspace=${workspace.name} source=${workspace.sourcePath}`);
|
|
@@ -42417,12 +42775,12 @@ async function runKgBuild(workspaceArg, options = {}) {
|
|
|
42417
42775
|
workspace: workspace.name,
|
|
42418
42776
|
graphify_path: "container"
|
|
42419
42777
|
};
|
|
42420
|
-
|
|
42421
|
-
|
|
42778
|
+
fs92.writeFileSync(
|
|
42779
|
+
path91.join(outDir, "freshness.json"),
|
|
42422
42780
|
JSON.stringify(freshness, null, 2) + "\n",
|
|
42423
42781
|
"utf-8"
|
|
42424
42782
|
);
|
|
42425
|
-
const finalOut =
|
|
42783
|
+
const finalOut = path91.join(outDir, "graphify-out");
|
|
42426
42784
|
if (options.json) {
|
|
42427
42785
|
process.stdout.write(JSON.stringify(freshness) + "\n");
|
|
42428
42786
|
} else {
|
|
@@ -42465,11 +42823,11 @@ function registerKg(program2) {
|
|
|
42465
42823
|
init_file_lock();
|
|
42466
42824
|
import { mkdirSync as mkdirSync63, appendFileSync as appendFileSync6 } from "node:fs";
|
|
42467
42825
|
import { homedir as homedir57 } from "node:os";
|
|
42468
|
-
import { dirname as dirname59, join as
|
|
42826
|
+
import { dirname as dirname59, join as join100 } from "node:path";
|
|
42469
42827
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
42470
42828
|
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "high", "medium", "low", "info", "warn"]);
|
|
42471
42829
|
var PROMPT_FEEDING_FIELDS = ["extracted_pattern", "severity", "affected_persona", "proposed_edit"];
|
|
42472
|
-
var BREADCRUMBS_BASE =
|
|
42830
|
+
var BREADCRUMBS_BASE = join100(homedir57(), ".local", "share", "claude", "breadcrumbs");
|
|
42473
42831
|
var LOCK_FILENAME = ".flywheel-emit.lock";
|
|
42474
42832
|
function buildRecord(opts) {
|
|
42475
42833
|
const rec = {
|
|
@@ -42516,7 +42874,7 @@ function validatePromptFeeding(rec) {
|
|
|
42516
42874
|
}
|
|
42517
42875
|
function destPath(projectSlug) {
|
|
42518
42876
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
42519
|
-
return
|
|
42877
|
+
return join100(BREADCRUMBS_BASE, projectSlug, `${today}.jsonl`);
|
|
42520
42878
|
}
|
|
42521
42879
|
async function emitBreadcrumb(opts) {
|
|
42522
42880
|
if (!VALID_SEVERITIES.has(opts.severity)) {
|
|
@@ -42535,14 +42893,14 @@ async function emitBreadcrumb(opts) {
|
|
|
42535
42893
|
);
|
|
42536
42894
|
process.exit(2);
|
|
42537
42895
|
}
|
|
42538
|
-
const
|
|
42539
|
-
const lockDir = dirname59(
|
|
42896
|
+
const path94 = destPath(rec.project_slug);
|
|
42897
|
+
const lockDir = dirname59(path94);
|
|
42540
42898
|
mkdirSync63(lockDir, { recursive: true });
|
|
42541
42899
|
const line = JSON.stringify(rec) + "\n";
|
|
42542
42900
|
await withFileLock(
|
|
42543
42901
|
lockDir,
|
|
42544
42902
|
() => {
|
|
42545
|
-
appendFileSync6(
|
|
42903
|
+
appendFileSync6(path94, line, "utf8");
|
|
42546
42904
|
},
|
|
42547
42905
|
{
|
|
42548
42906
|
lockFilename: LOCK_FILENAME,
|
|
@@ -42552,7 +42910,7 @@ async function emitBreadcrumb(opts) {
|
|
|
42552
42910
|
acquireTimeoutMs: 5e3
|
|
42553
42911
|
}
|
|
42554
42912
|
);
|
|
42555
|
-
process.stdout.write(`[K7-emit] ${
|
|
42913
|
+
process.stdout.write(`[K7-emit] ${path94}: ${rec.extracted_pattern} (${rec.severity})
|
|
42556
42914
|
`);
|
|
42557
42915
|
}
|
|
42558
42916
|
function registerFlywheelEmitBreadcrumb(parent) {
|
|
@@ -42617,7 +42975,7 @@ function registerFlywheelK5Score(parent) {
|
|
|
42617
42975
|
}
|
|
42618
42976
|
|
|
42619
42977
|
// src/commands/flywheel/k5-validate.ts
|
|
42620
|
-
import { readFileSync as
|
|
42978
|
+
import { readFileSync as readFileSync86, statSync as statSync30 } from "node:fs";
|
|
42621
42979
|
import { parse as parseYAML } from "yaml";
|
|
42622
42980
|
var K5_DIMS = ["direction", "approach", "open_questions", "constraints", "reuse"];
|
|
42623
42981
|
var MAX_PLAN_BYTES = 1048576;
|
|
@@ -42675,38 +43033,38 @@ function validateK5ScoredAt(scoredAt) {
|
|
|
42675
43033
|
}
|
|
42676
43034
|
return null;
|
|
42677
43035
|
}
|
|
42678
|
-
function validatePlan(
|
|
43036
|
+
function validatePlan(path94) {
|
|
42679
43037
|
let stat;
|
|
42680
43038
|
try {
|
|
42681
|
-
stat = statSync30(
|
|
43039
|
+
stat = statSync30(path94);
|
|
42682
43040
|
} catch (err) {
|
|
42683
|
-
return { ok: false, message: `FAIL cannot stat ${
|
|
43041
|
+
return { ok: false, message: `FAIL cannot stat ${path94}: ${err instanceof Error ? err.message : "unknown"}` };
|
|
42684
43042
|
}
|
|
42685
43043
|
if (stat.size > MAX_PLAN_BYTES) {
|
|
42686
|
-
return { ok: false, message: `FAIL ${
|
|
43044
|
+
return { ok: false, message: `FAIL ${path94}: plan file exceeds 1MB (${stat.size} bytes); refusing to parse` };
|
|
42687
43045
|
}
|
|
42688
43046
|
let text;
|
|
42689
43047
|
try {
|
|
42690
|
-
text =
|
|
43048
|
+
text = readFileSync86(path94, "utf8");
|
|
42691
43049
|
} catch (err) {
|
|
42692
|
-
return { ok: false, message: `FAIL cannot read ${
|
|
43050
|
+
return { ok: false, message: `FAIL cannot read ${path94}: ${err instanceof Error ? err.message : "unknown"}` };
|
|
42693
43051
|
}
|
|
42694
43052
|
if (!text.replace(/^/, "").startsWith("---")) {
|
|
42695
|
-
return { ok: false, message: `FAIL ${
|
|
43053
|
+
return { ok: false, message: `FAIL ${path94}: no YAML frontmatter (missing opening --- marker)` };
|
|
42696
43054
|
}
|
|
42697
43055
|
if (!text.includes("\n---", 3)) {
|
|
42698
|
-
return { ok: false, message: `FAIL ${
|
|
43056
|
+
return { ok: false, message: `FAIL ${path94}: frontmatter block never closed (missing closing --- marker)` };
|
|
42699
43057
|
}
|
|
42700
43058
|
const fm = extractFrontmatter(text);
|
|
42701
43059
|
if (fm === null) {
|
|
42702
|
-
return { ok: false, message: `FAIL ${
|
|
43060
|
+
return { ok: false, message: `FAIL ${path94}: frontmatter could not be parsed as YAML` };
|
|
42703
43061
|
}
|
|
42704
43062
|
const hasScores = "k5_scores" in fm;
|
|
42705
43063
|
const hasBoost = "k5_boost" in fm;
|
|
42706
43064
|
const hasComposite = "k5_composite" in fm;
|
|
42707
43065
|
const hasScoredAt = "k5_scored_at" in fm;
|
|
42708
43066
|
if (!hasScores && !hasBoost && !hasComposite && !hasScoredAt) {
|
|
42709
|
-
return { ok: true, message: `PASS ${
|
|
43067
|
+
return { ok: true, message: `PASS ${path94}: k5_scores absent (acceptable \u2014 legacy plan)` };
|
|
42710
43068
|
}
|
|
42711
43069
|
const errors = [];
|
|
42712
43070
|
if (hasScores) {
|
|
@@ -42726,9 +43084,9 @@ function validatePlan(path93) {
|
|
|
42726
43084
|
if (err !== null) errors.push(err);
|
|
42727
43085
|
}
|
|
42728
43086
|
if (errors.length > 0) {
|
|
42729
|
-
return { ok: false, message: `FAIL ${
|
|
43087
|
+
return { ok: false, message: `FAIL ${path94}: ${errors.join("; ")}` };
|
|
42730
43088
|
}
|
|
42731
|
-
const lines = [`PASS ${
|
|
43089
|
+
const lines = [`PASS ${path94}: k5_scores valid`];
|
|
42732
43090
|
if (hasScores && typeof fm.k5_scores === "object" && fm.k5_scores !== null) {
|
|
42733
43091
|
const scoresObj = fm.k5_scores;
|
|
42734
43092
|
const vals = [];
|
|
@@ -42769,7 +43127,7 @@ function registerFlywheelK5Validate(parent) {
|
|
|
42769
43127
|
}
|
|
42770
43128
|
|
|
42771
43129
|
// src/commands/flywheel/k10-measure.ts
|
|
42772
|
-
import { readFileSync as
|
|
43130
|
+
import { readFileSync as readFileSync87 } from "node:fs";
|
|
42773
43131
|
|
|
42774
43132
|
// ../core/dist/lib/k10-budget.js
|
|
42775
43133
|
var K10_TOKEN_CAP = 5500;
|
|
@@ -42826,7 +43184,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
42826
43184
|
parent.command("k10-measure").description("Measure K10 token budget for upstream + optional overlay; emit PASS/REJECT verdict").requiredOption("--upstream <path>", "path to upstream file (e.g. persona prompt)").option("--overlay <path>", "path to overlay file (omit if none \u2014 PASS without enforcement)").option("--json", "emit verdict as JSON instead of human-readable").action((opts) => {
|
|
42827
43185
|
let upstreamText;
|
|
42828
43186
|
try {
|
|
42829
|
-
upstreamText =
|
|
43187
|
+
upstreamText = readFileSync87(opts.upstream, "utf8");
|
|
42830
43188
|
} catch (err) {
|
|
42831
43189
|
process.stderr.write(
|
|
42832
43190
|
`[k10-measure-error] cannot read upstream ${opts.upstream}: ${err instanceof Error ? err.message : "unknown"}
|
|
@@ -42838,7 +43196,7 @@ function registerFlywheelK10Measure(parent) {
|
|
|
42838
43196
|
let overlayTokens = null;
|
|
42839
43197
|
if (opts.overlay !== void 0) {
|
|
42840
43198
|
try {
|
|
42841
|
-
const overlayText =
|
|
43199
|
+
const overlayText = readFileSync87(opts.overlay, "utf8");
|
|
42842
43200
|
overlayTokens = tokensFromText(overlayText);
|
|
42843
43201
|
} catch (err) {
|
|
42844
43202
|
process.stderr.write(
|
|
@@ -42872,13 +43230,13 @@ function registerFlywheelK10Measure(parent) {
|
|
|
42872
43230
|
}
|
|
42873
43231
|
|
|
42874
43232
|
// src/commands/flywheel/check-persona-skeleton.ts
|
|
42875
|
-
import { existsSync as existsSync109, readFileSync as
|
|
43233
|
+
import { existsSync as existsSync109, readFileSync as readFileSync88, statSync as statSync31 } from "node:fs";
|
|
42876
43234
|
import { homedir as homedir58 } from "node:os";
|
|
42877
|
-
import { basename as basename14, join as
|
|
43235
|
+
import { basename as basename14, join as join101 } from "node:path";
|
|
42878
43236
|
import { parse as parseYAML2 } from "yaml";
|
|
42879
43237
|
var CHARS_PER_TOKEN3 = 4;
|
|
42880
43238
|
var K10_TOKEN_CAP2 = 6e3;
|
|
42881
|
-
var AGENTS_DIR =
|
|
43239
|
+
var AGENTS_DIR = join101(homedir58(), ".claude", "agents");
|
|
42882
43240
|
var REQUIRED_FRONTMATTER_KEYS = ["name", "description", "allowed-tools"];
|
|
42883
43241
|
var REQUIRED_SECTIONS = [
|
|
42884
43242
|
"## Role",
|
|
@@ -42921,7 +43279,7 @@ function checkFile(filepath) {
|
|
|
42921
43279
|
if (!existsSync109(filepath) || !statSync31(filepath).isFile()) {
|
|
42922
43280
|
return { passed: false, failures: [`file not found: ${filepath}`], tokens: 0, mergedSkipped: false };
|
|
42923
43281
|
}
|
|
42924
|
-
const text =
|
|
43282
|
+
const text = readFileSync88(filepath, "utf8");
|
|
42925
43283
|
const { fm, body } = parseFile(text);
|
|
42926
43284
|
const failures = [];
|
|
42927
43285
|
for (const key of REQUIRED_FRONTMATTER_KEYS) {
|
|
@@ -42934,7 +43292,7 @@ function checkFile(filepath) {
|
|
|
42934
43292
|
const agentName = typeof fm.name === "string" ? fm.name : "";
|
|
42935
43293
|
let mergedSkipped = false;
|
|
42936
43294
|
if (!isNewAgent && agentName !== "") {
|
|
42937
|
-
const upstreamPath =
|
|
43295
|
+
const upstreamPath = join101(AGENTS_DIR, `${agentName}.md`);
|
|
42938
43296
|
if (existsSync109(upstreamPath)) {
|
|
42939
43297
|
mergedSkipped = true;
|
|
42940
43298
|
}
|
|
@@ -42987,7 +43345,7 @@ Results: ${passCount} passed, ${failCount} failed
|
|
|
42987
43345
|
}
|
|
42988
43346
|
|
|
42989
43347
|
// src/commands/flywheel/diversity-check.ts
|
|
42990
|
-
import { readFileSync as
|
|
43348
|
+
import { readFileSync as readFileSync89 } from "node:fs";
|
|
42991
43349
|
import { basename as basename15 } from "node:path";
|
|
42992
43350
|
import { globSync as globSync2 } from "node:fs";
|
|
42993
43351
|
|
|
@@ -43096,7 +43454,7 @@ function registerFlywheelDiversityCheck(parent) {
|
|
|
43096
43454
|
const personas = /* @__PURE__ */ new Map();
|
|
43097
43455
|
for (const filepath of files) {
|
|
43098
43456
|
try {
|
|
43099
|
-
const body =
|
|
43457
|
+
const body = readFileSync89(filepath, "utf8");
|
|
43100
43458
|
if (body.trim().length > 0) {
|
|
43101
43459
|
personas.set(basename15(filepath, ".md"), body);
|
|
43102
43460
|
}
|
|
@@ -43129,7 +43487,7 @@ ${formatRedivergencePrompt(persona_a, persona_b, score, void 0, void 0, threshol
|
|
|
43129
43487
|
// src/commands/flywheel/ping.ts
|
|
43130
43488
|
import { mkdirSync as mkdirSync64, writeFileSync as writeFileSync56 } from "node:fs";
|
|
43131
43489
|
import { homedir as homedir59 } from "node:os";
|
|
43132
|
-
import { dirname as dirname60, join as
|
|
43490
|
+
import { dirname as dirname60, join as join102 } from "node:path";
|
|
43133
43491
|
var COLD_START_BUDGET_GOOD_MS = 200;
|
|
43134
43492
|
var COLD_START_BUDGET_FAIR_MS = 500;
|
|
43135
43493
|
function classifyColdStart(coldStartMs) {
|
|
@@ -43145,7 +43503,7 @@ function readOlamVersion() {
|
|
|
43145
43503
|
}
|
|
43146
43504
|
}
|
|
43147
43505
|
function writeBaseline(record) {
|
|
43148
|
-
const baselinePath =
|
|
43506
|
+
const baselinePath = join102(homedir59(), ".local", "share", "olam", "flywheel-baseline.json");
|
|
43149
43507
|
mkdirSync64(dirname60(baselinePath), { recursive: true });
|
|
43150
43508
|
writeFileSync56(baselinePath, JSON.stringify(record, null, 2) + "\n", "utf8");
|
|
43151
43509
|
return baselinePath;
|
|
@@ -43184,18 +43542,19 @@ function registerFlywheelPing(parent) {
|
|
|
43184
43542
|
// src/commands/flywheel/migrate-overlays.ts
|
|
43185
43543
|
init_shim_targets();
|
|
43186
43544
|
init_skill_sources();
|
|
43545
|
+
init_prefix_rules();
|
|
43187
43546
|
import {
|
|
43188
43547
|
copyFileSync as copyFileSync15,
|
|
43189
43548
|
existsSync as existsSync110,
|
|
43190
43549
|
mkdirSync as mkdirSync65,
|
|
43191
|
-
readFileSync as
|
|
43550
|
+
readFileSync as readFileSync90,
|
|
43192
43551
|
readdirSync as readdirSync31,
|
|
43193
43552
|
statSync as statSync32,
|
|
43194
43553
|
writeFileSync as writeFileSync57
|
|
43195
43554
|
} from "node:fs";
|
|
43196
43555
|
import { spawnSync as spawnSync29 } from "node:child_process";
|
|
43197
43556
|
import { homedir as homedir60 } from "node:os";
|
|
43198
|
-
import { dirname as dirname61, join as
|
|
43557
|
+
import { dirname as dirname61, join as join103, relative as relative7 } from "node:path";
|
|
43199
43558
|
function escapeRegex(s) {
|
|
43200
43559
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
43201
43560
|
}
|
|
@@ -43232,7 +43591,7 @@ function walkOverlayFiles(dir) {
|
|
|
43232
43591
|
return [];
|
|
43233
43592
|
}
|
|
43234
43593
|
for (const entry of entries) {
|
|
43235
|
-
const fullPath =
|
|
43594
|
+
const fullPath = join103(dir, entry);
|
|
43236
43595
|
let stat;
|
|
43237
43596
|
try {
|
|
43238
43597
|
stat = statSync32(fullPath);
|
|
@@ -43271,10 +43630,10 @@ function resolveAtlasUser2(opts) {
|
|
|
43271
43630
|
assertValidAtlasUser(v);
|
|
43272
43631
|
return v;
|
|
43273
43632
|
}
|
|
43274
|
-
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ??
|
|
43275
|
-
const f =
|
|
43633
|
+
const claudeDir2 = opts._testClaudeDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join103(homedir60(), ".claude");
|
|
43634
|
+
const f = join103(claudeDir2, ".atlas-user");
|
|
43276
43635
|
if (existsSync110(f)) {
|
|
43277
|
-
const v =
|
|
43636
|
+
const v = readFileSync90(f, "utf-8").trim();
|
|
43278
43637
|
if (v.length === 0) return null;
|
|
43279
43638
|
assertValidAtlasUser(v);
|
|
43280
43639
|
return v;
|
|
@@ -43296,8 +43655,8 @@ function runGit2(args, cwd) {
|
|
|
43296
43655
|
function walkPushSourceFiles(claudeDir2) {
|
|
43297
43656
|
const result = [];
|
|
43298
43657
|
const roots = [
|
|
43299
|
-
{ dir:
|
|
43300
|
-
{ dir:
|
|
43658
|
+
{ dir: join103(claudeDir2, "skills.overrides"), overlayKind: "skills" },
|
|
43659
|
+
{ dir: join103(claudeDir2, "agents.overrides"), overlayKind: "agents" }
|
|
43301
43660
|
];
|
|
43302
43661
|
for (const { dir, overlayKind } of roots) {
|
|
43303
43662
|
const files = walkOverlayFiles(dir);
|
|
@@ -43408,6 +43767,27 @@ function pushOverlays(opts) {
|
|
|
43408
43767
|
Run \`olam skills atlas-user set <name>\` to configure your atlas user.`
|
|
43409
43768
|
);
|
|
43410
43769
|
}
|
|
43770
|
+
const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join103(homedir60(), ".claude");
|
|
43771
|
+
const sourceFiles = walkPushSourceFiles(claudeDir2);
|
|
43772
|
+
const registeredPrefixes = (opts._testSkillSources ?? listSkillSources()).map((s) => s.prefix).filter((p) => typeof p === "string" && p.length > 0);
|
|
43773
|
+
if (registeredPrefixes.length > 0) {
|
|
43774
|
+
for (const { srcFile, relPath } of sourceFiles) {
|
|
43775
|
+
const basename16 = relPath.split("/").pop() ?? relPath;
|
|
43776
|
+
let content;
|
|
43777
|
+
try {
|
|
43778
|
+
content = readFileSync90(srcFile);
|
|
43779
|
+
} catch {
|
|
43780
|
+
continue;
|
|
43781
|
+
}
|
|
43782
|
+
const validation = validateCanonical(basename16, content, registeredPrefixes);
|
|
43783
|
+
if (!validation.ok && validation.violation !== void 0) {
|
|
43784
|
+
throw new PushError(
|
|
43785
|
+
1,
|
|
43786
|
+
formatCanonicalViolation(relPath, validation.violation)
|
|
43787
|
+
);
|
|
43788
|
+
}
|
|
43789
|
+
}
|
|
43790
|
+
}
|
|
43411
43791
|
let clonePath;
|
|
43412
43792
|
if (opts._testClonePath !== void 0) {
|
|
43413
43793
|
clonePath = opts._testClonePath;
|
|
@@ -43426,8 +43806,6 @@ function pushOverlays(opts) {
|
|
|
43426
43806
|
}
|
|
43427
43807
|
clonePath = skillSourceClonePath(source.id);
|
|
43428
43808
|
}
|
|
43429
|
-
const claudeDir2 = opts._testClaudeDir ?? opts.targetDir ?? process.env["OLAM_CLAUDE_DIR"] ?? join102(homedir60(), ".claude");
|
|
43430
|
-
const sourceFiles = walkPushSourceFiles(claudeDir2);
|
|
43431
43809
|
if (opts.dryRun === true) {
|
|
43432
43810
|
const { preflightWarnings } = runPreFlight(clonePath, opts.forceCurrentBranch === true, true);
|
|
43433
43811
|
if (preflightWarnings.length > 0) {
|
|
@@ -43436,21 +43814,21 @@ function pushOverlays(opts) {
|
|
|
43436
43814
|
` + preflightWarnings.map((w) => ` - ${w.split("\n")[0]}`).join("\n") + "\n"
|
|
43437
43815
|
);
|
|
43438
43816
|
}
|
|
43439
|
-
const membersBase2 =
|
|
43817
|
+
const membersBase2 = join103(clonePath, "members", atlasUser);
|
|
43440
43818
|
let wouldCopy = 0;
|
|
43441
43819
|
let wouldUnchange = 0;
|
|
43442
43820
|
let wouldCreate = 0;
|
|
43443
43821
|
for (const { srcFile, overlayKind, relPath } of sourceFiles) {
|
|
43444
|
-
const targetDir =
|
|
43445
|
-
const targetFile =
|
|
43822
|
+
const targetDir = join103(membersBase2, `${overlayKind}.overrides`);
|
|
43823
|
+
const targetFile = join103(targetDir, relPath);
|
|
43446
43824
|
let srcBuf;
|
|
43447
43825
|
try {
|
|
43448
|
-
srcBuf =
|
|
43826
|
+
srcBuf = readFileSync90(srcFile);
|
|
43449
43827
|
} catch {
|
|
43450
43828
|
continue;
|
|
43451
43829
|
}
|
|
43452
43830
|
if (existsSync110(targetFile)) {
|
|
43453
|
-
const dstBuf =
|
|
43831
|
+
const dstBuf = readFileSync90(targetFile);
|
|
43454
43832
|
if (srcBuf.equals(dstBuf)) {
|
|
43455
43833
|
wouldUnchange += 1;
|
|
43456
43834
|
process.stdout.write(` [skip] ${overlayKind}.overrides/${relPath} (unchanged)
|
|
@@ -43491,23 +43869,23 @@ function pushOverlays(opts) {
|
|
|
43491
43869
|
`failed to create branch "${branchName}": ${err instanceof Error ? err.message : String(err)}`
|
|
43492
43870
|
);
|
|
43493
43871
|
}
|
|
43494
|
-
const membersBase =
|
|
43872
|
+
const membersBase = join103(clonePath, "members", atlasUser);
|
|
43495
43873
|
let filesCopied = 0;
|
|
43496
43874
|
let filesUnchanged = 0;
|
|
43497
43875
|
let filesCreated = 0;
|
|
43498
43876
|
try {
|
|
43499
43877
|
for (const { srcFile, overlayKind, relPath } of sourceFiles) {
|
|
43500
|
-
const targetDir =
|
|
43501
|
-
const targetFile =
|
|
43878
|
+
const targetDir = join103(membersBase, `${overlayKind}.overrides`, dirname61(relPath));
|
|
43879
|
+
const targetFile = join103(membersBase, `${overlayKind}.overrides`, relPath);
|
|
43502
43880
|
let srcBuf;
|
|
43503
43881
|
try {
|
|
43504
|
-
srcBuf =
|
|
43882
|
+
srcBuf = readFileSync90(srcFile);
|
|
43505
43883
|
} catch {
|
|
43506
43884
|
continue;
|
|
43507
43885
|
}
|
|
43508
43886
|
const targetExists = existsSync110(targetFile);
|
|
43509
43887
|
if (targetExists) {
|
|
43510
|
-
const dstBuf =
|
|
43888
|
+
const dstBuf = readFileSync90(targetFile);
|
|
43511
43889
|
if (srcBuf.equals(dstBuf)) {
|
|
43512
43890
|
filesUnchanged += 1;
|
|
43513
43891
|
continue;
|
|
@@ -43584,7 +43962,7 @@ function initMember(opts) {
|
|
|
43584
43962
|
clonePath = skillSourceClonePath(source.id);
|
|
43585
43963
|
}
|
|
43586
43964
|
const atlasUser = resolveAtlasUser2(opts) ?? memberName;
|
|
43587
|
-
const memberDir =
|
|
43965
|
+
const memberDir = join103(clonePath, "members", memberName);
|
|
43588
43966
|
if (existsSync110(memberDir)) {
|
|
43589
43967
|
throw new PushError(
|
|
43590
43968
|
1,
|
|
@@ -43593,9 +43971,9 @@ function initMember(opts) {
|
|
|
43593
43971
|
);
|
|
43594
43972
|
}
|
|
43595
43973
|
const wouldCreate = [
|
|
43596
|
-
|
|
43597
|
-
|
|
43598
|
-
|
|
43974
|
+
join103(memberDir, "skills.overrides", ".gitkeep"),
|
|
43975
|
+
join103(memberDir, "agents.overrides", ".gitkeep"),
|
|
43976
|
+
join103(memberDir, "README.md")
|
|
43599
43977
|
];
|
|
43600
43978
|
if (opts.dryRun === true) {
|
|
43601
43979
|
const { preflightWarnings } = runPreFlight(clonePath, opts.forceCurrentBranch === true, true);
|
|
@@ -43651,12 +44029,12 @@ function initMember(opts) {
|
|
|
43651
44029
|
);
|
|
43652
44030
|
}
|
|
43653
44031
|
try {
|
|
43654
|
-
mkdirSync65(
|
|
43655
|
-
writeFileSync57(
|
|
43656
|
-
mkdirSync65(
|
|
43657
|
-
writeFileSync57(
|
|
44032
|
+
mkdirSync65(join103(memberDir, "skills.overrides"), { recursive: true });
|
|
44033
|
+
writeFileSync57(join103(memberDir, "skills.overrides", ".gitkeep"), "");
|
|
44034
|
+
mkdirSync65(join103(memberDir, "agents.overrides"), { recursive: true });
|
|
44035
|
+
writeFileSync57(join103(memberDir, "agents.overrides", ".gitkeep"), "");
|
|
43658
44036
|
writeFileSync57(
|
|
43659
|
-
|
|
44037
|
+
join103(memberDir, "README.md"),
|
|
43660
44038
|
`# Member overlays for \`${memberName}\`
|
|
43661
44039
|
|
|
43662
44040
|
See docs/plans/member-overlays-sync/ for layer architecture.
|
|
@@ -43697,10 +44075,10 @@ Next steps (run in ${clonePath}):`,
|
|
|
43697
44075
|
};
|
|
43698
44076
|
}
|
|
43699
44077
|
function migrateOverlays(opts = {}) {
|
|
43700
|
-
const root = opts.targetDir ??
|
|
44078
|
+
const root = opts.targetDir ?? join103(homedir60(), ".claude");
|
|
43701
44079
|
const overrideRoots = [
|
|
43702
|
-
|
|
43703
|
-
|
|
44080
|
+
join103(root, "skills.overrides"),
|
|
44081
|
+
join103(root, "agents.overrides")
|
|
43704
44082
|
];
|
|
43705
44083
|
const allFiles = [];
|
|
43706
44084
|
for (const overrideRoot of overrideRoots) {
|
|
@@ -43716,7 +44094,7 @@ function migrateOverlays(opts = {}) {
|
|
|
43716
44094
|
for (const filePath of allFiles) {
|
|
43717
44095
|
let original;
|
|
43718
44096
|
try {
|
|
43719
|
-
original =
|
|
44097
|
+
original = readFileSync90(filePath, "utf8");
|
|
43720
44098
|
} catch {
|
|
43721
44099
|
continue;
|
|
43722
44100
|
}
|
|
@@ -43819,7 +44197,7 @@ function registerFlywheelMigrateOverlays(parent) {
|
|
|
43819
44197
|
}
|
|
43820
44198
|
return;
|
|
43821
44199
|
}
|
|
43822
|
-
const root = opts.targetDir ??
|
|
44200
|
+
const root = opts.targetDir ?? join103(homedir60(), ".claude");
|
|
43823
44201
|
const summary2 = migrateOverlays(opts);
|
|
43824
44202
|
if (opts.json === true) {
|
|
43825
44203
|
process.stdout.write(JSON.stringify(summary2, null, 2) + "\n");
|
|
@@ -44123,14 +44501,14 @@ init_manager();
|
|
|
44123
44501
|
init_context();
|
|
44124
44502
|
init_output();
|
|
44125
44503
|
import { spawnSync as defaultSpawnSync } from "node:child_process";
|
|
44126
|
-
import * as
|
|
44504
|
+
import * as fs93 from "node:fs";
|
|
44127
44505
|
import * as os48 from "node:os";
|
|
44128
|
-
import * as
|
|
44506
|
+
import * as path92 from "node:path";
|
|
44129
44507
|
function devboxContainerName(worldId) {
|
|
44130
44508
|
return `olam-${worldId}-devbox`;
|
|
44131
44509
|
}
|
|
44132
44510
|
function olamHomeDir() {
|
|
44133
|
-
return process.env["OLAM_HOME"] ??
|
|
44511
|
+
return process.env["OLAM_HOME"] ?? path92.join(os48.homedir(), ".olam");
|
|
44134
44512
|
}
|
|
44135
44513
|
function defaultRestartContainer(name, spawn13 = defaultSpawnSync) {
|
|
44136
44514
|
const r = spawn13("docker", ["restart", "--time", "30", name], {
|
|
@@ -44143,8 +44521,8 @@ function defaultRestartContainer(name, spawn13 = defaultSpawnSync) {
|
|
|
44143
44521
|
};
|
|
44144
44522
|
}
|
|
44145
44523
|
function defaultAppendAuditLog(homeDir, line) {
|
|
44146
|
-
|
|
44147
|
-
|
|
44524
|
+
fs93.mkdirSync(homeDir, { recursive: true });
|
|
44525
|
+
fs93.appendFileSync(path92.join(homeDir, "usage.log"), line.endsWith("\n") ? line : line + "\n", {
|
|
44148
44526
|
encoding: "utf-8"
|
|
44149
44527
|
});
|
|
44150
44528
|
}
|
|
@@ -44189,19 +44567,19 @@ async function doRekey(worldId, deps) {
|
|
|
44189
44567
|
);
|
|
44190
44568
|
const rotatedAt = deps.now().toISOString();
|
|
44191
44569
|
const homeDir = deps.olamHomeDir();
|
|
44192
|
-
const worldDir =
|
|
44193
|
-
|
|
44194
|
-
const credentialsPath =
|
|
44570
|
+
const worldDir = path92.join(homeDir, "worlds", worldId);
|
|
44571
|
+
fs93.mkdirSync(worldDir, { recursive: true });
|
|
44572
|
+
const credentialsPath = path92.join(worldDir, "credentials.json");
|
|
44195
44573
|
const payload = {
|
|
44196
44574
|
worldRoleName,
|
|
44197
44575
|
password,
|
|
44198
44576
|
rotatedAt
|
|
44199
44577
|
};
|
|
44200
|
-
|
|
44578
|
+
fs93.writeFileSync(credentialsPath, JSON.stringify(payload, null, 2) + "\n", {
|
|
44201
44579
|
encoding: "utf-8",
|
|
44202
44580
|
mode: 384
|
|
44203
44581
|
});
|
|
44204
|
-
|
|
44582
|
+
fs93.chmodSync(credentialsPath, 384);
|
|
44205
44583
|
const restart = deps.restartContainer(devboxContainerName(worldId));
|
|
44206
44584
|
deps.appendAuditLog(`${rotatedAt} ${worldId} rekey`);
|
|
44207
44585
|
if (!restart.ok) {
|
|
@@ -44265,18 +44643,18 @@ function registerRekey(program2) {
|
|
|
44265
44643
|
}
|
|
44266
44644
|
|
|
44267
44645
|
// src/pleri-config.ts
|
|
44268
|
-
import * as
|
|
44269
|
-
import * as
|
|
44646
|
+
import * as fs94 from "node:fs";
|
|
44647
|
+
import * as path93 from "node:path";
|
|
44270
44648
|
function isPleriConfigured(configDir = process.env.OLAM_CONFIG_DIR ?? ".olam") {
|
|
44271
44649
|
if (process.env.PLERI_BASE_URL) {
|
|
44272
44650
|
return true;
|
|
44273
44651
|
}
|
|
44274
|
-
const configPath =
|
|
44275
|
-
if (!
|
|
44652
|
+
const configPath = path93.join(configDir, "config.yaml");
|
|
44653
|
+
if (!fs94.existsSync(configPath)) {
|
|
44276
44654
|
return false;
|
|
44277
44655
|
}
|
|
44278
44656
|
try {
|
|
44279
|
-
const contents =
|
|
44657
|
+
const contents = fs94.readFileSync(configPath, "utf8");
|
|
44280
44658
|
return /^[^#\n]*\bpleri:/m.test(contents);
|
|
44281
44659
|
} catch {
|
|
44282
44660
|
return false;
|