Skip to content

Commit 0757423

Browse files
committed
Merge main into upgrade mounts PR
2 parents 946efa8 + fc4a95f commit 0757423

42 files changed

Lines changed: 3975 additions & 721 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.deva.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,34 @@ EPHEMERAL=false
4949
#
5050
# 6. Disable ephemeral containers (persistent):
5151
# EPHEMERAL=false
52+
#
53+
# 7. Enable Codex browser MCP for this project:
54+
# DEFAULT_AGENT=codex
55+
# CODEX_BROWSER_MCP=true
56+
#
57+
# Optional session-only Codex config overrides:
58+
# CODEX_CONFIG=features.apps=false
59+
# CODEX_CONFIG=features.plugins=false
60+
61+
# Hybrid Agent Setup:
62+
#
63+
# Hybrid is the DEFAULT. deva walks every populated subdir under
64+
# ~/.config/deva/ (claude, codex, gemini) and mounts each agent's
65+
# canonical entries into the container. Populated = you either
66+
# hand-created the subdir or autolink symlinked it from legacy
67+
# ~/.claude, ~/.codex, ~/.gemini on first run.
68+
#
69+
# No .deva entries required for the common case. To opt OUT of
70+
# hybrid for a single invocation, pass --config-home DIR to
71+
# isolate that run to a single home.
72+
#
73+
# Use VOLUME= only when you want to mount host paths OUTSIDE
74+
# ~/.config/deva/ (e.g. a shared secrets vault) at an agent target.
75+
# VOLUME= entries win over the default per-agent mount at the same
76+
# container target (first-writer-wins; CLI -v beats .deva).
77+
#
78+
# Auth credentials inside mounted agent dirs ride along — hybrid
79+
# only makes sense if you trust every agent equally.
5280

5381
# Project-Specific Config (.deva in project root):
5482
#

.github/workflows/ci.yml

Lines changed: 99 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ jobs:
4444
chmod +x scripts/version-check.sh
4545
./scripts/version-check.sh
4646
47-
- name: Test versions-up build args
48-
shell: bash
49-
run: bash ./tests/version-upgrade.sh
47+
- name: Unit tests (release-utils.sh)
48+
run: bash tests/test_release_utils.sh
49+
50+
- name: Unit tests (version-upgrade.sh)
51+
run: bash tests/version-upgrade.sh
5052

5153
smoke:
5254
name: Installer Smoke Test
@@ -55,25 +57,30 @@ jobs:
5557
- name: Checkout
5658
uses: actions/checkout@v4
5759

