create-egregore 0.19.33 → 0.20.1
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 +141 -14
- package/bin/cli.js +19 -3
- package/lib/connect-runtime.js +4 -2
- package/lib/local.js +15 -1
- package/lib/prime-runtime.js +208 -0
- package/lib/setup.js +66 -5
- package/package.json +4 -3
- package/runtime/codex/.codex/config.toml +3 -0
- package/runtime/codex/.codex/skills/archive/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/branch/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/checkup/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/commit/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/contribute/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/delete-user/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/ingest/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/ingest-corpus/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/ingest-user-interview/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/issue/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/me/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/meeting/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/note/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/onboarding/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/pr/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/pull/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/push/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/reflect/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/review-pr/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/save/SKILL.md +3 -1
- package/runtime/codex/.codex/skills/slack-connect/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/summon/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/sync-repos/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/codex/.codex/skills/telegram-connect/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/telemetry/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/test/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/tutorial/SKILL.md +1 -1
- package/runtime/codex/.codex/skills/update/SKILL.md +1 -1
- package/runtime/codex/.codex/spec-manifest.json +5 -5
- package/runtime/codex/AGENTS.md +41 -35
- package/runtime/codex/bin/activity-data.sh +4 -8
- package/runtime/codex/bin/agent.sh +17 -5
- package/runtime/codex/bin/attendant.sh +13 -0
- package/runtime/codex/bin/autosave.sh +27 -1
- package/runtime/codex/bin/codex-render-spec.mjs +33 -32
- package/runtime/codex/bin/codex-session-start.sh +3 -1
- package/runtime/codex/bin/codex-sync-skills.sh +6 -1
- package/runtime/codex/bin/graph-batch.sh +25 -6
- package/runtime/codex/bin/graph-op.sh +5 -4
- package/runtime/codex/bin/graph.sh +31 -5
- package/runtime/codex/bin/handoff-pr-backfill.sh +1 -1
- package/runtime/codex/bin/handoff-run.sh +8 -3
- package/runtime/codex/bin/handoff-save-egregore.sh +19 -7
- package/runtime/codex/bin/ingest.py +341 -10
- package/runtime/codex/bin/lib/context.sh +26 -1
- package/runtime/codex/bin/lib/git-message.sh +37 -0
- package/runtime/codex/bin/lib/git-sync.sh +10 -2
- package/runtime/codex/bin/lib/greeting.sh +4 -1
- package/runtime/codex/bin/lib/worktree-links.sh +25 -0
- package/runtime/codex/bin/session-autosave.sh +7 -1
- package/runtime/codex/bin/settings.sh +1 -1
- package/runtime/codex/manifest.json +10 -1
- package/runtime/pi/.codex/config.toml +3 -0
- package/runtime/pi/.codex/skills/archive/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/branch/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/checkup/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/commit/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/contribute/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/delete-user/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/ingest/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/ingest-corpus/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/issue/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/me/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/meeting/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/note/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/onboarding/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/pr/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/pull/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/push/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/reflect/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/review-pr/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/save/SKILL.md +3 -1
- package/runtime/pi/.codex/skills/slack-connect/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/summon/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/sync-repos/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/telemetry/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/test/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/tutorial/SKILL.md +1 -1
- package/runtime/pi/.codex/skills/update/SKILL.md +1 -1
- package/runtime/pi/.codex/spec-manifest.json +5 -5
- package/runtime/pi/.pi/APPEND_SYSTEM.md +57 -33
- package/runtime/pi/.pi/extensions/egregore.ts +17 -6
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +41 -35
- package/runtime/pi/bin/activity-data.sh +4 -8
- package/runtime/pi/bin/agent.sh +17 -5
- package/runtime/pi/bin/attendant.sh +13 -0
- package/runtime/pi/bin/autosave.sh +27 -1
- package/runtime/pi/bin/codex-render-spec.mjs +33 -32
- package/runtime/pi/bin/codex-session-start.sh +3 -1
- package/runtime/pi/bin/codex-sync-skills.sh +6 -1
- package/runtime/pi/bin/graph-batch.sh +25 -6
- package/runtime/pi/bin/graph-op.sh +5 -4
- package/runtime/pi/bin/graph.sh +31 -5
- package/runtime/pi/bin/handoff-pr-backfill.sh +1 -1
- package/runtime/pi/bin/handoff-run.sh +8 -3
- package/runtime/pi/bin/handoff-save-egregore.sh +19 -7
- package/runtime/pi/bin/ingest.py +341 -10
- package/runtime/pi/bin/lib/context.sh +26 -1
- package/runtime/pi/bin/lib/git-message.sh +37 -0
- package/runtime/pi/bin/lib/git-sync.sh +10 -2
- package/runtime/pi/bin/lib/greeting.sh +4 -1
- package/runtime/pi/bin/lib/worktree-links.sh +25 -0
- package/runtime/pi/bin/pi-branch-policy.mjs +138 -1
- package/runtime/pi/bin/pi-product-workflows.mjs +35 -7
- package/runtime/pi/bin/pi-render-spec.mjs +52 -26
- package/runtime/pi/bin/session-autosave.sh +7 -1
- package/runtime/pi/bin/settings.sh +1 -1
- package/runtime/pi/manifest.json +10 -1
- package/runtime/prime/.claude/context/notification-consent.md +66 -0
- package/runtime/prime/.codex/config.toml +20 -0
- package/runtime/prime/.codex/hooks/branch-guard.js +461 -0
- package/runtime/prime/.codex/hooks/search-hint.js +67 -0
- package/runtime/prime/.codex/hooks.json +30 -0
- package/runtime/prime/.codex/skills/activity/SKILL.md +82 -0
- package/runtime/prime/.codex/skills/announce/SKILL.md +67 -0
- package/runtime/prime/.codex/skills/archive/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/branch/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/checkup/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/commit/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/contribute/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/create-skill/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/dark-mode/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/dashboard/SKILL.md +59 -0
- package/runtime/prime/.codex/skills/deep-reflect/SKILL.md +109 -0
- package/runtime/prime/.codex/skills/delete-user/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/emissary/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/handoff/SKILL.md +166 -0
- package/runtime/prime/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
- package/runtime/prime/.codex/skills/harvest/SKILL.md +131 -0
- package/runtime/prime/.codex/skills/ingest/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/ingest-corpus/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/ingest-notion/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/ingest-user-interview/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/invite/SKILL.md +44 -0
- package/runtime/prime/.codex/skills/issue/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/me/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/meeting/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/note/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/notion-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/onboarding/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/pr/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/pull/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/push/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/quest/SKILL.md +80 -0
- package/runtime/prime/.codex/skills/reflect/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/review-pr/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/save/SKILL.md +127 -0
- package/runtime/prime/.codex/skills/slack-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/summon/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/sync-repos/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/teams-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/telegram-connect/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/telemetry/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/test/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/the-spiral/SKILL.md +84 -0
- package/runtime/prime/.codex/skills/tui-design/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/tutorial/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/update/SKILL.md +29 -0
- package/runtime/prime/.codex/skills/view/SKILL.md +156 -0
- package/runtime/prime/.codex/skills/view/agents/openai.yaml +4 -0
- package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +221 -0
- package/runtime/prime/.codex/skills/visual-explain/SKILL.md +45 -0
- package/runtime/prime/.codex/skills/wrap/SKILL.md +58 -0
- package/runtime/prime/.codex/spec-manifest.json +132 -0
- package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +416 -0
- package/runtime/prime/.prime/agent/extensions/egregore.ts +460 -0
- package/runtime/prime/.prime/agent/settings.json +4 -0
- package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +34 -0
- package/runtime/prime/.prime/agent/skills/egregore/pyproject.toml +13 -0
- package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +156 -0
- package/runtime/prime/.prime/agent/spec-manifest.json +12 -0
- package/runtime/prime/AGENTS.md +488 -0
- package/runtime/prime/bin/activity-data.sh +238 -0
- package/runtime/prime/bin/agent.sh +787 -0
- package/runtime/prime/bin/attendant.sh +707 -0
- package/runtime/prime/bin/autosave.sh +112 -0
- package/runtime/prime/bin/capture-reconcile.sh +69 -0
- package/runtime/prime/bin/capture-run.sh +341 -0
- package/runtime/prime/bin/codex-install-skills.sh +78 -0
- package/runtime/prime/bin/codex-render-spec.mjs +435 -0
- package/runtime/prime/bin/codex-session-start.sh +265 -0
- package/runtime/prime/bin/codex-skill-render.mjs +347 -0
- package/runtime/prime/bin/codex-sync-skills.sh +237 -0
- package/runtime/prime/bin/connect-refresh.sh +33 -0
- package/runtime/prime/bin/dashboard-data.sh +178 -0
- package/runtime/prime/bin/graph-batch.sh +79 -0
- package/runtime/prime/bin/graph-op.sh +1102 -0
- package/runtime/prime/bin/graph-wal.sh +229 -0
- package/runtime/prime/bin/graph.sh +223 -0
- package/runtime/prime/bin/handoff-pr-backfill.sh +86 -0
- package/runtime/prime/bin/handoff-run.sh +676 -0
- package/runtime/prime/bin/handoff-save-egregore.sh +224 -0
- package/runtime/prime/bin/index-handoff.sh +322 -0
- package/runtime/prime/bin/ingest-graph.sh +80 -0
- package/runtime/prime/bin/ingest-surface.html +495 -0
- package/runtime/prime/bin/ingest.py +1011 -0
- package/runtime/prime/bin/ingest.sh +279 -0
- package/runtime/prime/bin/ingest_graph.py +856 -0
- package/runtime/prime/bin/ingest_surface.py +544 -0
- package/runtime/prime/bin/lib/artifact-id.sh +46 -0
- package/runtime/prime/bin/lib/config.sh +116 -0
- package/runtime/prime/bin/lib/context.sh +621 -0
- package/runtime/prime/bin/lib/dashboard-artifact.sh +242 -0
- package/runtime/prime/bin/lib/ensure-develop.sh +183 -0
- package/runtime/prime/bin/lib/git-message.sh +37 -0
- package/runtime/prime/bin/lib/git-sync.sh +414 -0
- package/runtime/prime/bin/lib/greeting.sh +519 -0
- package/runtime/prime/bin/lib/hash.sh +13 -0
- package/runtime/prime/bin/lib/identity.sh +213 -0
- package/runtime/prime/bin/lib/metrics.sh +374 -0
- package/runtime/prime/bin/lib/noncode.sh +31 -0
- package/runtime/prime/bin/lib/permissions.sh +106 -0
- package/runtime/prime/bin/lib/time.sh +56 -0
- package/runtime/prime/bin/lib/worktree-links.sh +79 -0
- package/runtime/prime/bin/notify.sh +636 -0
- package/runtime/prime/bin/person.py +630 -0
- package/runtime/prime/bin/person.sh +448 -0
- package/runtime/prime/bin/pi-branch-policy.mjs +312 -0
- package/runtime/prime/bin/pi-product-workflows.mjs +394 -0
- package/runtime/prime/bin/prime-render-spec.mjs +147 -0
- package/runtime/prime/bin/prime-session-start.sh +24 -0
- package/runtime/prime/bin/publish-artifact.sh +271 -0
- package/runtime/prime/bin/publish-references.sh +144 -0
- package/runtime/prime/bin/repo-state.sh +96 -0
- package/runtime/prime/bin/search.sh +240 -0
- package/runtime/prime/bin/session-autosave.sh +215 -0
- package/runtime/prime/bin/session-log.sh +199 -0
- package/runtime/prime/bin/settings.sh +304 -0
- package/runtime/prime/bin/telemetry.sh +391 -0
- package/runtime/prime/bin/worktree-create.sh +128 -0
- package/runtime/prime/bin/worktree-remove.sh +50 -0
- package/runtime/prime/bin/worktree.sh +198 -0
- package/runtime/prime/manifest.json +181 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
existsSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
mkdtempSync,
|
|
7
|
+
readFileSync,
|
|
8
|
+
readdirSync,
|
|
9
|
+
rmSync,
|
|
10
|
+
writeFileSync,
|
|
11
|
+
} from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { basename, join, relative, resolve } from "node:path";
|
|
14
|
+
|
|
15
|
+
const ANSI = /\x1b\[[0-?]*[ -/]*[@-~]/g;
|
|
16
|
+
|
|
17
|
+
function resultCode(result) {
|
|
18
|
+
return Number(result?.code ?? result?.status ?? 0);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function commandFailure(label, result) {
|
|
22
|
+
const detail = String(result?.stderr || result?.stdout || "").replace(ANSI, "").trim();
|
|
23
|
+
return new Error(detail ? `${label}: ${detail}` : `${label} failed`);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function checkedExec(pi, command, args, options = {}, label = command) {
|
|
27
|
+
const result = await pi.exec(command, args, options);
|
|
28
|
+
if (resultCode(result) !== 0) throw commandFailure(label, result);
|
|
29
|
+
return String(result.stdout || "");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readJson(file, fallback = {}) {
|
|
33
|
+
try {
|
|
34
|
+
return JSON.parse(readFileSync(file, "utf8"));
|
|
35
|
+
} catch {
|
|
36
|
+
return fallback;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function cleanArgs(value) {
|
|
41
|
+
return String(value || "").trim();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function walkMarkdown(dir, files = []) {
|
|
45
|
+
if (!existsSync(dir)) return files;
|
|
46
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
47
|
+
const full = join(dir, entry.name);
|
|
48
|
+
if (entry.isDirectory()) walkMarkdown(full, files);
|
|
49
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) files.push(full);
|
|
50
|
+
}
|
|
51
|
+
return files;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function inferArtifactType(file) {
|
|
55
|
+
const normalized = file.replaceAll("\\", "/");
|
|
56
|
+
if (normalized.includes("/memory/quests/")) return "quest";
|
|
57
|
+
if (normalized.includes("/memory/handoffs/")) return "handoff";
|
|
58
|
+
return "document";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function matchingFiles(root, type, query) {
|
|
62
|
+
const base = type === "quest"
|
|
63
|
+
? join(root, "memory", "quests")
|
|
64
|
+
: type === "handoff"
|
|
65
|
+
? join(root, "memory", "handoffs")
|
|
66
|
+
: join(root, "memory");
|
|
67
|
+
const needle = query.toLowerCase().replace(/\.md$/, "");
|
|
68
|
+
return walkMarkdown(base)
|
|
69
|
+
.filter((file) => basename(file, ".md").toLowerCase().includes(needle))
|
|
70
|
+
.sort((a, b) => b.localeCompare(a));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export function parseViewRequest(root, rawArgs) {
|
|
74
|
+
const raw = cleanArgs(rawArgs);
|
|
75
|
+
if (!raw) return { kind: "choose" };
|
|
76
|
+
|
|
77
|
+
const fast = /(?:^|\s)--(?:fast|floor)(?:\s|$)/.test(raw);
|
|
78
|
+
const compose = /(?:^|\s)--compose(?:\s|$)/.test(raw);
|
|
79
|
+
const cleaned = raw.replace(/(?:^|\s)--(?:fast|floor|compose)(?=\s|$)/g, " ").trim();
|
|
80
|
+
const surface = cleaned.toLowerCase();
|
|
81
|
+
if (["activity", "board", "network"].includes(surface)) {
|
|
82
|
+
return { kind: "native", type: surface, source: "", fast: true };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const explicit = cleaned.match(/^(quest|handoff|document)\s+(.+)$/i);
|
|
86
|
+
const type = explicit?.[1]?.toLowerCase();
|
|
87
|
+
const target = (explicit?.[2] || cleaned).replace(/^@/, "").trim();
|
|
88
|
+
const direct = resolve(root, target);
|
|
89
|
+
if (existsSync(direct)) {
|
|
90
|
+
const inferred = type || inferArtifactType(direct);
|
|
91
|
+
if (inferred === "document" && (!fast || compose)) {
|
|
92
|
+
return { kind: "model", reason: "document-composition", raw };
|
|
93
|
+
}
|
|
94
|
+
return { kind: "native", type: inferred, source: direct, fast };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (type) {
|
|
98
|
+
const matches = matchingFiles(root, type, target);
|
|
99
|
+
if (matches.length === 1 && (type !== "document" || fast)) {
|
|
100
|
+
return { kind: "native", type, source: matches[0], fast };
|
|
101
|
+
}
|
|
102
|
+
if (matches.length > 1) return { kind: "choose-file", type, matches, fast };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { kind: "model", reason: "resolve-or-synthesize", raw };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function rendererCommand(root) {
|
|
109
|
+
const local = join(root, "packages", "egregore-artifacts", "bin", "cli.js");
|
|
110
|
+
const react = join(root, "packages", "egregore-artifacts", "node_modules", "react");
|
|
111
|
+
if (existsSync(local) && existsSync(react)) return { command: "node", prefix: [local] };
|
|
112
|
+
return { command: "npx", prefix: ["-y", "egregore-artifacts@latest"] };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function artifactPath(output) {
|
|
116
|
+
const clean = String(output || "").replace(ANSI, "");
|
|
117
|
+
const matches = clean.match(/(?:\/[^\s'\"]+|[A-Za-z]:\\[^\r\n'\"]+)\.html/g);
|
|
118
|
+
return matches?.at(-1) || "";
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export async function renderView(pi, root, request, signal) {
|
|
122
|
+
const renderer = rendererCommand(root);
|
|
123
|
+
const args = [...renderer.prefix, request.type];
|
|
124
|
+
if (request.source) args.push(request.source);
|
|
125
|
+
const output = await checkedExec(
|
|
126
|
+
pi,
|
|
127
|
+
renderer.command,
|
|
128
|
+
args,
|
|
129
|
+
{ signal, timeout: 120000 },
|
|
130
|
+
"Artifact render",
|
|
131
|
+
);
|
|
132
|
+
const file = artifactPath(output);
|
|
133
|
+
let text = "✓ Artifact opened in browser";
|
|
134
|
+
if (file) text += `\n File: ${file}`;
|
|
135
|
+
|
|
136
|
+
if (request.type === "board") {
|
|
137
|
+
const config = readJson(join(root, "egregore.json"));
|
|
138
|
+
if (config.slug && config.mode !== "local" && config.api_url) {
|
|
139
|
+
text += `\n◆ https://egregore.xyz/view/${config.slug}/board (stable — refresh for latest)`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return { text, file, type: request.type };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export async function renderGreeting(pi, root, signal, startScript = "pi-session-start.sh") {
|
|
146
|
+
const script = join(root, "bin", startScript);
|
|
147
|
+
if (!existsSync(script)) throw new Error("Egregore startup renderer is missing");
|
|
148
|
+
return checkedExec(pi, "bash", [script, "--card"], { signal, timeout: 45000 }, "Egregore startup");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Raw JSON from the most recent activity-data.sh run, so follow-up focus
|
|
152
|
+
// turns can receive the data inline instead of re-running the script inside
|
|
153
|
+
// a harness surface that may cap command time (Prime's kernel kills execs at
|
|
154
|
+
// ~5s, truncating the 10-20s data script to a partial fragment).
|
|
155
|
+
let lastActivityData = "";
|
|
156
|
+
export function lastActivityJson() {
|
|
157
|
+
return lastActivityData;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Stable on-disk copy of the same data. Focus turns point the model at this
|
|
161
|
+
// path instead of an inline excerpt: a file read is one fast kernel call,
|
|
162
|
+
// never truncated, and removes any reason to re-run the data script.
|
|
163
|
+
export function activityDataPath(root) {
|
|
164
|
+
return join(root, ".egregore", "activity-data.json");
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function persistActivityData(root, json) {
|
|
168
|
+
try {
|
|
169
|
+
mkdirSync(join(root, ".egregore"), { recursive: true });
|
|
170
|
+
writeFileSync(activityDataPath(root), json);
|
|
171
|
+
} catch {
|
|
172
|
+
// Cache only — rendering proceeds from memory when the disk write fails.
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export async function renderActivity(pi, root, signal, options = {}) {
|
|
177
|
+
if (options.sync !== false) {
|
|
178
|
+
await checkedExec(
|
|
179
|
+
pi,
|
|
180
|
+
"bash",
|
|
181
|
+
[join(root, "bin", "agent.sh"), "sync"],
|
|
182
|
+
{ signal, timeout: 120000 },
|
|
183
|
+
"Memory sync",
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const state = readJson(join(root, ".egregore-state.json"));
|
|
188
|
+
let handle = state.github_username || state.name || "";
|
|
189
|
+
if (!handle) {
|
|
190
|
+
handle = (await checkedExec(
|
|
191
|
+
pi,
|
|
192
|
+
"git",
|
|
193
|
+
["-C", root, "config", "user.name"],
|
|
194
|
+
{ signal, timeout: 5000 },
|
|
195
|
+
"Identity lookup",
|
|
196
|
+
)).trim();
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const json = await checkedExec(
|
|
200
|
+
pi,
|
|
201
|
+
"bash",
|
|
202
|
+
[join(root, "bin", "activity-data.sh"), handle],
|
|
203
|
+
{ signal, timeout: 120000 },
|
|
204
|
+
"Activity refresh",
|
|
205
|
+
);
|
|
206
|
+
lastActivityData = String(json || "");
|
|
207
|
+
persistActivityData(root, lastActivityData);
|
|
208
|
+
const temp = mkdtempSync(join(tmpdir(), "egregore-pi-activity-"));
|
|
209
|
+
const input = join(temp, "activity.json");
|
|
210
|
+
try {
|
|
211
|
+
writeFileSync(input, json);
|
|
212
|
+
return await checkedExec(
|
|
213
|
+
pi,
|
|
214
|
+
"node",
|
|
215
|
+
[join(root, "bin", "codex-skill-render.mjs"), "activity-card", input],
|
|
216
|
+
{ signal, timeout: 10000 },
|
|
217
|
+
"Activity render",
|
|
218
|
+
);
|
|
219
|
+
} finally {
|
|
220
|
+
rmSync(temp, { recursive: true, force: true });
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function section(title, body) {
|
|
225
|
+
const value = cleanArgs(body) || "- None recorded.";
|
|
226
|
+
return `## ${title}\n\n${value}`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function buildHandoffDocument(params, author, date = new Date().toISOString().slice(0, 10)) {
|
|
230
|
+
const topic = cleanArgs(params.topic);
|
|
231
|
+
const recipient = cleanArgs(params.recipient);
|
|
232
|
+
const lines = [
|
|
233
|
+
"---",
|
|
234
|
+
"capture_schema: egregore-capture/v1",
|
|
235
|
+
"capture_mode: addressed",
|
|
236
|
+
"kind: addressed",
|
|
237
|
+
`from: ${author}`,
|
|
238
|
+
];
|
|
239
|
+
if (recipient) lines.push(`addressed_to: ${recipient}`);
|
|
240
|
+
lines.push(
|
|
241
|
+
`date: ${date}`,
|
|
242
|
+
`topic: ${topic}`,
|
|
243
|
+
"intent: action",
|
|
244
|
+
"---",
|
|
245
|
+
"",
|
|
246
|
+
`# Handoff: ${topic}`,
|
|
247
|
+
"",
|
|
248
|
+
section("Briefing", params.briefing),
|
|
249
|
+
"",
|
|
250
|
+
section("Key Decisions", params.key_decisions),
|
|
251
|
+
"",
|
|
252
|
+
section("Current State", params.current_state),
|
|
253
|
+
"",
|
|
254
|
+
section("Open Threads", params.open_threads),
|
|
255
|
+
"",
|
|
256
|
+
section("Next Steps", params.next_steps),
|
|
257
|
+
"",
|
|
258
|
+
section("Entry Points", params.entry_points),
|
|
259
|
+
"",
|
|
260
|
+
);
|
|
261
|
+
return lines.join("\n");
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export async function createHandoff(pi, root, params, signal) {
|
|
265
|
+
const state = readJson(join(root, ".egregore-state.json"));
|
|
266
|
+
const author = state.github_username || state.name || "egregore";
|
|
267
|
+
const temp = mkdtempSync(join(tmpdir(), "egregore-pi-handoff-"));
|
|
268
|
+
const body = join(temp, "handoff.md");
|
|
269
|
+
const recipient = cleanArgs(params.recipient);
|
|
270
|
+
const runnerArgs = [
|
|
271
|
+
"--author", author,
|
|
272
|
+
"--topic", cleanArgs(params.topic),
|
|
273
|
+
"--content-mode", "supplied",
|
|
274
|
+
];
|
|
275
|
+
if (recipient) runnerArgs.push("--recipient", recipient);
|
|
276
|
+
writeFileSync(body, buildHandoffDocument(params, author));
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
const shell = 'tmp="$1"; body="$2"; runner="$3"; shift 3; TMPDIR="$tmp" bash "$runner" --mode addressed "$@" < "$body"';
|
|
280
|
+
await checkedExec(
|
|
281
|
+
pi,
|
|
282
|
+
"bash",
|
|
283
|
+
["-c", shell, "egregore-pi-handoff", temp, body, join(root, "bin", "capture-run.sh"), ...runnerArgs],
|
|
284
|
+
{ signal, timeout: 180000 },
|
|
285
|
+
"Handoff",
|
|
286
|
+
);
|
|
287
|
+
const resultFile = join(temp, "handoff-run-result.json");
|
|
288
|
+
if (!existsSync(resultFile)) throw new Error("Handoff completed without a result receipt");
|
|
289
|
+
const result = readJson(resultFile);
|
|
290
|
+
const card = await checkedExec(
|
|
291
|
+
pi,
|
|
292
|
+
"node",
|
|
293
|
+
[join(root, "bin", "codex-skill-render.mjs"), "handoff-card", resultFile],
|
|
294
|
+
{ signal, timeout: 10000 },
|
|
295
|
+
"Handoff receipt",
|
|
296
|
+
);
|
|
297
|
+
return {
|
|
298
|
+
text: card.trim(),
|
|
299
|
+
path: result.file ? `memory/${result.file}` : "",
|
|
300
|
+
url: result.artifactUrl || "",
|
|
301
|
+
};
|
|
302
|
+
} finally {
|
|
303
|
+
rmSync(temp, { recursive: true, force: true });
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export async function captureSessionEnd(pi, root, sessionFile, signal, runtime = "pi") {
|
|
308
|
+
const sessionIdFile = join(root, ".egregore-session-id");
|
|
309
|
+
if (!existsSync(sessionIdFile)) return false;
|
|
310
|
+
const sessionId = cleanArgs(readFileSync(sessionIdFile, "utf8"));
|
|
311
|
+
if (!sessionId) return false;
|
|
312
|
+
|
|
313
|
+
const temp = mkdtempSync(join(tmpdir(), "egregore-pi-session-end-"));
|
|
314
|
+
const input = join(temp, "session-end.json");
|
|
315
|
+
writeFileSync(input, JSON.stringify({
|
|
316
|
+
session_id: sessionId,
|
|
317
|
+
transcript_path: cleanArgs(sessionFile),
|
|
318
|
+
runtime,
|
|
319
|
+
}));
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
const shell = 'bash "$1" < "$2"';
|
|
323
|
+
await checkedExec(
|
|
324
|
+
pi,
|
|
325
|
+
"bash",
|
|
326
|
+
["-c", shell, "egregore-pi-session-end", join(root, "bin", "session-log.sh"), input],
|
|
327
|
+
{ signal, timeout: 10000 },
|
|
328
|
+
"Session capture",
|
|
329
|
+
);
|
|
330
|
+
return true;
|
|
331
|
+
} finally {
|
|
332
|
+
rmSync(temp, { recursive: true, force: true });
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export async function publishScroll(pi, root, params, signal) {
|
|
337
|
+
const source = resolve(root, String(params.source || "").replace(/^@/, ""));
|
|
338
|
+
if (!existsSync(source)) throw new Error(`Scroll source not found: ${relative(root, source)}`);
|
|
339
|
+
const html = readFileSync(source, "utf8");
|
|
340
|
+
if (/__[A-Z][A-Z0-9_]*__/.test(html)) throw new Error("Scroll still contains unresolved placeholders");
|
|
341
|
+
|
|
342
|
+
const config = readJson(join(root, "egregore.json"));
|
|
343
|
+
let url = "";
|
|
344
|
+
if (config.mode !== "local" && config.api_url) {
|
|
345
|
+
const output = await checkedExec(
|
|
346
|
+
pi,
|
|
347
|
+
"bash",
|
|
348
|
+
[
|
|
349
|
+
join(root, "bin", "publish-artifact.sh"),
|
|
350
|
+
"document",
|
|
351
|
+
source,
|
|
352
|
+
"--raw-html",
|
|
353
|
+
"--id",
|
|
354
|
+
cleanArgs(params.slug),
|
|
355
|
+
"--title",
|
|
356
|
+
cleanArgs(params.title),
|
|
357
|
+
"--author",
|
|
358
|
+
cleanArgs(params.author),
|
|
359
|
+
"--description",
|
|
360
|
+
cleanArgs(params.description),
|
|
361
|
+
],
|
|
362
|
+
{ signal, timeout: 180000 },
|
|
363
|
+
"Scroll publish",
|
|
364
|
+
);
|
|
365
|
+
url = String(output).match(/https:\/\/[^\s]+/)?.[0] || "";
|
|
366
|
+
if (!url) throw new Error("Scroll publish did not return a stable URL");
|
|
367
|
+
const opener = process.platform === "darwin" ? "open" : "xdg-open";
|
|
368
|
+
await checkedExec(pi, opener, [url], { signal, timeout: 10000 }, "Open scroll");
|
|
369
|
+
} else {
|
|
370
|
+
const opener = process.platform === "darwin" ? "open" : "xdg-open";
|
|
371
|
+
await checkedExec(pi, opener, [source], { signal, timeout: 10000 }, "Open scroll");
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
const version = cleanArgs(params.version) || "v1";
|
|
375
|
+
const destination = url || source;
|
|
376
|
+
return {
|
|
377
|
+
text: `✓ Scroll ${version} opened\n ${url ? "URL" : "File"}: ${destination}`,
|
|
378
|
+
path: source,
|
|
379
|
+
url,
|
|
380
|
+
version,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
export function workflowPrompt(name, args, extra = "", spec = { runtimeName: "Pi", specPath: ".pi/APPEND_SYSTEM.md" }) {
|
|
385
|
+
const userArgs = cleanArgs(args);
|
|
386
|
+
return [
|
|
387
|
+
`Run the Egregore /${name} workflow now.`,
|
|
388
|
+
`Read .codex/skills/${name}/SKILL.md completely and adapt Codex-specific wording to ${spec.runtimeName} using ${spec.specPath}.`,
|
|
389
|
+
"Work quietly: do not narrate progress, expose raw command output, or repeat tool results.",
|
|
390
|
+
"Use the fewest targeted reads and commands that preserve the workflow contract.",
|
|
391
|
+
userArgs ? `User arguments: ${userArgs}` : "",
|
|
392
|
+
extra,
|
|
393
|
+
].filter(Boolean).join("\n");
|
|
394
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Derive Prime Agent's project-local system appendix from the generated Codex
|
|
3
|
+
// protocol. CLAUDE.md remains canonical:
|
|
4
|
+
// CLAUDE.md -> AGENTS.md -> .prime/agent/APPEND_SYSTEM.md.
|
|
5
|
+
// The second hop deliberately reuses the reviewed shell-runtime translation,
|
|
6
|
+
// then adapts only the harness surfaces that differ between Codex and Prime.
|
|
7
|
+
|
|
8
|
+
import crypto from "node:crypto";
|
|
9
|
+
import fs from "node:fs";
|
|
10
|
+
import path from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
|
|
13
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
14
|
+
const SOURCE = path.join(ROOT, "AGENTS.md");
|
|
15
|
+
const OUTPUT = path.join(ROOT, ".prime", "agent", "APPEND_SYSTEM.md");
|
|
16
|
+
const MANIFEST = path.join(ROOT, ".prime", "agent", "spec-manifest.json");
|
|
17
|
+
const CODEX_BEGIN = "<!-- BEGIN GENERATED EGREGORE CODEX SPEC";
|
|
18
|
+
const CODEX_END = "<!-- END GENERATED EGREGORE CODEX SPEC -->";
|
|
19
|
+
|
|
20
|
+
function hash(value) {
|
|
21
|
+
return crypto.createHash("sha256").update(value).digest("hex").slice(0, 12);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function extractSpec(source) {
|
|
25
|
+
const begin = source.indexOf(CODEX_BEGIN);
|
|
26
|
+
const contentStart = source.indexOf("\n", begin);
|
|
27
|
+
const end = source.indexOf(CODEX_END, contentStart);
|
|
28
|
+
if (begin < 0 || contentStart < 0 || end < 0) {
|
|
29
|
+
throw new Error("AGENTS.md does not contain the generated Codex spec");
|
|
30
|
+
}
|
|
31
|
+
return source.slice(contentStart + 1, end).trim();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function replaceSection(markdown, heading, body) {
|
|
35
|
+
const marker = `## ${heading}`;
|
|
36
|
+
const start = markdown.indexOf(marker);
|
|
37
|
+
if (start < 0) throw new Error(`missing section in AGENTS.md: ${heading}`);
|
|
38
|
+
const rest = markdown.slice(start + marker.length);
|
|
39
|
+
const boundary = rest.search(/\n\n---\n\n## /);
|
|
40
|
+
const end = boundary < 0 ? markdown.length : start + marker.length + boundary;
|
|
41
|
+
return `${markdown.slice(0, start)}${marker}\n\n${body}${markdown.slice(end)}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Keep an inherited section and put runtime-specific framing in front of it.
|
|
45
|
+
// Command Awareness is the case that matters: the canonical category rows and
|
|
46
|
+
// disambiguation map live in CLAUDE.md, and a full replace here silently
|
|
47
|
+
// shipped a truncated copy that drifted for months. The Codex spec opens the
|
|
48
|
+
// section with its own skills-not-slash-commands paragraph, which is wrong for
|
|
49
|
+
// a runtime that does have slash commands, so that one paragraph is dropped.
|
|
50
|
+
function prependToSection(markdown, heading, body, dropLeadParagraphStartingWith) {
|
|
51
|
+
const marker = `## ${heading}`;
|
|
52
|
+
const start = markdown.indexOf(marker);
|
|
53
|
+
if (start < 0) throw new Error(`missing section in AGENTS.md: ${heading}`);
|
|
54
|
+
const rest = markdown.slice(start + marker.length);
|
|
55
|
+
const boundary = rest.search(/\n\n---\n\n## /);
|
|
56
|
+
const end = boundary < 0 ? markdown.length : start + marker.length + boundary;
|
|
57
|
+
let inherited = markdown.slice(start + marker.length, end).trim();
|
|
58
|
+
if (dropLeadParagraphStartingWith) {
|
|
59
|
+
if (!inherited.startsWith(dropLeadParagraphStartingWith)) {
|
|
60
|
+
throw new Error(`prime-render-spec: "${heading}" no longer opens with "${dropLeadParagraphStartingWith}" — the Codex wording moved; update this adaptation`);
|
|
61
|
+
}
|
|
62
|
+
inherited = inherited.slice(inherited.indexOf("\n\n") + 2).trim();
|
|
63
|
+
}
|
|
64
|
+
return replaceSection(markdown, heading, `${body}\n\n${inherited}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const CODEX_COMMAND_LEAD = "Codex reserves leading";
|
|
68
|
+
|
|
69
|
+
function adapt(sourceSpec) {
|
|
70
|
+
// Anchored replacements: every `from` string MUST exist in the generated
|
|
71
|
+
// Codex spec — a missing anchor no-ops silently and drops Prime-specific
|
|
72
|
+
// wording (see the tool_call gate incident). Fail the render loudly instead.
|
|
73
|
+
const ANCHORED = [
|
|
74
|
+
["Egregore on Codex", "Egregore on Prime Agent"],
|
|
75
|
+
["Codex-native", "Prime-native"],
|
|
76
|
+
["Codex sessions", "Prime Agent sessions"],
|
|
77
|
+
["On Codex", "On Prime Agent"],
|
|
78
|
+
["Codex has no", "Prime Agent has no built-in"],
|
|
79
|
+
["bin/codex-session-start.sh", "bin/prime-session-start.sh"],
|
|
80
|
+
[".codex/hooks/branch-guard.js", ".prime/agent/extensions/egregore.ts"],
|
|
81
|
+
["PreToolUse hook (launcher `--enable hooks`)", "`tool_call` gate (loaded from the project-local extension)"],
|
|
82
|
+
["If this Codex build does not support hooks", "If Prime Agent project extensions are disabled"],
|
|
83
|
+
["change permissions in `.claude/settings.json` anytime", "review or disable project resources in `.prime/agent/` anytime"],
|
|
84
|
+
];
|
|
85
|
+
let text = sourceSpec;
|
|
86
|
+
for (const [from, to] of ANCHORED) {
|
|
87
|
+
if (!text.includes(from)) {
|
|
88
|
+
throw new Error(`prime-render-spec: anchor not found in generated Codex spec: "${from}" — the Codex wording moved; update this replacement`);
|
|
89
|
+
}
|
|
90
|
+
text = text.replaceAll(from, to);
|
|
91
|
+
}
|
|
92
|
+
text = text
|
|
93
|
+
.replace(/`\$([a-z][a-z0-9-]*)/g, "`/$1")
|
|
94
|
+
.replace(/\$([a-z][a-z0-9-]*)/g, "/$1");
|
|
95
|
+
|
|
96
|
+
text = replaceSection(text, "Egregore on Prime Agent", `You are Prime Agent running inside Egregore — a shared intelligence layer for organizations using AI coding agents. You operate through Git-based shared memory, project-local Prime Agent resources, Egregore skills, and conventions that accumulate knowledge across sessions and people. You are not a tool. You are a participant.
|
|
97
|
+
|
|
98
|
+
This appendix is generated from the reviewed shell-runtime translation of \`CLAUDE.md\`, the behavioral source of truth. Prime Agent loads it through \`.prime/agent/APPEND_SYSTEM.md\`. Egregore workflows are shared from \`.codex/skills/\` through the Agent Skills standard (via \`.agents/skills\` and project settings) and exposed as familiar slash commands by \`.prime/agent/extensions/egregore.ts\`.
|
|
99
|
+
|
|
100
|
+
Your subagent mechanism (\`rlm(...)\`) spawns Prime Agent child sessions, not Egregore Loom lanes. Ignore Loom routing preambles inside shared skills: run those workflows inline.`);
|
|
101
|
+
|
|
102
|
+
text = replaceSection(text, "On Launch — MANDATORY FIRST ACTION", `The project-local Prime Agent extension renders the Egregore startup card (identity, handoffs, team activity) inside the session via \`bin/prime-session-start.sh\`. This works for direct \`prime-agent\` launches and launcher-managed sessions. Do not rerun startup checks and do not narrate startup. The card ends with **"What are you working on?"** — that question is already on screen; treat the user's first message as the answer to it. To re-show the card outside Prime Agent, run \`bash bin/prime-session-start.sh --card\`.`);
|
|
103
|
+
|
|
104
|
+
text = prependToSection(text, "Command Awareness", `Egregore workflows are available as Prime Agent slash commands such as \`/activity\`, \`/handoff\`, \`/save\`, and \`/view\`. They are registered from the shared skill inventory by \`.prime/agent/extensions/egregore.ts\`; the duplicate \`/skill:name\` listings are disabled so each workflow appears once. Natural-language requests work normally — and are the route for any workflow whose name collides with a Prime Agent built-in: **say "update egregore" rather than typing \`/update\`**, which is Prime Agent's own self-updater. \`/save\` is the user-facing abstraction for committing, pushing, opening or reusing pull requests, and syncing memory — never make users manage the git workflow by hand.
|
|
105
|
+
|
|
106
|
+
Read the selected skill's \`SKILL.md\` completely before acting. Codex wording inside the shared portable skills means the shell-capable runtime adapter; in Prime Agent, run referenced \`bin/\` scripts through the IPython kernel (or the bash tool when active), use ordinary shell/network access, ignore Codex approval-channel wording, and render compact numbered questions when no UI question surface is available.
|
|
107
|
+
|
|
108
|
+
The \`egregore\` Python-backed skill exposes the mechanics as kernel functions — \`import egregore\`, then \`egregore.search(query)\`, \`egregore.activity()\`, \`egregore.handoff(to, topic, body)\`, \`egregore.save(message, topic)\`, \`egregore.branch(topic)\`, \`egregore.notify_plan(recipient, message)\`. Prefer these over re-deriving \`bin/\` CLI usage by reading scripts. \`notify_plan\` is proposal-only: approval and dispatch always pass through the explicit human Send / Edit / Cancel checkpoint.
|
|
109
|
+
|
|
110
|
+
"Get the latest changes" inside a session means \`/reload\` — it re-reads instructions, context files, skills, and extensions from disk. Never \`git pull\`, \`git reset\`, or \`git checkout\` the working branch to pick up updates. When pivoting topics inside a worktree that carries unmerged branch work, create the new branch from the current HEAD, not \`origin/develop\` — branching from origin/develop in such a worktree removes the unmerged files from disk.
|
|
111
|
+
|
|
112
|
+
Kernel shell escapes can be time-capped by the harness. Egregore \`bin/\` scripts that sync git state or query the connected graph legitimately run 10–120 seconds: run them with a generous timeout (a \`%%bash\` cell, or the longest limit the harness exposes). If a command dies suspiciously fast (~5s) with partial output, treat it as a timeout — rerun once with a longer limit or render the workflow's designed one-line fallback. Never debug data plumbing inside a product workflow. Connected mode works normally here: graph reads and \`bin/search.sh\` enrichment use the instance's configured credentials, and when graph data is degraded say so in one plain line rather than narrating connectivity theories.`, CODEX_COMMAND_LEAD);
|
|
113
|
+
|
|
114
|
+
return `# Egregore on Prime Agent\n\nThis file is generated by \`bin/prime-render-spec.mjs\`; do not edit it by hand.\n\n${text}\n`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const check = process.argv.includes("--check");
|
|
118
|
+
const source = fs.readFileSync(SOURCE, "utf8");
|
|
119
|
+
const sourceSpec = extractSpec(source);
|
|
120
|
+
const rendered = adapt(sourceSpec);
|
|
121
|
+
const manifest = `${JSON.stringify({
|
|
122
|
+
generatedBy: "bin/prime-render-spec.mjs",
|
|
123
|
+
source: "AGENTS.md generated Codex spec",
|
|
124
|
+
sourceHash: hash(sourceSpec),
|
|
125
|
+
outputHash: hash(rendered),
|
|
126
|
+
adaptations: [
|
|
127
|
+
"Prime Agent APPEND_SYSTEM delivery from .prime/agent/",
|
|
128
|
+
"Prime Agent tool_call branch gate incl. ipython classification",
|
|
129
|
+
"Prime Agent slash-command extension over shared portable skills",
|
|
130
|
+
"rlm() subagents are not Loom lanes; Loom preambles run inline",
|
|
131
|
+
],
|
|
132
|
+
}, null, 2)}\n`;
|
|
133
|
+
|
|
134
|
+
if (check) {
|
|
135
|
+
const currentOutput = fs.existsSync(OUTPUT) ? fs.readFileSync(OUTPUT, "utf8") : "";
|
|
136
|
+
const currentManifest = fs.existsSync(MANIFEST) ? fs.readFileSync(MANIFEST, "utf8") : "";
|
|
137
|
+
if (currentOutput !== rendered || currentManifest !== manifest) {
|
|
138
|
+
console.error("prime spec out of date — run: node bin/prime-render-spec.mjs");
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
141
|
+
console.log("prime spec up to date");
|
|
142
|
+
} else {
|
|
143
|
+
fs.mkdirSync(path.dirname(OUTPUT), { recursive: true });
|
|
144
|
+
fs.writeFileSync(OUTPUT, rendered);
|
|
145
|
+
fs.writeFileSync(MANIFEST, manifest);
|
|
146
|
+
console.log(`prime spec rendered: .prime/agent/APPEND_SYSTEM.md (${Buffer.byteLength(rendered)} bytes)`);
|
|
147
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -o pipefail
|
|
3
|
+
|
|
4
|
+
# Prime Agent's project extension invokes this during session_start so direct
|
|
5
|
+
# `prime-agent` launches and launcher-managed sessions share the same greeting.
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
7
|
+
|
|
8
|
+
case "${1:---card}" in
|
|
9
|
+
--card|card)
|
|
10
|
+
exec bash "$SCRIPT_DIR/bin/codex-session-start.sh" --card
|
|
11
|
+
;;
|
|
12
|
+
--prompt|prompt)
|
|
13
|
+
cat <<'EOF'
|
|
14
|
+
You are Prime Agent running inside Egregore. The project extension renders the
|
|
15
|
+
startup card during session_start. Project instructions are in
|
|
16
|
+
.prime/agent/APPEND_SYSTEM.md, Egregore workflows are registered as slash
|
|
17
|
+
commands, and portable skill bodies live in .codex/skills.
|
|
18
|
+
EOF
|
|
19
|
+
;;
|
|
20
|
+
*)
|
|
21
|
+
echo "usage: bin/prime-session-start.sh [--card|--prompt]" >&2
|
|
22
|
+
exit 2
|
|
23
|
+
;;
|
|
24
|
+
esac
|