feat(code): add project hooks workspace trust - #5105
Merged
Johannes du Plessis (johannes117) merged 4 commits intoJul 29, 2026
Merged
feat(code): add project hooks workspace trust#5105Johannes du Plessis (johannes117) merged 4 commits into
Johannes du Plessis (johannes117) merged 4 commits into
Conversation
This was referenced Jul 27, 2026
Alexander Olsen (aolsenjazz)
requested changes
Jul 28, 2026
Alexander Olsen (aolsenjazz)
left a comment
Contributor
There was a problem hiding this comment.
Hopping on a meeting, submitting this feedback for now before I inevitably forget
Alexander Olsen (aolsenjazz)
left a comment
Contributor
There was a problem hiding this comment.
Overall pretty good! I think there are a couple things that would be worth taking a look at (I think mostly surfaced in the last review submission) but generally very good!
Johannes du Plessis (johannes117)
force-pushed
the
johannes/code/hooks-v2-project-trust
branch
from
July 28, 2026 22:35
231925f to
26ce3c7
Compare
Alexander Olsen (aolsenjazz)
self-requested a review
July 29, 2026 13:02
Alexander Olsen (aolsenjazz)
approved these changes
Jul 29, 2026
Alexander Olsen (aolsenjazz)
left a comment
Contributor
There was a problem hiding this comment.
LGTM
Alexander Olsen (aolsenjazz)
added a commit
that referenced
this pull request
Jul 29, 2026
Supersedes #5010 (auto-closed when #4997 squash-merged; GitHub seals force-pushed closed PRs). Related: [DCD-71](https://linear.app/langchain/issue/DCD-71/hooks-v2-integrate-client-owned-lifecycle-events) dcode now runs client-owned Hooks v2 lifecycle events consistently in interactive and headless sessions, including hook-driven approval decisions before permission prompts are shown. --- - Invokes `SessionStart` and `SessionEnd` at startup, resume, clear, compact, switch, and exit boundaries. - Applies `PermissionRequest` allow, deny, ask, interrupt, notice, terminal, and stop effects before client approval resolution. - Routes supported dcode notifications through one typed service with explicit wire mappings while avoiding migrated legacy duplicates. - Preserves session-start context for the next model turn and adds TUI/headless decision-parity coverage. - Ignores generated local transcript state through `.gitignore`. This branch was re-anchored onto `main` after #4997 squash-merged; the diff is identical to the approved #5010 head (`f4e8ee672`), minus a stale resurrection of `todo_list_prompt.md` that #5098 deleted on main. ## Review Guide 1. `hooks/client_lifecycle.py` — `ClientHookService`, context, permission outcomes 2. `app.py` — SessionStart/End boundaries + service wiring 3. `tui/textual_adapter.py`, `client/non_interactive.py` — interactive vs headless parity 4. Skim: `transcript.py`, `server_middleware.py` (PermissionRequest), `runtime.py` / `projection.py` 5. Tests: `test_client_lifecycle.py`, then adapter / non-interactive / server-lifecycle deltas <details> <summary>Test plan</summary> - 266 hooks unit tests pass on the rebuilt tip - 412 non-interactive / Textual adapter / status widget tests pass </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): integrate Hooks v2 client lifecycle events** :point_left: - #5105 - #5045 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://github.com/git-town/git-town)</sup> <!-- branch-stack-end --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
Project-level hooks now require an explicit workspace trust decision before their commands run. Interactive users can allow once, remember the workspace, or skip project hooks; headless runs remain opt-in through --trust-project-hooks. Re-anchored onto the rebuilt dcd-71 branch after #4997 squash-merged; carries the full PR #5044 delta.
The trust suite covered store internals (thread-lock gating, concurrent writers, symlink/worktree aliasing, partially invalid payloads) and repeated the same trusted/untrusted runtime assertions across several cases. Keep one test per behavior that can actually regress: canonical persistence with restrictive permissions, fail-closed handling of a corrupt store, project-source provenance in the runtime, the runtime trust guard, the three interactive prompt outcomes, prompt suppression for persisted trust, and the Textual wiring. The `test_app` mock-shape tweak is no longer needed, so it is dropped as well. Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Addresses automated review feedback on the project hook trust plumbing. - `WorkspaceTrust.explicit_only` ignores the persisted store, so a workspace remembered during an interactive session no longer opts a later `dcode -n` invocation into executing that repository's hooks. Headless runs stay explicit-opt-in, as their docstrings already promised. - `_load_store` now catches `UnicodeDecodeError` where decoding actually happens — during the read. A non-UTF-8 `hooks_trust.json` previously escaped the unreadable-store handler and crashed startup with a traceback instead of failing closed. - `WorkspaceTrust.allows` no longer restates the working directory in its warning; the raised exception already carries it, and CodeQL flagged the interpolation under py/clear-text-logging-sensitive-data.
Johannes du Plessis (johannes117)
force-pushed
the
johannes/code/hooks-v2-project-trust
branch
2 times, most recently
from
July 29, 2026 17:14
37ba40e to
4b05a0a
Compare
Johannes du Plessis (johannes117)
deleted the
johannes/code/hooks-v2-project-trust
branch
July 29, 2026 17:22
Johannes du Plessis (johannes117)
added a commit
that referenced
this pull request
Jul 29, 2026
Hook execution now reports progress, warnings, notices, and permission decisions consistently in the TUI and non-interactive client. Configured `statusMessage` values appear while handlers run, and server-owned hook output is no longer confined to logs. --- A shared `HookFeedback` presenter keeps event ownership out of the UI layer while preserving ordered engine reduction. It deduplicates visible diagnostics, tracks concurrent handler statuses without clearing a still-running hook, emits validated terminal sequences once, and attributes hook-owned allow/deny decisions in both clients. Re-anchored onto `main` after #5105 squash-merged. Call sites keep the parent `WorkspaceTrust` API and layer `HookFeedback` on top. ## Review Guide 1. `hooks/feedback.py` — `HookFeedback` presenter (progress / notices / decisions) 2. `hooks/engine.py` — handler progress reporting 3. `hooks/client_lifecycle.py`, `hooks/client.py` — feedback attachment vs log-only 4. `client/non_interactive.py`, `app.py`, `tui/widgets/status.py` — UI/status sinks 5. Skim: `HOOKS.md`, tiny adapter/runtime/threat-model edits 6. Tests: `test_feedback.py`, then engine / client-lifecycle / status <details> <summary>Test plan</summary> - Added focused presenter, concurrent progress, `statusMessage`, server-notice, and permission-attribution coverage. - Targeted feedback / engine / lifecycle / trust / status suite passed on the prior stack tip; CI re-runs on this re-anchor. </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): surface Hooks v2 runtime feedback** 👈 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://www.git-town.com)</sup> <!-- branch-stack-end -->
Marcelo5444
pushed a commit
to Marcelo5444/deepagents
that referenced
this pull request
Jul 30, 2026
…5104) Supersedes langchain-ai#5010 (auto-closed when langchain-ai#4997 squash-merged; GitHub seals force-pushed closed PRs). Related: [DCD-71](https://linear.app/langchain/issue/DCD-71/hooks-v2-integrate-client-owned-lifecycle-events) dcode now runs client-owned Hooks v2 lifecycle events consistently in interactive and headless sessions, including hook-driven approval decisions before permission prompts are shown. --- - Invokes `SessionStart` and `SessionEnd` at startup, resume, clear, compact, switch, and exit boundaries. - Applies `PermissionRequest` allow, deny, ask, interrupt, notice, terminal, and stop effects before client approval resolution. - Routes supported dcode notifications through one typed service with explicit wire mappings while avoiding migrated legacy duplicates. - Preserves session-start context for the next model turn and adds TUI/headless decision-parity coverage. - Ignores generated local transcript state through `.gitignore`. This branch was re-anchored onto `main` after langchain-ai#4997 squash-merged; the diff is identical to the approved langchain-ai#5010 head (`f4e8ee672`), minus a stale resurrection of `todo_list_prompt.md` that langchain-ai#5098 deleted on main. ## Review Guide 1. `hooks/client_lifecycle.py` — `ClientHookService`, context, permission outcomes 2. `app.py` — SessionStart/End boundaries + service wiring 3. `tui/textual_adapter.py`, `client/non_interactive.py` — interactive vs headless parity 4. Skim: `transcript.py`, `server_middleware.py` (PermissionRequest), `runtime.py` / `projection.py` 5. Tests: `test_client_lifecycle.py`, then adapter / non-interactive / server-lifecycle deltas <details> <summary>Test plan</summary> - 266 hooks unit tests pass on the rebuilt tip - 412 non-interactive / Textual adapter / status widget tests pass </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): integrate Hooks v2 client lifecycle events** :point_left: - langchain-ai#5105 - langchain-ai#5045 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://github.com/git-town/git-town)</sup> <!-- branch-stack-end --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
Marcelo5444
pushed a commit
to Marcelo5444/deepagents
that referenced
this pull request
Jul 30, 2026
Supersedes langchain-ai#5044 (auto-closed when langchain-ai#4997 squash-merged; GitHub seals force-pushed closed PRs). Project-level hooks now require an explicit workspace trust decision before their commands run. Interactive users can allow once, remember the workspace, or skip project hooks; headless runs remain opt-in through `--trust-project-hooks`. --- This closes the execution gap that left interactive project hooks permanently disabled while preserving fail-closed behavior. Trust is keyed to the canonical repository root, saved atomically, and enforced again at runtime if a snapshot is ever constructed inconsistently. `config path` and the threat model now expose the relevant project, user, and trust locations. Re-anchored onto `main` after langchain-ai#5104 squash-merged, so the PR diff contains only this branch's commits. ## Review Guide 1. `hooks/trust.py` — store, keys, atomic write, trust APIs 2. `hooks/loading.py` — project source ingest vs skip 3. `hooks/runtime.py` — fail-closed runtime guard 4. `main.py` — `--trust-project-hooks` + interactive prompt 5. Skim: `app.py`, `client/commands/config.py`, `THREAT_MODEL.md` 6. Tests: `test_trust.py`, then config/app/main touches <details> <summary>Test plan</summary> - Full hooks suite passes on the rebuilt stack tip. `test_trust.py` keeps one case per regressable behavior: canonical persistence, fail-closed corrupt-store handling, project-source provenance, the runtime trust guard, the three prompt outcomes, prompt suppression on persisted trust, and Textual wiring. </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): add project hooks workspace trust** 👈 - langchain-ai#5045 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://github.com/git-town/git-town)</sup> <!-- branch-stack-end --> --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Marcelo5444
pushed a commit
to Marcelo5444/deepagents
that referenced
this pull request
Jul 30, 2026
Hook execution now reports progress, warnings, notices, and permission decisions consistently in the TUI and non-interactive client. Configured `statusMessage` values appear while handlers run, and server-owned hook output is no longer confined to logs. --- A shared `HookFeedback` presenter keeps event ownership out of the UI layer while preserving ordered engine reduction. It deduplicates visible diagnostics, tracks concurrent handler statuses without clearing a still-running hook, emits validated terminal sequences once, and attributes hook-owned allow/deny decisions in both clients. Re-anchored onto `main` after langchain-ai#5105 squash-merged. Call sites keep the parent `WorkspaceTrust` API and layer `HookFeedback` on top. ## Review Guide 1. `hooks/feedback.py` — `HookFeedback` presenter (progress / notices / decisions) 2. `hooks/engine.py` — handler progress reporting 3. `hooks/client_lifecycle.py`, `hooks/client.py` — feedback attachment vs log-only 4. `client/non_interactive.py`, `app.py`, `tui/widgets/status.py` — UI/status sinks 5. Skim: `HOOKS.md`, tiny adapter/runtime/threat-model edits 6. Tests: `test_feedback.py`, then engine / client-lifecycle / status <details> <summary>Test plan</summary> - Added focused presenter, concurrent progress, `statusMessage`, server-notice, and permission-attribution coverage. - Targeted feedback / engine / lifecycle / trust / status suite passed on the prior stack tip; CI re-runs on this re-anchor. </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): surface Hooks v2 runtime feedback** 👈 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://www.git-town.com)</sup> <!-- branch-stack-end -->
Mason Daugherty (mdrxy)
pushed a commit
that referenced
this pull request
Jul 30, 2026
> [!CAUTION] > Merging this PR will automatically publish to **PyPI** and create a **GitHub release**. For the full release process, see [`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md). --- _Release notes preview: keep this section in sync with the package `CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`, not this PR description — keep them aligned anyway so the PR stays an accurate historical record for reviewers and anyone returning later._ --- ## [0.1.50](deepagents-code==0.1.49...deepagents-code==0.1.50) (2026-07-30) ### Highlights - Added project hooks workspace trust and expanded Hooks v2 support with client and server lifecycle events plus runtime feedback ([#5105](#5105), [#5104](#5104), [#4997](#4997), [#5045](#5045)). - Added an option to mute the “YOLO is active” toast ([#5103](#5103)). - Made the splash screen `thread` ID clickable to copy it ([#5173](#5173)). - Show `ask_user` answers directly on the answered tool row ([#5100](#5100)). - Show a toast when submitting an empty required `ask_user` answer ([#5095](#5095)). - Added thread message counts to the Debug Console ([#5117](#5117)). ### Fixes and improvements - Gated Hooks v2 behind `DEEPAGENTS_CODE_EXPERIMENTAL` and improved hook resume stability across identity and Command tool results ([#5146](#5146), [#5176](#5176)). - Kept server hook state out of task results ([#5164](#5164)). - Stopped duplicate Auto transcript events during interrupt replay ([#5157](#5157)). - Kept `/update` and `/install --package` prompts responsive ([#5127](#5127)). - Refreshed the `/threads` cache after each turn ([#5174](#5174)). - Anchored toasts above the chat input and added a toast when media is dropped into a free-text question ([#5101](#5101), [#5099](#5099)). - Improved thread status message styling and links ([#5118](#5118)). - Made resume hints echo the launched command name ([#5119](#5119)). - Scoped selection copy to the clicked screen ([#5140](#5140)). - Ignored mouse hits on detached widgets ([#5114](#5114)). _End release notes preview._ --- > [!NOTE] > A **New Contributors** section is appended to the GitHub release notes automatically at publish time (see [Release Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline), step 2). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: langchain-oss-automated-triage[bot] <248757908+langchain-oss-automated-triage[bot]@users.noreply.github.com> Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
Mason Daugherty (mdrxy)
pushed a commit
that referenced
this pull request
Jul 30, 2026
Supersedes #5010 (auto-closed when #4997 squash-merged; GitHub seals force-pushed closed PRs). Related: [DCD-71](https://linear.app/langchain/issue/DCD-71/hooks-v2-integrate-client-owned-lifecycle-events) dcode now runs client-owned Hooks v2 lifecycle events consistently in interactive and headless sessions, including hook-driven approval decisions before permission prompts are shown. --- - Invokes `SessionStart` and `SessionEnd` at startup, resume, clear, compact, switch, and exit boundaries. - Applies `PermissionRequest` allow, deny, ask, interrupt, notice, terminal, and stop effects before client approval resolution. - Routes supported dcode notifications through one typed service with explicit wire mappings while avoiding migrated legacy duplicates. - Preserves session-start context for the next model turn and adds TUI/headless decision-parity coverage. - Ignores generated local transcript state through `.gitignore`. This branch was re-anchored onto `main` after #4997 squash-merged; the diff is identical to the approved #5010 head (`f4e8ee672`), minus a stale resurrection of `todo_list_prompt.md` that #5098 deleted on main. 1. `hooks/client_lifecycle.py` — `ClientHookService`, context, permission outcomes 2. `app.py` — SessionStart/End boundaries + service wiring 3. `tui/textual_adapter.py`, `client/non_interactive.py` — interactive vs headless parity 4. Skim: `transcript.py`, `server_middleware.py` (PermissionRequest), `runtime.py` / `projection.py` 5. Tests: `test_client_lifecycle.py`, then adapter / non-interactive / server-lifecycle deltas <details> <summary>Test plan</summary> - 266 hooks unit tests pass on the rebuilt tip - 412 non-interactive / Textual adapter / status widget tests pass </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): integrate Hooks v2 client lifecycle events** :point_left: - #5105 - #5045 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://github.com/git-town/git-town)</sup> <!-- branch-stack-end --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
Mason Daugherty (mdrxy)
pushed a commit
that referenced
this pull request
Jul 30, 2026
Supersedes #5044 (auto-closed when #4997 squash-merged; GitHub seals force-pushed closed PRs). Project-level hooks now require an explicit workspace trust decision before their commands run. Interactive users can allow once, remember the workspace, or skip project hooks; headless runs remain opt-in through `--trust-project-hooks`. --- This closes the execution gap that left interactive project hooks permanently disabled while preserving fail-closed behavior. Trust is keyed to the canonical repository root, saved atomically, and enforced again at runtime if a snapshot is ever constructed inconsistently. `config path` and the threat model now expose the relevant project, user, and trust locations. Re-anchored onto `main` after #5104 squash-merged, so the PR diff contains only this branch's commits. ## Review Guide 1. `hooks/trust.py` — store, keys, atomic write, trust APIs 2. `hooks/loading.py` — project source ingest vs skip 3. `hooks/runtime.py` — fail-closed runtime guard 4. `main.py` — `--trust-project-hooks` + interactive prompt 5. Skim: `app.py`, `client/commands/config.py`, `THREAT_MODEL.md` 6. Tests: `test_trust.py`, then config/app/main touches <details> <summary>Test plan</summary> - Full hooks suite passes on the rebuilt stack tip. `test_trust.py` keeps one case per regressable behavior: canonical persistence, fail-closed corrupt-store handling, project-source provenance, the runtime trust guard, the three prompt outcomes, prompt suppression on persisted trust, and Textual wiring. </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): add project hooks workspace trust** 👈 - #5045 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://github.com/git-town/git-town)</sup> <!-- branch-stack-end --> --------- Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Mason Daugherty (mdrxy)
pushed a commit
that referenced
this pull request
Jul 30, 2026
Hook execution now reports progress, warnings, notices, and permission decisions consistently in the TUI and non-interactive client. Configured `statusMessage` values appear while handlers run, and server-owned hook output is no longer confined to logs. --- A shared `HookFeedback` presenter keeps event ownership out of the UI layer while preserving ordered engine reduction. It deduplicates visible diagnostics, tracks concurrent handler statuses without clearing a still-running hook, emits validated terminal sequences once, and attributes hook-owned allow/deny decisions in both clients. Re-anchored onto `main` after #5105 squash-merged. Call sites keep the parent `WorkspaceTrust` API and layer `HookFeedback` on top. ## Review Guide 1. `hooks/feedback.py` — `HookFeedback` presenter (progress / notices / decisions) 2. `hooks/engine.py` — handler progress reporting 3. `hooks/client_lifecycle.py`, `hooks/client.py` — feedback attachment vs log-only 4. `client/non_interactive.py`, `app.py`, `tui/widgets/status.py` — UI/status sinks 5. Skim: `HOOKS.md`, tiny adapter/runtime/threat-model edits 6. Tests: `test_feedback.py`, then engine / client-lifecycle / status <details> <summary>Test plan</summary> - Added focused presenter, concurrent progress, `statusMessage`, server-notice, and permission-attribution coverage. - Targeted feedback / engine / lifecycle / trust / status suite passed on the prior stack tip; CI re-runs on this re-anchor. </details> <!-- branch-stack-start --> ------------------------- - main - **feat(code): surface Hooks v2 runtime feedback** 👈 <sup>[Stack](https://www.git-town.com/how-to/proposal-breadcrumb.html) generated by [Git Town](https://www.git-town.com)</sup> <!-- branch-stack-end -->
Mason Daugherty (mdrxy)
pushed a commit
that referenced
this pull request
Jul 30, 2026
> [!CAUTION] > Merging this PR will automatically publish to **PyPI** and create a **GitHub release**. For the full release process, see [`.github/RELEASING.md`](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md). --- _Release notes preview: keep this section in sync with the package `CHANGELOG.md`. Publish reads the merged CHANGELOG via `release.yml`, not this PR description — keep them aligned anyway so the PR stays an accurate historical record for reviewers and anyone returning later._ --- ## [0.1.50](deepagents-code==0.1.49...deepagents-code==0.1.50) (2026-07-30) ### Highlights - Added project hooks workspace trust and expanded Hooks v2 support with client and server lifecycle events plus runtime feedback ([#5105](#5105), [#5104](#5104), [#4997](#4997), [#5045](#5045)). - Added an option to mute the “YOLO is active” toast ([#5103](#5103)). - Made the splash screen `thread` ID clickable to copy it ([#5173](#5173)). - Show `ask_user` answers directly on the answered tool row ([#5100](#5100)). - Show a toast when submitting an empty required `ask_user` answer ([#5095](#5095)). - Added thread message counts to the Debug Console ([#5117](#5117)). ### Fixes and improvements - Gated Hooks v2 behind `DEEPAGENTS_CODE_EXPERIMENTAL` and improved hook resume stability across identity and Command tool results ([#5146](#5146), [#5176](#5176)). - Kept server hook state out of task results ([#5164](#5164)). - Stopped duplicate Auto transcript events during interrupt replay ([#5157](#5157)). - Kept `/update` and `/install --package` prompts responsive ([#5127](#5127)). - Refreshed the `/threads` cache after each turn ([#5174](#5174)). - Anchored toasts above the chat input and added a toast when media is dropped into a free-text question ([#5101](#5101), [#5099](#5099)). - Improved thread status message styling and links ([#5118](#5118)). - Made resume hints echo the launched command name ([#5119](#5119)). - Scoped selection copy to the clicked screen ([#5140](#5140)). - Ignored mouse hits on detached widgets ([#5114](#5114)). _End release notes preview._ --- > [!NOTE] > A **New Contributors** section is appended to the GitHub release notes automatically at publish time (see [Release Pipeline](https://github.com/langchain-ai/deepagents/blob/main/.github/RELEASING.md#release-pipeline), step 2). --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: langchain-oss-automated-triage[bot] <248757908+langchain-oss-automated-triage[bot]@users.noreply.github.com> Co-authored-by: Johannes du Plessis <johannes@langchain.dev>
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.
Supersedes #5044 (auto-closed when #4997 squash-merged; GitHub seals force-pushed closed PRs).
Project-level hooks now require an explicit workspace trust decision before their commands run. Interactive users can allow once, remember the workspace, or skip project hooks; headless runs remain opt-in through
--trust-project-hooks.This closes the execution gap that left interactive project hooks permanently disabled while preserving fail-closed behavior. Trust is keyed to the canonical repository root, saved atomically, and enforced again at runtime if a snapshot is ever constructed inconsistently.
config pathand the threat model now expose the relevant project, user, and trust locations.Re-anchored onto
mainafter #5104 squash-merged, so the PR diff contains only this branch's commits.Review Guide
hooks/trust.py— store, keys, atomic write, trust APIshooks/loading.py— project source ingest vs skiphooks/runtime.py— fail-closed runtime guardmain.py—--trust-project-hooks+ interactive promptapp.py,client/commands/config.py,THREAT_MODEL.mdtest_trust.py, then config/app/main touchesTest plan
test_trust.pykeeps one case per regressable behavior: canonical persistence, fail-closed corrupt-store handling, project-source provenance, the runtime trust guard, the three prompt outcomes, prompt suppression on persisted trust, and Textual wiring.Stack generated by Git Town