create-egregore 0.19.5 → 0.19.7
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 +411 -25
- package/bin/cli.js +34 -20
- package/lib/local.js +21 -5
- package/lib/pi-runtime.js +186 -0
- package/lib/setup.js +56 -11
- package/lib/ui.js +1 -1
- package/package.json +7 -5
- package/runtime/codex/.codex/spec-manifest.json +1 -1
- package/runtime/codex/AGENTS.md +7 -2
- package/runtime/codex/bin/codex-render-spec.mjs +6 -1
- package/runtime/codex/bin/codex-session-start.sh +5 -59
- package/runtime/codex/bin/codex-skill-render.mjs +7 -5
- package/runtime/codex/bin/lib/context.sh +8 -1
- package/runtime/codex/bin/lib/greeting.sh +12 -108
- package/runtime/codex/bin/lib/metrics.sh +374 -0
- package/runtime/codex/bin/publish-artifact.sh +14 -0
- package/runtime/codex/bin/settings.sh +274 -0
- package/runtime/codex/manifest.json +2 -0
- package/runtime/pi/.codex/config.toml +15 -0
- package/runtime/pi/.codex/hooks/branch-guard.js +242 -0
- package/runtime/pi/.codex/hooks/search-hint.js +65 -0
- package/runtime/pi/.codex/hooks.json +30 -0
- package/runtime/pi/.codex/skills/activity/SKILL.md +70 -0
- package/runtime/pi/.codex/skills/add/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/announce/SKILL.md +54 -0
- package/runtime/pi/.codex/skills/answer/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/archive/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/ask/SKILL.md +59 -0
- package/runtime/pi/.codex/skills/branch/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/checkup/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/commit/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/contribute/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/dark-mode/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/dashboard/SKILL.md +59 -0
- package/runtime/pi/.codex/skills/deep-reflect/SKILL.md +74 -0
- package/runtime/pi/.codex/skills/delete-user/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/egregore-voice/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/emissary/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/env/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/handoff/SKILL.md +67 -0
- package/runtime/pi/.codex/skills/harvest/SKILL.md +107 -0
- package/runtime/pi/.codex/skills/ingest/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/ingest-google/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/invite/SKILL.md +40 -0
- package/runtime/pi/.codex/skills/issue/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/me/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/meeting/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/minion/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/note/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/onboarding/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/pr/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/project/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/pull/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/push/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/quest/SKILL.md +77 -0
- package/runtime/pi/.codex/skills/quest-suggest/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/reflect/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/review-pr/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/save/SKILL.md +62 -0
- package/runtime/pi/.codex/skills/scroll/SKILL.md +168 -0
- package/runtime/pi/.codex/skills/scroll/agents/openai.yaml +4 -0
- package/runtime/pi/.codex/skills/scroll/assets/shell.html +542 -0
- package/runtime/pi/.codex/skills/search/SKILL.md +56 -0
- package/runtime/pi/.codex/skills/session-view/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/setup/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/summon/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/sync-repos/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/telemetry/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/test/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/the-spiral/SKILL.md +84 -0
- package/runtime/pi/.codex/skills/thread/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/todo/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/tui-design/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/tutorial/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/update/SKILL.md +25 -0
- package/runtime/pi/.codex/skills/view/SKILL.md +156 -0
- package/runtime/pi/.codex/skills/view/agents/openai.yaml +4 -0
- package/runtime/pi/.codex/skills/view/assets/compose-scaffold.html +221 -0
- package/runtime/pi/.codex/skills/visual-explain/SKILL.md +41 -0
- package/runtime/pi/.codex/skills/wrap/SKILL.md +55 -0
- package/runtime/pi/.codex/spec-manifest.json +114 -0
- package/runtime/pi/.pi/APPEND_SYSTEM.md +255 -0
- package/runtime/pi/.pi/extensions/egregore.ts +324 -0
- package/runtime/pi/.pi/settings.json +6 -0
- package/runtime/pi/.pi/spec-manifest.json +12 -0
- package/runtime/pi/AGENTS.md +350 -0
- package/runtime/pi/bin/activity-data.sh +242 -0
- package/runtime/pi/bin/agent.sh +677 -0
- package/runtime/pi/bin/codex-install-skills.sh +78 -0
- package/runtime/pi/bin/codex-render-spec.mjs +394 -0
- package/runtime/pi/bin/codex-session-start.sh +188 -0
- package/runtime/pi/bin/codex-skill-render.mjs +323 -0
- package/runtime/pi/bin/codex-sync-skills.sh +227 -0
- package/runtime/pi/bin/dashboard-data.sh +178 -0
- package/runtime/pi/bin/graph-batch.sh +60 -0
- package/runtime/pi/bin/graph-op.sh +431 -0
- package/runtime/pi/bin/graph-wal.sh +228 -0
- package/runtime/pi/bin/graph.sh +177 -0
- package/runtime/pi/bin/handoff-pr-backfill.sh +86 -0
- package/runtime/pi/bin/handoff-run.sh +581 -0
- package/runtime/pi/bin/handoff-save-egregore.sh +136 -0
- package/runtime/pi/bin/index-handoff.sh +312 -0
- package/runtime/pi/bin/lib/artifact-id.sh +46 -0
- package/runtime/pi/bin/lib/config.sh +71 -0
- package/runtime/pi/bin/lib/context.sh +542 -0
- package/runtime/pi/bin/lib/dashboard-artifact.sh +142 -0
- package/runtime/pi/bin/lib/ensure-develop.sh +183 -0
- package/runtime/pi/bin/lib/git-sync.sh +288 -0
- package/runtime/pi/bin/lib/greeting.sh +340 -0
- package/runtime/pi/bin/lib/hash.sh +13 -0
- package/runtime/pi/bin/lib/identity.sh +174 -0
- package/runtime/pi/bin/lib/metrics.sh +374 -0
- package/runtime/pi/bin/lib/permissions.sh +106 -0
- package/runtime/pi/bin/lib/time.sh +56 -0
- package/runtime/pi/bin/lib/worktree-links.sh +54 -0
- package/runtime/pi/bin/notify.sh +207 -0
- package/runtime/pi/bin/pi-branch-policy.mjs +15 -0
- package/runtime/pi/bin/pi-product-workflows.mjs +324 -0
- package/runtime/pi/bin/pi-render-spec.mjs +114 -0
- package/runtime/pi/bin/pi-session-start.sh +24 -0
- package/runtime/pi/bin/publish-artifact.sh +201 -0
- package/runtime/pi/bin/publish-references.sh +144 -0
- package/runtime/pi/bin/repo-state.sh +99 -0
- package/runtime/pi/bin/telemetry.sh +391 -0
- package/runtime/pi/bin/worktree-create.sh +118 -0
- package/runtime/pi/bin/worktree-remove.sh +50 -0
- package/runtime/pi/bin/worktree.sh +198 -0
- package/runtime/pi/manifest.json +176 -0
|
@@ -153,6 +153,7 @@
|
|
|
153
153
|
"bin/lib/greeting.sh",
|
|
154
154
|
"bin/lib/hash.sh",
|
|
155
155
|
"bin/lib/identity.sh",
|
|
156
|
+
"bin/lib/metrics.sh",
|
|
156
157
|
"bin/lib/permissions.sh",
|
|
157
158
|
"bin/lib/time.sh",
|
|
158
159
|
"bin/lib/worktree-links.sh",
|
|
@@ -160,6 +161,7 @@
|
|
|
160
161
|
"bin/publish-artifact.sh",
|
|
161
162
|
"bin/publish-references.sh",
|
|
162
163
|
"bin/repo-state.sh",
|
|
164
|
+
"bin/settings.sh",
|
|
163
165
|
"bin/telemetry.sh",
|
|
164
166
|
"bin/worktree-create.sh",
|
|
165
167
|
"bin/worktree-remove.sh",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[features]
|
|
2
|
+
hooks = true
|
|
3
|
+
|
|
4
|
+
[tui]
|
|
5
|
+
status_line = [
|
|
6
|
+
"model-with-reasoning",
|
|
7
|
+
"git-branch",
|
|
8
|
+
"current-dir",
|
|
9
|
+
"context-remaining",
|
|
10
|
+
"five-hour-limit",
|
|
11
|
+
"weekly-limit",
|
|
12
|
+
"permissions",
|
|
13
|
+
"approval-mode",
|
|
14
|
+
]
|
|
15
|
+
status_line_use_colors = true
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const fs = require("node:fs");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
const { spawnSync } = require("node:child_process");
|
|
7
|
+
|
|
8
|
+
function readStdin() {
|
|
9
|
+
try {
|
|
10
|
+
return fs.readFileSync(0, "utf-8");
|
|
11
|
+
} catch {
|
|
12
|
+
return "";
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function parseJson(raw) {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(raw || "{}");
|
|
19
|
+
} catch {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function run(cmd, args, cwd) {
|
|
25
|
+
const result = spawnSync(cmd, args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
|
|
26
|
+
if (result.status !== 0) return "";
|
|
27
|
+
return String(result.stdout || "").trim();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function realish(filePath) {
|
|
31
|
+
const absolute = path.resolve(filePath);
|
|
32
|
+
let cursor = absolute;
|
|
33
|
+
while (!fs.existsSync(cursor)) {
|
|
34
|
+
const parent = path.dirname(cursor);
|
|
35
|
+
if (parent === cursor) return absolute;
|
|
36
|
+
cursor = parent;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const resolved = fs.realpathSync(cursor);
|
|
40
|
+
return path.join(resolved, path.relative(cursor, absolute));
|
|
41
|
+
} catch {
|
|
42
|
+
return absolute;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function inside(child, parent) {
|
|
47
|
+
const rel = path.relative(parent, child);
|
|
48
|
+
return rel === "" || (!!rel && !rel.startsWith("..") && !path.isAbsolute(rel));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function findProjectDir(input) {
|
|
52
|
+
// Tool payload cwd is the operation location. Codex launchers may keep
|
|
53
|
+
// EGREGORE_CODEX_PROJECT_DIR pointed at the main checkout even after the
|
|
54
|
+
// model continues in a task worktree, so using the env var first can make
|
|
55
|
+
// legitimate worktree writes look like writes on protected develop.
|
|
56
|
+
const cwd = input.cwd || process.cwd() || process.env.EGREGORE_CODEX_PROJECT_DIR;
|
|
57
|
+
const top = run("git", ["-C", cwd, "rev-parse", "--show-toplevel"], cwd);
|
|
58
|
+
if (top) return realish(top);
|
|
59
|
+
|
|
60
|
+
const envDir = process.env.EGREGORE_CODEX_PROJECT_DIR || "";
|
|
61
|
+
if (envDir) {
|
|
62
|
+
const envTop = run("git", ["-C", envDir, "rev-parse", "--show-toplevel"], envDir);
|
|
63
|
+
return realish(envTop || envDir);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return realish(cwd);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function currentBranch(projectDir) {
|
|
70
|
+
return run("git", ["-C", projectDir, "rev-parse", "--abbrev-ref", "HEAD"], projectDir);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function currentAuthor(projectDir) {
|
|
74
|
+
try {
|
|
75
|
+
const raw = fs.readFileSync(path.join(projectDir, ".egregore-state.json"), "utf-8");
|
|
76
|
+
const state = JSON.parse(raw);
|
|
77
|
+
const value = state.handle || state.display_name || state.name || "dev";
|
|
78
|
+
return String(value).trim().toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "") || "dev";
|
|
79
|
+
} catch {
|
|
80
|
+
return "dev";
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function isProtectedBranch(branch) {
|
|
85
|
+
return branch === "develop" || branch === "main" || branch === "master";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function isExemptPath(rawPath, projectDir, memoryDir) {
|
|
89
|
+
if (!rawPath) return false;
|
|
90
|
+
const absolute = path.isAbsolute(rawPath) ? rawPath : path.join(projectDir, rawPath);
|
|
91
|
+
const resolved = realish(absolute);
|
|
92
|
+
|
|
93
|
+
for (const dir of [".claude", ".codex", "memory"]) {
|
|
94
|
+
const target = realish(path.join(projectDir, dir));
|
|
95
|
+
if (inside(resolved, target)) return true;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for (const file of [".egregore-state.json", ".env"]) {
|
|
99
|
+
if (resolved === realish(path.join(projectDir, file))) return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (memoryDir && inside(resolved, memoryDir)) return true;
|
|
103
|
+
|
|
104
|
+
return !inside(resolved, projectDir);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function extractApplyPatchPaths(command) {
|
|
108
|
+
const paths = [];
|
|
109
|
+
for (const line of String(command || "").split(/\r?\n/)) {
|
|
110
|
+
const match = line.match(/^\*\*\* (?:Add|Update|Delete) File: (.+)$/) || line.match(/^\*\*\* Move to: (.+)$/);
|
|
111
|
+
if (match && match[1]) paths.push(match[1].trim());
|
|
112
|
+
}
|
|
113
|
+
return paths;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function commandTargetsOtherRepo(command, projectDir, memoryDir) {
|
|
117
|
+
const paths = [];
|
|
118
|
+
const patterns = [
|
|
119
|
+
/\bcd\s+["']?([^"';&|]+)["']?/g,
|
|
120
|
+
/\bgit\s+-C\s+["']?([^"';&|]+)["']?/g,
|
|
121
|
+
];
|
|
122
|
+
for (const pattern of patterns) {
|
|
123
|
+
let match;
|
|
124
|
+
while ((match = pattern.exec(command))) paths.push(match[1]);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (const raw of paths) {
|
|
128
|
+
const resolved = realish(path.isAbsolute(raw) ? raw : path.join(projectDir, raw));
|
|
129
|
+
if (memoryDir && inside(resolved, memoryDir)) return true;
|
|
130
|
+
if (!inside(resolved, projectDir)) return true;
|
|
131
|
+
}
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function isBranchSetupCommand(command) {
|
|
136
|
+
return (
|
|
137
|
+
/\bbin\/agent\.sh\s+branch\b/.test(command) ||
|
|
138
|
+
/\bgit\s+(checkout|switch)\s+(-b|-c)\b/.test(command) ||
|
|
139
|
+
/\bgit\s+branch\s+(dev|feature|bugfix)\//.test(command) ||
|
|
140
|
+
/\bgit\s+worktree\s+add\b/.test(command) ||
|
|
141
|
+
/\bbin\/worktree\.sh\s+setup\b/.test(command)
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function stagedOnlyFrameworkPaths(projectDir) {
|
|
146
|
+
const files = run("git", ["-C", projectDir, "diff", "--cached", "--name-only"], projectDir)
|
|
147
|
+
.split(/\r?\n/)
|
|
148
|
+
.filter(Boolean);
|
|
149
|
+
return files.length > 0 && files.every((file) => /^(bin\/|\.claude\/|\.codex\/|CLAUDE\.md$|AGENTS\.md$|skills\/)/.test(file));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function redirectLooksMutating(command, projectDir, memoryDir) {
|
|
153
|
+
const redirectPatterns = [
|
|
154
|
+
/(?:^|[\s;|&])(?:\d*)>>?\s*([^&\s;|]+)/g,
|
|
155
|
+
/\|\s*tee\s+(?:-a\s+)?([^&\s;|]+)/g,
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
for (const pattern of redirectPatterns) {
|
|
159
|
+
let match;
|
|
160
|
+
while ((match = pattern.exec(command))) {
|
|
161
|
+
const target = String(match[1] || "").replace(/^["']|["']$/g, "");
|
|
162
|
+
if (!target || target === "/dev/null" || target.startsWith("$")) continue;
|
|
163
|
+
if (!isExemptPath(target, projectDir, memoryDir)) return true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function shellLooksMutating(command, projectDir, memoryDir) {
|
|
170
|
+
if (!command.trim()) return false;
|
|
171
|
+
if (isBranchSetupCommand(command)) return false;
|
|
172
|
+
|
|
173
|
+
const mutatingPatterns = [
|
|
174
|
+
/\bgit\s+(add|commit|push|rm|mv|reset|restore|checkout\s+--|clean|rebase|merge|cherry-pick)\b/,
|
|
175
|
+
/\b(apply_patch|touch|mkdir|rm|mv|cp|chmod|chown|ln)\b/,
|
|
176
|
+
/\b(sed|perl)\b[^;&|]*\s-i(\s|$)/,
|
|
177
|
+
/\b(npm|pnpm|yarn|bun)\s+(install|add|remove|update|dedupe|ci)\b/,
|
|
178
|
+
/\b(go\s+mod\s+tidy|cargo\s+(fmt|fix|update)|rustfmt|prettier\s+--write|eslint\s+--fix)\b/,
|
|
179
|
+
];
|
|
180
|
+
|
|
181
|
+
if (/\bgit\s+commit\b/.test(command) && stagedOnlyFrameworkPaths(projectDir)) return false;
|
|
182
|
+
return mutatingPatterns.some((pattern) => pattern.test(command)) || redirectLooksMutating(command, projectDir, memoryDir);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function deny(reason) {
|
|
186
|
+
process.stdout.write(JSON.stringify({
|
|
187
|
+
hookSpecificOutput: {
|
|
188
|
+
hookEventName: "PreToolUse",
|
|
189
|
+
permissionDecision: "deny",
|
|
190
|
+
permissionDecisionReason: reason,
|
|
191
|
+
},
|
|
192
|
+
}));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function main() {
|
|
196
|
+
const input = parseJson(readStdin());
|
|
197
|
+
const projectDir = findProjectDir(input);
|
|
198
|
+
const branch = currentBranch(projectDir);
|
|
199
|
+
if (!isProtectedBranch(branch)) return;
|
|
200
|
+
|
|
201
|
+
// Consent bypass: the user explicitly chose to work on this protected branch.
|
|
202
|
+
// Written only after they pick "Proceed on <branch>"; cleared on session start,
|
|
203
|
+
// so consent is asked once per session, not per write.
|
|
204
|
+
try {
|
|
205
|
+
const consent = fs.readFileSync(path.join(projectDir, ".egregore-branch-consent"), "utf-8").trim();
|
|
206
|
+
if (consent === branch) return;
|
|
207
|
+
} catch {}
|
|
208
|
+
|
|
209
|
+
const toolName = input.tool_name || "";
|
|
210
|
+
const toolInput = input.tool_input || {};
|
|
211
|
+
const memoryDir = realish(path.join(projectDir, "memory"));
|
|
212
|
+
const author = currentAuthor(projectDir);
|
|
213
|
+
const reason = [
|
|
214
|
+
`Protected branch (${branch}). Ask the user how to proceed — do NOT auto-branch silently.`,
|
|
215
|
+
"Offer a choice (numbered or structured): Branch off (default) / Proceed on this branch / Cancel.",
|
|
216
|
+
` • Branch off: bin/agent.sh branch --topic "<work topic>" (prefix dev/${author}/...)`,
|
|
217
|
+
` • Proceed on ${branch}: echo '${branch}' > .egregore-branch-consent then retry`,
|
|
218
|
+
"Proceeding records consent for this branch for the rest of the session (cleared on next session start).",
|
|
219
|
+
].join("\n");
|
|
220
|
+
|
|
221
|
+
if (toolName === "apply_patch") {
|
|
222
|
+
const changedPaths = extractApplyPatchPaths(toolInput.command || "");
|
|
223
|
+
if (changedPaths.length === 0 || changedPaths.some((p) => !isExemptPath(p, projectDir, memoryDir))) {
|
|
224
|
+
deny(reason);
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (toolName === "Edit" || toolName === "Write") {
|
|
230
|
+
const target = toolInput.file_path || toolInput.path || "";
|
|
231
|
+
if (!target || !isExemptPath(target, projectDir, memoryDir)) deny(reason);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (toolName === "Bash") {
|
|
236
|
+
const command = String(toolInput.command || "");
|
|
237
|
+
if (commandTargetsOtherRepo(command, projectDir, memoryDir)) return;
|
|
238
|
+
if (shellLooksMutating(command, projectDir, memoryDir)) deny(reason);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
main();
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
// search-hint.js — UserPromptSubmit hook (Codex runtime).
|
|
4
|
+
//
|
|
5
|
+
// Mirror of .claude/hooks/search-hint.sh: when the user's prompt is
|
|
6
|
+
// recall-shaped ("find the handoff about…", "did we decide…"), inject a
|
|
7
|
+
// routing hint toward `bin/agent.sh search` — one ranked call over
|
|
8
|
+
// memory/ — instead of improvised ls/grep/graph exploration.
|
|
9
|
+
//
|
|
10
|
+
// Advisory only, never blocks, rate-limited once per session, exits 0.
|
|
11
|
+
// If the Codex runtime does not fire UserPromptSubmit, this file is inert.
|
|
12
|
+
|
|
13
|
+
const fs = require("node:fs");
|
|
14
|
+
const path = require("node:path");
|
|
15
|
+
const os = require("node:os");
|
|
16
|
+
|
|
17
|
+
function readStdin() {
|
|
18
|
+
try { return fs.readFileSync(0, "utf-8"); } catch { return ""; }
|
|
19
|
+
}
|
|
20
|
+
function parseJson(raw) {
|
|
21
|
+
try { return JSON.parse(raw || "{}"); } catch { return {}; }
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const input = parseJson(readStdin());
|
|
25
|
+
const prompt = String(input.prompt || input.user_prompt || "");
|
|
26
|
+
if (!prompt) process.exit(0);
|
|
27
|
+
|
|
28
|
+
const root = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
29
|
+
if (!fs.existsSync(path.join(root, "bin", "search.sh"))) process.exit(0);
|
|
30
|
+
|
|
31
|
+
// Already oriented toward search.
|
|
32
|
+
if (/(\/search\b|search\.sh|\bsearch (the )?memory\b)/i.test(prompt)) process.exit(0);
|
|
33
|
+
|
|
34
|
+
const RECALL = new RegExp(
|
|
35
|
+
[
|
|
36
|
+
"\\b(find|locate|dig up|look up|pull up)\\b.*\\b(handoff|decision|notes?|docs?|meeting|harvest|quest|reflection)s?\\b",
|
|
37
|
+
"\\bdid we (decide|discuss|agree|say|talk about|cover)\\b",
|
|
38
|
+
"\\bdo we have (any )?(notes?|docs?|anything|something)( on| about)?\\b",
|
|
39
|
+
"\\bwhat did we (decide|say|agree|discuss)\\b",
|
|
40
|
+
"\\bhave we (discussed|decided|covered|talked about|looked at)\\b",
|
|
41
|
+
"\\bnotes on\\b",
|
|
42
|
+
"\\bhandoff (from|about)\\b",
|
|
43
|
+
"\\bwho worked on\\b",
|
|
44
|
+
"\\bdidn.?t (someone|we) already\\b",
|
|
45
|
+
"\\bwas there (a|any) (handoff|decision|discussion|meeting)\\b",
|
|
46
|
+
].join("|"),
|
|
47
|
+
"i"
|
|
48
|
+
);
|
|
49
|
+
if (!RECALL.test(prompt)) process.exit(0);
|
|
50
|
+
|
|
51
|
+
// Rate-limit once per session.
|
|
52
|
+
let sid = "default";
|
|
53
|
+
try { sid = fs.readFileSync(path.join(root, ".egregore-session-id"), "utf-8").trim() || "default"; } catch {}
|
|
54
|
+
const flag = path.join(os.tmpdir(), `egregore-search-hint-${sid}`);
|
|
55
|
+
if (fs.existsSync(flag)) process.exit(0);
|
|
56
|
+
try { fs.writeFileSync(flag, "1"); } catch {}
|
|
57
|
+
|
|
58
|
+
process.stdout.write(JSON.stringify({
|
|
59
|
+
hookSpecificOutput: {
|
|
60
|
+
hookEventName: "UserPromptSubmit",
|
|
61
|
+
additionalContext:
|
|
62
|
+
"Routing hint: this prompt asks for recall from org memory. FIRST action: `bin/agent.sh search \"<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
|
+
},
|
|
64
|
+
}) + "\n");
|
|
65
|
+
process.exit(0);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"UserPromptSubmit": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/search-hint.js\"",
|
|
10
|
+
"timeout": 5,
|
|
11
|
+
"statusMessage": "Checking recall routing"
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
"PreToolUse": [
|
|
17
|
+
{
|
|
18
|
+
"matcher": "Bash|apply_patch|Edit|Write",
|
|
19
|
+
"hooks": [
|
|
20
|
+
{
|
|
21
|
+
"type": "command",
|
|
22
|
+
"command": "node \"$(git rev-parse --show-toplevel)/.codex/hooks/branch-guard.js\"",
|
|
23
|
+
"timeout": 5,
|
|
24
|
+
"statusMessage": "Checking Egregore branch policy"
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: activity
|
|
3
|
+
description: Show Egregore team activity, pending handoffs, and open questions when the user invokes /activity or $activity, or asks what is happening in an Egregore checkout.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Egregore Activity
|
|
7
|
+
|
|
8
|
+
Native Codex Egregore skill. Use this only inside an Egregore checkout.
|
|
9
|
+
|
|
10
|
+
Show the live team activity view without sending the user through Claude Code.
|
|
11
|
+
The graph API is useful when reachable, but the filesystem and memory repo must
|
|
12
|
+
remain enough to render a useful answer.
|
|
13
|
+
|
|
14
|
+
## Flow
|
|
15
|
+
|
|
16
|
+
1. Verify `bin/agent.sh` exists. If it does not, say this is not an Egregore
|
|
17
|
+
checkout.
|
|
18
|
+
2. Run `bin/agent.sh sync`.
|
|
19
|
+
3. Resolve the requested handle:
|
|
20
|
+
- If the user named a person, match it against `memory/people/*.md`.
|
|
21
|
+
- Otherwise use `.egregore-state.json` `github_username`, then git user
|
|
22
|
+
fallback.
|
|
23
|
+
4. Run `bash bin/activity-data.sh [handle]` with network escalation and capture
|
|
24
|
+
stdout as JSON. This command performs the graph API call internally; a
|
|
25
|
+
normal sandboxed Codex shell can make a healthy graph look unreachable.
|
|
26
|
+
5. Classify the graph status:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
node bin/codex-skill-render.mjs classify-graph --mode connected
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If the network-enabled command still returns `retry` because `graph_reason` is
|
|
33
|
+
`unreachable`, render the filesystem fallback and mention that the graph service
|
|
34
|
+
was unreachable after a network-enabled attempt. If network escalation is denied
|
|
35
|
+
or unavailable, run the command without escalation, render the fallback, and
|
|
36
|
+
say Codex graph network access was not granted; do not claim the graph itself
|
|
37
|
+
was unreachable. Do not retry for `missing_config`, `auth_error`, or
|
|
38
|
+
`server_error`; render the clear reason instead.
|
|
39
|
+
|
|
40
|
+
6. Render the card with:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
node bin/codex-skill-render.mjs activity-card <json-file>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Paste the rendered card exactly in the visible response, preferably in a
|
|
47
|
+
`text` fenced block. Do not paraphrase the card into bullets unless the user
|
|
48
|
+
asks for a summary.
|
|
49
|
+
|
|
50
|
+
7. Offer one compact focus prompt:
|
|
51
|
+
- `Handoffs` - open pending handoffs.
|
|
52
|
+
- `Questions` - answer or inspect pending questions.
|
|
53
|
+
- `Recent work` - inspect sessions and wraps.
|
|
54
|
+
- `Dashboard` - switch to the personal dashboard.
|
|
55
|
+
- `Done` - stop.
|
|
56
|
+
|
|
57
|
+
Use structured Codex question tooling when it is available. Otherwise render a
|
|
58
|
+
numbered list plus `Other:` and wait for the user.
|
|
59
|
+
|
|
60
|
+
## Rules
|
|
61
|
+
|
|
62
|
+
- Never show raw JSON.
|
|
63
|
+
- Do not narrate each command step unless something blocks the workflow; the
|
|
64
|
+
final visible response should lead with the rendered card.
|
|
65
|
+
- Structured UX parity is required: preserve the rendered activity TUI card,
|
|
66
|
+
no preamble, no prose-only replacement, and no raw collector output.
|
|
67
|
+
- Do not call `egregore-handoff`.
|
|
68
|
+
- Do not use Claude Code commands.
|
|
69
|
+
- Keep graph, pull request, and publish data best-effort; local memory remains
|
|
70
|
+
the source of truth when connected services are down.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add
|
|
3
|
+
description: 'Fallback Codex adapter for the Egregore add workflow.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- generated-by: bin/codex-sync-skills.sh -->
|
|
7
|
+
|
|
8
|
+
# Egregore add Adapter
|
|
9
|
+
|
|
10
|
+
This is fallback coverage for a long-tail Egregore workflow that has not been
|
|
11
|
+
ported to a hand-written Codex-native skill yet.
|
|
12
|
+
|
|
13
|
+
Use the project shell and filesystem directly. Do not invoke Claude Code
|
|
14
|
+
commands. Translate interactive choices to structured Codex question tooling
|
|
15
|
+
when it is available; otherwise render compact numbered choices with an
|
|
16
|
+
`Other:` option and wait for the user.
|
|
17
|
+
|
|
18
|
+
1. Read `.claude/skills/add/SKILL.md` for the workflow details.
|
|
19
|
+
2. Run the referenced `bin/` scripts directly from Codex.
|
|
20
|
+
3. Treat graph, publish, and notify steps as best-effort unless that workflow
|
|
21
|
+
explicitly says they are required.
|
|
22
|
+
4. Keep local-mode behavior filesystem-first and avoid graph or notification
|
|
23
|
+
calls when `egregore.json` declares `"mode": "local"`.
|
|
24
|
+
5. Never call the deprecated `egregore-handoff` CLI for Egregore project
|
|
25
|
+
handoffs.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: announce
|
|
3
|
+
description: Draft, confirm, and send an Egregore group announcement from Codex when the user invokes /announce or $announce.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Egregore Announce
|
|
7
|
+
|
|
8
|
+
Native Codex Egregore skill. Use this to send concise team announcements
|
|
9
|
+
through the existing Egregore notification path.
|
|
10
|
+
|
|
11
|
+
## Flow
|
|
12
|
+
|
|
13
|
+
1. Draft a message from the user request and current context. Keep it under
|
|
14
|
+
500 characters unless the user provided exact text.
|
|
15
|
+
2. If the announcement references a memory artifact, publish it first and add
|
|
16
|
+
the returned URL only when publication succeeds:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
bash bin/publish-artifact.sh document "$FILE_PATH" --title "$TITLE" --author "$AUTHOR" --description "$DESCRIPTION"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Use `handoff`, `quest`, or `document` as the artifact type when appropriate.
|
|
23
|
+
Never fabricate a URL.
|
|
24
|
+
|
|
25
|
+
3. Preview the exact message. Confirm with structured Codex question tooling
|
|
26
|
+
when available; otherwise render:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
Send this announcement?
|
|
30
|
+
1. Send
|
|
31
|
+
2. Edit
|
|
32
|
+
Other:
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
4. If the user edits, redraft and preview again. If they approve, run:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bash bin/notify.sh group "$MESSAGE"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
5. Emit telemetry in the background:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bash bin/telemetry.sh emit "command" '{"command":"announce"}' >/dev/null 2>&1 &
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
6. Confirm whether the group send succeeded.
|
|
48
|
+
|
|
49
|
+
## Rules
|
|
50
|
+
|
|
51
|
+
- Always preview before sending.
|
|
52
|
+
- Do not expose notification credentials.
|
|
53
|
+
- Use `bin/notify.sh`; do not call Telegram directly.
|
|
54
|
+
- Do not use Claude Code commands.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: answer
|
|
3
|
+
description: 'Fallback Codex adapter for the Egregore answer workflow.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- generated-by: bin/codex-sync-skills.sh -->
|
|
7
|
+
|
|
8
|
+
# Egregore answer Adapter
|
|
9
|
+
|
|
10
|
+
This is fallback coverage for a long-tail Egregore workflow that has not been
|
|
11
|
+
ported to a hand-written Codex-native skill yet.
|
|
12
|
+
|
|
13
|
+
Use the project shell and filesystem directly. Do not invoke Claude Code
|
|
14
|
+
commands. Translate interactive choices to structured Codex question tooling
|
|
15
|
+
when it is available; otherwise render compact numbered choices with an
|
|
16
|
+
`Other:` option and wait for the user.
|
|
17
|
+
|
|
18
|
+
1. Read `.claude/skills/answer/SKILL.md` for the workflow details.
|
|
19
|
+
2. Run the referenced `bin/` scripts directly from Codex.
|
|
20
|
+
3. Treat graph, publish, and notify steps as best-effort unless that workflow
|
|
21
|
+
explicitly says they are required.
|
|
22
|
+
4. Keep local-mode behavior filesystem-first and avoid graph or notification
|
|
23
|
+
calls when `egregore.json` declares `"mode": "local"`.
|
|
24
|
+
5. Never call the deprecated `egregore-handoff` CLI for Egregore project
|
|
25
|
+
handoffs.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: archive
|
|
3
|
+
description: 'Fallback Codex adapter for the Egregore archive workflow.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- generated-by: bin/codex-sync-skills.sh -->
|
|
7
|
+
|
|
8
|
+
# Egregore archive Adapter
|
|
9
|
+
|
|
10
|
+
This is fallback coverage for a long-tail Egregore workflow that has not been
|
|
11
|
+
ported to a hand-written Codex-native skill yet.
|
|
12
|
+
|
|
13
|
+
Use the project shell and filesystem directly. Do not invoke Claude Code
|
|
14
|
+
commands. Translate interactive choices to structured Codex question tooling
|
|
15
|
+
when it is available; otherwise render compact numbered choices with an
|
|
16
|
+
`Other:` option and wait for the user.
|
|
17
|
+
|
|
18
|
+
## Structured UX parity
|
|
19
|
+
|
|
20
|
+
This workflow has a Claude skill with user-visible structured output. After
|
|
21
|
+
reading `.claude/skills/archive/SKILL.md`, reproduce the same visible UX in Codex:
|
|
22
|
+
|
|
23
|
+
- Preserve TUI boxes, markdown tables, rich cards, browser artifact rendering,
|
|
24
|
+
exact confirmation blocks, and "no preamble" rules from the source skill.
|
|
25
|
+
- Use the source skill's frame width, section order, labels, status footer,
|
|
26
|
+
and examples as the contract for the final response.
|
|
27
|
+
- Never replace a required box/table/card/artifact view with a prose summary
|
|
28
|
+
unless the user explicitly asks for a summary.
|
|
29
|
+
- When the source says to output a TUI box directly, paste that box as the
|
|
30
|
+
visible response, preferably in a `text` fenced block.
|
|
31
|
+
- Never show raw JSON, raw command output, or unformatted script output when
|
|
32
|
+
the source skill requires formatted status or rendered output.
|
|
33
|
+
|
|
34
|
+
1. Read `.claude/skills/archive/SKILL.md` for the workflow details.
|
|
35
|
+
2. Run the referenced `bin/` scripts directly from Codex.
|
|
36
|
+
3. Treat graph, publish, and notify steps as best-effort unless that workflow
|
|
37
|
+
explicitly says they are required.
|
|
38
|
+
4. Keep local-mode behavior filesystem-first and avoid graph or notification
|
|
39
|
+
calls when `egregore.json` declares `"mode": "local"`.
|
|
40
|
+
5. Never call the deprecated `egregore-handoff` CLI for Egregore project
|
|
41
|
+
handoffs.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ask
|
|
3
|
+
description: Ask an asynchronous Egregore question to a teammate when the user invokes /ask or $ask, or help the current user formulate inward reflection questions.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Egregore Ask
|
|
7
|
+
|
|
8
|
+
Native Codex Egregore skill. Use this when the user wants to ask a teammate a
|
|
9
|
+
question, run a topic by someone, or inspect pending questions for themselves.
|
|
10
|
+
|
|
11
|
+
## Flow
|
|
12
|
+
|
|
13
|
+
1. Run `bin/agent.sh sync`.
|
|
14
|
+
2. Resolve the current author from `.egregore-state.json`, then git config.
|
|
15
|
+
3. Load people from `memory/people/*.md`. Match target names against filename,
|
|
16
|
+
`name:`, `github:`, and heading text, case-insensitively. Strip leading `@`.
|
|
17
|
+
4. If the user named a target, draft one to four concrete questions. In
|
|
18
|
+
connected mode, optionally gather context with `bin/graph.sh` queries, but
|
|
19
|
+
suppress raw JSON and continue from memory files if graph access fails.
|
|
20
|
+
5. Preview the exact questions and target. Use structured Codex question
|
|
21
|
+
tooling when available; otherwise render:
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
Send these questions?
|
|
25
|
+
1. Send as-is
|
|
26
|
+
2. Edit
|
|
27
|
+
Other:
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
6. For each approved question, run:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
bin/agent.sh ask --from "$AUTHOR" --to "$TARGET" --topic "$TOPIC" --question "$QUESTION"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Add harvest flags only when this ask is part of a harvest:
|
|
37
|
+
`--harvest-id`, `--harvest-session-id`, `--turn`, `--question-intent`, and
|
|
38
|
+
`--context-mode`.
|
|
39
|
+
|
|
40
|
+
7. In connected mode, notify best-effort with:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bash bin/notify.sh send "$TARGET" "$AUTHOR has a question about \"$TOPIC\". Ask for \$activity to answer."
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
8. Report the created `memory/knowledge/questions/...` path.
|
|
47
|
+
|
|
48
|
+
## Inward Mode
|
|
49
|
+
|
|
50
|
+
If no target matches, do not create a question file. Generate a small set of
|
|
51
|
+
questions for the user to answer in-session, grounded in current conversation
|
|
52
|
+
and memory context. Offer to save the result as a reflection only after the user
|
|
53
|
+
answers.
|
|
54
|
+
|
|
55
|
+
## Rules
|
|
56
|
+
|
|
57
|
+
- Person-targeted asks are asynchronous: store, optionally notify, then stop.
|
|
58
|
+
- Local mode is filesystem-only; skip graph and notification calls.
|
|
59
|
+
- Do not use Claude Code commands.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: branch
|
|
3
|
+
description: 'Fallback Codex adapter for the Egregore branch workflow.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!-- generated-by: bin/codex-sync-skills.sh -->
|
|
7
|
+
|
|
8
|
+
# Egregore branch Adapter
|
|
9
|
+
|
|
10
|
+
This is fallback coverage for a long-tail Egregore workflow that has not been
|
|
11
|
+
ported to a hand-written Codex-native skill yet.
|
|
12
|
+
|
|
13
|
+
Use the project shell and filesystem directly. Do not invoke Claude Code
|
|
14
|
+
commands. Translate interactive choices to structured Codex question tooling
|
|
15
|
+
when it is available; otherwise render compact numbered choices with an
|
|
16
|
+
`Other:` option and wait for the user.
|
|
17
|
+
|
|
18
|
+
1. Read `.claude/skills/branch/SKILL.md` for the workflow details.
|
|
19
|
+
2. Run the referenced `bin/` scripts directly from Codex.
|
|
20
|
+
3. Treat graph, publish, and notify steps as best-effort unless that workflow
|
|
21
|
+
explicitly says they are required.
|
|
22
|
+
4. Keep local-mode behavior filesystem-first and avoid graph or notification
|
|
23
|
+
calls when `egregore.json` declares `"mode": "local"`.
|
|
24
|
+
5. Never call the deprecated `egregore-handoff` CLI for Egregore project
|
|
25
|
+
handoffs.
|