@pleri/olam-cli 0.1.161 → 0.1.166
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/mcp-server.js
CHANGED
|
@@ -445,8 +445,8 @@ var init_parseUtil = __esm({
|
|
|
445
445
|
init_errors();
|
|
446
446
|
init_en();
|
|
447
447
|
makeIssue = (params) => {
|
|
448
|
-
const { data, path:
|
|
449
|
-
const fullPath = [...
|
|
448
|
+
const { data, path: path49, errorMaps, issueData } = params;
|
|
449
|
+
const fullPath = [...path49, ...issueData.path || []];
|
|
450
450
|
const fullIssue = {
|
|
451
451
|
...issueData,
|
|
452
452
|
path: fullPath
|
|
@@ -754,11 +754,11 @@ var init_types = __esm({
|
|
|
754
754
|
init_parseUtil();
|
|
755
755
|
init_util();
|
|
756
756
|
ParseInputLazyPath = class {
|
|
757
|
-
constructor(parent, value,
|
|
757
|
+
constructor(parent, value, path49, key) {
|
|
758
758
|
this._cachedPath = [];
|
|
759
759
|
this.parent = parent;
|
|
760
760
|
this.data = value;
|
|
761
|
-
this._path =
|
|
761
|
+
this._path = path49;
|
|
762
762
|
this._key = key;
|
|
763
763
|
}
|
|
764
764
|
get path() {
|
|
@@ -7332,8 +7332,8 @@ var require_utils = __commonJS({
|
|
|
7332
7332
|
}
|
|
7333
7333
|
return ind;
|
|
7334
7334
|
}
|
|
7335
|
-
function removeDotSegments(
|
|
7336
|
-
let input =
|
|
7335
|
+
function removeDotSegments(path49) {
|
|
7336
|
+
let input = path49;
|
|
7337
7337
|
const output = [];
|
|
7338
7338
|
let nextSlash = -1;
|
|
7339
7339
|
let len = 0;
|
|
@@ -7532,8 +7532,8 @@ var require_schemes = __commonJS({
|
|
|
7532
7532
|
wsComponent.secure = void 0;
|
|
7533
7533
|
}
|
|
7534
7534
|
if (wsComponent.resourceName) {
|
|
7535
|
-
const [
|
|
7536
|
-
wsComponent.path =
|
|
7535
|
+
const [path49, query] = wsComponent.resourceName.split("?");
|
|
7536
|
+
wsComponent.path = path49 && path49 !== "/" ? path49 : void 0;
|
|
7537
7537
|
wsComponent.query = query;
|
|
7538
7538
|
wsComponent.resourceName = void 0;
|
|
7539
7539
|
}
|
|
@@ -10895,12 +10895,12 @@ var require_dist = __commonJS({
|
|
|
10895
10895
|
throw new Error(`Unknown format "${name}"`);
|
|
10896
10896
|
return f;
|
|
10897
10897
|
};
|
|
10898
|
-
function addFormats(ajv, list,
|
|
10898
|
+
function addFormats(ajv, list, fs49, exportName) {
|
|
10899
10899
|
var _a3;
|
|
10900
10900
|
var _b;
|
|
10901
10901
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
10902
10902
|
for (const f of list)
|
|
10903
|
-
ajv.addFormat(f,
|
|
10903
|
+
ajv.addFormat(f, fs49[f]);
|
|
10904
10904
|
}
|
|
10905
10905
|
module.exports = exports = formatsPlugin;
|
|
10906
10906
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -11008,7 +11008,7 @@ import YAML from "yaml";
|
|
|
11008
11008
|
function bootstrapStepCmd(entry) {
|
|
11009
11009
|
return typeof entry === "string" ? entry : entry.cmd;
|
|
11010
11010
|
}
|
|
11011
|
-
function refineForbiddenKeys(value,
|
|
11011
|
+
function refineForbiddenKeys(value, path49, ctx, rejectSource) {
|
|
11012
11012
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
11013
11013
|
return;
|
|
11014
11014
|
}
|
|
@@ -11016,12 +11016,12 @@ function refineForbiddenKeys(value, path48, ctx, rejectSource) {
|
|
|
11016
11016
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
11017
11017
|
ctx.addIssue({
|
|
11018
11018
|
code: external_exports.ZodIssueCode.custom,
|
|
11019
|
-
path: [...
|
|
11019
|
+
path: [...path49, key],
|
|
11020
11020
|
message: `forbidden key "${key}" (prototype-pollution surface)`
|
|
11021
11021
|
});
|
|
11022
11022
|
continue;
|
|
11023
11023
|
}
|
|
11024
|
-
if (rejectSource &&
|
|
11024
|
+
if (rejectSource && path49.length === 0 && key === "source") {
|
|
11025
11025
|
ctx.addIssue({
|
|
11026
11026
|
code: external_exports.ZodIssueCode.custom,
|
|
11027
11027
|
path: ["source"],
|
|
@@ -11029,21 +11029,21 @@ function refineForbiddenKeys(value, path48, ctx, rejectSource) {
|
|
|
11029
11029
|
});
|
|
11030
11030
|
continue;
|
|
11031
11031
|
}
|
|
11032
|
-
refineForbiddenKeys(value[key], [...
|
|
11032
|
+
refineForbiddenKeys(value[key], [...path49, key], ctx, false);
|
|
11033
11033
|
}
|
|
11034
11034
|
}
|
|
11035
|
-
function rejectForbiddenKeys(value,
|
|
11035
|
+
function rejectForbiddenKeys(value, path49, rejectSource) {
|
|
11036
11036
|
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
11037
11037
|
return;
|
|
11038
11038
|
}
|
|
11039
11039
|
for (const key of Object.keys(value)) {
|
|
11040
11040
|
if (FORBIDDEN_KEYS.has(key)) {
|
|
11041
|
-
throw new Error(`[manifest] ${
|
|
11041
|
+
throw new Error(`[manifest] ${path49}: forbidden key "${key}" (prototype-pollution surface)`);
|
|
11042
11042
|
}
|
|
11043
11043
|
if (rejectSource && key === "source") {
|
|
11044
|
-
throw new Error(`[manifest] ${
|
|
11044
|
+
throw new Error(`[manifest] ${path49}: top-level "source" is loader-stamped \u2014 manifests must not author it`);
|
|
11045
11045
|
}
|
|
11046
|
-
rejectForbiddenKeys(value[key], `${
|
|
11046
|
+
rejectForbiddenKeys(value[key], `${path49}.${key}`, false);
|
|
11047
11047
|
}
|
|
11048
11048
|
}
|
|
11049
11049
|
function unknownTopLevelKeys(parsed) {
|
|
@@ -11895,7 +11895,7 @@ var init_loader = __esm({
|
|
|
11895
11895
|
});
|
|
11896
11896
|
|
|
11897
11897
|
// ../core/dist/skill-sources/schema.js
|
|
11898
|
-
var SKILL_SOURCE_ID_LENGTH, NAME_PATTERN, URL_PATTERN, SkillSourceSchema;
|
|
11898
|
+
var SKILL_SOURCE_ID_LENGTH, NAME_PATTERN, URL_PATTERN, PREFIX_PATTERN, SkillSourceSchema;
|
|
11899
11899
|
var init_schema3 = __esm({
|
|
11900
11900
|
"../core/dist/skill-sources/schema.js"() {
|
|
11901
11901
|
"use strict";
|
|
@@ -11903,13 +11903,24 @@ var init_schema3 = __esm({
|
|
|
11903
11903
|
SKILL_SOURCE_ID_LENGTH = 12;
|
|
11904
11904
|
NAME_PATTERN = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
|
|
11905
11905
|
URL_PATTERN = /^(?:https?:\/\/|git@|ssh:\/\/|file:\/\/|\/).+/;
|
|
11906
|
+
PREFIX_PATTERN = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
11906
11907
|
SkillSourceSchema = external_exports.object({
|
|
11907
11908
|
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"),
|
|
11908
11909
|
name: external_exports.string().regex(NAME_PATTERN, "skill-source name must be ASCII lowercase + digits + dash (1-64 chars, no leading/trailing dash)"),
|
|
11909
11910
|
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)"),
|
|
11910
11911
|
branch: external_exports.string().min(1, "branch must not be empty").default("main"),
|
|
11911
11912
|
addedAt: external_exports.number().int().nonnegative(),
|
|
11912
|
-
lastPulledSha: external_exports.string().regex(/^[a-f0-9]{40}$/, "lastPulledSha must be a 40-char lowercase hex git SHA").optional()
|
|
11913
|
+
lastPulledSha: external_exports.string().regex(/^[a-f0-9]{40}$/, "lastPulledSha must be a 40-char lowercase hex git SHA").optional(),
|
|
11914
|
+
/**
|
|
11915
|
+
* Optional rename prefix. When set, skills+agents from this source are
|
|
11916
|
+
* deployed under `<prefix>:<canonical-name>` (both filename + frontmatter
|
|
11917
|
+
* `name:` rewritten). Source clone + atlas-toolbox member overlays remain
|
|
11918
|
+
* canonical-named on disk; the rename is purely a deploy-time view.
|
|
11919
|
+
* Operator overlay files (`~/.claude/{skills,agents}.overrides/`) MUST
|
|
11920
|
+
* use canonical names; `olam flywheel migrate-overlays --push` enforces
|
|
11921
|
+
* this via the reverse validator.
|
|
11922
|
+
*/
|
|
11923
|
+
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()
|
|
11913
11924
|
});
|
|
11914
11925
|
}
|
|
11915
11926
|
});
|
|
@@ -12437,7 +12448,8 @@ var init_trust_audit_log = __esm({
|
|
|
12437
12448
|
"removed",
|
|
12438
12449
|
"meta-hook-stripped",
|
|
12439
12450
|
"setup-skill-source-picked",
|
|
12440
|
-
"setup-project-sweep-completed"
|
|
12451
|
+
"setup-project-sweep-completed",
|
|
12452
|
+
"prefix-collision"
|
|
12441
12453
|
]);
|
|
12442
12454
|
TrustMethodSchema = external_exports.enum(["flag", "interactive", "auto-reject-tty", "none"]);
|
|
12443
12455
|
TrustAuditEntrySchema = external_exports.object({
|
|
@@ -12550,24 +12562,49 @@ function updateSkillSource(id, patch) {
|
|
|
12550
12562
|
throw new Error(`skill-source name "${patch.name}" already in use by id "${collision.id}".`);
|
|
12551
12563
|
}
|
|
12552
12564
|
}
|
|
12565
|
+
if (patch.prefix !== void 0 && patch.prefix !== null) {
|
|
12566
|
+
if (!PREFIX_PATTERN2.test(patch.prefix)) {
|
|
12567
|
+
throw new Error(`prefix must match /^[a-z0-9][a-z0-9_-]{0,38}$/ \u2014 got "${patch.prefix}"`);
|
|
12568
|
+
}
|
|
12569
|
+
}
|
|
12553
12570
|
const existing = config2.skillSources[idx];
|
|
12571
|
+
let prefixUpdate = {};
|
|
12572
|
+
if (patch.prefix === null) {
|
|
12573
|
+
const { prefix: _dropped, ...rest } = existing;
|
|
12574
|
+
void _dropped;
|
|
12575
|
+
const updated2 = {
|
|
12576
|
+
...rest,
|
|
12577
|
+
...patch.name !== void 0 ? { name: patch.name } : {},
|
|
12578
|
+
...patch.branch !== void 0 ? { branch: patch.branch } : {},
|
|
12579
|
+
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
12580
|
+
};
|
|
12581
|
+
const next2 = [...config2.skillSources];
|
|
12582
|
+
next2[idx] = updated2;
|
|
12583
|
+
writeGlobalConfig({ ...config2, skillSources: next2 });
|
|
12584
|
+
return updated2;
|
|
12585
|
+
} else if (patch.prefix !== void 0) {
|
|
12586
|
+
prefixUpdate = { prefix: patch.prefix };
|
|
12587
|
+
}
|
|
12554
12588
|
const updated = {
|
|
12555
12589
|
...existing,
|
|
12556
12590
|
...patch.name !== void 0 ? { name: patch.name } : {},
|
|
12557
12591
|
...patch.branch !== void 0 ? { branch: patch.branch } : {},
|
|
12558
|
-
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {}
|
|
12592
|
+
...patch.lastPulledSha !== void 0 ? { lastPulledSha: patch.lastPulledSha } : {},
|
|
12593
|
+
...prefixUpdate
|
|
12559
12594
|
};
|
|
12560
12595
|
const next = [...config2.skillSources];
|
|
12561
12596
|
next[idx] = updated;
|
|
12562
12597
|
writeGlobalConfig({ ...config2, skillSources: next });
|
|
12563
12598
|
return updated;
|
|
12564
12599
|
}
|
|
12600
|
+
var PREFIX_PATTERN2;
|
|
12565
12601
|
var init_store2 = __esm({
|
|
12566
12602
|
"../core/dist/skill-sources/store.js"() {
|
|
12567
12603
|
"use strict";
|
|
12568
12604
|
init_store();
|
|
12569
12605
|
init_schema3();
|
|
12570
12606
|
init_trust_audit_log();
|
|
12607
|
+
PREFIX_PATTERN2 = /^[a-z0-9][a-z0-9_-]{0,38}$/;
|
|
12571
12608
|
}
|
|
12572
12609
|
});
|
|
12573
12610
|
|
|
@@ -14865,17 +14902,154 @@ var init_managed_merge = __esm({
|
|
|
14865
14902
|
}
|
|
14866
14903
|
});
|
|
14867
14904
|
|
|
14868
|
-
// ../core/dist/skill-sync/
|
|
14905
|
+
// ../core/dist/skill-sync/prefix-rules.js
|
|
14906
|
+
function applyPrefix(name, prefix, otherKnownPrefixes = []) {
|
|
14907
|
+
if (prefix.length === 0) {
|
|
14908
|
+
throw new Error("applyPrefix: prefix must be non-empty");
|
|
14909
|
+
}
|
|
14910
|
+
if (prefix.includes(":")) {
|
|
14911
|
+
throw new Error(`applyPrefix: prefix must not contain ':' (got "${prefix}")`);
|
|
14912
|
+
}
|
|
14913
|
+
if (name.startsWith(`${prefix}:`))
|
|
14914
|
+
return name;
|
|
14915
|
+
for (const other of otherKnownPrefixes) {
|
|
14916
|
+
if (other.length > 0 && name.startsWith(`${other}:`))
|
|
14917
|
+
return name;
|
|
14918
|
+
}
|
|
14919
|
+
return `${prefix}:${name}`;
|
|
14920
|
+
}
|
|
14921
|
+
function rewriteFrontmatterName(content, rewriter) {
|
|
14922
|
+
const text = content.toString("utf-8");
|
|
14923
|
+
const parsed = parseFrontmatter(text);
|
|
14924
|
+
if (Object.keys(parsed.fm).length === 0)
|
|
14925
|
+
return content;
|
|
14926
|
+
const currentName = parsed.fm["name"];
|
|
14927
|
+
if (currentName === void 0)
|
|
14928
|
+
return content;
|
|
14929
|
+
const newName = rewriter(currentName);
|
|
14930
|
+
if (newName === currentName)
|
|
14931
|
+
return content;
|
|
14932
|
+
const nextFm = { ...parsed.fm, name: newName };
|
|
14933
|
+
const rebuilt = serializeFrontmatter(nextFm) + parsed.body;
|
|
14934
|
+
return Buffer.from(rebuilt, "utf-8");
|
|
14935
|
+
}
|
|
14936
|
+
var init_prefix_rules = __esm({
|
|
14937
|
+
"../core/dist/skill-sync/prefix-rules.js"() {
|
|
14938
|
+
"use strict";
|
|
14939
|
+
init_markdown_merger();
|
|
14940
|
+
}
|
|
14941
|
+
});
|
|
14942
|
+
|
|
14943
|
+
// ../core/dist/skill-sync/prefix-deploy.js
|
|
14869
14944
|
import * as fs30 from "node:fs";
|
|
14870
|
-
import * as os18 from "node:os";
|
|
14871
14945
|
import * as path29 from "node:path";
|
|
14946
|
+
function buildSourcePrefixMap(sources) {
|
|
14947
|
+
const byId = /* @__PURE__ */ new Map();
|
|
14948
|
+
const prefixes = /* @__PURE__ */ new Set();
|
|
14949
|
+
for (const s of sources) {
|
|
14950
|
+
if (s.prefix !== void 0 && s.prefix.length > 0) {
|
|
14951
|
+
byId.set(s.id, s.prefix);
|
|
14952
|
+
prefixes.add(s.prefix);
|
|
14953
|
+
}
|
|
14954
|
+
}
|
|
14955
|
+
return {
|
|
14956
|
+
get: (sourceId) => byId.get(sourceId),
|
|
14957
|
+
registeredPrefixes: Array.from(prefixes)
|
|
14958
|
+
};
|
|
14959
|
+
}
|
|
14960
|
+
function applyPrefixRewrites(baseArtifacts, sourceMap, claudeDir2, dryRun) {
|
|
14961
|
+
const result = { rewrittenCount: 0, entries: [] };
|
|
14962
|
+
for (const artifact of baseArtifacts) {
|
|
14963
|
+
if (artifact.kind !== "skill" && artifact.kind !== "agent")
|
|
14964
|
+
continue;
|
|
14965
|
+
const prefix = sourceMap.get(artifact.sourceId);
|
|
14966
|
+
if (prefix === void 0)
|
|
14967
|
+
continue;
|
|
14968
|
+
const canonical = artifact.deployBasename;
|
|
14969
|
+
const otherPrefixes = sourceMap.registeredPrefixes.filter((p) => p !== prefix);
|
|
14970
|
+
const renamed = applyPrefix(canonical, prefix, otherPrefixes);
|
|
14971
|
+
if (renamed === canonical)
|
|
14972
|
+
continue;
|
|
14973
|
+
const renamedFrontmatterName = renamed.replace(/\.md$/, "");
|
|
14974
|
+
if (dryRun) {
|
|
14975
|
+
artifact.deployBasename = renamed;
|
|
14976
|
+
result.rewrittenCount += 1;
|
|
14977
|
+
result.entries.push({
|
|
14978
|
+
sourceId: artifact.sourceId,
|
|
14979
|
+
kind: artifact.kind,
|
|
14980
|
+
canonicalBasename: canonical,
|
|
14981
|
+
renamedBasename: renamed,
|
|
14982
|
+
prefix
|
|
14983
|
+
});
|
|
14984
|
+
continue;
|
|
14985
|
+
}
|
|
14986
|
+
if (artifact.kind === "skill") {
|
|
14987
|
+
const skillMdPath = path29.join(artifact.sourcePath, "SKILL.md");
|
|
14988
|
+
const content = fs30.readFileSync(skillMdPath);
|
|
14989
|
+
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
14990
|
+
const managedDir = materializeMergedSkill({
|
|
14991
|
+
sourceId: artifact.sourceId,
|
|
14992
|
+
sourcePath: artifact.sourcePath,
|
|
14993
|
+
deployBasename: renamed,
|
|
14994
|
+
mergedContent: rewritten,
|
|
14995
|
+
claudeDir: claudeDir2
|
|
14996
|
+
});
|
|
14997
|
+
artifact.sourcePath = managedDir;
|
|
14998
|
+
artifact.deployBasename = renamed;
|
|
14999
|
+
} else {
|
|
15000
|
+
const content = artifact.resolvedContent !== void 0 ? artifact.resolvedContent : fs30.readFileSync(artifact.sourcePath);
|
|
15001
|
+
const rewritten = rewriteFrontmatterName(content, () => renamedFrontmatterName);
|
|
15002
|
+
artifact.resolvedContent = rewritten;
|
|
15003
|
+
artifact.deployBasename = renamed;
|
|
15004
|
+
}
|
|
15005
|
+
result.rewrittenCount += 1;
|
|
15006
|
+
result.entries.push({
|
|
15007
|
+
sourceId: artifact.sourceId,
|
|
15008
|
+
kind: artifact.kind,
|
|
15009
|
+
canonicalBasename: canonical,
|
|
15010
|
+
renamedBasename: renamed,
|
|
15011
|
+
prefix
|
|
15012
|
+
});
|
|
15013
|
+
}
|
|
15014
|
+
return result;
|
|
15015
|
+
}
|
|
15016
|
+
function detectPrefixCollisions(sources) {
|
|
15017
|
+
const byPrefix = /* @__PURE__ */ new Map();
|
|
15018
|
+
for (const s of sources) {
|
|
15019
|
+
if (s.prefix === void 0 || s.prefix.length === 0)
|
|
15020
|
+
continue;
|
|
15021
|
+
const ids = byPrefix.get(s.prefix) ?? [];
|
|
15022
|
+
ids.push(s.id);
|
|
15023
|
+
byPrefix.set(s.prefix, ids);
|
|
15024
|
+
}
|
|
15025
|
+
const collisions = [];
|
|
15026
|
+
for (const [prefix, ids] of byPrefix.entries()) {
|
|
15027
|
+
if (ids.length < 2)
|
|
15028
|
+
continue;
|
|
15029
|
+
const [winner, ...losers] = ids;
|
|
15030
|
+
collisions.push({ prefix, winnerSourceId: winner, loserSourceIds: losers });
|
|
15031
|
+
}
|
|
15032
|
+
return collisions;
|
|
15033
|
+
}
|
|
15034
|
+
var init_prefix_deploy = __esm({
|
|
15035
|
+
"../core/dist/skill-sync/prefix-deploy.js"() {
|
|
15036
|
+
"use strict";
|
|
15037
|
+
init_prefix_rules();
|
|
15038
|
+
init_managed_merge();
|
|
15039
|
+
}
|
|
15040
|
+
});
|
|
15041
|
+
|
|
15042
|
+
// ../core/dist/skill-sync/engine.js
|
|
15043
|
+
import * as fs31 from "node:fs";
|
|
15044
|
+
import * as os18 from "node:os";
|
|
15045
|
+
import * as path30 from "node:path";
|
|
14872
15046
|
function resolveAtlasUser(override) {
|
|
14873
15047
|
if (override)
|
|
14874
15048
|
return override;
|
|
14875
|
-
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] ||
|
|
14876
|
-
const f =
|
|
14877
|
-
if (
|
|
14878
|
-
return
|
|
15049
|
+
const claudeDir2 = process.env["OLAM_CLAUDE_DIR"] || path30.join(os18.homedir(), ".claude");
|
|
15050
|
+
const f = path30.join(claudeDir2, ".atlas-user");
|
|
15051
|
+
if (fs31.existsSync(f)) {
|
|
15052
|
+
return fs31.readFileSync(f, "utf-8").trim() || void 0;
|
|
14879
15053
|
}
|
|
14880
15054
|
return void 0;
|
|
14881
15055
|
}
|
|
@@ -14887,7 +15061,7 @@ async function syncSkills(opts = {}) {
|
|
|
14887
15061
|
const perSource = [];
|
|
14888
15062
|
for (const source of sources) {
|
|
14889
15063
|
const clonePath = skillSourceClonePath(source.id);
|
|
14890
|
-
if (!
|
|
15064
|
+
if (!fs31.existsSync(clonePath))
|
|
14891
15065
|
continue;
|
|
14892
15066
|
const { artifacts, subscription } = await withFileLock(clonePath, () => {
|
|
14893
15067
|
const pinRef = projectOverride?.override.pin?.[source.id];
|
|
@@ -14925,9 +15099,15 @@ async function syncSkills(opts = {}) {
|
|
|
14925
15099
|
const memberOverlaysEnabled = process.env["OLAM_MEMBER_OVERLAYS"] === "1";
|
|
14926
15100
|
const baseArtifacts = projectFilteredArtifacts.filter((a) => a.kind !== "overlay");
|
|
14927
15101
|
const overlayArtifacts = memberOverlaysEnabled ? projectFilteredArtifacts.filter((a) => a.kind === "overlay") : [];
|
|
14928
|
-
|
|
15102
|
+
const sourcePrefixMap = buildSourcePrefixMap(sources);
|
|
15103
|
+
const hasPrefixRewrites = sources.some((s) => s.prefix !== void 0 && s.prefix.length > 0);
|
|
15104
|
+
const willMutateManagedDir = !opts.dryRun && (memberOverlaysEnabled && overlayArtifacts.length > 0 || hasPrefixRewrites);
|
|
15105
|
+
if (willMutateManagedDir) {
|
|
14929
15106
|
const claude = claudeDir();
|
|
14930
15107
|
cleanMergedDir(claude);
|
|
15108
|
+
}
|
|
15109
|
+
if (memberOverlaysEnabled && overlayArtifacts.length > 0 && !opts.dryRun) {
|
|
15110
|
+
const claude = claudeDir();
|
|
14931
15111
|
for (const overlay of overlayArtifacts) {
|
|
14932
15112
|
if (!overlay.targetKind)
|
|
14933
15113
|
continue;
|
|
@@ -14937,13 +15117,13 @@ async function syncSkills(opts = {}) {
|
|
|
14937
15117
|
let baseContent;
|
|
14938
15118
|
let basePath;
|
|
14939
15119
|
if (overlay.targetKind === "skill") {
|
|
14940
|
-
basePath =
|
|
14941
|
-
baseContent =
|
|
15120
|
+
basePath = path30.join(base.sourcePath, "SKILL.md");
|
|
15121
|
+
baseContent = fs31.readFileSync(basePath, "utf-8");
|
|
14942
15122
|
} else {
|
|
14943
15123
|
basePath = base.sourcePath;
|
|
14944
|
-
baseContent =
|
|
15124
|
+
baseContent = fs31.readFileSync(basePath, "utf-8");
|
|
14945
15125
|
}
|
|
14946
|
-
const overlayContent =
|
|
15126
|
+
const overlayContent = fs31.readFileSync(overlay.sourcePath, "utf-8");
|
|
14947
15127
|
const label = `${overlay.sourceId}/${overlay.deployBasename}`;
|
|
14948
15128
|
const mergeResult = mergeMarkdown(baseContent, overlayContent, label, basePath, overlay.sourcePath);
|
|
14949
15129
|
if ("error" in mergeResult) {
|
|
@@ -14967,6 +15147,23 @@ async function syncSkills(opts = {}) {
|
|
|
14967
15147
|
}
|
|
14968
15148
|
const hookFiles = projectFilteredArtifacts.filter((a) => a.kind === "hook").map((a) => a.sourcePath);
|
|
14969
15149
|
const permissionFiles = projectFilteredArtifacts.filter((a) => a.kind === "permission").map((a) => a.sourcePath);
|
|
15150
|
+
const claudeDirForRewrites = claudeDir();
|
|
15151
|
+
const prefixRewriteResult = applyPrefixRewrites(baseArtifacts, sourcePrefixMap, claudeDirForRewrites, opts.dryRun === true);
|
|
15152
|
+
const prefixCollisions = detectPrefixCollisions(sources);
|
|
15153
|
+
if (!opts.dryRun) {
|
|
15154
|
+
for (const collision of prefixCollisions) {
|
|
15155
|
+
try {
|
|
15156
|
+
appendTrustAudit({
|
|
15157
|
+
gitUrl: "internal:prefix-collision",
|
|
15158
|
+
action: "prefix-collision",
|
|
15159
|
+
trustMethod: "none",
|
|
15160
|
+
sourceId: collision.winnerSourceId,
|
|
15161
|
+
note: `prefix="${collision.prefix}"; winner=${collision.winnerSourceId}; losers=${collision.loserSourceIds.join(",")}`
|
|
15162
|
+
});
|
|
15163
|
+
} catch {
|
|
15164
|
+
}
|
|
15165
|
+
}
|
|
15166
|
+
}
|
|
14970
15167
|
const summary = {
|
|
14971
15168
|
sourceCount: sources.length,
|
|
14972
15169
|
artifactCount: projectFilteredArtifacts.length,
|
|
@@ -14977,13 +15174,15 @@ async function syncSkills(opts = {}) {
|
|
|
14977
15174
|
deploy: void 0,
|
|
14978
15175
|
merge: void 0,
|
|
14979
15176
|
metaHooks: void 0,
|
|
14980
|
-
perSource
|
|
15177
|
+
perSource,
|
|
15178
|
+
prefixRewrites: prefixRewriteResult.entries,
|
|
15179
|
+
prefixCollisions
|
|
14981
15180
|
};
|
|
14982
15181
|
if (opts.dryRun) {
|
|
14983
15182
|
summary.collisions = detectCollisions(baseArtifacts).collisions;
|
|
14984
15183
|
return summary;
|
|
14985
15184
|
}
|
|
14986
|
-
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] ||
|
|
15185
|
+
const claudeDirPath = process.env["OLAM_CLAUDE_DIR"] || path30.join(os18.homedir(), ".claude");
|
|
14987
15186
|
const overlayReferences = scanOverlayReferences(claudeDirPath, SHIM_TARGETS.map((t) => t.basename));
|
|
14988
15187
|
summary.deploy = deployArtifacts(baseArtifacts, {
|
|
14989
15188
|
installedOlamVersion,
|
|
@@ -15009,19 +15208,19 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
15009
15208
|
const result = await withSettingsJsonLock(() => {
|
|
15010
15209
|
let currentSettings = {};
|
|
15011
15210
|
let settingsExisted = false;
|
|
15012
|
-
if (
|
|
15211
|
+
if (fs31.existsSync(settingsFile)) {
|
|
15013
15212
|
settingsExisted = true;
|
|
15014
15213
|
try {
|
|
15015
|
-
const raw =
|
|
15214
|
+
const raw = fs31.readFileSync(settingsFile, "utf-8");
|
|
15016
15215
|
currentSettings = raw.trim() ? JSON.parse(raw) : {};
|
|
15017
15216
|
} catch {
|
|
15018
15217
|
try {
|
|
15019
|
-
const raw =
|
|
15020
|
-
const bakDir =
|
|
15021
|
-
|
|
15218
|
+
const raw = fs31.readFileSync(settingsFile);
|
|
15219
|
+
const bakDir = path30.join(path30.dirname(settingsFile), ".malformed-backups");
|
|
15220
|
+
fs31.mkdirSync(bakDir, { recursive: true });
|
|
15022
15221
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
15023
|
-
const bakFile =
|
|
15024
|
-
|
|
15222
|
+
const bakFile = path30.join(bakDir, `settings.json.malformed.${stamp}.bak`);
|
|
15223
|
+
fs31.writeFileSync(bakFile, raw, { mode: 384 });
|
|
15025
15224
|
snapshotError = `settings.json was malformed; original bytes preserved at ${bakFile}`;
|
|
15026
15225
|
} catch (bakErr) {
|
|
15027
15226
|
snapshotError = `settings.json malformed AND .bak write failed: ${bakErr instanceof Error ? bakErr.message : String(bakErr)}`;
|
|
@@ -15071,10 +15270,10 @@ async function injectMetaHooksIntoSettings(opts) {
|
|
|
15071
15270
|
} catch {
|
|
15072
15271
|
}
|
|
15073
15272
|
}
|
|
15074
|
-
|
|
15273
|
+
fs31.mkdirSync(path30.dirname(settingsFile), { recursive: true });
|
|
15075
15274
|
const tmpPath = `${settingsFile}.tmp-${process.pid}-${Date.now()}`;
|
|
15076
|
-
|
|
15077
|
-
|
|
15275
|
+
fs31.writeFileSync(tmpPath, JSON.stringify(inject.nextSettings, null, 2) + "\n");
|
|
15276
|
+
fs31.renameSync(tmpPath, settingsFile);
|
|
15078
15277
|
return inject;
|
|
15079
15278
|
}, { reason: `syncSkills meta-hook injection (mode=${mode})` });
|
|
15080
15279
|
return {
|
|
@@ -15108,23 +15307,24 @@ var init_engine = __esm({
|
|
|
15108
15307
|
init_meta_hook_injector();
|
|
15109
15308
|
init_markdown_merger();
|
|
15110
15309
|
init_managed_merge();
|
|
15310
|
+
init_prefix_deploy();
|
|
15111
15311
|
}
|
|
15112
15312
|
});
|
|
15113
15313
|
|
|
15114
15314
|
// ../core/dist/skill-sync/shadow-backup-manager.js
|
|
15115
|
-
import * as
|
|
15116
|
-
import * as
|
|
15315
|
+
import * as fs32 from "node:fs";
|
|
15316
|
+
import * as path31 from "node:path";
|
|
15117
15317
|
function listShadowBackups(opts = {}) {
|
|
15118
15318
|
const claude = opts.claudeDirOverride ?? claudeDir();
|
|
15119
15319
|
const now = opts.now ?? Date.now();
|
|
15120
15320
|
const out = [];
|
|
15121
15321
|
for (const bucket of SHADOW_BACKUP_BUCKETS) {
|
|
15122
|
-
const bucketDir =
|
|
15123
|
-
if (!
|
|
15322
|
+
const bucketDir = path31.join(claude, bucket);
|
|
15323
|
+
if (!fs32.existsSync(bucketDir))
|
|
15124
15324
|
continue;
|
|
15125
15325
|
let entries;
|
|
15126
15326
|
try {
|
|
15127
|
-
entries =
|
|
15327
|
+
entries = fs32.readdirSync(bucketDir);
|
|
15128
15328
|
} catch {
|
|
15129
15329
|
continue;
|
|
15130
15330
|
}
|
|
@@ -15135,10 +15335,10 @@ function listShadowBackups(opts = {}) {
|
|
|
15135
15335
|
const epochSeconds = Number.parseInt(match[1], 10);
|
|
15136
15336
|
if (!Number.isFinite(epochSeconds) || epochSeconds < 0)
|
|
15137
15337
|
continue;
|
|
15138
|
-
const full =
|
|
15338
|
+
const full = path31.join(bucketDir, name);
|
|
15139
15339
|
let sizeBytes = 0;
|
|
15140
15340
|
try {
|
|
15141
|
-
const st =
|
|
15341
|
+
const st = fs32.statSync(full);
|
|
15142
15342
|
if (st.isDirectory())
|
|
15143
15343
|
continue;
|
|
15144
15344
|
sizeBytes = st.size;
|
|
@@ -15151,7 +15351,7 @@ function listShadowBackups(opts = {}) {
|
|
|
15151
15351
|
bucket,
|
|
15152
15352
|
basename: name,
|
|
15153
15353
|
originalBasename,
|
|
15154
|
-
originalPath:
|
|
15354
|
+
originalPath: path31.join(bucketDir, originalBasename),
|
|
15155
15355
|
epochSeconds,
|
|
15156
15356
|
ageMs: now - epochSeconds * 1e3,
|
|
15157
15357
|
sizeBytes
|
|
@@ -15194,7 +15394,7 @@ function pruneShadowBackups(opts) {
|
|
|
15194
15394
|
}
|
|
15195
15395
|
if (!opts.dryRun) {
|
|
15196
15396
|
try {
|
|
15197
|
-
|
|
15397
|
+
fs32.unlinkSync(b.path);
|
|
15198
15398
|
} catch {
|
|
15199
15399
|
skipped.push(b);
|
|
15200
15400
|
continue;
|
|
@@ -15205,24 +15405,24 @@ function pruneShadowBackups(opts) {
|
|
|
15205
15405
|
return { deleted, skipped };
|
|
15206
15406
|
}
|
|
15207
15407
|
function restoreShadowBackup(opts) {
|
|
15208
|
-
const abs =
|
|
15209
|
-
if (!
|
|
15408
|
+
const abs = path31.resolve(opts.backupPath);
|
|
15409
|
+
if (!fs32.existsSync(abs)) {
|
|
15210
15410
|
throw new Error(`backup file not found: ${abs}`);
|
|
15211
15411
|
}
|
|
15212
|
-
const basename6 =
|
|
15412
|
+
const basename6 = path31.basename(abs);
|
|
15213
15413
|
const match = SHADOW_BACKUP_SUFFIX_RE.exec(basename6);
|
|
15214
15414
|
if (!match) {
|
|
15215
15415
|
throw new Error(`not a shadow-backup file (basename "${basename6}" does not match \`.shadow-backup-<epoch>\`): ${abs}`);
|
|
15216
15416
|
}
|
|
15217
15417
|
const originalBasename = basename6.slice(0, basename6.length - match[0].length);
|
|
15218
|
-
const originalPath =
|
|
15219
|
-
if (
|
|
15418
|
+
const originalPath = path31.join(path31.dirname(abs), originalBasename);
|
|
15419
|
+
if (fs32.existsSync(originalPath) && !opts.force) {
|
|
15220
15420
|
throw new Error(`original path already occupied: ${originalPath}. Move/rename it first OR re-run with --force.`);
|
|
15221
15421
|
}
|
|
15222
|
-
if (opts.force &&
|
|
15223
|
-
|
|
15422
|
+
if (opts.force && fs32.existsSync(originalPath)) {
|
|
15423
|
+
fs32.unlinkSync(originalPath);
|
|
15224
15424
|
}
|
|
15225
|
-
|
|
15425
|
+
fs32.renameSync(abs, originalPath);
|
|
15226
15426
|
return { restoredTo: originalPath };
|
|
15227
15427
|
}
|
|
15228
15428
|
var SHADOW_BACKUP_BUCKETS, SHADOW_BACKUP_SUFFIX_RE;
|
|
@@ -15236,14 +15436,14 @@ var init_shadow_backup_manager = __esm({
|
|
|
15236
15436
|
});
|
|
15237
15437
|
|
|
15238
15438
|
// ../core/dist/skill-sources/doctor-checks.js
|
|
15239
|
-
import * as
|
|
15240
|
-
import * as
|
|
15439
|
+
import * as fs33 from "node:fs";
|
|
15440
|
+
import * as path32 from "node:path";
|
|
15241
15441
|
import * as os19 from "node:os";
|
|
15242
15442
|
function claudeDirInternal3() {
|
|
15243
15443
|
const override = process.env["OLAM_CLAUDE_DIR"];
|
|
15244
15444
|
if (override && override.length > 0)
|
|
15245
15445
|
return override;
|
|
15246
|
-
return
|
|
15446
|
+
return path32.join(os19.homedir(), ".claude");
|
|
15247
15447
|
}
|
|
15248
15448
|
function checkStateFileParse() {
|
|
15249
15449
|
const filePath = globalConfigPath();
|
|
@@ -15252,11 +15452,11 @@ function checkStateFileParse() {
|
|
|
15252
15452
|
healthy: true,
|
|
15253
15453
|
description: `~/.olam state file (${filePath})`
|
|
15254
15454
|
};
|
|
15255
|
-
if (!
|
|
15455
|
+
if (!fs33.existsSync(filePath)) {
|
|
15256
15456
|
result.details = ["(file does not yet exist \u2014 will be created on first write)"];
|
|
15257
15457
|
return result;
|
|
15258
15458
|
}
|
|
15259
|
-
const raw =
|
|
15459
|
+
const raw = fs33.readFileSync(filePath, "utf-8");
|
|
15260
15460
|
let parsed;
|
|
15261
15461
|
try {
|
|
15262
15462
|
parsed = JSON.parse(raw);
|
|
@@ -15266,8 +15466,8 @@ function checkStateFileParse() {
|
|
|
15266
15466
|
result.details = [err instanceof Error ? err.message : String(err)];
|
|
15267
15467
|
result.repair = () => {
|
|
15268
15468
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
15269
|
-
|
|
15270
|
-
|
|
15469
|
+
fs33.renameSync(filePath, aside);
|
|
15470
|
+
fs33.writeFileSync(filePath, JSON.stringify({ schemaVersion: 1, repos: [], runbooks: [], skillSources: [] }, null, 2));
|
|
15271
15471
|
};
|
|
15272
15472
|
return result;
|
|
15273
15473
|
}
|
|
@@ -15278,7 +15478,7 @@ function checkStateFileParse() {
|
|
|
15278
15478
|
result.details = validation.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
|
|
15279
15479
|
result.repair = () => {
|
|
15280
15480
|
const aside = `${filePath}.corrupt-${Math.floor(Date.now() / 1e3)}`;
|
|
15281
|
-
|
|
15481
|
+
fs33.copyFileSync(filePath, aside);
|
|
15282
15482
|
const base = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
15283
15483
|
const next = {
|
|
15284
15484
|
...base,
|
|
@@ -15287,7 +15487,7 @@ function checkStateFileParse() {
|
|
|
15287
15487
|
runbooks: [],
|
|
15288
15488
|
skillSources: []
|
|
15289
15489
|
};
|
|
15290
|
-
|
|
15490
|
+
fs33.writeFileSync(filePath, JSON.stringify(next, null, 2));
|
|
15291
15491
|
};
|
|
15292
15492
|
return result;
|
|
15293
15493
|
}
|
|
@@ -15298,16 +15498,16 @@ function checkDanglingSymlinks() {
|
|
|
15298
15498
|
const buckets = ["commands", "agents", "skills", "scripts", "rules"];
|
|
15299
15499
|
const dangling = [];
|
|
15300
15500
|
for (const bucket of buckets) {
|
|
15301
|
-
const dir =
|
|
15302
|
-
if (!
|
|
15501
|
+
const dir = path32.join(claude, bucket);
|
|
15502
|
+
if (!fs33.existsSync(dir))
|
|
15303
15503
|
continue;
|
|
15304
|
-
for (const name of
|
|
15305
|
-
const linkPath =
|
|
15504
|
+
for (const name of fs33.readdirSync(dir)) {
|
|
15505
|
+
const linkPath = path32.join(dir, name);
|
|
15306
15506
|
try {
|
|
15307
|
-
const lst =
|
|
15507
|
+
const lst = fs33.lstatSync(linkPath);
|
|
15308
15508
|
if (!lst.isSymbolicLink())
|
|
15309
15509
|
continue;
|
|
15310
|
-
if (!
|
|
15510
|
+
if (!fs33.existsSync(linkPath)) {
|
|
15311
15511
|
dangling.push(linkPath);
|
|
15312
15512
|
}
|
|
15313
15513
|
} catch {
|
|
@@ -15325,7 +15525,7 @@ function checkDanglingSymlinks() {
|
|
|
15325
15525
|
result.repair = () => {
|
|
15326
15526
|
for (const p of dangling) {
|
|
15327
15527
|
try {
|
|
15328
|
-
|
|
15528
|
+
fs33.unlinkSync(p);
|
|
15329
15529
|
} catch {
|
|
15330
15530
|
}
|
|
15331
15531
|
}
|
|
@@ -15340,19 +15540,19 @@ function checkOrphanedSnapshots() {
|
|
|
15340
15540
|
healthy: true,
|
|
15341
15541
|
description: `orphaned migration snapshots under ${dir}`
|
|
15342
15542
|
};
|
|
15343
|
-
if (!
|
|
15543
|
+
if (!fs33.existsSync(dir)) {
|
|
15344
15544
|
return result;
|
|
15345
15545
|
}
|
|
15346
15546
|
const orphans = [];
|
|
15347
|
-
for (const name of
|
|
15547
|
+
for (const name of fs33.readdirSync(dir)) {
|
|
15348
15548
|
if (!name.endsWith(".json"))
|
|
15349
15549
|
continue;
|
|
15350
|
-
const full =
|
|
15550
|
+
const full = path32.join(dir, name);
|
|
15351
15551
|
try {
|
|
15352
|
-
const stat =
|
|
15552
|
+
const stat = fs33.statSync(full);
|
|
15353
15553
|
if (!stat.isFile())
|
|
15354
15554
|
continue;
|
|
15355
|
-
const raw =
|
|
15555
|
+
const raw = fs33.readFileSync(full, "utf-8");
|
|
15356
15556
|
let parsed;
|
|
15357
15557
|
try {
|
|
15358
15558
|
parsed = JSON.parse(raw);
|
|
@@ -15377,7 +15577,7 @@ function checkOrphanedSnapshots() {
|
|
|
15377
15577
|
result.repair = () => {
|
|
15378
15578
|
for (const o of orphans) {
|
|
15379
15579
|
try {
|
|
15380
|
-
|
|
15580
|
+
fs33.unlinkSync(o.path);
|
|
15381
15581
|
} catch {
|
|
15382
15582
|
}
|
|
15383
15583
|
}
|
|
@@ -15392,12 +15592,12 @@ function checkSentinelDrift() {
|
|
|
15392
15592
|
healthy: true,
|
|
15393
15593
|
description: `olam-skills sentinel block in ${filePath}`
|
|
15394
15594
|
};
|
|
15395
|
-
if (!
|
|
15595
|
+
if (!fs33.existsSync(filePath)) {
|
|
15396
15596
|
return result;
|
|
15397
15597
|
}
|
|
15398
15598
|
let parsed;
|
|
15399
15599
|
try {
|
|
15400
|
-
parsed = JSON.parse(
|
|
15600
|
+
parsed = JSON.parse(fs33.readFileSync(filePath, "utf-8"));
|
|
15401
15601
|
} catch {
|
|
15402
15602
|
return result;
|
|
15403
15603
|
}
|
|
@@ -15438,7 +15638,7 @@ function checkSentinelDrift() {
|
|
|
15438
15638
|
backupSettings();
|
|
15439
15639
|
} catch {
|
|
15440
15640
|
}
|
|
15441
|
-
const next = JSON.parse(
|
|
15641
|
+
const next = JSON.parse(fs33.readFileSync(filePath, "utf-8"));
|
|
15442
15642
|
if (!next.hooks)
|
|
15443
15643
|
return;
|
|
15444
15644
|
for (const stage of Object.keys(next.hooks)) {
|
|
@@ -15461,7 +15661,7 @@ function checkSentinelDrift() {
|
|
|
15461
15661
|
return bad === void 0;
|
|
15462
15662
|
});
|
|
15463
15663
|
}
|
|
15464
|
-
|
|
15664
|
+
fs33.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
15465
15665
|
};
|
|
15466
15666
|
}
|
|
15467
15667
|
return result;
|
|
@@ -15485,8 +15685,8 @@ function checkMemberNameMissing() {
|
|
|
15485
15685
|
return result;
|
|
15486
15686
|
}
|
|
15487
15687
|
const claudeDir2 = claudeDirInternal3();
|
|
15488
|
-
const atlasUserPath =
|
|
15489
|
-
const value =
|
|
15688
|
+
const atlasUserPath = path32.join(claudeDir2, ".atlas-user");
|
|
15689
|
+
const value = fs33.existsSync(atlasUserPath) ? fs33.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
15490
15690
|
if (value.length > 0) {
|
|
15491
15691
|
result.details = [`atlas-user: ${value}`];
|
|
15492
15692
|
return result;
|
|
@@ -15494,10 +15694,10 @@ function checkMemberNameMissing() {
|
|
|
15494
15694
|
result.healthy = false;
|
|
15495
15695
|
result.issue = "atlas-toolbox source registered but ~/.claude/.atlas-user not set";
|
|
15496
15696
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
15497
|
-
const membersDir =
|
|
15498
|
-
const existing =
|
|
15697
|
+
const membersDir = path32.join(clonePath, "members");
|
|
15698
|
+
const existing = fs33.existsSync(membersDir) ? fs33.readdirSync(membersDir).filter((e) => {
|
|
15499
15699
|
try {
|
|
15500
|
-
return
|
|
15700
|
+
return fs33.statSync(path32.join(membersDir, e)).isDirectory();
|
|
15501
15701
|
} catch {
|
|
15502
15702
|
return false;
|
|
15503
15703
|
}
|
|
@@ -15511,8 +15711,8 @@ function checkMemberNameMissing() {
|
|
|
15511
15711
|
}
|
|
15512
15712
|
function checkMemberOverlayDrift() {
|
|
15513
15713
|
const claudeDir2 = claudeDirInternal3();
|
|
15514
|
-
const atlasUserPath =
|
|
15515
|
-
const atlasUser =
|
|
15714
|
+
const atlasUserPath = path32.join(claudeDir2, ".atlas-user");
|
|
15715
|
+
const atlasUser = fs33.existsSync(atlasUserPath) ? fs33.readFileSync(atlasUserPath, "utf-8").trim() : "";
|
|
15516
15716
|
if (atlasUser.length === 0) {
|
|
15517
15717
|
return [];
|
|
15518
15718
|
}
|
|
@@ -15528,26 +15728,26 @@ function checkMemberOverlayDrift() {
|
|
|
15528
15728
|
const clonePath = skillSourceClonePath(atlasSource.id);
|
|
15529
15729
|
const results = [];
|
|
15530
15730
|
for (const kind of ["skills", "agents"]) {
|
|
15531
|
-
const localRoot =
|
|
15532
|
-
if (!
|
|
15731
|
+
const localRoot = path32.join(claudeDir2, `${kind}.overrides`);
|
|
15732
|
+
if (!fs33.existsSync(localRoot))
|
|
15533
15733
|
continue;
|
|
15534
15734
|
let entries;
|
|
15535
15735
|
try {
|
|
15536
|
-
entries =
|
|
15736
|
+
entries = fs33.readdirSync(localRoot);
|
|
15537
15737
|
} catch {
|
|
15538
15738
|
continue;
|
|
15539
15739
|
}
|
|
15540
15740
|
for (const entry of entries) {
|
|
15541
|
-
const localFile =
|
|
15741
|
+
const localFile = path32.join(localRoot, entry);
|
|
15542
15742
|
let stat;
|
|
15543
15743
|
try {
|
|
15544
|
-
stat =
|
|
15744
|
+
stat = fs33.statSync(localFile);
|
|
15545
15745
|
} catch {
|
|
15546
15746
|
continue;
|
|
15547
15747
|
}
|
|
15548
15748
|
if (!stat.isFile())
|
|
15549
15749
|
continue;
|
|
15550
|
-
const cloneFile =
|
|
15750
|
+
const cloneFile = path32.join(clonePath, "members", atlasUser, `${kind}.overrides`, entry);
|
|
15551
15751
|
const localSha = sha256OfPath(localFile);
|
|
15552
15752
|
const cloneSha = sha256OfPath(cloneFile);
|
|
15553
15753
|
if (localSha === cloneSha) {
|
|
@@ -15960,10 +16160,10 @@ function mergeDefs(...defs) {
|
|
|
15960
16160
|
function cloneDef(schema) {
|
|
15961
16161
|
return mergeDefs(schema._zod.def);
|
|
15962
16162
|
}
|
|
15963
|
-
function getElementAtPath(obj,
|
|
15964
|
-
if (!
|
|
16163
|
+
function getElementAtPath(obj, path49) {
|
|
16164
|
+
if (!path49)
|
|
15965
16165
|
return obj;
|
|
15966
|
-
return
|
|
16166
|
+
return path49.reduce((acc, key) => acc?.[key], obj);
|
|
15967
16167
|
}
|
|
15968
16168
|
function promiseAllObject(promisesObj) {
|
|
15969
16169
|
const keys = Object.keys(promisesObj);
|
|
@@ -16372,11 +16572,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
16372
16572
|
}
|
|
16373
16573
|
return false;
|
|
16374
16574
|
}
|
|
16375
|
-
function prefixIssues(
|
|
16575
|
+
function prefixIssues(path49, issues) {
|
|
16376
16576
|
return issues.map((iss) => {
|
|
16377
16577
|
var _a3;
|
|
16378
16578
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
16379
|
-
iss.path.unshift(
|
|
16579
|
+
iss.path.unshift(path49);
|
|
16380
16580
|
return iss;
|
|
16381
16581
|
});
|
|
16382
16582
|
}
|
|
@@ -16523,16 +16723,16 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
|
|
|
16523
16723
|
}
|
|
16524
16724
|
function formatError(error2, mapper = (issue2) => issue2.message) {
|
|
16525
16725
|
const fieldErrors = { _errors: [] };
|
|
16526
|
-
const processError = (error3,
|
|
16726
|
+
const processError = (error3, path49 = []) => {
|
|
16527
16727
|
for (const issue2 of error3.issues) {
|
|
16528
16728
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
16529
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
16729
|
+
issue2.errors.map((issues) => processError({ issues }, [...path49, ...issue2.path]));
|
|
16530
16730
|
} else if (issue2.code === "invalid_key") {
|
|
16531
|
-
processError({ issues: issue2.issues }, [...
|
|
16731
|
+
processError({ issues: issue2.issues }, [...path49, ...issue2.path]);
|
|
16532
16732
|
} else if (issue2.code === "invalid_element") {
|
|
16533
|
-
processError({ issues: issue2.issues }, [...
|
|
16733
|
+
processError({ issues: issue2.issues }, [...path49, ...issue2.path]);
|
|
16534
16734
|
} else {
|
|
16535
|
-
const fullpath = [...
|
|
16735
|
+
const fullpath = [...path49, ...issue2.path];
|
|
16536
16736
|
if (fullpath.length === 0) {
|
|
16537
16737
|
fieldErrors._errors.push(mapper(issue2));
|
|
16538
16738
|
} else {
|
|
@@ -27171,8 +27371,8 @@ var AuthClient = class {
|
|
|
27171
27371
|
throw new Error(`failed to report rate-limit for ${accountId} (HTTP ${res.status})`);
|
|
27172
27372
|
}
|
|
27173
27373
|
}
|
|
27174
|
-
async request(method,
|
|
27175
|
-
const url2 = `${this.baseUrl}${
|
|
27374
|
+
async request(method, path49, body, attempt = 0) {
|
|
27375
|
+
const url2 = `${this.baseUrl}${path49}`;
|
|
27176
27376
|
const controller = new AbortController();
|
|
27177
27377
|
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
27178
27378
|
const headers = {};
|
|
@@ -27190,7 +27390,7 @@ var AuthClient = class {
|
|
|
27190
27390
|
} catch (err) {
|
|
27191
27391
|
if (attempt < RETRY_COUNT && isTransient(err)) {
|
|
27192
27392
|
await sleep(RETRY_BACKOFF_MS * (attempt + 1));
|
|
27193
|
-
return this.request(method,
|
|
27393
|
+
return this.request(method, path49, body, attempt + 1);
|
|
27194
27394
|
}
|
|
27195
27395
|
throw err;
|
|
27196
27396
|
} finally {
|
|
@@ -28044,12 +28244,12 @@ function register3(server, _ctx, _initError) {
|
|
|
28044
28244
|
registry2.close();
|
|
28045
28245
|
}
|
|
28046
28246
|
try {
|
|
28047
|
-
const { default:
|
|
28247
|
+
const { default: fs49 } = await import("node:fs");
|
|
28048
28248
|
const { default: os28 } = await import("node:os");
|
|
28049
|
-
const { default:
|
|
28050
|
-
const tokenPath =
|
|
28051
|
-
if (
|
|
28052
|
-
const token =
|
|
28249
|
+
const { default: path49 } = await import("node:path");
|
|
28250
|
+
const tokenPath = path49.join(os28.homedir(), ".olam", "host-cp.token");
|
|
28251
|
+
if (fs49.existsSync(tokenPath)) {
|
|
28252
|
+
const token = fs49.readFileSync(tokenPath, "utf-8").trim();
|
|
28053
28253
|
await fetch("http://127.0.0.1:19000/api/admin/world-pr", {
|
|
28054
28254
|
method: "POST",
|
|
28055
28255
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${token}` },
|
|
@@ -28469,10 +28669,10 @@ function extractMcpConfig(claudeJsonPath) {
|
|
|
28469
28669
|
}
|
|
28470
28670
|
return { mcpServers, secrets };
|
|
28471
28671
|
}
|
|
28472
|
-
function readOptional(
|
|
28473
|
-
if (!existsSync6(
|
|
28672
|
+
function readOptional(path49) {
|
|
28673
|
+
if (!existsSync6(path49)) return null;
|
|
28474
28674
|
try {
|
|
28475
|
-
return readFileSync5(
|
|
28675
|
+
return readFileSync5(path49, "utf8");
|
|
28476
28676
|
} catch {
|
|
28477
28677
|
return null;
|
|
28478
28678
|
}
|
|
@@ -29918,8 +30118,8 @@ var CloudflareProvider = class extends ComputeProvider {
|
|
|
29918
30118
|
// -----------------------------------------------------------------------
|
|
29919
30119
|
// Internal fetch helper
|
|
29920
30120
|
// -----------------------------------------------------------------------
|
|
29921
|
-
async request(
|
|
29922
|
-
const url2 = `${this.config.workerUrl}${
|
|
30121
|
+
async request(path49, method, body) {
|
|
30122
|
+
const url2 = `${this.config.workerUrl}${path49}`;
|
|
29923
30123
|
const bearer = await this.config.mintToken();
|
|
29924
30124
|
const headers = {
|
|
29925
30125
|
Authorization: `Bearer ${bearer}`
|
|
@@ -32370,10 +32570,10 @@ async function writeManifest(args) {
|
|
|
32370
32570
|
capturedAt: args.capturedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
32371
32571
|
shots: entries
|
|
32372
32572
|
};
|
|
32373
|
-
const
|
|
32374
|
-
await writeFile(
|
|
32573
|
+
const path49 = join13(args.outDir, "manifest.json");
|
|
32574
|
+
await writeFile(path49, `${JSON.stringify(manifest, null, 2)}
|
|
32375
32575
|
`, "utf8");
|
|
32376
|
-
return { path:
|
|
32576
|
+
return { path: path49, manifest };
|
|
32377
32577
|
}
|
|
32378
32578
|
|
|
32379
32579
|
// ../mcp-server/src/tools/_capture/proxy.ts
|
|
@@ -32627,9 +32827,9 @@ async function startProxy(opts) {
|
|
|
32627
32827
|
const liveCompiled = verified.allowedPaths.map(compileGlob);
|
|
32628
32828
|
const target = parseRequestTarget(req);
|
|
32629
32829
|
if (!target) return httpReject(400, "invalid_target");
|
|
32630
|
-
const
|
|
32631
|
-
if (!liveCompiled.some((re) => re.test(
|
|
32632
|
-
return httpReject(403, "outside_allow_list", { path:
|
|
32830
|
+
const path49 = target.pathname;
|
|
32831
|
+
if (!liveCompiled.some((re) => re.test(path49))) {
|
|
32832
|
+
return httpReject(403, "outside_allow_list", { path: path49 });
|
|
32633
32833
|
}
|
|
32634
32834
|
const headerWorld = req.headers[WORLD_ASSERT_HEADER];
|
|
32635
32835
|
const headerWorldStr = typeof headerWorld === "string" ? headerWorld : Array.isArray(headerWorld) && headerWorld.length > 0 ? headerWorld[0] : void 0;
|
|
@@ -33408,14 +33608,14 @@ async function runShot(browser, shot, outDir, format, jpegQuality, allowEval, as
|
|
|
33408
33608
|
await page.waitForTimeout(shot.afterLoadMs);
|
|
33409
33609
|
}
|
|
33410
33610
|
const ext = format === "jpeg" ? "jpg" : "png";
|
|
33411
|
-
const
|
|
33611
|
+
const path49 = join14(outDir, `${shot.name}.${ext}`);
|
|
33412
33612
|
await page.screenshot({
|
|
33413
|
-
path:
|
|
33613
|
+
path: path49,
|
|
33414
33614
|
type: format,
|
|
33415
33615
|
...format === "jpeg" ? { quality: jpegQuality } : {},
|
|
33416
33616
|
fullPage: false
|
|
33417
33617
|
});
|
|
33418
|
-
return { name: shot.name, path:
|
|
33618
|
+
return { name: shot.name, path: path49, urlRedacted: redactUrl(shot.url), viewport };
|
|
33419
33619
|
} finally {
|
|
33420
33620
|
await context.close();
|
|
33421
33621
|
}
|
|
@@ -33859,12 +34059,12 @@ function openUrl(url2) {
|
|
|
33859
34059
|
var HOST_CP_URL = "http://127.0.0.1:19000";
|
|
33860
34060
|
async function readHostCpToken2() {
|
|
33861
34061
|
try {
|
|
33862
|
-
const { default:
|
|
34062
|
+
const { default: fs49 } = await import("node:fs");
|
|
33863
34063
|
const { default: os28 } = await import("node:os");
|
|
33864
|
-
const { default:
|
|
33865
|
-
const tp =
|
|
33866
|
-
if (!
|
|
33867
|
-
return { token:
|
|
34064
|
+
const { default: path49 } = await import("node:path");
|
|
34065
|
+
const tp = path49.join(os28.homedir(), ".olam", "host-cp.token");
|
|
34066
|
+
if (!fs49.existsSync(tp)) return { token: null };
|
|
34067
|
+
return { token: fs49.readFileSync(tp, "utf-8").trim() };
|
|
33868
34068
|
} catch {
|
|
33869
34069
|
return { token: null };
|
|
33870
34070
|
}
|
|
@@ -34124,9 +34324,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34124
34324
|
description: external_exports.string().optional().describe("Optional human-readable description."),
|
|
34125
34325
|
defaultBranch: external_exports.string().optional().describe("Default branch name (e.g. main).")
|
|
34126
34326
|
},
|
|
34127
|
-
async ({ name, path:
|
|
34327
|
+
async ({ name, path: path49, description, defaultBranch }) => {
|
|
34128
34328
|
try {
|
|
34129
|
-
const entry = addRepo({ name, path:
|
|
34329
|
+
const entry = addRepo({ name, path: path49, description, defaultBranch });
|
|
34130
34330
|
return {
|
|
34131
34331
|
content: [{
|
|
34132
34332
|
type: "text",
|
|
@@ -34167,9 +34367,9 @@ function register22(server, _ctx, _initError) {
|
|
|
34167
34367
|
description: external_exports.string().optional().describe("New description."),
|
|
34168
34368
|
defaultBranch: external_exports.string().optional().describe("New default branch.")
|
|
34169
34369
|
},
|
|
34170
|
-
async ({ name, path:
|
|
34370
|
+
async ({ name, path: path49, description, defaultBranch }) => {
|
|
34171
34371
|
try {
|
|
34172
|
-
const entry = updateRepo(name, { path:
|
|
34372
|
+
const entry = updateRepo(name, { path: path49, description, defaultBranch });
|
|
34173
34373
|
return {
|
|
34174
34374
|
content: [{
|
|
34175
34375
|
type: "text",
|
|
@@ -34190,15 +34390,15 @@ __export(process_port_exports, {
|
|
|
34190
34390
|
resolveHostCpToken: () => resolveHostCpToken
|
|
34191
34391
|
});
|
|
34192
34392
|
init_v3();
|
|
34193
|
-
import
|
|
34393
|
+
import fs34 from "node:fs";
|
|
34194
34394
|
import os20 from "node:os";
|
|
34195
|
-
import
|
|
34395
|
+
import path33 from "node:path";
|
|
34196
34396
|
var HOST_CP_BASE = "http://127.0.0.1:19000";
|
|
34197
34397
|
function resolveHostCpToken() {
|
|
34198
34398
|
const envToken = process.env["OLAM_HOST_CP_TOKEN"];
|
|
34199
34399
|
if (envToken) return envToken;
|
|
34200
|
-
const tokenPath =
|
|
34201
|
-
if (
|
|
34400
|
+
const tokenPath = path33.join(os20.homedir(), ".olam", "host-cp.token");
|
|
34401
|
+
if (fs34.existsSync(tokenPath)) return fs34.readFileSync(tokenPath, "utf-8").trim();
|
|
34202
34402
|
return null;
|
|
34203
34403
|
}
|
|
34204
34404
|
function tokenMissingError() {
|
|
@@ -34630,8 +34830,8 @@ __export(skills_exports, {
|
|
|
34630
34830
|
});
|
|
34631
34831
|
init_v3();
|
|
34632
34832
|
init_skill_sources();
|
|
34633
|
-
import * as
|
|
34634
|
-
import * as
|
|
34833
|
+
import * as fs35 from "node:fs";
|
|
34834
|
+
import * as path34 from "node:path";
|
|
34635
34835
|
function asMessage8(err) {
|
|
34636
34836
|
return err instanceof Error ? err.message : String(err);
|
|
34637
34837
|
}
|
|
@@ -34654,14 +34854,14 @@ function listDeployed() {
|
|
|
34654
34854
|
);
|
|
34655
34855
|
const entries = [];
|
|
34656
34856
|
for (const bucket of ["skills", "agents", "scripts", "rules", "commands"]) {
|
|
34657
|
-
const bucketDir =
|
|
34658
|
-
if (!
|
|
34659
|
-
for (const name of
|
|
34660
|
-
const full =
|
|
34857
|
+
const bucketDir = path34.join(dir, bucket);
|
|
34858
|
+
if (!fs35.existsSync(bucketDir)) continue;
|
|
34859
|
+
for (const name of fs35.readdirSync(bucketDir)) {
|
|
34860
|
+
const full = path34.join(bucketDir, name);
|
|
34661
34861
|
try {
|
|
34662
|
-
const stat =
|
|
34862
|
+
const stat = fs35.lstatSync(full);
|
|
34663
34863
|
if (!stat.isSymbolicLink()) continue;
|
|
34664
|
-
const target =
|
|
34864
|
+
const target = fs35.readlinkSync(full);
|
|
34665
34865
|
let sourceId;
|
|
34666
34866
|
for (const [clonePath, id] of sourcePaths.entries()) {
|
|
34667
34867
|
if (target.startsWith(clonePath)) {
|
|
@@ -34757,8 +34957,8 @@ function port() {
|
|
|
34757
34957
|
const n = Number.parseInt(env, 10);
|
|
34758
34958
|
return Number.isFinite(n) && n > 0 ? n : KG_SERVICE_PORT_DEFAULT;
|
|
34759
34959
|
}
|
|
34760
|
-
function url(
|
|
34761
|
-
return `http://127.0.0.1:${port()}${
|
|
34960
|
+
function url(path49) {
|
|
34961
|
+
return `http://127.0.0.1:${port()}${path49}`;
|
|
34762
34962
|
}
|
|
34763
34963
|
function kgServiceHealthUrl() {
|
|
34764
34964
|
return url("/health");
|
|
@@ -34957,8 +35157,8 @@ __export(kg_install_hook_exports, {
|
|
|
34957
35157
|
});
|
|
34958
35158
|
init_v3();
|
|
34959
35159
|
init_merge_settings();
|
|
34960
|
-
import * as
|
|
34961
|
-
import * as
|
|
35160
|
+
import * as fs36 from "node:fs";
|
|
35161
|
+
import * as path35 from "node:path";
|
|
34962
35162
|
import * as os21 from "node:os";
|
|
34963
35163
|
|
|
34964
35164
|
// ../core/dist/kg/hook-template.js
|
|
@@ -35009,10 +35209,10 @@ function buildHookMatcherEntry(opts) {
|
|
|
35009
35209
|
// ../mcp-server/src/tools/kg-install-hook.ts
|
|
35010
35210
|
function settingsPathFor2(scope, projectPath) {
|
|
35011
35211
|
if (scope === "user") {
|
|
35012
|
-
return
|
|
35212
|
+
return path35.join(os21.homedir(), ".claude", "settings.json");
|
|
35013
35213
|
}
|
|
35014
35214
|
const root = projectPath ?? process.cwd();
|
|
35015
|
-
return
|
|
35215
|
+
return path35.join(root, ".claude", "settings.json");
|
|
35016
35216
|
}
|
|
35017
35217
|
function register29(server, _ctx, _initError) {
|
|
35018
35218
|
server.tool(
|
|
@@ -35026,12 +35226,12 @@ function register29(server, _ctx, _initError) {
|
|
|
35026
35226
|
const scope = params.scope === "user" ? "user" : "project";
|
|
35027
35227
|
const filePath = settingsPathFor2(scope, params.projectPath);
|
|
35028
35228
|
try {
|
|
35029
|
-
|
|
35229
|
+
fs36.mkdirSync(path35.dirname(filePath), { recursive: true });
|
|
35030
35230
|
let backupPath = null;
|
|
35031
|
-
if (
|
|
35231
|
+
if (fs36.existsSync(filePath)) {
|
|
35032
35232
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35033
35233
|
backupPath = `${filePath}.olam-bak.${ts}`;
|
|
35034
|
-
|
|
35234
|
+
fs36.copyFileSync(filePath, backupPath);
|
|
35035
35235
|
}
|
|
35036
35236
|
const result = mergeHomeSettingsJson(filePath, {
|
|
35037
35237
|
ensureHook: {
|
|
@@ -35042,7 +35242,7 @@ function register29(server, _ctx, _initError) {
|
|
|
35042
35242
|
});
|
|
35043
35243
|
if (result.status === "already-present" && backupPath) {
|
|
35044
35244
|
try {
|
|
35045
|
-
|
|
35245
|
+
fs36.unlinkSync(backupPath);
|
|
35046
35246
|
} catch {
|
|
35047
35247
|
}
|
|
35048
35248
|
}
|
|
@@ -35086,15 +35286,15 @@ __export(kg_uninstall_hook_exports, {
|
|
|
35086
35286
|
register: () => register30
|
|
35087
35287
|
});
|
|
35088
35288
|
init_v3();
|
|
35089
|
-
import * as
|
|
35090
|
-
import * as
|
|
35289
|
+
import * as fs37 from "node:fs";
|
|
35290
|
+
import * as path36 from "node:path";
|
|
35091
35291
|
import * as os22 from "node:os";
|
|
35092
35292
|
function settingsPathFor3(scope, projectPath) {
|
|
35093
35293
|
if (scope === "user") {
|
|
35094
|
-
return
|
|
35294
|
+
return path36.join(os22.homedir(), ".claude", "settings.json");
|
|
35095
35295
|
}
|
|
35096
35296
|
const root = projectPath ?? process.cwd();
|
|
35097
|
-
return
|
|
35297
|
+
return path36.join(root, ".claude", "settings.json");
|
|
35098
35298
|
}
|
|
35099
35299
|
function dropSentinel(matchers) {
|
|
35100
35300
|
let changed = false;
|
|
@@ -35128,7 +35328,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35128
35328
|
const scope = params.scope === "user" ? "user" : "project";
|
|
35129
35329
|
const filePath = settingsPathFor3(scope, params.projectPath);
|
|
35130
35330
|
try {
|
|
35131
|
-
if (!
|
|
35331
|
+
if (!fs37.existsSync(filePath)) {
|
|
35132
35332
|
return {
|
|
35133
35333
|
content: [
|
|
35134
35334
|
{
|
|
@@ -35142,7 +35342,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35142
35342
|
]
|
|
35143
35343
|
};
|
|
35144
35344
|
}
|
|
35145
|
-
const raw =
|
|
35345
|
+
const raw = fs37.readFileSync(filePath, "utf-8");
|
|
35146
35346
|
const settings = raw.trim() ? JSON.parse(raw) : {};
|
|
35147
35347
|
const preToolUse = settings.hooks?.PreToolUse;
|
|
35148
35348
|
if (!Array.isArray(preToolUse) || preToolUse.length === 0) {
|
|
@@ -35177,7 +35377,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35177
35377
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
35178
35378
|
const backupPath = `${filePath}.olam-bak.${ts}`;
|
|
35179
35379
|
try {
|
|
35180
|
-
|
|
35380
|
+
fs37.copyFileSync(filePath, backupPath);
|
|
35181
35381
|
} catch {
|
|
35182
35382
|
}
|
|
35183
35383
|
const next = {
|
|
@@ -35189,7 +35389,7 @@ function register30(server, _ctx, _initError) {
|
|
|
35189
35389
|
if (otherStages.length === 0) delete next.hooks;
|
|
35190
35390
|
else delete next.hooks.PreToolUse;
|
|
35191
35391
|
}
|
|
35192
|
-
|
|
35392
|
+
fs37.writeFileSync(filePath, JSON.stringify(next, null, 2) + "\n");
|
|
35193
35393
|
return {
|
|
35194
35394
|
content: [
|
|
35195
35395
|
{
|
|
@@ -35404,9 +35604,9 @@ init_loader();
|
|
|
35404
35604
|
// ../core/dist/world/manager.js
|
|
35405
35605
|
import * as crypto8 from "node:crypto";
|
|
35406
35606
|
import { execSync as execSync5, spawnSync as spawnSync4 } from "node:child_process";
|
|
35407
|
-
import * as
|
|
35607
|
+
import * as fs46 from "node:fs";
|
|
35408
35608
|
import * as os26 from "node:os";
|
|
35409
|
-
import * as
|
|
35609
|
+
import * as path46 from "node:path";
|
|
35410
35610
|
|
|
35411
35611
|
// ../core/dist/world/state.js
|
|
35412
35612
|
var VALID_TRANSITIONS = {
|
|
@@ -35502,8 +35702,8 @@ function resolveDevboxImage(config2, tag) {
|
|
|
35502
35702
|
|
|
35503
35703
|
// ../core/dist/world/worktree.js
|
|
35504
35704
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
35505
|
-
import * as
|
|
35506
|
-
import * as
|
|
35705
|
+
import * as fs38 from "node:fs";
|
|
35706
|
+
import * as path37 from "node:path";
|
|
35507
35707
|
function resolveGitDir(repo) {
|
|
35508
35708
|
if (repo.path) {
|
|
35509
35709
|
return repo.path;
|
|
@@ -35513,11 +35713,11 @@ function resolveGitDir(repo) {
|
|
|
35513
35713
|
async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
35514
35714
|
const created = [];
|
|
35515
35715
|
for (const repo of repos) {
|
|
35516
|
-
const worktreePath =
|
|
35716
|
+
const worktreePath = path37.join(workspacePath, repo.name);
|
|
35517
35717
|
const gitDir = resolveGitDir(repo);
|
|
35518
35718
|
const branchName = branch || `olam/${worldId}`;
|
|
35519
35719
|
try {
|
|
35520
|
-
|
|
35720
|
+
fs38.mkdirSync(path37.dirname(worktreePath), { recursive: true });
|
|
35521
35721
|
execFileSync4("git", ["worktree", "add", worktreePath, "-b", branchName], {
|
|
35522
35722
|
cwd: gitDir,
|
|
35523
35723
|
stdio: "pipe"
|
|
@@ -35550,7 +35750,7 @@ async function createWorktrees(repos, worldId, workspacePath, branch) {
|
|
|
35550
35750
|
}
|
|
35551
35751
|
async function removeWorktrees(repos, workspacePath) {
|
|
35552
35752
|
for (const repo of repos) {
|
|
35553
|
-
const worktreePath =
|
|
35753
|
+
const worktreePath = path37.join(workspacePath, repo.name);
|
|
35554
35754
|
let gitDir;
|
|
35555
35755
|
try {
|
|
35556
35756
|
gitDir = resolveGitDir(repo);
|
|
@@ -35625,12 +35825,12 @@ function removeBranch(repo, branch) {
|
|
|
35625
35825
|
|
|
35626
35826
|
// ../core/dist/world/kg-overlay.js
|
|
35627
35827
|
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
35628
|
-
import * as
|
|
35629
|
-
import * as
|
|
35828
|
+
import * as fs39 from "node:fs";
|
|
35829
|
+
import * as path38 from "node:path";
|
|
35630
35830
|
|
|
35631
35831
|
// ../core/dist/kg/storage-paths.js
|
|
35632
35832
|
import { homedir as homedir22 } from "node:os";
|
|
35633
|
-
import { join as
|
|
35833
|
+
import { join as join38, resolve as resolve9 } from "node:path";
|
|
35634
35834
|
|
|
35635
35835
|
// ../core/dist/world/workspace-name.js
|
|
35636
35836
|
var InvalidWorkspaceNameError = class extends Error {
|
|
@@ -35651,25 +35851,25 @@ function validateWorkspaceName(name) {
|
|
|
35651
35851
|
|
|
35652
35852
|
// ../core/dist/kg/storage-paths.js
|
|
35653
35853
|
function olamHome() {
|
|
35654
|
-
return process.env.OLAM_HOME ??
|
|
35854
|
+
return process.env.OLAM_HOME ?? join38(homedir22(), ".olam");
|
|
35655
35855
|
}
|
|
35656
35856
|
function kgRoot() {
|
|
35657
|
-
return
|
|
35857
|
+
return join38(olamHome(), "kg");
|
|
35658
35858
|
}
|
|
35659
35859
|
function worldsRoot() {
|
|
35660
|
-
return
|
|
35860
|
+
return join38(olamHome(), "worlds");
|
|
35661
35861
|
}
|
|
35662
|
-
function assertWithinPrefix(
|
|
35663
|
-
if (!
|
|
35664
|
-
throw new Error(`${label} escape: ${
|
|
35862
|
+
function assertWithinPrefix(path49, prefix, label) {
|
|
35863
|
+
if (!path49.startsWith(prefix + "/")) {
|
|
35864
|
+
throw new Error(`${label} escape: ${path49} not under ${prefix}/`);
|
|
35665
35865
|
}
|
|
35666
35866
|
}
|
|
35667
35867
|
function kgPristinePath(workspace) {
|
|
35668
35868
|
validateWorkspaceName(workspace);
|
|
35669
35869
|
const root = kgRoot();
|
|
35670
|
-
const
|
|
35671
|
-
assertWithinPrefix(
|
|
35672
|
-
return
|
|
35870
|
+
const path49 = resolve9(join38(root, workspace));
|
|
35871
|
+
assertWithinPrefix(path49, root, "kgPristinePath");
|
|
35872
|
+
return path49;
|
|
35673
35873
|
}
|
|
35674
35874
|
var KG_PATHS_INTERNALS = Object.freeze({
|
|
35675
35875
|
olamHome,
|
|
@@ -35685,10 +35885,10 @@ var KgOverlayError = class extends Error {
|
|
|
35685
35885
|
}
|
|
35686
35886
|
};
|
|
35687
35887
|
function ensureGitignoreEntry(worldClonePath) {
|
|
35688
|
-
const gitignorePath =
|
|
35689
|
-
if (!
|
|
35888
|
+
const gitignorePath = path38.join(worldClonePath, ".gitignore");
|
|
35889
|
+
if (!fs39.existsSync(gitignorePath))
|
|
35690
35890
|
return "no-gitignore";
|
|
35691
|
-
const content =
|
|
35891
|
+
const content = fs39.readFileSync(gitignorePath, "utf-8");
|
|
35692
35892
|
const lines = content.split("\n").map((l) => l.trim());
|
|
35693
35893
|
const recognised = /* @__PURE__ */ new Set([
|
|
35694
35894
|
"graphify-out",
|
|
@@ -35703,24 +35903,24 @@ function ensureGitignoreEntry(worldClonePath) {
|
|
|
35703
35903
|
const eol = content.includes("\r\n") ? "\r\n" : "\n";
|
|
35704
35904
|
const needsLeadingNewline = content.length > 0 && !content.endsWith(eol);
|
|
35705
35905
|
const block = `${needsLeadingNewline ? eol : ""}${eol}# olam-kg-service: per-world KG overlay (Phase B1)${eol}graphify-out/${eol}`;
|
|
35706
|
-
|
|
35906
|
+
fs39.appendFileSync(gitignorePath, block, "utf-8");
|
|
35707
35907
|
return "appended";
|
|
35708
35908
|
}
|
|
35709
35909
|
function createWorldOverlay(opts) {
|
|
35710
35910
|
const pristineRoot = kgPristinePath(opts.workspace);
|
|
35711
|
-
const pristinePath =
|
|
35712
|
-
if (!
|
|
35911
|
+
const pristinePath = path38.join(pristineRoot, "graphify-out");
|
|
35912
|
+
if (!fs39.existsSync(pristinePath)) {
|
|
35713
35913
|
throw new KgOverlayError(`Pristine KG for workspace ${JSON.stringify(opts.workspace)} not found at ${pristinePath}. Run \`olam kg build ${opts.workspace}\` first.`);
|
|
35714
35914
|
}
|
|
35715
|
-
if (!
|
|
35915
|
+
if (!path38.isAbsolute(opts.worldClonePath)) {
|
|
35716
35916
|
throw new KgOverlayError(`worldClonePath must be absolute (got ${opts.worldClonePath})`);
|
|
35717
35917
|
}
|
|
35718
|
-
if (!
|
|
35918
|
+
if (!fs39.existsSync(opts.worldClonePath)) {
|
|
35719
35919
|
throw new KgOverlayError(`worldClonePath does not exist: ${opts.worldClonePath}. Create the clone before reflinking.`);
|
|
35720
35920
|
}
|
|
35721
|
-
const overlayPath =
|
|
35722
|
-
if (
|
|
35723
|
-
|
|
35921
|
+
const overlayPath = path38.join(opts.worldClonePath, "graphify-out");
|
|
35922
|
+
if (fs39.existsSync(overlayPath)) {
|
|
35923
|
+
fs39.rmSync(overlayPath, { recursive: true, force: true });
|
|
35724
35924
|
}
|
|
35725
35925
|
const useReflink = process.platform === "darwin";
|
|
35726
35926
|
let strategy;
|
|
@@ -35738,7 +35938,7 @@ function createWorldOverlay(opts) {
|
|
|
35738
35938
|
} else {
|
|
35739
35939
|
strategy = "cp-r";
|
|
35740
35940
|
}
|
|
35741
|
-
if (strategy === "cp-r" || !
|
|
35941
|
+
if (strategy === "cp-r" || !fs39.existsSync(overlayPath)) {
|
|
35742
35942
|
try {
|
|
35743
35943
|
execFileSync5("cp", ["-r", pristinePath, opts.worldClonePath], {
|
|
35744
35944
|
stdio: ["ignore", "ignore", "pipe"]
|
|
@@ -35750,7 +35950,7 @@ function createWorldOverlay(opts) {
|
|
|
35750
35950
|
throw new KgOverlayError(`cp -r failed: ${msg}${reflinkMsg}`);
|
|
35751
35951
|
}
|
|
35752
35952
|
}
|
|
35753
|
-
if (!
|
|
35953
|
+
if (!fs39.existsSync(overlayPath)) {
|
|
35754
35954
|
throw new KgOverlayError(`Overlay creation produced no ${overlayPath} after cp \u2014 filesystem returned without error?`);
|
|
35755
35955
|
}
|
|
35756
35956
|
const gitignoreAction = ensureGitignoreEntry(opts.worldClonePath);
|
|
@@ -35764,9 +35964,9 @@ function createWorldOverlay(opts) {
|
|
|
35764
35964
|
|
|
35765
35965
|
// ../core/dist/world/baseline-diff.js
|
|
35766
35966
|
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
35767
|
-
import * as
|
|
35967
|
+
import * as fs40 from "node:fs";
|
|
35768
35968
|
import * as os23 from "node:os";
|
|
35769
|
-
import * as
|
|
35969
|
+
import * as path39 from "node:path";
|
|
35770
35970
|
var DEFAULT_MAX_BUFFER_BYTES = 50 * 1024 * 1024;
|
|
35771
35971
|
function expandHome2(p, homedir28) {
|
|
35772
35972
|
return p.replace(/^~(?=$|\/|\\)/, homedir28());
|
|
@@ -35793,9 +35993,9 @@ ${stderr}`;
|
|
|
35793
35993
|
function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
35794
35994
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
35795
35995
|
const homedir28 = deps.homedir ?? (() => os23.homedir());
|
|
35796
|
-
const baselineDir =
|
|
35996
|
+
const baselineDir = path39.join(workspacePath, ".olam", "baseline");
|
|
35797
35997
|
try {
|
|
35798
|
-
|
|
35998
|
+
fs40.mkdirSync(baselineDir, { recursive: true });
|
|
35799
35999
|
} catch (err) {
|
|
35800
36000
|
const msg = err instanceof Error ? err.message : String(err);
|
|
35801
36001
|
console.warn(`[baseline-diff] mkdir ${baselineDir} failed: ${msg}; reaper will see no baseline at all`);
|
|
@@ -35807,9 +36007,9 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
35807
36007
|
if (!repo.path)
|
|
35808
36008
|
continue;
|
|
35809
36009
|
const filename = `${sanitizeRepoFilename(repo.name)}.diff`;
|
|
35810
|
-
const outPath =
|
|
36010
|
+
const outPath = path39.join(baselineDir, filename);
|
|
35811
36011
|
const repoPath = expandHome2(repo.path, homedir28);
|
|
35812
|
-
if (!
|
|
36012
|
+
if (!fs40.existsSync(repoPath)) {
|
|
35813
36013
|
writeBaselineFile(outPath, `# repo: ${repo.name}
|
|
35814
36014
|
# (skipped: path ${repoPath} does not exist)
|
|
35815
36015
|
`);
|
|
@@ -35876,7 +36076,7 @@ function snapshotBaselineDiff(repos, workspacePath, deps = {}) {
|
|
|
35876
36076
|
}
|
|
35877
36077
|
function writeBaselineFile(outPath, content) {
|
|
35878
36078
|
try {
|
|
35879
|
-
|
|
36079
|
+
fs40.writeFileSync(outPath, content);
|
|
35880
36080
|
} catch (err) {
|
|
35881
36081
|
const msg = err instanceof Error ? err.message : String(err);
|
|
35882
36082
|
console.warn(`[baseline-diff] write to ${outPath} failed: ${msg}`);
|
|
@@ -35884,8 +36084,8 @@ function writeBaselineFile(outPath, content) {
|
|
|
35884
36084
|
}
|
|
35885
36085
|
function stripWorktreeEdits(repos, workspacePath) {
|
|
35886
36086
|
for (const repo of repos) {
|
|
35887
|
-
const worktreePath =
|
|
35888
|
-
if (!
|
|
36087
|
+
const worktreePath = path39.join(workspacePath, repo.name);
|
|
36088
|
+
if (!fs40.existsSync(worktreePath))
|
|
35889
36089
|
continue;
|
|
35890
36090
|
try {
|
|
35891
36091
|
execFileSync6("git", ["checkout", "--", "."], {
|
|
@@ -35945,17 +36145,17 @@ function extractStderr(err) {
|
|
|
35945
36145
|
function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
35946
36146
|
const exec = deps.exec ?? ((cmd, args, opts) => execFileSync6(cmd, args, opts));
|
|
35947
36147
|
const homedir28 = deps.homedir ?? (() => os23.homedir());
|
|
35948
|
-
const existsSync46 = deps.existsSync ?? ((p) =>
|
|
35949
|
-
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) =>
|
|
36148
|
+
const existsSync46 = deps.existsSync ?? ((p) => fs40.existsSync(p));
|
|
36149
|
+
const copyFileSync9 = deps.copyFileSync ?? ((src, dest) => fs40.copyFileSync(src, dest));
|
|
35950
36150
|
const mkdirSync29 = deps.mkdirSync ?? ((dirPath, opts) => {
|
|
35951
|
-
|
|
36151
|
+
fs40.mkdirSync(dirPath, opts);
|
|
35952
36152
|
});
|
|
35953
36153
|
const plans = [];
|
|
35954
36154
|
for (const repo of repos) {
|
|
35955
36155
|
if (!repo.path)
|
|
35956
36156
|
continue;
|
|
35957
36157
|
const repoPath = expandHome2(repo.path, homedir28);
|
|
35958
|
-
const worktreePath =
|
|
36158
|
+
const worktreePath = path39.join(workspacePath, repo.name);
|
|
35959
36159
|
if (!existsSync46(repoPath))
|
|
35960
36160
|
continue;
|
|
35961
36161
|
if (!existsSync46(worktreePath)) {
|
|
@@ -36016,12 +36216,12 @@ function carryUncommittedEdits(repos, workspacePath, deps = {}) {
|
|
|
36016
36216
|
}
|
|
36017
36217
|
}
|
|
36018
36218
|
for (const rel of plan.diff.untracked) {
|
|
36019
|
-
const src =
|
|
36020
|
-
const dest =
|
|
36219
|
+
const src = path39.join(plan.repoPath, rel);
|
|
36220
|
+
const dest = path39.join(plan.worktreePath, rel);
|
|
36021
36221
|
if (!existsSync46(src))
|
|
36022
36222
|
continue;
|
|
36023
36223
|
try {
|
|
36024
|
-
mkdirSync29(
|
|
36224
|
+
mkdirSync29(path39.dirname(dest), { recursive: true });
|
|
36025
36225
|
copyFileSync9(src, dest);
|
|
36026
36226
|
} catch (err) {
|
|
36027
36227
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -36047,8 +36247,8 @@ function formatBaselineSummary(result) {
|
|
|
36047
36247
|
}
|
|
36048
36248
|
|
|
36049
36249
|
// ../core/dist/world/context-injection.js
|
|
36050
|
-
import * as
|
|
36051
|
-
import * as
|
|
36250
|
+
import * as fs41 from "node:fs";
|
|
36251
|
+
import * as path40 from "node:path";
|
|
36052
36252
|
|
|
36053
36253
|
// ../core/dist/world/templates/_generated.js
|
|
36054
36254
|
var GH_PR_CREATE = '# Creating PRs from inside an Olam world\n\n## The problem\n\nCalling `gh pr create` directly inside an Olam container **hangs forever** on a\nTTY confirmation prompt that the agent cannot answer. This is a known, reproduced issue.\n\n## The fix\n\nAlways use this exact pattern:\n\n```bash\necho y | timeout 30 gh pr create \\\n --base main \\\n --head <branch> \\\n --title "<title>" \\\n --body-file /tmp/pr-body.md\n```\n\n## Why each part matters\n\n- **`echo y |`** \u2014 answers the "Submit?" confirmation prompt up front so `gh` never pauses.\n- **`timeout 30`** \u2014 hard deadline. If `gh` hangs anyway, the command exits non-zero so the\n agent can react instead of stalling the world indefinitely.\n- **`--body-file /tmp/pr-body.md`** \u2014 write the PR body to a temp file first. Avoids\n shell-escaping bugs that occur with `--body "..."` for long or multi-line bodies.\n- **`--head` and `--base` explicitly** \u2014 removes all interactive prompts; `gh` has nothing to ask.\n\n## Troubleshooting\n\n**"no commits" or "branch not found" error:**\n\n```bash\ngit push -u origin <branch>\n# then retry:\necho y | timeout 30 gh pr create --base main --head <branch> --title "..." --body-file /tmp/pr-body.md\n```\n\n**Timeout exceeded (command exits 124):**\n\n- Check if the branch was pushed: `git log origin/<branch> --oneline -1`\n- Check GitHub CLI auth: `gh auth status`\n- Retry once; if it hangs again, open the PR via the GitHub web UI.\n';
|
|
@@ -36058,10 +36258,10 @@ var WORLD_CLAUDE_MD = '# Olam World: {{worldName}}\n\n{{taskBlock}}\n\n## Enviro
|
|
|
36058
36258
|
// ../core/dist/world/context-injection.js
|
|
36059
36259
|
function injectWorldContext(opts) {
|
|
36060
36260
|
const { world } = opts;
|
|
36061
|
-
const claudeDir2 =
|
|
36062
|
-
|
|
36261
|
+
const claudeDir2 = path40.join(world.workspacePath, ".claude");
|
|
36262
|
+
fs41.mkdirSync(claudeDir2, { recursive: true });
|
|
36063
36263
|
const content = WORLD_CLAUDE_MD.replace("{{worldName}}", world.name).replace("{{worldId}}", world.id).replace("{{branch}}", world.branch).replace("{{taskBlock}}", buildTaskBlock(opts)).replace("{{reposList}}", buildReposList(world)).replace("{{servicesLine}}", buildServicesLine(opts.services)).replace("{{pleriPlaneLine}}", buildPleriPlaneLine(opts.pleriPlaneUrl)).replace("{{planFileBlock}}", buildPlanFileBlock(world)).replace("{{extraContextBlock}}", buildExtraContextBlock(opts.claudeMdExtra));
|
|
36064
|
-
|
|
36264
|
+
fs41.writeFileSync(path40.join(claudeDir2, "CLAUDE.md"), content);
|
|
36065
36265
|
writeOlamDocs(world.workspacePath);
|
|
36066
36266
|
}
|
|
36067
36267
|
function buildTaskBlock(opts) {
|
|
@@ -36135,10 +36335,10 @@ function buildExtraContextBlock(extra) {
|
|
|
36135
36335
|
${extra}`;
|
|
36136
36336
|
}
|
|
36137
36337
|
function writeOlamDocs(workspacePath) {
|
|
36138
|
-
const docsDir =
|
|
36139
|
-
|
|
36140
|
-
|
|
36141
|
-
|
|
36338
|
+
const docsDir = path40.join(workspacePath, ".olam", "docs");
|
|
36339
|
+
fs41.mkdirSync(docsDir, { recursive: true });
|
|
36340
|
+
fs41.writeFileSync(path40.join(docsDir, "gh-pr-create.md"), GH_PR_CREATE);
|
|
36341
|
+
fs41.writeFileSync(path40.join(docsDir, "lane-orchestration.md"), LANE_ORCHESTRATION);
|
|
36142
36342
|
}
|
|
36143
36343
|
function formatTaskSource(ctx) {
|
|
36144
36344
|
if (ctx.source === "linear" && ctx.ticketId) {
|
|
@@ -36152,9 +36352,9 @@ function formatTaskSource(ctx) {
|
|
|
36152
36352
|
function hasPlanFile(world) {
|
|
36153
36353
|
if (world.repos.length === 0)
|
|
36154
36354
|
return false;
|
|
36155
|
-
const plansDir =
|
|
36355
|
+
const plansDir = path40.join(world.workspacePath, world.repos[0], "docs", "plans");
|
|
36156
36356
|
try {
|
|
36157
|
-
return
|
|
36357
|
+
return fs41.existsSync(plansDir) && fs41.readdirSync(plansDir).length > 0;
|
|
36158
36358
|
} catch {
|
|
36159
36359
|
return false;
|
|
36160
36360
|
}
|
|
@@ -36726,25 +36926,25 @@ init_repo_manifest();
|
|
|
36726
36926
|
|
|
36727
36927
|
// ../core/dist/world/snapshot.js
|
|
36728
36928
|
import * as crypto7 from "node:crypto";
|
|
36729
|
-
import * as
|
|
36929
|
+
import * as fs42 from "node:fs";
|
|
36730
36930
|
import * as os24 from "node:os";
|
|
36731
|
-
import * as
|
|
36931
|
+
import * as path41 from "node:path";
|
|
36732
36932
|
import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
|
|
36733
36933
|
import { gunzipSync } from "node:zlib";
|
|
36734
36934
|
function snapshotsDir() {
|
|
36735
|
-
return process.env["OLAM_SNAPSHOTS_DIR"] ??
|
|
36935
|
+
return process.env["OLAM_SNAPSHOTS_DIR"] ?? path41.join(os24.homedir(), ".olam", "snapshots");
|
|
36736
36936
|
}
|
|
36737
36937
|
function snapshotKindDirByWorkspace(workspace, arch, kind) {
|
|
36738
|
-
return
|
|
36938
|
+
return path41.join(snapshotsDir(), "by-workspace", workspace, arch, kind);
|
|
36739
36939
|
}
|
|
36740
36940
|
function cleanupLegacyByWorldDir(worldId) {
|
|
36741
|
-
const legacyDir =
|
|
36941
|
+
const legacyDir = path41.join(snapshotsDir(), worldId);
|
|
36742
36942
|
if (worldId === "by-workspace")
|
|
36743
36943
|
return;
|
|
36744
|
-
if (!
|
|
36944
|
+
if (!fs42.existsSync(legacyDir))
|
|
36745
36945
|
return;
|
|
36746
36946
|
try {
|
|
36747
|
-
|
|
36947
|
+
fs42.rmSync(legacyDir, { recursive: true, force: true });
|
|
36748
36948
|
} catch {
|
|
36749
36949
|
}
|
|
36750
36950
|
}
|
|
@@ -36763,11 +36963,11 @@ function hashBuffers(entries) {
|
|
|
36763
36963
|
return hash.digest("hex").slice(0, 12);
|
|
36764
36964
|
}
|
|
36765
36965
|
function computeGemsFingerprint(repoDir, imageDigest) {
|
|
36766
|
-
const lockfile =
|
|
36767
|
-
if (!
|
|
36966
|
+
const lockfile = path41.join(repoDir, "Gemfile.lock");
|
|
36967
|
+
if (!fs42.existsSync(lockfile))
|
|
36768
36968
|
return null;
|
|
36769
36969
|
const entries = [
|
|
36770
|
-
{ path: "Gemfile.lock", content:
|
|
36970
|
+
{ path: "Gemfile.lock", content: fs42.readFileSync(lockfile) }
|
|
36771
36971
|
];
|
|
36772
36972
|
if (imageDigest) {
|
|
36773
36973
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -36777,10 +36977,10 @@ function computeGemsFingerprint(repoDir, imageDigest) {
|
|
|
36777
36977
|
function computeNodeFingerprint(repoDir, imageDigest) {
|
|
36778
36978
|
const candidates = ["yarn.lock", "pnpm-lock.yaml", "package-lock.json"];
|
|
36779
36979
|
for (const name of candidates) {
|
|
36780
|
-
const lockfile =
|
|
36781
|
-
if (
|
|
36980
|
+
const lockfile = path41.join(repoDir, name);
|
|
36981
|
+
if (fs42.existsSync(lockfile)) {
|
|
36782
36982
|
const entries = [
|
|
36783
|
-
{ path: name, content:
|
|
36983
|
+
{ path: name, content: fs42.readFileSync(lockfile) }
|
|
36784
36984
|
];
|
|
36785
36985
|
if (imageDigest) {
|
|
36786
36986
|
entries.push({ path: "__image_digest__", content: Buffer.from(imageDigest, "utf-8") });
|
|
@@ -36799,18 +36999,18 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
36799
36999
|
detail: validation.detail ?? `unsafe entry: ${validation.unsafePath}`
|
|
36800
37000
|
};
|
|
36801
37001
|
}
|
|
36802
|
-
const parent =
|
|
36803
|
-
|
|
37002
|
+
const parent = path41.dirname(destDir);
|
|
37003
|
+
fs42.mkdirSync(parent, { recursive: true });
|
|
36804
37004
|
const tmpSuffix = `.tmp-${process.pid}-${crypto7.randomBytes(4).toString("hex")}`;
|
|
36805
37005
|
const tmpDir = `${destDir}${tmpSuffix}`;
|
|
36806
37006
|
try {
|
|
36807
|
-
|
|
37007
|
+
fs42.mkdirSync(tmpDir, { recursive: true });
|
|
36808
37008
|
execFileSync7("tar", ["-xzf", srcPath, "-C", tmpDir], { stdio: "pipe" });
|
|
36809
|
-
|
|
37009
|
+
fs42.renameSync(tmpDir, destDir);
|
|
36810
37010
|
return { ok: true, entryCount: validation.entries.length };
|
|
36811
37011
|
} catch (err) {
|
|
36812
37012
|
try {
|
|
36813
|
-
|
|
37013
|
+
fs42.rmSync(tmpDir, { recursive: true, force: true });
|
|
36814
37014
|
} catch {
|
|
36815
37015
|
}
|
|
36816
37016
|
return {
|
|
@@ -36821,12 +37021,12 @@ function unpackTarballAtomic(srcPath, destDir) {
|
|
|
36821
37021
|
}
|
|
36822
37022
|
}
|
|
36823
37023
|
function resolvesWithin(base, target) {
|
|
36824
|
-
const resolved =
|
|
36825
|
-
const baseResolved =
|
|
36826
|
-
const rel =
|
|
37024
|
+
const resolved = path41.resolve(base, target);
|
|
37025
|
+
const baseResolved = path41.resolve(base);
|
|
37026
|
+
const rel = path41.relative(baseResolved, resolved);
|
|
36827
37027
|
if (rel === "")
|
|
36828
37028
|
return true;
|
|
36829
|
-
return !rel.startsWith("..") && !
|
|
37029
|
+
return !rel.startsWith("..") && !path41.isAbsolute(rel);
|
|
36830
37030
|
}
|
|
36831
37031
|
var TYPE_CHAR_TO_TYPE = {
|
|
36832
37032
|
"-": "file",
|
|
@@ -36876,7 +37076,7 @@ function parseTarListLine(line) {
|
|
|
36876
37076
|
function validateHardlinksBinary(tarPath, targetDir) {
|
|
36877
37077
|
let raw;
|
|
36878
37078
|
try {
|
|
36879
|
-
raw = gunzipSync(
|
|
37079
|
+
raw = gunzipSync(fs42.readFileSync(tarPath));
|
|
36880
37080
|
} catch {
|
|
36881
37081
|
return null;
|
|
36882
37082
|
}
|
|
@@ -36891,7 +37091,7 @@ function validateHardlinksBinary(tarPath, targetDir) {
|
|
|
36891
37091
|
const name = block.subarray(0, nameNull >= 0 && nameNull <= 99 ? nameNull : 100).toString("utf-8");
|
|
36892
37092
|
const linkNull = block.indexOf(0, 157);
|
|
36893
37093
|
const linkname = block.subarray(157, linkNull >= 157 && linkNull <= 256 ? linkNull : 257).toString("utf-8");
|
|
36894
|
-
if (linkname && (
|
|
37094
|
+
if (linkname && (path41.isAbsolute(linkname) || !resolvesWithin(targetDir, linkname))) {
|
|
36895
37095
|
return {
|
|
36896
37096
|
valid: false,
|
|
36897
37097
|
reason: "hardlink-escape",
|
|
@@ -36929,7 +37129,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
36929
37129
|
const entry = parseTarListLine(line);
|
|
36930
37130
|
if (!entry)
|
|
36931
37131
|
continue;
|
|
36932
|
-
if (
|
|
37132
|
+
if (path41.isAbsolute(entry.name) || !resolvesWithin(targetDir, entry.name)) {
|
|
36933
37133
|
return {
|
|
36934
37134
|
valid: false,
|
|
36935
37135
|
reason: "path-traversal",
|
|
@@ -36937,8 +37137,8 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
36937
37137
|
};
|
|
36938
37138
|
}
|
|
36939
37139
|
if (entry.type === "symlink" && entry.linkname !== void 0) {
|
|
36940
|
-
const symlinkParent =
|
|
36941
|
-
if (
|
|
37140
|
+
const symlinkParent = path41.join(targetDir, path41.dirname(entry.name));
|
|
37141
|
+
if (path41.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, path41.join(path41.dirname(entry.name), entry.linkname))) {
|
|
36942
37142
|
return {
|
|
36943
37143
|
valid: false,
|
|
36944
37144
|
reason: "symlink-escape",
|
|
@@ -36948,7 +37148,7 @@ function enumerateAndValidateTarballEntries(tarPath, targetDir) {
|
|
|
36948
37148
|
}
|
|
36949
37149
|
}
|
|
36950
37150
|
if (entry.type === "hardlink" && entry.linkname !== void 0) {
|
|
36951
|
-
if (
|
|
37151
|
+
if (path41.isAbsolute(entry.linkname) || !resolvesWithin(targetDir, entry.linkname)) {
|
|
36952
37152
|
return {
|
|
36953
37153
|
valid: false,
|
|
36954
37154
|
reason: "hardlink-escape",
|
|
@@ -36981,8 +37181,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
36981
37181
|
}
|
|
36982
37182
|
const archDir = snapshotKindDirByWorkspace(input.workspace, input.arch, kind);
|
|
36983
37183
|
const tarFilename = `${repo.name}-${input.arch}-${fingerprint}.tar.gz`;
|
|
36984
|
-
const tarPath =
|
|
36985
|
-
if (!
|
|
37184
|
+
const tarPath = path41.join(archDir, tarFilename);
|
|
37185
|
+
if (!fs42.existsSync(tarPath)) {
|
|
36986
37186
|
outcomes.push({ repo: repo.name, kind, outcome: "miss", reason: "no-tarball", fingerprint });
|
|
36987
37187
|
continue;
|
|
36988
37188
|
}
|
|
@@ -36997,9 +37197,9 @@ function restoreSnapshotsForRepos(input) {
|
|
|
36997
37197
|
});
|
|
36998
37198
|
continue;
|
|
36999
37199
|
}
|
|
37000
|
-
const targetDir =
|
|
37200
|
+
const targetDir = path41.join(repo.worktreeDir, targetSubpath);
|
|
37001
37201
|
try {
|
|
37002
|
-
|
|
37202
|
+
fs42.rmSync(targetDir, { recursive: true, force: true });
|
|
37003
37203
|
} catch {
|
|
37004
37204
|
}
|
|
37005
37205
|
const result = unpackTarballAtomic(tarPath, targetDir);
|
|
@@ -37012,8 +37212,8 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37012
37212
|
fingerprint
|
|
37013
37213
|
});
|
|
37014
37214
|
try {
|
|
37015
|
-
|
|
37016
|
-
|
|
37215
|
+
fs42.rmSync(tarPath, { force: true });
|
|
37216
|
+
fs42.rmSync(manifestPath(tarPath), { force: true });
|
|
37017
37217
|
} catch {
|
|
37018
37218
|
}
|
|
37019
37219
|
continue;
|
|
@@ -37029,10 +37229,10 @@ function restoreSnapshotsForRepos(input) {
|
|
|
37029
37229
|
}
|
|
37030
37230
|
function readManifest(tarPath) {
|
|
37031
37231
|
const mPath = manifestPath(tarPath);
|
|
37032
|
-
if (!
|
|
37232
|
+
if (!fs42.existsSync(mPath))
|
|
37033
37233
|
return null;
|
|
37034
37234
|
try {
|
|
37035
|
-
return JSON.parse(
|
|
37235
|
+
return JSON.parse(fs42.readFileSync(mPath, "utf-8"));
|
|
37036
37236
|
} catch {
|
|
37037
37237
|
return null;
|
|
37038
37238
|
}
|
|
@@ -37047,17 +37247,17 @@ function isPidAlive(pid) {
|
|
|
37047
37247
|
}
|
|
37048
37248
|
}
|
|
37049
37249
|
function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
37050
|
-
|
|
37051
|
-
const lockPath =
|
|
37250
|
+
fs42.mkdirSync(dir, { recursive: true });
|
|
37251
|
+
const lockPath = path41.join(dir, EVICT_LOCK_FILENAME);
|
|
37052
37252
|
let fd;
|
|
37053
37253
|
try {
|
|
37054
|
-
fd =
|
|
37254
|
+
fd = fs42.openSync(lockPath, fs42.constants.O_WRONLY | fs42.constants.O_CREAT | fs42.constants.O_EXCL, 384);
|
|
37055
37255
|
} catch (err) {
|
|
37056
37256
|
if (err.code !== "EEXIST")
|
|
37057
37257
|
return 0;
|
|
37058
37258
|
let holderPid = null;
|
|
37059
37259
|
try {
|
|
37060
|
-
holderPid = parseInt(
|
|
37260
|
+
holderPid = parseInt(fs42.readFileSync(lockPath, "utf-8").trim(), 10);
|
|
37061
37261
|
} catch {
|
|
37062
37262
|
holderPid = null;
|
|
37063
37263
|
}
|
|
@@ -37065,23 +37265,23 @@ function evictOldSnapshotsWithFlock(maxBytes, dir = snapshotsDir()) {
|
|
|
37065
37265
|
return 0;
|
|
37066
37266
|
}
|
|
37067
37267
|
try {
|
|
37068
|
-
|
|
37069
|
-
fd =
|
|
37268
|
+
fs42.unlinkSync(lockPath);
|
|
37269
|
+
fd = fs42.openSync(lockPath, fs42.constants.O_WRONLY | fs42.constants.O_CREAT | fs42.constants.O_EXCL, 384);
|
|
37070
37270
|
} catch {
|
|
37071
37271
|
return 0;
|
|
37072
37272
|
}
|
|
37073
37273
|
}
|
|
37074
37274
|
try {
|
|
37075
|
-
|
|
37275
|
+
fs42.writeSync(fd, `${process.pid}
|
|
37076
37276
|
`);
|
|
37077
37277
|
} finally {
|
|
37078
|
-
|
|
37278
|
+
fs42.closeSync(fd);
|
|
37079
37279
|
}
|
|
37080
37280
|
try {
|
|
37081
37281
|
return evictOldSnapshots(maxBytes, dir);
|
|
37082
37282
|
} finally {
|
|
37083
37283
|
try {
|
|
37084
|
-
|
|
37284
|
+
fs42.unlinkSync(lockPath);
|
|
37085
37285
|
} catch {
|
|
37086
37286
|
}
|
|
37087
37287
|
}
|
|
@@ -37114,16 +37314,16 @@ function spawnAutoCapture(worldId, olamBin = "olam") {
|
|
|
37114
37314
|
}
|
|
37115
37315
|
}
|
|
37116
37316
|
function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
37117
|
-
if (!
|
|
37317
|
+
if (!fs42.existsSync(dir))
|
|
37118
37318
|
return 0;
|
|
37119
37319
|
const allTars = [];
|
|
37120
37320
|
const walk = (d) => {
|
|
37121
|
-
for (const entry of
|
|
37122
|
-
const full =
|
|
37321
|
+
for (const entry of fs42.readdirSync(d, { withFileTypes: true })) {
|
|
37322
|
+
const full = path41.join(d, entry.name);
|
|
37123
37323
|
if (entry.isDirectory()) {
|
|
37124
37324
|
walk(full);
|
|
37125
37325
|
} else if (entry.name.endsWith(".tar.gz")) {
|
|
37126
|
-
const stat =
|
|
37326
|
+
const stat = fs42.statSync(full);
|
|
37127
37327
|
allTars.push({ path: full, size: stat.size, mtime: stat.mtimeMs });
|
|
37128
37328
|
}
|
|
37129
37329
|
}
|
|
@@ -37138,8 +37338,8 @@ function evictOldSnapshots(maxBytes, dir = snapshotsDir()) {
|
|
|
37138
37338
|
for (const tar of allTars) {
|
|
37139
37339
|
if (remaining <= maxBytes)
|
|
37140
37340
|
break;
|
|
37141
|
-
|
|
37142
|
-
|
|
37341
|
+
fs42.rmSync(tar.path, { force: true });
|
|
37342
|
+
fs42.rmSync(manifestPath(tar.path), { force: true });
|
|
37143
37343
|
freed += tar.size;
|
|
37144
37344
|
remaining -= tar.size;
|
|
37145
37345
|
}
|
|
@@ -37256,14 +37456,14 @@ function gcloudAvailable(execFn = defaultExecFn) {
|
|
|
37256
37456
|
|
|
37257
37457
|
// ../core/dist/world/olam-yaml.js
|
|
37258
37458
|
init_repo_manifest();
|
|
37259
|
-
import * as
|
|
37459
|
+
import * as path42 from "node:path";
|
|
37260
37460
|
import YAML2 from "yaml";
|
|
37261
37461
|
function enrichReposWithManifests(repos, workspacePath) {
|
|
37262
37462
|
return repos.map((repo) => {
|
|
37263
37463
|
if (repo.manifest !== void 0 && repo.manifest !== null) {
|
|
37264
37464
|
return repo;
|
|
37265
37465
|
}
|
|
37266
|
-
const repoDir =
|
|
37466
|
+
const repoDir = path42.join(workspacePath, repo.name);
|
|
37267
37467
|
let manifest = null;
|
|
37268
37468
|
try {
|
|
37269
37469
|
manifest = loadRepoManifest(repoDir);
|
|
@@ -37278,8 +37478,8 @@ function enrichReposWithManifests(repos, workspacePath) {
|
|
|
37278
37478
|
}
|
|
37279
37479
|
|
|
37280
37480
|
// ../core/dist/policies/loader.js
|
|
37281
|
-
import * as
|
|
37282
|
-
import * as
|
|
37481
|
+
import * as fs43 from "node:fs";
|
|
37482
|
+
import * as path43 from "node:path";
|
|
37283
37483
|
import { parse as parseYaml4 } from "yaml";
|
|
37284
37484
|
function parseFrontmatter2(content) {
|
|
37285
37485
|
const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/m.exec(content);
|
|
@@ -37299,20 +37499,20 @@ function toStringArray(v) {
|
|
|
37299
37499
|
return v.filter((x) => typeof x === "string");
|
|
37300
37500
|
}
|
|
37301
37501
|
function loadPolicies(workspaceRoot) {
|
|
37302
|
-
const policiesDir =
|
|
37303
|
-
if (!
|
|
37502
|
+
const policiesDir = path43.join(workspaceRoot, ".olam", "policies");
|
|
37503
|
+
if (!fs43.existsSync(policiesDir))
|
|
37304
37504
|
return [];
|
|
37305
37505
|
let files;
|
|
37306
37506
|
try {
|
|
37307
|
-
files =
|
|
37507
|
+
files = fs43.readdirSync(policiesDir).filter((f) => f.endsWith(".md")).sort();
|
|
37308
37508
|
} catch {
|
|
37309
37509
|
return [];
|
|
37310
37510
|
}
|
|
37311
37511
|
const policies = [];
|
|
37312
37512
|
for (const file of files) {
|
|
37313
|
-
const filePath =
|
|
37513
|
+
const filePath = path43.join(policiesDir, file);
|
|
37314
37514
|
try {
|
|
37315
|
-
const content =
|
|
37515
|
+
const content = fs43.readFileSync(filePath, "utf8");
|
|
37316
37516
|
const parsed = parseFrontmatter2(content);
|
|
37317
37517
|
if (!parsed) {
|
|
37318
37518
|
console.warn(`[policies] skipping ${file}: no valid frontmatter block`);
|
|
@@ -37459,12 +37659,12 @@ init_store();
|
|
|
37459
37659
|
init_bridge();
|
|
37460
37660
|
|
|
37461
37661
|
// ../core/dist/global-config/runbook-resolver.js
|
|
37462
|
-
import * as
|
|
37662
|
+
import * as fs44 from "node:fs";
|
|
37463
37663
|
import * as os25 from "node:os";
|
|
37464
|
-
import * as
|
|
37664
|
+
import * as path44 from "node:path";
|
|
37465
37665
|
function expandTilde(p) {
|
|
37466
37666
|
if (p === "~" || p.startsWith("~/")) {
|
|
37467
|
-
return
|
|
37667
|
+
return path44.join(os25.homedir(), p.slice(1));
|
|
37468
37668
|
}
|
|
37469
37669
|
return p;
|
|
37470
37670
|
}
|
|
@@ -37476,7 +37676,7 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
37476
37676
|
throw new Error(`repo "${repoName}" is referenced by runbook "${runbook.name}" but is not in the registry. Run "olam repos add ${repoName} --path <path>" to register it.`);
|
|
37477
37677
|
}
|
|
37478
37678
|
const resolvedPath = expandTilde(entry.path);
|
|
37479
|
-
if (!
|
|
37679
|
+
if (!fs44.existsSync(resolvedPath)) {
|
|
37480
37680
|
throw new Error(`repo "${repoName}" path "${resolvedPath}" no longer exists. Run "olam repos update ${repoName} --path <new-path>" to fix.`);
|
|
37481
37681
|
}
|
|
37482
37682
|
}
|
|
@@ -37492,19 +37692,19 @@ function resolveRunbookToWorldParams(runbook, repoRegistry) {
|
|
|
37492
37692
|
init_port_validator();
|
|
37493
37693
|
|
|
37494
37694
|
// ../core/dist/world/bootstrap-hooks.js
|
|
37495
|
-
import * as
|
|
37496
|
-
import * as
|
|
37695
|
+
import * as fs45 from "node:fs";
|
|
37696
|
+
import * as path45 from "node:path";
|
|
37497
37697
|
function runFixtureCopySeeds(seeds, workspacePath) {
|
|
37498
37698
|
if (!seeds)
|
|
37499
37699
|
return;
|
|
37500
37700
|
for (const seed of seeds) {
|
|
37501
37701
|
if (seed.type !== "fixture-copy")
|
|
37502
37702
|
continue;
|
|
37503
|
-
const srcAbs =
|
|
37504
|
-
const destAbs =
|
|
37505
|
-
const destDir =
|
|
37506
|
-
|
|
37507
|
-
|
|
37703
|
+
const srcAbs = path45.resolve(workspacePath, seed.repo, seed.src);
|
|
37704
|
+
const destAbs = path45.resolve(workspacePath, seed.repo, seed.dest);
|
|
37705
|
+
const destDir = path45.dirname(destAbs);
|
|
37706
|
+
fs45.mkdirSync(destDir, { recursive: true });
|
|
37707
|
+
fs45.cpSync(srcAbs, destAbs, { recursive: true, force: true });
|
|
37508
37708
|
}
|
|
37509
37709
|
}
|
|
37510
37710
|
async function runSeedHooks(seeds, containerName, servicePortMap, exec) {
|
|
@@ -38140,7 +38340,7 @@ ${detail}`);
|
|
|
38140
38340
|
runbookSeeds = resolved.seeds;
|
|
38141
38341
|
}
|
|
38142
38342
|
const worldId = generateWorldId();
|
|
38143
|
-
const workspacePath =
|
|
38343
|
+
const workspacePath = path46.join(os26.homedir(), ".olam", "worlds", worldId);
|
|
38144
38344
|
const portOffset = this.registry.getNextPortOffset();
|
|
38145
38345
|
const branch = opts.branchName ?? `olam/${worldId}`;
|
|
38146
38346
|
const repos = this.resolveReposWithWorkspace(opts);
|
|
@@ -38222,37 +38422,37 @@ ${detail}`);
|
|
|
38222
38422
|
if (!repo.path)
|
|
38223
38423
|
continue;
|
|
38224
38424
|
const sourceRoot = repo.path.replace(/^~/, os26.homedir());
|
|
38225
|
-
const worktreeRoot =
|
|
38226
|
-
if (!
|
|
38425
|
+
const worktreeRoot = path46.join(workspacePath, repo.name);
|
|
38426
|
+
if (!fs46.existsSync(sourceRoot) || !fs46.existsSync(worktreeRoot))
|
|
38227
38427
|
continue;
|
|
38228
38428
|
let copied = 0;
|
|
38229
38429
|
for (const pattern of RUNTIME_FILE_PATTERNS) {
|
|
38230
38430
|
const matches2 = [];
|
|
38231
38431
|
if (pattern.includes("*")) {
|
|
38232
|
-
const [dir, glob] = [
|
|
38233
|
-
const sourceDir =
|
|
38234
|
-
if (
|
|
38432
|
+
const [dir, glob] = [path46.dirname(pattern), path46.basename(pattern)];
|
|
38433
|
+
const sourceDir = path46.join(sourceRoot, dir);
|
|
38434
|
+
if (fs46.existsSync(sourceDir)) {
|
|
38235
38435
|
const ext = glob.replace(/^\*+/, "");
|
|
38236
38436
|
try {
|
|
38237
|
-
for (const entry of
|
|
38437
|
+
for (const entry of fs46.readdirSync(sourceDir)) {
|
|
38238
38438
|
if (ext === "" || entry.endsWith(ext))
|
|
38239
|
-
matches2.push(
|
|
38439
|
+
matches2.push(path46.join(dir, entry));
|
|
38240
38440
|
}
|
|
38241
38441
|
} catch {
|
|
38242
38442
|
}
|
|
38243
38443
|
}
|
|
38244
|
-
} else if (
|
|
38444
|
+
} else if (fs46.existsSync(path46.join(sourceRoot, pattern))) {
|
|
38245
38445
|
matches2.push(pattern);
|
|
38246
38446
|
}
|
|
38247
38447
|
for (const rel of matches2) {
|
|
38248
|
-
const src =
|
|
38249
|
-
const dst =
|
|
38448
|
+
const src = path46.join(sourceRoot, rel);
|
|
38449
|
+
const dst = path46.join(worktreeRoot, rel);
|
|
38250
38450
|
try {
|
|
38251
|
-
const st =
|
|
38451
|
+
const st = fs46.statSync(src);
|
|
38252
38452
|
if (!st.isFile())
|
|
38253
38453
|
continue;
|
|
38254
|
-
|
|
38255
|
-
|
|
38454
|
+
fs46.mkdirSync(path46.dirname(dst), { recursive: true });
|
|
38455
|
+
fs46.copyFileSync(src, dst);
|
|
38256
38456
|
copied++;
|
|
38257
38457
|
} catch {
|
|
38258
38458
|
}
|
|
@@ -38338,7 +38538,7 @@ ${detail}`);
|
|
|
38338
38538
|
}
|
|
38339
38539
|
const overlayAttachments = [];
|
|
38340
38540
|
for (const repo of repos) {
|
|
38341
|
-
const worldClonePath =
|
|
38541
|
+
const worldClonePath = path46.join(workspacePath, repo.name);
|
|
38342
38542
|
try {
|
|
38343
38543
|
const result = createWorldOverlay({
|
|
38344
38544
|
workspace: repo.name,
|
|
@@ -38393,7 +38593,7 @@ ${detail}`);
|
|
|
38393
38593
|
try {
|
|
38394
38594
|
const hostExec = makeHostExecFn();
|
|
38395
38595
|
for (const repo of repos) {
|
|
38396
|
-
const repoDir =
|
|
38596
|
+
const repoDir = path46.join(workspacePath, repo.name);
|
|
38397
38597
|
if (repo.stack && Object.keys(repo.stack).length > 0) {
|
|
38398
38598
|
preDetectedStacks.set(repo.name, { repoName: repo.name, versions: repo.stack });
|
|
38399
38599
|
} else {
|
|
@@ -38437,10 +38637,10 @@ ${detail}`);
|
|
|
38437
38637
|
const worldEnv = {};
|
|
38438
38638
|
if (opts.task)
|
|
38439
38639
|
worldEnv.OLAM_TASK = opts.task;
|
|
38440
|
-
const r2CredsPath =
|
|
38441
|
-
if (
|
|
38640
|
+
const r2CredsPath = path46.join(os26.homedir(), ".olam", "r2-credentials.json");
|
|
38641
|
+
if (fs46.existsSync(r2CredsPath)) {
|
|
38442
38642
|
try {
|
|
38443
|
-
const r2Raw =
|
|
38643
|
+
const r2Raw = fs46.readFileSync(r2CredsPath, "utf-8").trim();
|
|
38444
38644
|
if (r2Raw.length > 0) {
|
|
38445
38645
|
const r2 = JSON.parse(r2Raw);
|
|
38446
38646
|
if (typeof r2.account_id === "string")
|
|
@@ -38457,10 +38657,10 @@ ${detail}`);
|
|
|
38457
38657
|
} catch {
|
|
38458
38658
|
}
|
|
38459
38659
|
}
|
|
38460
|
-
const keysYamlPath =
|
|
38461
|
-
if (
|
|
38660
|
+
const keysYamlPath = path46.join(os26.homedir(), ".olam", "keys.yaml");
|
|
38661
|
+
if (fs46.existsSync(keysYamlPath)) {
|
|
38462
38662
|
try {
|
|
38463
|
-
const keysRaw =
|
|
38663
|
+
const keysRaw = fs46.readFileSync(keysYamlPath, "utf-8").trim();
|
|
38464
38664
|
if (keysRaw.length > 0) {
|
|
38465
38665
|
const parsed = YAML3.parse(keysRaw);
|
|
38466
38666
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
@@ -38519,10 +38719,10 @@ ${detail}`);
|
|
|
38519
38719
|
worldEnv[k] = v;
|
|
38520
38720
|
}
|
|
38521
38721
|
for (const { repoName, relativePath, content } of fileWrites) {
|
|
38522
|
-
const absPath =
|
|
38722
|
+
const absPath = path46.join(workspacePath, repoName, relativePath);
|
|
38523
38723
|
try {
|
|
38524
|
-
|
|
38525
|
-
|
|
38724
|
+
fs46.mkdirSync(path46.dirname(absPath), { recursive: true });
|
|
38725
|
+
fs46.writeFileSync(absPath, content.endsWith("\n") ? content : content + "\n", {
|
|
38526
38726
|
mode: 384
|
|
38527
38727
|
});
|
|
38528
38728
|
console.log(`[secrets] ${repoName}: materialised ${relativePath} (${content.length} chars, mode 0600)`);
|
|
@@ -38699,7 +38899,7 @@ ${detail}`);
|
|
|
38699
38899
|
imageDigest: void 0,
|
|
38700
38900
|
repos: enrichedRepos.map((r) => ({
|
|
38701
38901
|
name: r.name,
|
|
38702
|
-
worktreeDir:
|
|
38902
|
+
worktreeDir: path46.join(workspacePath, r.name)
|
|
38703
38903
|
}))
|
|
38704
38904
|
});
|
|
38705
38905
|
for (const out of restoreResult.outcomes) {
|
|
@@ -38805,7 +39005,7 @@ ${detail}`);
|
|
|
38805
39005
|
}
|
|
38806
39006
|
if (opts.task) {
|
|
38807
39007
|
const allPolicies = repos.flatMap((repo) => {
|
|
38808
|
-
const repoWorktree =
|
|
39008
|
+
const repoWorktree = path46.join(workspacePath, repo.name);
|
|
38809
39009
|
try {
|
|
38810
39010
|
return loadPolicies(repoWorktree);
|
|
38811
39011
|
} catch (err) {
|
|
@@ -38818,8 +39018,8 @@ ${detail}`);
|
|
|
38818
39018
|
try {
|
|
38819
39019
|
execSync5(`docker exec ${containerName} mkdir -p /home/olam/.olam/policies`, { stdio: "pipe", timeout: 1e4 });
|
|
38820
39020
|
for (const repo of repos) {
|
|
38821
|
-
const policiesDir =
|
|
38822
|
-
if (
|
|
39021
|
+
const policiesDir = path46.join(workspacePath, repo.name, ".olam", "policies");
|
|
39022
|
+
if (fs46.existsSync(policiesDir)) {
|
|
38823
39023
|
execSync5(`docker cp "${policiesDir}/." "${containerName}:/home/olam/.olam/policies/"`, { stdio: "pipe", timeout: 15e3 });
|
|
38824
39024
|
}
|
|
38825
39025
|
}
|
|
@@ -38927,8 +39127,8 @@ ${detail}`);
|
|
|
38927
39127
|
} catch {
|
|
38928
39128
|
}
|
|
38929
39129
|
try {
|
|
38930
|
-
|
|
38931
|
-
if (
|
|
39130
|
+
fs46.rmSync(world.workspacePath, { recursive: true, force: true });
|
|
39131
|
+
if (fs46.existsSync(world.workspacePath)) {
|
|
38932
39132
|
console.warn(`[WorldManager] destroyWorld(${worldId}): workspace dir ${world.workspacePath} still exists after rmSync. Run \`olam clean --apply\` to reap.`);
|
|
38933
39133
|
}
|
|
38934
39134
|
} catch (err) {
|
|
@@ -39037,14 +39237,14 @@ ${detail}`);
|
|
|
39037
39237
|
}).filter((r) => r !== void 0);
|
|
39038
39238
|
}
|
|
39039
39239
|
transportPlanFile(planFilePath, workspacePath, repoNames) {
|
|
39040
|
-
const planContent =
|
|
39041
|
-
const planFileName =
|
|
39240
|
+
const planContent = fs46.readFileSync(planFilePath, "utf-8");
|
|
39241
|
+
const planFileName = path46.basename(planFilePath);
|
|
39042
39242
|
const targetRepo = repoNames[0];
|
|
39043
39243
|
if (!targetRepo)
|
|
39044
39244
|
return;
|
|
39045
|
-
const plansDir =
|
|
39046
|
-
|
|
39047
|
-
|
|
39245
|
+
const plansDir = path46.join(workspacePath, targetRepo, "docs", "plans");
|
|
39246
|
+
fs46.mkdirSync(plansDir, { recursive: true });
|
|
39247
|
+
fs46.writeFileSync(path46.join(plansDir, planFileName), planContent);
|
|
39048
39248
|
}
|
|
39049
39249
|
resolveServices(repos) {
|
|
39050
39250
|
const services = [];
|
|
@@ -39478,8 +39678,8 @@ import * as http2 from "node:http";
|
|
|
39478
39678
|
|
|
39479
39679
|
// ../core/dist/dashboard/server.js
|
|
39480
39680
|
import * as http from "node:http";
|
|
39481
|
-
import * as
|
|
39482
|
-
import * as
|
|
39681
|
+
import * as fs47 from "node:fs";
|
|
39682
|
+
import * as path47 from "node:path";
|
|
39483
39683
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
39484
39684
|
|
|
39485
39685
|
// ../core/dist/dashboard/serialize.js
|
|
@@ -39814,7 +40014,7 @@ function notFound(res) {
|
|
|
39814
40014
|
}
|
|
39815
40015
|
function openThoughtStore(workspacePath) {
|
|
39816
40016
|
const dbPath = getWorldDbPath(workspacePath);
|
|
39817
|
-
if (!
|
|
40017
|
+
if (!fs47.existsSync(dbPath))
|
|
39818
40018
|
return null;
|
|
39819
40019
|
return new ThoughtLocalStore(dbPath);
|
|
39820
40020
|
}
|
|
@@ -39985,13 +40185,13 @@ function findSessionInWorld(registry2, sessionId) {
|
|
|
39985
40185
|
}
|
|
39986
40186
|
function createDashboardServer(opts) {
|
|
39987
40187
|
const { port: port2, registry: registry2 } = opts;
|
|
39988
|
-
const thisDir =
|
|
39989
|
-
const defaultPublicDir =
|
|
40188
|
+
const thisDir = path47.dirname(fileURLToPath3(import.meta.url));
|
|
40189
|
+
const defaultPublicDir = path47.resolve(thisDir, "../../../control-plane/public");
|
|
39990
40190
|
const publicDir = opts.publicDir ?? defaultPublicDir;
|
|
39991
|
-
let hasPublicDir =
|
|
40191
|
+
let hasPublicDir = fs47.existsSync(publicDir);
|
|
39992
40192
|
const server = http.createServer((req, res) => {
|
|
39993
40193
|
if (!hasPublicDir) {
|
|
39994
|
-
hasPublicDir =
|
|
40194
|
+
hasPublicDir = fs47.existsSync(publicDir);
|
|
39995
40195
|
}
|
|
39996
40196
|
const host = req.headers.host ?? `localhost:${port2}`;
|
|
39997
40197
|
const url2 = new URL(req.url ?? "/", `http://${host}`);
|
|
@@ -40265,22 +40465,22 @@ function createDashboardServer(opts) {
|
|
|
40265
40465
|
res.end(`<html><body style="font-family:system-ui;padding:2rem"><h1>Olam Dashboard</h1><p>The React app has not been built yet.</p><p>Run <code>npm run build:app</code> in <code>packages/control-plane</code> to build it.</p><p>API routes are available at <code>/api/*</code>.</p></body></html>`);
|
|
40266
40466
|
return;
|
|
40267
40467
|
}
|
|
40268
|
-
let filePath =
|
|
40468
|
+
let filePath = path47.join(publicDir, pathname === "/" ? "index.html" : pathname);
|
|
40269
40469
|
if (!filePath.startsWith(publicDir)) {
|
|
40270
40470
|
notFound(res);
|
|
40271
40471
|
return;
|
|
40272
40472
|
}
|
|
40273
|
-
if (
|
|
40274
|
-
const ext =
|
|
40473
|
+
if (fs47.existsSync(filePath) && fs47.statSync(filePath).isFile()) {
|
|
40474
|
+
const ext = path47.extname(filePath);
|
|
40275
40475
|
const contentType = MIME[ext] ?? "application/octet-stream";
|
|
40276
40476
|
res.writeHead(200, { "Content-Type": contentType });
|
|
40277
|
-
|
|
40477
|
+
fs47.createReadStream(filePath).pipe(res);
|
|
40278
40478
|
return;
|
|
40279
40479
|
}
|
|
40280
|
-
filePath =
|
|
40281
|
-
if (
|
|
40480
|
+
filePath = path47.join(publicDir, "index.html");
|
|
40481
|
+
if (fs47.existsSync(filePath)) {
|
|
40282
40482
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
40283
|
-
|
|
40483
|
+
fs47.createReadStream(filePath).pipe(res);
|
|
40284
40484
|
return;
|
|
40285
40485
|
}
|
|
40286
40486
|
notFound(res);
|
|
@@ -40290,17 +40490,17 @@ function createDashboardServer(opts) {
|
|
|
40290
40490
|
}
|
|
40291
40491
|
|
|
40292
40492
|
// ../core/dist/dashboard/state.js
|
|
40293
|
-
import * as
|
|
40493
|
+
import * as fs48 from "node:fs";
|
|
40294
40494
|
import * as os27 from "node:os";
|
|
40295
|
-
import * as
|
|
40296
|
-
var STATE_PATH =
|
|
40495
|
+
import * as path48 from "node:path";
|
|
40496
|
+
var STATE_PATH = path48.join(os27.homedir(), ".olam", "dashboard.json");
|
|
40297
40497
|
function saveDashboardState(state) {
|
|
40298
|
-
|
|
40299
|
-
|
|
40498
|
+
fs48.mkdirSync(path48.dirname(STATE_PATH), { recursive: true });
|
|
40499
|
+
fs48.writeFileSync(STATE_PATH, JSON.stringify(state, null, 2));
|
|
40300
40500
|
}
|
|
40301
40501
|
function loadDashboardState() {
|
|
40302
40502
|
try {
|
|
40303
|
-
const raw =
|
|
40503
|
+
const raw = fs48.readFileSync(STATE_PATH, "utf-8");
|
|
40304
40504
|
return JSON.parse(raw);
|
|
40305
40505
|
} catch {
|
|
40306
40506
|
return null;
|
|
@@ -40308,7 +40508,7 @@ function loadDashboardState() {
|
|
|
40308
40508
|
}
|
|
40309
40509
|
function clearDashboardState() {
|
|
40310
40510
|
try {
|
|
40311
|
-
|
|
40511
|
+
fs48.unlinkSync(STATE_PATH);
|
|
40312
40512
|
} catch {
|
|
40313
40513
|
}
|
|
40314
40514
|
}
|
|
@@ -40588,8 +40788,8 @@ var PleriClient = class {
|
|
|
40588
40788
|
};
|
|
40589
40789
|
|
|
40590
40790
|
// ../mcp-server/src/env-loader.ts
|
|
40591
|
-
import { readFileSync as
|
|
40592
|
-
import { join as
|
|
40791
|
+
import { readFileSync as readFileSync37, existsSync as existsSync45, statSync as statSync14 } from "node:fs";
|
|
40792
|
+
import { join as join49, dirname as dirname28, resolve as resolve13 } from "node:path";
|
|
40593
40793
|
var PROJECT_MARKERS = [
|
|
40594
40794
|
".olam/config.yaml",
|
|
40595
40795
|
".olam/config.yml",
|
|
@@ -40601,12 +40801,12 @@ function findProjectRoot2(startDir) {
|
|
|
40601
40801
|
const root = resolve13("/");
|
|
40602
40802
|
while (true) {
|
|
40603
40803
|
for (const marker of PROJECT_MARKERS) {
|
|
40604
|
-
if (existsSync45(
|
|
40804
|
+
if (existsSync45(join49(dir, marker))) return dir;
|
|
40605
40805
|
}
|
|
40606
|
-
const pkg =
|
|
40806
|
+
const pkg = join49(dir, "package.json");
|
|
40607
40807
|
if (existsSync45(pkg)) {
|
|
40608
40808
|
try {
|
|
40609
|
-
const json = JSON.parse(
|
|
40809
|
+
const json = JSON.parse(readFileSync37(pkg, "utf8"));
|
|
40610
40810
|
const isOlamWorkspace = typeof json.name === "string" && json.name.startsWith("@olam/");
|
|
40611
40811
|
const hasOlamDep = json.dependencies && Object.keys(json.dependencies).some((k) => k.startsWith("@olam/")) || json.devDependencies && Object.keys(json.devDependencies).some((k) => k.startsWith("@olam/"));
|
|
40612
40812
|
if (isOlamWorkspace || hasOlamDep) return dir;
|
|
@@ -40618,9 +40818,9 @@ function findProjectRoot2(startDir) {
|
|
|
40618
40818
|
dir = parent;
|
|
40619
40819
|
}
|
|
40620
40820
|
}
|
|
40621
|
-
function parseEnvFile(
|
|
40821
|
+
function parseEnvFile(path49) {
|
|
40622
40822
|
const out = {};
|
|
40623
|
-
const raw =
|
|
40823
|
+
const raw = readFileSync37(path49, "utf8");
|
|
40624
40824
|
for (const line of raw.split(/\r?\n/)) {
|
|
40625
40825
|
const trimmed = line.trim();
|
|
40626
40826
|
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
@@ -40643,7 +40843,7 @@ function loadProjectEnv(startDir = process.cwd()) {
|
|
|
40643
40843
|
const filesRead = [];
|
|
40644
40844
|
const merged = {};
|
|
40645
40845
|
for (const name of [".env", ".env.local"]) {
|
|
40646
|
-
const p =
|
|
40846
|
+
const p = join49(root, name);
|
|
40647
40847
|
if (existsSync45(p) && statSync14(p).isFile()) {
|
|
40648
40848
|
Object.assign(merged, parseEnvFile(p));
|
|
40649
40849
|
filesRead.push(p);
|