more docs on workspace strategy'

This commit is contained in:
Dotta 2026-03-10 14:49:53 -05:00
parent 98b0e2fca1
commit b754752164

View file

@ -88,6 +88,613 @@ It also avoids forcing a host-filesystem model onto cloud agents. A cloud adapte
- create an isolated branch/workspace inside the provider's remote environment
- ignore local-only fields like host cwd while still honoring branch/ref/isolation intent
## Product and UX Requirements
The current technical model is directionally right, but the product surface needs clearer separation between:
- the generic cross-adapter concept of an **execution workspace**
- the user-visible local-git implementation concept of an **isolated issue checkout**
- the specific git implementation detail of a **git worktree**
Those should not be collapsed into one label in the UI.
### Terminology recommendation
For product/UI copy:
- use **execution workspace** for the generic cross-adapter concept
- use **isolated issue checkout** for the user-facing feature when we want to say "this issue gets its own branch/checkout"
- reserve **git worktree** for advanced or implementation detail views
That gives Paperclip room to support:
- local git worktrees
- remote sandbox checkouts
- adapter-managed remote workspaces
without teaching users that "workspace" always means "git worktree on my machine".
### Project-level defaults should drive the feature
The main place this should be configured is the **project**, not the agent form.
Reasoning:
- whether a repo/project wants isolated issue checkouts is primarily a project workflow decision
- most operators do not want to configure runtime JSON per agent
- agents should inherit the project's workspace policy unless there is a strong adapter-specific override
- the board needs a place to express repo workflow defaults such as branching, PRs, cleanup, and preview lifecycle
So the project should own a setting like:
- `isolatedIssueCheckouts.enabled` or equivalent
and that should be the default driver for new issues in that project.
### Issue-level use should stay optional
Even when a project supports isolated issue checkouts, not every issue should be forced into one.
Examples:
- a small fix may be fine in the main project workspace
- an operator may want to work directly on a long-lived branch
- a board user may want to create a task without paying the setup/cleanup overhead
So the model should be:
- project defines whether isolated issue checkouts are available and what the defaults are
- each issue can opt in or out when created
- the default issue value can be inherited from the project
This should not require showing advanced adapter config in normal issue creation flows.
### Runtime services should usually be hidden from the agent form
The current raw runtime service JSON is too low-level as a primary UI for most local agents.
For `claude_local` and `codex_local`, the likely desired behavior is:
- Paperclip handles workspace runtime services under the hood using project/workspace policy
- operators do not need to hand-author generic runtime JSON in the agent form
- if a provider-specific adapter later needs richer runtime configuration, give it a purpose-built UI rather than generic JSON by default
So the UI recommendation is:
- keep runtime service JSON out of the default local-agent editing experience
- allow it only behind an advanced section or adapter-specific expert mode
- move the common workflow settings up to project-level workspace automation settings
### Pull request workflow needs explicit ownership and approval rules
Once Paperclip is creating isolated issue checkouts, it is implicitly touching a bigger workflow:
- branch creation
- runtime service start/stop
- commit and push
- PR creation
- cleanup after merge or abandonment
That means the product needs an explicit model for **who owns PR creation and merge readiness**.
At minimum there are two valid modes:
- agent-managed PR creation
- approval-gated PR creation
And likely three distinct decision points:
1. should the agent commit automatically?
2. should the agent open the PR automatically?
3. does opening or marking-ready require board approval?
Those should not be buried inside adapter prompts. They are workflow policy.
### Human operator workflows are different from issue-isolation workflows
A human operator may want a long-lived personal integration branch such as `dotta` and may not want every task to create a new branch/workspace dance.
That is a legitimate workflow and should be supported directly.
So Paperclip should distinguish:
- **isolated issue checkout workflows**: optimized for agent parallelism and issue-scoped isolation
- **personal branch workflows**: optimized for a human or operator making multiple related changes on a long-lived branch and creating PRs back to the main branch when convenient
This implies:
- isolated issue checkouts should be optional even when available
- project workflow settings should support a "use base branch directly" or "use preferred operator branch" path
- PR policy should not assume that every unit of work maps 1:1 to a new branch or PR
## Recommended UX Model
### 1. Project-level "Execution Workspace" settings
Projects should have a dedicated settings area for workspace automation.
Suggested structure:
- `Execution Workspaces`
- `Enable isolated issue checkouts`
- `Default for new issues`
- `Checkout implementation`
- `Branch and PR behavior`
- `Runtime services`
- `Cleanup behavior`
For a local git-backed project, the visible language can be more concrete:
- `Enable isolated issue checkouts`
- `Implementation: Git worktree`
For remote or adapter-managed projects, the same section can instead say:
- `Implementation: Adapter-managed workspace`
### 2. Issue creation should expose a simple opt-in
When creating an issue inside a project with execution workspace support enabled:
- show a checkbox or toggle such as `Use isolated issue checkout`
- default it from the project setting
- hide advanced workspace controls unless the operator has expanded an advanced section
If the project does not support execution workspaces, do not show the control at all.
This keeps the default UI light while preserving control.
### 3. Agent configuration should be mostly inheritance-based
The agent form should not be the primary place where operators assemble worktree/runtime policy for common local agents.
Instead:
- local coding agents inherit the project's execution workspace policy
- the agent form only exposes an override when truly necessary
- raw JSON config is advanced-only
That means the common case becomes:
- configure the project once
- assign a local coding agent
- create issues with optional isolated checkout behavior
### 4. Advanced implementation detail can still exist
There should still be an advanced view for power users that shows:
- execution workspace strategy payload
- runtime service intent payload
- adapter-specific overrides
But that should be treated like an expert/debugging surface, not the default mental model.
## Recommended Workflow Policy Model
### Workspace realization policy
Suggested policy values:
- `shared_project_workspace`
- `isolated_issue_checkout`
- `adapter_managed_isolated_workspace`
For local git projects, `isolated_issue_checkout` may map to `git_worktree`.
### Branch policy
Suggested project-level branch policy fields:
- `baseBranch`
- `branchMode`: `issue_scoped | operator_branch | project_primary`
- `branchTemplate` for issue-scoped branches
- `operatorPreferredBranch` for human/operator workflows
This allows:
- strict issue branches for agents
- long-lived personal branches for humans
- direct use of the project primary workspace when desired
### Pull request policy
Suggested project-level PR policy fields:
- `prMode`: `none | agent_may_open | agent_auto_open | approval_required`
- `autoPushOnDone`: boolean
- `requireApprovalBeforeOpen`: boolean
- `requireApprovalBeforeReady`: boolean
- `defaultBaseBranch`
This keeps PR behavior explicit and governable.
### Cleanup policy
Suggested project-level cleanup fields:
- `stopRuntimeServicesOnDone`
- `removeIsolatedCheckoutOnDone`
- `removeIsolatedCheckoutOnMerged`
- `deleteIssueBranchOnMerged`
- `retainFailedWorkspaceForInspection`
These matter because workspace automation is not just setup. The cleanup path is part of the product.
## Design Recommendations for the Current UI Problem
Based on the concerns above, the UI should change in these ways:
### Agent UI
- remove generic runtime service JSON from the default local-agent configuration surface
- keep raw workspace/runtime JSON behind advanced settings only
- prefer inheritance from project settings for `claude_local` and `codex_local`
- only add adapter-specific runtime UI when an adapter truly needs settings that Paperclip cannot infer
### Project UI
- add a project-level execution workspace settings section
- allow enabling isolated issue checkouts for that project
- store default issue behavior there
- expose branch, PR, runtime service, and cleanup defaults there
### Issue creation UI
- only show `Use isolated issue checkout` when the project has execution workspace support enabled
- keep it as an issue-level opt-in/out, defaulted from the project
- hide advanced execution workspace details unless requested
## Consequences for the Spec
This changes the emphasis of the plan in a useful way:
- the project becomes the main workflow configuration owner
- the issue becomes the unit of opt-in/out for isolated checkout behavior
- the agent becomes an executor that usually inherits the workflow policy
- raw runtime JSON becomes an advanced/internal representation, not the main UX
It also clarifies that PR creation and cleanup are not optional side notes. They are core parts of the workspace automation product surface.
## Concrete Integration Checklist
This section turns the product requirements above into a concrete implementation plan for the current codebase.
### Guiding precedence rule
The runtime decision order should become:
1. issue-level execution workspace override
2. project-level execution workspace policy
3. agent-level adapter override
4. current default behavior
That is the key architectural change. Today the implementation is too agent-config-centered for the desired UX.
## Proposed Field Names
### Project-level fields
Add a project-owned execution workspace policy object. Suggested shared shape:
```ts
type ProjectExecutionWorkspacePolicy = {
enabled: boolean;
defaultMode: "inherit_project_default" | "shared_project_workspace" | "isolated_issue_checkout";
implementation: "git_worktree" | "adapter_managed";
branchPolicy: {
baseBranch: string | null;
branchMode: "issue_scoped" | "operator_branch" | "project_primary";
branchTemplate: string | null;
operatorPreferredBranch: string | null;
};
pullRequestPolicy: {
mode: "none" | "agent_may_open" | "agent_auto_open" | "approval_required";
autoPushOnDone: boolean;
requireApprovalBeforeOpen: boolean;
requireApprovalBeforeReady: boolean;
defaultBaseBranch: string | null;
};
cleanupPolicy: {
stopRuntimeServicesOnDone: boolean;
removeExecutionWorkspaceOnDone: boolean;
removeExecutionWorkspaceOnMerged: boolean;
deleteIssueBranchOnMerged: boolean;
retainFailedWorkspaceForInspection: boolean;
};
runtimeServices: {
mode: "disabled" | "project_default";
services?: Array<Record<string, unknown>>;
};
};
```
Notes:
- `enabled` controls whether the project exposes isolated issue checkout behavior at all
- `defaultMode` controls issue creation defaults
- `implementation` stays generic enough for local or remote adapters
- runtime service config stays nested here, not in the default agent form
### Issue-level fields
Add issue-owned opt-in/override fields. Suggested shape:
```ts
type IssueExecutionWorkspaceSettings = {
mode?: "inherit_project_default" | "shared_project_workspace" | "isolated_issue_checkout";
branchOverride?: string | null;
pullRequestModeOverride?: "inherit" | "none" | "agent_may_open" | "agent_auto_open" | "approval_required";
};
```
This should usually be hidden behind simple UI:
- a checkbox like `Use isolated issue checkout`
- advanced controls only when needed
### Agent-level fields
Keep agent-level workspace/runtime configuration, but reposition it as advanced override only.
Suggested semantics:
- if absent, inherit project + issue policy
- if present, override only the implementation detail needed for that adapter
## Shared Type and API Changes
### 1. Shared project types
Files to change first:
- `packages/shared/src/types/project.ts`
- `packages/shared/src/validators/project.ts`
Add:
- `executionWorkspacePolicy?: ProjectExecutionWorkspacePolicy | null`
### 2. Shared issue types
Files to change:
- `packages/shared/src/types/issue.ts`
- `packages/shared/src/validators/issue.ts`
Add:
- `executionWorkspaceSettings?: IssueExecutionWorkspaceSettings | null`
### 3. DB schema
If we want these fields persisted directly on existing entities instead of living in opaque JSON:
- `packages/db/src/schema/projects.ts`
- `packages/db/src/schema/issues.ts`
- migration generation in `packages/db/src/migrations/`
Recommended first cut:
- store project policy as JSONB on `projects`
- store issue setting override as JSONB on `issues`
That minimizes schema churn while the product model is still moving.
Suggested columns:
- `projects.execution_workspace_policy jsonb`
- `issues.execution_workspace_settings jsonb`
## Server-Side Resolution Changes
### 4. Project service read/write path
Files:
- `server/src/services/projects.ts`
- project routes in `server/src/routes/projects.ts`
Tasks:
- accept and validate project execution workspace policy
- return it from project API payloads
- enforce company scoping as usual
### 5. Issue service create/update path
Files:
- `server/src/services/issues.ts`
- `server/src/routes/issues.ts`
Tasks:
- accept issue-level `executionWorkspaceSettings`
- when creating an issue in a project with execution workspaces enabled, default the issue setting from the project policy if not explicitly provided
- keep issue payload simple for normal clients; advanced fields may be optional
### 6. Heartbeat and run resolution
Primary file:
- `server/src/services/heartbeat.ts`
Current behavior should be refactored so workspace resolution is based on:
- issue setting
- then project policy
- then adapter override
Specific technical work:
- load project execution workspace policy during run resolution
- load issue execution workspace settings during run resolution
- derive an effective execution workspace decision object before adapter launch
- keep adapter config as override only
Suggested internal helper:
```ts
type EffectiveExecutionWorkspaceDecision = {
mode: "shared_project_workspace" | "isolated_issue_checkout";
implementation: "git_worktree" | "adapter_managed" | "project_primary";
branchPolicy: {...};
pullRequestPolicy: {...};
cleanupPolicy: {...};
runtimeServices: {...};
};
```
## UI Changes
### 7. Project settings UI
Likely files:
- `ui/src/components/ProjectProperties.tsx`
- project detail/settings pages under `ui/src/pages/`
- project API client in `ui/src/api/projects.ts`
Add a project-owned section:
- `Execution Workspaces`
- enable isolated issue checkouts
- default for new issues
- implementation type
- branch settings
- PR settings
- cleanup settings
- runtime service defaults
Important UX rule:
- runtime service config should not default to raw JSON
- if the first cut must use JSON internally, wrap it in a minimal structured form or advanced disclosure
### 8. Issue creation/edit UI
Likely files:
- issue create UI components and issue detail edit surfaces in `ui/src/pages/`
- issue API client in `ui/src/api/issues.ts`
Add:
- `Use isolated issue checkout` toggle, only when project policy enables it
- advanced workspace behavior controls only when expanded
Do not show:
- raw runtime service JSON
- raw strategy payloads
in the default issue creation flow.
### 9. Agent UI cleanup
Files:
- `ui/src/adapters/local-workspace-runtime-fields.tsx`
- `ui/src/adapters/codex-local/config-fields.tsx`
- `ui/src/adapters/claude-local/config-fields.tsx`
Technical direction:
- keep the existing config surface as advanced override
- remove it from the default form flow for local coding agents
- add explanatory copy that project execution workspace policy is inherited unless overridden
## Adapter and Orchestration Changes
### 10. Local adapter behavior
Files:
- `packages/adapters/codex-local/src/ui/build-config.ts`
- `packages/adapters/claude-local/src/ui/build-config.ts`
- local adapter execute paths already consuming env/context
Tasks:
- continue to accept resolved workspace/runtime context from heartbeat
- stop assuming the agent config is the primary source of workspace policy
- preserve adapter-specific override support
### 11. Runtime service orchestration
Files:
- `server/src/services/workspace-runtime.ts`
Tasks:
- accept runtime service defaults from the effective project/issue policy
- keep adapter-config runtime service JSON as override-only
- preserve portability for remote adapters
## Pull Request and Cleanup Workflow
### 12. PR policy execution
This is not fully implemented today and should be treated as a separate orchestration layer.
Likely files:
- `server/src/services/heartbeat.ts`
- future git/provider integration helpers
Needed decisions:
- when issue moves to done, should Paperclip auto-commit?
- should it auto-push?
- should it auto-open a PR?
- should PR open/ready be approval-gated?
Suggested approach:
- store PR policy on project
- resolve effective PR policy per issue/run
- emit explicit workflow actions rather than relying on prompt text alone
### 13. Cleanup policy execution
Likely files:
- `server/src/services/workspace-runtime.ts`
- `server/src/services/heartbeat.ts`
- any future merge-detection hooks
Needed behaviors:
- stop runtime services on done or merged
- remove isolated checkout on done or merged
- delete branch on merged if policy says so
- optionally retain failed workspace for inspection
## Recommended First Implementation Sequence
To integrate these ideas without destabilizing the system, implement in this order:
1. Add project policy fields to shared types, validators, DB, services, routes, and project UI.
2. Add issue-level execution workspace setting fields to shared types, validators, DB, services, routes, and issue create/edit UI.
3. Refactor heartbeat to compute effective execution workspace policy from issue -> project -> agent override.
4. Change local-agent UI so workspace/runtime JSON becomes advanced-only.
5. Move default runtime service behavior to project settings.
6. Add explicit PR policy storage and resolution.
7. Add explicit cleanup policy storage and resolution.
## Definition of Done for This Product Shift
This design shift is complete when all are true:
- project settings own the default workspace policy
- issue creation exposes a simple opt-in/out when available
- local agent forms no longer require raw runtime JSON for common cases
- heartbeat resolves effective workspace behavior from project + issue + override precedence
- PR and cleanup behavior are modeled as explicit policy, not implied prompt behavior
- the UI language distinguishes execution workspace from local git worktree implementation details
## What the Current Code Already Supports
Paperclip already has the right foundation for a project-first model.