Skip to content

feat(hooks): report every launched harness's lifecycle back to Medulla, and give hooks a page - #192

Merged
senamakel merged 51 commits into
mainfrom
harness-lifecycle-hooks
Aug 6, 2026
Merged

feat(hooks): report every launched harness's lifecycle back to Medulla, and give hooks a page#192
senamakel merged 51 commits into
mainfrom
harness-lifecycle-hooks

Conversation

@senamakel

@senamakel senamakel commented Aug 5, 2026

Copy link
Copy Markdown
Member

What this fixes

[[hooks]] injection worked, but Medulla shipped zero hooks of its own, so a
Claude Code or Codex session Medulla launched carried nothing unless the operator
had hand-written a [[hooks]] section — which is why /hooks in a Medulla-spawned
session showed nothing at all. A harness on a pty was opaque: "is this waiting for
me?" and "did that turn finish?" were answered by pattern-matching its screen.

What is here

Medulla's own reporting hooks, on by default (src/sdk/src/harness_hooks/builtin.rs).
Resolved at config load, so every spawn door — the pty pane, the executor, the
wrapper, the daemon — installs them without knowing they exist. Each runs
medulla hook <Event>; the shim reads the harness's native payload on stdin and
files a one-line summary on the control socket that spawn was already handed,
authenticating with that session's grant.

Two properties are deliberate:

  • They only observe. No PreToolUse, no PermissionRequest — both can deny a
    call, and a hook Medulla installs everywhere must not change what a session does.
  • The payload never travels. Prompt text, tool inputs, and file contents stay in
    the harness's process tree; the shim summarizes at the source (used Edit,
    prompt submitted (412 chars)).

Switched off with [hookDefaults] enabled = false, or b on the new page. Never
written to the operator's config file, so a later release can change or withdraw them.

A Hooks page under Hosts (Hosts → 3 Hooks). Medulla as hook aggregator: one
place to declare a hook for every harness it launches. Shows what a harness started
right now would carry, marks Medulla's own separately from the operator's, summarizes
per-harness coverage gaps (OpenCode has no declarative hook API; Codex needs one
/hooks trust), and renders the reports arriving live underneath. a add, e edit,
d remove, b toggle Medulla's own — the operator's half round-trips through
[[hooks]] in their config file.

Validation

  • cargo test — all suites pass, including a new e2e_hook_shim that runs the real
    medulla hook binary against a real control socket and asserts the report lands in
    the log (and that the tool input does not).
  • cargo clippy --all-targets -- -D warnings, cargo fmt --check.
  • Real Claude Code 2.1.222, launched with the exact argv launch_args produces
    against a stand-in control plane: SessionStart, UserPromptSubmit,
    PostToolUse (used Bash), Stop, SessionEnd all reported, with no payload in
    any of them.
  • Page driven under tmux: renders, adds a hook, persists it, warns about coverage.

Codex remains inert until the operator trusts the hooks once (/hooks) — Medulla
still refuses --dangerously-bypass-hook-trust, and the page says so.

Summary by CodeRabbit

  • New Features
    • Added built-in lifecycle hooks that report harness activity to Medulla.
    • Added a Hooks page for viewing recent reports, coverage warnings, and hook details.
    • Added tools to create, edit, delete, and reorder operator-defined hooks.
    • Added the medulla hook command for lifecycle event reporting with protected, summarized payloads.
  • Configuration
    • Built-in hooks are enabled by default and can be disabled in configuration.
    • Hook settings and definitions now persist across supported configuration formats.
  • Bug Fixes
    • Restricted hook credentials to reporting-only operations.
    • Preserved custom hooks when built-in hooks are enabled.

…a, and give hooks a page

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 13 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7ee06587-d468-4370-a2c9-2635fda5defa

📥 Commits

Reviewing files that changed from the base of the PR and between 47e924d and d894c2b.

📒 Files selected for processing (4)
  • src/sdk/src/control_socket/server/handle/hooks.rs
  • src/sdk/src/control_socket/server/handle/hooks_tests.rs
  • src/tui/src/commands/hook.rs
  • src/tui/src/commands/hook_tests.rs
📝 Walkthrough

Walkthrough

Medulla now installs built-in lifecycle reporting hooks, injects scoped hook-only grants into spawned harnesses, records sanitized reports through the control socket, persists hook settings, and adds TUI editing and reporting views.

