mirror-mind 0.33.4 → 0.35.0
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/.agents/plugins/marketplace.json +16 -0
- package/.pi/skills/mm-build/SKILL.md +1 -1
- package/.pi/skills/mm-explore/SKILL.md +1 -1
- package/.pi/skills/mm-help/SKILL.md +2 -2
- package/.pi/skills/mm-soul/SKILL.md +1 -1
- package/AGENTS.md +9 -8
- package/README.md +5 -6
- package/docs/releases/index.md +2 -0
- package/docs/releases/v0.34.0.md +142 -0
- package/docs/releases/v0.35.0.md +199 -0
- package/package.json +3 -6
- package/plugins/mirror-mind/.claude-plugin/plugin.json +1 -1
- package/plugins/mirror-mind/agy/pre-invocation.sh +92 -0
- package/plugins/mirror-mind/agy/session-start.sh +92 -0
- package/plugins/mirror-mind/agy/stop.sh +92 -0
- package/plugins/mirror-mind/hooks.json +26 -0
- package/plugins/mirror-mind/mcp_config.json +11 -0
- package/plugins/mirror-mind/plugin.json +4 -0
- package/plugins/mirror-mind/rules/AGENTS.md +189 -0
- package/plugins/mirror-mind/skills/mm-build/SKILL.md +1 -1
- package/ts/src/conversation/agyTranscript.ts +105 -0
- package/ts/src/conversation/backfill.ts +13 -129
- package/ts/src/conversation/commandTurn.ts +42 -0
- package/ts/src/conversation/deferredCloseTail.ts +154 -0
- package/ts/src/conversation/logger.ts +104 -20
- package/ts/src/conversation/loggerCli.ts +6 -18
- package/ts/src/conversation/loggerRuntime.ts +6 -1
- package/ts/src/conversation/runtimePolicy.ts +59 -0
- package/ts/src/conversation/sessionComposites.ts +54 -8
- package/ts/src/docs/docsLint.ts +14 -1
- package/ts/src/frontDoor/routing.ts +3 -2
- package/ts/src/frontDoor/runtimeRoute.ts +13 -1
- package/ts/src/frontDoor/stdinSource.ts +2 -2
- package/ts/src/guards/claudePlugin.ts +113 -2
- package/ts/src/guards/packContents.ts +7 -6
- package/ts/src/guards/piSourcedSkills.ts +1 -1
- package/ts/src/guards/retiredSurfaces.ts +67 -0
- package/ts/src/hooks/agy.ts +229 -0
- package/ts/src/hooks/claude.ts +16 -4
- package/ts/src/hooks/main.ts +17 -31
- package/ts/src/hooks/payload.ts +8 -15
- package/ts/src/hooks/runtime.ts +11 -10
- package/ts/src/providers/config.ts +11 -0
- package/ts/src/runtime/diagnose.ts +115 -1
- package/ts/src/runtime/pluginWiring.ts +135 -0
- package/ts/src/runtime/update.ts +39 -6
- package/ts/src/runtime/wiring.ts +42 -46
- package/.gemini/hooks/log-assistant.sh +0 -85
- package/.gemini/hooks/log-user.sh +0 -85
- package/.gemini/hooks/session-end.sh +0 -85
- package/.gemini/hooks/session-start.sh +0 -85
- package/scripts/codex-hooks/session-end.sh +0 -85
- package/scripts/codex-hooks/session-start.sh +0 -85
- package/scripts/codex-mirror.sh +0 -48
- package/ts/src/hooks/codex.ts +0 -45
- package/ts/src/hooks/gemini.ts +0 -126
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mirror-mind",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "Mirror Mind"
|
|
5
|
+
},
|
|
6
|
+
"plugins": [
|
|
7
|
+
{
|
|
8
|
+
"name": "mirror-mind",
|
|
9
|
+
"source": {
|
|
10
|
+
"source": "local",
|
|
11
|
+
"path": "./plugins/mirror-mind"
|
|
12
|
+
},
|
|
13
|
+
"description": "Mirror Mind — local-first memory and identity for agentic runtimes."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: "mm-help"
|
|
3
|
-
description: Shows available Mirror Mind commands on Pi
|
|
3
|
+
description: Shows available Mirror Mind commands on Pi
|
|
4
4
|
user-invocable: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Help
|
|
8
8
|
|
|
9
|
-
Show the user the available commands
|
|
9
|
+
Show the user the available commands:
|
|
10
10
|
|
|
11
11
|
## Operating Modes
|
|
12
12
|
|
package/AGENTS.md
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# Mirror Mind — Operating Instructions
|
|
2
2
|
|
|
3
3
|
<!-- This file ships in the mirror-mind package and is read by every runtime:
|
|
4
|
-
Pi and Codex read it from the project root natively, Claude Code
|
|
5
|
-
|
|
6
|
-
package's Pi session receives it from the extension
|
|
4
|
+
Pi and Codex read it from the project root natively, Claude Code through
|
|
5
|
+
the @AGENTS.md import in CLAUDE.md, Antigravity as the plugin's rules, and
|
|
6
|
+
an installed package's Pi session receives it from the extension
|
|
7
|
+
(CV22.DS10.US3, D13).
|
|
7
8
|
It holds nothing about this repository; that is CLAUDE.md's part. -->
|
|
8
9
|
|
|
9
10
|
---
|
|
@@ -17,11 +18,11 @@ Applies to all sessions, regardless of project.
|
|
|
17
18
|
The mirror operates in four modes, chosen automatically based on context:
|
|
18
19
|
Mirror, Builder, Explorer, and Soul.
|
|
19
20
|
|
|
20
|
-
Each skill below is named three ways: `/mm-<skill>` in Pi
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
`mirror-mind:mm-<skill>` as the skill's own
|
|
24
|
-
the same skill.
|
|
21
|
+
Each skill below is named three ways: `/mm-<skill>` in Pi, `$mm-<skill>` in
|
|
22
|
+
Codex, `/mm:<skill>` in Claude Code. A **plugin** install prefixes the plugin's
|
|
23
|
+
name — `/mirror-mind:mm:<skill>` in Claude Code's menu and in Antigravity,
|
|
24
|
+
`$mirror-mind:mm:<skill>` in Codex, `mirror-mind:mm-<skill>` as the skill's own
|
|
25
|
+
name — and the forms below refer to the same skill.
|
|
25
26
|
|
|
26
27
|
**Mirror Mode** — activate for: life decisions, feelings, business strategy,
|
|
27
28
|
writing, mentoring, health, existential questions, sensemaking, psychological
|
package/README.md
CHANGED
|
@@ -60,8 +60,8 @@ This is not a chatbot with memory. This is a mirror — and yours.
|
|
|
60
60
|
|
|
61
61
|
## How It Works
|
|
62
62
|
|
|
63
|
-
Local-first. SQLite. Four supported runtimes: Pi,
|
|
64
|
-
|
|
63
|
+
Local-first. SQLite. Four supported runtimes: Pi, Claude Code, Codex,
|
|
64
|
+
Antigravity. One TypeScript core, run by Node.js. Jungian architecture: Self, Ego,
|
|
65
65
|
Personas, Shadow.
|
|
66
66
|
Context-activated modes — Mirror, Builder, Explorer, and Soul. The identity lives
|
|
67
67
|
in your machine, not a server.
|
|
@@ -79,9 +79,8 @@ in your machine, not a server.
|
|
|
79
79
|
- [OpenRouter](https://openrouter.ai) account with at least $5 in credits —
|
|
80
80
|
embeddings, memory extraction, and multi-LLM
|
|
81
81
|
- An AI runtime subscription:
|
|
82
|
-
[Codex Plus](https://openai.com/codex/) (recommended)
|
|
83
|
-
[Claude Code Pro](https://code.claude.com/docs)
|
|
84
|
-
[Gemini AI Pro](https://geminicli.com/)
|
|
82
|
+
[Codex Plus](https://openai.com/codex/) (recommended) or
|
|
83
|
+
[Claude Code Pro](https://code.claude.com/docs)
|
|
85
84
|
- [Pi](https://github.com/earendil-works/pi/tree/main/packages/coding-agent)
|
|
86
85
|
— recommended harness (multi-model, not locked to one provider)
|
|
87
86
|
|
|
@@ -111,7 +110,7 @@ this repository, turning a personal experiment into a reusable framework:
|
|
|
111
110
|
|
|
112
111
|
- **English** — full migration from Portuguese across code, CLI, schema, identity, and docs
|
|
113
112
|
- **Framework/user separation** — user identity and memory live privately under `~/.mirror/<user>/`, outside the repository
|
|
114
|
-
- **Multi-runtime** — from Claude Code only to
|
|
113
|
+
- **Multi-runtime** — from Claude Code only to Pi, Claude Code, Codex, and Antigravity
|
|
115
114
|
- **Multi-user** — independent mirrors for multiple users on the same machine
|
|
116
115
|
- **Multi-session** — concurrent sessions tracked safely in a database-backed session registry
|
|
117
116
|
- **Intelligence depth** — hybrid semantic and lexical search, honest reinforcement, two-pass extraction, memory consolidation, and shadow cultivation
|
package/docs/releases/index.md
CHANGED
|
@@ -12,6 +12,8 @@ Future release notes should use the structure defined in [Release Notes](../proc
|
|
|
12
12
|
|
|
13
13
|
## Releases
|
|
14
14
|
|
|
15
|
+
- [v0.35.0 — Four Runtimes, One Successor](v0.35.0.md) — minor release closing CV21.DS8: the Gemini CLI integration no longer ships and Antigravity stands in its place, the gate met by DS7's live L4 on agy 1.4.2. Four runtimes — Pi, Claude Code, Codex, Antigravity — named everywhere; the cutoff recorded in full, with the four hook entries a Gemini CLI user deletes and v0.34.0 as the last release that carries the integration; a retired-surface guard keeps it removed. No migration.
|
|
16
|
+
- [v0.34.0 — Codex Through the Canonical Plugin](v0.34.0.md) — minor release closing CV21.DS4: Codex runs Mirror through the canonical plugin, installed in two commands from a marketplace the package ships, measured live at L4 on Codex 0.163.0. The v0.32.1 wrapper wiring no longer ships; `runtime diagnose` and `runtime update` say when Codex's cached plugin copy is behind and name the re-add that brings it level. No migration.
|
|
15
17
|
- [v0.33.4 — A Name Is a Key](v0.33.4.md) — patch release of three first-run corrections: two from a contributor's PR #43 and CR141, which its review opened. `init --help` created a home named `--help`, `init ../escaped` created one outside `.mirror-minds`, and `init "My User"` put a space into `MIRROR_USER`; a user name is now a kebab-case key like a journey slug or a persona id, refused otherwise with a name that would work and nothing created. `identity edit` on Windows opens Notepad when no editor is named. Existing homes untouched. No migration.
|
|
16
18
|
- [v0.33.3 — Mirror Finds Itself Under Any Path](v0.33.3.md) — patch release of one Change Request, CR140, carried by a contributor's PR #42: Mirror read its own install path from `URL.pathname`, so a checkout or package under a path with a space or a non-ASCII character read as `Install: unknown`, the welcome card showed no update, and `runtime update` refused. The path is now a filesystem path, a guard keeps the idiom out, and an `unknown` install names the path it looked up from. On Windows, npm's global layout is recognized and npm runs with no shell, verified on Windows in CI for the two files they touch; there is still no Windows product. Affected installs update once by hand. No migration.
|
|
17
19
|
- [v0.33.2 — Git Runs Where Mirror Lives](v0.33.2.md) — patch release of one Change Request, CR138: on a clone install, `runtime status`, `version`, and `diagnose` describe the install from any directory, and `diagnose` grades Mirror's own tree. Git now runs only in the install's own checkout, so a checkout someone else made can no longer run a `core.fsmonitor` command through these commands; `version --start PATH` is the one explicit exception. Package installs were never exposed. No migration.
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
---
|
|
2
|
+
digest: >
|
|
3
|
+
v0.34.0 is a minor release closing CV21.DS4: Codex runs Mirror through the
|
|
4
|
+
canonical plugin, the same one Claude Code loads. The package ships a Codex
|
|
5
|
+
marketplace; two commands install the plugin, Codex asks once to trust its
|
|
6
|
+
hooks, and from then on every session carries the skills, the Operating
|
|
7
|
+
Instructions, per-turn Mirror Mode injection, the MCP server, and logging as
|
|
8
|
+
`codex` with every reply beside its prompt — measured live at L4 on Codex
|
|
9
|
+
0.163.0. The v0.32.1 wrapper wiring is removed: `scripts/codex-mirror.sh`,
|
|
10
|
+
its hooks, and the JSONL backfill no longer ship. Because Codex copies the
|
|
11
|
+
plugin into a versioned cache, `runtime diagnose` and `runtime update` now
|
|
12
|
+
say when that copy is behind and name the one command that brings it level.
|
|
13
|
+
No migration.
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# v0.34.0 — Codex Through the Canonical Plugin
|
|
17
|
+
|
|
18
|
+
**Date:** 2026-10-17
|
|
19
|
+
|
|
20
|
+
## Highlights
|
|
21
|
+
|
|
22
|
+
- **Codex installs Mirror as a plugin, from a marketplace the package ships**
|
|
23
|
+
(CV21.DS4.US1). Two commands — `codex plugin marketplace add "<pkg>"`, then
|
|
24
|
+
`codex plugin add mirror-mind@mirror-mind` — and Codex asks once, at the
|
|
25
|
+
next session, to trust the plugin's hooks. `mirror init` prints exactly
|
|
26
|
+
these steps when it finds `codex` on the PATH.
|
|
27
|
+
- **Codex is at L4, measured live** (CV21.DS4.US4, on Codex 0.163.0): all 25
|
|
28
|
+
skills, the Operating Instructions as a developer message, Mirror Mode on
|
|
29
|
+
an ordinary turn and on `$mirror-mind:mm:mirror`, the 7 MCP tools behind
|
|
30
|
+
Codex's `tool_search`, and every prompt and reply logged as `codex`. Codex
|
|
31
|
+
detaches the TUI on `/quit` and fires SessionEnd only when its daemon reaps
|
|
32
|
+
the idle thread, so Mirror gained a safety net for sessions that outlive
|
|
33
|
+
their TUI: session maintenance closes them as orphans
|
|
34
|
+
(`MIRROR_STALE_ORPHAN_MINUTES`, default 30).
|
|
35
|
+
- **A bounded SessionEnd no longer cuts extraction** (CV21.DS4.TS2). Codex
|
|
36
|
+
bounds the hook at 1 s; the close now runs no LLM work, and the next
|
|
37
|
+
session start finishes the deferred tail. Grok's 1.5 s bound rides the same
|
|
38
|
+
change.
|
|
39
|
+
- **`$`-skill turns are command turns** (CV21.DS4.TS3), as `/`-commands are
|
|
40
|
+
on every other runtime, with Mirror's explicit form the one exception.
|
|
41
|
+
- **The v0.32.1 Codex wiring is removed** (CV21.DS4.TS5). What no longer
|
|
42
|
+
exists: `scripts/codex-mirror.sh`, `scripts/codex-hooks/`, the
|
|
43
|
+
`codex:session-*` hook entries, and
|
|
44
|
+
`conversation-logger backfill-codex-session` — the plugin logs Codex turns
|
|
45
|
+
as they happen, so nothing re-imports the transcript at exit. A
|
|
46
|
+
retired-surfaces guard keeps the wiring from drifting back.
|
|
47
|
+
- **An updated Mirror now reaches Codex's plugin cache — or says so**
|
|
48
|
+
(CV21.DS4.TS6). Codex copies the plugin into its cache at a version, so an
|
|
49
|
+
npm update changes the install but not the copy Codex runs. `runtime
|
|
50
|
+
diagnose` reports `codex_plugin_cache_behind` naming both versions and the
|
|
51
|
+
measured command — `codex plugin add mirror-mind@mirror-mind`; re-adding
|
|
52
|
+
refreshes the cache in place, no remove needed — and a successful `runtime
|
|
53
|
+
update` prints the same line. A dangling Claude Code skills link is
|
|
54
|
+
reported too (`claude_plugin_link_dangling`). Absence is not drift: an
|
|
55
|
+
unwired machine stays green.
|
|
56
|
+
|
|
57
|
+
## Where We Started
|
|
58
|
+
|
|
59
|
+
v0.33.0 proved one plugin works as it is on Claude Code, Codex, and Grok.
|
|
60
|
+
But a Codex user still wired Mirror by hand: a skills link, an `AGENTS.md`
|
|
61
|
+
link, and a wrapper script around every session that imported the transcript
|
|
62
|
+
from JSONL at exit — v0.32.1's wiring, built when Codex had no hook system.
|
|
63
|
+
Codex 0.157 added plugins; DS4 asked whether the canonical plugin could be
|
|
64
|
+
the whole answer, and set a gate: the old wiring retires only once parity is
|
|
65
|
+
shown live.
|
|
66
|
+
|
|
67
|
+
## What Changed
|
|
68
|
+
|
|
69
|
+
**The install is two commands.** The npm package root carries
|
|
70
|
+
`.agents/plugins/marketplace.json`, one local plugin — the same
|
|
71
|
+
`plugins/mirror-mind` Claude Code loads. Codex copies it into its cache at
|
|
72
|
+
the plugin's version and runs its Claude-family hooks as they are; runtime
|
|
73
|
+
detection reads Codex's `turn_id` and labels the session `codex`.
|
|
74
|
+
|
|
75
|
+
**The gate was met, so the old path is gone.** US4 measured L4 twice, live,
|
|
76
|
+
through the shipped plugin alone. TS5 then removed the wrapper, its generated
|
|
77
|
+
hooks, the `codex:*` hook family, the JSONL backfill (its only caller was the
|
|
78
|
+
wrapper's exit hook; the plugin's SessionEnd closes without reading it),
|
|
79
|
+
their pack-contents guards, and their CI step. The docs name the marketplace
|
|
80
|
+
install and nothing else.
|
|
81
|
+
|
|
82
|
+
**The one stale copy is watched.** Claude Code reads the plugin through a
|
|
83
|
+
link, in place; Codex runs a versioned copy. TS6 taught `runtime diagnose`
|
|
84
|
+
and `runtime update`'s post-update hints to compare that copy against the
|
|
85
|
+
installed version — the landed version, read from the just-updated tree —
|
|
86
|
+
and to print the one command that works on Codex 0.163.0, which has no
|
|
87
|
+
plugin-update verb: the re-add.
|
|
88
|
+
|
|
89
|
+
## Upgrading
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npm install -g mirror-mind@latest # or: mirror runtime update
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**If Codex runs the plugin already:** after this update (and any future one),
|
|
96
|
+
bring the cache level once:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
codex plugin add mirror-mind@mirror-mind
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`mirror runtime diagnose` will tell you whenever this is needed.
|
|
103
|
+
|
|
104
|
+
**If you wired Codex before the plugin** (a skills link, an `AGENTS.md` link,
|
|
105
|
+
the wrapper script): install the plugin with the two commands above, then
|
|
106
|
+
undo the old wiring — the exact steps are in Getting Started's Codex section.
|
|
107
|
+
If you do nothing, everything still works, at the cost of doubled skills and
|
|
108
|
+
double logging where the old wrapper still runs; an older installed package
|
|
109
|
+
keeps its own wrapper copy, but this version ships none.
|
|
110
|
+
|
|
111
|
+
No migration. Existing homes, sessions, and memories are untouched.
|
|
112
|
+
|
|
113
|
+
## Conscious Exclusions
|
|
114
|
+
|
|
115
|
+
- **Codex logging is no longer end-to-end tested**, by decision: the retired
|
|
116
|
+
wrapper smoke was the only artifact-level Codex check. Confidence now rests
|
|
117
|
+
on the shared Claude-family hook path (smoked), runtime-detection units,
|
|
118
|
+
and US4's live measurement.
|
|
119
|
+
- **Mirror never runs `codex` itself.** The cache readers are read-only
|
|
120
|
+
filesystem checks; the person runs the printed command.
|
|
121
|
+
- **Two named silences in the wiring checks:** a cache *ahead* of the install
|
|
122
|
+
(a deliberate downgrade gets no advice from the older tree), and a Claude
|
|
123
|
+
link that resolves to another install tree (healthy means the target
|
|
124
|
+
reads). Both are recorded as decisions with tests.
|
|
125
|
+
- **CR142 is captured, not fixed:** the Claude plugin smoke's negative probe
|
|
126
|
+
fails on a machine with a globally installed `mirror-hook` — a smoke
|
|
127
|
+
isolation bug found during TS5's validation, pre-existing, filed under
|
|
128
|
+
RS010.
|
|
129
|
+
|
|
130
|
+
## What We Learned
|
|
131
|
+
|
|
132
|
+
The gate ordering did the work: retiring the old wiring only after L4 was
|
|
133
|
+
measured live meant the removal was a deletion, not a bet. And the one real
|
|
134
|
+
surprise of the arc — Codex sessions outlive their TUI — was caught by the
|
|
135
|
+
live measurement, not by any test, which is why the measurement is part of
|
|
136
|
+
the method.
|
|
137
|
+
|
|
138
|
+
## Next Horizon
|
|
139
|
+
|
|
140
|
+
DS4 closes with this release. CV21's remaining runtime stories — Antigravity
|
|
141
|
+
through a native layer (DS7), Grok (DS10) — are pulled deliberately from the
|
|
142
|
+
CV21 index.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
---
|
|
2
|
+
digest: >
|
|
3
|
+
v0.35.0 is a minor release closing CV21.DS8: the Gemini CLI integration no
|
|
4
|
+
longer ships, and Antigravity stands in its place. Mirror Mind supports four
|
|
5
|
+
runtimes — Pi, Claude Code, Codex, Antigravity — and every document says so.
|
|
6
|
+
The removal waited for its gate: DS7 measured Antigravity at L4 on agy 1.4.2,
|
|
7
|
+
all five bar items, so a Gemini CLI user who moves loses nothing and gains
|
|
8
|
+
MCP. The cutoff is recorded here in full — what no longer exists, why, what
|
|
9
|
+
to do instead, what still works, and what a user who does nothing will see —
|
|
10
|
+
with the four hook entries to delete named, and v0.34.0 named as the last
|
|
11
|
+
release that carries the integration. A retired-surface guard keeps the
|
|
12
|
+
removal removed. No migration: homes, memories, journeys, and the
|
|
13
|
+
conversations logged as gemini_cli are untouched.
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# v0.35.0 — Four Runtimes, One Successor
|
|
17
|
+
|
|
18
|
+
**Date:** 2026-10-18
|
|
19
|
+
|
|
20
|
+
## Highlights
|
|
21
|
+
|
|
22
|
+
- **Gemini CLI is no longer a Mirror runtime; Antigravity is its successor**
|
|
23
|
+
([decision](../project/decisions.md#gemini-cli-is-retired-and-antigravity-is-its-successor)).
|
|
24
|
+
The four `.gemini/hooks` wrappers, the `gemini:*` hook family, the two
|
|
25
|
+
Gemini CLI steps `mirror init` printed, and the Gemini smoke no longer ship
|
|
26
|
+
(CV21.DS8.US1). The package's description and keywords, and every
|
|
27
|
+
runtime-facing document, name Pi, Claude Code, Codex, and Antigravity
|
|
28
|
+
(CV21.DS8.US2).
|
|
29
|
+
- **The gate was met first.** v0.33.0 gave notice that the integration would
|
|
30
|
+
be removed "only once Antigravity gives a Gemini CLI user what they have
|
|
31
|
+
now". CV21.DS7.US4 measured that on agy 1.4.2, live: all of Mirror's
|
|
32
|
+
skills, the Operating Instructions at session start, Mirror Mode context
|
|
33
|
+
injected once per user turn, every turn logged and the conversation closed,
|
|
34
|
+
setup in one step against Gemini CLI's two — and MCP reachable, which the
|
|
35
|
+
Gemini CLI wiring never had.
|
|
36
|
+
- **The cutoff is written where a user reads it before it happens to them**:
|
|
37
|
+
the section below, the Antigravity section of
|
|
38
|
+
[Getting Started](../getting-started.md#antigravity), and a
|
|
39
|
+
[troubleshooting entry](../process/troubleshooting.md#gemini-cli-runs-a-mirror-hook-that-no-longer-exists)
|
|
40
|
+
for the symptom a Gemini CLI user would meet.
|
|
41
|
+
- **A retired-surface guard keeps the removal removed.** `.gemini/` can never
|
|
42
|
+
ship again from this package: the row is enforced on every push and by the
|
|
43
|
+
release tripwire. That matters because `mirror init` once told users to
|
|
44
|
+
write absolute paths into that directory into their settings — a standing
|
|
45
|
+
instruction to execute whatever a later release might put there.
|
|
46
|
+
|
|
47
|
+
## Where We Started
|
|
48
|
+
|
|
49
|
+
v0.32.1 shipped Gemini CLI as one of four supported runtimes, at L4 parity,
|
|
50
|
+
wired by two documented steps. On 2026-09-25 the Navigator retired it —
|
|
51
|
+
Google had set a deprecation date for the Gemini Code Assist backend for
|
|
52
|
+
individuals, and Antigravity, which imports Claude-format plugins, was the
|
|
53
|
+
successor — but the call lived in one story's notes while the release kept
|
|
54
|
+
advertising the runtime. The decision was recorded on 2026-10-13, with a
|
|
55
|
+
condition: the integration goes only behind a documented cutoff, and only
|
|
56
|
+
once Antigravity meets the bar a Gemini CLI user already had. DS7 built the
|
|
57
|
+
agy-native layer and measured the bar. DS8 is the cutoff.
|
|
58
|
+
|
|
59
|
+
## What Changed
|
|
60
|
+
|
|
61
|
+
**The integration is gone from the package.** No `.gemini/hooks`, no `gemini`
|
|
62
|
+
entry in the wiring `mirror init` prints, no `gemini:*` hook names — an
|
|
63
|
+
unknown name is noted in `hooks.log` and the turn proceeds, as any unknown
|
|
64
|
+
name does. The Gemini smoke and the npm smoke's Gemini section retired with
|
|
65
|
+
it; the hook payload reader dropped the one field only Gemini CLI supplied.
|
|
66
|
+
|
|
67
|
+
**The docs say what ships.** Twenty files: README, Getting Started,
|
|
68
|
+
REFERENCE, the Operating Instructions and their plugin copy, the
|
|
69
|
+
runtime-interface spec, the welcome spec, the architecture, and the skills
|
|
70
|
+
that said "Pi and Gemini CLI". Where a runtime list, a wiring step, or a
|
|
71
|
+
parity table had Gemini CLI, it has Antigravity. Where a lesson says what
|
|
72
|
+
Gemini CLI taught — the payload-shape bug its smoke caught, the one-JSON-
|
|
73
|
+
object rule its hook entries kept — the lesson stays, in the past tense.
|
|
74
|
+
Getting Started's subscription table no longer carries a Gemini AI Pro row
|
|
75
|
+
and invents no Antigravity row: what Antigravity requires is Google's to
|
|
76
|
+
say, and Mirror needs only the `agy` command on your PATH.
|
|
77
|
+
|
|
78
|
+
**Antigravity's own documentation is unchanged** beyond taking Gemini CLI's
|
|
79
|
+
place: DS7 wrote it and measured it.
|
|
80
|
+
|
|
81
|
+
## The Cutoff: Gemini CLI
|
|
82
|
+
|
|
83
|
+
**What you keep.** Everything that is yours. Your `~/.mirror-minds/<user>`
|
|
84
|
+
home, your identity, your memories, your journeys, and every conversation
|
|
85
|
+
you logged — including the ones labelled `gemini_cli`, which stay readable
|
|
86
|
+
in `mm-conversations` and `mm-recall` and are never migrated or relabelled.
|
|
87
|
+
Only the runtime that reads them changes.
|
|
88
|
+
|
|
89
|
+
**Removed.** The four `.gemini/hooks` wrappers (`session-start.sh`,
|
|
90
|
+
`log-user.sh`, `log-assistant.sh`, `session-end.sh`) and the `gemini:*` hook
|
|
91
|
+
family behind them; the two Gemini CLI steps `mirror init` printed (the
|
|
92
|
+
skills link, the four hooks merged into `~/.gemini/settings.json`); the
|
|
93
|
+
Gemini smoke; the runtime from the package's description and keywords and
|
|
94
|
+
from every runtime-facing document.
|
|
95
|
+
|
|
96
|
+
**Why.** Google deprecated the Gemini Code Assist backend for individuals
|
|
97
|
+
(2026-06-18). Antigravity is its successor and imports Claude-format
|
|
98
|
+
plugins — the one plugin Mirror already ships. The removal waited for
|
|
99
|
+
DS7.US4's measurement on agy 1.4.2: all five items of the bar DS12.TS3 set
|
|
100
|
+
PASS, with per-turn injection — the cost the decision feared losing —
|
|
101
|
+
carried by agy's `PreInvocation` hook. The one difference that did
|
|
102
|
+
materialize: agy has no session-end signal, so a conversation closes when
|
|
103
|
+
your next session starts rather than at exit (as Codex's does); logging
|
|
104
|
+
parity holds, and memories extract after the close.
|
|
105
|
+
|
|
106
|
+
**What to do instead.** Install Antigravity, then the one step `mirror init`
|
|
107
|
+
prints when it finds `agy` on your PATH:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
agy plugin install "<pkg>/plugins/mirror-mind" # <pkg> = $(npm root -g)/mirror-mind
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Your home carries over unchanged — nothing to export, nothing to re-seed.
|
|
114
|
+
Same home, same memory, different door. The skills carry the plugin's name:
|
|
115
|
+
`/mirror-mind:mm:mirror`, `/mirror-mind:mm:journeys`, and so on.
|
|
116
|
+
|
|
117
|
+
**What still works.** Gemini *models*. Memory extraction runs on
|
|
118
|
+
`google/gemini-2.5-flash-lite` through OpenRouter, and `consult` reaches the
|
|
119
|
+
`gemini` family as before. Those are model choices, not the runtime.
|
|
120
|
+
|
|
121
|
+
**If you do nothing.** After the update, the four `mirror-*` hook commands in
|
|
122
|
+
your `~/.gemini/settings.json` point at files that no longer exist, while the
|
|
123
|
+
links in `~/.gemini/skills/` still resolve — `.pi/skills` keeps shipping. So
|
|
124
|
+
Gemini CLI keeps Mirror's skills and loses logging and Mirror Mode injection.
|
|
125
|
+
Said plainly: your Gemini CLI sessions stop being logged and Mirror Mode
|
|
126
|
+
stops being injected, and nothing on screen says so. Measured on Gemini CLI
|
|
127
|
+
0.61.0 in headless mode (`gemini -p`), 2026-10-18: a registered hook whose
|
|
128
|
+
command is missing is skipped silently; the session proceeds. The entries to
|
|
129
|
+
delete, in `~/.gemini/settings.json`: `mirror-session-start` (under
|
|
130
|
+
`SessionStart`), `mirror-log-user` (`BeforeAgent`), `mirror-log-assistant`
|
|
131
|
+
(`AfterAgent`), `mirror-session-end` (`SessionEnd`); and the `mm-*` links in
|
|
132
|
+
`~/.gemini/skills/`. Mirror never wrote those files and does not edit them.
|
|
133
|
+
Whether Antigravity also reads `~/.gemini/skills/` — which would show a
|
|
134
|
+
migrated user the stale links as duplicate skills — was not measured;
|
|
135
|
+
remove the links either way.
|
|
136
|
+
|
|
137
|
+
**To stay on Gemini CLI a while longer.** `npm install -g mirror-mind@0.34.0`
|
|
138
|
+
is the last release that carries the integration. The welcome card and
|
|
139
|
+
`runtime update` will keep offering the newer version every session; the pin
|
|
140
|
+
is a choice to make knowingly, not a quiet state.
|
|
141
|
+
|
|
142
|
+
## Upgrading
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
npm install -g mirror-mind@latest # or: mirror runtime update
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**If you used Gemini CLI:** read the cutoff above; the steps are in Getting
|
|
149
|
+
Started's Antigravity section. **Every other runtime:** nothing to do. No
|
|
150
|
+
migration. Existing homes, sessions, and memories are untouched.
|
|
151
|
+
|
|
152
|
+
## Also In This Release
|
|
153
|
+
|
|
154
|
+
- **Typecheck is green on `main` again.** DS7.TS3 left one early return in
|
|
155
|
+
`hooks/agy.ts` without the field it had just added; `tsc --noEmit`, a CI
|
|
156
|
+
gate, refused since. Found by DS8.US1's validation, paid in its own commit.
|
|
157
|
+
- **The docs link check is green again.** The plugin's byte copy of the
|
|
158
|
+
Operating Instructions carries a root-relative link that cannot resolve
|
|
159
|
+
under `rules/`; the checker reported it on every `.md` push since DS7.US1.
|
|
160
|
+
The copy's links now resolve where the source lives — not skipped: a link
|
|
161
|
+
the source cannot resolve still fails through the copy.
|
|
162
|
+
- **The P1 redaction invariant outlives the runtime it was written against.**
|
|
163
|
+
"A failed hook never writes the prompt or the reply to `hooks.log`" was
|
|
164
|
+
tested through the Gemini CLI hooks; it now runs through the Claude-family
|
|
165
|
+
hooks every plugin runtime shares.
|
|
166
|
+
|
|
167
|
+
## Conscious Exclusions
|
|
168
|
+
|
|
169
|
+
- **No second cutoff document.** CV22 needed `pending-cutoffs.md` for eleven
|
|
170
|
+
cutoffs in one release; DS8 has one, and this note is its record.
|
|
171
|
+
- **Mirror does not edit `~/.gemini/settings.json` or `~/.gemini/skills/`.**
|
|
172
|
+
It never wrote them. The note and the guidance name what to remove.
|
|
173
|
+
- **The Claude plugin smoke's negative probe** still cannot run on a machine
|
|
174
|
+
with a globally installed `mirror-hook` (CR142, D-031): pre-existing,
|
|
175
|
+
local-only, carried.
|
|
176
|
+
- **DS5, DS10, DS11** — user extensions on every runtime, Grok through the
|
|
177
|
+
plugin, the contract and docs refresh — are CV21's remaining stories, not
|
|
178
|
+
this release's.
|
|
179
|
+
|
|
180
|
+
## What We Learned
|
|
181
|
+
|
|
182
|
+
A retirement that lives in a decision while the release advertises the
|
|
183
|
+
runtime has not happened; it happened here in three stories, in order:
|
|
184
|
+
remove, then make the tree say so, then tell the user — and the guard that
|
|
185
|
+
proves each step split by story, so nothing went red between them. The
|
|
186
|
+
sweep found what the inventory missed (a spec line, a history link), which
|
|
187
|
+
is what a guard is for. And the one fact this note most needed — what a
|
|
188
|
+
user who does nothing will see — turned out to be *nothing*: Gemini CLI
|
|
189
|
+
skips a missing hook in silence. That is the strongest reason the cutoff is
|
|
190
|
+
written where the user looks, not only here.
|
|
191
|
+
|
|
192
|
+
## Next Horizon
|
|
193
|
+
|
|
194
|
+
DS8 closes with this release, and with it the runtime set CV21 set out to
|
|
195
|
+
reach: the canonical plugin on Claude Code, Codex, and Antigravity, Pi
|
|
196
|
+
through its extension. What remains in CV21 is pulled deliberately from the
|
|
197
|
+
CV21 index: user extensions on every runtime (DS5), Grok through the plugin
|
|
198
|
+
(DS10), and the contract and docs refresh that folds all of it into one
|
|
199
|
+
account (DS11).
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mirror-mind",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Mirror Mind: a local-first memory and identity framework for agentic AI runtimes (Pi, Claude Code,
|
|
3
|
+
"version": "0.35.0",
|
|
4
|
+
"description": "Mirror Mind: a local-first memory and identity framework for agentic AI runtimes (Pi, Claude Code, Codex, Antigravity)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"agent",
|
|
16
16
|
"pi-package",
|
|
17
17
|
"claude-code",
|
|
18
|
-
"gemini-cli",
|
|
19
18
|
"codex",
|
|
20
19
|
"sqlite",
|
|
21
20
|
"local-first"
|
|
@@ -36,10 +35,8 @@
|
|
|
36
35
|
".pi/extensions",
|
|
37
36
|
".pi/skills",
|
|
38
37
|
".claude/hooks",
|
|
39
|
-
".gemini/hooks",
|
|
40
38
|
"plugins/mirror-mind",
|
|
41
|
-
"
|
|
42
|
-
"scripts/codex-mirror.sh",
|
|
39
|
+
".agents/plugins",
|
|
43
40
|
"AGENTS.md",
|
|
44
41
|
"README.md",
|
|
45
42
|
"LICENSE"
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Mirror Mind hook wrapper — GENERATED by scripts/generate_hook_wrappers.sh.
|
|
3
|
+
# Edit the generator, never this file: every agy wrapper shares these bytes
|
|
4
|
+
# and differs only in the hook name and its stdin gate (CV21.DS7.TS2).
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
HOOK="agy:pre-invocation"
|
|
7
|
+
GATE='"invocationNum"[[:space:]]*:[[:space:]]*-?[0-9]*[1-9]'
|
|
8
|
+
|
|
9
|
+
# agy sends the payload on stdin and blocks its agent loop on this process.
|
|
10
|
+
# Read the payload once; when the gate says this invocation is not ours,
|
|
11
|
+
# answer the empty object without resolving Node at all.
|
|
12
|
+
PAYLOAD="$(cat 2>/dev/null || true)"
|
|
13
|
+
if [ -n "$GATE" ] && printf '%s' "$PAYLOAD" | grep -qE "$GATE"; then
|
|
14
|
+
printf '{}\n'
|
|
15
|
+
exit 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
# This wrapper is the Claude plugin's, and a plugin is copied into Claude
|
|
19
|
+
# Code's own cache: no relative path from here reaches the Mirror tree. It
|
|
20
|
+
# runs the installed `mirror-hook` bin instead, and reads no tree .env.
|
|
21
|
+
REPO_ROOT=""
|
|
22
|
+
|
|
23
|
+
# A hook never fails the user's turn, and never fails in silence: when it
|
|
24
|
+
# cannot do its job it appends ONE line to <mirror home>/hooks.log and exits
|
|
25
|
+
# 0 — after answering agy's contract, so the agent loop never stalls.
|
|
26
|
+
env_file_value() {
|
|
27
|
+
[ -f "$2" ] || return 0
|
|
28
|
+
sed -n -E "s/^[[:space:]]*(export[[:space:]]+)?$1[[:space:]]*=[[:space:]]*//p" "$2" \
|
|
29
|
+
| tail -n 1 | tr -d "\"'\r"
|
|
30
|
+
}
|
|
31
|
+
env_value() {
|
|
32
|
+
local value=""
|
|
33
|
+
if [ -n "${!1+set}" ]; then printf '%s' "${!1}"; return; fi
|
|
34
|
+
[ -z "$REPO_ROOT" ] || value="$(env_file_value "$1" "$REPO_ROOT/.env")"
|
|
35
|
+
[ -n "$value" ] || value="$(env_file_value "$1" "${XDG_CONFIG_HOME:-$HOME/.config}/mirror/env")"
|
|
36
|
+
printf '%s' "$value"
|
|
37
|
+
}
|
|
38
|
+
note() {
|
|
39
|
+
local home user
|
|
40
|
+
home="$(env_value MIRROR_HOME)"
|
|
41
|
+
user="$(env_value MIRROR_USER)"
|
|
42
|
+
if [ -n "$home" ]; then
|
|
43
|
+
home="${home/#\~/$HOME}"
|
|
44
|
+
elif [ -n "$user" ]; then
|
|
45
|
+
home="$HOME/.mirror-minds/$user"
|
|
46
|
+
[ -d "$home" ] || [ ! -d "$HOME/.mirror/$user" ] || home="$HOME/.mirror/$user"
|
|
47
|
+
else
|
|
48
|
+
return 0
|
|
49
|
+
fi
|
|
50
|
+
mkdir -p "$home" 2>/dev/null \
|
|
51
|
+
&& printf '%s %s: %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$HOOK" "$1" >> "$home/hooks.log" 2>/dev/null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# Find the bin. MIRROR_BIN names the directory holding `mirror` and
|
|
55
|
+
# `mirror-hook` (`$(npm prefix -g)/bin`), the same trust class as MIRROR_NODE;
|
|
56
|
+
# then the PATH; then the global bin directories a GUI launch leaves off it.
|
|
57
|
+
ENTRY=""
|
|
58
|
+
[ -n "${MIRROR_BIN:-}" ] && [ -x "$MIRROR_BIN/mirror-hook" ] && ENTRY="$MIRROR_BIN/mirror-hook"
|
|
59
|
+
[ -n "$ENTRY" ] || ENTRY="$(command -v mirror-hook 2>/dev/null || true)"
|
|
60
|
+
for candidate in "$HOME/.nvm/current/bin" /opt/homebrew/bin /usr/local/bin; do
|
|
61
|
+
[ -n "$ENTRY" ] && break
|
|
62
|
+
[ -x "$candidate/mirror-hook" ] && ENTRY="$candidate/mirror-hook"
|
|
63
|
+
done
|
|
64
|
+
|
|
65
|
+
if [ -z "$ENTRY" ]; then
|
|
66
|
+
note "mirror-hook not found on PATH; hook skipped. Install mirror-mind (npm install -g mirror-mind) or set MIRROR_BIN to its bin directory."
|
|
67
|
+
exit 0
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
NODE="${MIRROR_NODE:-}"
|
|
71
|
+
if [ -z "$NODE" ] || [ ! -x "$NODE" ]; then
|
|
72
|
+
NODE="$(command -v node 2>/dev/null || true)"
|
|
73
|
+
fi
|
|
74
|
+
for candidate in "$(dirname "$ENTRY")/node" "$HOME/.nvm/current/bin/node" /opt/homebrew/bin/node /usr/local/bin/node; do
|
|
75
|
+
[ -n "$NODE" ] && break
|
|
76
|
+
[ -x "$candidate" ] && NODE="$candidate"
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
if [ -z "$NODE" ]; then
|
|
80
|
+
printf '{}\n'
|
|
81
|
+
note "node not found on PATH; hook skipped. Set MIRROR_NODE."
|
|
82
|
+
exit 0
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# The payload was consumed by the gate read; re-feed it to the entry.
|
|
86
|
+
printf '%s' "$PAYLOAD" | "$NODE" "$ENTRY" "$HOOK" "$@"
|
|
87
|
+
status=$?
|
|
88
|
+
if [ "$status" -ne 0 ]; then
|
|
89
|
+
printf '{}\n'
|
|
90
|
+
note "node exited $status before the hook finished ($NODE, $("$NODE" --version 2>/dev/null || echo 'version unknown')); Mirror needs Node 24 or later. Set MIRROR_NODE."
|
|
91
|
+
fi
|
|
92
|
+
exit 0
|