create-egregore 0.19.13 → 0.19.15
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 +76 -27
- package/assets/egregore-launcher.sh +7 -3
- package/lib/setup.js +94 -14
- package/package.json +2 -2
- package/runtime/codex/.codex/hooks/search-hint.js +4 -2
- package/runtime/codex/.codex/skills/search/SKILL.md +28 -5
- package/runtime/codex/.codex/spec-manifest.json +7 -1
- package/runtime/codex/AGENTS.md +50 -3
- package/runtime/codex/bin/codex-render-spec.mjs +1 -0
- package/runtime/codex/bin/search.sh +240 -0
- package/runtime/codex/manifest.json +1 -0
- package/runtime/pi/.codex/hooks/search-hint.js +4 -2
- package/runtime/pi/.codex/skills/search/SKILL.md +28 -5
- package/runtime/pi/.codex/spec-manifest.json +7 -1
- package/runtime/pi/.pi/APPEND_SYSTEM.md +47 -0
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +50 -3
- package/runtime/pi/bin/codex-render-spec.mjs +1 -0
- package/runtime/pi/bin/search.sh +240 -0
- package/runtime/pi/manifest.json +1 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// egregore-launcher-version: 0.19.
|
|
2
|
+
// egregore-launcher-version: 0.19.15
|
|
3
3
|
//
|
|
4
4
|
// egregore — launch and browse Egregore instances from your terminal.
|
|
5
5
|
// Installed by create-egregore. Reads ~/.egregore/instances.json.
|
|
@@ -33,7 +33,7 @@ const crypto = require("node:crypto");
|
|
|
33
33
|
const { spawnSync, spawn } = require("node:child_process");
|
|
34
34
|
const readline = require("node:readline");
|
|
35
35
|
|
|
36
|
-
const VERSION = "0.19.
|
|
36
|
+
const VERSION = "0.19.15";
|
|
37
37
|
const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
|
|
38
38
|
const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
|
|
39
39
|
const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
|
|
@@ -701,6 +701,24 @@ function installCodexSkills(egregoreDir) {
|
|
|
701
701
|
}
|
|
702
702
|
}
|
|
703
703
|
|
|
704
|
+
function claudeLaunchArgs(egregoreDir) {
|
|
705
|
+
const args = ["start"];
|
|
706
|
+
const memoryLink = path.join(egregoreDir, "memory");
|
|
707
|
+
try {
|
|
708
|
+
const memoryDir = fs.realpathSync(memoryLink);
|
|
709
|
+
if (fs.statSync(memoryDir).isDirectory()) {
|
|
710
|
+
// Egregore memory is intentionally a sibling Git repository. Declare it
|
|
711
|
+
// as part of Claude's workspace so auto mode does not classify normal
|
|
712
|
+
// organizational recall as an unexplained cross-project read.
|
|
713
|
+
args.push("--add-dir", memoryDir);
|
|
714
|
+
}
|
|
715
|
+
} catch {
|
|
716
|
+
// A missing/dangling memory link is diagnosed by session startup. Do not
|
|
717
|
+
// prevent the harness from opening.
|
|
718
|
+
}
|
|
719
|
+
return args;
|
|
720
|
+
}
|
|
721
|
+
|
|
704
722
|
function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
705
723
|
if (runtime === "codex") {
|
|
706
724
|
return [
|
|
@@ -711,7 +729,7 @@ function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
|
711
729
|
];
|
|
712
730
|
}
|
|
713
731
|
if (runtime === "pi") return piTrustArgs();
|
|
714
|
-
return
|
|
732
|
+
return claudeLaunchArgs(egregoreDir);
|
|
715
733
|
}
|
|
716
734
|
|
|
717
735
|
async function launch(inst, runtimeOverride) {
|
|
@@ -1098,14 +1116,14 @@ function cmdCliUpdate(latest) {
|
|
|
1098
1116
|
{ encoding: "utf-8", stdio: ["inherit", "pipe", "pipe"], env: { ...process.env } },
|
|
1099
1117
|
);
|
|
1100
1118
|
if (result.status !== 0) {
|
|
1101
|
-
console.log(`\r [1/2] ${YELLOW}!${RESET} Install failed`);
|
|
1119
|
+
console.log(`\r${ANSI.clearLine} [1/2] ${YELLOW}!${RESET} Install failed`);
|
|
1102
1120
|
const detail = String(result.stderr || result.stdout || "").trim().split("\n").filter(Boolean).pop();
|
|
1103
1121
|
if (detail) console.error(` ${DIM}${detail}${RESET}`);
|
|
1104
1122
|
console.error(` Retry: npx -y ${PUBLIC_NPX_PACKAGE}@${latest} --refresh-launcher\n`);
|
|
1105
1123
|
process.exitCode = 1;
|
|
1106
1124
|
return;
|
|
1107
1125
|
}
|
|
1108
|
-
console.log(`\r [1/2] ${GREEN}✓${RESET} CLI ${latest} installed`);
|
|
1126
|
+
console.log(`\r${ANSI.clearLine} [1/2] ${GREEN}✓${RESET} CLI ${latest} installed`);
|
|
1109
1127
|
|
|
1110
1128
|
if (process.env.EGREGORE_UPDATE_NO_RELAUNCH === "1") {
|
|
1111
1129
|
console.log(` [2/2] ${GREEN}✓${RESET} Ready for the next launch\n`);
|
|
@@ -1250,12 +1268,42 @@ async function cmdConnect(args) {
|
|
|
1250
1268
|
|
|
1251
1269
|
let intentId = activation.intent_id || "";
|
|
1252
1270
|
let connectUrl = activation.connect_url || "";
|
|
1253
|
-
|
|
1271
|
+
let ticketExpiresAt = Number(activation.connect_ticket_expires_at || 0) * 1000;
|
|
1272
|
+
const resumable = ["created", "checkout_pending", "entitled", "provisioning", "backfilling"].includes(
|
|
1273
|
+
activation.status,
|
|
1274
|
+
);
|
|
1275
|
+
if (
|
|
1276
|
+
intentId &&
|
|
1277
|
+
resumable &&
|
|
1278
|
+
(!activation.connect_ticket || !ticketExpiresAt || ticketExpiresAt <= Date.now() + 60_000)
|
|
1279
|
+
) {
|
|
1280
|
+
const refreshed = await connectedApiRequest(
|
|
1281
|
+
githubToken,
|
|
1282
|
+
"POST",
|
|
1283
|
+
`/api/billing/connect/${encodeURIComponent(intentId)}/ticket`,
|
|
1284
|
+
{},
|
|
1285
|
+
);
|
|
1286
|
+
if (refreshed.status !== 200) {
|
|
1287
|
+
die(`could not refresh Connected link: ${connectError(refreshed, `HTTP ${refreshed.status}`)}`);
|
|
1288
|
+
}
|
|
1289
|
+
connectUrl = refreshed.data.connect_url;
|
|
1290
|
+
ticketExpiresAt = Number(refreshed.data.connect_ticket_expires_at || 0) * 1000;
|
|
1291
|
+
persistConnectState(inst, {
|
|
1292
|
+
connect_ticket: refreshed.data.connect_ticket,
|
|
1293
|
+
connect_ticket_expires_at: refreshed.data.connect_ticket_expires_at,
|
|
1294
|
+
connect_url: connectUrl,
|
|
1295
|
+
status: refreshed.data.status || activation.status,
|
|
1296
|
+
});
|
|
1297
|
+
}
|
|
1298
|
+
if (
|
|
1299
|
+
!intentId ||
|
|
1300
|
+
!resumable
|
|
1301
|
+
) {
|
|
1254
1302
|
console.log(` [1/5] ${DIM}Creating connection intent…${RESET}`);
|
|
1255
1303
|
const checkout = await connectedApiRequest(
|
|
1256
1304
|
githubToken,
|
|
1257
1305
|
"POST",
|
|
1258
|
-
"/api/billing/
|
|
1306
|
+
"/api/billing/connect-intents",
|
|
1259
1307
|
{
|
|
1260
1308
|
org_slug: cfg.slug || inst.slug,
|
|
1261
1309
|
plan: "connect",
|
|
@@ -1275,9 +1323,10 @@ async function cmdConnect(args) {
|
|
|
1275
1323
|
connectUrl = checkout.data.connect_url;
|
|
1276
1324
|
persistConnectState(inst, {
|
|
1277
1325
|
intent_id: intentId,
|
|
1278
|
-
|
|
1326
|
+
connect_ticket: checkout.data.connect_ticket,
|
|
1327
|
+
connect_ticket_expires_at: checkout.data.connect_ticket_expires_at,
|
|
1279
1328
|
connect_url: connectUrl,
|
|
1280
|
-
status: "
|
|
1329
|
+
status: checkout.data.status || "created",
|
|
1281
1330
|
});
|
|
1282
1331
|
console.log(` [1/5] ${GREEN}✓${RESET} Connection intent`);
|
|
1283
1332
|
} else {
|
|
@@ -1369,12 +1418,17 @@ async function cmdConnect(args) {
|
|
|
1369
1418
|
let backfillSummary = { replayed: true };
|
|
1370
1419
|
try { backfillSummary = JSON.parse((sync.stdout || "").trim()); } catch {}
|
|
1371
1420
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1421
|
+
let complete;
|
|
1422
|
+
for (let attempt = 0; attempt < 3; attempt += 1) {
|
|
1423
|
+
complete = await connectedApiRequest(
|
|
1424
|
+
githubToken,
|
|
1425
|
+
"POST",
|
|
1426
|
+
`/api/billing/connect/${encodeURIComponent(intentId)}/complete`,
|
|
1427
|
+
{ backfill_summary: backfillSummary },
|
|
1428
|
+
);
|
|
1429
|
+
if (complete.status === 200 || complete.status !== 0) break;
|
|
1430
|
+
await sleep(250 * (attempt + 1));
|
|
1431
|
+
}
|
|
1378
1432
|
if (complete.status !== 200) {
|
|
1379
1433
|
die(`graph replay finished, but activation could not be finalized: ${connectError(complete, `HTTP ${complete.status}`)}`);
|
|
1380
1434
|
}
|
|
@@ -1839,6 +1893,11 @@ function renderHeroPanel({ selected, pv, width, height, countSuffix, filter, fil
|
|
|
1839
1893
|
const top = `${margin}${DIM}┌${"─".repeat(2)}${label}${"─".repeat(Math.max(0, innerWidth - label.length - 2))}┐${RESET}`;
|
|
1840
1894
|
const bottom = `${margin}${DIM}└${"─".repeat(innerWidth)}┘${RESET}`;
|
|
1841
1895
|
const mid = `${margin}${DIM}├${"─".repeat(innerWidth)}┤${RESET}`;
|
|
1896
|
+
const updateBand = cliUpdate?.available
|
|
1897
|
+
? (colorOn
|
|
1898
|
+
? `${margin}${DIM}│${RESET}${E(43)}${E(30)}${pad(` CLI UPDATE AVAILABLE · ${cliUpdate.current} → ${cliUpdate.latest} · ${E(1)}U${E(22)} INSTALL`, innerWidth)}${RESET}${DIM}│${RESET}`
|
|
1899
|
+
: `${margin}│${pad(` CLI UPDATE AVAILABLE · ${cliUpdate.current} → ${cliUpdate.latest} · U INSTALL`, innerWidth)}│`)
|
|
1900
|
+
: null;
|
|
1842
1901
|
const lines = [top];
|
|
1843
1902
|
|
|
1844
1903
|
const title = selected ? `${selected.slug || selected.name || "egregore"}` : "egregore";
|
|
@@ -1879,20 +1938,10 @@ function renderHeroPanel({ selected, pv, width, height, countSuffix, filter, fil
|
|
|
1879
1938
|
lines.push(boxLine(`${BOLD}${CYAN}EGREGORE${RESET} ${DIM}v${VERSION} · ${countSuffix} · ${filterText}${RESET}`, innerWidth, margin));
|
|
1880
1939
|
}
|
|
1881
1940
|
lines.push(emptyBoxLine(innerWidth, margin));
|
|
1882
|
-
lines.push(mid);
|
|
1941
|
+
lines.push(updateBand || mid);
|
|
1883
1942
|
lines.push(boxLine(`${BOLD}${title}${RESET} ${DIM}· ${org} · ${runtime} · ${countSuffix} · ${filterText}${RESET}`, innerWidth, margin));
|
|
1884
1943
|
lines.push(boxLine(`${DIM}skills${RESET} ${skillStatus}`, innerWidth, margin));
|
|
1885
|
-
|
|
1886
|
-
lines.push(boxLine(
|
|
1887
|
-
`${YELLOW}→ CLI update ${cliUpdate.latest} available${RESET} ${DIM}· installed ${cliUpdate.current} · ${RESET}${BOLD}U${RESET}${DIM} install${RESET}`,
|
|
1888
|
-
innerWidth,
|
|
1889
|
-
margin,
|
|
1890
|
-
));
|
|
1891
|
-
} else {
|
|
1892
|
-
// Reserve the status row so the list never jumps when the async version
|
|
1893
|
-
// check resolves and reveals an available release.
|
|
1894
|
-
lines.push(emptyBoxLine(innerWidth, margin));
|
|
1895
|
-
}
|
|
1944
|
+
lines.push(emptyBoxLine(innerWidth, margin));
|
|
1896
1945
|
|
|
1897
1946
|
const sigilWidth = Math.max(...EGREGORE_SIGIL.map((line) => line.length));
|
|
1898
1947
|
const twoColumn = bodyWidth >= 68;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
# egregore-launcher-version: 0.4.
|
|
2
|
+
# egregore-launcher-version: 0.4.10
|
|
3
3
|
# egregore — launch an Egregore instance in Claude Code.
|
|
4
4
|
# Reads ~/.egregore/instances.json for the registry of installed egregores.
|
|
5
5
|
#
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
set -u
|
|
24
24
|
|
|
25
|
-
VERSION="0.4.
|
|
25
|
+
VERSION="0.4.10"
|
|
26
26
|
REGISTRY="${HOME}/.egregore/instances.json"
|
|
27
27
|
DEFAULT_FILE="${HOME}/.egregore/default"
|
|
28
28
|
|
|
@@ -93,7 +93,11 @@ launch() {
|
|
|
93
93
|
printf ' %s→%s launching %s%s%s ...\n\n' "$DIM" "$RESET" "$BOLD" "$target_slug" "$RESET"
|
|
94
94
|
fi
|
|
95
95
|
cd "$target_path" || die "Could not cd into $target_path"
|
|
96
|
-
|
|
96
|
+
local -a claude_args=("start")
|
|
97
|
+
if [ -d "$target_path/memory" ]; then
|
|
98
|
+
claude_args+=("--add-dir" "$target_path/memory")
|
|
99
|
+
fi
|
|
100
|
+
exec claude "${claude_args[@]}"
|
|
97
101
|
}
|
|
98
102
|
|
|
99
103
|
cmd_ls() {
|
package/lib/setup.js
CHANGED
|
@@ -426,6 +426,15 @@ async function install(data, ui, targetDir, opts = {}) {
|
|
|
426
426
|
ui.success("Linked");
|
|
427
427
|
}
|
|
428
428
|
|
|
429
|
+
// The connected config is required infrastructure, not an optional overlay.
|
|
430
|
+
// A setup race once left develop behind main, so a newly-created work branch
|
|
431
|
+
// could lose egregore.json even though the default branch contained it.
|
|
432
|
+
// Recover that exact file from origin/main when possible, then validate it
|
|
433
|
+
// before writing credentials or registering a launcher.
|
|
434
|
+
if (api_key || data.api_url) {
|
|
435
|
+
ensureConnectedConfig(egregoreDir, data, ui);
|
|
436
|
+
}
|
|
437
|
+
|
|
429
438
|
// 4. Write .env (secrets only — never committed to git)
|
|
430
439
|
ui.step(4, totalSteps, "Writing credentials...");
|
|
431
440
|
const envPath = path.join(egregoreDir, ".env");
|
|
@@ -450,19 +459,7 @@ async function install(data, ui, targetDir, opts = {}) {
|
|
|
450
459
|
fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + "\n");
|
|
451
460
|
try { ensurePersonOnboardingWitness(memoryDir, state); } catch {}
|
|
452
461
|
|
|
453
|
-
// 4c.
|
|
454
|
-
const configPath = path.join(egregoreDir, "egregore.json");
|
|
455
|
-
if (fs.existsSync(configPath)) {
|
|
456
|
-
try {
|
|
457
|
-
const config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
458
|
-
if (!config.mode) {
|
|
459
|
-
config.mode = "connected";
|
|
460
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
461
|
-
}
|
|
462
|
-
} catch {}
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// 4d. Overlay the selected shell-runtime support. Claude Code reads
|
|
462
|
+
// 4c. Overlay the selected shell-runtime support. Claude Code reads
|
|
466
463
|
// CLAUDE.md, not AGENTS.md; overlaying the Codex AGENTS.md/.codex into a Claude
|
|
467
464
|
// workspace gives a wandering agent a competing startup protocol (the
|
|
468
465
|
// xenocracy onboarding regression). Claude joiners keep the cloned repo as-is —
|
|
@@ -584,6 +581,74 @@ async function install(data, ui, targetDir, opts = {}) {
|
|
|
584
581
|
await launchOrInstruct(path.join(base, forkDirName), alias, ui, opts);
|
|
585
582
|
}
|
|
586
583
|
|
|
584
|
+
/**
|
|
585
|
+
* Require and validate the connected instance configuration.
|
|
586
|
+
*
|
|
587
|
+
* If the current branch is missing egregore.json, restore it from origin/main
|
|
588
|
+
* without changing branches or disturbing existing work. A missing/invalid
|
|
589
|
+
* remote config aborts setup before credentials and launcher registration.
|
|
590
|
+
*/
|
|
591
|
+
function ensureConnectedConfig(repoDir, data, ui) {
|
|
592
|
+
const configPath = path.join(repoDir, "egregore.json");
|
|
593
|
+
|
|
594
|
+
if (!fs.existsSync(configPath)) {
|
|
595
|
+
try {
|
|
596
|
+
execFileSync(
|
|
597
|
+
"git",
|
|
598
|
+
["-C", repoDir, "fetch", "origin", "+main:refs/remotes/origin/main"],
|
|
599
|
+
{
|
|
600
|
+
stdio: "pipe", encoding: "utf-8", timeout: 30000,
|
|
601
|
+
},
|
|
602
|
+
);
|
|
603
|
+
const remoteConfig = execFileSync(
|
|
604
|
+
"git",
|
|
605
|
+
["-C", repoDir, "show", "origin/main:egregore.json"],
|
|
606
|
+
{ stdio: "pipe", encoding: "utf-8", timeout: 10000 },
|
|
607
|
+
);
|
|
608
|
+
JSON.parse(remoteConfig);
|
|
609
|
+
fs.writeFileSync(configPath, remoteConfig.endsWith("\n") ? remoteConfig : `${remoteConfig}\n`);
|
|
610
|
+
if (ui && typeof ui.warn === "function") {
|
|
611
|
+
ui.warn("Restored missing egregore.json from origin/main");
|
|
612
|
+
}
|
|
613
|
+
} catch {
|
|
614
|
+
throw new Error(
|
|
615
|
+
"Connected setup is incomplete: egregore.json is missing from this checkout and origin/main. Retry setup from egregore.xyz/setup."
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
let config;
|
|
621
|
+
try {
|
|
622
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
623
|
+
} catch {
|
|
624
|
+
throw new Error("Connected setup is incomplete: egregore.json is not valid JSON.");
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const required = ["org_name", "github_org", "memory_repo", "api_url", "slug"];
|
|
628
|
+
const missing = required.filter((key) => !config[key]);
|
|
629
|
+
if (missing.length) {
|
|
630
|
+
throw new Error(
|
|
631
|
+
`Connected setup is incomplete: egregore.json is missing ${missing.join(", ")}. Retry setup from egregore.xyz/setup.`
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
if (data.slug && config.slug !== data.slug) {
|
|
635
|
+
throw new Error(
|
|
636
|
+
`Connected setup mismatch: expected org ${data.slug}, but egregore.json belongs to ${config.slug}.`
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
if (data.github_org && config.github_org.toLowerCase() !== data.github_org.toLowerCase()) {
|
|
640
|
+
throw new Error(
|
|
641
|
+
`Connected setup mismatch: expected GitHub owner ${data.github_org}, but egregore.json uses ${config.github_org}.`
|
|
642
|
+
);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
if (config.mode !== "connected") {
|
|
646
|
+
config.mode = "connected";
|
|
647
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
648
|
+
}
|
|
649
|
+
return config;
|
|
650
|
+
}
|
|
651
|
+
|
|
587
652
|
/**
|
|
588
653
|
* Ensure a cloned repo has a develop branch. Creates from default branch and pushes if missing.
|
|
589
654
|
* Idempotent — safe to call on repos that already have develop.
|
|
@@ -752,6 +817,20 @@ function piTrustArgs() {
|
|
|
752
817
|
}
|
|
753
818
|
}
|
|
754
819
|
|
|
820
|
+
function claudeLaunchArgs(egregoreDir) {
|
|
821
|
+
const args = ["start"];
|
|
822
|
+
const memoryLink = path.join(egregoreDir, "memory");
|
|
823
|
+
try {
|
|
824
|
+
const memoryDir = fs.realpathSync(memoryLink);
|
|
825
|
+
if (fs.statSync(memoryDir).isDirectory()) {
|
|
826
|
+
args.push("--add-dir", memoryDir);
|
|
827
|
+
}
|
|
828
|
+
} catch {
|
|
829
|
+
// Session startup owns the actionable missing-memory diagnostic.
|
|
830
|
+
}
|
|
831
|
+
return args;
|
|
832
|
+
}
|
|
833
|
+
|
|
755
834
|
function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
756
835
|
if (normalizeRuntime(runtime) === "codex") {
|
|
757
836
|
return [
|
|
@@ -762,7 +841,7 @@ function runtimeLaunchArgs(runtime, egregoreDir) {
|
|
|
762
841
|
];
|
|
763
842
|
}
|
|
764
843
|
if (normalizeRuntime(runtime) === "pi") return piTrustArgs();
|
|
765
|
-
return
|
|
844
|
+
return claudeLaunchArgs(egregoreDir);
|
|
766
845
|
}
|
|
767
846
|
|
|
768
847
|
function startSpinner(label) {
|
|
@@ -1353,5 +1432,6 @@ module.exports = {
|
|
|
1353
1432
|
assistantInstallCommand,
|
|
1354
1433
|
initMemoryDirs,
|
|
1355
1434
|
ensureDevelop,
|
|
1435
|
+
ensureConnectedConfig,
|
|
1356
1436
|
run,
|
|
1357
1437
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-egregore",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.15",
|
|
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": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"scripts": {
|
|
13
13
|
"build:runtime": "node scripts/build-runtime-bundle.mjs && node scripts/build-pi-runtime-bundle.mjs",
|
|
14
14
|
"build:pi-runtime": "node scripts/build-pi-runtime-bundle.mjs",
|
|
15
|
-
"test": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/context.test.js test/parse-join-target.test.js test/skip-repos.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/pi-runtime.test.js test/pi-product-workflows.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js test/launcher-refocus-redraw.test.js test/multiselect-remote-search.test.js test/back-navigation.test.js test/manifest-form.test.js test/launcher-delete.test.js test/launcher-connect.test.js test/launcher-update.test.js",
|
|
15
|
+
"test": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/context.test.js test/parse-join-target.test.js test/skip-repos.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/pi-runtime.test.js test/pi-product-workflows.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js test/launcher-refocus-redraw.test.js test/multiselect-remote-search.test.js test/back-navigation.test.js test/manifest-form.test.js test/launcher-delete.test.js test/launcher-connect.test.js test/launcher-update.test.js test/connected-config.test.js",
|
|
16
16
|
"test:e2e": "node --test test/e2e-local.test.js",
|
|
17
17
|
"test:all": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/"
|
|
18
18
|
},
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
//
|
|
5
5
|
// Mirror of .claude/hooks/search-hint.sh: when the user's prompt is
|
|
6
6
|
// recall-shaped ("find the handoff about…", "did we decide…"), inject a
|
|
7
|
-
// routing hint toward `bin/
|
|
7
|
+
// routing hint toward `bash bin/search.sh query` — one ranked call over
|
|
8
8
|
// memory/ — instead of improvised ls/grep/graph exploration.
|
|
9
9
|
//
|
|
10
10
|
// Advisory only, never blocks, rate-limited once per session, exits 0.
|
|
@@ -43,6 +43,8 @@ const RECALL = new RegExp(
|
|
|
43
43
|
"\\bwho worked on\\b",
|
|
44
44
|
"\\bdidn.?t (someone|we) already\\b",
|
|
45
45
|
"\\bwas there (a|any) (handoff|decision|discussion|meeting)\\b",
|
|
46
|
+
"\\b(our|company|org|organization|team)\\b.*\\b(pricing|price|tiers?|plans?|paid|free|strategy|policy|positioning|ownership|decision)\\b",
|
|
47
|
+
"\\b(pricing|price|tiers?|plans?|paid|free)\\b.*\\b(our|company|org|organization|team)\\b",
|
|
46
48
|
].join("|"),
|
|
47
49
|
"i"
|
|
48
50
|
);
|
|
@@ -59,7 +61,7 @@ process.stdout.write(JSON.stringify({
|
|
|
59
61
|
hookSpecificOutput: {
|
|
60
62
|
hookEventName: "UserPromptSubmit",
|
|
61
63
|
additionalContext:
|
|
62
|
-
"Routing hint: this prompt asks for recall from org memory. FIRST action: `bin/
|
|
64
|
+
"Routing hint: this prompt asks for recall from org memory. FIRST action: `bash bin/search.sh query \"<the concept, not the literal sentence>\"` — one ranked call over all of memory/ (hybrid keyword+semantic; graph-state annotations attach automatically in connected mode). Read the top hits and cite paths. Do NOT improvise ls/grep/graph exploration first — hand-written graph queries against invented labels (e.g. :Handoff — handoffs are :Session nodes) return empty. Full spec: the search skill.",
|
|
63
65
|
},
|
|
64
66
|
}) + "\n");
|
|
65
67
|
process.exit(0);
|
|
@@ -11,12 +11,35 @@ search before answering from conversation context alone.
|
|
|
11
11
|
|
|
12
12
|
## Flow
|
|
13
13
|
|
|
14
|
-
1.
|
|
14
|
+
1. Organizational recall must begin with the Egregore search entry point in
|
|
15
|
+
step 2. Do not resolve `memory/` to its sibling Git repository, change into
|
|
16
|
+
that absolute path, or improvise raw grep/listing as the first retrieval
|
|
17
|
+
action. Use direct file reads or grep only on evidence paths returned by the
|
|
18
|
+
ranked search.
|
|
19
|
+
|
|
20
|
+
Before any shell, file-read, grep, or other retrieval tool call, send exactly
|
|
21
|
+
one standalone commentary line:
|
|
22
|
+
|
|
23
|
+
- local/filesystem-only:
|
|
24
|
+
`⌕ Egregore · searching your organization’s memory`
|
|
25
|
+
- connected mode with automatic graph enrichment:
|
|
26
|
+
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
27
|
+
|
|
28
|
+
Send the line verbatim. Do not replace it with generic narration such as
|
|
29
|
+
“I’ll search org memory.” It must be visible before the tool call; captured
|
|
30
|
+
command output does not satisfy this requirement. Emit it once even when the
|
|
31
|
+
retrieval needs multiple queries or source reads.
|
|
32
|
+
|
|
33
|
+
2. Run the search:
|
|
15
34
|
|
|
16
35
|
```bash
|
|
17
|
-
bin/
|
|
36
|
+
bash bin/search.sh query "your query" -n 6
|
|
18
37
|
```
|
|
19
38
|
|
|
39
|
+
- The command also prints the attribution as a direct-shell fallback. That
|
|
40
|
+
captured banner is diagnostic redundancy, not the user-visible product beat.
|
|
41
|
+
If the answer instead begins with a graph-only named read, follow the same
|
|
42
|
+
global Egregore Retrieval Beat before that query.
|
|
20
43
|
- Default is hybrid (BM25 + vector + rerank); it falls back to keyword
|
|
21
44
|
search automatically when local models aren't built, with a note.
|
|
22
45
|
- `--fast` — keyword only (BM25), instant. Use for exact terms: names,
|
|
@@ -27,15 +50,15 @@ bin/agent.sh search "your query" -n 6
|
|
|
27
50
|
state lines (status, recipient, artifact type, quest) with no flag.
|
|
28
51
|
`--no-enrich` skips it when speed matters; local mode never attempts it.
|
|
29
52
|
|
|
30
|
-
|
|
53
|
+
3. Search the *concept*, not the user's literal sentence. If the first query
|
|
31
54
|
returns weak scores, run a second with different wording — one
|
|
32
55
|
keyword-ish, one conceptual.
|
|
33
56
|
|
|
34
|
-
|
|
57
|
+
4. Results are snippets with `memory/...` file paths. Read the source file
|
|
35
58
|
for anything you will cite or act on — snippets truncate, and memory
|
|
36
59
|
files carry dates, authors, and caveats that change the answer.
|
|
37
60
|
|
|
38
|
-
|
|
61
|
+
5. Answer directly, citing file paths. If results are empty or weak, say so
|
|
39
62
|
plainly — "nothing in memory on X" is a real answer. Do not present
|
|
40
63
|
conversation-context guesses as memory.
|
|
41
64
|
|
|
@@ -50,6 +50,12 @@
|
|
|
50
50
|
"sourceHash": "b5d9a149f1a6",
|
|
51
51
|
"note": "Kept verbatim — bin/graph.sh is runtime-neutral."
|
|
52
52
|
},
|
|
53
|
+
{
|
|
54
|
+
"section": "Egregore Retrieval Beat",
|
|
55
|
+
"action": "keep",
|
|
56
|
+
"sourceHash": "0c4d4715fb13",
|
|
57
|
+
"note": "Kept verbatim — product attribution applies across runtimes."
|
|
58
|
+
},
|
|
53
59
|
{
|
|
54
60
|
"section": "Notifications",
|
|
55
61
|
"action": "keep",
|
|
@@ -95,7 +101,7 @@
|
|
|
95
101
|
{
|
|
96
102
|
"section": "Command Awareness",
|
|
97
103
|
"action": "keep",
|
|
98
|
-
"sourceHash": "
|
|
104
|
+
"sourceHash": "a020fc5d9b98",
|
|
99
105
|
"note": "Prepended the Codex command surface (skill tokens, native vs adapter split, $save abstraction); disambiguation map kept with /x -> $x token rendering. Tokens with no Codex skill (e.g. /loop, a Claude Code harness feature) are left as-is."
|
|
100
106
|
},
|
|
101
107
|
{
|
package/runtime/codex/AGENTS.md
CHANGED
|
@@ -220,6 +220,53 @@ Run `catalog` only when the route is unclear. Named reads return bounded stable
|
|
|
220
220
|
|
|
221
221
|
---
|
|
222
222
|
|
|
223
|
+
## Egregore Retrieval Beat
|
|
224
|
+
|
|
225
|
+
Egregore's organizational search is a product surface, not indistinguishable
|
|
226
|
+
agent tool use. For each user-directed lookup of organizational knowledge,
|
|
227
|
+
show exactly one visible attribution line:
|
|
228
|
+
|
|
229
|
+
- memory-only retrieval:
|
|
230
|
+
`⌕ Egregore · searching your organization’s memory`
|
|
231
|
+
- retrieval that actually queries the connected graph:
|
|
232
|
+
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
233
|
+
|
|
234
|
+
**Visibility is the contract.** Emit the applicable line verbatim as a
|
|
235
|
+
standalone assistant message before the first Bash, Grep, Glob, Read, or other
|
|
236
|
+
retrieval tool call. Shell/tool output does not satisfy this requirement:
|
|
237
|
+
Claude Code and other harnesses may collapse it. Do not paraphrase the line or
|
|
238
|
+
replace it with generic narration such as “I’ll search org memory.”
|
|
239
|
+
|
|
240
|
+
Use the memory form for local/filesystem-only organizational retrieval. Use the
|
|
241
|
+
Connect form when the retrieval route will query the connected graph, including
|
|
242
|
+
automatic graph enrichment in `bin/search.sh query`, a graph-only named read,
|
|
243
|
+
or exploratory Cypher. Emit once for the whole retrieval episode, not once per
|
|
244
|
+
hop. The banner printed by `bin/search.sh` remains a direct-shell fallback and
|
|
245
|
+
does not replace the assistant-visible beat.
|
|
246
|
+
|
|
247
|
+
**Routing is part of the contract.** For organizational history, decisions,
|
|
248
|
+
handoffs, meetings, people, pricing, strategy, or other shared-memory content,
|
|
249
|
+
the first retrieval action is:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
bash bin/search.sh query "<concept>" -n 6
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Do not start by resolving `memory/` to its sibling repository, changing
|
|
256
|
+
directory into that absolute path, or improvising `grep`/`ls` over it. The
|
|
257
|
+
search entry point owns keyword/semantic selection and automatically attaches
|
|
258
|
+
graph state in connected mode. Read or grep the returned `memory/...` source
|
|
259
|
+
paths only after the ranked call when verification needs the full document.
|
|
260
|
+
Native Grep/Glob remain the right first action for repository code, filenames,
|
|
261
|
+
and exact error strings—not organizational recall.
|
|
262
|
+
|
|
263
|
+
Do not emit the beat for native repository/code search, Git inspection, startup
|
|
264
|
+
context hydration, graph writes, ingestion projection, background sync,
|
|
265
|
+
maintenance, or command-internal queries that are not answering a user lookup.
|
|
266
|
+
Never name `Egregore Connect` unless a graph read will actually run.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
223
270
|
## Notifications
|
|
224
271
|
|
|
225
272
|
**Connected mode only.** Always use `bin/notify.sh` for Telegram notifications — never construct API calls directly. See DEVELOPMENT.md §1 for usage examples. In local mode there are no live notifications.
|
|
@@ -306,7 +353,7 @@ Codex reserves leading `/` for built-ins, so Egregore workflows are **skills**,
|
|
|
306
353
|
Invoke commands from user intent — don't wait for the slash. Each command file has a `## When to invoke` section. Load it for the full spec.
|
|
307
354
|
|
|
308
355
|
**Core loop** — `$activity` `$dashboard` `$handoff` `$wrap` `$save` `$reflect` `$todo`
|
|
309
|
-
**Knowledge** — `$search` `$deep-reflect` `$archive` `$note` `$add` `$meeting` `$ingest` `$scroll`
|
|
356
|
+
**Knowledge** — `$search` `$deep-reflect` `$archive` `$note` `$add` `$meeting` `$ingest` `$scroll` `$mock`
|
|
310
357
|
**Identity** — `$me` (view profile or set display name)
|
|
311
358
|
**Coordination** — `$ask` `$quest` `$issue` `$invite` `$delete-user` `$announce`
|
|
312
359
|
**Connectors** — `$telegram-connect` (Telegram group setup) `$teams-connect` (Microsoft Teams channel setup)
|
|
@@ -316,9 +363,9 @@ Invoke commands from user intent — don't wait for the slash. Each command file
|
|
|
316
363
|
|
|
317
364
|
**Disambiguation:**
|
|
318
365
|
- Knowledge: `$reflect` (share-ready) · `$note` (half-baked) · `$deep-reflect` (deep research over memory — questions AND cross-referencing) · `$archive` (AI patterns)
|
|
319
|
-
- Finding things —
|
|
366
|
+
- Finding things — **organizational recall starts with `bash bin/search.sh query`** (ranked filesystem retrieval in OSS; automatic relationship/status enrichment in Connect). Use `bin/graph.sh` named reads first only for a pure relationship/status traversal. Use Grep/Glob first for repository code, filenames, and exact error strings—not shared-memory recall. Do not `cd` into the sibling memory repository.
|
|
320
367
|
- Finding **something you generated** (a scroll, handoff, emissary, decision, any hosted egregore.xyz link): `bash bin/artifacts.sh find <query>`. Every generative surface already records into memory — hosted artifacts self-register into `memory/artifacts/` at publish (and the record is committed+pushed, so it's findable from *any* session, not just the one that made it); handoffs land in `memory/handoffs/`, emissaries in `memory/handoffs/outbound/`, decisions/findings/patterns in `memory/knowledge/`. The finder searches **all** of them, ranks title/topic matches above passing body mentions, tags each hit by type (`[document]`/`[handoff]`/`[emissary]`/`[decision]`), and surfaces the shareable URL. Findable by **content, not just name**, across all three layers — grep-first for OSS, folding in search + graph when available. *"bring me the artifact where I laid out our GTM plan"* → this.
|
|
321
|
-
- Artifacts with questions: `$scroll` (living paper + embedded harvest, updates in place) · `$view` (static render) · `$harvest` (elicitation, no published face)
|
|
368
|
+
- Artifacts with questions: `$scroll` (living paper + embedded harvest, updates in place) · `$view` (static render) · `$harvest` (elicitation, no published face) · `$mock` (pre-build walkthrough of decided design — gauge per stop, verdict copy-back)
|
|
322
369
|
- Status: `$dashboard` (personal) · `$activity` (org-wide)
|
|
323
370
|
- Ending: `$wrap` (personal closure) · `$handoff` (notes for others) · `$save` (still working)
|
|
324
371
|
- Tasks: `$todo` (personal) · `$quest` (team exploration) · `$issue` (something broken)
|
|
@@ -301,6 +301,7 @@ const RULES = {
|
|
|
301
301
|
},
|
|
302
302
|
'Config Files': { action: 'keep', note: 'Kept verbatim — shell facts, runtime-neutral.' },
|
|
303
303
|
'Knowledge Graph': { action: 'keep', note: 'Kept verbatim — bin/graph.sh is runtime-neutral.' },
|
|
304
|
+
'Egregore Retrieval Beat': { action: 'keep', note: 'Kept verbatim — product attribution applies across runtimes.' },
|
|
304
305
|
'Notifications': { action: 'keep', note: 'Kept verbatim — bin/notify.sh is runtime-neutral.' },
|
|
305
306
|
'Onboarding': { action: 'keep', note: 'Kept; /onboarding rendered as $onboarding.' },
|
|
306
307
|
'Transparency Beat': { action: 'keep', note: 'Kept verbatim.' },
|