Skip to content

Add safer Agent Orchestration and harden ask_user session handling#88

Merged
4regab merged 5 commits into
4regab:mainfrom
sgaabdu4:feature/agent-orchestration-ask-user-hardening
Apr 4, 2026
Merged

Add safer Agent Orchestration and harden ask_user session handling#88
4regab merged 5 commits into
4regab:mainfrom
sgaabdu4:feature/agent-orchestration-ask-user-hardening

Conversation

@sgaabdu4

@sgaabdu4 sgaabdu4 commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds a new Agent Orchestration setting and makes TaskSync safer when switching between multi-session mode and single-session mode.

When Agent Orchestration is on, TaskSync keeps separate sessions, the sessions list, session switching, and split view.

When Agent Orchestration is off, TaskSync works in one single-session lane for the workspace. It hides the sessions list, turns off split view, and routes every ask_user call into the active TaskSync session.

What changed

  • added tasksync.agentOrchestration and defaulted it to true
  • added the Agent Orchestration toggle to settings
  • hid multi-session UI when orchestration is off
  • limited split view to orchestration mode
  • enforced single-session routing in the provider instead of only hiding UI
  • always returned session_id in the ask_user payload
  • added structured directive payloads for bootstrap, cancelled, and rejected ask_user results
  • tightened bootstrap, superseded, and rejected ask_user messaging so the model stays in the ask_user loop
  • wired the setting through local UI, remote UI, and live VS Code config changes
  • lowered normal TaskSync trace logging from error-level to info-level
  • replaced the inline SVG select arrow with a CSP-safe CSS arrow

Safety changes

  • blocking disable no longer silently collapses waiting sessions into one hidden lane
  • the UI now shows a modal with Stop current session(s) and turn off Agent Orchestration
  • confirming that action cancels pending ask_user calls, marks those sessions terminated, and then disables orchestration
  • the backend keeps the same safety guard for remote actions and external config changes
  • single-session mode will not reuse a terminated session

Docs and release notes

  • updated the extension README
  • updated the root README
  • added the changelog entry for v3.0.10
  • bumped the extension version to 3.0.10

Testing

  • npm run validate

Validation passed:

  • build
  • typecheck
  • tests: 584 passed
  • lint
  • code-quality checks

Issues

Closes #87
Closes #86
Closes #85
Closes #84

Screenshots

image

Turned off:
image

Turned on:
image

When 2 sessions are running:
image

image

Copilot AI review requested due to automatic review settings April 3, 2026 09:51

Copilot AI 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.

Pull request overview

This PR introduces an “Agent Orchestration” setting to let TaskSync switch between multi-session orchestration and a safer single-session routing mode, while also hardening ask_user session handling and directives so Copilot stays in the tool loop.

Changes:

  • Add tasksync.agentOrchestration (default true) and wire it through VS Code settings, local webview UI, and remote clients.
  • Enforce single-session routing when orchestration is disabled (backend + UI), including safer handling of waiting/terminated sessions.
  • Harden ask_user tool results with always-present session_id plus structured directive payloads for bootstrap/cancelled/rejected flows.

Reviewed changes

