Repository navigation
Retain pinned hook bundles across plugin cache updates - #106
Open
adit-chandra wants to merge 3 commits into
Open
adit-chandra wants to merge 3 commits into
adit-chandra wants to merge 3 commits into
Conversation
This was referenced Oct 23, 2026
adit-chandra
marked this pull request as ready for review
October 23, 2026 01:06
adit-chandra
added a commit
that referenced
this pull request
Oct 23, 2026
## Motivation When a marketplace update removes a plugin version still referenced by a running session, Python exits with code 2 before the hook adapter starts. Codex interprets that infrastructure failure as an intentional hook block, potentially hiding the result of a command that already ran. ## Summary Embed a Python launcher in portable hook commands so it survives deletion of plugin files. Portable context hooks now report bounded failure diagnostics and exit successfully; native JSON hooks retain their authored blocking semantics. Execution remains in-process so cancellation reaches handlers. Stack: this PR targets `main`; #106 adds retained runtime bundles on top, and #107 separates installation from current-session activation. ## Validation - Full suite: 1,053 passed. - Focused hook suite: 59 passed, covering deleted adapters, entrypoints and helpers across Claude, Codex and Cursor; script exit 2; and native blocking behavior. - Repository-wide Ruff lint/format and ty passed (using the worktree environment). - Generated commands exercised in local subprocesses; live desktop-host acceptance and marketplace publication are not part of this PR.
Base automatically changed from
adit-chandra/codex/hook-failure-isolation
to
main
October 23, 2026 01:08
| "schema": 1, | ||
| "host": target, | ||
| "hook": asset.id, | ||
| "entrypoint": f"{asset.id}/{spec.entrypoint}", |
There was a problem hiding this comment.
[Medium] Normalize the entrypoint before storing it in the manifest. HookDefinition accepts paths such as ./handler.py and sub//handler.py, which previously executed successfully, but the manifest file keys are normalized by pathlib while this field preserves the original spelling. Consequently, read_manifest rejects these valid bundles as "incomplete hook manifest", and both preparation and ordinary invocations silently skip the hook on all targets. Construct this field with (Path(asset.id) / spec.entrypoint).as_posix() and add coverage for these accepted spellings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Nonblocking failure handling keeps the agent usable, but a running session should continue executing the hook version it loaded even after an update removes that plugin cache directory.
Summary
Pin each generated portable hook command to a manifest covering its adapter, configuration, helper files and other bundle contents. Prepare a private copy at SessionStart (without executing authored code), or on first invocation. Validate and atomically publish complete bundles into a durable store outside host plugin caches; concurrent invocations share only the exact verified digest.
Loaded commands retain their behavior across upgrades, rollback and same-version replacement. Corrupt or unavailable bundles skip nonblockingly with a deduplicated diagnostic. There is no latest-version fallback or automatic eviction: safe cleanup needs lifetime information for idle/resumable sessions. Dependencies must be bundled and resolved relative to
__file__; writable hook state belongs elsewhere.Stack: depends on #105. #107 separates installation from session activation in the update workflow. This change covers portable declarations, not authored native JSON or the managed trace runtime.
Validation