Skip to content

Reach two more harnesses, and stop a database pin from drifting - #7

Merged
UnbreakableMJ merged 4 commits into
mainfrom
harness-openclaude-antigravity
Aug 22, 2026
Merged

Reach two more harnesses, and stop a database pin from drifting#7
UnbreakableMJ merged 4 commits into
mainfrom
harness-openclaude-antigravity

Conversation

@UnbreakableMJ

Copy link
Copy Markdown
Contributor

Reported: engram's slash commands never appear in Antigravity CLI (agy) or OpenClaude. Two unrelated causes — plus a defect found on the way that matters more than either.

1. OpenClaude was simply unknown

A Claude Code fork (@gitlawb/openclaude v0.24.0) with its own config root. Now the eighth harness:

Commands ~/.openclaude/commands/
MCP registration ~/.openclaude.json — the ~/.claude.json analogue, not ~/.openclaude/settings.json, which carries no servers block
Transcripts ~/.openclaude/projects/<mangled-cwd>/*.jsonl, read by the existing Claude Code reader

Verified against a real session: 2 turns captured, unknown_record: 0. The fork-only record types (mode, file-history-snapshot, last-prompt) were already in the non-message allowlist — and must stay there, because a fork tripping the drift alarm on every run would train a reader to ignore it.

2. Antigravity was correctly refused, but dishonestly explained

It has no slash-command directory at all. Its extension surface is skills, packaged in plugins. Decisively:

$ agy plugin validate <plugin-with-commands/>
  [ok]  ✔ commands : 2 processed (converted to skills)

A command there becomes a skill regardless, so engram writes the plugin directly — and agy plugin validate accepts it:

$ agy plugin validate ~/.gemini/config/plugins/engram
  [ok]  ✔ skills : 3 processed

This reverses the documented "engram never ships a skill" rule. That rule was written for the Nix-locked ~/.claude/skills and does not generalise; the rule is now that engram installs into whatever a harness makes writable and never into the Nix store. Antigravity's own skills path is store-managed — its plugins path is not.

HarnessSpec models this as CommandSurface::{Markdown, Plugin, None}. The old command_frontmatter: bool could not express it: the artifact's shape differs, not just whether a header is read. None now carries a per-harness reason, since one shared sentence described none of the three harnesses it was applied to.

3. The defect worth more than both

Every harness on this machine had moved to ~/.local/share/engram/engram.db. The installed commands still pinned ~/.gemini/engram.db. Both databases are real and actively written, with disjoint scopes:

~/.local/share/… (2.5M) ~/.gemini/engram.db (1.6M)
majestic-codex 1530, vacuum 192, standard 175, engram 135 bravais 602, majestic 311, construct 75

So /engram-* and engram's MCP tools had been reading different stores for weeks, with nothing to say so.

registered_db was never wrong — the registrations changed after install ran, and nothing checked. It checks now, reporting the drift on the file and on the harness before correcting it:

WARNING [claude-code]: generated commands were pinned to /home/mj/.gemini/engram.db
  but this harness registers /home/mj/.local/share/engram/engram.db; re-pinned.
  Until now, /engram-* commands and engram's MCP tools were reading different databases.

Every response also carries db_origin (override / registered / env / default) so the relative-engram.db fallback is visible rather than silent.

4. find_git_root accepted an empty .git

Found because the test suite started failing on it. Any .git entry counted as a repository, so an empty /tmp/.git made save-chat resolve its project root to /tmp — creating /tmp/chat/ and adding chat/ to /tmp/.gitignore. Which is exactly what the test suite had been doing.

A directory now needs .git/HEAD; a .git file (worktree, submodule) still counts. Tests that resolve a project root pin their own marker via pinned_project rather than depending on whether the developer's /tmp looks like a repository.

Gates

fmt · clippy -D warnings · 259 tests across both feature sets · REUSE 3.3 · makeinfo clean

🤖 Generated with Claude Code

https://claude.ai/code/session_016i16R4GhdSffsboRYq97Fs

UnbreakableMJ and others added 3 commits August 8, 2026 12:43
Steelbore Standard §5.7 makes AGENTS.md the single harness-neutral source
of truth and reduces CLAUDE.md to an @AGENTS.md import plus Claude-only
content. Rendering the managed block into both files therefore delivers
it to Claude twice, and — worse — creates two copies that can disagree
once anything edits one of them.

§5.7 puts the obligation on the tooling: rendered blocks target
AGENTS.md, and every harness reading CLAUDE.md picks them up through the
import. DEFAULT_TARGETS drops to ["AGENTS.md"]; --file still overrides.

User-facing strings updated across the CLI, MCP, and HTTP surfaces, plus
the manual and README. rule_sync_dry_run_writes_no_files now asserts one
target and names it.

cargo test: 245 passed. clippy -D warnings and fmt --check clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Companion to the rule-sync change on this branch: CLAUDE.md's project
content moves into AGENTS.md, and CLAUDE.md becomes the @AGENTS.md
import. The absolute `/home/mj/.gemini/engram.db` path in the {{DB}}
note is genericised, since AGENTS.md is a published artifact.

Steelbore Standard v1.46 §5.7.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reported: engram's slash commands never appear in Antigravity CLI or
OpenClaude. Two unrelated causes, plus a defect found on the way that matters
more than either.

OpenClaude was simply unknown. It is a Claude Code fork with its own config
root, so it is now the eighth harness: commands go to
`~/.openclaude/commands/`, the MCP registration is read from
`~/.openclaude.json` (the `~/.claude.json` analogue, not the settings file,
which carries no servers block), and its transcripts are read by the existing
Claude Code reader. Verified against a real session: two turns captured and
`unknown_record: 0` — the fork-only record types were already in the
non-message allowlist, and they must stay there, because a fork tripping the
drift alarm on every run would train a reader to ignore it.

Antigravity was correctly refused but dishonestly explained. It has no
slash-command directory at all; its extension surface is skills, packaged in
plugins. `agy plugin validate` reports a plugin's own `commands/` as
"2 processed (converted to skills)", so a command there becomes a skill either
way — engram now writes the plugin directly, and `validate` accepts it. This
reverses the "engram never ships a skill" rule, which was written for the
Nix-locked `~/.claude/skills` and does not generalise: the rule is now that
engram installs into whatever a harness makes writable and never into the Nix
store. Antigravity's own skills path is store-managed; its plugins path is not.

`HarnessSpec` models this as `CommandSurface::{Markdown, Plugin, None}`. The
old `command_frontmatter: bool` could not express it — the artifact's *shape*
differs, not just whether a header is read — and `None` now carries a
per-harness reason, since one shared sentence described none of the three
harnesses it was applied to.

The defect: every harness on this machine had moved to
`~/.local/share/engram/engram.db`, while the installed commands still pinned
`~/.gemini/engram.db`. Both databases are real and actively written, with
disjoint scopes, so `/engram-*` and engram's MCP tools had been reading
different stores for weeks with nothing to say so. `registered_db` was never
wrong; the registrations changed after `install` ran, and nothing checked. It
checks now, reporting the drift on the file and the harness before correcting
it, and every response carries `db_origin` so the relative-`engram.db` fallback
is visible rather than silent.

Also fixed, found because the test suite started failing on it: `find_git_root`
treated any `.git` entry as a repository. An empty `/tmp/.git` therefore made
`save-chat` resolve its project root to `/tmp`, create `/tmp/chat/`, and add
`chat/` to `/tmp/.gitignore` — which is exactly what the suite had been doing.
A directory now needs `.git/HEAD`; a `.git` file (worktree, submodule) still
counts. Tests that resolve a project root pin their own marker rather than
depending on whether the developer's `/tmp` looks like a repository.

Gates: fmt, clippy -D warnings, 259 tests (both feature sets), REUSE 3.3,
makeinfo clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016i16R4GhdSffsboRYq97Fs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e8b3580d1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/rules.rs
/// `CLAUDE.md` picks them up through the import.
///
/// Callers that genuinely need another destination still pass `--file`.
pub const DEFAULT_TARGETS: [&str; 1] = ["AGENTS.md"];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep syncing the Claude policy target by default

In projects whose CLAUDE.md does not already import @AGENTS.md—including existing Engram users created before this convention—changing the sole default to AGENTS.md means rule sync no longer updates any file Claude Code loads, so newly added or retired rules silently fail to take effect there. The CLI, MCP, and HTTP paths all consume this default; either continue syncing CLAUDE.md or ensure the import exists before relying on it.

AGENTS.md reference: AGENTS.md:L88-L90

Useful? React with 👍 / 👎.

Comment thread src/install.rs
Comment on lines +383 to +387
let written = managed_file::write_managed(
&manifest,
PLUGIN_MANIFEST,
WritePolicy::Owned,
dry_run,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Refuse to overwrite a foreign plugin manifest

When an Antigravity user already has ~/.gemini/config/plugins/engram/plugin.json, this unconditional owned-file write replaces that manifest even without --force; unlike each SKILL.md, the manifest has no banner and is never passed through is_ours. This can destroy metadata belonging to an existing plugin that happens to use the engram name, despite install promising to skip files it cannot identify as generated by Engram.

AGENTS.md reference: AGENTS.md:L179-L180

Useful? React with 👍 / 👎.

Comment thread src/install.rs
Comment on lines +369 to +371
written.reason = Some(format!(
"was pinned to {old}; re-pinned to {db}. Commands and MCP tools were reading \
different databases."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Describe dry-run repinning as a preview

When a stale pin is found under install --dry-run, write_managed deliberately leaves the file untouched, but this reason still says it "re-pinned" the command. A user can therefore finish the dry run believing the database split was corrected even though the old pin remains active; make the wording conditional on dry_run (for example, "would re-pin").

Useful? React with 👍 / 👎.

Comment thread src/install.rs
Comment on lines +400 to +403
let mut w = format!(
"generated commands were pinned to {old} but this harness registers {db}; \
re-pinned. Until now, /engram-* commands and engram's MCP tools were reading \
different databases."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Do not label non-registered database choices as registered

If the target database came from --db-path, ENGRAM_DB, or the default rather than the harness configuration, this warning falsely says the harness "registers" that value and claims the command/MCP split was repaired. For example, install --db-path /override.db with MCP still registered to /registered.db produces this success message while deliberately leaving the two surfaces divergent; use db_origin to reserve the MCP-alignment claim for Registered.

AGENTS.md reference: AGENTS.md:L278-L278

Useful? React with 👍 / 👎.

CI's clippy is newer than the local toolchain and rejects `chunks_exact(4)`
under `chunks_exact_to_as_chunks`. The lint is right: `as_chunks::<4>()` yields
`[u8; 4]` arrays directly, so the `try_into().expect("chunks_exact yields 4
bytes")` that justified itself in a comment simply disappears.

Both call sites decoded the same blob the same way, so the logic is now one
`decode_vector` helper rather than two copies of a fallible conversion that
could never fail.

Behaviour is unchanged, including for a corrupt row: trailing bytes that do not
fill an f32 are still dropped, and a short vector still cosines to 0.0 rather
than panicking mid-query.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016i16R4GhdSffsboRYq97Fs
@UnbreakableMJ
UnbreakableMJ merged commit 3ad3242 into main Aug 22, 2026
5 checks passed
@UnbreakableMJ
UnbreakableMJ deleted the harness-openclaude-antigravity branch August 22, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant