a4fc26eed360357640501540f0059014ecab58ea
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a329acf23c |
fix(antigravity): resolve interpreter from console-script shebang
`uv tool install mempalace` / `pipx install` place the mempalace console scripts in an isolated environment whose interpreter is not the system python3. mempal_resolve_python previously resolved `command -v python3`, landing on a Python that cannot import mempalace: the `-m mempalace --version` probe failed and mining silently never fired (hit by a real user on PR #1633). Resolution now derives the interpreter from the mempalace-mcp / mempalace console-script shebang on PATH (the same script the MCP server launches) before falling back to python3. It is pure shebang parsing + stat — no Python subprocess at source time — so the hook performance budget is preserved. An env-style `#!/usr/bin/env python` shebang and a non-executable interpreter are both rejected and fall through. MEMPAL_PYTHON remains the explicit override. Adds 6 resolver regression tests, documents resolution + MEMPAL_PYTHON in the guide and hooks README (fixing the stale `command -v mempalace` note), and a CHANGELOG entry. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
df295bd743 |
fix(antigravity): atomic counter write, background --version probe, state-file GC
Addresses igorls' review on PR #1633 (antigravity branch only): - Atomic counter write: add mempal_write_counter_atomic (same-dir temp + mv -f rename) and use it in the save hook, replacing the truncate-then -write printf that the comment falsely called "atomic". Concurrent readers now always see a complete value. - Background the expensive probe: `mempalace --version` pays the full chromadb/onnx cold-start import (the mine subparser imports mempalace.miner before argparse handles --version), so running it in the foreground blew the <500ms save budget. Probe + mine + pending -marker cleanup now run in one detached subshell; the foreground returns immediately. This also retires the kill -0 watcher (the prior gemini fix) since cleanup is now sequential within the mine's own shell, removing the sibling-PID hazard entirely. - State-file GC: add mempal_state_ttl_days (default 30, env MEMPAL_STATE_TTL_DAYS) and mempal_gc_stale_state, a daily-throttled sweep (antigravity_last_sweep marker) that removes stale antigravity_save_count_*, antigravity_pending_*, and antigravity_woke_* artifacts. Called after the kill-switch check so a disabled hook touches nothing; specific name globs leave shared logs untouched. Tests: atomic-counter behavior + no-temp-leftover, single-subshell structure (no wait/kill -0/MINE_PID), backgrounded-probe timing (3s stub returns in <2s), async log polling for the missing-module path, GC sweep/throttle/TTL-validation, and GC gated by the kill switch. Also hardens the wake-missing test to pin MEMPAL_PYTHON so a shell -exported interpreter can't defeat the simulation. bash 3.2.57 safe, fail-open on every path, {}-only Stop output. Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
b06cf2452e |
fix(antigravity): address gemini-code-assist review on PR #1633
Five fixes for issues called out by the gemini-code-assist[bot] review.
Each gets a regression test that locks in the correction.
1. CRITICAL: marker-cleanup watcher used POSIX `wait` on a sibling pid
(save hook). bash `wait` only works on direct children of the
calling shell — the `( wait $MINE_PID ... ) &` subshell runs as a
sibling of MINE_PID, so wait fails immediately and the pending
marker is deleted within milliseconds, defeating the concurrency
guard. Replace with `while kill -0 $MINE_PID; do sleep 1; done`,
which queries pid existence regardless of parent-child relationship.
Test: test_save_hook_marker_watcher_uses_kill_polling.
2. Bare `mempalace` console-script invocation in the save hook fails
when the venv's bin/ is not on the hook's PATH (e.g. uv tool
install in some configurations, manually managed virtualenvs).
Switch to `"$MEMPAL_PYTHON_BIN" -m mempalace mine ...` so the
resolved interpreter runs the package directly via
mempalace/__main__.py. Tests:
test_save_hook_uses_python_module_invocation,
test_save_hook_missing_mempalace_python_module_does_not_crash.
3. Same issue in the wake hook's inner Python helper. Switch
`['mempalace', 'wake-up', ...]` to `[sys.executable, '-m',
'mempalace', 'wake-up', ...]` — sys.executable is the same
interpreter that resolved MEMPAL_PYTHON in lib/common.sh.
Test: test_wake_hook_uses_sys_executable_module_invocation.
4. The Python parser in lib/common.sh wrapped `json.load` in
`try/except` and silently fell back to `data = {}`. The script
then printed the `__MEMPAL_PARSE_OK__` sentinel even on parse
failure, so the bash sentinel-check on the caller side
(`[ "$_marker" != "__MEMPAL_PARSE_OK__" ]`) never triggered the
defense-in-depth `input parse failed` branch. Remove the
try/except so the exception propagates, Python exits non-zero,
and the sentinel is omitted on bad JSON. The traceback still
lands in antigravity_last_python_err.log for debugging.
Test: test_common_sh_parser_omits_sentinel_on_malformed_json.
5. `mempal_save_interval()` failed to strip leading zeros from
MEMPAL_SAVE_INTERVAL. Values like "08" or "09" then crashed the
modulo step `$((COUNT % INTERVAL))` because bash arithmetic
parses tokens starting with `0` as octal, and 8/9 are not valid
octal digits ("value too great for base"). Strip leading zeros
while preserving the literal "0" (which is then floored to 15).
Test: test_save_hook_handles_leading_zero_save_interval (4 cases).
Plus one cosmetic fix in install.sh: removed a no-op `(cd "$OLDPWD"
2>/dev/null || cd .) >/dev/null 2>&1` line in mempal_absolutize().
The subshell cd doesn't affect the parent shell, and the installer
never cd's in the main shell anyway, so $PWD is already correct.
Verification:
* 9 new regression tests, all 65 antigravity tests pass
* full repo: 2323 passed (was 2314), 3 skipped, 1 unrelated warning
* ruff check + ruff format --check both clean across 139 files
* bash -n clean on all four shell files
* clean reinstall to ~/.gemini/config/plugins/mempalace/ succeeds
* idempotent re-run produces zero file writes (cmp-gated)
* both hooks return {} exit 0 with synthetic camelCase stdin
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
bf156fb010 |
feat: add Antigravity IDE support (plugin, MCP, skill, hooks, docs, tests)
Adds first-class integration with Google's Antigravity IDE (https://antigravity.google/) as a third sibling to the existing Claude Code and Codex hook integrations. Strictly additive — no existing files in main are restructured. What ships ---------- * `.antigravity-plugin/` — verified-minimal plugin package: * `plugin.json` with `{"name": "mempalace"}` (no fabricated fields) * `mcp_config.json` registering the `mempalace-mcp` stdio server * `hooks.json.tmpl` templated with `__PLUGIN_DIR__` substitution * `skills/mempalace/SKILL.md` (real file — no symlinks) * `hooks/antigravity/`: * `lib/common.sh` — shared bash 3.2.57-compatible helpers with sentinel-guarded camelCase JSON parser, antigravity_*-namespaced state files, every existing kill switch, `MEMPAL_SAVE_INTERVAL >= 1` floor (no /0), and fail-open emitters * `mempal_save_hook_antigravity.sh` — Stop event handler: increments per-conversation counter, defers when fullyIdle=False or terminationReason=error, validates transcriptPath against `..` traversal, spawns `mempalace mine --mode convos` in a detached subprocess with a per-conversation pending marker, ALWAYS emits `{}` (never `{"decision":"continue"}` — that would force an infinite agent loop) * `mempal_wake_hook_antigravity.sh` — PreInvocation handler gated to invocationNum==1 with an atomic mkdir loop guard, runs `mempalace wake-up` with a 500ms hard timeout, emits verbatim output as `{"injectSteps":[{"ephemeralMessage":"..."}]}` or `{}` on any failure * `install.sh` — idempotent installer with cmp-gated copies, `__PLUGIN_DIR__` substitution, relative path absolutization, `--dry-run`, and basename-guarded `--uninstall` (refuses to wipe a directory whose basename isn't `mempalace`) * `INVESTIGATION.md` — verbatim quotes + URLs + dates from the five official Antigravity doc pages, recording every surface shipped and every surface deliberately omitted (PreCompact equivalent, slash-commands, rules/, plugin permissions field — the latter is third-party fabrication) * `STDIN_SHAPE.md` — exact stdin/stdout contract per event with worked examples * `README.md` — local hook docs + troubleshooting * `examples/antigravity/{hooks.json,mcp_config.json,README.md}` — standalone configs for users who don't want the full installer * `website/guide/antigravity.md` + sidebar entry — VitePress guide * Updates to `README.md`, `CHANGELOG.md` (Unreleased), `hooks/README.md` Tests (56 new, all passing) --------------------------- * `tests/test_antigravity_plugin_manifest.py` (11 tests) — schema contract on the in-repo `.antigravity-plugin/` directory, including guards against re-introducing the fabricated `permissions` field and against any symlink leak. * `tests/test_antigravity_hooks_shell.py` (31 tests) — invokes the bash hooks via subprocess with synthetic camelCase stdin, asserts `{}` on every failure path, kill-switch coverage (env vars + config.json + palace nuke), divide-by-zero floor, transcript traversal rejection, namespacing, wing inference, and the hard refusal to ever emit `decision=continue` from the Stop hook. * `tests/test_antigravity_hooks_install.py` (14 tests) — `--dry-run` side-effect-free, real install layout, executable bits preserved, byte-identical idempotent re-runs (md5 + filecmp), basename-match uninstall safety, refusal when plugin.json is missing or names a different plugin, relative path absolutization. Skipped on Windows. Verification ------------ * `uv run pytest tests/ --ignore=tests/benchmarks -v` → 2314 passed, 3 skipped (Windows), 1 unrelated warning * `uv run ruff check .` → all checks passed * `uv run ruff format --check .` → 139 files already formatted * `bash -n` clean on common.sh, both hook scripts, install.sh * Local install at `~/.gemini/config/plugins/mempalace/` verified end- to-end: layout correct, paths absolutized in hooks.json, both hooks fire with realistic camelCase JSON in <1s, wing inference picks `wing_mempalace` from workspacePaths[0], state files all `antigravity_*`-namespaced, second `install.sh` run produces byte-identical output (md5 snapshots match), uninstall removes only the mempalace plugin and leaves all 6 sibling Google plugins untouched. Constraints honoured -------------------- bash 3.2.57 (no mapfile / readarray / declare -A / `${var^^}`), verbatim guarantee on all wake injections, hooks <500ms / startup injection <100ms target (kill-switch path returns in <1.5s in CI), zero new runtime dependencies, no telemetry, no external API, strictly additive (existing Claude/Codex hooks unchanged). Refs: hooks/antigravity/INVESTIGATION.md for the full audit. |