create-egregore 0.21.0-runtime-mvp.15 → 0.21.0-runtime-mvp.17
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 +2 -2
- package/package.json +1 -1
- package/runtime/claude/CLAUDE.md +19 -19
- package/runtime/claude/bin/codex-render-spec.mjs +2 -3
- package/runtime/claude/egregore_runtime/harness_cli.py +96 -3
- package/runtime/codex/.codex/spec-manifest.json +1 -1
- package/runtime/codex/AGENTS.md +17 -16
- package/runtime/codex/bin/codex-render-spec.mjs +2 -3
- package/runtime/codex/egregore_runtime/harness_cli.py +96 -3
- package/runtime/pi/.codex/spec-manifest.json +1 -1
- package/runtime/pi/.pi/APPEND_SYSTEM.md +17 -16
- package/runtime/pi/.pi/spec-manifest.json +2 -2
- package/runtime/pi/AGENTS.md +17 -16
- package/runtime/pi/bin/codex-render-spec.mjs +2 -3
- package/runtime/pi/egregore_runtime/harness_cli.py +96 -3
- package/runtime/prime/.codex/spec-manifest.json +1 -1
- package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +17 -16
- package/runtime/prime/.prime/agent/spec-manifest.json +2 -2
- package/runtime/prime/AGENTS.md +17 -16
- package/runtime/prime/bin/codex-render-spec.mjs +2 -3
- package/runtime/prime/egregore_runtime/harness_cli.py +96 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// egregore-launcher-version: 0.21.0-runtime-mvp.
|
|
2
|
+
// egregore-launcher-version: 0.21.0-runtime-mvp.17
|
|
3
3
|
//
|
|
4
4
|
// egregore — launch and browse Egregore instances from your terminal.
|
|
5
5
|
// Installed by create-egregore. Reads ~/.egregore/instances.json.
|
|
@@ -35,7 +35,7 @@ const crypto = require("node:crypto");
|
|
|
35
35
|
const { spawnSync, spawn } = require("node:child_process");
|
|
36
36
|
const readline = require("node:readline");
|
|
37
37
|
|
|
38
|
-
const VERSION = "0.21.0-runtime-mvp.
|
|
38
|
+
const VERSION = "0.21.0-runtime-mvp.17";
|
|
39
39
|
const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
|
|
40
40
|
const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
|
|
41
41
|
const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-egregore",
|
|
3
|
-
"version": "0.21.0-runtime-mvp.
|
|
3
|
+
"version": "0.21.0-runtime-mvp.17",
|
|
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": {
|
package/runtime/claude/CLAUDE.md
CHANGED
|
@@ -228,19 +228,21 @@ For each user-directed organizational lookup, show exactly one visible line:
|
|
|
228
228
|
- retrieval that actually queries the connected graph:
|
|
229
229
|
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
230
230
|
|
|
231
|
-
|
|
232
|
-
is only the schema label. When attached, authorized retrieval is complete:
|
|
231
|
+
When `EGREGORE_ORG_CONTEXT_V1` is attached, authorized retrieval is complete:
|
|
233
232
|
never query again that turn, and state any evidence gap. `OPENED_BY_OBSERVE`
|
|
234
233
|
means the evidence is open. A later explicit search starts a new turn.
|
|
235
234
|
|
|
236
|
-
**
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
Shell/tool output does not satisfy this requirement. Do not paraphrase the line.
|
|
235
|
+
**Scope.** Egregore Runtime is for organizational recall only: team memory,
|
|
236
|
+
decisions, handoffs, prior work. Code, files, Git, and tests use the harness's
|
|
237
|
+
normal tools, with no beat and no Runtime call.
|
|
240
238
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
239
|
+
**Visibility is the contract.** Emit it verbatim as a standalone assistant
|
|
240
|
+
message before the first tool call that performs the organizational recall
|
|
241
|
+
(the `bin/search.sh` query or a graph read). Tool output does not satisfy it.
|
|
242
|
+
Do not paraphrase the line.
|
|
243
|
+
|
|
244
|
+
Use Connect only for a graph traversal that actually runs. Emit once per
|
|
245
|
+
episode.
|
|
244
246
|
|
|
245
247
|
**Routing:** Organizational recall always enters Egregore Runtime. The model is
|
|
246
248
|
the semantic intent authority, deciding from meaning rather than fixed phrases.
|
|
@@ -251,20 +253,18 @@ Without sufficient attached context, make exactly one Runtime/QMD call:
|
|
|
251
253
|
bash bin/search.sh query "<concept>" -n 6 --compact --context-packet
|
|
252
254
|
```
|
|
253
255
|
|
|
254
|
-
`--context-packet`
|
|
255
|
-
|
|
256
|
-
Never re-print ranked results, file/rank/excerpt metadata, or raw JSON.
|
|
256
|
+
`--context-packet` attaches the evidence privately; the visible output is the
|
|
257
|
+
attribution line alone. Never re-print ranked results or raw JSON.
|
|
257
258
|
|
|
258
259
|
Do not resolve `memory/` to its sibling repo or start with raw `grep`/`ls`.
|
|
259
|
-
Search
|
|
260
|
-
|
|
260
|
+
Search attaches no graph by default. Open a source only when its excerpt
|
|
261
|
+
cannot support a necessary claim. For current
|
|
261
262
|
team/person synthesis, retain known organization/member names and choose
|
|
262
|
-
`--recent-days` plus `--min-evidence`.
|
|
263
|
-
Grep/Glob for code and exact errors. `/activity`, `/dashboard`, and `/project`
|
|
263
|
+
`--recent-days` plus `--min-evidence`. `/activity`, `/dashboard`, and `/project`
|
|
264
264
|
display bounded status surfaces only when named or directly requested as a
|
|
265
|
-
card.
|
|
266
|
-
|
|
267
|
-
|
|
265
|
+
card. Explained syntheses of current organizational work and prior-work
|
|
266
|
+
discovery are Runtime/QMD recall. Do not run retrieval on unrelated prompts or
|
|
267
|
+
infer graph from recall intent.
|
|
268
268
|
|
|
269
269
|
Do not emit the beat for code search, Git inspection, startup hydration, graph
|
|
270
270
|
writes, ingestion, background sync, maintenance, or internal queries.
|
|
@@ -157,9 +157,8 @@ const NON_SKILL_TOKENS = new Set(['loop', 'fast', 'config', 'clear', 'help']);
|
|
|
157
157
|
// hook delivers there. Rewrite the fallback command to the stdout form and
|
|
158
158
|
// state the same hygiene contract in shell terms: search output is
|
|
159
159
|
// model-internal; the visible reply carries only the retrieval line.
|
|
160
|
-
const CLAUDE_PACKET_NOTE = `\`--context-packet\`
|
|
161
|
-
|
|
162
|
-
Never re-print ranked results, file/rank/excerpt metadata, or raw JSON.`;
|
|
160
|
+
const CLAUDE_PACKET_NOTE = `\`--context-packet\` attaches the evidence privately; the visible output is the
|
|
161
|
+
attribution line alone. Never re-print ranked results or raw JSON.`;
|
|
163
162
|
const SHELL_PACKET_NOTE = `Search output is model-internal: show only the retrieval line and receipts —
|
|
164
163
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.`;
|
|
165
164
|
|
|
@@ -38,7 +38,7 @@ from .runtime import EgregoreRuntime, local_runtime
|
|
|
38
38
|
_ORG_CONTEXT_PREFETCH_PATTERN = re.compile(
|
|
39
39
|
"|".join(
|
|
40
40
|
(
|
|
41
|
-
r"\b(find|locate|dig up|look up|pull up)\b
|
|
41
|
+
r"\b(find|locate|dig up|look up|pull up)\b[^\n]*\b"
|
|
42
42
|
r"(handoff|decision|notes?|docs?|meeting|harvest|quest|reflection)s?\b",
|
|
43
43
|
r"\bdid we (decide|discuss|agree|say|talk about|cover)\b",
|
|
44
44
|
r"\bdo we have (any )?(notes?|docs?|anything|something)( on| about)?\b",
|
|
@@ -161,6 +161,26 @@ def _clear_observe_receipt(root: Path, harness: str) -> None:
|
|
|
161
161
|
pass
|
|
162
162
|
|
|
163
163
|
|
|
164
|
+
def _actor_contract_marker_path(
|
|
165
|
+
root: Path, harness: str, session: str | None = None
|
|
166
|
+
) -> Path:
|
|
167
|
+
"""Gitignored per-session marker: the full actor/retrieval contract was
|
|
168
|
+
already attached once. Later prompts receive a short reminder instead of
|
|
169
|
+
the ~4 KB block. bin/pre-compact.sh removes the marker so the first prompt
|
|
170
|
+
after a compaction re-attaches the full contract.
|
|
171
|
+
|
|
172
|
+
``session`` is the harness's own session id from the hook payload. The
|
|
173
|
+
Egregore session file in the checkout is shared by every concurrent
|
|
174
|
+
session there and rewritten by each new one, so keying on it alone made
|
|
175
|
+
parallel sessions re-attach the full contract on every prompt."""
|
|
176
|
+
|
|
177
|
+
session = re.sub(r"[^A-Za-z0-9_.-]", "-", session or _session_id(root))[:120]
|
|
178
|
+
return (
|
|
179
|
+
root / ".egregore" / "runtime" / "observe"
|
|
180
|
+
/ f"actor-contract-{harness}-{session}.sent"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
164
184
|
def _write_observe_receipt(root: Path, harness: str, prompt: str, context) -> None:
|
|
165
185
|
"""Record that this prompt already received useful authorized evidence.
|
|
166
186
|
|
|
@@ -378,6 +398,37 @@ def _query(args: argparse.Namespace) -> int:
|
|
|
378
398
|
return 0
|
|
379
399
|
|
|
380
400
|
|
|
401
|
+
_PASTED_OUTPUT_LINE = re.compile(
|
|
402
|
+
r"^(?:"
|
|
403
|
+
r"[ MADRCU?!]{2}\s+\S" # git status --short / porcelain rows
|
|
404
|
+
r"|[▶❯»]\s" # terminal prompt markers
|
|
405
|
+
r"|\$\s\S" # shell prompt
|
|
406
|
+
r"|(?:\+\+\+|---|@@)\s" # unified diff
|
|
407
|
+
r"|diff --git\b"
|
|
408
|
+
r"|Traceback \(most recent call last\)"
|
|
409
|
+
r"|\s+File \"[^\"]+\", line \d+"
|
|
410
|
+
r"|\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}" # log timestamps
|
|
411
|
+
r"|[A-Za-z0-9_./-]+/[A-Za-z0-9_.-]+\.[a-z]{1,6}$" # a bare path
|
|
412
|
+
r")"
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def _looks_like_pasted_output(prompt: str) -> bool:
|
|
417
|
+
"""True for terminal output, diffs, logs, and code blocks pasted into a prompt.
|
|
418
|
+
|
|
419
|
+
Those carry words like "handoff", "notes", or "docs" by accident; running a
|
|
420
|
+
retrieval on them attaches unrelated evidence and costs seconds. The actor
|
|
421
|
+
context still tells the model to recall once if the prompt truly needs it.
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
if "```" in prompt:
|
|
425
|
+
return True
|
|
426
|
+
lines = [line for line in prompt.splitlines() if line.strip()]
|
|
427
|
+
if len(lines) >= 8:
|
|
428
|
+
return True
|
|
429
|
+
return sum(1 for line in lines if _PASTED_OUTPUT_LINE.match(line)) >= 2
|
|
430
|
+
|
|
431
|
+
|
|
381
432
|
def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
382
433
|
"""Return whether Observe should prefetch likely organizational context.
|
|
383
434
|
|
|
@@ -390,6 +441,7 @@ def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
|
390
441
|
return bool(
|
|
391
442
|
prompt
|
|
392
443
|
and not _EXPLICIT_SEARCH.search(prompt)
|
|
444
|
+
and not _looks_like_pasted_output(prompt)
|
|
393
445
|
and (
|
|
394
446
|
_ORG_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
395
447
|
or _ORG_RITUAL_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
@@ -414,8 +466,22 @@ def prompt_requests_actor_context(prompt: str) -> bool:
|
|
|
414
466
|
return bool(prompt and prompt.strip())
|
|
415
467
|
|
|
416
468
|
|
|
417
|
-
|
|
418
|
-
"
|
|
469
|
+
_RECALL_ONLY_SCOPE = (
|
|
470
|
+
"Egregore Runtime is for organizational recall and memory only: team memory, "
|
|
471
|
+
"decisions, handoffs, meetings, prior work. Code search, file reads, Git, tests, "
|
|
472
|
+
"and every other task use the harness's normal tools (Grep, Glob, Read, Bash) "
|
|
473
|
+
"with no retrieval ritual and no Runtime call."
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _actor_context_block(
|
|
478
|
+
runtime: EgregoreRuntime, root: Path, harness: str, *, full: bool = True
|
|
479
|
+
) -> str:
|
|
480
|
+
"""Render the stable identity and the recall contract for harness rituals.
|
|
481
|
+
|
|
482
|
+
``full`` renders the complete contract (once per session); otherwise a
|
|
483
|
+
short reminder that keeps identity and the recall-only scope in view.
|
|
484
|
+
"""
|
|
419
485
|
|
|
420
486
|
actor_context = _actor(runtime, root, harness)
|
|
421
487
|
actor = actor_context.actor
|
|
@@ -435,6 +501,22 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
435
501
|
search_command = 'bash bin/search.sh query "<concept>" -n 6 --compact'
|
|
436
502
|
if harness == "claude":
|
|
437
503
|
search_command += " --context-packet"
|
|
504
|
+
if not full:
|
|
505
|
+
return "\n".join(
|
|
506
|
+
(
|
|
507
|
+
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
508
|
+
"Reminder — the full contract was attached earlier in this session.",
|
|
509
|
+
f"Actor: {actor.display_name} · Actor ID: {actor.actor_id} · "
|
|
510
|
+
f"Organization ID: {actor_context.profile.org_id} · Runtime root: {root}",
|
|
511
|
+
_RECALL_ONLY_SCOPE,
|
|
512
|
+
"When a prompt needs that recall and no EGREGORE_ORG_CONTEXT_V1 block is "
|
|
513
|
+
f"attached, run exactly one `{search_command}`; exact latest/oldest/open "
|
|
514
|
+
"handoff questions use `bash bin/search.sh handoffs …` instead.",
|
|
515
|
+
"`me` and `myself` mean this Actor ID and display name; never infer identity "
|
|
516
|
+
"from the OS user, Git, or GitHub names.",
|
|
517
|
+
"END_EGREGORE_ACTOR_CONTEXT_V1",
|
|
518
|
+
)
|
|
519
|
+
)
|
|
438
520
|
return "\n".join(
|
|
439
521
|
(
|
|
440
522
|
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
@@ -451,6 +533,7 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
451
533
|
f"Runtime root: {root}",
|
|
452
534
|
"Run Egregore retrieval and workflow commands from this Runtime root. "
|
|
453
535
|
"Do not fall back to a launch checkout named elsewhere in the session.",
|
|
536
|
+
_RECALL_ONLY_SCOPE,
|
|
454
537
|
"Organizational retrieval status: NOT_PERFORMED. This actor-only block "
|
|
455
538
|
"does not mean organizational recall is unnecessary.",
|
|
456
539
|
"Interpret the user's intent semantically, without requiring trigger words. "
|
|
@@ -687,11 +770,21 @@ def _prompt_hook(args: argparse.Namespace) -> int:
|
|
|
687
770
|
args.limit,
|
|
688
771
|
)
|
|
689
772
|
else:
|
|
773
|
+
hook_session = str(payload.get("session_id") or "").strip() or None
|
|
774
|
+
marker = _actor_contract_marker_path(root, args.harness, hook_session)
|
|
775
|
+
full = not marker.exists()
|
|
690
776
|
additional_context = _actor_context_block(
|
|
691
777
|
runtime,
|
|
692
778
|
root,
|
|
693
779
|
args.harness,
|
|
780
|
+
full=full,
|
|
694
781
|
)
|
|
782
|
+
if full:
|
|
783
|
+
try:
|
|
784
|
+
marker.parent.mkdir(parents=True, exist_ok=True)
|
|
785
|
+
marker.write_text(datetime.now(UTC).isoformat(), encoding="utf-8")
|
|
786
|
+
except OSError:
|
|
787
|
+
pass
|
|
695
788
|
except Exception as exc: # Hooks are advisory and must never block a prompt.
|
|
696
789
|
additional_context = (
|
|
697
790
|
"Egregore Runtime context was requested but the Local Runtime is unavailable "
|
package/runtime/codex/AGENTS.md
CHANGED
|
@@ -258,19 +258,21 @@ For each user-directed organizational lookup, show exactly one visible line:
|
|
|
258
258
|
- retrieval that actually queries the connected graph:
|
|
259
259
|
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
260
260
|
|
|
261
|
-
|
|
262
|
-
is only the schema label. When attached, authorized retrieval is complete:
|
|
261
|
+
When `EGREGORE_ORG_CONTEXT_V1` is attached, authorized retrieval is complete:
|
|
263
262
|
never query again that turn, and state any evidence gap. `OPENED_BY_OBSERVE`
|
|
264
263
|
means the evidence is open. A later explicit search starts a new turn.
|
|
265
264
|
|
|
266
|
-
**
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Shell/tool output does not satisfy this requirement. Do not paraphrase the line.
|
|
265
|
+
**Scope.** Egregore Runtime is for organizational recall only: team memory,
|
|
266
|
+
decisions, handoffs, prior work. Code, files, Git, and tests use the harness's
|
|
267
|
+
normal tools, with no beat and no Runtime call.
|
|
270
268
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
**Visibility is the contract.** Emit it verbatim as a standalone assistant
|
|
270
|
+
message before the first tool call that performs the organizational recall
|
|
271
|
+
(the `bin/search.sh` query or a graph read). Tool output does not satisfy it.
|
|
272
|
+
Do not paraphrase the line.
|
|
273
|
+
|
|
274
|
+
Use Connect only for a graph traversal that actually runs. Emit once per
|
|
275
|
+
episode.
|
|
274
276
|
|
|
275
277
|
**Routing:** Organizational recall always enters Egregore Runtime. The model is
|
|
276
278
|
the semantic intent authority, deciding from meaning rather than fixed phrases.
|
|
@@ -285,15 +287,14 @@ Search output is model-internal: show only the retrieval line and receipts —
|
|
|
285
287
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.
|
|
286
288
|
|
|
287
289
|
Do not resolve `memory/` to its sibling repo or start with raw `grep`/`ls`.
|
|
288
|
-
Search
|
|
289
|
-
|
|
290
|
+
Search attaches no graph by default. Open a source only when its excerpt
|
|
291
|
+
cannot support a necessary claim. For current
|
|
290
292
|
team/person synthesis, retain known organization/member names and choose
|
|
291
|
-
`--recent-days` plus `--min-evidence`.
|
|
292
|
-
Grep/Glob for code and exact errors. `$activity`, `$dashboard`, and `$project`
|
|
293
|
+
`--recent-days` plus `--min-evidence`. `$activity`, `$dashboard`, and `$project`
|
|
293
294
|
display bounded status surfaces only when named or directly requested as a
|
|
294
|
-
card.
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
card. Explained syntheses of current organizational work and prior-work
|
|
296
|
+
discovery are Runtime/QMD recall. Do not run retrieval on unrelated prompts or
|
|
297
|
+
infer graph from recall intent.
|
|
297
298
|
|
|
298
299
|
Do not emit the beat for code search, Git inspection, startup hydration, graph
|
|
299
300
|
writes, ingestion, background sync, maintenance, or internal queries.
|
|
@@ -157,9 +157,8 @@ const NON_SKILL_TOKENS = new Set(['loop', 'fast', 'config', 'clear', 'help']);
|
|
|
157
157
|
// hook delivers there. Rewrite the fallback command to the stdout form and
|
|
158
158
|
// state the same hygiene contract in shell terms: search output is
|
|
159
159
|
// model-internal; the visible reply carries only the retrieval line.
|
|
160
|
-
const CLAUDE_PACKET_NOTE = `\`--context-packet\`
|
|
161
|
-
|
|
162
|
-
Never re-print ranked results, file/rank/excerpt metadata, or raw JSON.`;
|
|
160
|
+
const CLAUDE_PACKET_NOTE = `\`--context-packet\` attaches the evidence privately; the visible output is the
|
|
161
|
+
attribution line alone. Never re-print ranked results or raw JSON.`;
|
|
163
162
|
const SHELL_PACKET_NOTE = `Search output is model-internal: show only the retrieval line and receipts —
|
|
164
163
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.`;
|
|
165
164
|
|
|
@@ -38,7 +38,7 @@ from .runtime import EgregoreRuntime, local_runtime
|
|
|
38
38
|
_ORG_CONTEXT_PREFETCH_PATTERN = re.compile(
|
|
39
39
|
"|".join(
|
|
40
40
|
(
|
|
41
|
-
r"\b(find|locate|dig up|look up|pull up)\b
|
|
41
|
+
r"\b(find|locate|dig up|look up|pull up)\b[^\n]*\b"
|
|
42
42
|
r"(handoff|decision|notes?|docs?|meeting|harvest|quest|reflection)s?\b",
|
|
43
43
|
r"\bdid we (decide|discuss|agree|say|talk about|cover)\b",
|
|
44
44
|
r"\bdo we have (any )?(notes?|docs?|anything|something)( on| about)?\b",
|
|
@@ -161,6 +161,26 @@ def _clear_observe_receipt(root: Path, harness: str) -> None:
|
|
|
161
161
|
pass
|
|
162
162
|
|
|
163
163
|
|
|
164
|
+
def _actor_contract_marker_path(
|
|
165
|
+
root: Path, harness: str, session: str | None = None
|
|
166
|
+
) -> Path:
|
|
167
|
+
"""Gitignored per-session marker: the full actor/retrieval contract was
|
|
168
|
+
already attached once. Later prompts receive a short reminder instead of
|
|
169
|
+
the ~4 KB block. bin/pre-compact.sh removes the marker so the first prompt
|
|
170
|
+
after a compaction re-attaches the full contract.
|
|
171
|
+
|
|
172
|
+
``session`` is the harness's own session id from the hook payload. The
|
|
173
|
+
Egregore session file in the checkout is shared by every concurrent
|
|
174
|
+
session there and rewritten by each new one, so keying on it alone made
|
|
175
|
+
parallel sessions re-attach the full contract on every prompt."""
|
|
176
|
+
|
|
177
|
+
session = re.sub(r"[^A-Za-z0-9_.-]", "-", session or _session_id(root))[:120]
|
|
178
|
+
return (
|
|
179
|
+
root / ".egregore" / "runtime" / "observe"
|
|
180
|
+
/ f"actor-contract-{harness}-{session}.sent"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
164
184
|
def _write_observe_receipt(root: Path, harness: str, prompt: str, context) -> None:
|
|
165
185
|
"""Record that this prompt already received useful authorized evidence.
|
|
166
186
|
|
|
@@ -378,6 +398,37 @@ def _query(args: argparse.Namespace) -> int:
|
|
|
378
398
|
return 0
|
|
379
399
|
|
|
380
400
|
|
|
401
|
+
_PASTED_OUTPUT_LINE = re.compile(
|
|
402
|
+
r"^(?:"
|
|
403
|
+
r"[ MADRCU?!]{2}\s+\S" # git status --short / porcelain rows
|
|
404
|
+
r"|[▶❯»]\s" # terminal prompt markers
|
|
405
|
+
r"|\$\s\S" # shell prompt
|
|
406
|
+
r"|(?:\+\+\+|---|@@)\s" # unified diff
|
|
407
|
+
r"|diff --git\b"
|
|
408
|
+
r"|Traceback \(most recent call last\)"
|
|
409
|
+
r"|\s+File \"[^\"]+\", line \d+"
|
|
410
|
+
r"|\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}" # log timestamps
|
|
411
|
+
r"|[A-Za-z0-9_./-]+/[A-Za-z0-9_.-]+\.[a-z]{1,6}$" # a bare path
|
|
412
|
+
r")"
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def _looks_like_pasted_output(prompt: str) -> bool:
|
|
417
|
+
"""True for terminal output, diffs, logs, and code blocks pasted into a prompt.
|
|
418
|
+
|
|
419
|
+
Those carry words like "handoff", "notes", or "docs" by accident; running a
|
|
420
|
+
retrieval on them attaches unrelated evidence and costs seconds. The actor
|
|
421
|
+
context still tells the model to recall once if the prompt truly needs it.
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
if "```" in prompt:
|
|
425
|
+
return True
|
|
426
|
+
lines = [line for line in prompt.splitlines() if line.strip()]
|
|
427
|
+
if len(lines) >= 8:
|
|
428
|
+
return True
|
|
429
|
+
return sum(1 for line in lines if _PASTED_OUTPUT_LINE.match(line)) >= 2
|
|
430
|
+
|
|
431
|
+
|
|
381
432
|
def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
382
433
|
"""Return whether Observe should prefetch likely organizational context.
|
|
383
434
|
|
|
@@ -390,6 +441,7 @@ def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
|
390
441
|
return bool(
|
|
391
442
|
prompt
|
|
392
443
|
and not _EXPLICIT_SEARCH.search(prompt)
|
|
444
|
+
and not _looks_like_pasted_output(prompt)
|
|
393
445
|
and (
|
|
394
446
|
_ORG_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
395
447
|
or _ORG_RITUAL_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
@@ -414,8 +466,22 @@ def prompt_requests_actor_context(prompt: str) -> bool:
|
|
|
414
466
|
return bool(prompt and prompt.strip())
|
|
415
467
|
|
|
416
468
|
|
|
417
|
-
|
|
418
|
-
"
|
|
469
|
+
_RECALL_ONLY_SCOPE = (
|
|
470
|
+
"Egregore Runtime is for organizational recall and memory only: team memory, "
|
|
471
|
+
"decisions, handoffs, meetings, prior work. Code search, file reads, Git, tests, "
|
|
472
|
+
"and every other task use the harness's normal tools (Grep, Glob, Read, Bash) "
|
|
473
|
+
"with no retrieval ritual and no Runtime call."
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _actor_context_block(
|
|
478
|
+
runtime: EgregoreRuntime, root: Path, harness: str, *, full: bool = True
|
|
479
|
+
) -> str:
|
|
480
|
+
"""Render the stable identity and the recall contract for harness rituals.
|
|
481
|
+
|
|
482
|
+
``full`` renders the complete contract (once per session); otherwise a
|
|
483
|
+
short reminder that keeps identity and the recall-only scope in view.
|
|
484
|
+
"""
|
|
419
485
|
|
|
420
486
|
actor_context = _actor(runtime, root, harness)
|
|
421
487
|
actor = actor_context.actor
|
|
@@ -435,6 +501,22 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
435
501
|
search_command = 'bash bin/search.sh query "<concept>" -n 6 --compact'
|
|
436
502
|
if harness == "claude":
|
|
437
503
|
search_command += " --context-packet"
|
|
504
|
+
if not full:
|
|
505
|
+
return "\n".join(
|
|
506
|
+
(
|
|
507
|
+
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
508
|
+
"Reminder — the full contract was attached earlier in this session.",
|
|
509
|
+
f"Actor: {actor.display_name} · Actor ID: {actor.actor_id} · "
|
|
510
|
+
f"Organization ID: {actor_context.profile.org_id} · Runtime root: {root}",
|
|
511
|
+
_RECALL_ONLY_SCOPE,
|
|
512
|
+
"When a prompt needs that recall and no EGREGORE_ORG_CONTEXT_V1 block is "
|
|
513
|
+
f"attached, run exactly one `{search_command}`; exact latest/oldest/open "
|
|
514
|
+
"handoff questions use `bash bin/search.sh handoffs …` instead.",
|
|
515
|
+
"`me` and `myself` mean this Actor ID and display name; never infer identity "
|
|
516
|
+
"from the OS user, Git, or GitHub names.",
|
|
517
|
+
"END_EGREGORE_ACTOR_CONTEXT_V1",
|
|
518
|
+
)
|
|
519
|
+
)
|
|
438
520
|
return "\n".join(
|
|
439
521
|
(
|
|
440
522
|
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
@@ -451,6 +533,7 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
451
533
|
f"Runtime root: {root}",
|
|
452
534
|
"Run Egregore retrieval and workflow commands from this Runtime root. "
|
|
453
535
|
"Do not fall back to a launch checkout named elsewhere in the session.",
|
|
536
|
+
_RECALL_ONLY_SCOPE,
|
|
454
537
|
"Organizational retrieval status: NOT_PERFORMED. This actor-only block "
|
|
455
538
|
"does not mean organizational recall is unnecessary.",
|
|
456
539
|
"Interpret the user's intent semantically, without requiring trigger words. "
|
|
@@ -687,11 +770,21 @@ def _prompt_hook(args: argparse.Namespace) -> int:
|
|
|
687
770
|
args.limit,
|
|
688
771
|
)
|
|
689
772
|
else:
|
|
773
|
+
hook_session = str(payload.get("session_id") or "").strip() or None
|
|
774
|
+
marker = _actor_contract_marker_path(root, args.harness, hook_session)
|
|
775
|
+
full = not marker.exists()
|
|
690
776
|
additional_context = _actor_context_block(
|
|
691
777
|
runtime,
|
|
692
778
|
root,
|
|
693
779
|
args.harness,
|
|
780
|
+
full=full,
|
|
694
781
|
)
|
|
782
|
+
if full:
|
|
783
|
+
try:
|
|
784
|
+
marker.parent.mkdir(parents=True, exist_ok=True)
|
|
785
|
+
marker.write_text(datetime.now(UTC).isoformat(), encoding="utf-8")
|
|
786
|
+
except OSError:
|
|
787
|
+
pass
|
|
695
788
|
except Exception as exc: # Hooks are advisory and must never block a prompt.
|
|
696
789
|
additional_context = (
|
|
697
790
|
"Egregore Runtime context was requested but the Local Runtime is unavailable "
|
|
@@ -183,19 +183,21 @@ For each user-directed organizational lookup, show exactly one visible line:
|
|
|
183
183
|
- retrieval that actually queries the connected graph:
|
|
184
184
|
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
is only the schema label. When attached, authorized retrieval is complete:
|
|
186
|
+
When `EGREGORE_ORG_CONTEXT_V1` is attached, authorized retrieval is complete:
|
|
188
187
|
never query again that turn, and state any evidence gap. `OPENED_BY_OBSERVE`
|
|
189
188
|
means the evidence is open. A later explicit search starts a new turn.
|
|
190
189
|
|
|
191
|
-
**
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
Shell/tool output does not satisfy this requirement. Do not paraphrase the line.
|
|
190
|
+
**Scope.** Egregore Runtime is for organizational recall only: team memory,
|
|
191
|
+
decisions, handoffs, prior work. Code, files, Git, and tests use the harness's
|
|
192
|
+
normal tools, with no beat and no Runtime call.
|
|
195
193
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
194
|
+
**Visibility is the contract.** Emit it verbatim as a standalone assistant
|
|
195
|
+
message before the first tool call that performs the organizational recall
|
|
196
|
+
(the `bin/search.sh` query or a graph read). Tool output does not satisfy it.
|
|
197
|
+
Do not paraphrase the line.
|
|
198
|
+
|
|
199
|
+
Use Connect only for a graph traversal that actually runs. Emit once per
|
|
200
|
+
episode.
|
|
199
201
|
|
|
200
202
|
**Routing:** Organizational recall always enters Egregore Runtime. The model is
|
|
201
203
|
the semantic intent authority, deciding from meaning rather than fixed phrases.
|
|
@@ -210,15 +212,14 @@ Search output is model-internal: show only the retrieval line and receipts —
|
|
|
210
212
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.
|
|
211
213
|
|
|
212
214
|
Do not resolve `memory/` to its sibling repo or start with raw `grep`/`ls`.
|
|
213
|
-
Search
|
|
214
|
-
|
|
215
|
+
Search attaches no graph by default. Open a source only when its excerpt
|
|
216
|
+
cannot support a necessary claim. For current
|
|
215
217
|
team/person synthesis, retain known organization/member names and choose
|
|
216
|
-
`--recent-days` plus `--min-evidence`.
|
|
217
|
-
Grep/Glob for code and exact errors. `/activity`, `/dashboard`, and `/project`
|
|
218
|
+
`--recent-days` plus `--min-evidence`. `/activity`, `/dashboard`, and `/project`
|
|
218
219
|
display bounded status surfaces only when named or directly requested as a
|
|
219
|
-
card.
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
card. Explained syntheses of current organizational work and prior-work
|
|
221
|
+
discovery are Runtime/QMD recall. Do not run retrieval on unrelated prompts or
|
|
222
|
+
infer graph from recall intent.
|
|
222
223
|
|
|
223
224
|
Do not emit the beat for code search, Git inspection, startup hydration, graph
|
|
224
225
|
writes, ingestion, background sync, maintenance, or internal queries.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"generatedBy": "bin/pi-render-spec.mjs",
|
|
3
3
|
"source": "AGENTS.md generated Codex spec",
|
|
4
|
-
"sourceHash": "
|
|
5
|
-
"outputHash": "
|
|
4
|
+
"sourceHash": "496480654dd9",
|
|
5
|
+
"outputHash": "6eef1a6daeb9",
|
|
6
6
|
"adaptations": [
|
|
7
7
|
"Pi project trust and APPEND_SYSTEM delivery",
|
|
8
8
|
"Pi tool_call branch gate",
|
package/runtime/pi/AGENTS.md
CHANGED
|
@@ -258,19 +258,21 @@ For each user-directed organizational lookup, show exactly one visible line:
|
|
|
258
258
|
- retrieval that actually queries the connected graph:
|
|
259
259
|
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
260
260
|
|
|
261
|
-
|
|
262
|
-
is only the schema label. When attached, authorized retrieval is complete:
|
|
261
|
+
When `EGREGORE_ORG_CONTEXT_V1` is attached, authorized retrieval is complete:
|
|
263
262
|
never query again that turn, and state any evidence gap. `OPENED_BY_OBSERVE`
|
|
264
263
|
means the evidence is open. A later explicit search starts a new turn.
|
|
265
264
|
|
|
266
|
-
**
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Shell/tool output does not satisfy this requirement. Do not paraphrase the line.
|
|
265
|
+
**Scope.** Egregore Runtime is for organizational recall only: team memory,
|
|
266
|
+
decisions, handoffs, prior work. Code, files, Git, and tests use the harness's
|
|
267
|
+
normal tools, with no beat and no Runtime call.
|
|
270
268
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
**Visibility is the contract.** Emit it verbatim as a standalone assistant
|
|
270
|
+
message before the first tool call that performs the organizational recall
|
|
271
|
+
(the `bin/search.sh` query or a graph read). Tool output does not satisfy it.
|
|
272
|
+
Do not paraphrase the line.
|
|
273
|
+
|
|
274
|
+
Use Connect only for a graph traversal that actually runs. Emit once per
|
|
275
|
+
episode.
|
|
274
276
|
|
|
275
277
|
**Routing:** Organizational recall always enters Egregore Runtime. The model is
|
|
276
278
|
the semantic intent authority, deciding from meaning rather than fixed phrases.
|
|
@@ -285,15 +287,14 @@ Search output is model-internal: show only the retrieval line and receipts —
|
|
|
285
287
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.
|
|
286
288
|
|
|
287
289
|
Do not resolve `memory/` to its sibling repo or start with raw `grep`/`ls`.
|
|
288
|
-
Search
|
|
289
|
-
|
|
290
|
+
Search attaches no graph by default. Open a source only when its excerpt
|
|
291
|
+
cannot support a necessary claim. For current
|
|
290
292
|
team/person synthesis, retain known organization/member names and choose
|
|
291
|
-
`--recent-days` plus `--min-evidence`.
|
|
292
|
-
Grep/Glob for code and exact errors. `$activity`, `$dashboard`, and `$project`
|
|
293
|
+
`--recent-days` plus `--min-evidence`. `$activity`, `$dashboard`, and `$project`
|
|
293
294
|
display bounded status surfaces only when named or directly requested as a
|
|
294
|
-
card.
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
card. Explained syntheses of current organizational work and prior-work
|
|
296
|
+
discovery are Runtime/QMD recall. Do not run retrieval on unrelated prompts or
|
|
297
|
+
infer graph from recall intent.
|
|
297
298
|
|
|
298
299
|
Do not emit the beat for code search, Git inspection, startup hydration, graph
|
|
299
300
|
writes, ingestion, background sync, maintenance, or internal queries.
|
|
@@ -157,9 +157,8 @@ const NON_SKILL_TOKENS = new Set(['loop', 'fast', 'config', 'clear', 'help']);
|
|
|
157
157
|
// hook delivers there. Rewrite the fallback command to the stdout form and
|
|
158
158
|
// state the same hygiene contract in shell terms: search output is
|
|
159
159
|
// model-internal; the visible reply carries only the retrieval line.
|
|
160
|
-
const CLAUDE_PACKET_NOTE = `\`--context-packet\`
|
|
161
|
-
|
|
162
|
-
Never re-print ranked results, file/rank/excerpt metadata, or raw JSON.`;
|
|
160
|
+
const CLAUDE_PACKET_NOTE = `\`--context-packet\` attaches the evidence privately; the visible output is the
|
|
161
|
+
attribution line alone. Never re-print ranked results or raw JSON.`;
|
|
163
162
|
const SHELL_PACKET_NOTE = `Search output is model-internal: show only the retrieval line and receipts —
|
|
164
163
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.`;
|
|
165
164
|
|
|
@@ -38,7 +38,7 @@ from .runtime import EgregoreRuntime, local_runtime
|
|
|
38
38
|
_ORG_CONTEXT_PREFETCH_PATTERN = re.compile(
|
|
39
39
|
"|".join(
|
|
40
40
|
(
|
|
41
|
-
r"\b(find|locate|dig up|look up|pull up)\b
|
|
41
|
+
r"\b(find|locate|dig up|look up|pull up)\b[^\n]*\b"
|
|
42
42
|
r"(handoff|decision|notes?|docs?|meeting|harvest|quest|reflection)s?\b",
|
|
43
43
|
r"\bdid we (decide|discuss|agree|say|talk about|cover)\b",
|
|
44
44
|
r"\bdo we have (any )?(notes?|docs?|anything|something)( on| about)?\b",
|
|
@@ -161,6 +161,26 @@ def _clear_observe_receipt(root: Path, harness: str) -> None:
|
|
|
161
161
|
pass
|
|
162
162
|
|
|
163
163
|
|
|
164
|
+
def _actor_contract_marker_path(
|
|
165
|
+
root: Path, harness: str, session: str | None = None
|
|
166
|
+
) -> Path:
|
|
167
|
+
"""Gitignored per-session marker: the full actor/retrieval contract was
|
|
168
|
+
already attached once. Later prompts receive a short reminder instead of
|
|
169
|
+
the ~4 KB block. bin/pre-compact.sh removes the marker so the first prompt
|
|
170
|
+
after a compaction re-attaches the full contract.
|
|
171
|
+
|
|
172
|
+
``session`` is the harness's own session id from the hook payload. The
|
|
173
|
+
Egregore session file in the checkout is shared by every concurrent
|
|
174
|
+
session there and rewritten by each new one, so keying on it alone made
|
|
175
|
+
parallel sessions re-attach the full contract on every prompt."""
|
|
176
|
+
|
|
177
|
+
session = re.sub(r"[^A-Za-z0-9_.-]", "-", session or _session_id(root))[:120]
|
|
178
|
+
return (
|
|
179
|
+
root / ".egregore" / "runtime" / "observe"
|
|
180
|
+
/ f"actor-contract-{harness}-{session}.sent"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
164
184
|
def _write_observe_receipt(root: Path, harness: str, prompt: str, context) -> None:
|
|
165
185
|
"""Record that this prompt already received useful authorized evidence.
|
|
166
186
|
|
|
@@ -378,6 +398,37 @@ def _query(args: argparse.Namespace) -> int:
|
|
|
378
398
|
return 0
|
|
379
399
|
|
|
380
400
|
|
|
401
|
+
_PASTED_OUTPUT_LINE = re.compile(
|
|
402
|
+
r"^(?:"
|
|
403
|
+
r"[ MADRCU?!]{2}\s+\S" # git status --short / porcelain rows
|
|
404
|
+
r"|[▶❯»]\s" # terminal prompt markers
|
|
405
|
+
r"|\$\s\S" # shell prompt
|
|
406
|
+
r"|(?:\+\+\+|---|@@)\s" # unified diff
|
|
407
|
+
r"|diff --git\b"
|
|
408
|
+
r"|Traceback \(most recent call last\)"
|
|
409
|
+
r"|\s+File \"[^\"]+\", line \d+"
|
|
410
|
+
r"|\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}" # log timestamps
|
|
411
|
+
r"|[A-Za-z0-9_./-]+/[A-Za-z0-9_.-]+\.[a-z]{1,6}$" # a bare path
|
|
412
|
+
r")"
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def _looks_like_pasted_output(prompt: str) -> bool:
|
|
417
|
+
"""True for terminal output, diffs, logs, and code blocks pasted into a prompt.
|
|
418
|
+
|
|
419
|
+
Those carry words like "handoff", "notes", or "docs" by accident; running a
|
|
420
|
+
retrieval on them attaches unrelated evidence and costs seconds. The actor
|
|
421
|
+
context still tells the model to recall once if the prompt truly needs it.
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
if "```" in prompt:
|
|
425
|
+
return True
|
|
426
|
+
lines = [line for line in prompt.splitlines() if line.strip()]
|
|
427
|
+
if len(lines) >= 8:
|
|
428
|
+
return True
|
|
429
|
+
return sum(1 for line in lines if _PASTED_OUTPUT_LINE.match(line)) >= 2
|
|
430
|
+
|
|
431
|
+
|
|
381
432
|
def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
382
433
|
"""Return whether Observe should prefetch likely organizational context.
|
|
383
434
|
|
|
@@ -390,6 +441,7 @@ def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
|
390
441
|
return bool(
|
|
391
442
|
prompt
|
|
392
443
|
and not _EXPLICIT_SEARCH.search(prompt)
|
|
444
|
+
and not _looks_like_pasted_output(prompt)
|
|
393
445
|
and (
|
|
394
446
|
_ORG_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
395
447
|
or _ORG_RITUAL_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
@@ -414,8 +466,22 @@ def prompt_requests_actor_context(prompt: str) -> bool:
|
|
|
414
466
|
return bool(prompt and prompt.strip())
|
|
415
467
|
|
|
416
468
|
|
|
417
|
-
|
|
418
|
-
"
|
|
469
|
+
_RECALL_ONLY_SCOPE = (
|
|
470
|
+
"Egregore Runtime is for organizational recall and memory only: team memory, "
|
|
471
|
+
"decisions, handoffs, meetings, prior work. Code search, file reads, Git, tests, "
|
|
472
|
+
"and every other task use the harness's normal tools (Grep, Glob, Read, Bash) "
|
|
473
|
+
"with no retrieval ritual and no Runtime call."
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _actor_context_block(
|
|
478
|
+
runtime: EgregoreRuntime, root: Path, harness: str, *, full: bool = True
|
|
479
|
+
) -> str:
|
|
480
|
+
"""Render the stable identity and the recall contract for harness rituals.
|
|
481
|
+
|
|
482
|
+
``full`` renders the complete contract (once per session); otherwise a
|
|
483
|
+
short reminder that keeps identity and the recall-only scope in view.
|
|
484
|
+
"""
|
|
419
485
|
|
|
420
486
|
actor_context = _actor(runtime, root, harness)
|
|
421
487
|
actor = actor_context.actor
|
|
@@ -435,6 +501,22 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
435
501
|
search_command = 'bash bin/search.sh query "<concept>" -n 6 --compact'
|
|
436
502
|
if harness == "claude":
|
|
437
503
|
search_command += " --context-packet"
|
|
504
|
+
if not full:
|
|
505
|
+
return "\n".join(
|
|
506
|
+
(
|
|
507
|
+
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
508
|
+
"Reminder — the full contract was attached earlier in this session.",
|
|
509
|
+
f"Actor: {actor.display_name} · Actor ID: {actor.actor_id} · "
|
|
510
|
+
f"Organization ID: {actor_context.profile.org_id} · Runtime root: {root}",
|
|
511
|
+
_RECALL_ONLY_SCOPE,
|
|
512
|
+
"When a prompt needs that recall and no EGREGORE_ORG_CONTEXT_V1 block is "
|
|
513
|
+
f"attached, run exactly one `{search_command}`; exact latest/oldest/open "
|
|
514
|
+
"handoff questions use `bash bin/search.sh handoffs …` instead.",
|
|
515
|
+
"`me` and `myself` mean this Actor ID and display name; never infer identity "
|
|
516
|
+
"from the OS user, Git, or GitHub names.",
|
|
517
|
+
"END_EGREGORE_ACTOR_CONTEXT_V1",
|
|
518
|
+
)
|
|
519
|
+
)
|
|
438
520
|
return "\n".join(
|
|
439
521
|
(
|
|
440
522
|
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
@@ -451,6 +533,7 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
451
533
|
f"Runtime root: {root}",
|
|
452
534
|
"Run Egregore retrieval and workflow commands from this Runtime root. "
|
|
453
535
|
"Do not fall back to a launch checkout named elsewhere in the session.",
|
|
536
|
+
_RECALL_ONLY_SCOPE,
|
|
454
537
|
"Organizational retrieval status: NOT_PERFORMED. This actor-only block "
|
|
455
538
|
"does not mean organizational recall is unnecessary.",
|
|
456
539
|
"Interpret the user's intent semantically, without requiring trigger words. "
|
|
@@ -687,11 +770,21 @@ def _prompt_hook(args: argparse.Namespace) -> int:
|
|
|
687
770
|
args.limit,
|
|
688
771
|
)
|
|
689
772
|
else:
|
|
773
|
+
hook_session = str(payload.get("session_id") or "").strip() or None
|
|
774
|
+
marker = _actor_contract_marker_path(root, args.harness, hook_session)
|
|
775
|
+
full = not marker.exists()
|
|
690
776
|
additional_context = _actor_context_block(
|
|
691
777
|
runtime,
|
|
692
778
|
root,
|
|
693
779
|
args.harness,
|
|
780
|
+
full=full,
|
|
694
781
|
)
|
|
782
|
+
if full:
|
|
783
|
+
try:
|
|
784
|
+
marker.parent.mkdir(parents=True, exist_ok=True)
|
|
785
|
+
marker.write_text(datetime.now(UTC).isoformat(), encoding="utf-8")
|
|
786
|
+
except OSError:
|
|
787
|
+
pass
|
|
695
788
|
except Exception as exc: # Hooks are advisory and must never block a prompt.
|
|
696
789
|
additional_context = (
|
|
697
790
|
"Egregore Runtime context was requested but the Local Runtime is unavailable "
|
|
@@ -185,19 +185,21 @@ For each user-directed organizational lookup, show exactly one visible line:
|
|
|
185
185
|
- retrieval that actually queries the connected graph:
|
|
186
186
|
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
187
187
|
|
|
188
|
-
|
|
189
|
-
is only the schema label. When attached, authorized retrieval is complete:
|
|
188
|
+
When `EGREGORE_ORG_CONTEXT_V1` is attached, authorized retrieval is complete:
|
|
190
189
|
never query again that turn, and state any evidence gap. `OPENED_BY_OBSERVE`
|
|
191
190
|
means the evidence is open. A later explicit search starts a new turn.
|
|
192
191
|
|
|
193
|
-
**
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
Shell/tool output does not satisfy this requirement. Do not paraphrase the line.
|
|
192
|
+
**Scope.** Egregore Runtime is for organizational recall only: team memory,
|
|
193
|
+
decisions, handoffs, prior work. Code, files, Git, and tests use the harness's
|
|
194
|
+
normal tools, with no beat and no Runtime call.
|
|
197
195
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
196
|
+
**Visibility is the contract.** Emit it verbatim as a standalone assistant
|
|
197
|
+
message before the first tool call that performs the organizational recall
|
|
198
|
+
(the `bin/search.sh` query or a graph read). Tool output does not satisfy it.
|
|
199
|
+
Do not paraphrase the line.
|
|
200
|
+
|
|
201
|
+
Use Connect only for a graph traversal that actually runs. Emit once per
|
|
202
|
+
episode.
|
|
201
203
|
|
|
202
204
|
**Routing:** Organizational recall always enters Egregore Runtime. The model is
|
|
203
205
|
the semantic intent authority, deciding from meaning rather than fixed phrases.
|
|
@@ -212,15 +214,14 @@ Search output is model-internal: show only the retrieval line and receipts —
|
|
|
212
214
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.
|
|
213
215
|
|
|
214
216
|
Do not resolve `memory/` to its sibling repo or start with raw `grep`/`ls`.
|
|
215
|
-
Search
|
|
216
|
-
|
|
217
|
+
Search attaches no graph by default. Open a source only when its excerpt
|
|
218
|
+
cannot support a necessary claim. For current
|
|
217
219
|
team/person synthesis, retain known organization/member names and choose
|
|
218
|
-
`--recent-days` plus `--min-evidence`.
|
|
219
|
-
Grep/Glob for code and exact errors. `/activity`, `/dashboard`, and `/project`
|
|
220
|
+
`--recent-days` plus `--min-evidence`. `/activity`, `/dashboard`, and `/project`
|
|
220
221
|
display bounded status surfaces only when named or directly requested as a
|
|
221
|
-
card.
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
card. Explained syntheses of current organizational work and prior-work
|
|
223
|
+
discovery are Runtime/QMD recall. Do not run retrieval on unrelated prompts or
|
|
224
|
+
infer graph from recall intent.
|
|
224
225
|
|
|
225
226
|
Do not emit the beat for code search, Git inspection, startup hydration, graph
|
|
226
227
|
writes, ingestion, background sync, maintenance, or internal queries.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"generatedBy": "bin/prime-render-spec.mjs",
|
|
3
3
|
"source": "AGENTS.md generated Codex spec",
|
|
4
|
-
"sourceHash": "
|
|
5
|
-
"outputHash": "
|
|
4
|
+
"sourceHash": "496480654dd9",
|
|
5
|
+
"outputHash": "fa7b0b82de98",
|
|
6
6
|
"adaptations": [
|
|
7
7
|
"Prime Agent APPEND_SYSTEM delivery from .prime/agent/",
|
|
8
8
|
"Prime Agent tool_call branch gate incl. ipython classification",
|
package/runtime/prime/AGENTS.md
CHANGED
|
@@ -258,19 +258,21 @@ For each user-directed organizational lookup, show exactly one visible line:
|
|
|
258
258
|
- retrieval that actually queries the connected graph:
|
|
259
259
|
`⌕ Egregore Connect · searching your organization’s memory and relationships`
|
|
260
260
|
|
|
261
|
-
|
|
262
|
-
is only the schema label. When attached, authorized retrieval is complete:
|
|
261
|
+
When `EGREGORE_ORG_CONTEXT_V1` is attached, authorized retrieval is complete:
|
|
263
262
|
never query again that turn, and state any evidence gap. `OPENED_BY_OBSERVE`
|
|
264
263
|
means the evidence is open. A later explicit search starts a new turn.
|
|
265
264
|
|
|
266
|
-
**
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Shell/tool output does not satisfy this requirement. Do not paraphrase the line.
|
|
265
|
+
**Scope.** Egregore Runtime is for organizational recall only: team memory,
|
|
266
|
+
decisions, handoffs, prior work. Code, files, Git, and tests use the harness's
|
|
267
|
+
normal tools, with no beat and no Runtime call.
|
|
270
268
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
**Visibility is the contract.** Emit it verbatim as a standalone assistant
|
|
270
|
+
message before the first tool call that performs the organizational recall
|
|
271
|
+
(the `bin/search.sh` query or a graph read). Tool output does not satisfy it.
|
|
272
|
+
Do not paraphrase the line.
|
|
273
|
+
|
|
274
|
+
Use Connect only for a graph traversal that actually runs. Emit once per
|
|
275
|
+
episode.
|
|
274
276
|
|
|
275
277
|
**Routing:** Organizational recall always enters Egregore Runtime. The model is
|
|
276
278
|
the semantic intent authority, deciding from meaning rather than fixed phrases.
|
|
@@ -285,15 +287,14 @@ Search output is model-internal: show only the retrieval line and receipts —
|
|
|
285
287
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.
|
|
286
288
|
|
|
287
289
|
Do not resolve `memory/` to its sibling repo or start with raw `grep`/`ls`.
|
|
288
|
-
Search
|
|
289
|
-
|
|
290
|
+
Search attaches no graph by default. Open a source only when its excerpt
|
|
291
|
+
cannot support a necessary claim. For current
|
|
290
292
|
team/person synthesis, retain known organization/member names and choose
|
|
291
|
-
`--recent-days` plus `--min-evidence`.
|
|
292
|
-
Grep/Glob for code and exact errors. `$activity`, `$dashboard`, and `$project`
|
|
293
|
+
`--recent-days` plus `--min-evidence`. `$activity`, `$dashboard`, and `$project`
|
|
293
294
|
display bounded status surfaces only when named or directly requested as a
|
|
294
|
-
card.
|
|
295
|
-
|
|
296
|
-
|
|
295
|
+
card. Explained syntheses of current organizational work and prior-work
|
|
296
|
+
discovery are Runtime/QMD recall. Do not run retrieval on unrelated prompts or
|
|
297
|
+
infer graph from recall intent.
|
|
297
298
|
|
|
298
299
|
Do not emit the beat for code search, Git inspection, startup hydration, graph
|
|
299
300
|
writes, ingestion, background sync, maintenance, or internal queries.
|
|
@@ -157,9 +157,8 @@ const NON_SKILL_TOKENS = new Set(['loop', 'fast', 'config', 'clear', 'help']);
|
|
|
157
157
|
// hook delivers there. Rewrite the fallback command to the stdout form and
|
|
158
158
|
// state the same hygiene contract in shell terms: search output is
|
|
159
159
|
// model-internal; the visible reply carries only the retrieval line.
|
|
160
|
-
const CLAUDE_PACKET_NOTE = `\`--context-packet\`
|
|
161
|
-
|
|
162
|
-
Never re-print ranked results, file/rank/excerpt metadata, or raw JSON.`;
|
|
160
|
+
const CLAUDE_PACKET_NOTE = `\`--context-packet\` attaches the evidence privately; the visible output is the
|
|
161
|
+
attribution line alone. Never re-print ranked results or raw JSON.`;
|
|
163
162
|
const SHELL_PACKET_NOTE = `Search output is model-internal: show only the retrieval line and receipts —
|
|
164
163
|
never ranked blocks, file/rank/excerpt metadata, or raw JSON.`;
|
|
165
164
|
|
|
@@ -38,7 +38,7 @@ from .runtime import EgregoreRuntime, local_runtime
|
|
|
38
38
|
_ORG_CONTEXT_PREFETCH_PATTERN = re.compile(
|
|
39
39
|
"|".join(
|
|
40
40
|
(
|
|
41
|
-
r"\b(find|locate|dig up|look up|pull up)\b
|
|
41
|
+
r"\b(find|locate|dig up|look up|pull up)\b[^\n]*\b"
|
|
42
42
|
r"(handoff|decision|notes?|docs?|meeting|harvest|quest|reflection)s?\b",
|
|
43
43
|
r"\bdid we (decide|discuss|agree|say|talk about|cover)\b",
|
|
44
44
|
r"\bdo we have (any )?(notes?|docs?|anything|something)( on| about)?\b",
|
|
@@ -161,6 +161,26 @@ def _clear_observe_receipt(root: Path, harness: str) -> None:
|
|
|
161
161
|
pass
|
|
162
162
|
|
|
163
163
|
|
|
164
|
+
def _actor_contract_marker_path(
|
|
165
|
+
root: Path, harness: str, session: str | None = None
|
|
166
|
+
) -> Path:
|
|
167
|
+
"""Gitignored per-session marker: the full actor/retrieval contract was
|
|
168
|
+
already attached once. Later prompts receive a short reminder instead of
|
|
169
|
+
the ~4 KB block. bin/pre-compact.sh removes the marker so the first prompt
|
|
170
|
+
after a compaction re-attaches the full contract.
|
|
171
|
+
|
|
172
|
+
``session`` is the harness's own session id from the hook payload. The
|
|
173
|
+
Egregore session file in the checkout is shared by every concurrent
|
|
174
|
+
session there and rewritten by each new one, so keying on it alone made
|
|
175
|
+
parallel sessions re-attach the full contract on every prompt."""
|
|
176
|
+
|
|
177
|
+
session = re.sub(r"[^A-Za-z0-9_.-]", "-", session or _session_id(root))[:120]
|
|
178
|
+
return (
|
|
179
|
+
root / ".egregore" / "runtime" / "observe"
|
|
180
|
+
/ f"actor-contract-{harness}-{session}.sent"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
|
|
164
184
|
def _write_observe_receipt(root: Path, harness: str, prompt: str, context) -> None:
|
|
165
185
|
"""Record that this prompt already received useful authorized evidence.
|
|
166
186
|
|
|
@@ -378,6 +398,37 @@ def _query(args: argparse.Namespace) -> int:
|
|
|
378
398
|
return 0
|
|
379
399
|
|
|
380
400
|
|
|
401
|
+
_PASTED_OUTPUT_LINE = re.compile(
|
|
402
|
+
r"^(?:"
|
|
403
|
+
r"[ MADRCU?!]{2}\s+\S" # git status --short / porcelain rows
|
|
404
|
+
r"|[▶❯»]\s" # terminal prompt markers
|
|
405
|
+
r"|\$\s\S" # shell prompt
|
|
406
|
+
r"|(?:\+\+\+|---|@@)\s" # unified diff
|
|
407
|
+
r"|diff --git\b"
|
|
408
|
+
r"|Traceback \(most recent call last\)"
|
|
409
|
+
r"|\s+File \"[^\"]+\", line \d+"
|
|
410
|
+
r"|\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}" # log timestamps
|
|
411
|
+
r"|[A-Za-z0-9_./-]+/[A-Za-z0-9_.-]+\.[a-z]{1,6}$" # a bare path
|
|
412
|
+
r")"
|
|
413
|
+
)
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
def _looks_like_pasted_output(prompt: str) -> bool:
|
|
417
|
+
"""True for terminal output, diffs, logs, and code blocks pasted into a prompt.
|
|
418
|
+
|
|
419
|
+
Those carry words like "handoff", "notes", or "docs" by accident; running a
|
|
420
|
+
retrieval on them attaches unrelated evidence and costs seconds. The actor
|
|
421
|
+
context still tells the model to recall once if the prompt truly needs it.
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
if "```" in prompt:
|
|
425
|
+
return True
|
|
426
|
+
lines = [line for line in prompt.splitlines() if line.strip()]
|
|
427
|
+
if len(lines) >= 8:
|
|
428
|
+
return True
|
|
429
|
+
return sum(1 for line in lines if _PASTED_OUTPUT_LINE.match(line)) >= 2
|
|
430
|
+
|
|
431
|
+
|
|
381
432
|
def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
382
433
|
"""Return whether Observe should prefetch likely organizational context.
|
|
383
434
|
|
|
@@ -390,6 +441,7 @@ def prompt_prefetches_org_context(prompt: str) -> bool:
|
|
|
390
441
|
return bool(
|
|
391
442
|
prompt
|
|
392
443
|
and not _EXPLICIT_SEARCH.search(prompt)
|
|
444
|
+
and not _looks_like_pasted_output(prompt)
|
|
393
445
|
and (
|
|
394
446
|
_ORG_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
395
447
|
or _ORG_RITUAL_CONTEXT_PREFETCH_PATTERN.search(prompt)
|
|
@@ -414,8 +466,22 @@ def prompt_requests_actor_context(prompt: str) -> bool:
|
|
|
414
466
|
return bool(prompt and prompt.strip())
|
|
415
467
|
|
|
416
468
|
|
|
417
|
-
|
|
418
|
-
"
|
|
469
|
+
_RECALL_ONLY_SCOPE = (
|
|
470
|
+
"Egregore Runtime is for organizational recall and memory only: team memory, "
|
|
471
|
+
"decisions, handoffs, meetings, prior work. Code search, file reads, Git, tests, "
|
|
472
|
+
"and every other task use the harness's normal tools (Grep, Glob, Read, Bash) "
|
|
473
|
+
"with no retrieval ritual and no Runtime call."
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
def _actor_context_block(
|
|
478
|
+
runtime: EgregoreRuntime, root: Path, harness: str, *, full: bool = True
|
|
479
|
+
) -> str:
|
|
480
|
+
"""Render the stable identity and the recall contract for harness rituals.
|
|
481
|
+
|
|
482
|
+
``full`` renders the complete contract (once per session); otherwise a
|
|
483
|
+
short reminder that keeps identity and the recall-only scope in view.
|
|
484
|
+
"""
|
|
419
485
|
|
|
420
486
|
actor_context = _actor(runtime, root, harness)
|
|
421
487
|
actor = actor_context.actor
|
|
@@ -435,6 +501,22 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
435
501
|
search_command = 'bash bin/search.sh query "<concept>" -n 6 --compact'
|
|
436
502
|
if harness == "claude":
|
|
437
503
|
search_command += " --context-packet"
|
|
504
|
+
if not full:
|
|
505
|
+
return "\n".join(
|
|
506
|
+
(
|
|
507
|
+
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
508
|
+
"Reminder — the full contract was attached earlier in this session.",
|
|
509
|
+
f"Actor: {actor.display_name} · Actor ID: {actor.actor_id} · "
|
|
510
|
+
f"Organization ID: {actor_context.profile.org_id} · Runtime root: {root}",
|
|
511
|
+
_RECALL_ONLY_SCOPE,
|
|
512
|
+
"When a prompt needs that recall and no EGREGORE_ORG_CONTEXT_V1 block is "
|
|
513
|
+
f"attached, run exactly one `{search_command}`; exact latest/oldest/open "
|
|
514
|
+
"handoff questions use `bash bin/search.sh handoffs …` instead.",
|
|
515
|
+
"`me` and `myself` mean this Actor ID and display name; never infer identity "
|
|
516
|
+
"from the OS user, Git, or GitHub names.",
|
|
517
|
+
"END_EGREGORE_ACTOR_CONTEXT_V1",
|
|
518
|
+
)
|
|
519
|
+
)
|
|
438
520
|
return "\n".join(
|
|
439
521
|
(
|
|
440
522
|
"EGREGORE_ACTOR_CONTEXT_V1",
|
|
@@ -451,6 +533,7 @@ def _actor_context_block(runtime: EgregoreRuntime, root: Path, harness: str) ->
|
|
|
451
533
|
f"Runtime root: {root}",
|
|
452
534
|
"Run Egregore retrieval and workflow commands from this Runtime root. "
|
|
453
535
|
"Do not fall back to a launch checkout named elsewhere in the session.",
|
|
536
|
+
_RECALL_ONLY_SCOPE,
|
|
454
537
|
"Organizational retrieval status: NOT_PERFORMED. This actor-only block "
|
|
455
538
|
"does not mean organizational recall is unnecessary.",
|
|
456
539
|
"Interpret the user's intent semantically, without requiring trigger words. "
|
|
@@ -687,11 +770,21 @@ def _prompt_hook(args: argparse.Namespace) -> int:
|
|
|
687
770
|
args.limit,
|
|
688
771
|
)
|
|
689
772
|
else:
|
|
773
|
+
hook_session = str(payload.get("session_id") or "").strip() or None
|
|
774
|
+
marker = _actor_contract_marker_path(root, args.harness, hook_session)
|
|
775
|
+
full = not marker.exists()
|
|
690
776
|
additional_context = _actor_context_block(
|
|
691
777
|
runtime,
|
|
692
778
|
root,
|
|
693
779
|
args.harness,
|
|
780
|
+
full=full,
|
|
694
781
|
)
|
|
782
|
+
if full:
|
|
783
|
+
try:
|
|
784
|
+
marker.parent.mkdir(parents=True, exist_ok=True)
|
|
785
|
+
marker.write_text(datetime.now(UTC).isoformat(), encoding="utf-8")
|
|
786
|
+
except OSError:
|
|
787
|
+
pass
|
|
695
788
|
except Exception as exc: # Hooks are advisory and must never block a prompt.
|
|
696
789
|
additional_context = (
|
|
697
790
|
"Egregore Runtime context was requested but the Local Runtime is unavailable "
|