Copilot reviewed 31 out of 32 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tasksync-chat/src/webview/webviewUtils.ts Switch debug logging from console.error to console.info.
tasksync-chat/src/webview/webviewTypes.ts Add AskUserDirective + new settings message fields/types.
tasksync-chat/src/webview/webviewProvider.ts Add orchestration flag, config-change handler, single-session routing helpers.
tasksync-chat/src/webview/webviewProvider.test.ts Add unit tests for single-session helpers + config change handling.
tasksync-chat/src/webview/toolCallHandler.ts Add directives to rejected/cancelled tool results; adjust deleted-ID behavior for single-session mode.
tasksync-chat/src/webview/toolCallHandler.test.ts Expand tests for directive payloads and single-session routing behavior.
tasksync-chat/src/webview/settingsHandlers.ts Load/persist orchestration setting; add safety guard + stop-and-disable handler.
tasksync-chat/src/webview/settingsHandlers.comprehensive.test.ts Comprehensive tests for orchestration setting + stop-and-disable flow.
tasksync-chat/src/webview/messageRouter.ts Route new orchestration messages from webview to handlers.
tasksync-chat/src/webview/messageRouter.test.ts Tests for routing orchestration-related messages.
tasksync-chat/src/webview-ui/state.js Add client-side orchestration state + visible-session helpers + split-view gating.
tasksync-chat/src/webview-ui/settings.js Add orchestration toggle UI logic + stop-and-disable action.
tasksync-chat/src/webview-ui/settings.test.ts Tests for orchestration toggle + modal confirm behavior.
tasksync-chat/src/webview-ui/rendering.js Hide/disable sessions list + split view controls when orchestration is off.
tasksync-chat/src/webview-ui/rendering.test.ts Update rendering harness expectations for orchestration gating.
tasksync-chat/src/webview-ui/messageHandler.js Apply orchestration setting updates and refresh sessions/welcome UI.
tasksync-chat/src/webview-ui/init.js Add disable-orchestration modal creation + settings modal toggle wiring.
tasksync-chat/src/webview-ui/events.js Prevent multi-session UI actions when orchestration is off; wire toggle events.
tasksync-chat/src/webview-ui/adapter.js Prevent remote session switching UI actions when orchestration is off.
tasksync-chat/src/tools.ts Always return session_id; add directive payload mapping for tool output.
tasksync-chat/src/tools.test.ts Tests for session_id always present + bootstrap directive behavior.
tasksync-chat/src/server/remoteSettingsHandler.ts Handle remote updateAgentOrchestrationSetting.
tasksync-chat/src/server/remoteSettingsHandler.test.ts Add test coverage for remote orchestration setting updates.
tasksync-chat/src/server/remoteServer.ts Remote debug logging uses console.info instead of console.error.
tasksync-chat/src/constants/remoteConstants.ts Update superseded ask_user message to stronger tool-loop wording.
tasksync-chat/README.md Document Agent Orchestration setting and behavior.
README.md Mention orchestration toggle as a top-level feature.
tasksync-chat/package.json Bump version; contribute setting; gate split-view command on config.
tasksync-chat/package-lock.json Lockfile version bump to 3.0.10.
tasksync-chat/media/webview.js Update bundled webview JS to include orchestration behavior.
tasksync-chat/media/main.css Replace inline SVG select arrow with CSP-safe CSS arrow.
CHANGELOG.md Add v3.0.10 release notes entry.
Files not reviewed (1)
  • tasksync-chat/package-lock.json: Language not supported

Comment thread tasksync-chat/src/server/remoteSettingsHandler.ts
@sgaabdu4

sgaabdu4 commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator Author

@4regab ready for your review now

@4regab 4regab requested a review from n-r-w April 3, 2026 11:01
@4regab

4regab commented Apr 3, 2026

Copy link
Copy Markdown
Owner

LGTM. Just a suggestion could we maybe remove this title when orchestration is off?
image

@4regab

4regab commented Apr 3, 2026

Copy link
Copy Markdown
Owner

Also this feels redundant when on single session mode
image

@sgaabdu4

sgaabdu4 commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator Author

@4regab Yeah, it is a bit redundant in single-session mode. I left session_id in place so the ask_user contract stays stable across both modes... That way if the user turns Agent Orchestration back on later, we do not change the payload shape or risk breaking the next ask_user call path?

@4regab

4regab commented Apr 3, 2026

Copy link
Copy Markdown
Owner

Got it, that clears things up on my end. Curious to see what @n-r-w has in mind for this PR

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

I'd like to point out that I didn't notice any performance changes at all after implementing multi-session. But I have a MacBook Pro m4 max.

@4regab

4regab commented Apr 3, 2026

Copy link
Copy Markdown
Owner

I'd like to point out that I didn't notice any performance changes at all after implementing multi-session.

Same here

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Review in progress

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Review Results: PR #88 - Add safer Agent Orchestration and harden ask_user session handling

Diff scope only: origin/main...HEAD. Out of scope: unchanged code except where it was needed to verify changed behavior.

Summary

Outcome: 🔄 Request changes

  • FND-001: A rejected external disable of tasksync.agentOrchestration still runs singleton-collapse side effects first.
  • FND-002: Single-session mode removes session_id as a real isolation boundary, so stale chats can re-enter the live singleton after reset, fresh-chat, and stop-and-disable flows.
  • FND-003: Singleton collapse does not send a full remote state refresh, so remote clients can keep stale history or pending state.
  • FND-004: The new remote orchestration messages send duplicate settingsChanged broadcasts.

Findings

