Skip to content

feat: tower wake steering, prompt hook folding, WaitFor cap, sticky fullscreen messages - #339

Merged
elkaix merged 9 commits into
mainfrom
fix/reconcile-2026-10-01
Oct 1, 2026
Merged

elkaix merged 9 commits into
mainfrom
fix/reconcile-2026-10-01

Conversation

@elkaix

@elkaix elkaix commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Requirement or Bug

Land a batch of agent-experience behavior changes: tower wake steering and safer tower operations, prompt hook-output folding, a shorter WaitFor cap, and sticky fullscreen user messages.

Bug Reproduction Steps

N/A

Root Cause

N/A

Code Changes

  • Engine (packages/agent-core-v2): WaitFor caps at 90 seconds and a newly sent message ends the wait early; UserPromptSubmit hook output folds into the prompt message as meta-marked content parts (annotate-then-filter keeps legacy wires readable); tower wake turns abort on user input; tower teardown gains keep-live worktrees, exclude, and dry_run; the tower store serializes across processes and writes atomically; tower workers must check their inbox before completing a mission.
  • Transcript / gateway: transcript grouping and cold-load mode state follow the folded parts; prompts API exposes the folded shape.
  • TUI (apps/pythinker-code): sticky user message pinned above the transcript in fullscreen (TranscriptView + gutter pill + layout effects in the vendored TUI); wait renderer gains an "interrupted" state; user message bullet is now ❯ with wrap-aware line heights.
  • VS Code: replay adapter and hook-part helpers understand the folded parts.

Behavior Changes and Affected Users

Behavior Before After Who relies on the old behavior Escape hatch
WaitFor timeout cap up to 600s capped at 90s agents (or scripts prompting agents) that issued multi-minute waits none — the changeset names the cap
Ending a WaitFor wait early Ctrl-S only sending a message with Enter also steers it in and ends the wait; queued shell commands or skills keep the queue until the turn ends users who queued commands expecting the agent to stay waiting none; queued non-message work still waits
Tower wake turns a message sent during a wake turn queued behind it the message aborts the wake turn and runs as its own turn tower users relying on undisturbed wake turns tower mode is experimental ([experimental] tower = true)
Tower teardown forced teardown could remove worktrees of live agents keeps worktrees of live agents even when forced; supports exclude and dry_run tower users scripting teardown the new options control the behavior
User message bullet ✨ ❯ users matching the old glyph in scripts or themes themes and keybindings unaffected; the glyph only changes rendered output
Hook output in the transcript standalone hook_result user message folded into the prompt message as marked content parts (one prompt = one user message) transcript consumers: SDK callers, desktop/web replay, VS Code adapter — updated in the same change; external raw-wire parsers see meta-marked parts none

