Skip to content

Commit 4ef7a39

Browse files
committed
ci(cloak): stop the optional cloak image from gating releases
- release job no longer needs build-and-push-cloak; the cloak job is continue-on-error. A ~200MB Chromium bake per arch (arm64 under QEMU) must not sit on the critical path of a GitHub Release, and a flake in an optional layer must not fail a release whose artifact is deva.sh - cloak holds no agent CLIs and only changes when Dockerfile.cloak, cloak-entrypoint.sh or CLOAKBROWSER_WRAPPER_VERSION change -- never on a version bump. Nightly already skipped it for the same reason - release notes: :cloak is the rolling tag, :vX.Y.Z-cloak may lag - skill: goto(data:,{domcontentloaded}) not setContent() -- setContent hangs on a fresh daemon page waiting for a load event that never fires - dev log records the live proofs that close the 07-21 unverified gap: RFB 003.008 on :5900, CDP on :9222, connectOverCDP drives the live browser and the daemon survives client disconnect Refs #456
1 parent f90b836 commit 4ef7a39

5 files changed

Lines changed: 33 additions & 5 deletions

File tree

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ jobs:
169169
set -euo pipefail
170170
./scripts/test-install-agent-tooling.sh
171171
172+
- name: Smoke image/tag precedence
173+
shell: bash
174+
run: |
175+
set -euo pipefail
176+
./scripts/test-image-precedence.sh
177+
172178
- name: Smoke kimi auth wiring
173179
shell: bash
174180
run: |

.github/workflows/release.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,17 @@ jobs:
217217
RUST_DEFAULT_TOOLCHAIN=${{ needs.load-version-pins.outputs.rust_default_toolchain }}
218218
RUST_TARGETS=${{ needs.load-version-pins.outputs.rust_targets }}
219219
220+
# Optional, non-gating: the cloak layer bakes a ~200MB Chromium per arch
221+
# (arm64 under QEMU), holds no agent CLIs, and changes only when
222+
# Dockerfile.cloak / cloak-entrypoint.sh / CLOAKBROWSER_WRAPPER_VERSION move
223+
# -- not on a deva.sh version bump. The GitHub Release must not be hostage to
224+
# it, so `release` does not wait on this job and a failure here does not fail
225+
# the release. Re-run this job alone to publish a missing -cloak tag.
220226
build-and-push-cloak:
221227
name: Build and Push Cloak Profile Image
222228
runs-on: ubuntu-latest
223229
needs: [prepare, load-version-pins, build-and-push-rust]
230+
continue-on-error: true
224231
permissions:
225232
contents: read
226233
packages: write
@@ -270,7 +277,7 @@ jobs:
270277
release:
271278
name: Create GitHub Release
272279
runs-on: ubuntu-latest
273-
needs: [prepare, build-and-push, build-and-push-rust, build-and-push-cloak]
280+
needs: [prepare, build-and-push, build-and-push-rust]
274281
permissions:
275282
contents: write
276283
steps:
@@ -309,9 +316,9 @@ jobs:
309316
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:${RELEASE_TAG}-rust\`" >> release_notes.md
310317
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:rust\`" >> release_notes.md
311318
echo "" >> release_notes.md
312-
echo "**Cloak Profile (CloakBrowser stealth Chromium, headed):**" >> release_notes.md
313-
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:${RELEASE_TAG}-cloak\`" >> release_notes.md
319+
echo "**Cloak Profile (CloakBrowser stealth Chromium, headed) - optional:**" >> release_notes.md
314320
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:cloak\`" >> release_notes.md
321+
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:${RELEASE_TAG}-cloak\` (published when the non-gating cloak build finishes; it may lag this release)" >> release_notes.md
315322
echo "" >> release_notes.md
316323
echo "## Supported Architectures" >> release_notes.md
317324
echo "" >> release_notes.md

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5050
in versions.env pins the wrapper and thereby Chromium. Ships the
5151
`deva-cloak` skill (keyed off `DEVA_CLOAK=1`), `make build-cloak` /
5252
`test-cloak` targets, a paths-filtered `cloak-image.yml` CI workflow,
53-
and release pushes `:cloak` / `:vX.Y.Z-cloak` tags. Nightly skips cloak
54-
on purpose — that layer contains no agent CLIs.
53+
and release pushes `:cloak` / `:vX.Y.Z-cloak` tags. cloak is an auxiliary
54+
image on its own cadence: nightly skips it (that layer holds no agent
55+
CLIs) and the release cloak job is non-gating (`continue-on-error`, not
56+
in the `release` job's `needs`) — a ~200MB Chromium bake per arch must
57+
never hold the GitHub Release hostage.
5558

5659
### Fixed
5760
- `--trace` launch killed by `cp: cannot create regular file