58-
- name: Setup Node
59-
uses: actions/setup-node@v4
60-
with:
61-
node-version: "24"
62-
63-
- name: Resolve tool versions
64-
id: versions
65-
env:
66-
GH_TOKEN: ${{ github.token }}
67-
run: bash ./scripts/resolve-tool-versions.sh
60+
- name: Load pinned versions
61+
id: pins
62+
shell: bash
63+
run: |
64+
set -euo pipefail
65+
source ./scripts/version-pins.sh
66+
load_version_pins
67+
emit_github_outputs "$GITHUB_OUTPUT"
6868
6969
- name: Build local smoke image
7070
run: |
7171
docker build -t deva-smoke:ci \
72-
--build-arg CLAUDE_CODE_VERSION="${{ steps.versions.outputs.claude_code_version }}" \
73-
--build-arg CODEX_VERSION="${{ steps.versions.outputs.codex_version }}" \
74-
--build-arg GEMINI_CLI_VERSION="${{ steps.versions.outputs.gemini_cli_version }}" \
75-
--build-arg ATLAS_CLI_VERSION="${{ steps.versions.outputs.atlas_cli_version }}" \
76-
--build-arg COPILOT_API_VERSION="${{ steps.versions.outputs.copilot_api_version }}" \
72+
--build-arg NODE_MAJOR="${{ steps.pins.outputs.node_major }}" \
73+
--build-arg GO_VERSION="${{ steps.pins.outputs.go_version }}" \
74+
--build-arg PYTHON_VERSION="${{ steps.pins.outputs.python_version }}" \
75+
--build-arg DELTA_VERSION="${{ steps.pins.outputs.delta_version }}" \
76+
--build-arg TMUX_VERSION="${{ steps.pins.outputs.tmux_version }}" \
77+
--build-arg TMUX_SHA256="${{ steps.pins.outputs.tmux_sha256 }}" \
78+
--build-arg CLAUDE_CODE_VERSION="${{ steps.pins.outputs.claude_code_version }}" \
79+
--build-arg CLAUDE_TRACE_VERSION="${{ steps.pins.outputs.claude_trace_version }}" \
80+
--build-arg CODEX_VERSION="${{ steps.pins.outputs.codex_version }}" \
81+
--build-arg GEMINI_CLI_VERSION="${{ steps.pins.outputs.gemini_cli_version }}" \
82+
--build-arg ATLAS_CLI_VERSION="${{ steps.pins.outputs.atlas_cli_version }}" \
83+
--build-arg COPILOT_API_VERSION="${{ steps.pins.outputs.copilot_api_version }}" \
7784
.
7885
7986
- name: Build core and rust images via Makefile
@@ -83,28 +90,22 @@ jobs:
8390
TAG=ci \
8491
CORE_TAG=ci-core \
8592
RUST_TAG=ci-rust \
86-
CLAUDE_CODE_VERSION="${{ steps.versions.outputs.claude_code_version }}" \
87-
CODEX_VERSION="${{ steps.versions.outputs.codex_version }}" \
88-
GEMINI_CLI_VERSION="${{ steps.versions.outputs.gemini_cli_version }}" \
89-
ATLAS_CLI_VERSION="${{ steps.versions.outputs.atlas_cli_version }}" \
90-
COPILOT_API_VERSION="${{ steps.versions.outputs.copilot_api_version }}"
91-
92-
- name: Smoke rust runtime and browser tooling
93-
shell: bash
94-
run: |
95-
set -euo pipefail
96-
docker run --rm deva-smoke:ci-rust bash -lc '
97-
bwrap --version
98-
go version | grep "go1.26.2"
99-
playwright --version
100-
playwright-mcp --help >/dev/null
101-
playwright install --list
102-
if command -v google-chrome >/dev/null 2>&1; then
103-
google-chrome --version
104-
else
105-
echo "google-chrome not installed on $(dpkg --print-architecture)"
106-
fi
107-
'
93+
NODE_MAJOR="${{ steps.pins.outputs.node_major }}" \
94+
GO_VERSION="${{ steps.pins.outputs.go_version }}" \
95+
PYTHON_VERSION="${{ steps.pins.outputs.python_version }}" \
96+
DELTA_VERSION="${{ steps.pins.outputs.delta_version }}" \
97+
TMUX_VERSION="${{ steps.pins.outputs.tmux_version }}" \
98+
TMUX_SHA256="${{ steps.pins.outputs.tmux_sha256 }}" \
99+
CLAUDE_CODE_VERSION="${{ steps.pins.outputs.claude_code_version }}" \
100+
CLAUDE_TRACE_VERSION="${{ steps.pins.outputs.claude_trace_version }}" \
101+
CODEX_VERSION="${{ steps.pins.outputs.codex_version }}" \
102+
GEMINI_CLI_VERSION="${{ steps.pins.outputs.gemini_cli_version }}" \
103+
ATLAS_CLI_VERSION="${{ steps.pins.outputs.atlas_cli_version }}" \
104+
COPILOT_API_VERSION="${{ steps.pins.outputs.copilot_api_version }}" \
105+
PLAYWRIGHT_VERSION="${{ steps.pins.outputs.playwright_version }}" \
106+
RUST_TOOLCHAINS="${{ steps.pins.outputs.rust_toolchains }}" \
107+
RUST_DEFAULT_TOOLCHAIN="${{ steps.pins.outputs.rust_default_toolchain }}" \
108+
RUST_TARGETS="${{ steps.pins.outputs.rust_targets }}"
108109
109110
- name: Install and launch each agent without a TTY
110111
shell: bash
@@ -148,6 +149,26 @@ jobs:
148149
grep -F -- "$bridge_dir:/deva-host-chrome-bridge" <<<"$dry_run"
149150
grep -F -- "$profile_dir/Extensions:/home/deva/.config/google-chrome/Default/Extensions:ro" <<<"$dry_run"
150151
152+
- name: Smoke bind mount shape guard
153+
shell: bash
154+
run: |
155+
set -euo pipefail
156+
DEVA_DOCKER_IMAGE=deva-smoke \
157+
DEVA_DOCKER_TAG=ci \
158+
./scripts/test-mount-shape.sh
159+
160+
- name: Smoke agent tooling installer
161+
shell: bash
162+
run: |
163+
set -euo pipefail
164+
./scripts/test-install-agent-tooling.sh
165+
166+
- name: Smoke version targets
167+
shell: bash
168+
run: |
169+
set -euo pipefail
170+
./scripts/test-version-targets.sh
171+
151172
- name: Smoke Chrome bridge entrypoint symlink
152173
shell: bash
153174
run: |
@@ -168,6 +189,44 @@ jobs:
168189
deva-smoke:ci \
169190
bash -lc 'link="/tmp/claude-mcp-browser-bridge-$(id -un)"; test -L "$link"; test "$(readlink "$link")" = "/deva-host-chrome-bridge"'
170191
192+
- name: Smoke tmux-bridge CLI surface
193+
shell: bash
194+
run: |
195+
set -euo pipefail
196+
# tmux-bridge is the layer-2 agent comms CLI vendored from smux.
197+
# We assert it's installed, executable, runs outside a tmux pane for
198+
# the version/help/id error paths, and that tmux itself is present
199+
# so a future operator can drive tmux-bridge against host tmux.
200+
docker run --rm deva-smoke:ci bash -lc '
201+
set -euo pipefail
202+
command -v tmux-bridge
203+
command -v tmux
204+
tmux-bridge version
205+
tmux-bridge --help | grep -q "cross-pane communication"
206+
# id requires $TMUX_PANE; outside tmux it must error cleanly.
207+
if tmux-bridge id 2>/dev/null; then
208+
echo "tmux-bridge id should fail outside a tmux pane" >&2
209+
exit 1
210+
fi
211+
# Ephemeral tmux server to prove list/name/read/type work end-to-end.
212+
sock="/tmp/tmux-smoke.sock"
213+
tmux -S "$sock" new-session -d -s smoke "sleep 30"
214+
export TMUX_BRIDGE_SOCKET="$sock"
215+
tmux-bridge list | tee /tmp/list.out
216+
grep -q "smoke:0" /tmp/list.out
217+
target="$(tmux -S "$sock" display-message -p "#{pane_id}")"
218+
tmux-bridge name "$target" smoke-worker
219+
tmux-bridge resolve smoke-worker
220+
tmux-bridge read "$target" 5 >/dev/null
221+
# read-guard: must read before type; second type without read must fail
222+
tmux-bridge type smoke-worker "echo hi"
223+
if tmux-bridge type smoke-worker "echo twice" 2>/dev/null; then
224+
echo "read-guard should have blocked second type without read" >&2
225+
exit 1
226+
fi
227+
tmux -S "$sock" kill-server
228+
'
229+
171230
docs:
172231
name: Docs Build
173232
runs-on: ubuntu-latest

