create-egregore 0.21.0-runtime-mvp.24 → 0.21.0-runtime-mvp.25
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/assets/egregore-launcher.js +37 -12
- package/package.json +1 -1
- package/runtime/claude/.claude/skills/save/SKILL.md +4 -11
- package/runtime/claude/bin/agent.sh +8 -0
- package/runtime/claude/bin/runtime-upgrade.sh +3 -1
- package/runtime/claude/egregore_runtime/runtime.py +5 -8
- package/runtime/codex/.codex/skills/save/SKILL.md +4 -7
- package/runtime/codex/bin/agent.sh +8 -0
- package/runtime/codex/bin/runtime-upgrade.sh +3 -1
- package/runtime/codex/egregore_runtime/runtime.py +5 -8
- package/runtime/pi/.codex/skills/save/SKILL.md +4 -7
- package/runtime/pi/bin/agent.sh +8 -0
- package/runtime/pi/bin/runtime-upgrade.sh +3 -1
- package/runtime/pi/egregore_runtime/runtime.py +5 -8
- package/runtime/prime/.codex/skills/save/SKILL.md +4 -7
- package/runtime/prime/bin/agent.sh +8 -0
- package/runtime/prime/bin/runtime-upgrade.sh +3 -1
- package/runtime/prime/egregore_runtime/runtime.py +5 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// egregore-launcher-version: 0.21.0-runtime-mvp.
|
|
2
|
+
// egregore-launcher-version: 0.21.0-runtime-mvp.25
|
|
3
3
|
//
|
|
4
4
|
// egregore — launch and browse Egregore instances from your terminal.
|
|
5
5
|
// Installed by create-egregore. Reads ~/.egregore/instances.json.
|
|
@@ -35,7 +35,7 @@ const crypto = require("node:crypto");
|
|
|
35
35
|
const { spawnSync, spawn } = require("node:child_process");
|
|
36
36
|
const readline = require("node:readline");
|
|
37
37
|
|
|
38
|
-
const VERSION = "0.21.0-runtime-mvp.
|
|
38
|
+
const VERSION = "0.21.0-runtime-mvp.25";
|
|
39
39
|
const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
|
|
40
40
|
const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
|
|
41
41
|
const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
|
|
@@ -1288,7 +1288,19 @@ function compareReleaseVersions(a, b) {
|
|
|
1288
1288
|
if (left.prerelease === right.prerelease) return 0;
|
|
1289
1289
|
if (!left.prerelease) return 1;
|
|
1290
1290
|
if (!right.prerelease) return -1;
|
|
1291
|
-
|
|
1291
|
+
const leftIds = left.prerelease.split(".");
|
|
1292
|
+
const rightIds = right.prerelease.split(".");
|
|
1293
|
+
for (let i = 0; i < Math.max(leftIds.length, rightIds.length); i++) {
|
|
1294
|
+
if (leftIds[i] === undefined) return -1;
|
|
1295
|
+
if (rightIds[i] === undefined) return 1;
|
|
1296
|
+
if (leftIds[i] === rightIds[i]) continue;
|
|
1297
|
+
const leftNumeric = /^\d+$/.test(leftIds[i]);
|
|
1298
|
+
const rightNumeric = /^\d+$/.test(rightIds[i]);
|
|
1299
|
+
if (leftNumeric && rightNumeric) return BigInt(leftIds[i]) > BigInt(rightIds[i]) ? 1 : -1;
|
|
1300
|
+
if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
|
|
1301
|
+
return leftIds[i] > rightIds[i] ? 1 : -1;
|
|
1302
|
+
}
|
|
1303
|
+
return 0;
|
|
1292
1304
|
}
|
|
1293
1305
|
|
|
1294
1306
|
function cliUpdateState(latest) {
|
|
@@ -2353,13 +2365,20 @@ function resolveUpgradeBridge(inst) {
|
|
|
2353
2365
|
return null;
|
|
2354
2366
|
}
|
|
2355
2367
|
|
|
2368
|
+
// Snapshot the bridge before starting Bash: older instances still have a
|
|
2369
|
+
// non-exec bridge that activation overwrites while its shell is running.
|
|
2370
|
+
// Keep $0 and all arguments intact for root resolution and exact forwarding.
|
|
2371
|
+
function upgradeBridgeArgs(bridge, args) {
|
|
2372
|
+
return ["-c", fs.readFileSync(bridge.script, "utf-8"), bridge.script, ...args];
|
|
2373
|
+
}
|
|
2374
|
+
|
|
2356
2375
|
function runUpgrade(inst, args, timeout = 60000) {
|
|
2357
2376
|
const bridge = resolveUpgradeBridge(inst);
|
|
2358
2377
|
if (!bridge) {
|
|
2359
2378
|
return { status: 127, stdout: "", stderr: "Runtime update is unavailable — no upgrade engine in this egregore or the installed launcher package.\n", missing: true };
|
|
2360
2379
|
}
|
|
2361
2380
|
try {
|
|
2362
|
-
return spawnSync("bash",
|
|
2381
|
+
return spawnSync("bash", upgradeBridgeArgs(bridge, args), { cwd: inst.path, stdio: "pipe", encoding: "utf-8", timeout, env: { ...process.env, ...bridge.env } });
|
|
2363
2382
|
} catch (err) {
|
|
2364
2383
|
return { status: 1, stdout: "", stderr: String(err) };
|
|
2365
2384
|
}
|
|
@@ -2502,7 +2521,7 @@ function upgradeStatusAsync(inst, cb) {
|
|
|
2502
2521
|
if (!bridge) return cb({ status: "unavailable", failure: { message: "No Runtime update engine is installed" } });
|
|
2503
2522
|
let buf = ""; let err = "";
|
|
2504
2523
|
try {
|
|
2505
|
-
const child = spawn("bash",
|
|
2524
|
+
const child = spawn("bash", upgradeBridgeArgs(bridge, ["status"]), { cwd: inst.path, stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, ...bridge.env } });
|
|
2506
2525
|
child.stdout.on("data", (d) => { buf += d; });
|
|
2507
2526
|
child.stderr.on("data", (d) => { err += d; });
|
|
2508
2527
|
child.on("close", (code) => {
|
|
@@ -2639,12 +2658,18 @@ const UPGRADE_STATUS_LABEL = {
|
|
|
2639
2658
|
// Settings-row truth for the Runtime update line. The row must say outright
|
|
2640
2659
|
// whether this egregore runs the new Runtime — "no update staged" is
|
|
2641
2660
|
// transaction state, not the condition the user needs to see.
|
|
2661
|
+
function runtimeUpdateAvailable(st, candidate) {
|
|
2662
|
+
return st?.status === "active"
|
|
2663
|
+
&& RUNTIME_MVP_VERSION_RE.test(candidate || "")
|
|
2664
|
+
&& compareReleaseVersions(candidate, st.active_version) > 0;
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2642
2667
|
function runtimeUpdateRowValue(st, candidate) {
|
|
2643
2668
|
if (st === undefined) return `${DIM}checking…${RESET}`;
|
|
2644
2669
|
if (st === null) return `${DIM}unavailable${RESET}`;
|
|
2645
2670
|
if (st.status === "active") {
|
|
2646
2671
|
const v = st.active_version || "?";
|
|
2647
|
-
if (
|
|
2672
|
+
if (runtimeUpdateAvailable(st, candidate)) return `${v} active ${YELLOW}· update available ${candidate}${RESET}`;
|
|
2648
2673
|
return `${GREEN}${v} active${RESET}${candidate ? `${DIM} · up to date${RESET}` : ""}`;
|
|
2649
2674
|
}
|
|
2650
2675
|
if (st.status === "unavailable") return `${YELLOW}update unavailable${RESET}`;
|
|
@@ -2682,8 +2707,10 @@ function formatUpgradeLines(inst, st, { candidate = "", retrieval = null } = {})
|
|
|
2682
2707
|
lines.push(`Location: ${inst.path}`);
|
|
2683
2708
|
lines.push("");
|
|
2684
2709
|
const activeLabel = d.active_version ? `${d.active_version} active` : "not yet activated here";
|
|
2685
|
-
|
|
2686
|
-
|
|
2710
|
+
const candidateLabel = d.status === "active"
|
|
2711
|
+
? (runtimeUpdateAvailable(d, candidate) ? ` → candidate ${candidate} available` : "")
|
|
2712
|
+
: (d.candidate_version ? ` → candidate ${d.candidate_version}` : candidate ? ` → candidate ${candidate} available` : "");
|
|
2713
|
+
lines.push(`Runtime: ${activeLabel}${candidateLabel}`);
|
|
2687
2714
|
lines.push(`Status: ${UPGRADE_STATUS_LABEL[d.status] || d.status}`);
|
|
2688
2715
|
if (d.candidate_digest) lines.push(`Package digest: sha256 ${String(d.candidate_digest).slice(0, 16)}…`);
|
|
2689
2716
|
// A recorded failure only needs attention while the transaction is stuck
|
|
@@ -3161,7 +3188,7 @@ function renderUpgradePanel({ inst, data, candidate, retrieval, mode, notice, wi
|
|
|
3161
3188
|
if (notice) lines.push(boxLine(notice, innerWidth, margin));
|
|
3162
3189
|
const keys = [];
|
|
3163
3190
|
if (!status || status === "none" || ["pending", "failed", "interrupted", "cancelled", "rolled-back"].includes(status)) keys.push(`${BOLD}p${RESET}${DIM} prepare${RESET}`);
|
|
3164
|
-
if (
|
|
3191
|
+
if (runtimeUpdateAvailable(data, candidate)) keys.push(`${BOLD}p${RESET}${DIM} prepare update${RESET}`);
|
|
3165
3192
|
if (status === "ready-to-activate") keys.push(`${BOLD}a${RESET}${DIM} activate${RESET}`);
|
|
3166
3193
|
if (status === "preparing") keys.push(`${BOLD}c${RESET}${DIM} cancel${RESET}`);
|
|
3167
3194
|
if (status === "active") keys.push(`${BOLD}r${RESET}${DIM} roll back${RESET}`);
|
|
@@ -3924,9 +3951,7 @@ async function browser(args = {}) {
|
|
|
3924
3951
|
render(); return;
|
|
3925
3952
|
}
|
|
3926
3953
|
const status = state.upgradeData && state.upgradeData.status;
|
|
3927
|
-
const activeUpdatable =
|
|
3928
|
-
&& state.upgradeCandidate
|
|
3929
|
-
&& state.upgradeCandidate !== (state.upgradeData && state.upgradeData.active_version);
|
|
3954
|
+
const activeUpdatable = runtimeUpdateAvailable(state.upgradeData, state.upgradeCandidate);
|
|
3930
3955
|
if (chunk === "p" && (!status || activeUpdatable || ["none", "pending", "failed", "interrupted", "cancelled", "rolled-back"].includes(status))) {
|
|
3931
3956
|
const staged = state.upgradeData
|
|
3932
3957
|
&& !["none", "cancelled", "rolled-back", "active"].includes(status)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-egregore",
|
|
3
|
-
"version": "0.21.0-runtime-mvp.
|
|
3
|
+
"version": "0.21.0-runtime-mvp.25",
|
|
4
4
|
"description": "Set up Egregore for your team in one command — installs the egregore launcher and your choice of Claude Code, Codex, or Pi.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bin": {
|
|
@@ -36,17 +36,10 @@ BASE=$(bash -c 'SCRIPT_DIR="$PWD"; CONFIG="$PWD/egregore.json"; . "$PWD/bin/lib/
|
|
|
36
36
|
|
|
37
37
|
Stop before mutation if it cannot be resolved.
|
|
38
38
|
|
|
39
|
-
3.
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
if [ -f bin/capability-distribution.mjs ] && [ -f capability-distribution.json ]; then
|
|
45
|
-
bash bin/node-run.sh bin/capability-distribution.mjs validate --root .
|
|
46
|
-
bash bin/node-run.sh bin/capability-distribution.mjs changes --root . --base "origin/$BASE" --json
|
|
47
|
-
bash bin/node-run.sh bin/capability-distribution.mjs runtime-skill-audit --root . --strict-contract
|
|
48
|
-
fi
|
|
49
|
-
```
|
|
39
|
+
3. The shared `bin/agent.sh save` preflight runs distribution validation,
|
|
40
|
+
the change report, and the strict Runtime-skill audit before any memory or
|
|
41
|
+
project mutation. Both engine and registry must exist; installed public
|
|
42
|
+
instances intentionally omit the development engine.
|
|
50
43
|
|
|
51
44
|
Ask one placement question only for a genuinely new/unclassified component or
|
|
52
45
|
an explicit placement change. Ordinary edits to an existing component do not
|
|
@@ -397,6 +397,14 @@ cmd_save() {
|
|
|
397
397
|
[ -n "$message" ] || message="chore(save): $topic"
|
|
398
398
|
base="$(resolve_base_branch)" || die "save stopped before Git changes"
|
|
399
399
|
|
|
400
|
+
# Shared invariant across harnesses, before memory or project mutations.
|
|
401
|
+
# Installed public instances intentionally omit the development engine.
|
|
402
|
+
if [ -f "$SCRIPT_DIR/bin/capability-distribution.mjs" ] && [ -f "$SCRIPT_DIR/capability-distribution.json" ]; then
|
|
403
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" validate --root "$SCRIPT_DIR" || die "distribution validation failed"
|
|
404
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" changes --root "$SCRIPT_DIR" --base "origin/$base" --json || die "distribution change check failed"
|
|
405
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" runtime-skill-audit --root "$SCRIPT_DIR" --strict-contract || die "runtime skill contract failed"
|
|
406
|
+
fi
|
|
407
|
+
|
|
400
408
|
if [ -d "$MEMORY_DIR" ]; then
|
|
401
409
|
save_memory "$message" "."
|
|
402
410
|
echo "memory: synced"
|
|
@@ -22,10 +22,12 @@ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
22
22
|
# tree, while the target instance is set explicitly — never inferred.
|
|
23
23
|
INSTANCE_ROOT="${EGREGORE_INSTANCE_ROOT:-$SCRIPT_DIR}"
|
|
24
24
|
|
|
25
|
+
# Activation and rollback can replace this script. Hand off the process so
|
|
26
|
+
# Bash never resumes reading changed bytes after the Runtime returns.
|
|
25
27
|
_runtime() {
|
|
26
28
|
EGREGORE_ROOT="$INSTANCE_ROOT" \
|
|
27
29
|
PYTHONPATH="$SCRIPT_DIR${PYTHONPATH:+:$PYTHONPATH}" \
|
|
28
|
-
python3 -m egregore_runtime.harness_cli "$@"
|
|
30
|
+
exec python3 -m egregore_runtime.harness_cli "$@"
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
_ensure_identity() {
|
|
@@ -230,15 +230,12 @@ class EgregoreRuntime:
|
|
|
230
230
|
"this document is admin-marked; Egregore serves it to organization admins only"
|
|
231
231
|
)
|
|
232
232
|
stable_artifact_id = canonical_artifact_id(content, path)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
stable_decision = self.authorize(actor, Permission.READ, (stable_artifact_id,))
|
|
234
|
+
if not stable_decision.allowed:
|
|
235
|
+
raise AuthorizationDenied(
|
|
236
|
+
"canonical artifact identity is outside the actor read scope"
|
|
236
237
|
)
|
|
237
|
-
|
|
238
|
-
raise AuthorizationDenied(
|
|
239
|
-
"canonical artifact identity is outside the actor read scope"
|
|
240
|
-
)
|
|
241
|
-
artifact_id = stable_artifact_id
|
|
238
|
+
artifact_id = stable_artifact_id
|
|
242
239
|
try:
|
|
243
240
|
self.telemetry.emit(
|
|
244
241
|
TelemetryEvent(
|
|
@@ -42,13 +42,10 @@ esac
|
|
|
42
42
|
- Stop with "everything is already saved" only when there are no repo or
|
|
43
43
|
memory changes and either the branch has no commits to integrate
|
|
44
44
|
(`AHEAD=0`) or an open integration PR already exists.
|
|
45
|
-
4.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
bash bin/node-run.sh bin/capability-distribution.mjs validate --root .
|
|
50
|
-
bash bin/node-run.sh bin/capability-distribution.mjs changes --root . --base "origin/$BASE" --json
|
|
51
|
-
```
|
|
45
|
+
4. The shared `bin/agent.sh save` preflight runs distribution validation,
|
|
46
|
+
the change report, and the strict Runtime-skill audit before any memory or
|
|
47
|
+
project mutation. It runs only when both the registry and development
|
|
48
|
+
engine exist; public installed instances intentionally omit that engine.
|
|
52
49
|
|
|
53
50
|
Inspect the diff as well as the receipt. Ask when this work introduces a new
|
|
54
51
|
or unclassified Egregore component, or changes a component's placement
|
|
@@ -397,6 +397,14 @@ cmd_save() {
|
|
|
397
397
|
[ -n "$message" ] || message="chore(save): $topic"
|
|
398
398
|
base="$(resolve_base_branch)" || die "save stopped before Git changes"
|
|
399
399
|
|
|
400
|
+
# Shared invariant across harnesses, before memory or project mutations.
|
|
401
|
+
# Installed public instances intentionally omit the development engine.
|
|
402
|
+
if [ -f "$SCRIPT_DIR/bin/capability-distribution.mjs" ] && [ -f "$SCRIPT_DIR/capability-distribution.json" ]; then
|
|
403
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" validate --root "$SCRIPT_DIR" || die "distribution validation failed"
|
|
404
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" changes --root "$SCRIPT_DIR" --base "origin/$base" --json || die "distribution change check failed"
|
|
405
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" runtime-skill-audit --root "$SCRIPT_DIR" --strict-contract || die "runtime skill contract failed"
|
|
406
|
+
fi
|
|
407
|
+
|
|
400
408
|
if [ -d "$MEMORY_DIR" ]; then
|
|
401
409
|
save_memory "$message" "."
|
|
402
410
|
echo "memory: synced"
|
|
@@ -22,10 +22,12 @@ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
22
22
|
# tree, while the target instance is set explicitly — never inferred.
|
|
23
23
|
INSTANCE_ROOT="${EGREGORE_INSTANCE_ROOT:-$SCRIPT_DIR}"
|
|
24
24
|
|
|
25
|
+
# Activation and rollback can replace this script. Hand off the process so
|
|
26
|
+
# Bash never resumes reading changed bytes after the Runtime returns.
|
|
25
27
|
_runtime() {
|
|
26
28
|
EGREGORE_ROOT="$INSTANCE_ROOT" \
|
|
27
29
|
PYTHONPATH="$SCRIPT_DIR${PYTHONPATH:+:$PYTHONPATH}" \
|
|
28
|
-
python3 -m egregore_runtime.harness_cli "$@"
|
|
30
|
+
exec python3 -m egregore_runtime.harness_cli "$@"
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
_ensure_identity() {
|
|
@@ -230,15 +230,12 @@ class EgregoreRuntime:
|
|
|
230
230
|
"this document is admin-marked; Egregore serves it to organization admins only"
|
|
231
231
|
)
|
|
232
232
|
stable_artifact_id = canonical_artifact_id(content, path)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
stable_decision = self.authorize(actor, Permission.READ, (stable_artifact_id,))
|
|
234
|
+
if not stable_decision.allowed:
|
|
235
|
+
raise AuthorizationDenied(
|
|
236
|
+
"canonical artifact identity is outside the actor read scope"
|
|
236
237
|
)
|
|
237
|
-
|
|
238
|
-
raise AuthorizationDenied(
|
|
239
|
-
"canonical artifact identity is outside the actor read scope"
|
|
240
|
-
)
|
|
241
|
-
artifact_id = stable_artifact_id
|
|
238
|
+
artifact_id = stable_artifact_id
|
|
242
239
|
try:
|
|
243
240
|
self.telemetry.emit(
|
|
244
241
|
TelemetryEvent(
|
|
@@ -42,13 +42,10 @@ esac
|
|
|
42
42
|
- Stop with "everything is already saved" only when there are no repo or
|
|
43
43
|
memory changes and either the branch has no commits to integrate
|
|
44
44
|
(`AHEAD=0`) or an open integration PR already exists.
|
|
45
|
-
4.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
bash bin/node-run.sh bin/capability-distribution.mjs validate --root .
|
|
50
|
-
bash bin/node-run.sh bin/capability-distribution.mjs changes --root . --base "origin/$BASE" --json
|
|
51
|
-
```
|
|
45
|
+
4. The shared `bin/agent.sh save` preflight runs distribution validation,
|
|
46
|
+
the change report, and the strict Runtime-skill audit before any memory or
|
|
47
|
+
project mutation. It runs only when both the registry and development
|
|
48
|
+
engine exist; public installed instances intentionally omit that engine.
|
|
52
49
|
|
|
53
50
|
Inspect the diff as well as the receipt. Ask when this work introduces a new
|
|
54
51
|
or unclassified Egregore component, or changes a component's placement
|
package/runtime/pi/bin/agent.sh
CHANGED
|
@@ -397,6 +397,14 @@ cmd_save() {
|
|
|
397
397
|
[ -n "$message" ] || message="chore(save): $topic"
|
|
398
398
|
base="$(resolve_base_branch)" || die "save stopped before Git changes"
|
|
399
399
|
|
|
400
|
+
# Shared invariant across harnesses, before memory or project mutations.
|
|
401
|
+
# Installed public instances intentionally omit the development engine.
|
|
402
|
+
if [ -f "$SCRIPT_DIR/bin/capability-distribution.mjs" ] && [ -f "$SCRIPT_DIR/capability-distribution.json" ]; then
|
|
403
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" validate --root "$SCRIPT_DIR" || die "distribution validation failed"
|
|
404
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" changes --root "$SCRIPT_DIR" --base "origin/$base" --json || die "distribution change check failed"
|
|
405
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" runtime-skill-audit --root "$SCRIPT_DIR" --strict-contract || die "runtime skill contract failed"
|
|
406
|
+
fi
|
|
407
|
+
|
|
400
408
|
if [ -d "$MEMORY_DIR" ]; then
|
|
401
409
|
save_memory "$message" "."
|
|
402
410
|
echo "memory: synced"
|
|
@@ -22,10 +22,12 @@ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
22
22
|
# tree, while the target instance is set explicitly — never inferred.
|
|
23
23
|
INSTANCE_ROOT="${EGREGORE_INSTANCE_ROOT:-$SCRIPT_DIR}"
|
|
24
24
|
|
|
25
|
+
# Activation and rollback can replace this script. Hand off the process so
|
|
26
|
+
# Bash never resumes reading changed bytes after the Runtime returns.
|
|
25
27
|
_runtime() {
|
|
26
28
|
EGREGORE_ROOT="$INSTANCE_ROOT" \
|
|
27
29
|
PYTHONPATH="$SCRIPT_DIR${PYTHONPATH:+:$PYTHONPATH}" \
|
|
28
|
-
python3 -m egregore_runtime.harness_cli "$@"
|
|
30
|
+
exec python3 -m egregore_runtime.harness_cli "$@"
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
_ensure_identity() {
|
|
@@ -230,15 +230,12 @@ class EgregoreRuntime:
|
|
|
230
230
|
"this document is admin-marked; Egregore serves it to organization admins only"
|
|
231
231
|
)
|
|
232
232
|
stable_artifact_id = canonical_artifact_id(content, path)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
stable_decision = self.authorize(actor, Permission.READ, (stable_artifact_id,))
|
|
234
|
+
if not stable_decision.allowed:
|
|
235
|
+
raise AuthorizationDenied(
|
|
236
|
+
"canonical artifact identity is outside the actor read scope"
|
|
236
237
|
)
|
|
237
|
-
|
|
238
|
-
raise AuthorizationDenied(
|
|
239
|
-
"canonical artifact identity is outside the actor read scope"
|
|
240
|
-
)
|
|
241
|
-
artifact_id = stable_artifact_id
|
|
238
|
+
artifact_id = stable_artifact_id
|
|
242
239
|
try:
|
|
243
240
|
self.telemetry.emit(
|
|
244
241
|
TelemetryEvent(
|
|
@@ -42,13 +42,10 @@ esac
|
|
|
42
42
|
- Stop with "everything is already saved" only when there are no repo or
|
|
43
43
|
memory changes and either the branch has no commits to integrate
|
|
44
44
|
(`AHEAD=0`) or an open integration PR already exists.
|
|
45
|
-
4.
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
bash bin/node-run.sh bin/capability-distribution.mjs validate --root .
|
|
50
|
-
bash bin/node-run.sh bin/capability-distribution.mjs changes --root . --base "origin/$BASE" --json
|
|
51
|
-
```
|
|
45
|
+
4. The shared `bin/agent.sh save` preflight runs distribution validation,
|
|
46
|
+
the change report, and the strict Runtime-skill audit before any memory or
|
|
47
|
+
project mutation. It runs only when both the registry and development
|
|
48
|
+
engine exist; public installed instances intentionally omit that engine.
|
|
52
49
|
|
|
53
50
|
Inspect the diff as well as the receipt. Ask when this work introduces a new
|
|
54
51
|
or unclassified Egregore component, or changes a component's placement
|
|
@@ -397,6 +397,14 @@ cmd_save() {
|
|
|
397
397
|
[ -n "$message" ] || message="chore(save): $topic"
|
|
398
398
|
base="$(resolve_base_branch)" || die "save stopped before Git changes"
|
|
399
399
|
|
|
400
|
+
# Shared invariant across harnesses, before memory or project mutations.
|
|
401
|
+
# Installed public instances intentionally omit the development engine.
|
|
402
|
+
if [ -f "$SCRIPT_DIR/bin/capability-distribution.mjs" ] && [ -f "$SCRIPT_DIR/capability-distribution.json" ]; then
|
|
403
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" validate --root "$SCRIPT_DIR" || die "distribution validation failed"
|
|
404
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" changes --root "$SCRIPT_DIR" --base "origin/$base" --json || die "distribution change check failed"
|
|
405
|
+
bash "$SCRIPT_DIR/bin/node-run.sh" "$SCRIPT_DIR/bin/capability-distribution.mjs" runtime-skill-audit --root "$SCRIPT_DIR" --strict-contract || die "runtime skill contract failed"
|
|
406
|
+
fi
|
|
407
|
+
|
|
400
408
|
if [ -d "$MEMORY_DIR" ]; then
|
|
401
409
|
save_memory "$message" "."
|
|
402
410
|
echo "memory: synced"
|
|
@@ -22,10 +22,12 @@ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
22
22
|
# tree, while the target instance is set explicitly — never inferred.
|
|
23
23
|
INSTANCE_ROOT="${EGREGORE_INSTANCE_ROOT:-$SCRIPT_DIR}"
|
|
24
24
|
|
|
25
|
+
# Activation and rollback can replace this script. Hand off the process so
|
|
26
|
+
# Bash never resumes reading changed bytes after the Runtime returns.
|
|
25
27
|
_runtime() {
|
|
26
28
|
EGREGORE_ROOT="$INSTANCE_ROOT" \
|
|
27
29
|
PYTHONPATH="$SCRIPT_DIR${PYTHONPATH:+:$PYTHONPATH}" \
|
|
28
|
-
python3 -m egregore_runtime.harness_cli "$@"
|
|
30
|
+
exec python3 -m egregore_runtime.harness_cli "$@"
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
_ensure_identity() {
|
|
@@ -230,15 +230,12 @@ class EgregoreRuntime:
|
|
|
230
230
|
"this document is admin-marked; Egregore serves it to organization admins only"
|
|
231
231
|
)
|
|
232
232
|
stable_artifact_id = canonical_artifact_id(content, path)
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
233
|
+
stable_decision = self.authorize(actor, Permission.READ, (stable_artifact_id,))
|
|
234
|
+
if not stable_decision.allowed:
|
|
235
|
+
raise AuthorizationDenied(
|
|
236
|
+
"canonical artifact identity is outside the actor read scope"
|
|
236
237
|
)
|
|
237
|
-
|
|
238
|
-
raise AuthorizationDenied(
|
|
239
|
-
"canonical artifact identity is outside the actor read scope"
|
|
240
|
-
)
|
|
241
|
-
artifact_id = stable_artifact_id
|
|
238
|
+
artifact_id = stable_artifact_id
|
|
242
239
|
try:
|
|
243
240
|
self.telemetry.emit(
|
|
244
241
|
TelemetryEvent(
|