Skip to content

fix(hooks): portable mtime in macOS hook throttles; doc cleanup#1811

Merged
igorls merged 2 commits into
developfrom
fix/3.4.1-review-followups
Jun 15, 2026
Merged

fix(hooks): portable mtime in macOS hook throttles; doc cleanup#1811
igorls merged 2 commits into
developfrom
fix/3.4.1-review-followups

Conversation

@igorls

@igorls igorls commented Jun 14, 2026

Copy link
Copy Markdown
Member

Addresses the bot review feedback raised on the 3.4.1 release promotion (#1810). All items verified against the code, not applied blindly.

Bug fix — date -r breaks on macOS (Gemini, 3 hits)

date -r FILE is GNU coreutils only. On BSD/macOS, date -r interprets its argument as epoch seconds, not a file path, so it errors on the path string. With 2>/dev/null in an && chain, the staleness/throttle checks silently evaluate false:

Fixed with a portable os.path.getmtime one-liner via the already-resolved $MEMPAL_PYTHON_BIN. This is in the headline Cursor/Antigravity hooks shipping in 3.4.1, and restores the "bash 3.2.57 / macOS default" compatibility the changelog claims.

Docs (Copilot + Gemini)

  • Tool count → 33. Was stale at 19/29/31 in 21 places across plugin manifests, READMEs, and website docs. The authoritative count (TOOLS dict + website/reference/mcp-tools.md ### headings, both test-enforced) is 33. Updated all to agree.
  • CHANGELOG broken link — Cursor skill is at skills/mempalace/SKILL.md, not .cursor-plugin/skills/... (that dir has no skills/).
  • SKILL.md relative link../../../website/... resolved above the repo root from skills/mempalace/; corrected to ../../.
  • Cursor README mcp.json example — added the mcpServers wrapper that the real shipped mcp.json uses, so copy-paste yields a valid Cursor config.

Verified NOT a bug — left unchanged

Gemini's HIGH on mcp_server.py os.dup2(fd 1) is deliberate and documented (#225 keeps the JSON-RPC channel off fd 1; the dup captures C-level onnxruntime/chromadb banners). Changing it risks regressing #225.

Note on the drift treadmill

The README tool-count test (test_readme_claims.py) uses (\d+)\s+tools, which misses the "N MCP tools" phrasing (the "MCP" between number and "tools"), so these counts can drift unnoticed. Worth tightening the guard in a follow-up; out of scope here.

Validation

  • bash -n clean on all 3 hook scripts
  • ruff check + ruff format --check — clean
  • Full suite: 2853 passed, 5 skipped

Merging this into develop flows it into the #1810 release promotion.

Address review feedback surfaced on the 3.4.1 release promotion (#1810).

Bug fix — `date -r FILE` is GNU-only. On BSD/macOS `date -r` expects
epoch seconds, not a path, so the staleness/throttle checks in the new
Cursor and Antigravity hooks silently failed on macOS: the state GC
swept on every fire and the pending-save guard was skipped. Replace
with a portable `os.path.getmtime` one-liner via the already-resolved
$MEMPAL_PYTHON_BIN (cursor/lib, antigravity/lib, antigravity save hook).
This restores the "bash 3.2.57 / macOS default" compatibility the
Antigravity changelog claims.

Docs:
- Correct the MCP tool count to 33 (was 19/29/31 in 21 places across
  plugin manifests, READMEs, and website docs — all drifted from the
  TOOLS dict / mcp-tools.md reference, which both have 33).
- Fix broken CHANGELOG link to the Cursor skill (skills/, not
  .cursor-plugin/skills/).
- Fix one-too-many `../` in skills/mempalace/SKILL.md's cursor-hooks
  link (resolved above the repo root).
- Add the required `mcpServers` wrapper to the mcp.json example in
  .cursor-plugin/README.md so copy-paste yields a valid Cursor config.

Left intentionally unchanged: the os.dup2 fd-1 redirect in
mcp_server.py is deliberate (#225 keeps JSON-RPC off fd 1).
@igorls igorls requested a review from milla-jovovich as a code owner June 14, 2026 22:54
Copilot AI review requested due to automatic review settings June 14, 2026 22:54

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request updates various documentation, plugin manifests, and metadata files to reflect the increase in the number of MCP tools to 33, and updates the Cursor plugin's MCP configuration structure. It also replaces the platform-dependent date -r command with a portable Python inline script to retrieve file modification times in the hook scripts. However, the reviewer identified a critical issue in the bash scripts where sys.argv[1] is used inside double quotes; the shell expands $1 as a positional parameter, leading to Python syntax errors. The reviewer provided suggestions to escape the dollar sign as \$1 to prevent this expansion.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread hooks/antigravity/lib/common.sh Outdated
if [ -f "$marker" ]; then
local mtime now
if mtime=$(date -r "$marker" '+%s' 2>/dev/null) \
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[1])))" "$marker" 2>/dev/null) \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

In bash, double quotes allow parameter expansion. The expression sys.argv[1] contains $1, which is expanded by the shell to the first positional parameter of the current context (which is empty inside mempal_gc_stale_state). This results in a Python syntax error (sys.argv[]) and causes the check to silently fail. Escape the $ as \$1 to pass it literally to Python.

Suggested change
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[1])))" "$marker" 2>/dev/null) \
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[\$1])))" "$marker" 2>/dev/null) \