.github/workflows/nightly-images.yml

Lines changed: 45 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ on:
88
env:
99
REGISTRY: ghcr.io
1010
IMAGE_NAME: thevibeworks/deva
11-
GO_VERSION: 1.26.2
12-
PLAYWRIGHT_VERSION: 1.59.1
13-
PLAYWRIGHT_MCP_VERSION: 0.0.70
1411

1512
permissions:
1613
contents: read
@@ -21,6 +18,34 @@ concurrency:
2118
cancel-in-progress: true
2219

2320
jobs:
21+
load-version-pins:
22+
name: Load Pinned Toolchain Versions
23+
runs-on: ubuntu-latest
24+
outputs:
25+
node_major: ${{ steps.pins.outputs.node_major }}
26+
go_version: ${{ steps.pins.outputs.go_version }}
27+
python_version: ${{ steps.pins.outputs.python_version }}
28+
delta_version: ${{ steps.pins.outputs.delta_version }}
29+
tmux_version: ${{ steps.pins.outputs.tmux_version }}
30+
tmux_sha256: ${{ steps.pins.outputs.tmux_sha256 }}
31+
claude_trace_version: ${{ steps.pins.outputs.claude_trace_version }}
32+
playwright_version: ${{ steps.pins.outputs.playwright_version }}
33+
rust_toolchains: ${{ steps.pins.outputs.rust_toolchains }}
34+
rust_default_toolchain: ${{ steps.pins.outputs.rust_default_toolchain }}
35+
rust_targets: ${{ steps.pins.outputs.rust_targets }}
36+
steps:
37+
- name: Checkout
38+
uses: actions/checkout@v4
39+
40+
- name: Load pins
41+
id: pins
42+
shell: bash
43+
run: |
44+
set -euo pipefail
45+
source ./scripts/version-pins.sh
46+
load_version_pins
47+
emit_github_outputs "$GITHUB_OUTPUT"
48+
2449
resolve-versions:
2550
name: Resolve Latest Tool Versions
2651
runs-on: ubuntu-latest
@@ -38,7 +63,7 @@ jobs:
3863
- name: Setup Node
3964
uses: actions/setup-node@v4
4065
with:
41-
node-version: "24"
66+
node-version: "22"
4267

