@bluenotelogic/harness 0.1.0 → 0.2.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/CHANGELOG.md +114 -0
- package/NOTICE +5 -0
- package/README.md +175 -20
- package/assets/antigravity-plugin/README.md +69 -0
- package/assets/antigravity-plugin/hooks.json +77 -0
- package/assets/antigravity-plugin/plugin.json +5 -0
- package/assets/antigravity-plugin/rules/proofmem.md +9 -0
- package/assets/antigravity-plugin/scripts/antigravity-hook.mjs +630 -0
- package/assets/antigravity-plugin/scripts/resolve-bash.mjs +48 -0
- package/dist/antigravity.d.ts +26 -0
- package/dist/antigravity.js +118 -0
- package/dist/antigravity.js.map +1 -0
- package/dist/bundle.d.ts +22 -0
- package/dist/bundle.js +36 -1
- package/dist/bundle.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.js +398 -64
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +44 -3
- package/dist/oauth.js +106 -11
- package/dist/oauth.js.map +1 -1
- package/dist/writers.d.ts +57 -15
- package/dist/writers.js +258 -58
- package/dist/writers.js.map +1 -1
- package/package.json +10 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to `@bluenotelogic/harness`. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/). While the version is 0.x, a minor
|
|
5
|
+
release may contain breaking changes; they are listed first.
|
|
6
|
+
|
|
7
|
+
## [0.2.0] - 2026-10-31
|
|
8
|
+
|
|
9
|
+
Everything since 0.1.0 (the npm release, built from `7b48279`). The product is now ProofMEM, and
|
|
10
|
+
the defaults follow it.
|
|
11
|
+
|
|
12
|
+
### Breaking
|
|
13
|
+
|
|
14
|
+
- **Default server** `https://mem.bnlgit.com` is now `https://proofmem.com`. Use `--url` to point
|
|
15
|
+
at another deployment.
|
|
16
|
+
- **OAuth client** `blue-note-mem-mcp` is now `proofmem-mcp`. Use `--client-id` if your server
|
|
17
|
+
still registers the old client.
|
|
18
|
+
- **Codex token variable** `BNL_MEMORY_MCP_TOKEN` is now `PROOFMEM_TOKEN`, and the Codex config
|
|
19
|
+
references the new name. Existing `BNL_MEMORY_MCP_TOKEN` and `CAVEAU_MCP_TOKEN` lines in
|
|
20
|
+
`~/.codex/.env` are left in place, with a one-line notice naming them (never their values).
|
|
21
|
+
- **MCP server key** `mem` is now `proofmem`. The key comes from the server's bundle; `proofmem`
|
|
22
|
+
is also the fallback. `--server-name` still overrides it.
|
|
23
|
+
- **No token in the repo, ever.** `--mint-token` and `--codex` no longer write the token into
|
|
24
|
+
the target repo's `.claude/settings.local.json`. `~/.codex/.env` is its only home; Claude Code
|
|
25
|
+
and VS Code use OAuth and need no token.
|
|
26
|
+
- **Codex config is one managed block.** The installer now owns a marked
|
|
27
|
+
`# BEGIN/END @bluenotelogic/harness managed MCP` block in `~/.codex/config.toml`, with
|
|
28
|
+
`default_tools_approval_mode = "prompt"` and approvals for the memory and harness-run tools.
|
|
29
|
+
The 0.1.0 block, and the exact table `codex mcp add` writes, are adopted into it. Any other
|
|
30
|
+
table with the same name is left untouched and reported, never overwritten.
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- `--antigravity`: installs the ProofMEM plugin for Google Antigravity. It has a
|
|
35
|
+
tokenless native OAuth MCP config, plus Caveau Harness v2 lifecycle hooks that use their own
|
|
36
|
+
owner-only 90-day key. Needs `--harness-home <caveau-harness-v2>` (or `HARNESS_HOME`), and bash
|
|
37
|
+
plus jq for the hooks. `--antigravity-home` overrides `~/.gemini/config`.
|
|
38
|
+
- Only the memory hooks get the hook key, and they are then pinned to ProofMEM
|
|
39
|
+
(`HARNESS_MEMORY_PROVIDER` and `HARNESS_COORDINATION_STORE` = `caveaumem`). The key and its
|
|
40
|
+
API URL always come as a pair from one source.
|
|
41
|
+
- The guard, checkpoint, lint and verify hooks get no credential-shaped environment variable:
|
|
42
|
+
a name part that is `KEY`, `PAT`, `PWD`, `PASS` or `AUTH` (`AUTH` except in `HARNESS_*`
|
|
43
|
+
names), or that ends in `TOKEN`, `SECRET`, `PASSWORD`, `PASSWD`, `PASSPHRASE`, `CREDENTIAL`,
|
|
44
|
+
`BEARER`, `APIKEY` or `JWT`. Nor do they get the editor's Git and SSH credential bridges,
|
|
45
|
+
which hold no secret but hand a child process your credentials anyway: `GIT_ASKPASS`,
|
|
46
|
+
`SSH_ASKPASS`, `SSH_ASKPASS_REQUIRE`, `SSH_AUTH_SOCK`, `GIT_SSH_COMMAND`, `GIT_SSH`, every
|
|
47
|
+
`VSCODE_GIT_*`, and `GIT_CONFIG_PARAMETERS`, `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_<n>` and
|
|
48
|
+
`GIT_CONFIG_VALUE_<n>`. A trusted project's verify build that needs your SSH agent or Git
|
|
49
|
+
sign-in has to be run by hand. Other names, a credential helper your own Git config names, and
|
|
50
|
+
credential files such as `~/.npmrc`, are not hidden.
|
|
51
|
+
- With `--codex` as well, Codex and the hooks get separate keys, so revoking one leaves the
|
|
52
|
+
other working.
|
|
53
|
+
- `--verify-gate`: opt in to the Antigravity Stop hook running the open project's own
|
|
54
|
+
build/test/lint. Off by default, because it runs that project's code. An empty exported
|
|
55
|
+
`HARNESS_VERIFY_GATE` counts as unset, so it cannot switch the gate on.
|
|
56
|
+
- Sign-in through the proofmem.com OAuth gateway. Its `/oauth/token` already returns a ProofMEM
|
|
57
|
+
key (`cmem_…`), which the CLI now uses directly; sending it to `/api/oidc_exchange.php` again
|
|
58
|
+
was a 401 that made sign-in impossible. A Blue Note ID token, from a server without the
|
|
59
|
+
gateway, is still exchanged.
|
|
60
|
+
- `doctor`: read-only installation checks for the Codex block, the credential store,
|
|
61
|
+
`HARNESS_HOME` and a tokenless repo config. With `--antigravity` it also checks the plugin,
|
|
62
|
+
hook-key expiry and that bash resolves. It never prints a credential.
|
|
63
|
+
- A minted token's expiry (90 days, set by the server) is printed after a real run. The value
|
|
64
|
+
never is.
|
|
65
|
+
- Distinct messages for an identity the server cannot use (422) and for Blue Note ID being
|
|
66
|
+
down (503), so neither reads as a failed login.
|
|
67
|
+
- A sign-in the proofmem.com gateway refuses with `access_denied` (no ProofMEM subscription, or a
|
|
68
|
+
Blue Note ID without a verified email) now says so and where to fix each: `/pricing.php` on
|
|
69
|
+
the server, or `https://id.bluenotelogic.com`. It used to print
|
|
70
|
+
`token exchange failed: 400 {"error":"access_denied"}`, which read as a failed login. With
|
|
71
|
+
`--device` it also lists a declined approval.
|
|
72
|
+
- `NOTICE` and this `CHANGELOG.md` ship in the package.
|
|
73
|
+
|
|
74
|
+
### Fixed
|
|
75
|
+
|
|
76
|
+
- On Windows the browser opens the whole sign-in URL. It used to go through `cmd /c start`,
|
|
77
|
+
which ends a command at every `&`, so the browser opened `/oauth/authorize?response_type=code`
|
|
78
|
+
only and the server refused it; pasting the printed URL was the only way in. The CLI now
|
|
79
|
+
starts `rundll32 url.dll,FileProtocolHandler` directly, with no shell, and opens only http(s)
|
|
80
|
+
URLs.
|
|
81
|
+
- `--dry-run` no longer mints. It used to create a real, non-expiring token server-side and print
|
|
82
|
+
it in the preview. Credential files are now shown redacted. Signing in still creates one
|
|
83
|
+
short-lived (1 h) session key.
|
|
84
|
+
- A sign-in no longer leaves its refresh grant behind. The CLI asks for `offline_access` but
|
|
85
|
+
never uses the refresh token, and through proofmem.com that token stands for a Blue Note ID
|
|
86
|
+
refresh token the gateway keeps, encrypted, for up to 35 days. Every run, `--dry-run` included,
|
|
87
|
+
now revokes it (RFC 7009) once the configuration is fetched, and says so if the server does not
|
|
88
|
+
confirm.
|
|
89
|
+
- The token no longer lands in the repo (see Breaking): `.claude/settings.local.json` is never
|
|
90
|
+
written.
|
|
91
|
+
- Credential files are owner-only: `chmod 0600` on Linux and macOS, and on Windows an access list
|
|
92
|
+
with exactly one entry for the current user's SID (verified in any language; sandbox entries
|
|
93
|
+
such as `CodexSandboxUsers` are removed). A credential file is recreated rather than rewritten,
|
|
94
|
+
so an old grant cannot survive. If the protection cannot be proved, the file is deleted and the
|
|
95
|
+
install fails.
|
|
96
|
+
|
|
97
|
+
### Migrating from 0.1.0
|
|
98
|
+
|
|
99
|
+
1. Re-run `npx @bluenotelogic/harness init` in each configured repo. It adds the `proofmem`
|
|
100
|
+
server to `.mcp.json` and never deletes keys it does not own, so remove the old `mem` entry by
|
|
101
|
+
hand.
|
|
102
|
+
2. If you used `--mint-token` or `--codex` with 0.1.0, delete the `BNL_MEMORY_MCP_TOKEN` entry
|
|
103
|
+
from that repo's `.claude/settings.local.json`. Tokens from that era may have no expiry, so
|
|
104
|
+
revoke the ones you no longer use at `https://proofmem.com/app/keys.php`.
|
|
105
|
+
3. Codex: re-run `init --codex`. The managed block switches to `PROOFMEM_TOKEN`. Remove
|
|
106
|
+
`BNL_MEMORY_MCP_TOKEN` / `CAVEAU_MCP_TOKEN` from `~/.codex/.env` once nothing else on the
|
|
107
|
+
machine reads them; `doctor` warns while they are there.
|
|
108
|
+
4. For a deployment other than proofmem.com, pass `--url`, and `--client-id` if it still uses the
|
|
109
|
+
old OAuth client.
|
|
110
|
+
|
|
111
|
+
## [0.1.0]
|
|
112
|
+
|
|
113
|
+
First npm release: `init` with browser (PKCE) and `--device` sign-in, a tokenless `.mcp.json`,
|
|
114
|
+
optional `--mint-token` / `--codex`, `--harness-home` routing, and `--timeout`.
|
package/NOTICE
ADDED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @bluenotelogic/harness
|
|
2
2
|
|
|
3
|
-
Point a machine at [
|
|
3
|
+
Point a machine at [ProofMEM](https://proofmem.com) in one command.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npx @bluenotelogic/harness init
|
|
@@ -12,7 +12,7 @@ working MCP config into the current repo.
|
|
|
12
12
|
## What it writes — and what it deliberately does not
|
|
13
13
|
|
|
14
14
|
```json
|
|
15
|
-
{ "mcpServers": { "
|
|
15
|
+
{ "mcpServers": { "proofmem": { "type": "http", "url": "https://proofmem.com/mcp" } } }
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
**There is no token in that file.** Claude Code and VS Code discover authentication from the
|
|
@@ -24,25 +24,63 @@ That is the entire point of this tool. The setup it replaces meant pasting a bea
|
|
|
24
24
|
hand into `.mcp.json`, `~/.claude.json`, `~/.codex/config.toml` and a VS Code roaming
|
|
25
25
|
profile — and rotating anything meant editing every one of them again.
|
|
26
26
|
|
|
27
|
-
## Codex
|
|
27
|
+
## Codex
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Codex can sign in with OAuth on its own. Codex CLI 0.163.0 runs the OAuth flow for an MCP
|
|
30
|
+
server with `codex mcp login <name>` and keeps that credential itself; this was verified with
|
|
31
|
+
proofmem.com on 2026-10-27. That path needs no token from this CLI. A plain `init` writes no
|
|
32
|
+
Codex config, so add the server to Codex first, then sign in:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
codex mcp add proofmem --url https://proofmem.com/mcp
|
|
36
|
+
codex mcp login proofmem
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
The same two steps are in the [ProofMEM docs](https://proofmem.com/docs.php).
|
|
40
|
+
|
|
41
|
+
This CLI does not run Codex's sign-in for you. `--codex` configures Codex with a minted token
|
|
42
|
+
instead (`--codex` implies `--mint-token`):
|
|
30
43
|
|
|
31
44
|
```bash
|
|
32
45
|
npx @bluenotelogic/harness init --codex
|
|
33
46
|
```
|
|
34
47
|
|
|
35
|
-
The minted token goes to `~/.codex/.env` and is referenced from
|
|
36
|
-
(`bearer_token_env_var`), so the config file stays safe to read over someone's shoulder — and
|
|
37
|
-
the token still never touches the repo
|
|
38
|
-
`--mint-token`, this CLI creates no credential and no
|
|
48
|
+
The minted token goes to `~/.codex/.env` as `PROOFMEM_TOKEN` and is referenced from
|
|
49
|
+
`config.toml` by name (`bearer_token_env_var`), so the config file stays safe to read over someone's shoulder — and
|
|
50
|
+
the token still never touches the repo, not even the target repo's own `.claude/settings.local.json`.
|
|
51
|
+
Minting is opt-in: without `--codex` or `--mint-token`, this CLI creates no credential and no
|
|
52
|
+
database row.
|
|
53
|
+
|
|
54
|
+
`BNL_MEMORY_MCP_TOKEN` and `CAVEAU_MCP_TOKEN` are earlier names for that token. If the Codex env
|
|
55
|
+
file still has them, the installer leaves those lines exactly as they are, because other tools
|
|
56
|
+
on the machine may still read them, and prints a one-line notice naming them (never their
|
|
57
|
+
values). Remove them by hand once nothing uses them. The Codex TOML
|
|
58
|
+
writer owns one explicitly marked block; it preserves unrelated servers and settings, updates
|
|
59
|
+
its own block idempotently, and refuses an unowned table whose ownership is ambiguous.
|
|
60
|
+
|
|
61
|
+
Two more things a minted token gets, that a hand-pasted one never did: an expiry — 90 days,
|
|
62
|
+
printed to you (never the value) after a real run — and the file is locked to your own account
|
|
63
|
+
only (`chmod 0600` on Linux/macOS, an owner-only ACL on Windows) immediately after it is
|
|
64
|
+
written. If that protection can't be verified, the file is deleted rather than left in an
|
|
65
|
+
unknown state.
|
|
39
66
|
|
|
40
|
-
|
|
67
|
+
## CI
|
|
68
|
+
|
|
69
|
+
A CI runner has no browser and nobody there to sign in, so it needs a real credential. Pass
|
|
70
|
+
a ProofMEM key you already hold (a `cmem_` token) and the CLI skips sign-in entirely:
|
|
41
71
|
|
|
42
72
|
```bash
|
|
43
|
-
npx @bluenotelogic/harness init --token "$
|
|
73
|
+
npx @bluenotelogic/harness init --token "$PROOFMEM_TOKEN"
|
|
44
74
|
```
|
|
45
75
|
|
|
76
|
+
The CLI uses that key only for this run. It writes the same tokenless `.mcp.json` and stores
|
|
77
|
+
no credential, so an agent on the runner gets no key from it. If an agent there needs a key of
|
|
78
|
+
its own, add `--mint-token`: the CLI mints one and writes it to `~/.codex/.env` as
|
|
79
|
+
`PROOFMEM_TOKEN`, outside the repo.
|
|
80
|
+
|
|
81
|
+
`--device` (below) also works without a browser on the machine, but someone has to approve the
|
|
82
|
+
code on another device, so it suits headless machines and SSH sessions, not unattended CI.
|
|
83
|
+
|
|
46
84
|
## Headless machines
|
|
47
85
|
|
|
48
86
|
```bash
|
|
@@ -51,29 +89,133 @@ npx @bluenotelogic/harness init --device
|
|
|
51
89
|
|
|
52
90
|
Prints a short code and a URL to open on any other device. Standard RFC 8628 device flow.
|
|
53
91
|
|
|
92
|
+
## Google Antigravity
|
|
93
|
+
|
|
94
|
+
Google Antigravity signs in to ProofMEM with OAuth, and its Caveau Harness hooks are available now.
|
|
95
|
+
The hooks need a Caveau Harness v2 checkout, which is not publicly distributed: our team sets it up
|
|
96
|
+
with you in a guided Caveau Harness session (contact ProofMEM to book one). With the checkout in
|
|
97
|
+
place, install the ProofMEM plugin and its Caveau Harness v2 lifecycle adapter with:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
npx @bluenotelogic/harness init --antigravity --harness-home /path/to/caveau-harness-v2
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
On Windows, `--harness-home C:\\path\\to\\caveau-harness-v2` is accepted. If `HARNESS_HOME`
|
|
104
|
+
already names a v2 checkout, the flag may be omitted.
|
|
105
|
+
|
|
106
|
+
The installed `mcp_config.json` points directly at `https://proofmem.com/mcp` and carries no
|
|
107
|
+
token, header, environment variable, or stdio bridge. Antigravity completes native OAuth/DCR and
|
|
108
|
+
keeps that session in its own protected store. Lifecycle hook processes cannot read that OAuth
|
|
109
|
+
store, so the installer mints a second bounded token solely for hooks and locks it to the current
|
|
110
|
+
OS account under `~/.gemini/config/proofmem/hook-token`. Its value is not copied into the plugin,
|
|
111
|
+
repo, logs, or Codex environment.
|
|
112
|
+
|
|
113
|
+
On Windows the file's access list is replaced with a single entry for the current user (by SID,
|
|
114
|
+
so it holds in every Windows language) and then verified; sandbox groups such as
|
|
115
|
+
`CodexSandboxUsers` are removed rather than tolerated. If that cannot be proved, the file is
|
|
116
|
+
deleted and the install fails. With `--codex` as well, Codex and the hooks get separate tokens.
|
|
117
|
+
|
|
118
|
+
The hook token is never handed to the guard, checkpoint, lint, or verify scripts, so a project's
|
|
119
|
+
own build or test scripts do not inherit it from Antigravity. Nor do they get any environment
|
|
120
|
+
variable whose name, split at every character that is not a letter or digit, has a part that is
|
|
121
|
+
`KEY`, `PAT`, `PWD`, `PASS` or `AUTH`, or that ends in `TOKEN`, `SECRET`, `PASSWORD`, `PASSWD`,
|
|
122
|
+
`PASSPHRASE`, `CREDENTIAL`, `BEARER`, `APIKEY` or `JWT` (case-insensitive, plural or a trailing
|
|
123
|
+
`KEY` allowed): `GITHUB_TOKEN`, `AWS_SECRET_ACCESS_KEY`, `OPENAI_API_KEY`, `NPM_CONFIG__AUTH`,
|
|
124
|
+
`GITEA_PAT`, `DB_PWD`, `SSH_AUTH_SOCK`, `CI_JOB_JWT`, and so on. `PATH`, `HOME`, `PWD` and the
|
|
125
|
+
other process basics are always kept, and an `AUTH` part does not count in the Harness's own
|
|
126
|
+
`HARNESS_*` names, where it is a mode switch (`HARNESS_MEMORY_AUTH`).
|
|
127
|
+
They also lose the editor's credential bridges, variables that hold no secret but let a child
|
|
128
|
+
process use your Git or SSH credentials anyway: `GIT_ASKPASS`, `SSH_ASKPASS`,
|
|
129
|
+
`SSH_ASKPASS_REQUIRE`, `SSH_AUTH_SOCK`, `GIT_SSH_COMMAND`, `GIT_SSH`, every `VSCODE_GIT_*` (the
|
|
130
|
+
editor's askpass helper and its IPC handle, which can answer with your Git account's token), and
|
|
131
|
+
`GIT_CONFIG_PARAMETERS`, `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_<n>` and `GIT_CONFIG_VALUE_<n>`
|
|
132
|
+
(which can inject a credential helper). The memory hooks keep them for SessionStart's Git refresh.
|
|
133
|
+
So if a trusted project's opt-in verify build needs your SSH agent or Git sign-in, run that build
|
|
134
|
+
yourself. A credential under any other name, a credential helper your own Git config already
|
|
135
|
+
names (such as Git Credential Manager), and credential files such as `~/.npmrc` or
|
|
136
|
+
`~/.aws/credentials` are not hidden, which is one more reason the verify gate below is opt-in.
|
|
137
|
+
The memory hooks that do receive the hook token are pinned to ProofMEM
|
|
138
|
+
(`HARNESS_MEMORY_PROVIDER=caveaumem`, `HARNESS_COORDINATION_STORE=caveaumem`), so an exported
|
|
139
|
+
value cannot send that session's memory to another store.
|
|
140
|
+
|
|
141
|
+
The plugin adapts SessionStart bootstrap, focused per-prompt context, destructive-command checks,
|
|
142
|
+
edit checkpoints/lint, and memory capture. Restart Antigravity after install, enable the ProofMEM
|
|
143
|
+
plugin, and authenticate its MCP server when prompted.
|
|
144
|
+
|
|
145
|
+
**Prerequisites for the hooks: bash and jq.** On Windows that is Git for Windows' bash, plus jq
|
|
146
|
+
installed so that it runs from that bash (Git for Windows does not include jq); WSL bash is
|
|
147
|
+
deliberately not used. On Linux and macOS, bash and jq on the `PATH`. Without bash no hook runs,
|
|
148
|
+
and without jq the memory hooks cannot work; either way they fail open rather than block you.
|
|
149
|
+
|
|
150
|
+
The Stop verification gate is **off by default**. When on, it runs the open project's own
|
|
151
|
+
`npm run build`, `npm test` or `npm run lint` each time the agent stops, outside Antigravity's
|
|
152
|
+
command approval, so opening an untrusted repository would run its code. Turn it on with
|
|
153
|
+
`--verify-gate` only for projects you trust. An exported `HARNESS_VERIFY_GATE=0` or `=1` overrides
|
|
154
|
+
that choice; an empty value counts as unset.
|
|
155
|
+
|
|
156
|
+
The hook token is bounded (90 days). `doctor --antigravity` warns 14 days before it expires, and
|
|
157
|
+
SessionStart says so too. Renew it by running the same `init --antigravity` command again; do not
|
|
158
|
+
export a token in the environment instead. The MCP server's `enabledTools` list hides skill/tool
|
|
159
|
+
authoring and vault tools from the agent. It is a convenience, not a security boundary: the
|
|
160
|
+
server enforces each token's scopes, and no ProofMEM token can read the vault.
|
|
161
|
+
|
|
54
162
|
## Options
|
|
55
163
|
|
|
56
164
|
| Flag | Effect |
|
|
57
165
|
|---|---|
|
|
58
|
-
| `--dry-run` | Show every file that would change
|
|
59
|
-
| `--url <base>` | Point at a self-hosted deployment (default `https://
|
|
166
|
+
| `--dry-run` | Show every file that would change and write nothing. Mints no long-lived token, but signing in still creates one short-lived (1 h) session key on the server; the sign-in's refresh grant is revoked at once (see below) |
|
|
167
|
+
| `--url <base>` | Point at a self-hosted deployment (default `https://proofmem.com`) |
|
|
60
168
|
| `--dir <path>` | Repo to configure (default: current directory) |
|
|
61
169
|
| `--device` | Device-code login for headless boxes and SSH sessions |
|
|
62
170
|
| `--token <token>` | Use an existing token instead of logging in |
|
|
63
171
|
| `--mint-token` | Also mint a token for hosts that cannot do OAuth |
|
|
64
172
|
| `--codex` | Configure Codex too (implies `--mint-token`) |
|
|
173
|
+
| `--antigravity` | Install the ProofMEM Antigravity plugin (implies one hook-token mint) |
|
|
174
|
+
| `--antigravity-home <dir>` | Override Antigravity config home (default `~/.gemini/config`) |
|
|
175
|
+
| `--verify-gate` | Antigravity: run the open project's build/test/lint when the agent stops (off by default) |
|
|
65
176
|
| `--harness-home <dir>` | Materialize hosted model routing into `<dir>/state/routing/` |
|
|
66
177
|
| `--server-name <name>` | Override the MCP server key written into `.mcp.json` |
|
|
67
178
|
| `--no-browser` | Print the login URL instead of opening a browser |
|
|
68
179
|
|
|
180
|
+
Validate the result without contacting the service or printing secrets:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
npx @bluenotelogic/harness doctor --dir /path/to/repo
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
For the Antigravity installation only:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
npx @bluenotelogic/harness doctor --antigravity --dir /path/to/repo
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
The doctor requires the canonical token reference, one installer-managed Codex block, a
|
|
193
|
+
tokenless repo MCP config, and a `HARNESS_HOME` whose `.harness-generation` marker is exactly
|
|
194
|
+
`caveau-harness-v2`. Routing will not be written into an archived or unidentified harness.
|
|
195
|
+
|
|
69
196
|
Run `--dry-run` first if you like seeing before you commit. It prints the full contents of
|
|
70
|
-
every file it would touch
|
|
197
|
+
every file it would touch — except a credential file (`~/.codex/.env`), which is shown as
|
|
198
|
+
`create`/`update` with its content redacted, whether or not `--dry-run` actually minted
|
|
199
|
+
anything. `--dry-run` writes nothing and never mints a long-lived token: no Codex or hook key is
|
|
200
|
+
created. Signing in still creates one short-lived (1 h) session key on the server, because that
|
|
201
|
+
key is how the CLI reads your configuration; with `--token`, not even that.
|
|
202
|
+
|
|
203
|
+
Signing in also returns a refresh token, which the CLI never uses. Through proofmem.com it stands
|
|
204
|
+
for a sign-in record the gateway keeps (your Blue Note ID refresh token, encrypted, for up to 35
|
|
205
|
+
days). So once the CLI has your configuration, on every run including `--dry-run`, it revokes that
|
|
206
|
+
refresh token at the server's revocation endpoint, and the record is gone. If the server does not
|
|
207
|
+
confirm, the CLI prints a one-line note, and the record lapses on its own when it expires.
|
|
208
|
+
|
|
209
|
+
Revoking: every ProofMEM key, including that session key and the 90-day Codex and hook keys, is
|
|
210
|
+
listed in the ProofMEM console at `https://proofmem.com/app/keys.php`, and revoking it there cuts
|
|
211
|
+
it off. Signing out of Blue Note ID does not: a key already handed to a client stays valid until
|
|
212
|
+
it expires.
|
|
71
213
|
|
|
72
214
|
## It will not clobber your config
|
|
73
215
|
|
|
74
|
-
Every write reads what is already on disk and replaces **only** the keys
|
|
75
|
-
unrelated MCP server in your `.mcp.json` survives untouched
|
|
76
|
-
|
|
216
|
+
Every write reads what is already on disk and replaces **only** the keys or marked blocks it
|
|
217
|
+
owns. An unrelated MCP server in your `.mcp.json` or Codex TOML survives untouched, and so do
|
|
218
|
+
unrelated top-level keys.
|
|
77
219
|
|
|
78
220
|
If a file is not valid JSON, the CLI reports it and **leaves it exactly as it found it** —
|
|
79
221
|
"it looked broken" is precisely when someone's half-finished hand edit is sitting in it.
|
|
@@ -97,16 +239,29 @@ not. `test/writers.test.js` pins that behaviour so it cannot happen again.
|
|
|
97
239
|
.mcp.json, routing YAML, optional Codex config
|
|
98
240
|
```
|
|
99
241
|
|
|
242
|
+
On proofmem.com the OAuth endpoints belong to the ProofMEM gateway, which runs the
|
|
243
|
+
`oidc_exchange.php` step itself and returns the short-lived ProofMEM key (`cmem_…`) as the
|
|
244
|
+
access token. The CLI recognises that key and goes straight to `harness_bootstrap.php`; it only
|
|
245
|
+
calls `oidc_exchange.php` itself when the sign-in returned a Blue Note ID token, as a server
|
|
246
|
+
without the gateway does.
|
|
247
|
+
|
|
100
248
|
Identity and entitlement are separate on purpose. A Blue Note Account authenticates a person;
|
|
101
249
|
it does not by itself grant memory access. If you sign in successfully but hold no
|
|
102
|
-
subscription
|
|
103
|
-
|
|
250
|
+
subscription, the exchange says exactly that, rather than giving a login error that sends you
|
|
251
|
+
looking in the wrong place. Through the gateway that refusal, and an identity the server cannot
|
|
252
|
+
use (no verified email on the Blue Note Account), both end the sign-in with `access_denied`, so
|
|
253
|
+
the CLI names both causes: start a subscription at `https://proofmem.com/pricing.php`, or verify
|
|
254
|
+
the account's email at `https://id.bluenotelogic.com`, then run the command again. Signing in
|
|
255
|
+
again without either change does not help.
|
|
104
256
|
|
|
105
257
|
## Requirements
|
|
106
258
|
|
|
107
259
|
Node 20 or newer. **No runtime dependencies** — PKCE, the loopback listener and the HTTP
|
|
108
260
|
client are all Node built-ins, so `npx` is fast and there is no dependency tree to audit.
|
|
109
261
|
|
|
262
|
+
The Antigravity hooks also need bash and jq: Git for Windows' bash plus jq on
|
|
263
|
+
Windows, bash plus jq elsewhere. See [Google Antigravity](#google-antigravity).
|
|
264
|
+
|
|
110
265
|
## Development
|
|
111
266
|
|
|
112
267
|
```bash
|
|
@@ -119,5 +274,5 @@ npm run lint # tsc --noEmit
|
|
|
119
274
|
|
|
120
275
|
Apache-2.0 — © 2026 Blue Note Logic Inc. See [LICENSE](LICENSE).
|
|
121
276
|
|
|
122
|
-
This CLI is free and open source. It configures a machine to talk to
|
|
123
|
-
|
|
277
|
+
This CLI is free and open source. It configures a machine to talk to ProofMEM;
|
|
278
|
+
a ProofMEM subscription is a separate commercial product.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# ProofMEM for Google Antigravity
|
|
2
|
+
|
|
3
|
+
Installed and updated by `npx @bluenotelogic/harness init --antigravity`.
|
|
4
|
+
|
|
5
|
+
The MCP server uses Antigravity's native Streamable HTTP OAuth/DCR support. Its
|
|
6
|
+
`mcp_config.json` deliberately contains no bearer header, environment variable, token, or
|
|
7
|
+
stdio bridge. Antigravity owns and refreshes that OAuth session in its protected store.
|
|
8
|
+
|
|
9
|
+
Lifecycle hooks run through Caveau Harness v2. Because Antigravity does not expose its OAuth
|
|
10
|
+
credential to hook subprocesses, the installer mints a separate bounded ProofMEM token for
|
|
11
|
+
those hooks and protects it in the user's Antigravity config directory. `harness-home.json`
|
|
12
|
+
contains paths and the ProofMEM API URL only; it never contains the credential value.
|
|
13
|
+
|
|
14
|
+
If the MCP server first appears as `Unauthorized`, open Antigravity's Customizations / MCP
|
|
15
|
+
Servers panel and authenticate the ProofMEM server. Do not add headers or tokens to the plugin.
|
|
16
|
+
|
|
17
|
+
The hooks need bash and jq. On Windows that means Git for Windows' bash, plus jq installed so
|
|
18
|
+
that it runs from that bash (Git for Windows does not include jq); WSL bash is not used.
|
|
19
|
+
Elsewhere, any bash with jq on its PATH.
|
|
20
|
+
|
|
21
|
+
Only the memory hooks receive the hook credential. When they do, they are also pinned to
|
|
22
|
+
ProofMEM (`HARNESS_MEMORY_PROVIDER` and `HARNESS_COORDINATION_STORE` = `caveaumem`), so an
|
|
23
|
+
exported value cannot send that session's memory to another store. The command guard, edit
|
|
24
|
+
checkpoint, lint and verify scripts run without the credential, and without any environment
|
|
25
|
+
variable whose name has a part (split at every non-letter, non-digit) that is `KEY`, `PAT`, `PWD`,
|
|
26
|
+
`PASS` or `AUTH`, or that ends in `TOKEN`, `SECRET`, `PASSWORD`, `PASSWD`, `PASSPHRASE`,
|
|
27
|
+
`CREDENTIAL`, `BEARER`, `APIKEY` or `JWT`: `GITHUB_TOKEN`, `AWS_SECRET_ACCESS_KEY`,
|
|
28
|
+
`NPM_CONFIG__AUTH`, `GITEA_PAT`, `SSH_AUTH_SOCK`, and so on. `PATH`, `HOME`, `PWD` and the other
|
|
29
|
+
process basics are always kept, and an `AUTH` part does not count in the Harness's own `HARNESS_*`
|
|
30
|
+
names, where it is a mode switch (`HARNESS_MEMORY_AUTH`).
|
|
31
|
+
|
|
32
|
+
Those four scripts also run without the editor's credential bridges, which hold no secret but let
|
|
33
|
+
a child process use your Git or SSH credentials anyway: `GIT_ASKPASS`, `SSH_ASKPASS`,
|
|
34
|
+
`SSH_ASKPASS_REQUIRE`, `SSH_AUTH_SOCK`, `GIT_SSH_COMMAND`, `GIT_SSH`, every `VSCODE_GIT_*` (the
|
|
35
|
+
askpass helper and its IPC handle back into the editor), and `GIT_CONFIG_PARAMETERS`,
|
|
36
|
+
`GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_<n>` and `GIT_CONFIG_VALUE_<n>` (which can inject a credential
|
|
37
|
+
helper). The memory hooks keep them for SessionStart's Git refresh. If a trusted project's opt-in
|
|
38
|
+
verify build needs your SSH agent or Git sign-in, run that build yourself. A credential under any
|
|
39
|
+
other name, a credential helper your own Git config already names (such as Git Credential
|
|
40
|
+
Manager), and files such as `~/.npmrc` or `~/.aws/credentials` are not hidden from them.
|
|
41
|
+
|
|
42
|
+
The hook credential lasts 90 days; SessionStart and `doctor --antigravity` warn 14 days ahead.
|
|
43
|
+
Renew it by re-running the same `npx @bluenotelogic/harness init --antigravity ...` command,
|
|
44
|
+
never by exporting a token. To cut it off sooner, revoke it in the ProofMEM console at
|
|
45
|
+
`https://proofmem.com/app/keys.php`. Signing out of Blue Note ID does not cancel a key a client
|
|
46
|
+
already holds: it stays valid until it expires or is revoked there.
|
|
47
|
+
|
|
48
|
+
The installer's own sign-in leaves only the keys it creates on the server (the hook key, and a
|
|
49
|
+
1-hour session key it reads your configuration with). Once it has your configuration it revokes
|
|
50
|
+
that sign-in's refresh grant, which through proofmem.com is an encrypted Blue Note ID refresh
|
|
51
|
+
token the gateway would otherwise keep for up to 35 days; if the server does not confirm, the
|
|
52
|
+
installer says so and the record lapses on its own. Antigravity's MCP sign-in is different: the
|
|
53
|
+
gateway keeps its refresh token, encrypted, so that Antigravity can stay signed in without asking
|
|
54
|
+
you again.
|
|
55
|
+
|
|
56
|
+
The Stop verification gate is off unless you installed with `--verify-gate`. When on, it runs the
|
|
57
|
+
open project's own build/test/lint whenever the agent stops, outside Antigravity's command
|
|
58
|
+
approval, so enable it only for projects you trust. An exported `HARNESS_VERIFY_GATE=0` or `=1`
|
|
59
|
+
overrides the install choice; an empty value counts as unset.
|
|
60
|
+
|
|
61
|
+
`enabledTools` in `mcp_config.json` controls which tools Antigravity offers. It is a convenience,
|
|
62
|
+
not a security boundary: ProofMEM enforces each token's scopes server-side. The hooks fail open:
|
|
63
|
+
a guard or memory error never blocks your work, so treat their warnings as diagnostics.
|
|
64
|
+
|
|
65
|
+
Run a read-only installation check with:
|
|
66
|
+
|
|
67
|
+
```text
|
|
68
|
+
npx @bluenotelogic/harness doctor --antigravity --harness-home /path/to/caveau-harness-v2
|
|
69
|
+
```
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"proofmem-session-bootstrap": {
|
|
3
|
+
"enabled": true,
|
|
4
|
+
"SessionStart": [
|
|
5
|
+
{
|
|
6
|
+
"type": "command",
|
|
7
|
+
"command": "node ./scripts/antigravity-hook.mjs session-start",
|
|
8
|
+
"timeout": 40
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"proofmem-focused-memory": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"PreInvocation": [
|
|
15
|
+
{
|
|
16
|
+
"type": "command",
|
|
17
|
+
"command": "node ./scripts/antigravity-hook.mjs prompt-context",
|
|
18
|
+
"timeout": 30
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
"proofmem-command-guard": {
|
|
23
|
+
"enabled": true,
|
|
24
|
+
"PreToolUse": [
|
|
25
|
+
{
|
|
26
|
+
"matcher": "run_command",
|
|
27
|
+
"hooks": [
|
|
28
|
+
{
|
|
29
|
+
"type": "command",
|
|
30
|
+
"command": "node ./scripts/antigravity-hook.mjs pre-tool",
|
|
31
|
+
"timeout": 15
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
"proofmem-edit-checkpoint": {
|
|
38
|
+
"enabled": true,
|
|
39
|
+
"PreToolUse": [
|
|
40
|
+
{
|
|
41
|
+
"matcher": "write_file|edit_file|write_to_file|replace_file_content|multi_replace_file_content",
|
|
42
|
+
"hooks": [
|
|
43
|
+
{
|
|
44
|
+
"type": "command",
|
|
45
|
+
"command": "node ./scripts/antigravity-hook.mjs pre-edit",
|
|
46
|
+
"timeout": 15
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
"proofmem-post-edit": {
|
|
53
|
+
"enabled": true,
|
|
54
|
+
"PostToolUse": [
|
|
55
|
+
{
|
|
56
|
+
"matcher": "write_file|edit_file|write_to_file|replace_file_content|multi_replace_file_content",
|
|
57
|
+
"hooks": [
|
|
58
|
+
{
|
|
59
|
+
"type": "command",
|
|
60
|
+
"command": "node ./scripts/antigravity-hook.mjs post-edit",
|
|
61
|
+
"timeout": 60
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"proofmem-stop-gate": {
|
|
68
|
+
"enabled": true,
|
|
69
|
+
"Stop": [
|
|
70
|
+
{
|
|
71
|
+
"type": "command",
|
|
72
|
+
"command": "node ./scripts/antigravity-hook.mjs stop",
|
|
73
|
+
"timeout": 220
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# ProofMEM and Caveau Harness
|
|
2
|
+
|
|
3
|
+
- ProofMEM is the durable memory home shared by Antigravity, Claude Code, and Codex. Do not create a second persistent memory system in local markdown files.
|
|
4
|
+
- The SessionStart hook runs `bootstrap`. Do not run it again in the same conversation; use `context` or `persistent_recall` for later retrieval.
|
|
5
|
+
- Use `proposal_create` and `feedback_file` for governed learning. Do not bypass review controls with direct rewrites unless the user explicitly authorizes the change.
|
|
6
|
+
- Use scratch memory only for short-lived coordination and episodic memory for session events.
|
|
7
|
+
- Never put raw credentials in prompts, notes, scratch records, episodic events, committed files, or logs.
|
|
8
|
+
- If the ProofMEM MCP server returns `Unauthorized`, preserve its tokenless `serverUrl` configuration and start Antigravity's native OAuth/DCR flow. Never repair authentication by adding a bearer header, token, environment variable, or stdio bridge to `mcp_config.json`.
|
|
9
|
+
- Treat Harness hook warnings as actionable diagnostics. A fail-open memory warning does not waive repository tests or safety rules.
|