Changes

Lifecycle hook reporting

Layer / File(s) Summary
Hook configuration and persistence
src/sdk/src/config/*, src/sdk/src/harness_hooks/types.rs, src/sdk/tests/feature_hooks_config.rs
Configuration separates built-in and operator hooks. Built-ins are enabled by default. Operator hooks persist independently in TOML or JSON.
Built-in hooks and event logs
src/sdk/src/harness_hooks/builtin.rs, src/sdk/src/harness_hooks/report.rs, src/sdk/src/harness_hooks/grant.rs
Medulla defines observational lifecycle hooks, bounded report storage, and feature-gated grant seeding with drop-time revocation.
Secure reporting transport
src/sdk/src/control_socket/*, src/sdk/src/mcp/*, src/sdk/src/sessions/*, src/sdk/src/wrapper/*, src/sdk/src/daemon/providers/execute.rs
Hook-only grants can submit hook.report but cannot access worker or task operations. Spawn paths inject and retain these grants for the session lifetime.
Hook command and runtime wiring
src/tui/src/commands/*, src/tui/src/cli/*, src/tui/src/control_plane/*, src/tui/src/event_loop/*, src/tui/src/app_loop.rs
The hook command reads bounded payloads, creates sanitized summaries, reports through the control socket, and avoids dotenv loading. Shared logs flow into the control plane and TUI.
Hooks page management and display
src/tui/src/ui/app/hooks/*, src/tui/src/ui/app/render/routing/*, src/tui/src/ui/app/keys/routing/*, src/tui/tests/feature_workers/*
The TUI adds hook creation, editing, deletion, built-in toggling, session synchronization, coverage warnings, and recent report rendering.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested reviewers: sanil-23

Poem

I’m a rabbit with hooks in my ear,
Reporting each lifecycle hop loud and clear.
Grants bloom, then fade when runs are done,
Safe summaries hide payloads from the sun.
The TUI shows each event in view—
Hop, hop, review!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: lifecycle reporting for launched harnesses and a new Hooks page.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 00c9b95cfe

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tui/src/commands/hook.rs Outdated
Comment thread src/sdk/src/config/persist.rs Outdated
# Conflicts:
#	src/sdk/src/harness_hooks/README.md
#	src/tui/src/app_loop.rs
#	src/tui/src/event_loop/mod.rs
#	src/tui/src/event_loop/types.rs
#	src/tui/src/ui/app/commands/dispatch.rs
#	src/tui/src/ui/app/mod.rs
#	src/tui/src/ui/app/state.rs
#	src/tui/src/ui/app/types.rs

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 074b5cb4eb

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tui/src/ui/app/hooks/mod.rs Outdated
senamakel and others added 2 commits August 5, 2026 20:17
…eport with

The hook shim read MEDULLA_MCP_SOCKET/GRANT, which only ever reach the
MCP subprocess's own secret_env file, never the harness's own
environment the hook command inherits — so every built-in reporting
hook installed by default was inert on the normal PTY/CLI launch path
(chatgpt-codex-connector P1 on PR #192).

Mint a distinct hook-only grant per launch (Grant::hook_only,
MEDULLA_HOOK_SOCKET/GRANT), written straight into the harness's own
environment: the server's dispatch refuses every op but hook.report
for it, so leaking it to a subprocess the harness spawns can do
nothing but attribute a fabricated report to its own session. Minted
unconditionally in attach_mcp regardless of provider, override, or
whether the fleet grant was withheld, since hooks apply to every
provider and carry no fleet capability to protect.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
persist_hooks went through read_document/write_document directly,
which always parse and render TOML, so saving from the Hooks page
against a JSON config (medulla.tui.json, or an extensionless config
the loader treats as JSON) failed to parse the operator's document and
lost the edit (chatgpt-codex-connector P2 on PR #192).

Route it through persist_root_setting (now JSON-aware, like
persist_setting/persist_section already are) and a new
clear_root_setting for the empty-hooks-list case, backed by shared
read_json_document/write_json_document helpers.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3690a16867

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sdk/src/harness_hooks/builtin.rs
Comment thread src/sdk/src/harness_hooks/builtin.rs Outdated
The Hooks page saved through the app's general config_path, which
app_loop resolves to the highest-precedence discovered layer — the
project-local .medulla/config.toml or medulla.toml when one exists.
load_config strips [[hooks]] from exactly that layer on every
non-explicit load (project configuration must not authorize shell
commands in the operator's environment), so a hook saved there showed
"Hook saved" and applied for the rest of the session while the file
Medulla reads on the next launch never carried it
(chatgpt-codex-connector P2 on PR #192).

Give hook persistence its own App::hooks_config_path, defaulted to
config_path by set_config_path and overridden by app_loop to the
user-global config (or an explicit --config file, which load_config
never strips) whenever the two must differ. persist_hooks now targets
it and tells the operator when the save landed somewhere other than
the project's own config.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e47708f0d2

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tui/src/ui/app/hooks/mod.rs
…paths correctly

Two built-in-hook correctness bugs (chatgpt-codex-connector P2s on PR
#192):

- Every built-in serialized the same 5-second timeout regardless of
  event, but Codex's hook config refuses a SessionEnd handler whose
  declared timeout exceeds 3 seconds — so a default Codex launch got
  an unsupported hook definition for the one event it must report on
  exit. SessionEnd now declares 3s, matching the shim's own internal
  report budget.
- The built-in's command quoted the launching binary's path with
  POSIX single-quote escaping unconditionally, which is wrong on a
  native Windows launch where the command runs through cmd.exe/
  PowerShell rather than a POSIX shell. shell_quote now quotes for
  cfg!(windows) (double quotes, doubled embedded quotes), via a
  platform-parameterized shell_quote_for so both rules are covered by
  tests regardless of which CI runner executes them.

Does not attempt Codex's separate commandWindows override or Claude's
Git-Bash-vs-PowerShell distinction for arbitrary operator hook text —
this only ever quotes the running binary's own path, and going further
needs a real Windows harness to verify against.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e1039e08b2

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tui/src/commands/hook.rs Outdated
senamakel and others added 2 commits August 5, 2026 21:06
Saving or toggling a hook updated loaded.config.hooks, but LocalSessions.hooks
— the copy harness_pane::spawn::open_unmanaged actually reads when the
operator starts a harness from the Agents pane — was a separate clone taken
once at startup and never touched again. The status line claimed "applies to
harnesses started from now on" while a session opened before a restart kept
launching with the stale set: a newly added hook would not run, and a removed
one would keep running (chatgpt-codex-connector P2 on PR #192).

Added App::sync_local_sessions_hooks, called from both persist_hooks and
toggle_builtin_hooks, so the live launch state always matches what was just
saved. The fleet-dispatched task path (EmbeddedDaemonOptions.hooks, baked in
at host start) has the same staleness class but needs a materially larger
change — threading a shared, mutable hook config through daemon/embedded and
daemon/providers across ~24 existing construction sites — so it is called out
as a known follow-up rather than folded into this fix.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The shim's 3-second report budget only wrapped hook.report itself;
read_payload had already been allowed up to 500ms before it, so the worst
case (~3.5s) exceeded Codex's documented 3-second SessionEnd cap — the
harness would kill the shim outright instead of it dropping the report
quietly (chatgpt-codex-connector P2 on PR #192).

One deadline now covers the whole run: declared_timeout mirrors
harness_hooks::builtin's per-event value (3s for SessionEnd, 5s otherwise,
minus a fixed headroom), read_payload's own budget shrinks to whatever is
left of it, and the report is given whatever remains after that — so the
total can never exceed what the harness declared, for any event.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b093379a0e

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sdk/src/config/load.rs
… built-ins

Resolving the built-in reporting hooks at config load (85706f3 / this PR's
own dd27c79) put the medulla hook <Event> command in every loaded config,
but only the pty door (worker::pty::launch::attach_mcp) seeded the
MEDULLA_HOOK_SOCKET/MEDULLA_HOOK_GRANT environment that command needs to find
anything to report to. The headless one-shot executor
(daemon::providers::execute), the interactive session
(sessions::interactive), and the medulla <cli> wrapper installed the same
hooks and none of them seeded the grant, so every built-in on those doors
spawned, found nothing to report to, and exited — a wasted process per firing,
and PostToolUse fires once per tool call (chatgpt-codex-connector P2 on PR
#192, filed against dd27c79).

Chose to plumb the credential into every door rather than gate the built-ins
to the one door that already had it: control_socket::active() is the same
process-wide handle the ACP spawn path already reads without a registry
threaded through it, so every non-ACP door can mint a hook-only grant the same
way local_hook_grant already does for pty, at the cost of one seam per door
rather than a config change that would make the Hooks page lie about which
harnesses actually report.

Added harness_hooks::seed_hook_grant (in a new grant.rs, gated behind the
workflows feature the same way attach_mcp already is), a HookGrantGuard that
revokes the grant when it drops so a short-lived spawn does not leave a live
token in the registry, and wired it into execute.rs's headless run,
wrapper::run's child spawn (reusing the already-unique wrapper_session_id),
and InteractiveSession (stored on the struct so it outlives every turn, not
just open()). ACP dispatch remains unfixed by design: Medulla spawns an ACP
server that spawns the harness itself, so there is no argv to install either
the command or now the grant onto — already reported as a warning rather than
silently doing nothing.

Updated harness_hooks/README.md, builtin.rs's module docs, and the
'resolved at load' comment in config/load.rs so all three now say a
door needs both the installed command and a seeded grant, and that ACP
is the one door that gets neither.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcc7e16475

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tui/src/main.rs
@senamakel senamakel self-assigned this Aug 5, 2026
senamakel and others added 5 commits August 6, 2026 12:10
Add an accessor for the resolved `[[hooks]]` configuration so that a one-shot embedded daemon started elsewhere for the same session can install the same built-in and operator hooks, matching the behavior already provided for custom harnesses.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The command dispatcher now retrieves hooks from the local host spawner and forwards them to the workflow spawn function, enabling hooks to be available during workflow execution.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The workflow runner now receives the hooks configuration so that custom harness hooks can be applied during workflow execution. This enables the TUI to support the same hook functionality as the CLI when running workflows.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The workflow runner now receives the hooks configuration so it can apply harness hooks during workflow execution. This enables custom hooks to be triggered as part of the workflow lifecycle.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The one-shot daemon now receives the same lifecycle hooks as the session's primary host, matching the existing behavior for custom harnesses. This ensures the daemon does not start without the built-in and operator hooks it needs.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 47e924db66

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/tui/src/ui/app/render/routing/hooks.rs
senamakel and others added 3 commits August 6, 2026 12:34
Hook payloads can contain control characters that would be rendered directly into the operator's terminal, so the summary is now filtered to strip all control bytes before it becomes part of the report. This prevents terminal escape sequences from harness-supplied text from being interpreted as commands.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The doc comment on the `sanitize` function now points to the fully qualified `medulla::harness_hooks::HookReport::summary` type instead of the previously ambiguous local reference, clarifying where the sanitized text is used.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add tests asserting that control bytes in notification messages and tool names are stripped from the generated summaries, guarding against terminal escape sequences leaking through to the operator.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 11e32e5430

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sdk/src/control_socket/server/handle/hooks.rs
senamakel and others added 7 commits August 6, 2026 12:55
The hook report summary is now passed through the sanitizer before being truncated, ensuring that any control characters or unsafe content in the summary field are removed prior to storage. This prevents malformed or potentially harmful data from being persisted in the report.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
Strip control characters from caller-supplied hook report fields before recording them, since the hook shim is not the only path that can invoke `hook.report` — any subprocess with the grant can call it directly. This prevents terminal escape sequences from reaching the operator's terminal when summaries are rendered via `Span::raw`.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds tests for the control socket server's hook handling, covering the expected behavior of hook registration and invocation. This ensures the hook mechanism works correctly and guards against regressions.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test now verifies that the recorded summary is sanitized by checking it contains no control characters and matches the expected cleaned value, replacing the previous placeholder shadow.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
Added a test module declaration for the hooks file, gated behind the test configuration, so the existing hooks tests are compiled and run as part of the test suite.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
The test module now imports `RunError`, `TaskOutcome`, and `TaskRequest` from the `hub` module instead of the `types` module, reflecting the relocation of these types. This keeps the test imports aligned with the current type definitions.

Co-authored-by: Medulla <medulla@tinyhumans.ai>
Reformatted the summary assertion in the hook recording test to use a multi-line expression, improving code readability without changing the test's behavior.

Co-authored-by: Medulla <medulla@tinyhumans.ai>

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

senamakel has reached the 50-credit limit for trial accounts. To continue receiving code reviews, upgrade your plan.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d894c2b008

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/sdk/src/harness_hooks/types.rs
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.

1 participant