Add workspace affinity - #86
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c59ca8d2d
ℹ️ 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".
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
@codex review |
|
Codex Review: Didn't find any major issues. Nice work! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 906ef33eeb
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5f02d216c5
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce3eedd9ca
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 09978bb4de
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0abcc6e028
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eef0f54358
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 18678bfb14
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d6d8bae57a
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dd4e24fc90
ℹ️ 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".
| {...fieldError(errors, "workspaceAffinityKey")} | ||
| /> | ||
| <WarningAlert title="Workspace sharing, not session continuation"> | ||
| Each arrival creates a separate agent; runs can overlap in the same files. |
There was a problem hiding this comment.
Reject workspace affinity with agent continuation
When affinity is enabled on a conversational single-run trigger, the form still defaults continuation to conversation, so compileTriggerDocument attaches that policy and acquireAndSpawnAgentWithoutTimeout routes subsequent arrivals through AgentSessions, which reuses the existing agent instead of creating the separate agent promised here. Since later arrivals also skip daemon creation, their newer retainUntil values are never sent, allowing the workspace to expire under the first arrival's deadline. Require “New agent” continuity for affinity or implement explicit combined semantics instead of silently accepting this default combination.
AGENTS.md reference: AGENTS.md:L26-L26
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d87b1067ae
ℹ️ 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".
| async connectWithCredential( | ||
| hubOrigin: string, | ||
| credential: string, | ||
| permissions: readonly string[] = [], |
There was a problem hiding this comment.
Grant execution permission in workflow E2E connections
HubE2E.connect() calls this method without the new argument, so every source-built workflow suite—including both workspace-affinity-e2e matrix legs—now invokes paseo hub connect without --permission hub.execute. The CLI contract documented at docs/public-api.md:16 makes execution authority explicit, and src/configuration/store.ts:486-504 excludes a connected daemon lacking that permission; consequently configuration installation cannot resolve the daemon and these tests fail before exercising affinity. Keep the empty default for presence-only tests, but have the workflow harness pass ['hub.execute'].
AGENTS.md reference: AGENTS.md:L13-L14
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ff05ad36da
ℹ️ 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".
| const reply = await callMcp(this.hubMcp, 2, "tools/call", { | ||
| name: "reply", | ||
| arguments: { ...executionArgs, content: output }, | ||
| arguments: { content: output }, |
There was a problem hiding this comment.
Restore execution IDs in session MCP calls
In the continuation path exercised by src/e2e/hub-foundation.e2e.test.ts, AgentSessions supplies /agent-sessions/{sessionId}/mcp, whose tool schema in src/execution-capabilities/server.ts:69-81 requires an executionId. The fixture now derives the session UUID from that URL and omits executionId from these arguments, so the first reply is rejected and the later finish_execution cannot complete the run; restore the execution ID extraction from the injected Hub execution: prompt and pass it to session-scoped calls.
AGENTS.md reference: AGENTS.md:L13-L14
Useful? React with 👍 / 👎.
|
|
||
| async initialize() { | ||
| return { protocolVersion: sdk.PROTOCOL_VERSION, agentCapabilities: { loadSession: true } }; | ||
| return { protocolVersion: sdk.PROTOCOL_VERSION, agentCapabilities: { loadSession: false } }; |
There was a problem hiding this comment.
Keep loadSession support in the continuation fixture
When the required Hub source E2E archives the first conversation agent and dispatches the second arrival, the daemon must reload the persisted ACP session to reuse that agent and workspace. Advertising loadSession: false while removing the handler makes that restoration unavailable, so the continuation test cannot reach its same-agent assertion; retain the capability and handler, since the affinity test already requests new agents independently.
AGENTS.md reference: AGENTS.md:L13-L14
Useful? React with 👍 / 👎.
…260829 # Conflicts: # src/triggers/configuration/editor.ts
Summary
Add explicit, custom
workspace_affinity.keyrouting so related trigger arrivals can share checkout/files without sharing an agent session. Hub renders and persists the trusted key and workflow deadline; an optional daemon capability owns atomic workspace reuse, restoration, and expiry.Usage
In the trigger form, open Workspace affinity under Where it runs and enter a custom key. Empty disables reuse. The equivalent complete single-run trigger is:
The full workflow/bundle format uses the same
workspace_affinity: { key: ... }object on a step. Both authoring paths use the existing authority validator. Single-step startup migration now preserves the key in the supportedsingle_runrepresentation, with unchanged workflow/step deadlines and archive policy; multistep workflows still retain their lossless legacy lane.paseo.trigger.conversation_keycomes from authenticated provider routing: Slack connection/workspace/channel/root thread; Discord connection/guild/channel/thread or starter message; GitHub connection/repository/issue-or-PR/number; or Linear connection/organization/stable issue UUID. Linear exposes it forlinear.issue_entered_scope,linear.issue_assigned, andlinear.comment_created. Issue names, comment IDs, delivery IDs, and session IDs are not workspace identity. Unsupported events such asgithub.pushand manual triggers cannot use this expression.Keys can instead be literals or expressions composed from finite declared inputs, values, and outputs (values/step outputs belong to the full workflow format). Prompt text, ambient context, execution IDs, and unbounded values cannot select an existing workspace. Validation follows transitive named values; rendered keys preserve exact bytes and must be nonblank and 1–512 characters. The editor preserves surrounding whitespace and comments, rejects whitespace-only keys, and removes affinity only when explicitly cleared. A workflow-specific prefix keeps different workflows separate when desired.
Lifecycle and compatibility
max_runtimedeadline, including gaps after agents finish. Single-run triggers use top-levelmax_runtimeif authored, otherwiserun.max_runtime.idle_timeoutremains execution liveness, not workspace expiry between arrivals.auto_archive: true, finished agents archive while the workspace remains retained. At expiry, daemon-owned cleanup archives it when safe; unrelated agents prevent destructive cleanup. Withauto_archive: false, affinity introduces no workspace archival.Why daemon changes are necessary
The existing restricted
hub.executeAPI cannot select an arbitrary existing workspace or restore an archived one. Implementing that from Hub would require broader workspace authority and duplicate daemon-local lifecycle state. The daemon owns worktrees, workspace/agent registration, restoration, persistence, and archive safety. It must bind key-to-workspace atomically and exclude concurrent activation during destructive cleanup.The companion hashes keys before persistence and optionally acknowledges
workspaceAffinityApplied: true. Hub accepts both response shapes. Companion implementation and served public docs: getpaseo/paseo#3994, includingpublic-docs/hub/configuration/hub-yml.md.Integration and strategy
This update reconciles current main while preserving its provider-catalog baseline. CI independently pins the baseline daemon (
c16d4f14a3ec95485f37aa7fb6201b7c239d9d2a) and affinity-capable companion (bb3a46346c7e781bc963ffb2e0fdbd3f5ed3efa3). The new source-built matrix proves legacy fallback and capable retention/reuse/manual-archive restoration/key isolation, with separate agents. Normal browser/Hub integration tests stay on main's baseline. This avoids repeatedly coupling unrelated daemon changes to the unmerged affinity companion.Design re-review and scoped improvements:
24571b978fd4e205813e2696ba63b3cbe9714810: its context already includes connection/organization/issue. Keep workspace identity issue-scoped and Linear session ID as reply/stop identity. Follow up Linear triggers with Agent Sessions, team routing, and replies #88 still needs to enable its implemented session event names and test same-issue/different-session reuse with session-scoped replies/cancellation. This PR does not silently enable unimplemented session events or resume provider agents.Remaining separate work:
workspaceAffinityAppliedper execution. The optional acknowledgement is accepted on the wire but currently dropped; successful execution alone is not proof of reuse. Preserve an unconfirmed state after missing acknowledgement/reconnect.Validation
September 7 design follow-up, Linux:
The browser journey proves create → save/reload → unrelated edit → YAML → explicit removal without altering key bytes. Desktop and 390px phone-width screenshots are captured at
e2e/screenshots/triggers/affinity-{desktop,mobile}.png; fresh CI attaches them as workspace-affinity-editor. This tests browser layouts on Linux, not native mobile apps.The new complete public-doc YAML example was compiled against this Hub build. Companion follow-up is documentation-only (formatter + example validation); no Paseo runtime code or dependencies changed.
Local browser setup initially lacked the Playwright-pinned Chromium binary; installing that exact headless browser resolved the environment blocker. A new Linear test fixture initially omitted its mandatory project filter; corrected the fixture without changing production validation.
The authoring commit excludes only the known broken staged-file lint wrapper for root browser tests, after both full lint commands passed independently; formatting and full typecheck hooks remain enabled. The Linear follow-up uses normal hooks.
Previous reconciliation: 193 focused contract tests, both exact source-built daemon affinity journeys, and all 11 CI checks passed on
684716d7. Fresh CI validates this follow-up separately. The daemon compatibility implementation and immutable baseline/capable pins are unchanged.