fix(plugins): author Codex checkpoints after compaction (#1138) · basicmachines-co/basic-memory@c28159d · GitHub
Skip to content

Commit c28159d

Browse files
authored
fix(plugins): author Codex checkpoints after compaction (#1138)
Signed-off-by: phernandez <paul@basicmachines.co>
1 parent 0a52e32 commit c28159d

32 files changed

Lines changed: 909 additions & 1512 deletions

justfile

Lines changed: 4 additions & 1 deletion

plugins/claude-code/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ local checkout. Two disclosures:
9494
- **Event capture is opt-in and off by default.** Setting `captureEvents: true`
9595
(the JSON boolean — strings never enable it) records redacted lifecycle-event
9696
envelopes to a local inbox under your Basic Memory home. Inspect with
97-
`basic-memory hook status`, project with `basic-memory hook flush`.
97+
`basic-memory hook status`, archive locally with `basic-memory hook flush`.
98+
The lifecycle trace never becomes a graph note.
9899

99100
Every failure path exits 0 — the hooks stay invisible rather than disrupt a
100101
session.
@@ -160,10 +161,9 @@ general setup seeds `session`; a **coding setup** (persisted as
160161
`sessionProfile: "coding"` with a user-confirmed `repository`) seeds
161162
`coding_session`, whose required repository, repo-root, working-directory,
162163
branch, and Git SHA frontmatter make checkpoints queryable by structured
163-
filters; typed pull-request fields are added when a PR exists. Optional flush projection also writes
164-
normalized `session` and `tool_ledger` artifacts. Those projection contracts are
165-
owned and tested by Basic Memory core rather than copied into separate
166-
host-plugin schemas.
164+
filters; typed pull-request fields are added when a PR exists. Lifecycle-event
165+
envelopes are operational trace rather than knowledge; `bm hook flush` archives
166+
them locally and never creates session or tool-ledger notes.
167167

168168
To customize how Claude writes memory, edit `skills/bm-writing/SKILL.md` in the
169169
plugin source. `bm-remember` and the output style's capture reflexes apply that

plugins/claude-code/skills/bm-orient/SKILL.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,9 @@ of a session; this is the deliberate mid-session version with deeper reads.
3636
report that setup is incomplete. Merge and deduplicate the results, sort them
3737
newest first, and prefer the highest-signal checkpoint regardless of which
3838
producer wrote it. `coding_session` carries schema-required, queryable Git
39-
context; `session` covers general checkpoints, PreCompact captures, and
40-
normalized `bm hook flush` projections.
39+
context; `session` covers general checkpoints and PreCompact captures. Do not
40+
query lifecycle trace: `bm hook flush` archives it locally rather than
41+
promoting it into the graph.
4142

4243
3. Query configured `secondaryProjects` read-only for open decisions. Do not write
4344
to shared projects during orientation.

plugins/claude-code/skills/bm-setup/SKILL.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,11 @@ Ask only what you can't infer. Cover:
112112
schemas" below.)
113113

114114
6. **Lifecycle-event capture.** "Should I also keep a local, redacted trail of
115-
SessionStart and PreCompact events for later projection?" Default to **off**.
115+
SessionStart and PreCompact events for diagnostics?" Default to **off**.
116116
Explain that the normal session brief and PreCompact checkpoint work either
117117
way; enabling this adds envelopes to a local inbox until `bm hook flush`
118-
projects them. Only the JSON boolean `true` enables capture.
118+
archives them locally. It never creates knowledge-graph notes. Only the JSON
119+
boolean `true` enables capture.
119120
- If enabled, optionally ask for repo-specific `redactKeys` (additional payload
120121
keys) and `redactPaths` (working directories or path-bearing content). The
121122
built-in redaction floor still applies when these lists are empty.
@@ -144,10 +145,9 @@ from this skill's directory, then `schemas/`** (this skill is at
144145
`<plugin>/skills/bm-setup/`). Read `coding-session.md` for a coding profile or
145146
`session.md` for a general profile, then read `decision.md` and `task.md`.
146147

147-
These schemas cover notes the Claude integration writes directly. The normalized
148-
`session` and `tool_ledger` artifacts written by `bm hook flush` are core-owned
149-
projections; their shape belongs to the core projector and its tests, not a
150-
duplicated per-plugin `tool_ledger` schema.
148+
These schemas cover notes the Claude integration writes directly. Lifecycle
149+
envelopes are not notes: `bm hook flush` archives that operational trace locally,
150+
so there is no projected session or tool-ledger schema to seed.
151151

152152
For each one:
153153
- Check whether the chosen project already has a schema for that type

plugins/claude-code/skills/bm-status/SKILL.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ This is a quick diagnostic — gather the facts and lay them out; don't over-inv
3232

3333
3. **Core hook health.** With the first available launcher, run
3434
`basic-memory hook status --harness claude --project-dir <project-root>`.
35-
Report its shared inbox path, pending envelopes, processed envelopes, last
35+
Report its shared inbox path, pending envelopes, archived envelopes, pending
36+
checkpoint requests, last
3637
flush, settings state, resolved primary project, capture state, capture folder,
3738
Basic Memory version, and uv version. Inbox counts are global across supported
3839
harnesses; do not attribute a backlog solely to Claude. Treat this command's
@@ -76,7 +77,8 @@ you couldn't determine, rather than failing the whole report):
7677
- Redact paths: <configured count or none>
7778
- Shared hook inbox: <path or unavailable>
7879
- Shared pending envelopes: <count or unavailable>
79-
- Shared processed envelopes: <count or unavailable>
80+
- Shared archived envelopes: <count or unavailable>
81+
- Pending checkpoint requests: <count or unavailable>
8082
- Last flush: <timestamp, never, or unavailable>
8183
- Hook runtime: basic-memory <version>; uv <version or missing>
8284
- Recent checkpoints: <n across session and coding_session>

plugins/codex/DEVELOPMENT.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ projects on the same machine. Repo-specific memory routing still comes from each
3838

3939
## Iteration Loop
4040

41-
Pin both hook scripts to the Basic Memory revision under test:
41+
Pin all three hook scripts to the Basic Memory revision under test:
4242

4343
```bash
4444
just set-codex-hook-version "$(git rev-parse origin/main)"

plugins/codex/README.md

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ verification, decision capture, and resumable checkpoints.
1111

1212
- **Orient from memory.** The `bm-orient` skill reads active tasks, open
1313
decisions, and recent Codex checkpoints before substantial work.
14-
- **Checkpoint work.** The `bm-checkpoint` skill and `PreCompact` hook write
15-
general `codex_session` notes or schema-backed `coding_session` notes with
16-
structured repository and pull-request context.
14+
- **Checkpoint work.** `PreCompact` records a private request and the `Stop`
15+
hook asks the active Codex turn to run `bm-checkpoint` once after compaction.
16+
The resulting `codex_session` or `coding_session` note is agent-authored from
17+
the compacted working context, with repository and pull-request evidence.
1718
- **Capture decisions.** The `bm-decide` skill records durable engineering
1819
decisions with rationale, alternatives, and consequences.
1920
- **Remember lightly.** The `bm-remember` skill saves small facts without turning
@@ -32,16 +33,18 @@ verification, decision capture, and resumable checkpoints.
3233
| --- | --- |
3334
| `.codex-plugin/plugin.json` | Codex plugin manifest |
3435
| `.mcp.json` | Basic Memory MCP server configuration |
35-
| `hooks/hooks.json` | SessionStart and PreCompact hook registration |
36+
| `hooks/hooks.json` | SessionStart, PreCompact, and Stop hook registration |
3637
| `hooks/session_start.py` | uv script: runs `basic-memory hook session-start --harness codex` |
3738
| `hooks/pre_compact.py` | uv script: runs `basic-memory hook pre-compact --harness codex` |
39+
| `hooks/stop.py` | uv script: runs `basic-memory hook stop --harness codex` |
3840
| `skills/` | Codex-native Basic Memory workflows |
3941
| `schemas/` | Seed schemas for Codex sessions, decisions, and tasks |
4042

41-
The hook scripts carry no logic: the brief, the checkpoint, and lifecycle-event
42-
capture all live in the pinned Basic Memory revision behind `bm hook`. Each is
43-
a self-contained PEP 723 script pinned to a Basic Memory Git ref. Both refs
44-
are updated together with `just set-codex-hook-version <sha-or-tag>`.
43+
The hook scripts carry no logic: the brief, checkpoint coordination, and
44+
lifecycle-event capture all live in the pinned Basic Memory revision behind
45+
`bm hook`. Each is a self-contained PEP 723 script pinned to a Basic Memory Git
46+
ref. All refs are updated together with
47+
`just set-codex-hook-version <sha-or-tag>`.
4548

4649
## Requirements
4750

@@ -69,6 +72,13 @@ Plugin installation is user-level in Codex, so one install makes the plugin
6972
available across projects on the same machine. Start a new Codex thread after
7073
installing so Codex can load the plugin skills, MCP configuration, and hooks.
7174

75+
When adding the marketplace from the Git repository UI, leave **Sparse paths**
76+
empty. If a sparse checkout is required, include both `.agents/plugins` and
77+
`plugins/codex`. Selecting only `plugins/codex` omits
78+
`.agents/plugins/marketplace.json`, so Codex correctly reports that the checked
79+
out marketplace root has no supported manifest. The marketplace file should not
80+
be moved into the plugin directory.
81+
7282
Configuration can live at user level in `~/.codex/basic-memory.json` or at
7383
project level in `.codex/basic-memory.json`. User-level settings are the base;
7484
the nearest project file overrides only the keys it declares. `redactKeys` and
@@ -103,9 +113,16 @@ Run the setup skill, or create `~/.codex/basic-memory.json` for shared defaults:
103113

104114
Codex event capture is on by default. Set the JSON boolean `false` at user or
105115
project level to opt out; malformed values fail closed. Captured, redacted
106-
lifecycle-event envelopes land in a local inbox under your Basic Memory home
107-
(`basic-memory hook status` / `basic-memory hook flush`). Add `redactKeys` and
108-
`redactPaths` arrays to extend the built-in redaction floor.
116+
lifecycle-event envelopes land in a local inbox under your Basic Memory home.
117+
The lifecycle trace stays local: `basic-memory hook flush` only moves valid
118+
envelopes into the local retention archive and never creates graph notes. Add
119+
`redactKeys` and `redactPaths` arrays to extend the built-in redaction floor.
120+
121+
Codex ignores PreCompact stdout, so PreCompact cannot ask the model to write a
122+
note directly. It leaves a private request for the Stop hook. Stop then blocks
123+
the turn once with a request to run `bm-checkpoint`; the active model writes an
124+
agent-authored checkpoint from its compacted context, and the next Stop is a
125+
no-op to prevent loops.
109126

110127
When `captureFolder` is omitted, Codex resolves the Git top-level directory and
111128
writes to `codex/<repo-dir>`. An explicit folder still wins.
@@ -125,12 +142,9 @@ identifier in the project file without duplicating the shared settings:
125142
The plugin's seed schemas cover notes Codex writes directly: `codex_session`,
126143
`coding_session`, `decision`, and `task`. Coding sessions require structured
127144
repository, repository-root, working-directory, branch, and Git SHA frontmatter;
128-
current pull-request fields are added when a PR exists. Optional flush projection
129-
also writes normalized `session` and `tool_ledger` artifacts. Those are
130-
core-owned contracts implemented and tested with the projector, not duplicate
131-
schema files maintained by each host plugin. `bm-orient` and `bm-status` still
132-
recall normalized `session` notes
133-
alongside Codex checkpoints.
145+
current pull-request fields are added when a PR exists. Lifecycle envelopes are
146+
operational trace rather than knowledge, so orientation only recalls authored
147+
checkpoint types.
134148

135149
Codex plugin hooks must be reviewed and trusted before they run. Open `/hooks` in
136150
Codex after enabling the plugin and trust the Basic Memory hook definitions.

plugins/codex/hooks/hooks.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"description": "Basic Memory for Codex hooks - orient from the graph on session start and checkpoint before compaction.",
2+
"description": "Basic Memory for Codex hooks - orient from the graph, record local lifecycle trace, and request an authored checkpoint after compaction.",
33
"hooks": {
44
"SessionStart": [
55
{
@@ -26,6 +26,18 @@
2626
}
2727
]
2828
}
29+
],
30+
"Stop": [
31+
{
32+
"hooks": [
33+
{
34+
"type": "command",
35+
"command": "uv run --quiet --script \"${PLUGIN_ROOT}/hooks/stop.py\"",
36+
"statusMessage": "Finishing the Basic Memory checkpoint",
37+
"timeout": 30
38+
}
39+
]
40+
}
2941
]
3042
}
3143
}

plugins/codex/hooks/pre_compact.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# /// script
33
# requires-python = ">=3.12"
44
# dependencies = [
5-
# "basic-memory @ git+https://github.com/basicmachines-co/basic-memory@bd5d145d5be3bab3c73291ae2a698f8e5a1e54cb",
5+
# "basic-memory @ git+https://github.com/basicmachines-co/basic-memory@1cb7a541fbb43c5a4f1b552c0123a1c55beb8dfb",
66
# ]
77
# ///
88
"""PreCompact hook launcher backed by a pinned Basic Memory revision.

plugins/codex/hooks/session_start.py

Lines changed: 1 addition & 1 deletion

0 commit comments

Comments
 (0)