Major

  • ⚠️ FND-001

    • Severity: Major
    • Location: loadSettings(), _handleConfigurationChange(), _getSingleSession(), _syncActiveSessionState(), _updateSessionsUI(), local updateSettings handling in messageHandler.js, remote updateSessions handling in adapter.js
    • Issue: An external config change can set agentOrchestration=false, and the provider reload path immediately calls _getSingleSession() before it checks whether disabling orchestration must be rejected. When _getSingleSession() picks a different waiting session, it switches the active session, syncs local UI state, posts updateSettings to the local webview, broadcasts updateSessions to remote clients, and saves sessions to disk. Only after that does _handleConfigurationChange() show the warning and restore the setting.
    • Impact: The “reject unsafe disable” path is not side-effect free. Even though the final setting ends up back at true, the active session can already change, local split view can be cleared, and remote clients can already receive a different active session in updateSessions.
    • Recommendation: Validate the multi-waiting precondition before _loadSettings() can collapse sessions, or make loadSettings() side-effect free during config refresh. Add a regression test that uses the real _loadSettings() path instead of stubbing it.
    • Verification: The existing revert test stubs _loadSettings() in webviewProvider.test.ts, so it does not cover the real singleton-collapse behavior.
  • ⚠️ FND-002

    • Severity: Major
    • Location: startNewSessionAndResetCopilotChat(), startNewSession(), cancelPendingToolCall(), askUser(), waitForUserResponse(), _bindSession(), stale-id tests in toolCallHandler.test.ts and webviewProvider.test.ts
    • Issue: In single-session mode, the new routing discards the caller's session_id and always binds to the current singleton. Fresh-chat reset reuses the same TaskSync session id. User-triggered cancellation paths return a normal cancelled result instead of a hard rejection, and askUser() intentionally keeps the tool loop alive for cancelled results. waitForUserResponse() skips the deleted-session barrier when orchestration is off, so stale chats reach _bindSession() before any stale-id rejection can fire.
    • Impact: An older Copilot chat can call ask_user again after reset, fresh chat, or stop-and-disable and get rebound into the live singleton session. That breaks session isolation exactly in the safety flows this PR adds. The same single-session branch also runs before stopCurrentSession is handled, so that option is effectively ignored when orchestration is off.
    • Recommendation: Add a hard stale-chat barrier in single-session mode. Examples: a generation token, a tombstone that survives singleton reuse, or a rejected directive that is enforced before _bindSession() discards the caller id. Also ensure stopCurrentSession semantics are still honored in the single-session branch.
    • Verification: The added tests explicitly expect stale explicit session_id values to bind to the singleton when orchestration is off.
  • ⚠️ FND-003

    • Severity: Major
    • Location: _setActiveSession(), _getSingleSession(), handleUpdateAgentOrchestrationSetting(), remote settingsChanged and updateSessions handling in adapter.js, full-state refresh in applyServerState()
    • Issue: The normal multi-session switch path broadcasts a full remote state refresh after a successful switch. The new singleton-collapse path does not. _getSingleSession() only syncs local state, updates session summaries, and saves to disk. handleUpdateAgentOrchestrationSetting(false) relies on that path and still only sends updateSettings, sendSessionSettingsToWebview, _updateSessionsUI(), and settingsChanged.
    • Impact: After disabling orchestration or after any singleton reselection, a remote client can show the new active singleton in the sessions list while the main panel still renders the old session's history, pending prompt, or timer state.
    • Recommendation: Broadcast a full remote state refresh whenever _getSingleSession() changes or creates the active session, or route singleton collapse through the same state-broadcast path used by _setActiveSession().
    • Verification: _getSingleSession() updates session summaries but does not broadcast remote state; the remote client refreshes full history, pending state, and timer data only from state, not from updateSessions or settingsChanged.

Minor

  • ℹ️ FND-004
    • Severity: Minor
    • Location: handleUpdateAgentOrchestrationSetting(), handleStopSessionsAndDisableAgentOrchestration(), dispatchSettingsMessage(), broadcast wiring in remoteServer.ts and remoteServer.ts
    • Issue: The underlying orchestration handlers already call broadcastAllSettingsToRemote(), but the new remote dispatcher branches also call broadcastSettingsChanged() for the same messages.
    • Impact: Remote clients receive the same settingsChanged payload twice for one orchestration action, so the same remote settings update is applied redundantly.
    • Recommendation: Keep exactly one remote settingsChanged broadcast layer for the new orchestration messages and add a regression test that asserts a single send.
    • Verification: This duplication happens in the live remote-server path, not only in isolated unit tests.

Assumptions

  • None.

Open Questions

  • None.

Next Steps

  • NXT-001: Fix FND-001 before merge so rejected external disables do not mutate active-session state first.
  • NXT-002: Fix FND-002 before merge so stale chats cannot re-enter the live singleton and stopCurrentSession still means stop.
  • NXT-003: Fix FND-003 before merge so remote clients receive a full state refresh when singleton collapse changes the active session.
  • NXT-004: Fix FND-004 in the same PR or add a targeted follow-up immediately after merge.

References

@4regab

4regab commented Apr 3, 2026

Copy link
Copy Markdown
Owner

If you want @n-r-w we can use your code-review instructions and add it to this repo so that copilot code review will use it automatically

@sgaabdu4

sgaabdu4 commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator Author

Ooh, I'm out atm so won't be able to work on this until tomorrow, feel free to pick it up!

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

If you want @n-r-w we can use your code-review instructions and add it to this repo so that copilot code review will use it automatically

I have a complex review pipeline with a ton of rules and subagents, so I can't transfer it to the repository instructions.

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Ooh, I'm out atm so won't be able to work on this until tomorrow, feel free to pick it up!

I can fix this, but I'm not sure if I have the rights, since the branch is in the repository https://github.com/sgaabdu4/TaskSync

@4regab

4regab commented Apr 3, 2026

Copy link
Copy Markdown
Owner

but I'm not sure if I have the rights, since the branch is in the repository https://github.com/sgaabdu4/TaskSync

You should be able to add commits in this PR, just git remote his repo and fetch then checkout this PR

image

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Additionally, I have various mcp for coordinating subagents and symbolic analysis of the code base, which greatly improves the efficiency of the analysis.

Would love to try it out if it's public

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Additionally, I have various mcp for coordinating subagents and symbolic analysis of the code base, which greatly improves the efficiency of the analysis.

Would love to try it out if it's public

Coordination is available at https://github.com/n-r-w/team-mcp. It's important to separate tool permissions between the main agent and subagents, as specified in the README.

Symbolic search.
Previously, I used https://github.com/oraios/serena, but it's a very heavyweight project that requires initializing each repository, contains a nasty system prompt that needs to be fixed with custom settings, etc. However, only three of its tools are useful: get_symbols_overview, find_symbol, find_referencing_symbols

I've now created my own lightweight version exclusively for symbolic search and without the need for initialization, but it's currently privately accessible while I'm testing it.
I think I'll make it public this weekend.

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Fix in progress

@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

Another bug:
When the Settings modal is opened from the chat list, the first click on Agent Orchestration partially applies the change: the UI switches from the chat list to a single chat, but a redundant stale settings update immediately restores the toggle state. As a result, the first click appears to do nothing even though the view has already changed.

… session flow

- Implements the fixes identified in the PR 4regab#88 review and resolves several related regressions beyond `pr-88-code-review.md`.
- Makes configuration reloads side-effect free before collapsing to single-session mode.
- Prevents stale, deleted, or terminated `ask_user` session IDs from reattaching to the live singleton session.
- Restores correct `stopCurrentSession` behavior when starting a fresh chat in single-session mode.
- Ensures remote clients receive a full state refresh when the active singleton changes.
- Removes duplicate remote `settingsChanged` broadcasts for agent orchestration actions.
- Improves dialog UX and accessibility by focusing modals on open, restoring focus on close, and handling `Escape` consistently.
- Brings the TaskSync view to the foreground before opening dialogs and includes small UI polish updates.
- Adds regression tests for stale-session recovery, remote settings broadcasts, modal focus handling, and session action flows.
@n-r-w

n-r-w commented Apr 3, 2026

Copy link
Copy Markdown
Collaborator

fix(ui,settings,session): improve dialog handling, settings sync, and session flow

  • Implements the fixes identified in the PR Add safer Agent Orchestration and harden ask_user session handling #88 review and resolves several related regressions beyond pr-88-code-review.md.
  • Makes configuration reloads side-effect free before collapsing to single-session mode.
  • Prevents stale, deleted, or terminated ask_user session IDs from reattaching to the live singleton session.
  • Restores correct stopCurrentSession behavior when starting a fresh chat in single-session mode.
  • Ensures remote clients receive a full state refresh when the active singleton changes.
  • Removes duplicate remote settingsChanged broadcasts for agent orchestration actions.
  • Improves dialog UX and accessibility by focusing modals on open, restoring focus on close, and handling Escape consistently.
  • Brings the TaskSync view to the foreground before opening dialogs and includes small UI polish updates.
  • Adds regression tests for stale-session recovery, remote settings broadcasts, modal focus handling, and session action flows.

@n-r-w n-r-w requested a review from 4regab April 3, 2026 21:46

Copilot AI 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.

Pull request overview

Copilot reviewed 37 out of 38 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • tasksync-chat/package-lock.json: Language not supported

Comment thread tasksync-chat/src/webview/toolCallHandler.ts
Comment thread tasksync-chat/media/main.css
…g focus tests

- Add "stale_session_id" as a directive reason for single-session recovery
- Update CSS to clarify focus handling for history modal overlays
- Enhance unit tests to verify dialog and overlay focus visibility and directive handling
@4regab 4regab merged commit 87a26ca into 4regab:main Apr 4, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants