Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/claude/cowork.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Cowork is not an implemented session mode: no Cowork session can be created or r

`cowork/output-integration` now holds the whole native source stack, and none of it runs: the activation seam (`cowork/native-activation.ts`, `COWORK_NATIVE_ENVIRONMENT_ACTIVATED = false`) answers `undefined`, the host-env graph loads lazily behind it (`test/cowork/host-env-lazy.test.ts`), and no VM, Hypervisor.framework call or app launch has ever been made from it. Wire contract and revision history: [cowork-native-worker.md](../cowork-native-worker.md) (revision 3 added host-backed shares, cold resume and the guest file channel). There is no NIC and no vsock anywhere in it.

- **libkrun stack (SH2).** `apple/Cowork/WinterCoworkLibkrun` is a pinned patch queue (0004-0026) over upstream libkrun v1.19.6 with a reproducible build of one stripped archive that the worker links. Patches 0024-0026 are SH2: the confined virtio-fs server core, its git rules and quarantine, and the guarded fs device with the shares ABI gate. Nothing in the repository imports the directory (a test pins that); its README holds the pins and the rebuild steps. A release ships the worker only with the archive inputs ([release.md](./release.md#the-cowork-native-pair-is-an-explicit-choice)).
- **libkrun stack (SH2).** The libkrun patch-queue package under `apple/Cowork/` (not named by path outside CI: its anti-wiring guard refuses any other referrer) is a pinned patch queue (0004-0026) over upstream libkrun v1.19.6 with a reproducible build of one stripped archive that the worker links. Patches 0024-0026 are SH2: the confined virtio-fs server core, its git rules and quarantine, and the guarded fs device with the shares ABI gate. Nothing in the repository imports the directory (a test pins that); its README holds the pins and the rebuild steps. A release ships the worker only with the archive inputs ([release.md](./release.md#the-cowork-native-pair-is-an-explicit-choice)).
- **Host-backed shares over virtio-fs (SH6, guest side).** PID 1 (`apple/Cowork/WinterCoworkGuest/init/shares.c`) reads the virtio-fs tag inventory (it must equal the declared tags), mounts each share with `nosuid,nodev` and `dax=never` on a checked mount point's descriptor, then verifies every mount in `/proc/self/mountinfo`; any failure unmounts what it mounted. Three Winter shares are fixed: guidance at `/run/winter/shared-instructions` (read-only; PID 1 also links `/workspace/.winter/WINTER.md` to it), memory at `/workspace/.winter/memory` and outputs at `/workspace/outputs`, all `noexec`. A connected Mac folder is a guest share at `/workspace/folders/<name>` (mode 0700 mount point, `exec` kept because builds run there, read-only when the share is). Guest ownership and modes on a share are no boundary: the host serves shares under simplified ownership.
- **Plan view.** For a conversation under policy `plan`, PID 1 makes `/workspace/plan/<sid>/<epoch>` (contract 12.5) for its own conversation only: owned by the conversation's tool uid alone (0700, never the workspace group), parents never symlinks, refused when a later epoch already exists. The guest supervisor admits it writable only under `plan` and never below an epoch already made; the tool launcher mounts it writable for the file worker only.
- **Environment image `/etc/gitconfig`.** The image carries a fixed system gitconfig (`scripts/cowork-guest-artifact/environment/gitconfig`, hash pinned in `pins.json`): an empty git template directory, `core.hooksPath=/dev/null`, no fsmonitor, no credential helper, no include, `protocol.ext.allow=never`. The tool launcher mounts it read-only at `/etc/gitconfig` for the process worker; `verify.py` accepts exactly those settings and refuses a stray `/etc/gitconfig`.
Expand Down
2 changes: 1 addition & 1 deletion docs/claude/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ bun run scripts/release.ts # real release (bumps first; --
| `COWORK_LIBKRUN_INCLUDE` (the directory holding `libkrun.h`) AND `COWORK_LIBKRUN_ARCHIVE` (the stripped production archive) | build | `buildCoworkNative` builds the launcher (`swift build`) and the worker (`apple/Cowork/WinterCoworkHVFWorker/build.py`, which refuses unless the header and archive hash to that folder's `pins.json`) into `dist/cowork-native`; project.yml's "Embed Cowork native" phase (`scripts/embed-cowork-native.sh`) signs them into `Winter.app/Contents/Helpers/WinterCowork/` and writes `Contents/Resources/cowork-native-pins.json`. The release then verifies identifiers, team, hardened runtime, the stated designated requirement, entitlements (worker: the hypervisor key alone; launcher: none), platform dylibs only, no test hooks, and that the pin manifest's CDHashes and libkrun/worker/guest-artifact pins are the ones in this checkout. |
| `COWORK_NATIVE=omit` (and neither libkrun variable) | omit | Nothing is built or embedded: no `WinterCowork` helpers, no pins file. The release fails if a leftover from an earlier build is in the bundle (`checkCoworkNativeOmitted`). |

Anything else exits before any build with a message naming both ways out: neither given; only one of the two libkrun variables; `COWORK_NATIVE=omit` together with either libkrun variable; or any other value of `COWORK_NATIVE`. `omit` is never the default. `release.ts` does not build or fetch the libkrun archive; the patch queue and its reproducible build are in `apple/Cowork/WinterCoworkLibkrun` (`scripts/build_archive.py`), and its stripped archive is what `COWORK_LIBKRUN_ARCHIVE` points at. A release that must not wait on one uses `COWORK_NATIVE=omit`. `scripts/build-cowork-native.ts` reads the same two variables (or `--libkrun-include` / `--libkrun-archive`; `--launcher-only` skips the worker), and `embed-cowork-native.sh` itself also honours `COWORK_NATIVE=omit` and rejects any other value.
Anything else exits before any build with a message naming both ways out: neither given; only one of the two libkrun variables; `COWORK_NATIVE=omit` together with either libkrun variable; or any other value of `COWORK_NATIVE`. `omit` is never the default. `release.ts` does not build or fetch the libkrun archive; the patch queue and its reproducible build are in the libkrun patch-queue package under `apple/Cowork/` (its `scripts/build_archive.py`; deliberately not named by path outside CI, which its anti-wiring guard enforces), and its stripped archive is what `COWORK_LIBKRUN_ARCHIVE` points at. A release that must not wait on one uses `COWORK_NATIVE=omit`. `scripts/build-cowork-native.ts` reads the same two variables (or `--libkrun-include` / `--libkrun-archive`; `--launcher-only` skips the worker), and `embed-cowork-native.sh` itself also honours `COWORK_NATIVE=omit` and rejects any other value.

## Rolling back across a schema bump
A release that raises `RUNTIME_STATE_SCHEMA_VERSION` (the Cowork tables arrived in v8 to v17; v18 added the session binding, v19 the session reservations, v20 the export content binding, v21 the stable guest uids and cold-resume records; it is v21 now) cannot be undone by installing the older app: the older build refuses the newer store (`newer-schema`). A revert release reverts the feature, never the schema. The user-facing way back is `winter migrate --cowork-schema --rollback` with the newer CLI and the daemon stopped, before installing the older app (it accepts v8..v21, drops only empty Cowork tables and refuses with `cowork-data-present` if one holds a row); a store left at v18, v19 or v20 by an intermediate build needs the same step. Put that line in the release notes of any release that bumps the schema (see `docs/RELEASE-NOTES-cowork-schema.md`; what each version adds: [settings-and-migrations.md](./settings-and-migrations.md#runtime-state-schema-v21-and-the-way-back)).
2 changes: 1 addition & 1 deletion docs/cowork-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The 2026-10-12 text above (except the opening paragraph, which is re-dated and e
Everything below is source on the integration branch; none of it runs, and nothing has booted.

- **Still true: no Cowork session can be created.** `session.create {mode: "cowork"}` still answers `unsupported_topology` for every role. The session door's records exist (runtime-state schema v18 to v21: binding location, reservations, export content binding, stable guest uids and cold-resume records; see [settings-and-migrations.md](claude/settings-and-migrations.md#runtime-state-schema-v21-and-the-way-back)) but no door is switched on, and the native activation seam (`cowork/native-activation.ts`) answers `undefined`.
- **Native source now exists end to end, unwired.** The Swift launcher (`apple/Cowork/WinterCoworkLauncher`), the C VM worker (`apple/Cowork/WinterCoworkHVFWorker`), the host adapter and wire contract (`packages/core/src/cowork/native/`, [cowork-native-worker.md](cowork-native-worker.md), revision 3), the guest PID 1, relay and file channel (`apple/Cowork/WinterCoworkGuest`) and a pinned libkrun patch queue (`apple/Cowork/WinterCoworkLibkrun`, patches 0004-0026 over libkrun v1.19.6). The release script requires an explicit choice: `COWORK_NATIVE=omit` or both libkrun inputs ([release.md](claude/release.md#the-cowork-native-pair-is-an-explicit-choice)).
- **Native source now exists end to end, unwired.** The Swift launcher (`apple/Cowork/WinterCoworkLauncher`), the C VM worker (`apple/Cowork/WinterCoworkHVFWorker`), the host adapter and wire contract (`packages/core/src/cowork/native/`, [cowork-native-worker.md](cowork-native-worker.md), revision 3), the guest PID 1, relay and file channel (`apple/Cowork/WinterCoworkGuest`) and a pinned libkrun patch queue (the libkrun patch-queue package under `apple/Cowork/`, patches 0004-0026 over libkrun v1.19.6). The release script requires an explicit choice: `COWORK_NATIVE=omit` or both libkrun inputs ([release.md](claude/release.md#the-cowork-native-pair-is-an-explicit-choice)).
- **libkrun SH2:** the confined virtio-fs server core (0024), its git rules and quarantine (0025), and the guarded fs device with the shares ABI gate (0026).
- **Guest side of host-backed shares (SH6)** and the **plan view** `/workspace/plan/<sid>/<epoch>` are in the guest init; Mac folders are guest shares at `/workspace/folders/<name>` over virtio-fs; the memory share is at `/workspace/.winter/memory`; the image carries a fixed `/etc/gitconfig` for the process worker. Details: [cowork.md](claude/cowork.md#native-guest-stack-on-the-integration-branch-source-only-never-booted).
- **Cold resume:** the host half (store state, continuation, proven-ended boots) and the guest owner patch are both present; the host port is not supplied by any production composition, so a recorded-backend conversation still refuses `cold_resume_unavailable`.
Expand Down
Loading