Conversation
…ate and logs mounts The blanket ~/.copilot bind mount at the chroot path (/host$HOME/.copilot) shadowed the pre-chroot AWF workDir volume mounts for session-state and logs. After chroot, Copilot CLI wrote events.jsonl to the host filesystem via the bind mount, bypassing the AWF workDir entirely. This prevented events.jsonl from being captured in workflow artifacts. Replace the single ~/.copilot mount with two targeted mounts that map AWF workDir subdirectories (agent-session-state, agent-logs) to the chroot paths. This ensures: - events.jsonl is captured in AWF workDir (fixable in artifacts) - Agent logs go through AWF workDir (consistent with non-chroot mode) - Host ~/.copilot contents (config, auth state) are no longer exposed to the sandboxed agent — it gets an empty writable ~/.copilot from the empty home volume instead Fixes #1592 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
| Metric | Base | PR | Delta |
|---|---|---|---|
| Lines | 85.73% | 85.71% | 📉 -0.02% |
| Statements | 85.62% | 85.60% | 📉 -0.02% |
| Functions | 86.66% | 86.66% | ➡️ +0.00% |
| Branches | 78.43% | 78.33% | 📉 -0.10% |
📁 Per-file Coverage Changes (1 files)
| File | Lines (Before → After) | Statements (Before → After) |
|---|---|---|
src/docker-manager.ts |
85.5% → 85.5% (-0.09%) | 85.1% → 85.0% (-0.09%) |
Coverage comparison generated by scripts/ci/compare-coverage.ts
There was a problem hiding this comment.
Pull request overview
This PR fixes an artifact-capture bug in chroot mode by preventing a broad ~/.copilot bind mount from shadowing AWF workDir mounts, ensuring Copilot CLI events.jsonl and logs are written into the AWF workDir (and improving sandbox isolation by not exposing the host’s full ~/.copilot).
Changes:
- Replace the blanket chroot mount of
~/.copilotwith targeted chroot mounts for~/.copilot/session-stateand~/.copilot/logssourced fromworkDir. - Update inline documentation to reflect the new security/behavior rationale.
- Update the volume-mount unit test to assert the new targeted mounts and the absence of the blanket mount.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/docker-manager.ts | Replaces the chroot ~/.copilot blanket mount with targeted mounts for session-state and logs from workDir to ensure artifacts are captured and host config isn’t exposed. |
| src/docker-manager.test.ts | Adjusts expectations to verify targeted ~/.copilot/{session-state,logs} mounts and confirm the blanket ~/.copilot mount is absent. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
🤖 Smoke test results for Claude engine:
Overall: PASS
|
This comment has been minimized.
This comment has been minimized.
Add a --session-state-dir option (following the --proxy-logs-dir pattern) that writes the entire Copilot CLI session directory tree directly to a predictable, external path. This makes the full session state (events.jsonl, session.db, plan.md, checkpoints, etc.) available for artifact upload without relying on post-cleanup /tmp paths. When specified: - Session state is written directly to the given path during execution - Permissions are fixed during cleanup (chmod -R a+rX) - The path survives AWF workDir deletion (timeout-safe) When not specified (default): - Session state goes to workDir/agent-session-state as before - Moved to /tmp/awf-agent-session-state-<timestamp> during cleanup Also supports AWF_SESSION_STATE_DIR environment variable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Smoke Test Results✅ GitHub MCP: #1581 feat: add esbuild single-file bundle as lightweight distribution, #1588 fix: rename and scope token analyzer to Copilot workflows Overall: PASS
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Copilot CLI needs to create ~/.copilot/pkg/ for package extraction. When the blanket ~/.copilot bind mount was replaced with targeted sub-mounts (session-state, logs), Docker auto-created the .copilot directory as root-owned to serve as a mount point. This caused EACCES when Copilot CLI tried to mkdir ~/.copilot/pkg as the runner user. Fix by pre-creating .copilot inside the empty home volume directory with correct UID/GID ownership, so it's writable after chroot. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
| Metric | Base | PR | Delta |
|---|---|---|---|
| Lines | 85.73% | 85.74% | ➡️ +0.01% |
| Statements | 85.62% | 85.63% | ➡️ +0.01% |
| Functions | 86.66% | 86.66% | ➡️ +0.00% |
| Branches | 78.43% | 78.29% | 📉 -0.14% |
📁 Per-file Coverage Changes (1 files)
| File | Lines (Before → After) | Statements (Before → After) |
|---|---|---|
src/docker-manager.ts |
85.5% → 85.6% (+0.05%) | 85.1% → 85.1% (+0.05%) |
Coverage comparison generated by scripts/ci/compare-coverage.ts
|
Smoke Test Results — PASS
|
This comment has been minimized.
This comment has been minimized.
Removing the blanket ~/.copilot mount broke MCP config access and package extraction. Copilot CLI needs: - ~/.copilot/mcp-config.json (MCP server config, written by gh-aw framework) - ~/.copilot/pkg/ (package extraction during startup) Restore the host ~/.copilot bind mount and overlay session-state and logs from the AWF workDir on top. Docker processes mounts in order, so the later session-state and logs mounts shadow the corresponding paths under the parent ~/.copilot mount. Result: - MCP config and packages accessible from host (as before) - session-state → AWF workDir (events.jsonl captured) - logs → AWF workDir (agent logs captured) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
| Metric | Base | PR | Delta |
|---|---|---|---|
| Lines | 85.73% | 85.71% | 📉 -0.02% |
| Statements | 85.62% | 85.60% | 📉 -0.02% |
| Functions | 86.66% | 86.66% | ➡️ +0.00% |
| Branches | 78.43% | 78.33% | 📉 -0.10% |
📁 Per-file Coverage Changes (1 files)
| File | Lines (Before → After) | Statements (Before → After) |
|---|---|---|
src/docker-manager.ts |
85.5% → 85.5% (-0.07%) | 85.1% → 85.0% (-0.07%) |
Coverage comparison generated by scripts/ci/compare-coverage.ts
|
Smoke test results (run 23881935575) ✅ GitHub MCP — #1581 feat: add esbuild single-file bundle as lightweight distribution, #1588 fix: rename and scope token analyzer to Copilot workflows Overall: PASS
|
Smoke Test Results — Run 23881935565
Overall: PASS Author:
|
This comment has been minimized.
This comment has been minimized.
AWF runs as root but the agent container runs as the host user (e.g., UID 1001). The session-state and agent-logs overlay directories were created by root and never chowned, so Copilot CLI could not create session subdirectories or write events.jsonl. Chown both directories to the host user's UID/GID after creation, matching how squid-logs are chowned to the proxy user. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
| Metric | Base | PR | Delta |
|---|---|---|---|
| Lines | 85.73% | 85.73% | ➡️ +0.00% |
| Statements | 85.62% | 85.62% | ➡️ +0.00% |
| Functions | 86.66% | 86.66% | ➡️ +0.00% |
| Branches | 78.43% | 78.33% | 📉 -0.10% |
📁 Per-file Coverage Changes (1 files)
| File | Lines (Before → After) | Statements (Before → After) |
|---|---|---|
src/docker-manager.ts |
85.5% → 85.6% (+0.01%) | 85.1% → 85.1% (+0.01%) |
Coverage comparison generated by scripts/ci/compare-coverage.ts
Smoke Test Results✅ GitHub MCP — #1581 feat: add esbuild single-file bundle as lightweight distribution; #1588 fix: rename and scope token analyzer to Copilot workflows Overall: PASS
|
|
Smoke test results ✅ GitHub MCP — Last 2 merged PRs: #1588 "fix: rename and scope token analyzer to Copilot workflows", #1586 "fix: recompile token-usage-analyzer lock file" Overall: PASS
|
This comment has been minimized.
This comment has been minimized.
Chroot Version Comparison Results
Overall: ❌ NOT all tests passed — Python and Node.js versions differ between host and chroot environments.
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Add tests covering the sessionStateDir conditional cleanup paths to fix the branch coverage regression (-0.10%): - Preserve session state to /tmp when sessionStateDir is not specified - Chmod session state in-place when sessionStateDir is specified Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
✅ Coverage Check PassedOverall Coverage
📁 Per-file Coverage Changes (1 files)
Coverage comparison generated by |
|
Smoke Test Results — PASS
|
🏗️ Build Test Suite Results
Overall: 0/8 ecosystems passed — ❌ FAIL Error DetailsAll 8 ecosystems failed with the same error: The
|
Smoke Test Results
Last 2 merged PRs: #1588 "fix: rename and scope token analyzer to Copilot workflows", #1586 "fix: recompile token-usage-analyzer lock file" (author: Overall: PASS
|
Chroot Version Comparison Results
Overall: ❌ Not all versions match Go versions match, but Python and Node.js differ between host and chroot environments. The chroot uses system-installed versions (Ubuntu 22.04 defaults) while the host has newer versions from tool caches.
|
Smoke Test: GitHub Actions Services Connectivity ✅All checks passed:
|
This comment has been minimized.
This comment has been minimized.
… var Add the --session-state-dir CLI flag and AWF_SESSION_STATE_DIR environment variable to the documentation, introduced in #1593. - docs/usage.md: add --session-state-dir to the CLI options list (after --proxy-logs-dir), and expand the Agent Session State description to mention the flag's timeout-safe, predictable-path behaviour useful for GitHub Actions artifact uploads - docs/environment.md: add AWF_SESSION_STATE_DIR to the internal variables table and update the note to clarify it is user-configurable Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Smoke Test: PASS (Claude, run 23900672204)
|
This comment has been minimized.
This comment has been minimized.
|
🔮 The ancient spirits stir, and the smoke has been read.
|
… var (#1600) Add the --session-state-dir CLI flag and AWF_SESSION_STATE_DIR environment variable to the documentation, introduced in #1593. - docs/usage.md: add --session-state-dir to the CLI options list (after --proxy-logs-dir), and expand the Agent Session State description to mention the flag's timeout-safe, predictable-path behaviour useful for GitHub Actions artifact uploads - docs/environment.md: add AWF_SESSION_STATE_DIR to the internal variables table and update the note to clarify it is user-configurable Co-authored-by: Copilot <copilot@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
Fixes #1592 —
events.jsonland the full Copilot CLI session directory are never captured in workflow artifacts because the chroot bind mount shadows the AWF workDir volume mount.Problem
Two competing volume mounts for
~/.copilot/session-state:workDir/agent-session-state → ~/.copilot/session-state:rw~/.copilot → /host~/.copilot:rwAfter chroot to
/host, mount #2 wins — Copilot CLI writes the entire session directory tree (events.jsonl,session.db,plan.md,checkpoints/, etc.) directly to the host filesystem, completely bypassing the AWF workDir. Nothing appears in artifacts.Additionally, mounting the entire
~/.copilotdirectory exposes configuration and cached auth state to the sandboxed agent unnecessarily.Changes
Commit 1: Replace blanket mount with targeted mounts
Replace the single
~/.copilotchroot bind mount with two targeted mounts pointing to the AWF workDir:~/.copilot/session-state/~/.copilot/logs/~/.copilot/(rest)Commit 2: Add
--session-state-dirflagFollowing the
--proxy-logs-dirpattern, adds a--session-state-diroption for writing the full session directory tree to a predictable, timeout-safe path suitable for artifact upload:awf --session-state-dir /tmp/gh-aw/sandbox/agent/session-state \ --allow-domains github.com -- copilot ...--session-state-dir: Written directly to specified path during execution; survives workDir deletion; permissions fixed during cleanupworkDir/agent-session-state; moved to/tmp/awf-agent-session-state-<timestamp>during cleanupAWF_SESSION_STATE_DIRenvironment variableFiles changed:
src/types.ts,src/cli.ts,src/docker-manager.ts,src/docker-manager.test.tsTesting
sessionStateDirconfig optionRelated
--session-state-dir)