Repository navigation
chore(release): memhub v0.133.0 - #292
Conversation
Promoted from XTraceAI/agent-plugins-internal by scripts/promote_ship.py. Source-RevId: 5403278ed2328628872b897a75d6c4e97ce04946
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 25b27259b4
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| else: | ||
| spawn_cursor_flush(payload, event) |
There was a problem hiding this comment.
Honor the repository allowlist before Cursor capture
When repos.json excludes the current repository, Cursor events still reach this branch and launch cursor_flush.py; unlike the Claude/Codex entry path, neither this launcher nor cursor_flush.py checks repo_allow.session_enabled. Consequently a user selecting only trusted repositories can still have a Cursor session from an unlisted client repository uploaded, contradicting the new dormant-mode privacy guarantee. Check the payload's workspace/cwd against the allowlist before spawning any capture process.
Useful? React with 👍 / 👎.
| | `find-contributing-sessions` | Reads this machine's Claude Code, Codex and Cursor session history to find the sessions behind your pull requests. Its script runs `gh pr view` and `gh api` for each PR's files. It prints paths, branches and commit ids, never transcript content, and links only the sessions you approve. | | ||
| | `pr-babysit` | Polls a pull request's review bots and CI with `gh`. The agent fixes findings, commits, pushes and replies on review threads. Once the PR is clean, it saves a review record to the repository's brain. The `pr_babysit_trigger` hook asks the agent to start it after `gh pr create`. | | ||
| | `create-rule` | Drafts a team rule, replays it over this machine's sessions, and files it as `proposed` with `create_rule`. | | ||
| | `link-pr` | Links or unlinks a session and a pull request in MemHub. Asks the agent to run `gh pr view`. With `--find`, reads this machine's Claude Code, Codex and Cursor session history to find the sessions behind your pull requests: its script runs `gh pr view` and `gh api` for each PR's files, prints paths, branches and commit ids, never transcript content, and the skill links only the sessions you approve. | |
There was a problem hiding this comment.
Move the finder tests with the consolidated skill
The checked bump-guard.yml workflow runs scripts/check-plugin.sh, which executes every tests/*_test.py, but this consolidation deletes skills/find-contributing-sessions while tests/find_sessions_test.py and tests/documentation_test.py still open files at that old path. Running python3 tests/find_sessions_test.py now exits with FileNotFoundError, so the required plugin check fails on every run; update those suites and the remaining top-level README references to target skills/link-pr and --find.
Useful? React with 👍 / 👎.
| p = pending_path(sdir, session) | ||
| st = _load(p) |
There was a problem hiding this comment.
Serialize effect-state read-modify-write operations
When the async Stop handler overlaps the next UserPromptSubmit—the race this feature explicitly supports—on_turn_end and on_prompt both load and later replace the same effects state without a lock or merge. For example, the prompt can save last_prompt after this load and then have it overwritten here, causing the window to remain pending and be attributed to the following user message; the reverse interleaving can erase the pending window entirely. Serialize the whole state transition per session so effect verdicts and repair proposals are based on the correct reaction.
Useful? React with 👍 / 👎.
A promotion replaces plugins/memhub/ and install.sh only, so public's tests/ stayed at 0.124.0 while the plugin moved to 0.133.0. Twelve suites failed guard and probe-tests on #292, each on an intentional internal change. The twelve suites are internal's at 5403278e (the promoted commit), with memhub-staging rewritten to memhub. The README's installer paragraph now describes the installer this release ships (auto-update, fork agent, the repository allowlist with /memhub:repos, the companion prompt). No file under plugins/ changes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
🧠 Session context1 session behind this pull request. Team rules that fired while building this
Effort Sessions
|
test: bring public's suites up to the v0.133.0 plugin
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a0647de4c9
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if info[0] not in _BOOKS: | ||
| got = load_rules(info[0]) | ||
| if refresh: | ||
| got = first_fetch(info[0], got[0], got[2], got[3]) # (rules, fetched_at, sources) |
There was a problem hiding this comment.
Honor the allowlist before loading foreign-file rulebooks
When a shell call runs in listed repo A but accesses a path in unlisted repo B without changing directories (for example, cat ../client/secret or echo x > ../client/file), repo_of_call selects A and passes the top-level allowlist check, after which _file_book loads and may refresh B's book without checking repo_allow.enabled(info[1]). Rules from a repository that is supposed to be dormant can therefore inspect or block the cross-repo read/write; reject foreign books whose checkout is not enabled before loading or fetching them.
Useful? React with 👍 / 👎.
| band.active = await activeOf($, band) | ||
| return wanted && band.active.enabled |
There was a problem hiding this comment.
Stop proposal polling in dormant repositories
When wantedOf finds that the current repository is excluded, this result only disables the animal; setUp still immediately calls pollProposals and installs its five-minute timer. An authenticated /v1/team/rulebook/proposed request therefore continues from a repository advertised as dormant, and returned proposals can even take precedence over the inactive strip and expose Activate/Reject controls. Gate proposal polling and proposal-state rendering on band.active.enabled (while resolving sign-in locally if needed for the enable prompt).
Useful? React with 👍 / 👎.
| for sp in _subagent_files(host, path): | ||
| try: srecs, _ = R[host].to_canonical(sp) | ||
| except Exception: continue | ||
| _, sc, sr, src, _ = _walk(srecs, keep_users=False) | ||
| subs.append((sc, sr, src)); subagent_files += 1; subagent_calls += len(sc) |
There was a problem hiding this comment.
Filter inherited history before folding subagent calls
For Claude fork transcripts that repeat their parent's history, _walk accepts every record—including inherited/isSidechain records—and the resulting calls and results are merged back into the already-parsed parent. Each parent call is consequently replayed once per fork, inflating fired_n and ordering evidence and potentially pushing rules over proposal thresholds even though those calls occurred only once. Fold only the subagent's own trajectory, or explicitly discard inherited sidechain records before merging.
Useful? React with 👍 / 👎.
| try: | ||
| with open(path, encoding="utf-8") as f: | ||
| rec = json.load(f) | ||
| return isinstance(rec, dict) and age_s(rec.get("at")) < window |
There was a problem hiding this comment.
Consume expansion markers after one submitted prompt
If a normal user prompt arrives within five seconds after a slash-command expansion, this function still returns true because the marker is never consumed or matched to a particular submission. The ordinary prompt is then treated as another command body, so it neither arms prompt obligations nor becomes the next-person-message evidence for fire effects; the reverse event order mentioned in the comment makes this especially reproducible because the marker can be written after the actual command body was submitted. Consume the marker on the first matching submit, or correlate it with the recorded expanded prompt.
Useful? React with 👍 / 👎.
| tid = repair.get("tool_use_id") | ||
| if not tid: | ||
| return None |
There was a problem hiding this comment.
Map prompt-lane fires before discarding their repairs
When the effect judge returns a cost verdict for a prompt rule, its fire has hook_phase="prompt" and no tool_use_id, so _turn_of_fire always returns None. fire_effect.pending_repair has already advanced the verdict offset and marked the rule as handed before this check, making the repair permanently disappear for the cooldown period. Resolve prompt fires to the corresponding person turn using their phase/time instead of requiring a tool result ID.
Useful? React with 👍 / 👎.
| if has_rule: | ||
| cleaned = _with_rule(cleaned, path, False) |
There was a problem hiding this comment.
Preserve pre-existing Agent(fork) allow rules
If the user already allowed Agent(fork) for unrelated workflows before installing MemHub, running the documented onboard removal path unconditionally deletes that permission even though this installer did not add it. This silently changes the user's broader Claude permission policy; either record ownership when adding the rule or leave an indistinguishable pre-existing allow rule intact during removal.
Useful? React with 👍 / 👎.
With the 0.133.0 plugin, check-plugin.sh's bare-Python and MCP-SDK legs run past guard's 10-minute limit (cancelled at 10m16s on #292, #293 and this PR), so guard never reports. promote.yml on internal runs the same two legs under 20 minutes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
MemHub plugin v0.133.0, built from internal main.
Source-RevId:
5403278ed2328628872b897a75d6c4e97ce04946SHA256SUMS:
70a7eab8da80e2a6ef34d520bc759146aeb8c204a1cf019e7c9812708c1dd633Built by promote run 38672534170 at
XTraceAI/agent-plugins-internal@5403278ed2328628872b897a75d6c4e97ce04946: the plugin suites pass at that commit, and theexport is verified — named
memhub, one version across all four manifests, the productionbackend in
.mcp.json, and nothing shaped like a credential. Every file's digest wasre-checked against
SHA256SUMSin the clone this branch was pushed from, so what is here iswhat that run produced.
What's in this release
Everything merged on internal
mainsince the last release, v0.124.0 (7eb88f97d): 40 change(s), 28 of them in the plugin (full range).Breaking changes
Security
Features
Bug fixes
Performance
Changes
Documentation
Merged on internal but not in the plugin (12)
Proved on staging, per surface (
scripts/surface_evidence.py, source commit and v0.133.0):releasetierreleasetierreleasetierreleasetierBefore this can merge:
mainrequires theReal agent evidencecheck, which is a commitstatus, not a check run — it exists only once someone dispatches it on this PR's exact head:
Push again and the new head needs a new run.
After merge, in this order (RELEASING.md):
memhub--v0.133.0and push the tag first — the Claude pincannot resolve a ref that is not there yet.
refandshain.claude-plugin/marketplace.jsonto that tag, by PR.Codex and Cursor ship the moment this merges: their catalogs carry no pin and cache by
version string.