4368
- name: Resolve versions
4469
id: versions
@@ -62,7 +87,7 @@ jobs:
6287
6388
build-base:
6489
name: Build Nightly Base Image
65-
needs: [resolve-versions, build-core]
90+
needs: [load-version-pins, resolve-versions]
6691
runs-on: ubuntu-latest
6792
steps:
6893
- name: Checkout
@@ -105,65 +130,22 @@ jobs:
105130
cache-from: type=gha,scope=nightly-base
106131
cache-to: type=gha,mode=max,scope=nightly-base
107132
build-args: |
133+
NODE_MAJOR=${{ needs.load-version-pins.outputs.node_major }}
134+
GO_VERSION=${{ needs.load-version-pins.outputs.go_version }}
135+
PYTHON_VERSION=${{ needs.load-version-pins.outputs.python_version }}
136+
DELTA_VERSION=${{ needs.load-version-pins.outputs.delta_version }}
137+
TMUX_VERSION=${{ needs.load-version-pins.outputs.tmux_version }}
138+
TMUX_SHA256=${{ needs.load-version-pins.outputs.tmux_sha256 }}
108139
CLAUDE_CODE_VERSION=${{ needs.resolve-versions.outputs.claude_code_version }}
140+
CLAUDE_TRACE_VERSION=${{ needs.load-version-pins.outputs.claude_trace_version }}
109141
CODEX_VERSION=${{ needs.resolve-versions.outputs.codex_version }}
110142
GEMINI_CLI_VERSION=${{ needs.resolve-versions.outputs.gemini_cli_version }}
111143
ATLAS_CLI_VERSION=${{ needs.resolve-versions.outputs.atlas_cli_version }}
112144
COPILOT_API_VERSION=${{ needs.resolve-versions.outputs.copilot_api_version }}
113-
GO_VERSION=${{ env.GO_VERSION }}
114-
115-
build-core:
116-
name: Build Nightly Core Image
117-
needs: resolve-versions
118-
runs-on: ubuntu-latest
119-
steps:
120-
- name: Checkout
121-
uses: actions/checkout@v4
122-
123-
- name: Set up QEMU
124-
uses: docker/setup-qemu-action@v3
125-
126-
- name: Set up Docker Buildx
127-
uses: docker/setup-buildx-action@v3
128-
129-
- name: Log in to Container Registry
130-
uses: docker/login-action@v3
131-
with:
132-
registry: ${{ env.REGISTRY }}
133-
username: ${{ github.actor }}
134-
password: ${{ secrets.GITHUB_TOKEN }}
135-
136-
- name: Extract metadata
137-
id: meta-core
138-
uses: docker/metadata-action@v5
139-
with:
140-
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
141-
tags: |
142-
type=raw,value=nightly-core
143-
type=raw,value=nightly-${{ needs.resolve-versions.outputs.stamp }}-core
144-
labels: |
145-
org.opencontainers.image.title=deva-nightly-core
146-
org.opencontainers.image.description=Nightly deva core image for downstream profile builds
147-
148-
- name: Build and push core image
149-
uses: docker/build-push-action@v5
150-
with:
151-
context: .
152-
file: ./Dockerfile
153-
target: agent-base
154-
platforms: linux/amd64,linux/arm64
155-
push: true
156-
tags: ${{ steps.meta-core.outputs.tags }}
157-
labels: ${{ steps.meta-core.outputs.labels }}
158-
cache-from: type=gha,scope=nightly-core
159-
cache-to: type=gha,mode=max,scope=nightly-core
160-
build-args: |
161-
COPILOT_API_VERSION=${{ needs.resolve-versions.outputs.copilot_api_version }}
162-
GO_VERSION=${{ env.GO_VERSION }}
163145
164146
build-rust:
165147
name: Build Nightly Rust Image
166-
needs: [resolve-versions, build-core]
148+
needs: [load-version-pins, resolve-versions, build-base]
167149
runs-on: ubuntu-latest
168150
steps:
169151
- name: Checkout
@@ -206,26 +188,27 @@ jobs:
206188
cache-from: type=gha,scope=nightly-rust
207189
cache-to: type=gha,mode=max,scope=nightly-rust
208190
build-args: |
209-
BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${{ needs.resolve-versions.outputs.stamp }}-core
191+
BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${{ needs.resolve-versions.outputs.stamp }}
210192
CLAUDE_CODE_VERSION=${{ needs.resolve-versions.outputs.claude_code_version }}
193+
CLAUDE_TRACE_VERSION=${{ needs.load-version-pins.outputs.claude_trace_version }}
211194
CODEX_VERSION=${{ needs.resolve-versions.outputs.codex_version }}
212195
GEMINI_CLI_VERSION=${{ needs.resolve-versions.outputs.gemini_cli_version }}
213196
ATLAS_CLI_VERSION=${{ needs.resolve-versions.outputs.atlas_cli_version }}
214-
PLAYWRIGHT_VERSION=${{ env.PLAYWRIGHT_VERSION }}
215-
PLAYWRIGHT_MCP_VERSION=${{ env.PLAYWRIGHT_MCP_VERSION }}
197+
PLAYWRIGHT_VERSION=${{ needs.load-version-pins.outputs.playwright_version }}
198+
RUST_TOOLCHAINS=${{ needs.load-version-pins.outputs.rust_toolchains }}
199+
RUST_DEFAULT_TOOLCHAIN=${{ needs.load-version-pins.outputs.rust_default_toolchain }}
200+
RUST_TARGETS=${{ needs.load-version-pins.outputs.rust_targets }}
216201
217202
summary:
218203
name: Nightly Summary
219-
needs: [resolve-versions, build-core, build-base, build-rust]
204+
needs: [resolve-versions, build-base, build-rust]
220205
runs-on: ubuntu-latest
221206
steps:
222207
- name: Publish summary
223208
run: |
224209
cat <<EOF >> "$GITHUB_STEP_SUMMARY"
225210
## Published Nightly Images
226211
227-
- \`ghcr.io/thevibeworks/deva:nightly-core\`
228-
- \`ghcr.io/thevibeworks/deva:nightly-${{ needs.resolve-versions.outputs.stamp }}-core\`
229212
- \`ghcr.io/thevibeworks/deva:nightly\`
230213
- \`ghcr.io/thevibeworks/deva:nightly-${{ needs.resolve-versions.outputs.stamp }}\`
231214
- \`ghcr.io/thevibeworks/deva:nightly-rust\`

0 commit comments

Comments
 (0)