doc/plans/2026-04-12-vscode-task-interoperability-plan.md
Status: planning only, no code changes
Date: 2026-04-12
Related issue: PAP-1377
Paperclip should not replace its workspace runtime service model with VS Code tasks.
It should add a narrow interoperability layer that can discover and adopt supported entries from .vscode/tasks.json.
The core product model should stay:
VS Code tasks should be treated as:
tasks.jsonThe current implementation is already service-oriented:
workspaceRuntime config plus desiredState and per-service serviceStatesRelevant files:
packages/shared/src/types/workspace-runtime.tsserver/src/services/workspace-runtime.tsserver/src/services/project-workspace-runtime-config.tsui/src/components/WorkspaceRuntimeControls.tsxui/src/pages/ProjectWorkspaceDetail.tsxui/src/pages/ExecutionWorkspaceDetail.tsxThis is directionally correct for Paperclip because it gives the control plane an explicit model for service lifecycle, health, reuse, and restart behavior.
The current UX is still too raw:
.vscode/tasks.jsonThe issue is not that services are the wrong abstraction. The issue is that the configuration surface is too low-level and Paperclip does not yet leverage existing workspace metadata.
Keep Paperclip runtime services as the source of truth for service supervision. Add a new workspace command model above the raw JSON layer, with VS Code task discovery as one input.
The product model should become:
Workspace command
A named runnable thing attached to a workspace.
Workspace service
A workspace command that is expected to stay alive and be supervised.
Workspace job
A workspace command that runs once and exits.
Runtime service instance
The live process record that already exists today in Paperclip.
In that model, VS Code tasks are a way to populate workspace commands. Only commands that map cleanly to Paperclip service or job semantics should become runnable in Paperclip.
VS Code tasks are broader than Paperclip runtime services. They include shell/process tasks, compound tasks, background/watch tasks, presentation settings, extension/task-provider types, variable substitution, and problem-matcher-driven lifecycle.
That creates a bad fit if Paperclip tries to use tasks.json as its only runtime model:
The right boundary is interoperability, not replacement.
Paperclip should support a conservative subset of VS Code tasks and clearly mark unsupported entries.
shell and process tasks with a concrete command Paperclip can resolveoptions.cwddependsOn for import-time expansion or display-only dependency hintsPaperclip needs an explicit classification layer instead of assuming every VS Code task is a service.
Recommended classification:
service
Explicitly marked by Paperclip metadata, or confidently inferred from background/watch task semantics
job
One-shot command expected to exit
unsupported
Present in tasks.json, but not safely runnable by Paperclip
The important product decision is that service classification must be visible and editable by the operator. Inference can help, but it should not be the only source of truth.
Project and execution workspace pages should stop making raw runtime JSON the primary editing surface.
Default UI should show:
Raw JSON should remain available behind an advanced section.
For a workspace with cwd, Paperclip should look for .vscode/tasks.json.
The workspace UI should show:
tasks.json file was foundStart and stop UI should always name the exact entry being controlled.
Examples:
Start webStop apiRun db:migrateAvoid generic workspace-level labels when multiple commands exist.
Do not mix one-shot jobs and long-running services into one undifferentiated list.
Recommended sections:
ServicesJobsUnsupported imported tasksThat resolves the ambiguity called out in the issue.
Do not replace workspaceRuntime immediately.
Instead add a higher-level representation that can compile down to the existing runtime-service machinery.
Suggested workspace metadata shape:
type WorkspaceCommandSource =
| { type: "paperclip" }
| { type: "vscode_task"; taskLabel: string; taskPath: ".vscode/tasks.json" };
type WorkspaceCommandKind = "service" | "job";
type WorkspaceCommandDefinition = {
id: string;
name: string;
kind: WorkspaceCommandKind;
source: WorkspaceCommandSource;
command: string | null;
cwd: string | null;
env?: Record<string, string> | null;
autoStart?: boolean;
serviceConfig?: {
lifecycle?: "shared" | "ephemeral";
reuseScope?: "project_workspace" | "execution_workspace" | "run";
readiness?: Record<string, unknown> | null;
expose?: Record<string, unknown> | null;
} | null;
importWarnings?: string[];
disabledReason?: string | null;
};
workspaceRuntime can then become a derived or advanced representation for service-type commands until the rest of the system is migrated.
Paperclip should map imported tasks with explicit, documented rules.
Recommended rules:
job by default.service only when:
dependsOn is preserved as metadata, not silently flattened into hidden behavior.Paperclip-specific metadata can live in a namespaced field on the imported task definition, for example:
{
"label": "web",
"type": "shell",
"command": "pnpm dev",
"isBackground": true,
"paperclip": {
"kind": "service",
"readiness": {
"type": "http",
"urlTemplate": "http://127.0.0.1:${port}"
},
"expose": {
"type": "url",
"urlTemplate": "http://127.0.0.1:${port}"
}
}
}
That gives us interoperability without depending on VS Code-only semantics for service readiness and exposure.
Project workspaces should be the main place where imported commands are discovered and curated. Execution workspaces should inherit that curated command set by default, with optional issue-level overrides.
Recommended precedence:
This matches the existing direction in doc/plans/2026-03-10-workspace-strategy-and-git-worktrees.md.
Goal: show imported VS Code tasks in the workspace UI without changing runtime behavior.
Work:
.vscode/tasks.json for project workspaces with local cwdSuccess condition: an operator can see what Paperclip would import and why.
Goal: introduce a first-class workspace command layer above raw runtime JSON.
Work:
service and job in UISuccess condition: the workspace UI is command-first, and raw runtime JSON is advanced-only.
Goal: run supported imported service commands through the current Paperclip supervisor.
Work:
Success condition: imported service commands behave like native Paperclip services once adopted.
Goal: support one-shot imported commands without pretending they are services.
Work:
Run actions for jobsdependsOn execution for jobs with clear loggingSuccess condition: one-shot tasks are runnable, but they are not mixed into the service lifecycle model.
Goal: let agents and issue-scoped workspaces consume the curated command model consistently.
Work:
Success condition: agents, operators, and workspaces all refer to the same named commands.
These risks are manageable if the import layer stays explicit, conservative, and operator-editable.
Paperclip should adopt VS Code tasks as an optional workspace command source, not as the canonical runtime model.
The main UX change should be:
.vscode/tasks.json pre-populate those commands when availabledoc/plans/2026-03-10-workspace-strategy-and-git-worktrees.md