From b63df9afc91ff24bcb304672a270c35e6de0936c Mon Sep 17 00:00:00 2001 From: "Bode (Kiro Crew Issue Radar)" Date: Wed, 26 Aug 2026 11:32:00 +0000 Subject: [PATCH 1/2] fix(kirocrew): mount EBS-backed workspace Fixes #105 Crew: Bode (Kiro Crew Issue Radar) --- deploy/bootstrap.sh | 32 +++++++ packs/kirocrew/PLAN.md | 2 +- packs/kirocrew/manifest.yaml | 2 +- .../resources/kirocrew-gateway.service | 1 + packs/registry.json | 2 +- packs/registry.yaml | 2 +- tests/test-kirocrew-ebs.sh | 83 +++++++++++++++++++ 7 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 tests/test-kirocrew-ebs.sh diff --git a/deploy/bootstrap.sh b/deploy/bootstrap.sh index 630b045..4066c4a 100755 --- a/deploy/bootstrap.sh +++ b/deploy/bootstrap.sh @@ -543,6 +543,38 @@ else info "Pack requests no data volume — skipping mount" fi +# ---- KiroCrew workspace data-volume mapping ---- +step "KiroCrew Workspace Mount" +if [[ "${PACK_NAME}" == "kirocrew" && "${DATA_VOL_GB}" -gt 0 && -d /mnt/ebs-data ]]; then + mkdir -p /mnt/ebs-data/workplace + if ! mountpoint -q /home/ec2-user/workplace; then + if [[ -L /home/ec2-user/workplace ]]; then + rm -f /home/ec2-user/workplace + elif [[ -d /home/ec2-user/workplace ]]; then + if find /home/ec2-user/workplace -mindepth 1 -maxdepth 1 -print -quit | grep -q .; then + cp -a /home/ec2-user/workplace/. /mnt/ebs-data/workplace/ + fi + rm -rf /home/ec2-user/workplace + elif [[ -e /home/ec2-user/workplace ]]; then + fail "KiroCrew workspace path exists but is not a directory" + exit 1 + fi + mkdir -p /home/ec2-user/workplace + mount --bind /mnt/ebs-data/workplace /home/ec2-user/workplace + fi + if ! grep -qF "/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0" /etc/fstab; then + echo "/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0" >> /etc/fstab + fi + chown ec2-user:ec2-user /mnt/ebs-data/workplace /home/ec2-user/workplace + ok "Bind-mounted KiroCrew workplace -> /mnt/ebs-data/workplace" +elif [[ "${PACK_NAME}" == "kirocrew" ]]; then + mkdir -p /home/ec2-user/workplace + chown ec2-user:ec2-user /home/ec2-user/workplace + info "KiroCrew workspace uses the root volume because no data volume is available" +else + info "KiroCrew workspace mount: skipped for ${PACK_NAME}" +fi + # ---- Enable systemd user session for ec2-user (needed by openclaw gateway) ---- loginctl enable-linger ec2-user 2>/dev/null || true # Wait for user runtime dir — linger starts the user manager asynchronously diff --git a/packs/kirocrew/PLAN.md b/packs/kirocrew/PLAN.md index 8072581..1095b9c 100644 --- a/packs/kirocrew/PLAN.md +++ b/packs/kirocrew/PLAN.md @@ -171,7 +171,7 @@ provides: instance_type: t4g.medium root_volume_gb: 40 -data_volume_gb: 0 +data_volume_gb: 80 experimental: true ``` diff --git a/packs/kirocrew/manifest.yaml b/packs/kirocrew/manifest.yaml index 26081f5..61c42df 100644 --- a/packs/kirocrew/manifest.yaml +++ b/packs/kirocrew/manifest.yaml @@ -53,6 +53,6 @@ provides: instance_type: t4g.medium root_volume_gb: 40 -data_volume_gb: 0 +data_volume_gb: 80 experimental: true diff --git a/packs/kirocrew/resources/kirocrew-gateway.service b/packs/kirocrew/resources/kirocrew-gateway.service index 545ef9a..6683090 100644 --- a/packs/kirocrew/resources/kirocrew-gateway.service +++ b/packs/kirocrew/resources/kirocrew-gateway.service @@ -31,6 +31,7 @@ ProtectHome=read-only # that kiro-cli subprocesses (spawned via ACP) may write to. ReadWritePaths=/home/ec2-user/.kiro ReadWritePaths=/home/ec2-user/.local +ReadWritePaths=/home/ec2-user/workplace ReadWritePaths=__HOME__ PrivateTmp=true diff --git a/packs/registry.json b/packs/registry.json index bf09b0c..cfe039c 100644 --- a/packs/registry.json +++ b/packs/registry.json @@ -133,7 +133,7 @@ "deps": [], "instance_type": "t4g.medium", "root_volume_gb": 40, - "data_volume_gb": 0, + "data_volume_gb": 80, "ports": { "gateway": 5476 }, diff --git a/packs/registry.yaml b/packs/registry.yaml index 440ccf5..7d2da6f 100644 --- a/packs/registry.yaml +++ b/packs/registry.yaml @@ -126,7 +126,7 @@ packs: deps: [] instance_type: t4g.medium root_volume_gb: 40 - data_volume_gb: 0 + data_volume_gb: 80 ports: gateway: 5476 brain: false diff --git a/tests/test-kirocrew-ebs.sh b/tests/test-kirocrew-ebs.sh new file mode 100644 index 0000000..44ead08 --- /dev/null +++ b/tests/test-kirocrew-ebs.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +# tests/test-kirocrew-ebs.sh — KiroCrew EBS workspace contract +# Verifies the pack requests a data volume and bootstrap maps the agent workspace +# onto that volume. The test is static because mounting requires a live EC2 host. + +set -euo pipefail + +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +MANIFEST="${ROOT_DIR}/packs/kirocrew/manifest.yaml" +REGISTRY_YAML="${ROOT_DIR}/packs/registry.yaml" +REGISTRY_JSON="${ROOT_DIR}/packs/registry.json" +BOOTSTRAP="${ROOT_DIR}/deploy/bootstrap.sh" +SERVICE="${ROOT_DIR}/packs/kirocrew/resources/kirocrew-gateway.service" + +PASS=0 +FAIL=0 + +pass() { printf '[PASS] %s\n' "$1"; PASS=$((PASS + 1)); } +fail() { printf '[FAIL] %s\n' "$1"; FAIL=$((FAIL + 1)); } + +if python3 - "$MANIFEST" <<'PY' +import sys +import yaml + +with open(sys.argv[1], encoding="utf-8") as stream: + data = yaml.safe_load(stream) +assert data["data_volume_gb"] == 80 +PY +then + pass "KiroCrew manifest requests an 80 GB data volume" +else + fail "KiroCrew manifest must request an 80 GB data volume" +fi + +if grep -A12 '^ kirocrew:' "$REGISTRY_YAML" | grep -q '^ data_volume_gb: 80$'; then + pass "KiroCrew YAML registry requests an 80 GB data volume" +else + fail "KiroCrew YAML registry must request an 80 GB data volume" +fi + +if python3 - "$REGISTRY_JSON" <<'PY' +import json +import sys + +with open(sys.argv[1], encoding="utf-8") as stream: + data = json.load(stream) +assert data["packs"]["kirocrew"]["data_volume_gb"] == 80 +PY +then + pass "KiroCrew generated registry requests an 80 GB data volume" +else + fail "KiroCrew generated registry must request an 80 GB data volume" +fi + +assert_bootstrap_contains() { + local pattern="$1" + local description="$2" + if grep -Fq "$pattern" "$BOOTSTRAP"; then + pass "$description" + else + fail "$description" + fi +} + +assert_bootstrap_contains \ + 'if [[ "${PACK_NAME}" == "kirocrew" && "${DATA_VOL_GB}" -gt 0 && -d /mnt/ebs-data ]]; then' \ + "bootstrap gates the workspace mapping on KiroCrew and a mounted data volume" +assert_bootstrap_contains \ + 'mount --bind /mnt/ebs-data/workplace /home/ec2-user/workplace' \ + "bootstrap bind-mounts the EBS workplace directory" +assert_bootstrap_contains \ + '/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0' \ + "bootstrap persists the workplace bind mount across reboots" +if grep -Fq 'ReadWritePaths=/home/ec2-user/workplace' "$SERVICE"; then + pass "KiroCrew gateway can write to the EBS-backed workplace" +else + fail "KiroCrew gateway must allow writes to the EBS-backed workplace" +fi + +printf '\nResults: PASS=%d FAIL=%d\n' "$PASS" "$FAIL" +if (( FAIL > 0 )); then + exit 1 +fi From 72fb2653000d13ab7b73916c00f882d6c2f939e3 Mon Sep 17 00:00:00 2001 From: "Bode (Kiro Crew Issue Radar)" Date: Wed, 26 Aug 2026 11:40:19 +0000 Subject: [PATCH 2/2] fix(kirocrew): make workspace mount boot-safe Address review feedback by making the dependent bind mount non-fatal when the EBS volume is unavailable, preserving mount ordering, and migrating the legacy fstab entry. --- deploy/bootstrap.sh | 6 ++++-- tests/test-kirocrew-ebs.sh | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/deploy/bootstrap.sh b/deploy/bootstrap.sh index 4066c4a..8ac3c85 100755 --- a/deploy/bootstrap.sh +++ b/deploy/bootstrap.sh @@ -562,8 +562,10 @@ if [[ "${PACK_NAME}" == "kirocrew" && "${DATA_VOL_GB}" -gt 0 && -d /mnt/ebs-data mkdir -p /home/ec2-user/workplace mount --bind /mnt/ebs-data/workplace /home/ec2-user/workplace fi - if ! grep -qF "/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0" /etc/fstab; then - echo "/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0" >> /etc/fstab + WORKPLACE_FSTAB_ENTRY="/mnt/ebs-data/workplace /home/ec2-user/workplace none bind,nofail,x-systemd.requires-mounts-for=/mnt/ebs-data 0 0" + sed -i '\|^/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0$|d' /etc/fstab + if ! grep -qF "${WORKPLACE_FSTAB_ENTRY}" /etc/fstab; then + printf '%s\n' "${WORKPLACE_FSTAB_ENTRY}" >> /etc/fstab fi chown ec2-user:ec2-user /mnt/ebs-data/workplace /home/ec2-user/workplace ok "Bind-mounted KiroCrew workplace -> /mnt/ebs-data/workplace" diff --git a/tests/test-kirocrew-ebs.sh b/tests/test-kirocrew-ebs.sh index 44ead08..ae8aedd 100644 --- a/tests/test-kirocrew-ebs.sh +++ b/tests/test-kirocrew-ebs.sh @@ -69,8 +69,8 @@ assert_bootstrap_contains \ 'mount --bind /mnt/ebs-data/workplace /home/ec2-user/workplace' \ "bootstrap bind-mounts the EBS workplace directory" assert_bootstrap_contains \ - '/mnt/ebs-data/workplace /home/ec2-user/workplace none bind 0 0' \ - "bootstrap persists the workplace bind mount across reboots" + '/mnt/ebs-data/workplace /home/ec2-user/workplace none bind,nofail,x-systemd.requires-mounts-for=/mnt/ebs-data 0 0' \ + "bootstrap persists a non-fatal workplace bind mount after the data volume" if grep -Fq 'ReadWritePaths=/home/ec2-user/workplace' "$SERVICE"; then pass "KiroCrew gateway can write to the EBS-backed workplace" else