Skip to content

feat(code): surface Hooks v2 runtime feedback - #5045

Merged
Johannes du Plessis (johannes117) merged 7 commits into
mainfrom
johannes/code/hooks-v2-runtime-feedback
Jul 29, 2026
Merged

feat(code): surface Hooks v2 runtime feedback#5045
Johannes du Plessis (johannes117) merged 7 commits into
mainfrom
johannes/code/hooks-v2-runtime-feedback

Conversation

@johannes117

@johannes117 Johannes du Plessis (johannes117) commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

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.pyHookFeedback 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
Test plan
  • 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.

  • main
    • feat(code): surface Hooks v2 runtime feedback 👈

Stack generated by Git Town

@github-actions github-actions Bot added dcode Related to `deepagents-code` feature New feature/enhancement or request for one internal User is a member of the `langchain-ai` GitHub organization size: L 500-999 LOC labels Jul 24, 2026

@open-swe open-swe 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.

Open SWE Review found 1 potential issue.

Open in WebView Open SWE trace

Comment thread libs/code/deepagents_code/app.py Outdated
@github-actions github-actions Bot added size: XL 1000+ LOC and removed size: L 500-999 LOC labels Jul 24, 2026

@open-swe open-swe 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.

Open SWE Review found 1 potential issue.

Open in WebView Open SWE trace

Comment thread libs/code/deepagents_code/hooks/client_lifecycle.py Outdated
Johannes du Plessis (johannes117) added a commit that referenced this pull request Jul 27, 2026
<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
Depends on #4971
Closes DCD-69

Server-owned Hooks v2 events now pause the agent over LangGraph
interrupts, run on the client `HooksRuntime`, and resume with typed
decisions.

---

This starts the DCD-69 stack on top of the DCD-70 leaf (#4971).

- Adds a versioned `hook_invocation` interrupt/resume transport around
`HookInvocationRequest` / `HookInvocationResponse`.
- Installs `ServerHooksMiddleware` for `PreToolUse`, `PostToolUse`,
`Stop`, `SubagentStart`, and `SubagentStop`, gated by the session's
configured server events so idle sessions skip the round-trip.
- Creates a session-scoped client `HooksRuntime` and fulfills server
interrupts from both the Textual adapter and headless runner.
- Applies `deny`/`ask` as blocking tool errors for now; `ask` approval
UX remains for DCD-71.

## Review Guide

1. `hooks/server_middleware.py` — middleware, gating, interrupt raise,
decision apply
2. `hooks/interrupt.py` — `hook_invocation` pause/resume contract
3. `hooks/client.py` — client fulfillment + resume ledger
4. `agent.py` — middleware install (main + subagents)
5. `tui/textual_adapter.py`, `client/non_interactive.py` — interrupt
fulfillment call sites
6. Skim: `envelope.py`, `context.py`, `runtime.py`, `_cli_context.py`,
small `app`/`auto_mode`/`main`/`snapshot`/`engine` touches
7. Tests: `test_server_lifecycle.py`, then `test_agent` /
`test_non_interactive` / `test_engine`

<details>
<summary>Test plan</summary>

- `uv run --group test pytest tests/unit_tests/hooks` — 133 passed
- `make lint` in `libs/code`

</details>


<!-- branch-stack-start -->

-------------------------
- main
- **feat(code): integrate Hooks v2 server lifecycle events**
:point_left:
    - #5010
      - #5044
        - #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 Agent <cursoragent@cursor.com>
Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Johannes du Plessis (johannes117) added a commit that referenced this pull request Jul 27, 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.

Re-anchored onto the rebuilt project-trust branch after #4997 squash-merged;
carries the full PR #5045 delta.
@johannes117
Johannes du Plessis (johannes117) force-pushed the johannes/code/hooks-v2-runtime-feedback branch from 95c63b7 to 4d26eed Compare July 27, 2026 23:27
@github-actions github-actions Bot added size: L 500-999 LOC and removed size: XL 1000+ LOC labels Jul 28, 2026
Comment thread libs/code/deepagents_code/hooks/presenter.py
Comment thread libs/code/deepagents_code/hooks/engine.py Outdated
Comment thread libs/code/deepagents_code/hooks/engine.py Outdated
Comment thread libs/code/deepagents_code/hooks/engine.py Outdated
Comment thread libs/code/deepagents_code/hooks/client_lifecycle.py Outdated
Comment thread libs/code/deepagents_code/hooks/client_lifecycle.py Outdated
Comment thread libs/code/deepagents_code/hooks/client_lifecycle.py
Johannes du Plessis (johannes117) added a commit that referenced this pull request Jul 28, 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.

Re-anchored onto the rebuilt project-trust branch after #4997 squash-merged;
carries the full PR #5045 delta.
@johannes117
Johannes du Plessis (johannes117) force-pushed the johannes/code/hooks-v2-runtime-feedback branch from 00e9116 to 5af1ed7 Compare July 28, 2026 22:35
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>
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.

Re-anchored onto the rebuilt project-trust branch after #4997 squash-merged;
carries the full PR #5045 delta.
@johannes117
Johannes du Plessis (johannes117) force-pushed the johannes/code/hooks-v2-runtime-feedback branch from ff12624 to aa9d208 Compare July 29, 2026 17:06
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.

Re-anchored onto the rebuilt project-trust branch after #4997 squash-merged;
carries the full PR #5045 delta.
@johannes117
Johannes du Plessis (johannes117) force-pushed the johannes/code/hooks-v2-runtime-feedback branch from aa9d208 to e6b91b1 Compare July 29, 2026 17:15
Base automatically changed from johannes/code/hooks-v2-project-trust to main July 29, 2026 17:22
Johannes du Plessis (johannes117) added a commit that referenced this pull request Jul 29, 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>
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.

Re-anchored onto the rebuilt project-trust branch after #4997 squash-merged;
carries the full PR #5045 delta.
@johannes117
Johannes du Plessis (johannes117) force-pushed the johannes/code/hooks-v2-runtime-feedback branch from e6b91b1 to 6ccadf4 Compare July 29, 2026 17:23
@github-actions github-actions Bot added size: XL 1000+ LOC and removed size: L 500-999 LOC labels Jul 29, 2026

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.

Just a few nits, but I'm ready to stamp. I think the design is more inline with what we want. just check in with the comment I made re. the exception made for the noninteractive presentation layer

Comment thread libs/code/deepagents_code/client/non_interactive.py Outdated
Comment thread libs/code/deepagents_code/client/non_interactive.py Outdated
Comment thread libs/code/deepagents_code/client/non_interactive.py Outdated
Comment thread libs/code/deepagents_code/hooks/engine.py
CI merges main, which gates Hooks v2 behind DEEPAGENTS_CODE_EXPERIMENTAL;
without the flag these tests saw an inert manager and failed.

Co-authored-by: Cursor <cursoragent@cursor.com>
@johannes117
Johannes du Plessis (johannes117) merged commit 66d526f into main Jul 29, 2026
55 checks passed
@johannes117
Johannes du Plessis (johannes117) deleted the johannes/code/hooks-v2-runtime-feedback branch July 29, 2026 20:57
Marcelo5444 pushed a commit to Marcelo5444/deepagents that referenced this pull request Jul 30, 2026
…4997)