# mtime in epoch seconds (date -r); if stale (> 1 hour), reclaim.
if mtime=$(date -r "$PENDING_FILE" '+%s' 2>/dev/null) \
# mtime in epoch seconds (portable; BSD/macOS `date -r` takes epoch, not a path).
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[1])))" "$PENDING_FILE" 2>/dev/null) \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

In bash, double quotes allow parameter expansion. The expression sys.argv[1] contains $1, which is expanded by the shell to the first positional parameter of the script. This results in a Python syntax error or incorrect behavior. Escape the $ as \$1 to pass it literally to Python.

Suggested change
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[1])))" "$PENDING_FILE" 2>/dev/null) \
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[\$1])))" "$PENDING_FILE" 2>/dev/null) \

Comment thread hooks/cursor/lib/common.sh Outdated
if [ -f "$marker" ]; then
local mtime now
if mtime=$(date -r "$marker" '+%s' 2>/dev/null) \
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[1])))" "$marker" 2>/dev/null) \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

In bash, double quotes allow parameter expansion. The expression sys.argv[1] contains $1, which is expanded by the shell to the first positional parameter of the current context (which is empty inside mempal_gc_stale_state). This results in a Python syntax error (sys.argv[]) and causes the check to silently fail. Escape the $ as \$1 to pass it literally to Python.

Suggested change
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[1])))" "$marker" 2>/dev/null) \
if mtime=$("$MEMPAL_PYTHON_BIN" -c "import os, sys; print(int(os.path.getmtime(sys.argv[\$1])))" "$marker" 2>/dev/null) \

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes macOS/BSD compatibility in the Cursor and Antigravity hook throttle/guard logic by replacing GNU-specific date -r FILE usage with a portable mtime lookup via Python, and then normalizes documentation/tooling claims across the repo to consistently reflect the current MCP tool count.

Changes:

  • Replace date -r <file> '+%s' with python -c "os.path.getmtime(...)" in hook staleness/throttle checks for macOS portability.
  • Update docs, plugin manifests, and READMEs to consistently claim 33 MCP tools (matching mempalace/mcp_server.py’s TOOLS dict).
  • Fix broken/incorrect relative links (notably the Cursor skill link in CHANGELOG.md and a relative website link in skills/mempalace/SKILL.md).

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated no comments.

Show a summary per file
File Description
website/reference/modules.md Updates MCP server tool-count claim to 33 in module overview text.
website/reference/mcp-tools.md Updates top-level statement to “33 MCP tools”.
website/guide/openclaw.md Updates OpenClaw integration doc to reflect 33 tools.
website/guide/mcp-integration.md Updates MCP integration guide references from 29 → 33 tools.
website/guide/claude-code.md Updates Claude Code guide bullet to 33 tools.
skills/mempalace/SKILL.md Updates Cursor-specific tool-count claim and fixes relative link to website guide.
README.md Updates project README MCP tool-count claim to 33.
mempalace/README.md Updates package README module table entry to 33 tools.
hooks/cursor/lib/common.sh Uses portable Python getmtime() for daily GC throttle marker instead of date -r.
hooks/antigravity/mempal_save_hook_antigravity.sh Uses portable Python getmtime() for pending-save marker staleness guard.
hooks/antigravity/lib/common.sh Uses portable Python getmtime() for daily GC throttle marker instead of date -r.
CHANGELOG.md Fixes Cursor skill link target to skills/mempalace/SKILL.md.
.cursor-plugin/README.md Updates tool count claims and corrects the mcp.json example shape (mcpServers wrapper).
.cursor-plugin/plugin.json Updates description tool-count claim to 33.
.cursor-plugin/marketplace.json Updates marketplace description tool-count claim to 33.
.codex-plugin/README.md Updates tool-count claim to 33.
.codex-plugin/plugin.json Updates description fields to claim 33 tools.
.claude-plugin/README.md Updates tool-count claim to 33.
.claude-plugin/plugin.json Updates description tool-count claim to 33.
.claude-plugin/marketplace.json Updates marketplace description tool-count claim to 33.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

The snippet has no shell interpolation — the path arrives via argv, not
string interpolation — so single quotes are correct and make it
unambiguous that nothing is shell-expanded. Behavior is identical:
`sys.argv[1]` contains no `$`, so it was never expanded (verified
empirically). Matches the single-quoted `python -c` blocks already in
hooks/cursor/lib/common.sh. No functional change.
@igorls igorls merged commit db6e4f0 into develop Jun 15, 2026
9 checks passed
@igorls igorls deleted the fix/3.4.1-review-followups branch June 15, 2026 09:00
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.

2 participants