Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ their manifests.
- Keep `.codex-plugin/plugin.json` as the required manifest entry point.
- Keep MCP credentials out of source. Use OAuth or local credential storage.
- Preserve explicit hook trust and safe degraded behavior.
- Keep HyperMemory recall on the main agent and persistence/token reporting on
one awaited memory-writer sub-agent.
- Keep HyperMemory recall on the main agent for substantive prompts and skip it
only for narrowly classified lightweight social prompts.
- Keep persistence/token reporting on one fresh fire-and-forget memory-writer
sub-agent; the main agent must never wait, poll, inspect, or message it.
- Keep HyperColab join/sync/claims on the main agent. Delegated coordination
writers may record progress but must not bypass ownership conflicts.

Expand Down
30 changes: 17 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,27 +211,28 @@ sequenceDiagram
participant L as Codex token listener

U->>M: Submit a prompt
M->>MCP: Overview and relevant recall
M->>MCP: Overview and recall for substantive prompts
MCP-->>M: Relationship-aware context
M->>M: Complete the requested work
M->>W: Delegate a concise finalization summary
M-)W: Dispatch a concise finalization summary
M-->>U: Return final response without waiting
W->>MCP: Recall before writing
W->>MCP: Store or update durable knowledge
W->>MCP: Write one timeline entry
W->>L: Inspect token-counter delta
L-->>W: Exact payload or fallback instruction
W->>MCP: Report tokens once
W->>L: Acknowledge accepted exact claim
W-->>M: Return brief status
M-->>U: Return final response
```

The main agent performs recall because remembered context must be available
while reasoning about the user's request. Persistence and telemetry are moved
to one awaited memory-writer sub-agent to keep the main context focused. Each
turn uses a fresh, turn-unique writer with `fork_turns="none"`; reusing a writer
or copying the full parent history would repeatedly charge that context during
tool continuations. The role contract prevents recursive delegation.
The main agent performs recall for substantive prompts because remembered
context must be available while reasoning about the user's request. Narrow,
standalone greetings and acknowledgements skip retrieval. Persistence and
telemetry move to one fire-and-forget memory-writer sub-agent so they do not
delay the user-facing response. Each turn uses a fresh, turn-unique writer with
`fork_turns="none"`; reusing a writer or copying the full parent history would
repeatedly charge that context during tool continuations. The role contract
prevents recursive delegation.

This coordination is deliberately invisible in normal use. HyperMemory does
not emit status messages, inject synthetic user prompts, or append memory
Expand Down Expand Up @@ -624,7 +625,7 @@ The tests cover:

- catalog-to-plugin path and identity consistency;
- required manifests, MCP declarations, hooks, skills, and assets;
- HyperMemory stop-hook delegation and recursion protection;
- HyperMemory prompt classification and fire-and-forget writer delegation;
- exact token aggregation and two-phase checkpointing;
- HyperColab hook behavior, Git discovery, cached leases, and queued events;
- logo format and dimensions; and
Expand All @@ -637,12 +638,15 @@ python3 ~/.codex/skills/.system/plugin-creator/scripts/validate_plugin.py \
plugins/hypermemory
python3 ~/.codex/skills/.system/plugin-creator/scripts/validate_plugin.py \
plugins/hypercolab
python3 ~/.codex/skills/.system/skill-creator/scripts/quick_validate.py \
plugins/hypermemory/skills/hypermemory
python3 ~/.codex/skills/.system/skill-creator/scripts/quick_validate.py \
plugins/hypercolab/skills/hypercolab
```

The official HyperMemory MCP skill retains its extended `version`,
`enforcement`, and `trigger` frontmatter, which the generic skill validator
does not currently accept. The HyperMemory plugin validator and repository
tests cover that package without stripping its official metadata.

### Build review archives

```bash
Expand Down
12 changes: 9 additions & 3 deletions plugins/hypermemory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ separate token-reporting branches for ChatGPT and Codex.

## Behavior

- Main agent: overview and recall so memory can inform the response.
- Main agent: overview and recall for substantive prompts so memory can inform
the response; narrow standalone greetings and acknowledgements skip retrieval.
- Memory-writer sub-agent: a fresh, turn-unique worker created without parent
conversation history performs store, update, forget, one timeline write, and
one token report before the final response.
one token report asynchronously after dispatch. The parent never waits for,
polls, messages, or reads the worker.
- Codex: trusted hooks enforce the lifecycle and read exact cumulative token
counters from the active rollout JSONL using a two-phase inspect/ack helper.
- ChatGPT: reports an uncertainty-labelled workload estimate because consumer
Expand Down Expand Up @@ -51,6 +53,10 @@ it does not require a checked-in `.app.json`.

```bash
python3 ~/.codex/skills/.system/plugin-creator/scripts/validate_plugin.py plugins/hypermemory
python3 ~/.codex/skills/.system/skill-creator/scripts/quick_validate.py plugins/hypermemory/skills/hypermemory
pytest -q tests/test_hypermemory_plugin.py
```

The official HyperMemory MCP skill intentionally retains its extended
`version`, `enforcement`, and `trigger` frontmatter. Codex's generic
`quick_validate.py` currently rejects those official keys, so the plugin
validator and HyperMemory tests validate this package instead.
12 changes: 7 additions & 5 deletions plugins/hypermemory/agents/memory-writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ description: Bounded HyperMemory persistence, timeline, and token-reporting role
# Memory writer

This is a packaged role contract, not a user-facing skill. The HyperMemory
skill asks the host to spawn one awaited sub-agent with this role after the main
agent has completed the requested work. The host must create a fresh,
turn-unique task with `fork_turns="none"` and provide only a concise bounded
summary; it must never reuse a writer from an earlier turn.
skill asks the host to spawn one fire-and-forget sub-agent with this role after
the main agent has completed the requested work. The host must create a fresh,
turn-unique task with `fork_turns="none"`, provide only a concise bounded
summary, and continue without waiting or polling; it must never reuse a writer
from an earlier turn.

1. Recall related nodes before changing the graph.
2. Store durable new knowledge or update the existing canonical node.
Expand All @@ -18,7 +19,8 @@ summary; it must never reuse a writer from an earlier turn.
5. Report token usage exactly once. Use the Codex listener's exact payload when
available; otherwise use an honest estimate with uncertainty.
6. Acknowledge a Codex listener claim only after the MCP accepts the report.
7. Return a brief status to the parent and never spawn another agent.
7. Never spawn another agent. A brief diagnostic status may be returned, but
the parent does not wait for or consume it.

Never store credentials, hidden reasoning, raw transcripts, complete command
output, tool payloads, or large code bodies.
67 changes: 39 additions & 28 deletions plugins/hypermemory/scripts/hypermemory_hook.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
#!/usr/bin/env python3
"""Silent Codex lifecycle bridge for mandatory HyperMemory behavior.

The hook prepares token-listener jobs before model work and injects only hidden
developer context. It never blocks Stop, creates continuation prompts, or reads
conversation content from the transcript.
The hook classifies lightweight prompts, prepares token-listener jobs before
model work, and injects concise hidden developer context. It never blocks Stop,
creates continuation prompts, or reads conversation content from the transcript.
"""

from __future__ import annotations

import argparse
import json
import os
import re
import sys
import tempfile
from datetime import UTC, datetime
from pathlib import Path
from typing import Any

LIGHTWEIGHT_MAX_CHARS = 80
LIGHTWEIGHT_PHRASES = frozenset({"got it", "hello", "hey", "hi", "howdy", "ok", "okay", "thank you", "thanks"})


def _prompt_text(payload):
return payload.get("prompt") or ""


def _normalize_prompt(text):
text = text.casefold().replace("’", "'")
return " ".join(re.sub(r"[^\w\s']+", " ", text).split())


def _is_lightweight_prompt(text):
return bool(text) and len(text) <= LIGHTWEIGHT_MAX_CHARS and _normalize_prompt(text) in LIGHTWEIGHT_PHRASES


def _read_input() -> dict[str, Any]:
try:
Expand Down Expand Up @@ -105,12 +122,9 @@ def session_start(payload: dict[str, Any]) -> int:

_context(
"SessionStart",
"HyperMemory is mandatory for this session. Before the first response, "
"call hm_get_overview and hm_recall. On every turn recall on the main "
"agent, then delegate store/update/forget, one timeline entry, and one "
"token report to a fresh memory-writer sub-agent created with "
"fork_turns=\"none\" before returning the final response. Never reuse a "
"memory-writer across turns.",
"HyperMemory is active. Follow the HyperMemory skill and each turn's "
"prompt classification. Do not recall solely because the session started. "
"Memory-writers are fire-and-forget: dispatch once, never wait or poll.",
)
return 0

Expand All @@ -136,28 +150,25 @@ def _turn_job(payload: dict[str, Any]) -> tuple[Path, Path]:
def user_prompt(payload: dict[str, Any]) -> int:
listener, job_path = _turn_job(payload)
writer_task = _agent_task_name(payload.get("turn_id"))
lightweight = _is_lightweight_prompt(_prompt_text(payload))
recall_instruction = (
"mode=lightweight; skip hm_get_overview and hm_recall on the main agent."
if lightweight
else "mode=substantive; call hm_recall before substantive work and call "
"hm_get_overview first if it has not run in this conversation."
)
_context(
"UserPromptSubmit",
"For this turn, silently call HyperMemory hm_recall before substantive "
"work. Keep graph writes, hm_timeline_write, and hm_tokens off the main "
"agent: exactly one memory-writer sub-agent must perform them during "
"finalization before the final response. That sub-agent must be fresh. "
"HyperMemory work is internal: "
"never mention its recall, delegation, finalization, timeline, or token "
"telemetry in commentary or the final answer unless the user explicitly "
"asks about HyperMemory operation. Spawn the sub-agent with "
f"task_name={writer_task} and fork_turns=\"none\". Do not reuse a "
"memory-writer from another turn or fork the conversation history; pass "
"only a concise bounded summary plus these exact paths:\n"
f"HyperMemory turn: {recall_instruction}\n"
"Apply the HyperMemory skill silently. Keep graph writes and telemetry "
"off the main agent. "
"Before the final response, spawn exactly one fresh memory-writer with "
f"task_name={writer_task}, fork_turns=\"none\", a bounded turn summary, "
"and the skill's writer contract. Pass:\n"
f"listener={listener}\njob={job_path}\n"
"The sub-agent must recall first, store or update only durable knowledge "
"with specific relationships, write exactly one hm_timeline_write entry, "
"choose unique semantic activity segments totaling 100, run python3 "
"<listener> inspect --job <job> --segments-json '<json>', call hm_tokens "
"exactly once with the returned hm_tokens_payload object, and "
"acknowledge the listener only "
"after hm_tokens succeeds. If exact inspection is unavailable, it must "
"send one honest self_estimated report with the same segmentation.",
"Fire-and-forget: after spawn succeeds, do not wait, poll, inspect, read, "
"message, or otherwise synchronize with the writer; return the final "
"response immediately.",
)
return 0

Expand Down
Loading