<!-- CURSOR_AGENT_PR_BODY_BEGIN -->
Depends on langchain-ai#4971
Closes DCD-69

Server-owned Hooks v2 events now pause the agent over LangGraph
interrupts, run on the client `HooksRuntime`, and resume with typed
decisions.

---

This starts the DCD-69 stack on top of the DCD-70 leaf (langchain-ai#4971).

- Adds a versioned `hook_invocation` interrupt/resume transport around
`HookInvocationRequest` / `HookInvocationResponse`.
- Installs `ServerHooksMiddleware` for `PreToolUse`, `PostToolUse`,
`Stop`, `SubagentStart`, and `SubagentStop`, gated by the session's
configured server events so idle sessions skip the round-trip.
- Creates a session-scoped client `HooksRuntime` and fulfills server
interrupts from both the Textual adapter and headless runner.
- Applies `deny`/`ask` as blocking tool errors for now; `ask` approval
UX remains for DCD-71.

## Review Guide

1. `hooks/server_middleware.py` — middleware, gating, interrupt raise,
decision apply
2. `hooks/interrupt.py` — `hook_invocation` pause/resume contract
3. `hooks/client.py` — client fulfillment + resume ledger
4. `agent.py` — middleware install (main + subagents)
5. `tui/textual_adapter.py`, `client/non_interactive.py` — interrupt
fulfillment call sites
6. Skim: `envelope.py`, `context.py`, `runtime.py`, `_cli_context.py`,
small `app`/`auto_mode`/`main`/`snapshot`/`engine` touches
7. Tests: `test_server_lifecycle.py`, then `test_agent` /
`test_non_interactive` / `test_engine`

<details>
<summary>Test plan</summary>

- `uv run --group test pytest tests/unit_tests/hooks` — 133 passed
- `make lint` in `libs/code`

</details>


<!-- branch-stack-start -->

-------------------------
- main
- **feat(code): integrate Hooks v2 server lifecycle events**
:point_left:
    - langchain-ai#5010
      - langchain-ai#5044
        - 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 Agent <cursoragent@cursor.com>
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
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dcode Related to `deepagents-code` feature New feature/enhancement or request for one internal User is a member of the `langchain-ai` GitHub organization size: XL 1000+ LOC

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants