From 7c63a6ef2df6f43d2a42fc3b8614624c70cc41e8 Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Tue, 13 Oct 2026 22:36:33 +0200 Subject: [PATCH 1/8] docs(adr): record in-container AI agents for wave one Amends ADR 0006 per owner decision H7:a/H9:a. Co-Authored-By: Claude Sonnet 5.5 --- docs/adr/0006-optional-ai-execution.md | 1 + docs/adr/0009-in-container-ai-agents.md | 42 +++++++++++++++++++++++++ docs/index.md | 1 + 3 files changed, 44 insertions(+) create mode 100644 docs/adr/0009-in-container-ai-agents.md diff --git a/docs/adr/0006-optional-ai-execution.md b/docs/adr/0006-optional-ai-execution.md index 1e154103..b254c356 100644 --- a/docs/adr/0006-optional-ai-execution.md +++ b/docs/adr/0006-optional-ai-execution.md @@ -2,6 +2,7 @@ Date: 2026-10-12 | Proposal updated: 2026-10-13 Status: Proposed; no product implementation authorization +Amended by: [ADR 0009](0009-in-container-ai-agents.md) (in-container agents, wave one) ## Context diff --git a/docs/adr/0009-in-container-ai-agents.md b/docs/adr/0009-in-container-ai-agents.md new file mode 100644 index 00000000..ce93f7d1 --- /dev/null +++ b/docs/adr/0009-in-container-ai-agents.md @@ -0,0 +1,42 @@ +# 0009-in-container-ai-agents: AI agents run inside the workspace container in wave one + +Date: 2026-10-13 +Status: Proposed; owner decision H7:a/H9:a recorded 2026-10-13 + +## Context + +[ADR 0006](0006-optional-ai-execution.md) proposed a later execution board and +listed AI features as a product non-goal. The owner has decided (H7:a/H9:a) that +AI agents run inside the workspace container in wave one, while +Symphony/OpenAI-style orchestration is wave two. This ADR amends ADR 0006 and +supersedes its AI non-goal wording. + +## Decision + +- Wave one: an AI agent is an ordinary process in the workspace container, using + the workspace's files, network policy and trust grant. WorkHarbor does not + schedule, dispatch or approve agent work. +- Wave two: Symphony/OpenAI-style orchestration and the execution board of ADR 0006 + remain proposed and keep every approval and evidence gate stated there. +- Interop uses a small in-container session interface with five operations: + list, attach, status, send input, stop. It is exposed to the owner through + existing authorized workspace access, never as raw host shell access. +- Agents hold no host-agent credentials, control sockets or other workspaces' data + (see the isolation section of the [architecture](../architecture.md)). +- Ordinary lifecycle and terminal access remain usable without an AI subscription + or tracker account. + +## Amendment of ADR 0006 + +ADR 0006 stays Proposed for the wave-two board. Its statements that AI features are +non-goals and that no AI scope exists are superseded for in-container agents only. +Nothing here authorizes orchestration, dispatch or board work. + +## Consequences + +[Product](../product.md) and [architecture](../architecture.md) state the wave-one +scope. The constitution still lists AI orchestration as excluded; its amendment or +scoped exception needs owner action under its governance and is not made here. +The session interface wire format, authorization binding and failure behavior are +undesigned and belong to a feature spec. Credential handling for agent +subscriptions is open. Nothing is implemented or verified. diff --git a/docs/index.md b/docs/index.md index 28f2ab02..0e3f5c9d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -24,6 +24,7 @@ - [Development methodology](adr/0005-development.md) - [Optional execution integration (proposed)](adr/0006-optional-ai-execution.md) - [Explicit CI acceptance (proposed)](adr/0007-explicit-ci-acceptance.md) +- [In-container AI agents, wave one (proposed)](adr/0009-in-container-ai-agents.md) ## Background and references From 6752f9b5d4f97f52a0b307671c78dd0924e641cb Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Tue, 13 Oct 2026 22:36:33 +0200 Subject: [PATCH 2/8] docs: state wave-one in-container AI scope Co-Authored-By: Claude Sonnet 5.5 --- docs/architecture.md | 7 +++++++ docs/product.md | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 15b7e429..150e1df3 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -51,6 +51,13 @@ project. Full future devenv integration would build project-specific OCI images from those inputs and use the existing container boundary. This is not implemented and does not add Nix or devenv to the current runtime requirements. +## In-container AI agents (wave one) +Agents run inside the workspace container. A small in-container session interface +(list, attach, status, send input, stop) gives owner-authorized interop through +existing workspace access ([ADR 0009](adr/0009-in-container-ai-agents.md)). The +control plane does not schedule agents; orchestration is wave two. Wire format and +authorization binding are undesigned. + ## Isolation Host agent can control Docker and is privileged infrastructure. A compromised workspace must not obtain agent credentials, control sockets or other owners' data. diff --git a/docs/product.md b/docs/product.md index e9fc9092..9af90ce1 100644 --- a/docs/product.md +++ b/docs/product.md @@ -20,7 +20,7 @@ Podman, Kubernetes, multiple users, OAuth, Forgejo/Gitea/Codeberg/GitHub integra CI integration and a broader CLI follow demonstrated demand and adapter tests. ## Non-goals -AI features, agent management as a product, general container administration, +Orchestration of AI agents (wave two), agent management as a product, general container administration, built-in Git hosting, billing, managed SaaS, collaborative editing and arbitrary multi-tenant execution. A browser editor is planned, not delivered by feature 001. @@ -31,6 +31,12 @@ existing minimal Git server or beside project repositories. Per-user forks are optional provenance, not an authorization mechanism. MVP uses one config repo per workspace. Imported repos are never implicitly rewritten or recursively cloned. +## AI scope +Wave one: AI agents run inside the workspace container as ordinary processes. A small +in-container session interface (list, attach, status, send input, stop) provides +interop; see [ADR 0009](adr/0009-in-container-ai-agents.md). Wave two: +Symphony/OpenAI-style orchestration, proposed in ADR 0006. Not yet implemented. + ## Success criteria The owner can create, inspect, access, stop and restart a workspace using only the browser. Disconnected hosts display uncertainty. Restart retains committed and @@ -47,7 +53,7 @@ feature is approved and verified; the current Docker/devcontainer baseline remai [ADR 0006](adr/0006-optional-ai-execution.md) proposes a later optional internal execution board linking Spec Kit artifacts, Symphony scheduling and WorkHarbor workspaces, resources, interventions and evidence. This is outside the accepted -baseline and the sequence above; AI features remain current non-goals. Start with +baseline and the sequence above; orchestration remains a wave-two non-goal. Start with a proposed read-only Spec Kit view at an identified Git revision, linking task prerequisites, attempts, workspaces and separate approval/check/review/merge/live evidence. Add guarded controls only after that view is proven; moving a card From ff30d7c8eff863c54a30e47cc2281c3aed87f993 Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Tue, 13 Oct 2026 22:43:29 +0200 Subject: [PATCH 3/8] docs(adr): point agent session interface to its own contract Records owner decisions H16:b and H18:a. Co-Authored-By: Claude Sonnet 5.5 --- docs/adr/0009-in-container-ai-agents.md | 12 ++++++++---- docs/architecture.md | 7 ++++--- docs/product.md | 4 ++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/adr/0009-in-container-ai-agents.md b/docs/adr/0009-in-container-ai-agents.md index ce93f7d1..7226e0cf 100644 --- a/docs/adr/0009-in-container-ai-agents.md +++ b/docs/adr/0009-in-container-ai-agents.md @@ -18,9 +18,13 @@ supersedes its AI non-goal wording. schedule, dispatch or approve agent work. - Wave two: Symphony/OpenAI-style orchestration and the execution board of ADR 0006 remain proposed and keep every approval and evidence gate stated there. -- Interop uses a small in-container session interface with five operations: - list, attach, status, send input, stop. It is exposed to the owner through - existing authorized workspace access, never as raw host shell access. +- Interop uses a small in-container agent session interface (list, attach, + status, send input, stop). Owner decision H16:b: it becomes its own versioned + contract under `contracts/`, tracked as #71 (held, depends on #66). That future + contract, not this ADR, defines the interface details. It is exposed to the + owner through existing authorized workspace access, never as raw host shell + access. +- Owner decision H18:a: the console is a reattachable workspace session. - Agents hold no host-agent credentials, control sockets or other workspaces' data (see the isolation section of the [architecture](../architecture.md)). - Ordinary lifecycle and terminal access remain usable without an AI subscription @@ -37,6 +41,6 @@ Nothing here authorizes orchestration, dispatch or board work. [Product](../product.md) and [architecture](../architecture.md) state the wave-one scope. The constitution still lists AI orchestration as excluded; its amendment or scoped exception needs owner action under its governance and is not made here. -The session interface wire format, authorization binding and failure behavior are +The session interface contract (#71) and its wire format, authorization binding and failure behavior are undesigned and belong to a feature spec. Credential handling for agent subscriptions is open. Nothing is implemented or verified. diff --git a/docs/architecture.md b/docs/architecture.md index 150e1df3..836cc4f8 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -52,9 +52,10 @@ from those inputs and use the existing container boundary. This is not implement and does not add Nix or devenv to the current runtime requirements. ## In-container AI agents (wave one) -Agents run inside the workspace container. A small in-container session interface -(list, attach, status, send input, stop) gives owner-authorized interop through -existing workspace access ([ADR 0009](adr/0009-in-container-ai-agents.md)). The +Agents run inside the workspace container. A small in-container agent session interface +gives owner-authorized interop through +existing workspace access; its details belong to a future versioned contract +under `contracts/` (#71) ([ADR 0009](adr/0009-in-container-ai-agents.md)). The control plane does not schedule agents; orchestration is wave two. Wire format and authorization binding are undesigned. diff --git a/docs/product.md b/docs/product.md index 9af90ce1..cc637bb4 100644 --- a/docs/product.md +++ b/docs/product.md @@ -33,8 +33,8 @@ workspace. Imported repos are never implicitly rewritten or recursively cloned. ## AI scope Wave one: AI agents run inside the workspace container as ordinary processes. A small -in-container session interface (list, attach, status, send input, stop) provides -interop; see [ADR 0009](adr/0009-in-container-ai-agents.md). Wave two: +in-container agent session interface provides interop; its details live in a +future versioned contract under `contracts/` (#71); see [ADR 0009](adr/0009-in-container-ai-agents.md). Wave two: Symphony/OpenAI-style orchestration, proposed in ADR 0006. Not yet implemented. ## Success criteria From e1f005eda275180674a5ad6f4b5bc69c3757e829 Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Tue, 13 Oct 2026 23:03:00 +0200 Subject: [PATCH 4/8] docs(adr): narrow AI non-goal and fix ADR 0006 references Co-Authored-By: Claude Sonnet 5.5 --- docs/adr/0009-in-container-ai-agents.md | 20 +++++++++++--------- docs/architecture.md | 2 +- docs/product.md | 8 +++++--- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/adr/0009-in-container-ai-agents.md b/docs/adr/0009-in-container-ai-agents.md index 7226e0cf..de12cc4d 100644 --- a/docs/adr/0009-in-container-ai-agents.md +++ b/docs/adr/0009-in-container-ai-agents.md @@ -6,10 +6,10 @@ Status: Proposed; owner decision H7:a/H9:a recorded 2026-10-13 ## Context [ADR 0006](0006-optional-ai-execution.md) proposed a later execution board and -listed AI features as a product non-goal. The owner has decided (H7:a/H9:a) that +framed every AI product scope as later and optional. The owner has decided (H7:a/H9:a) that AI agents run inside the workspace container in wave one, while -Symphony/OpenAI-style orchestration is wave two. This ADR amends ADR 0006 and -supersedes its AI non-goal wording. +Symphony/OpenAI-style orchestration is wave two. This ADR amends that framing; the +superseded non-goal wording is in [product](../product.md). ## Decision @@ -20,11 +20,11 @@ supersedes its AI non-goal wording. remain proposed and keep every approval and evidence gate stated there. - Interop uses a small in-container agent session interface (list, attach, status, send input, stop). Owner decision H16:b: it becomes its own versioned - contract under `contracts/`, tracked as #71 (held, depends on #66). That future + contract under `contracts/`, tracked as [#71](https://github.com/wstein/workharbor-nxt/issues/71). That future contract, not this ADR, defines the interface details. It is exposed to the owner through existing authorized workspace access, never as raw host shell access. -- Owner decision H18:a: the console is a reattachable workspace session. +- Owner decision H18:a: the agent console is a reattachable workspace session. - Agents hold no host-agent credentials, control sockets or other workspaces' data (see the isolation section of the [architecture](../architecture.md)). - Ordinary lifecycle and terminal access remain usable without an AI subscription @@ -32,8 +32,9 @@ supersedes its AI non-goal wording. ## Amendment of ADR 0006 -ADR 0006 stays Proposed for the wave-two board. Its statements that AI features are -non-goals and that no AI scope exists are superseded for in-container agents only. +ADR 0006 stays Proposed for the wave-two board. Its framing that every AI product +scope is later and optional (lines 9-21) is amended: in-container agents are wave +one. The non-goal wording superseded is in `docs/product.md`. Nothing here authorizes orchestration, dispatch or board work. ## Consequences @@ -41,6 +42,7 @@ Nothing here authorizes orchestration, dispatch or board work. [Product](../product.md) and [architecture](../architecture.md) state the wave-one scope. The constitution still lists AI orchestration as excluded; its amendment or scoped exception needs owner action under its governance and is not made here. -The session interface contract (#71) and its wire format, authorization binding and failure behavior are -undesigned and belong to a feature spec. Credential handling for agent +The session interface contract ([#71](https://github.com/wstein/workharbor-nxt/issues/71)) and its wire format, +authorization binding and failure behavior are undesigned and belong to a +feature spec. Credential handling for agent subscriptions is open. Nothing is implemented or verified. diff --git a/docs/architecture.md b/docs/architecture.md index 836cc4f8..17c48ee1 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -55,7 +55,7 @@ and does not add Nix or devenv to the current runtime requirements. Agents run inside the workspace container. A small in-container agent session interface gives owner-authorized interop through existing workspace access; its details belong to a future versioned contract -under `contracts/` (#71) ([ADR 0009](adr/0009-in-container-ai-agents.md)). The +under `contracts/` ([#71](https://github.com/wstein/workharbor-nxt/issues/71)) ([ADR 0009](adr/0009-in-container-ai-agents.md)). The control plane does not schedule agents; orchestration is wave two. Wire format and authorization binding are undesigned. diff --git a/docs/product.md b/docs/product.md index cc637bb4..3bdba8aa 100644 --- a/docs/product.md +++ b/docs/product.md @@ -20,8 +20,8 @@ Podman, Kubernetes, multiple users, OAuth, Forgejo/Gitea/Codeberg/GitHub integra CI integration and a broader CLI follow demonstrated demand and adapter tests. ## Non-goals -Orchestration of AI agents (wave two), agent management as a product, general container administration, -built-in Git hosting, billing, managed SaaS, collaborative editing and arbitrary +AI agent orchestration (deferred to wave two), agent fleet management beyond the +in-container session interface, general container administration, built-in Git hosting, billing, managed SaaS, collaborative editing and arbitrary multi-tenant execution. A browser editor is planned, not delivered by feature 001. ## Workspace repository @@ -34,7 +34,9 @@ workspace. Imported repos are never implicitly rewritten or recursively cloned. ## AI scope Wave one: AI agents run inside the workspace container as ordinary processes. A small in-container agent session interface provides interop; its details live in a -future versioned contract under `contracts/` (#71); see [ADR 0009](adr/0009-in-container-ai-agents.md). Wave two: +future versioned contract under `contracts/` +([#71](https://github.com/wstein/workharbor-nxt/issues/71)); see +[ADR 0009](adr/0009-in-container-ai-agents.md). Wave two: Symphony/OpenAI-style orchestration, proposed in ADR 0006. Not yet implemented. ## Success criteria From 5aa2fceac5a6f37baa5c17c6a4fb1749bb1c7b2e Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Tue, 13 Oct 2026 23:09:07 +0200 Subject: [PATCH 5/8] docs(adr): record persistent workspace console decision Records H18:a and H22:a. Co-Authored-By: Claude Sonnet 5.5 --- docs/adr/0009-in-container-ai-agents.md | 3 ++- docs/adr/0012-persistent-workspace-console.md | 27 +++++++++++++++++++ docs/index.md | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 docs/adr/0012-persistent-workspace-console.md diff --git a/docs/adr/0009-in-container-ai-agents.md b/docs/adr/0009-in-container-ai-agents.md index de12cc4d..1f4d49b2 100644 --- a/docs/adr/0009-in-container-ai-agents.md +++ b/docs/adr/0009-in-container-ai-agents.md @@ -24,7 +24,8 @@ superseded non-goal wording is in [product](../product.md). contract, not this ADR, defines the interface details. It is exposed to the owner through existing authorized workspace access, never as raw host shell access. -- Owner decision H18:a: the agent console is a reattachable workspace session. +- Owner decision H18:a: the workspace console is a reattachable + session (see [ADR 0012](0012-persistent-workspace-console.md)). - Agents hold no host-agent credentials, control sockets or other workspaces' data (see the isolation section of the [architecture](../architecture.md)). - Ordinary lifecycle and terminal access remain usable without an AI subscription diff --git a/docs/adr/0012-persistent-workspace-console.md b/docs/adr/0012-persistent-workspace-console.md new file mode 100644 index 00000000..c9fd4401 --- /dev/null +++ b/docs/adr/0012-persistent-workspace-console.md @@ -0,0 +1,27 @@ +# 0012-persistent-workspace-console: The console is a reattachable workspace session + +Date: 2026-10-13 +Status: Proposed; owner decisions H18:a and H22:a recorded 2026-10-13 + +## Context + +[ADR 0009](0009-in-container-ai-agents.md) records H18:a: the console is a +reattachable workspace session. Feature 001 said disconnect cleans up the PTY, +which conflicts with a console that outlives its connections. + +## Decision + +- Each workspace has one persistent console session whose lifetime is independent + of its connections. +- Disconnect, grant expiry and idle timeout end only the connection. Its relay + resources are released within five seconds, including when the transport + vanishes without a close frame. +- Workspace stop, rebuild, runtime deletion or an explicit close end the session. +- Reattachment requires a new single-use grant; other grant and relay bounds of + feature 001 are unchanged. + +## Consequences + +The [feature 001 spec](../../specs/001-workspace-lifecycle/spec.md) is reconciled +to this rule. Retained output, host-disconnect state and CLI behavior belong to +the specs that use the console. Nothing is implemented or verified. diff --git a/docs/index.md b/docs/index.md index 0e3f5c9d..daaa8b9b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -25,6 +25,7 @@ - [Optional execution integration (proposed)](adr/0006-optional-ai-execution.md) - [Explicit CI acceptance (proposed)](adr/0007-explicit-ci-acceptance.md) - [In-container AI agents, wave one (proposed)](adr/0009-in-container-ai-agents.md) +- [Persistent workspace console (proposed)](adr/0012-persistent-workspace-console.md) ## Background and references From b644b611de6bbee3d40eb6ce2792558b95af8971 Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Tue, 13 Oct 2026 23:09:07 +0200 Subject: [PATCH 6/8] docs(spec001): reconcile PTY cleanup with the persistent console Co-Authored-By: Claude Sonnet 5.5 --- specs/001-workspace-lifecycle/spec.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/specs/001-workspace-lifecycle/spec.md b/specs/001-workspace-lifecycle/spec.md index 315255f0..f358be15 100644 --- a/specs/001-workspace-lifecycle/spec.md +++ b/specs/001-workspace-lifecycle/spec.md @@ -19,7 +19,8 @@ require explicit trust. Clone/build errors expose redacted diagnostic events. ### US3 (P1): Access terminal From the running workspace, owner opens a browser terminal inside the container. Terminal grants are single-use, expire and cannot access another workspace/owner. -Disconnect cleans up the PTY; resizing and reconnect are bounded and observable. +Disconnect ends only the connection and releases its +relay; resizing and reconnect are bounded and observable. Host secrets, Docker socket and host shell are inaccessible through the session. ### US4 (P1): Stop, restart and recover @@ -46,13 +47,17 @@ host: UI displays unknown/stale state, then converges after authenticated reconn - Enrollment codes expire five minutes after creation. Expired, consumed and revoked codes fail without issuing an identity; consumption is atomic. - Terminal grants expire 60 seconds after issuance and are consumed atomically on - connection. An established session lasts at most eight hours and expires after - 15 minutes without owner input. Reconnect requires a new grant. At most two - sessions per workspace and eight per owner may be active; excess requests fail - with an explicit limit error. Each relay direction buffers at most 1 MiB per - session; overflow terminates that session with a diagnostic. Dimensions must be - within 1–500 columns and 1–200 rows. Disconnect releases the PTY within five - seconds, including when the transport disappears without a close frame. + connection. An established connection lasts at most eight hours and expires after + 15 minutes without owner input; either limit ends only the connection. Reconnect + requires a new grant. At most two connections per workspace and eight per owner + may be active; excess requests fail with an explicit limit error. Each relay + direction buffers at most 1 MiB per connection; overflow ends that connection + with a diagnostic. Dimensions must be within 1–500 columns and 1–200 rows. + Disconnect, grant expiry and idle timeout end only the connection and release + its relay within five seconds, including when the transport disappears without a + close frame; stop, rebuild, runtime deletion or an explicit close end the + console session + ([ADR 0012](../../docs/adr/0012-persistent-workspace-console.md)). - Before any config-provided executable hook, the owner explicitly approves a resolved config commit and the complete set of resolved submodule commits. Store this approval with owner, repository identity, revisions and timestamp. From e5c9f1598ef5566ed1a25329c4fcb8d9ff0cbd07 Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Tue, 13 Oct 2026 23:17:27 +0200 Subject: [PATCH 7/8] docs(spec001): reconcile tasks and data model with the persistent console Co-Authored-By: Claude Sonnet 5.5 --- docs/adr/0012-persistent-workspace-console.md | 10 ++++++++-- specs/001-workspace-lifecycle/data-model.md | 7 ++++--- specs/001-workspace-lifecycle/spec.md | 2 +- specs/001-workspace-lifecycle/tasks.md | 6 +++--- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/docs/adr/0012-persistent-workspace-console.md b/docs/adr/0012-persistent-workspace-console.md index c9fd4401..3d287a33 100644 --- a/docs/adr/0012-persistent-workspace-console.md +++ b/docs/adr/0012-persistent-workspace-console.md @@ -22,6 +22,12 @@ which conflicts with a console that outlives its connections. ## Consequences -The [feature 001 spec](../../specs/001-workspace-lifecycle/spec.md) is reconciled -to this rule. Retained output, host-disconnect state and CLI behavior belong to +The feature 001 [spec](../../specs/001-workspace-lifecycle/spec.md), +[tasks](../../specs/001-workspace-lifecycle/tasks.md) and +[data model](../../specs/001-workspace-lifecycle/data-model.md) are reconciled +to this rule. The wording of the feature 001 plan (lines 61-62) is flagged for +the plan's next revision. The persistent console-session state model (entity and +end events: stop, rebuild, deletion, explicit close) is follow-up work for the +spec that uses it; the existing Session entity and migration naming refers to the +single-use grant. Retained output, host-disconnect state and CLI behavior belong to the specs that use the console. Nothing is implemented or verified. diff --git a/specs/001-workspace-lifecycle/data-model.md b/specs/001-workspace-lifecycle/data-model.md index 5fa66573..2314fc9d 100644 --- a/specs/001-workspace-lifecycle/data-model.md +++ b/specs/001-workspace-lifecycle/data-model.md @@ -3,7 +3,7 @@ See [domain contracts](../../contracts/README.md) for required fields and transitions. Database foreign keys enforce workspace owner/host references. Unique operation key: (owner_id, workspace_id, idempotency_key); retain canonical request hash and outcome. -User ownership does not depend on repository fork ownership. Session expiry and +User ownership does not depend on repository fork ownership. Grant expiry and atomic consumed_at update enforce single use. Storage references outlive instances. Agent reports carry generation so stale reports cannot overwrite newer observations. @@ -12,7 +12,8 @@ config commit, complete submodule path/commit set and approved_at. Approval matc that exact revision set; any changed commit requires new approval. Provisioning commands carry the matching approval reference and revisions. Enrollment stores expires_at and atomic consumed_at; expiry is five minutes. -Session grants expire after 60 seconds; active relays enforce the spec's quotas, -maximum/idle lifetimes, dimensions and per-direction buffer limits. Host observations +Terminal grants expire after 60 seconds; active relays enforce the spec's +connection quotas per workspace and owner, per-connection maximum/idle lifetimes, +dimensions and per-direction buffer limits. Host observations become unknown after 30 seconds without authenticated heartbeat. Restore retains identities, revocations and operation outcomes but resets observations to unknown. diff --git a/specs/001-workspace-lifecycle/spec.md b/specs/001-workspace-lifecycle/spec.md index f358be15..98879d1c 100644 --- a/specs/001-workspace-lifecycle/spec.md +++ b/specs/001-workspace-lifecycle/spec.md @@ -72,7 +72,7 @@ host: UI displays unknown/stale state, then converges after authenticated reconn of 1, 2 and 4 seconds; exhausted or timed-out work remains visibly failed or unknown, retains storage, and requires an explicit retry operation. - Acceptance environment: one Linux Docker host, one control plane and one owner, - with up to five workspaces and eight terminal sessions. Record exact machine, + with up to five workspaces and eight terminal connections. Record exact machine, OS and tool versions. Measure time from the triggering event; timing tests use a responsive provider and report unavailable-host/provider cases separately. - Backup/restore must recover control-plane metadata and persistent project files diff --git a/specs/001-workspace-lifecycle/tasks.md b/specs/001-workspace-lifecycle/tasks.md index 2762a6ba..6e31622b 100644 --- a/specs/001-workspace-lifecycle/tasks.md +++ b/specs/001-workspace-lifecycle/tasks.md @@ -38,9 +38,9 @@ config and unapproved revisions produce no hooks or provider mutation. ## Phase 5: US3 — Access terminal Goal: browser terminal confined to the authorized container with finite resources. Independent acceptance: owner can type and resize; other-owner, expired/reused grants, -quota overflow and buffer overflow fail; transport loss cleans up the PTY. +quota overflow and buffer overflow fail; transport loss ends only the connection and releases its relay. -- [ ] T008 [US3] Implement atomic 60-second grants in `apps/control_plane/lib/workharbor/sessions.ex`, relay in `apps/control_plane/lib/workharbor_web/channels/terminal_channel.ex` and PTY service in `apps/host_agent/internal/terminal/`; enforce eight-hour maximum, 15-minute input idle expiry, two sessions/workspace, eight/owner, 1 MiB/direction, 1–500 columns, 1–200 rows and five-second disconnect cleanup; verify boundary/concurrent-use tests in both suites plus a real container PTY (FR-008, FR-011; SC-004). +- [ ] T008 [US3] Implement atomic 60-second grants in `apps/control_plane/lib/workharbor/sessions.ex`, relay in `apps/control_plane/lib/workharbor_web/channels/terminal_channel.ex` and PTY service in `apps/host_agent/internal/terminal/`; enforce eight-hour maximum, 15-minute input idle expiry, two connections/workspace, eight/owner, 1 MiB/direction, 1–500 columns and 1–200 rows, all per connection; disconnect, grant expiry and idle timeout end only the connection with the relay released within five seconds, while stop, rebuild, runtime deletion or an explicit close end the console session; verify boundary/concurrent-use tests in both suites plus a real container PTY (FR-008, FR-011; SC-004). - [ ] T018 [US3] Implement browser terminal UI in `apps/control_plane/lib/workharbor_web/live/terminal_live.ex` and `apps/control_plane/assets/js/terminal.js`; test input, resize, fresh-grant reconnect, limit diagnostics and absence of host-shell/socket access; record browser walkthrough in `docs/quality.md` (FR-008, FR-012). ## Phase 6: US4 — Stop, restart and recover @@ -54,7 +54,7 @@ one outcome, changed payload conflicts; interrupted provision reconciles safely. ## Phase 7: Release evidence and recovery - [ ] T019 Implement quiesced backup and clean-install restore in `scripts/backup-workharbor.sh`, `scripts/restore-workharbor.sh` and `docs/development/backup-restore.md`; verify retained owner/host/workspace associations, operation outcomes and exact uncommitted file contents, unknown restored observations, revoked-identity rejection and no automatic runtime start on a clean host; abort backup if quiescence fails (plan: backup/restore gate; SC-005). -- [ ] T010 Run US1–US4 and all SC-001–SC-006 at the specified five-workspace/eight-session load on a real host; record exact startup/test/browser commands, versions, timings, idle/load measurements and failure evidence in `specs/001-workspace-lifecycle/quickstart.md` and `docs/quality.md`; include tested rotation and backup/restore runbooks and rerun `make check` plus both application gates; missing tools/hosts block release (FR-001–FR-012). +- [ ] T010 Run US1–US4 and all SC-001–SC-006 at the specified five-workspace/eight-connection load on a real host; record exact startup/test/browser commands, versions, timings, idle/load measurements and failure evidence in `specs/001-workspace-lifecycle/quickstart.md` and `docs/quality.md`; include tested rotation and backup/restore runbooks and rerun `make check` plus both application gates; missing tools/hosts block release (FR-001–FR-012). ## Dependencies T001/T011 → T012 → T002 → T013 → T003 → T004 → T014 → T015. From ee0a66e8a971244fb70bca622c211f37be1d4acc Mon Sep 17 00:00:00 2001 From: Werner Stein Date: Wed, 14 Oct 2026 00:40:22 +0200 Subject: [PATCH 8/8] test(scope): rebind protected feature 001 baseline after reconciliation Owner decision H31:a (2026-10-14): specs/001 was amended under H22:a and H26:a. Rebind BASELINE 95b5bed59c91 to e5c9f1598ef5 and tree id specs/001-workspace-lifecycle 0fda80d6f62c to bae1fd2c3b42. Co-Authored-By: Claude Opus 5.5 --- tests/test_single_task_scope.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_single_task_scope.py b/tests/test_single_task_scope.py index 7899e3e2..34568410 100644 --- a/tests/test_single_task_scope.py +++ b/tests/test_single_task_scope.py @@ -536,9 +536,9 @@ def test(self): class ProtectedFeatureIdentityTests(unittest.TestCase): """T027 binds protected source trees to immutable pre-implementation bytes.""" - BASELINE = '95b5bed59c918bc100880771ac6be4d127b8edb7' + BASELINE = 'e5c9f1598ef5566ed1a25329c4fcb8d9ff0cbd07' TREES = { - 'specs/001-workspace-lifecycle': '0fda80d6f62c7576394495969187f349f7d0a81a', + 'specs/001-workspace-lifecycle': 'bae1fd2c3b428e90cf72dae500c56c3459204d94', 'specs/002-symphony-doc-smoke': '3b2dce04b696b247e21535c741759cc5633b514a', }