You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add V2 Project preparation and host debug sessions - #350
V2 needs a project-level representation of user code that can run as a host process or in a container, with AppHost controlling startup through a debug adapter rather than the V1 IDE protocol. This PR adds Project preparation and host/container debug sessions, keeping application lifetime, adapter lifetime, and prepared execution context separate.
Approach
Prepare user code without automatically launching it. Project accepts exactly one immutable process or container template, an informational source root, and service-backed ports. It publishes evaluated application arguments/environment for AppHost. Process Projects prepare inputs without starting an application; container Projects create a reusable physical container running tail -f /dev/null. Readiness describes preparation and session coordination, not application health. Process environment suppression matches V1 Executable; explicitly declared container variables are retained, matching V1 Container.
Run caller-supplied adapters in the selected execution context. The process/container template determines adapter location; there is no separate placement field. Adapter configuration declares a required host directory, command/arguments, transport, and environment. Container Projects install that directory at /opt/dcp/debug-adapter or a caller-selected containerDirectory. {{adapterDirectory}} expands to the appropriate location. Optional executableFiles identifies regular files to mark executable in the streamed archive, including when copying Linux binaries from Windows; source files remain unchanged. A general physical-container CopyFiles API supports streamed directories, SHA256-verified tar sources, and inline archives, with a 10-minute runtime transfer limit and opt-in tar-source cleanup.
Expose authenticated native DAP over a WebSocket subresource. Debug connections require non-empty DCP_SECURE_TOKEN and/or DCP_DEBUG_SESSION_TOKEN configuration. Whenever the separate debug token is configured, the request must carry it in X-DCP-Debug-Session-Token, in addition to normal API bearer authentication. The header avoids upstream request-URI logging of query credentials. Host adapters support stdio, TCP-connect, and TCP-callback; container adapters support stdio and TCP-connect through Docker, Podman, and WSLC. TCP-connect sessions share a reference-counted provider; other supported modes use dedicated adapter executions.
Report observations without retaining DAP request history. Each bridge publishes current connection state and latched initialize/launch/attach, initialized/process, debuggee-exit, termination, and disconnection observations. Opaque launch configuration is forwarded rather than copied into status. Session readiness requires observed client initialization and the adapter initialized event while connected. Request correlation remains internal to bounded outstanding-request maps. disconnect stops further request forwarding without treating late traffic as failure or synthesizing responses; adapter responses/events continue draining within bounded shutdown.
Keep target ownership distinct from attachment and session closure. Identity-safe host target registrations survive session closure for Project observation and bounded cleanup. Targets reported as attach or attachForSuspendedLaunch are observed but not cleanup-owned, including on registration failure. Container PIDs never select host cleanup handles, and attached runtime-command completion does not prove in-container process termination. Failed provider cleanup remains explicitly unconfirmed and fences duplicate launches. Output buffering is bounded to 64 MiB per stream, with explicit overflow failure and cleanup.
Project reconciliation reuses existing V2 state, work-queue, create-recovery, finalizer, namespace-cleanup, and logging mechanisms. API-server-owned debug observations use isolated status writes; Project-specific serving lives in internal/projectdebug, and generic framing/correlation lives in internal/dap. Supporting changes include bounded initial image-identity inspection retries and precision-aware process identity comparison across API serialization.
Boundaries and follow-up work
Host/container terminals, runInTerminal, adapter-terminal execution, and container TCP-callback remain follow-up work. DCP does not acquire debug adapters, infer language-specific launch configuration, implement V1 IDE orchestration, create automatic source mounts, or recover debug executions across controller restarts.
Target cleanup is bounded best effort for reported, owned identities—not a guarantee that adapters report every target. Session closure alone does not establish target exit or cleanup. Session/execution records remain until Project deletion; pruning is deferred. Installation uses the DCP installation directory or the client's selected destination, without special inspection of existing container symlinks. Decisions and follow-up scope are recorded in plan/v2-project-debugging-plan.md.
Verification
The latest full native macOS test suite and repository-wide lint passed. Focused race coverage passed for Project preparation/lifecycle, DAP forwarding and shutdown, adapter/runtime boundaries, attached-target preservation, executable-file permissions, and copy deadlines.
Real API-server/storage and running-controller tests cover status-writer isolation, readiness loss, identity replacement, create recovery, provider sharing/fencing, target cleanup, declared container environment, and directory installation. Dedicated credential tests verify admission and absence of accepted/rejected tokens from verbose server, audit, and standard-library panic logs across successful and failing requests.
Docker, Podman, and WSLC command-stream tests use native subprocess stand-ins rather than real container runtimes. Real-container execution and cross-platform runtime validation remain CI work.
Delve E2E coverage includes initialization, launch, verified breakpoint/locals, continuation, and deletion while stopped. That scenario previously passed locally under explicit user authorization; it was not rerun locally for the latest changes.
Capture process output in the physical controller and publish immediate physical log-source snapshots through logical status. Reuse shared V2 streaming and owner-scoped system diagnostics, with direct file redirection for retained processes.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: aa4abbe1-3392-4398-9f96-566f68ce0fa9
Port upstream watch-setup ordering and regression tests into internal/logstream, preserving the V1 API adapter and existing streaming handoff. Adopt Tilt v0.19.2 and namespace watcher hardening.
Co-authored-by: Copilot App <[email protected]>
Preserve the original physical source identity in a completed, unavailable descriptor so logical-only followers finish through the existing lifecycle callbacks. Cover physical deletion through an isolated real API server with no physical log request.
Co-authored-by: Copilot App <[email protected]>
Use one filename contract for command and runtime captures, preserve V1 startup filenames and runtime capture suffixes, and capture physical image output with ordinary stdout/stderr source names.
Co-authored-by: Copilot App <[email protected]>
Integrate the immediate process parent and Tilt v0.19.2 through the existing stack order.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 89db152a-aa9d-4e1d-9058-d4c0090c88d6
Inspect and adopt a matching owned physical process before rechecking creation prerequisites. Exclude mutable stop from immutable configuration comparison and forward it through runtime reconciliation. Cover lost successful-create responses in session and persistent modes through the real API.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: aa4abbe1-3392-4398-9f96-566f68ce0fa9
Acquire exclusive runtime-name leases so one logical network cannot release another startup's claim. Exercise two same-owner logical networks in the shared real API/controller environment and verify reuse after settlement.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: bbe01c56-5ae4-4f36-8134-93b3b2718fd2
Finish physical and logical followers after confirmed runtime disappearance, wait for image log-writer release in its assertion, and remove unnecessary simulated image aliases. Cover failed pull diagnostics and stream closure at the production Docker/Podman adapter boundary.
Co-authored-by: Copilot App <[email protected]>
Isolate process lease keys, preserve runtime stop handling during persistence settlement, and select raw capture reader settings. Publish output completion after pipe drainage and retry capture disposal through existing cleanup helpers and reconciliation. Add focused regressions and remove the cleanup test's file-restoration race.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: aa4abbe1-3392-4398-9f96-566f68ce0fa9
Preserve the existing real-client test hooks while adding the parent process executor hook and shared raw capture handling.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 89db152a-aa9d-4e1d-9058-d4c0090c88d6
Treat loss of handed-off physical backing as terminal, preserve completed log-source identity, and release startup leases without recreating resources or reconstructing runtime ownership. Cover startup and ownership-recording loss, status conflicts, and namespace deletion.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: aa4abbe1-3392-4398-9f96-566f68ce0fa9
…agation
Use operation-local ownership candidates from verified physical observations, settle retained startup before child deletion, and release canceled pre-handoff leases without runtime-name ownership discovery. Preserve namespace cleanup when termination prevents physical startup, including a committed Create with a lost response.
Surface terminal image failure while logical network dependencies remain unavailable and keep startup failure latched after dependency recovery.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: bbe01c56-5ae4-4f36-8134-93b3b2718fd2
Update every matching label entry in the shared setter while preserving unrelated labels and their ordering. Cover reserved ownership labels, caller immutability, and persistent-network reuse with duplicate lifecycle labels.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: bbe01c56-5ae4-4f36-8134-93b3b2718fd2
Forward lease options through WithResourceLease and opt V1 network creation into same-process exclusivity. Keep release within the callback scope instead of issuing redundant status-driven releases that can remove a later startup's lease.
Cover wrapper exclusivity and real-API V1/V2 creation serialization, shared runtime references, and retained workload registration.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: bbe01c56-5ae4-4f36-8134-93b3b2718fd2
Match the physical-container Unknown/missing projection without periodic requeue. Preserve event-driven observation of the pinned runtime ID and retry transient inspection failures.
Cover retry-policy parity, retained identity and details, same-name replacement isolation, and deletion without removing the replacement.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: bbe01c56-5ae4-4f36-8134-93b3b2718fd2
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Unresolved defects can indefinitely block TCP output bridges and Project deletion, while successful image verification retains stale failure counts that prematurely exhaust retries.
Adds V2 Project preparation and debug-session coordination for AppHost-controlled application launch, integrating with DCP’s existing controllers, logging, and cleanup mechanisms while separating application, adapter, and prepared-container lifetimes.
Changes:
Adds Project registration, preparation snapshots, target-process observation, and cleanup integration.
Retain identity-bound runtime logs on Unknown transitions, refresh valid original backing observations without reopening lifecycle state, and complete followers only on confirmed absence. Cover existing followers, late readers, capture completion, and missing-backing status retries.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Follow logical-resource terminal handlers by retaining failure state and diagnostics across backing lookup changes. Cover missing and replaced backings and preserve follower completion through status conflicts without requiring a terminal-state transition.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Evaluate declared values before overlaying process overrides onto literal ambient values, using a focused merge function. Keep containers isolated from ambient environment and compare prepared slices element-wise so empty environments cannot starve finalizer removal. Cover Project/namespace deletion and wait for missing-backing status convergence in the CI regression.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
A root-exit race can leave descendant processes alive while reporting cleanup complete, and acknowledged DAP disconnects can still be misreported as failures.
Pass Project container runArgs through to the physical container, matching
LogicalContainer. Allocate host tcp-callback adapter listener ports through
the shared DCP port allocator so they cannot reuse recently allocated ports.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
A client closing its stream after the adapter acknowledged its disconnect
request is normal protocol shutdown, even if the adapter connection stays
open. Earlier client loss still fails the session.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
An upstream read error can be masked as EOF during writer closure, causing a reset TCP connection to be recorded as Exited rather than Failed before asynchronous cancellation occurs.
No open issues 🎉
1 previously missed issue
In code that hasn't changed since last review
Preserve upstream read errors before closing the writer
internal/projectdebug/output.go:33
A non-EOF upstream read error becomes EOF when writer.Close() runs, so the bridge can return success before the asynchronous failure callback cancels the serving context. A reset TCP connection can therefore be recorded as an Exited session rather than Failed. Close the buffered reader with the upstream error before closing the writer so failure does not depend on callback scheduling.
Consolidate preparation and shutdown reasons while retaining detailed causes
in messages. Remember successful preparation across uncertain observations
to distinguish initial preparation failures from lost execution context.
Align namespace admission and paused reporting with logical controllers.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Require an adapter directory and derive execution placement from the Project
template. Add physical copy contexts for directories, verified tar files,
and inline archives, backed by a general runtime tar-copy API. Keep directory
packaging in the tar utilities and perform opted-in file cleanup best-effort
on successful copy, terminal failure, and settled stop or deletion.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Replace retained request history with latched session observations and forward-only connection state. Preserve progress across status writers and report stream termination independently from adapter and target lifetime.
Validate composed symlinks, preserve directory archive sources during cleanup, and release temporary context-reader workers promptly.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Require DCP_SECURE_TOKEN or DCP_DEBUG_SESSION_TOKEN configuration, validating the separate debug token through the X-DCP-Debug-Session-Token header before session creation or adapter launch.
Cover admission combinations and verify credentials remain absent from verbose server, audit, and panic logs. Update integration clients and document the connection contract.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Increase archive-transfer limits to ten minutes, exclude attached debug targets from Project cleanup, and expose executableFiles declarations for directory copies and container adapters.
Add focused regressions for transfer deadlines, attached target survival and registration failure, executable paths and modes, and Project-to-physical copy handoff.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Discard further requests after disconnect without failing shutdown or synthesizing replies. Restrict Project environment prefix suppression to process templates, matching V1 container behavior.
Add regressions for late requests and explicit container variables, and update the debugging contract.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Use standard test contexts, explicit cancellation, and deterministic synchronization for buffered pipes, debounce cancellation, process completion, and initialization-lock tests. Inject cleanup verification failures instead of waiting for context expiry, and allocate free listener ports for tunnel idempotency.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Apply one timing policy to scheduling, debounce, and retry eligibility while preserving production defaults. Configure faster V2 integration-test intervals without shortening test context deadlines, and retain a slow monitoring fallback for exit-notification coverage.
Verify policy isolation and delayed delivery, synchronize backing-deletion assertions, and document the test timing profile.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
Rewrite existing debounce tests with deterministic timing and invocation assertions without increasing test count. Derive controller idle observation from two test-profile scheduling/debounce cycles rather than a fixed ten-second wait.
Co-authored-by: Copilot App <[email protected]>
Copilot-Session: 754d257d-9693-4e17-91ef-e520d4a620d9
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
V2 needs a project-level representation of user code that can run as a host process or in a container, with AppHost controlling startup through a debug adapter rather than the V1 IDE protocol. This PR adds Project preparation and host/container debug sessions, keeping application lifetime, adapter lifetime, and prepared execution context separate.
Approach
tail -f /dev/null. Readiness describes preparation and session coordination, not application health. Process environment suppression matches V1 Executable; explicitly declared container variables are retained, matching V1 Container./opt/dcp/debug-adapteror a caller-selectedcontainerDirectory.{{adapterDirectory}}expands to the appropriate location. OptionalexecutableFilesidentifies regular files to mark executable in the streamed archive, including when copying Linux binaries from Windows; source files remain unchanged. A general physical-containerCopyFilesAPI supports streamed directories, SHA256-verified tar sources, and inline archives, with a 10-minute runtime transfer limit and opt-in tar-source cleanup.DCP_SECURE_TOKENand/orDCP_DEBUG_SESSION_TOKENconfiguration. Whenever the separate debug token is configured, the request must carry it inX-DCP-Debug-Session-Token, in addition to normal API bearer authentication. The header avoids upstream request-URI logging of query credentials. Host adapters support stdio, TCP-connect, and TCP-callback; container adapters support stdio and TCP-connect through Docker, Podman, and WSLC. TCP-connect sessions share a reference-counted provider; other supported modes use dedicated adapter executions.disconnectstops further request forwarding without treating late traffic as failure or synthesizing responses; adapter responses/events continue draining within bounded shutdown.attachorattachForSuspendedLaunchare observed but not cleanup-owned, including on registration failure. Container PIDs never select host cleanup handles, and attached runtime-command completion does not prove in-container process termination. Failed provider cleanup remains explicitly unconfirmed and fences duplicate launches. Output buffering is bounded to 64 MiB per stream, with explicit overflow failure and cleanup.Project reconciliation reuses existing V2 state, work-queue, create-recovery, finalizer, namespace-cleanup, and logging mechanisms. API-server-owned debug observations use isolated status writes; Project-specific serving lives in
internal/projectdebug, and generic framing/correlation lives ininternal/dap. Supporting changes include bounded initial image-identity inspection retries and precision-aware process identity comparison across API serialization.Boundaries and follow-up work
Host/container terminals,
runInTerminal, adapter-terminal execution, and container TCP-callback remain follow-up work. DCP does not acquire debug adapters, infer language-specific launch configuration, implement V1 IDE orchestration, create automatic source mounts, or recover debug executions across controller restarts.Target cleanup is bounded best effort for reported, owned identities—not a guarantee that adapters report every target. Session closure alone does not establish target exit or cleanup. Session/execution records remain until Project deletion; pruning is deferred. Installation uses the DCP installation directory or the client's selected destination, without special inspection of existing container symlinks. Decisions and follow-up scope are recorded in
plan/v2-project-debugging-plan.md.Verification