docs: define the single-image single-stack isolation contract - #37
Conversation
|
@coderabbitai full review Please verify the architecture contract for internal consistency, distinguish current behavior from planned behavior, flag contradictions with existing documentation, and check Markdown quality. Do not suggest runtime implementation changes in this documentation-only PR unless the documentation would otherwise promise unsupported behavior. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a2015d7027
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '=== PR metadata and changed files ==='
git status --short
git diff --name-status HEAD^ HEAD
echo
echo '=== Diff (documentation changes) ==='
git diff --unified=80 HEAD^ HEAD -- '*.md' '*.mdx' '*.markdown' || true
echo
echo '=== Markdown/document inventory ==='
fd -HI -t f -e md -e mdx -e markdown . | sort
echo
echo '=== Contract-related references outside changed docs ==='
rg -n -i -C 3 \
'child[- ]image|single[- ]image|single[- ]stack|launcher|bubblewrap|docker socket|privileged|codex|antigravity|claude|isolat(ed|ion)|agent service|remote dev' \
-g '*.md' -g '*.mdx' -g '*.markdown' . || true
echo
echo '=== Markdown tooling/configuration ==='
fd -HI -t f '(^|/)(\.markdownlint.*|markdownlint.*|package\.json|\.remarkrc.*|remark\.config\..*)$' . -x sh -c 'echo "--- $1"; sed -n "1,220p" "$1"' sh {} \; || true
echo
echo '=== Markdown links in changed files ==='
git diff --name-only HEAD^ HEAD -- '*.md' '*.mdx' '*.markdown' \
| while IFS= read -r file; do
echo "--- $file"
rg -n '\[[^]]+\]\([^)]+\)|<https?://[^>]+>|https?://[^[:space:])>]+' "$file" || true
doneLength of output: 60618 🏁 Script executed: #!/bin/bash
set -euo pipefail
base="$(git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main)"
echo "=== Merge base: $base ==="
echo "=== Full PR changed files ==="
git diff --name-status "$base"...HEAD
echo
echo "=== Full PR stats ==="
git diff --stat "$base"...HEAD
echo
echo "=== Architecture-document diff ==="
git diff --unified=30 "$base"...HEAD -- \
README.md README.es.md PROJECT_STATUS.md CHANGELOG.md \
docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md \
docs/security.md docs/releases.md
echo
echo "=== Final focused documents with line numbers ==="
for file in README.md CHANGELOG.md docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md PROJECT_STATUS.md; do
if [ -f "$file" ]; then
echo "--- $file"
nl -ba "$file"
fi
done
echo
echo "=== Referenced issues and compatibility/image terminology ==="
rg -n -C 2 \
'(issue|Issue) #(24|25|31|36)|codex-remote-dev|remote-dev-base|child image|child-image|one final image|same final image|current (edge|development image|Codex deployment)|not implemented|planned|future' \
README.md README.es.md CHANGELOG.md PROJECT_STATUS.md docs || true
echo
echo "=== Markdown structural checks ==="
python3 - <<'PY'
from pathlib import Path
import re
files = [p for p in Path(".").rglob("*.md") if ".git" not in p.parts]
for p in sorted(files):
text = p.read_text(encoding="utf-8")
issues = []
if not text.endswith("\n"):
issues.append("missing final newline")
fences = len(re.findall(r"(?m)^```", text))
if fences % 2:
issues.append(f"unbalanced fenced-code markers ({fences})")
for n, line in enumerate(text.splitlines(), 1):
if len(line) > 120 and not re.match(r"^\s*\|", line):
issues.append(f"line {n} exceeds 120 columns ({len(line)})")
if issues:
print(f"{p}: " + "; ".join(issues))
print("Relative Markdown-link targets missing:")
for p in sorted(files):
text = p.read_text(encoding="utf-8")
for n, target in enumerate(re.findall(r"\[[^\]]*\]\(([^)\s]+)(?:\s+\"[^\"]*\")?\)", text), 1):
if target.startswith(("#", "http://", "https://", "mailto:")):
continue
clean = target.split("#", 1)[0]
if clean and not (p.parent / clean).exists():
print(f"{p}: {target}")
PYLength of output: 39670 🏁 Script executed: #!/bin/bash
set -euo pipefail
base="fee981e46d0c157dca446c02bf5e0bb3f99f3674"
echo '=== Final modified documents with portable line numbers ==='
for file in CHANGELOG.md README.md docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md; do
echo "--- $file"
awk '{ printf "%6d\t%s\n", NR, $0 }' "$file"
done
echo
echo '=== Pin/source-of-truth comparison (base vs HEAD) ==='
for file in versions.env mise.lock Dockerfile; do
if [ -f "$file" ]; then
echo "--- $file"
git diff --unified=3 "$base"...HEAD -- "$file" || true
rg -n 'CODEX|MISE|UV|PYTHON|0\.146\.0|2026\.7\.16|0\.12\.0' "$file" || true
fi
done
echo
echo '=== Tracking issue metadata ==='
for issue in 24 25 31 36; do
echo "--- #$issue"
gh issue view "$issue" --repo eXPerience83/remote-dev-containers \
--json number,title,state,url,body \
--jq '"#\(.number) [\(.state)] \(.title)\n\(.url)\n\(.body[0:500])"' \
|| echo "Unable to read issue #$issue"
done
echo
echo '=== Markdown structural and relative-link checks ==='
python3 - <<'PY'
from pathlib import Path
import re
files = [
Path("CHANGELOG.md"), Path("README.md"), Path("docs/architecture.md"),
Path("docs/decisions.md"), Path("docs/roadmap.md"), Path("docs/tool-matrix.md")
]
for p in files:
text = p.read_text(encoding="utf-8")
errors = []
fence_count = len(re.findall(r"(?m)^[ \t]*```", text))
if fence_count % 2:
errors.append(f"unbalanced fenced code blocks: {fence_count}")
headings = [m.group(1) for m in re.finditer(r"(?m)^(#{1,6})\s+\S", text)]
jumps = [(i, len(headings[i - 1]), len(h)) for i, h in enumerate(headings[1:], 1)
if len(h) > len(headings[i - 1]) + 1]
if jumps:
errors.append(f"heading-level jumps: {jumps}")
for index, line in enumerate(text.splitlines(), 1):
if line.rstrip() != line:
errors.append(f"trailing whitespace at line {index}")
print(f"{p}: " + ("OK" if not errors else "; ".join(errors)))
print("Missing relative link targets:")
missing = False
for p in files:
for match in re.finditer(r"\[[^\]]*\]\(([^)\s]+)", p.read_text(encoding="utf-8")):
target = match.group(1)
if target.startswith(("https://", "http://", "mailto:", "#")):
continue
path = target.split("#", 1)[0]
if path and not (p.parent / path).exists():
missing = True
print(f"{p}: {target}")
if not missing:
print("none")
PY
echo
echo '=== Ambiguous present-tense target claims ==='
rg -n -i -C 1 \
'\b(is|are|uses|use|receives|receive|runs|run|contains|contain|must|will)\b' \
README.md docs/architecture.md docs/decisions.md docs/roadmap.md docs/tool-matrix.md \
| rg -i -C 2 'launcher|antigravity|claude|agent service|final image|stack|target|current|planned|future' || trueLength of output: 52941
The documentation is internally consistent across the README, architecture contract, decision log, roadmap, tool matrix, and changelog:
✅ Action performedFull review finished. |
|
Warning Review limit reached
Next review available in: 42 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
WalkthroughThe PR replaces the previous architecture documentation with a Remote Dev contract covering a shared immutable image, isolated launcher and agent services, security boundaries, migration requirements, validation assertions, and an updated implementation roadmap. ChangesRemote Dev architecture
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Summary
Document the accepted Remote Dev target architecture before changing the runtime:
Scope
Documentation and architectural decisions only. This PR does not implement the launcher, add services, change Compose, remove Bubblewrap or publish a new runtime image.
Changes
Validation
fee981e46d0c157dca446c02bf5e0bb3f99f3674, the exact edge revision manually validated on TrueNAS with Codex CLI0.146.0;Addresses #24.