Affected modules and coverage per row: engine wait/hook/tower changes carry unit and contract tests (test/agent/loop, test/agent/task, test/features/tower, test/features/externalHooks); transcript folding is covered by the packages/transcript and gateway transcript/prompt suites; TUI behavior by component and message-flow tests; VS Code by replay-adapter tests.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue (external PRs: the issue must have a maintainer's /approve).
  • I have added tests that prove my feature works.
  • The behavior-change table above is complete, and every removed behavior or flipped default is named in the changeset and either has an escape hatch or was explicitly approved by a maintainer in this PR.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 107 files, which is 7 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Repository: PyModel/pythinker-code/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 1372178f-58a7-4d68-a959-114e18c98ccd

📥 Commits

Reviewing files that changed from the base of the PR and between 7fe5adf and 6a6c757.

📒 Files selected for processing (107)
  • .agents/skills/gen-changesets/SKILL.md
  • .agents/skills/review-pr/SKILL.md
  • .agents/skills/review-pr/surfaces.md
  • .agents/skills/write-pr/SKILL.md
  • .changeset/hook-prompt-fold.md
  • .changeset/shorter-wait-for.md
  • .changeset/sticky-user-messages.md
  • .changeset/tower-ops-hardening.md
  • .changeset/tower-wake-steer.md
  • .github/pull_request_template.md
  • AGENTS.md
  • apps/pythinker-code/dist-web/.web-bundle-manifest.json
  • apps/pythinker-code/src/tui/components/chrome/gutter-container.ts
  • apps/pythinker-code/src/tui/components/messages/sticky-user-message.ts
  • apps/pythinker-code/src/tui/components/messages/tool-renderers/wait-for.ts
  • apps/pythinker-code/src/tui/components/messages/transcript-view.ts
  • apps/pythinker-code/src/tui/components/messages/user-message.ts
  • apps/pythinker-code/src/tui/constant/symbols.ts
  • apps/pythinker-code/src/tui/controllers/editor-keyboard.ts
  • apps/pythinker-code/src/tui/controllers/session-event-handler.ts
  • apps/pythinker-code/src/tui/controllers/session-replay.ts
  • apps/pythinker-code/src/tui/controllers/staging-leases.ts
  • apps/pythinker-code/src/tui/controllers/streaming-ui.ts
  • apps/pythinker-code/src/tui/pythinker-tui.ts
  • apps/pythinker-code/src/tui/tui-state.ts
  • apps/pythinker-code/src/tui/types.ts
  • apps/pythinker-code/src/tui/utils/export-markdown.ts
  • apps/pythinker-code/src/tui/utils/message-replay.ts
  • apps/pythinker-code/src/tui/utils/sticky-user-message.ts
  • apps/pythinker-code/test/tui/components/chrome/gutter-container.test.ts
  • apps/pythinker-code/test/tui/components/messages/sticky-user-message.test.ts
  • apps/pythinker-code/test/tui/components/messages/tool-call.test.ts
  • apps/pythinker-code/test/tui/components/messages/user-message.test.ts
  • apps/pythinker-code/test/tui/controllers/editor-keyboard.test.ts
  • apps/pythinker-code/test/tui/controllers/staging-leases.test.ts
  • apps/pythinker-code/test/tui/create-tui-state.test.ts
  • apps/pythinker-code/test/tui/export-markdown.test.ts
  • apps/pythinker-code/test/tui/fullscreen-layout.test.ts
  • apps/pythinker-code/test/tui/message-replay.test.ts
  • apps/pythinker-code/test/tui/pythinker-tui-message-flow.test.ts
  • apps/pythinker-code/test/tui/utils/sticky-user-message.test.ts
  • apps/vscode/src/runtime/replay-adapter.ts
  • apps/vscode/src/utils/hook-parts.ts
  • apps/vscode/src/utils/session-context.ts
  • apps/vscode/test/replay-adapter.test.ts
  • docs/guides/interaction.md
  • docs/reference/tools.md
  • packages/agent-core-v2/docs/state-manifest.d.ts
  • packages/agent-core-v2/src/agent/contextMemory/compactionHandoff.ts
  • packages/agent-core-v2/src/agent/contextMemory/hookParts.ts
  • packages/agent-core-v2/src/agent/loop/loop.ts
  • packages/agent-core-v2/src/agent/loop/loopService.ts
  • packages/agent-core-v2/src/agent/loop/turnEvents.ts
  • packages/agent-core-v2/src/agent/tools/task/task-wait/task-wait-subagent.md
  • packages/agent-core-v2/src/agent/tools/task/task-wait/task-wait.md
  • packages/agent-core-v2/src/agent/tools/task/task-wait/task-wait.ts
  • packages/agent-core-v2/src/agent/tools/task/task-wait/taskWaitTool.ts
  • packages/agent-core-v2/src/agent/undo/undoService.ts
  • packages/agent-core-v2/src/features/externalHooks/agent/agentExternalHooksService.ts
  • packages/agent-core-v2/src/features/externalHooks/internal/userPrompt.ts
  • packages/agent-core-v2/src/features/skill/skillService.ts
  • packages/agent-core-v2/src/features/tower/injection/tower-mode-full-reminder.md
  • packages/agent-core-v2/src/features/tower/protocol/store.ts
  • packages/agent-core-v2/src/features/tower/protocol/types.ts
  • packages/agent-core-v2/src/features/tower/tools/inbox/inbox.md
  • packages/agent-core-v2/src/features/tower/tools/inbox/inboxTool.ts
  • packages/agent-core-v2/src/features/tower/tools/mission/mission.md
  • packages/agent-core-v2/src/features/tower/tools/spawn/spawnTool.ts
  • packages/agent-core-v2/src/features/tower/tools/status/statusTool.ts
  • packages/agent-core-v2/src/features/tower/tools/teardown/teardown.md
  • packages/agent-core-v2/src/features/tower/tools/teardown/teardown.ts
  • packages/agent-core-v2/src/features/tower/tools/teardown/teardownTool.ts
  • packages/agent-core-v2/src/features/tower/towerService.ts
  • packages/agent-core-v2/src/human/agent/historySchema.ts
  • packages/agent-core-v2/src/human/agent/origin.ts
  • packages/agent-core-v2/src/human/llm/message.ts
  • packages/agent-core-v2/src/human/test/agent/machine.test.ts
  • packages/agent-core-v2/src/session/sessionTitle/agentTitlePromptSourceService.ts
  • packages/agent-core-v2/src/workspace/sessionLifecycle/internal/forkTurnSlice.ts
  • packages/agent-core-v2/test/agent/contextMemory/context.test.ts
  • packages/agent-core-v2/test/agent/loop/loop.test.ts
  • packages/agent-core-v2/test/agent/prompt/promptService.test.ts
  • packages/agent-core-v2/test/agent/task/taskService.test.ts
  • packages/agent-core-v2/test/agent/task/tools/task-tools.test.ts
  • packages/agent-core-v2/test/agent/undo/undo.test.ts
  • packages/agent-core-v2/test/features/externalHooks/integration.test.ts
  • packages/agent-core-v2/test/features/externalHooks/runner.test.ts
  • packages/agent-core-v2/test/features/goal/goal.test.ts
  • packages/agent-core-v2/test/features/goal/stubs.ts
  • packages/agent-core-v2/test/features/tower/store.test.ts
  • packages/agent-core-v2/test/features/tower/tools/spawnTool.test.ts
  • packages/agent-core-v2/test/features/tower/tools/towerTools.test.ts
  • packages/agent-core-v2/test/features/tower/towerService.test.ts
  • packages/agent-gateway/src/routes/prompts.ts
  • packages/agent-gateway/src/services/transcript/coreEventMap.ts
  • packages/agent-gateway/src/services/transcript/transcriptService.ts
  • packages/agent-gateway/test/modelCatalogCatalog.test.ts
  • packages/agent-gateway/test/prompts.test.ts
  • packages/agent-gateway/test/services/transcript.test.ts
  • packages/pi-tui/UPSTREAM.md
  • packages/pi-tui/src/index.ts
  • packages/pi-tui/src/tui-alt-screen.ts
  • packages/pi-tui/src/tui.ts
  • packages/pi-tui/test/layout.test.ts
  • packages/pi-tui/test/tui-alt-screen.test.ts
  • packages/transcript/src/history/groupTurns.ts
  • packages/transcript/test/layers.test.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@pkg-pr-new

pkg-pr-new Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@pymodel/pythinker-code@6a6c757
npx https://pkg.pr.new/@pymodel/pythinker-code@6a6c757

commit: 6a6c757

Comment thread apps/pythinker-code/test/tui/fullscreen-layout.test.ts Fixed
@elkaix
elkaix merged commit 78fd037 into main Oct 1, 2026
25 checks passed
@elkaix
elkaix deleted the fix/reconcile-2026-10-01 branch October 1, 2026 16:22
elkaix pushed a commit that referenced this pull request Oct 1, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @pymodel/pythinker-code@2.4.0

### Minor Changes

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Let a new message
interrupt a running tower wake turn and run as its own turn. Enable
tower mode with `[experimental] tower = true`.

### Patch Changes

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Fold hook output into
your prompt message so one prompt always produces exactly one user
message in the transcript.

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Cap WaitFor at 90
seconds; sending a message with Enter ends the wait early and steers it
into the turn.

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Pin your latest message
above the transcript in fullscreen mode and render user messages with a
❯ bullet.

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Make tower teardown safer
around live agents and persist tower state atomically.
## @pymodel/pythinker-desktop@1.5.0

### Minor Changes

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Let a new message
interrupt a running tower wake turn and run as its own turn. Enable
tower mode with `[experimental] tower = true`.

### Patch Changes

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Fold hook output into
your prompt message so one prompt always produces exactly one user
message in the transcript.

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Cap WaitFor at 90
seconds; sending a message with Enter ends the wait early and steers it
into the turn.

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Pin your latest message
above the transcript in fullscreen mode and render user messages with a
❯ bullet.

- [#339](#339)
[`78fd037`](78fd037)
Thanks [@elkaix](https://github.com/elkaix)! - Make tower teardown safer
around live agents and persist tower state atomically.

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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