DEV-LOGS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@
1313
- Minimal markdown markers, no unnecessary formatting, minimal emojis.
1414
- Reference issue numbers in the format `#<issue-number>` for easy linking.
1515

16+
# [2026-07-27] Dev Log: cloak release policy + closing the unverified VNC/daemon gap #456
17+
- Why: two loose ends before shipping. (1) The 2026-07-21 entry left "x11vnc serving RFB and a live daemon inside the built image" unverified — that env couldn't apt-install. (2) release.yml made the GitHub Release `needs` the cloak build, so a ~200MB Chromium bake per arch (arm64 under QEMU) sat on the critical path of every release, including patch releases that touch nothing in that layer.
18+
- What:
19+
- Live verification against the built `:cloak` image (wrapper 0.5.2, Chrome 146.0.7680.177): x11vnc answers the RFB handshake on :5900 with `RFB 003.008`; cloak-browserd serves CDP on 127.0.0.1:9222; a separate playwright-core client `connectOverCDP`s, drives a page, and the daemon survives that client's `close()`. Stealth confirmed live: UA spoofs `Windows NT 10.0`, `navigator.webdriver === false`. First probe raced the daemons — both are up ~4s after boot, so poll the ports, don't poll only the display.
20+
- Agent-facing footgun found while proving it: `page.setContent()` on a fresh daemon page hangs waiting for a `load` event that never fires. `goto('data:text/html,...', {waitUntil:'domcontentloaded'})` is the working equivalent — documented in the skill.
21+
- Release policy: cloak is an auxiliary image on its own cadence, NOT a general releasable profile. It holds no agent CLIs, and its content only moves when Dockerfile.cloak / cloak-entrypoint.sh / CLOAKBROWSER_WRAPPER_VERSION move — never on a deva.sh version bump. So the cloak job is now `continue-on-error: true` and is OUT of the `release` job's `needs`; release notes present `:cloak` as the rolling tag and mark `:vX.Y.Z-cloak` as possibly lagging. Nightly already skipped cloak for the same reason.
22+
- Result: all four live proofs pass; `make test-cloak` green. The structural point: an optional 200MB capability layer must never be able to fail the mandatory release artifact. Follow-up filed for the profile registry — profile identity is currently duplicated across deva.sh, Makefile, and three workflows.
23+
1624
# [2026-07-21] Dev Log: cloak always-on browser + VNC + persistent profile #456
1725
- Why: three asks for auth sites in the cloak browser — (1) VNC auto-secured with a password, (2) an always-on browser the agent can drive freely, (3) mount what preserves the whole session to the host. Verified the load-bearing assumption first in a throwaway cloak container: a persistent CloakBrowser launched with `--remote-debugging-port` exposes a CDP endpoint a SEPARATE Playwright client reaches via connectOverCDP, drives, and the browser survives that client disconnecting. So one daemon can back both the human (VNC) and the agent (CDP).
1826
- What:

skills/deva-cloak/SKILL.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ await b.close(); // detaches; the daemon browser stays
164164
absence means there is no daemon and you should launch your own browser as
165165
above.
166166
167+
Use `goto()`, not `setContent()`: on a fresh daemon page `setContent` waits for
168+
a `load` event that never fires and times out. `page.goto('data:text/html,...',
169+
{waitUntil: 'domcontentloaded'})` is the working equivalent for injected markup.
170+
167171
**Persistence / what to mount.** `--cloak-vnc` (and `--cloak-browser`)
168172
auto-mounts `~/.config/deva/cloak-profile` (host) to the Chromium `userDataDir`
169173
`/home/deva/.cloak-profile`. That one dir is the whole session -- cookies,

0 commit comments

Comments
 (0)