Skip to content

Cowork: second landing (inert; nothing creatable or runnable) - #144

Merged
Winterrks merged 784 commits into
mainfrom
cowork/landing-2
Oct 25, 2026
Merged

Winterrks merged 784 commits into
mainfrom
cowork/landing-2

Conversation

@Winterrks

Copy link
Copy Markdown
Member

Second landing of cowork/output-integration onto main, as a real merge commit (no squash, no rebase). Draft: the owner approves the merge.

Cowork stays inert

Nothing is creatable or runnable. session.create {mode:"cowork"} still refuses every role with unsupported_topology (test/ipc/session-create-cowork.test.ts, session-cowork-row-refused.test.ts, sessions/session-mode.test.ts pass). Production supplies no Cowork environment, so the native wiring, provisioning port, held-input verbs and peer inbox stay unwired.

What lands (integration since the first landing, #106)

Not included

The egress broker and the provider bridge: held.

Conflict resolution

merge-tree against main reported 142 conflicted paths. #106 squashed integration at 6f4c71829 (#113's merge): #106's tree equals it exactly except four doc paths, which #106's own head added on top (v19 docs + schema-docs-pin.test.ts). Each path was merged three-way with #106 as the effective base, so main's side is only its own 38 commits.

  • (a) 133: main's version equals the squashed snapshot -> integration's version.
  • (b) 6: main's own commits. RoundTripTests.swift, parity-fixtures.test.ts (AskUserQuestion free text), runtime-sdk/embedded.ts, embedded-floor.test.ts (SDK 0.0.54 capability injection): integration had not touched them since the squash -> main's. cli/src/main.ts: main's AskUserQuestion CLI and integration's probe routes, disjoint hunks, both kept. fixtures/embedded-floor.ts: by hand, main's hostPathProtectionCapability: null plus integration's lifecycle-event wait.
  • (c) docs: RELEASE-NOTES-cowork-schema.md, docs/claude/release.md, settings-and-migrations.md -> integration's v21 versions under main's names; schema-docs-pin.test.ts kept from main (integration lacked it) and passes against v21.
  • (d) versions/pins: no conflicts. VERSION unchanged. Agent SDK pins differ: main 0.0.55, integration 0.0.53 -> 0.0.55 (main's). Runtime SDK ^0.0.16 on both. The guest image's SDK pin stays.

Non-Cowork behaviour this changes on main: every daemon runs migrations 20 and 21 on upgrade (empty Cowork tables); a Release build needs COWORK_NATIVE=omit or both libkrun inputs; the CI verify job gains two compiled-binary gates. SessionMessaging's send/list reshape answers only for a cowork caller; the projector's new system/host_input_committed case comes only from a Cowork runtime.

Tests run

  • bun install, bun run typecheck (all six projects): clean.
  • pnpm test: winter-for-chrome 123/123, protocol 256/256, core 11373 pass / 68 skip / 1 fail. The failure was http-read.test.ts's loopback TLS connect (identical to main); it passes on a rerun on its own (39/39). plugin-sdk 23/23 and cli 1633/1633 were run on their own after pnpm stopped at core.
  • bun test scripts/: 508/509. The one failure needs a prebuilt dist/winter, which a fresh worktree does not have.
  • Cowork guest Python (python3 -I -S -B -m unittest): bootstrap 198 OK, guest tests 304 OK, cowork-guest-artifact 135 OK, kernel 46 OK (Linux-only and root cases skipped on macOS).
  • Swift swift test (no failures): WinterProtocol 69 XCTest + 32 swift-testing, WinterKit 689 (1 skip), WinterChatKit 454 (1 skip), WinterBrowserHost 34, WinterComputerUse 194, WinterCUCore 1096 (11 skip), WinterCoworkLauncher 231, and 236 with -DWINTER_COWORK_TEST_BUILD.
  • App: xcodegen generate and a build-only Debug xcodebuild ... -derivedDataPath <scratch> build: BUILD SUCCEEDED. No xcodebuild test, no app launch, release.ts not run.

# Conflicts:
#	packages/core/src/cowork/guest-runtime.ts
…n acknowledged workspace across approval-only changes
…on set request, the driver's starter is that port narrowed to the running incarnation, and the router messaging attach is required for every runnable mode and absent for Cowork
cowork launcher: receipt MAC (text version 2) [stacked on #57]
…reclaim

test: the owned Git read slot-reclaim run asserts admission, not speed
… glob segments deny, plan scratch view pinned
…r; profile-swap, pause-cap and lock-order tests; note wording
…tests, the drain-window refusal, a guest that refuses a frame ends its runtime, and the D3 note (protected-read proof, NEEDS, owner decisions)
…h the plan view mounted (no slice mounts it yet)
…nconfirmed (test; the guard is exposed on the environment)
cowork launcher: key-equality lock order, profile-swap and pause-cap tests
cowork: landing review fixes (inert timers, hygiene, Mac row, CLI help, start-up cost)
cowork: doctor restore keeps the raw pre-restore copy; erase large peer-message bodies
…leaving a silent gap (nothing further held, held frames discarded, run stopped as a violation)
…t builds embed nothing, sparkle rig omits, verify gate covers every branch
…ng, descriptor-relative walk, opaque output ids, ACL check, intake call cap, resolved-import pins)
…test file shifts shard membership and exposes an older cross-file pollution)
…ed mount point's descriptor; a test-build-only owner lets the unprivileged test reach the refused mount(2); a root CI step proves the step, the mountinfo reader and every check on real mounts (tmpfs, ext4 with dax=never, the refused virtiofs call); a source-derived virtio-fs mountinfo fixture; 48 guard mutants; init re-pinned
- test_pid1_linux: the FileChannelPid1Tests workspace is shared by the class and the plan view's record of epochs is the disk itself, so epoch 9 made by the no-browse-uid test (rightly) made epoch 3 stale for the next test. The code was right (a lower epoch is never made again); the harness now removes the plan folder before each test, as a fresh data volume would.
- test_mutants: the browse-uid mutant's anchor was the text before the plan view changed that line; it now deletes the current guard (data roots would then be made for a workspace without a browse uid), a real guard mutant killed by the browse-uid test.
…tshare subcommands (dropped in the review fold), and a test that runs everywhere and fails when a subcommand the Linux tests use is missing from the driver
cowork guest: PID 1 makes the plan view /workspace/plan/<sid>/<epoch>
…the refused-before-mounting test counts mount(2) calls, exact-size payload truncations, two mountinfo parser cases, a root test of the alias owner, UMOUNT_NOFOLLOW on share unmounts, the named mutants (root-only ones run in CI's root step); init re-pinned
plan-view lows + gitconfig verify + SDK pin ec91fe06
…cowork/n2-sh6-guest-shares

# Conflicts:
#	.github/workflows/cowork-guest-boot.yml
#	apple/Cowork/WinterCoworkGuest/tests/linux_init_tool.c
#	scripts/cowork-guest-artifact/image.py
#	scripts/cowork-guest-artifact/pins.json
…criptor, the epoch scan's skips pinned by tests, verify requires the environment claim by default and refuses a stray /etc/gitconfig

- dataroots.c make_plan_dir: after fchmod the bits are read back from the held descriptor and a mismatch is refused (as make_one does); a test build interposes fchmod to lie, and a ratchet mutant removes the check.
- The epoch scan's leading-zero skip and the full-name digit check (i == n) are the lax side; a test now holds both (junk and non-canonical sibling names never make an epoch stale) and three ratchet mutants cover them. The two existing read-back mutants follow the new text.
- verify.py: require_environment defaults to True in the library (callers that checked an older root pass False explicitly); a cpio that carries /etc/gitconfig of its own is refused, claim or no claim (the image ships the file only under /opt/winter/environment/base).
- Guest source digests (init, relay, bootstrap helper) and the SDK pin ec91fe06 are already current; nothing moves.
… (UNPINNED), a set pin that differs stays a hard failure

- pins.json: guest.programs.init and winter-guest-relay binarySha256 are null (sourceSha256 unchanged): no Zig is run by a lane, so build 5 reports the digests it produces.
- image.py: build_guest keeps refusing a set pin that differs and now refuses a missing key; guest_binary_problems reports each null with the built digest and the build ends at exit 3 with the other unpinned fields. check_startup uses the built init when the pin is null.
- verify.py: a null init pin is read back only with allow_unpinned, against the init digest the root's own receipt claims (cpio and receipt must agree), and reports initPinned false; without the flag it is refused, a missing key is an error.
- Tests for null, mismatch and missing key; test_binary_pin_mutants.py (11 mutants, "treat a mismatch as unpinned" among them).
…n guards held for empty and wrongly typed pins, relay read-back, digests.json carries both guest digests

- dataroots.c make_one reads the leaf's mode back from the descriptor (02770, setgid included) and refuses a mismatch; the test fchmod can lie on the root's own mode ("leaf") or add the sticky bit ("special"), which also kills the 07777 -> 0777 mask mutant; the plan-directory comment is now true.
- image.py / verify.py: an empty or wrongly typed binary pin ('', 0, false, a list) is a hard failure, never unpinned (tests; mutants for truthiness and `not pinned_init`). verify.py also holds the relay to its pin (null only with allow_unpinned, read back against the receipt; a set pin must be the relay in the cpio, 0555, and the receipt must say so).
- Comments: the top-level etc is a symlink into the base, so a literal etc/gitconfig cpio entry would write through it.
- image_build_report.py: digests.json carries relaySha256 and initPinned / relayPinned beside initSha256, and problems() names an unpinned or stale guest binary pin.
Cowork image build 5 prep: #140 security-review lows, verify defaults
…and the guest init and relay binaries

Pinned exactly what build 5 produced (two identical builds, both receipts compared): expectedArtifact runtime/cpio/rootManifest and the five helper binary digests, runtimeArtifacts.ownerLibrary.binarySha256 and executable.sha256 (the launcher is unchanged), guest.programs.init and winter-guest-relay binarySha256 (were null). previousCommit stays 39ba77ec and previousExpectedArtifact is untouched.
…k/guest-image-build-6 (build 5's is spent and frozen); REVIEWED_HEAD stays zeros
… inputs, schema v21 rollback (accepts v8..v21), cowork.md and cowork-status.md brought up to the native stack on integration (docs only)
Cowork docs pass: native-pair release choice, schema v21 rollback, cowork docs up to date
Main's side resolved against #106 (ac25fde, the squash of integration at 6f4c718) as the
effective base: paths main changed only through that squash take integration's version; main's own
commits since (AskUserQuestion free text, SDK 0.0.54/0.0.55 pins, the embedded capability
injection) are kept. The embedded-floor fixture carries both main's absent-capability injection and
integration's lifecycle-event wait. The schema docs pin test from #106 stays and pins the v21 docs.
@Winterrks
Winterrks marked this pull request as ready for review October 25, 2026 04:17
@Winterrks
Winterrks merged commit e4435fa into main Oct 25, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant