Commit 8020b63
feat: add Docker sbx microVM runtime support (#6101)
* feat: add Docker sbx microVM runtime support
- Activate sbx in RUNTIME_REGISTRY (executionModel: microvm)
- Gate agent service in compose-generator: skip when !runtimeUsesComposeAgent
- New src/sbx-manager.ts: create/exec/wait/rm sandbox lifecycle
- Wire sbx path in main-action.ts: infra-only compose, then sbx exec
- Add sbx cleanup to buildCleanupFn
- Update JSON schemas, spec doc, CLI help with sbx option
- Add 4 sbx tests to container-runtime.test.ts (14 total)
- Postprocess script injects --container-runtime sbx into lock file
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* ci: add sbx CLI install step to smoke-docker-sbx workflow
Adds Docker sbx CLI installation via apt (docker-sbx package) and
KVM availability check before the AWF invocation step.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: use 'sbx version' instead of 'sbx --version'
The sbx CLI uses subcommand style (sbx version) not flag style (sbx --version).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* ci: add sbx login step with Docker PAT authentication
sbx requires Docker authentication even for basic sandbox creation.
Uses DOCKER_PAT and DOCKER_USERNAME repo secrets.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: strip secret env vars from sbx CLI calls
createSandbox() and execInSandbox() were spreading process.env into
sbx CLI invocations, which could leak credential-bearing env vars
into the sbx sandbox.
Add sanitizeEnvForSbx() that strips env vars matching secret patterns
(TOKEN, SECRET, PASSWORD, KEY, CREDENTIAL, PAT) before passing to sbx.
Also removes redundant DOCKER_PAT env from the lock.yml login step.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: address sbx runtime review feedback
* fix: pass full env to sbx create, sanitize only sbx exec
sbx create is a host-side management operation that needs Docker auth
credentials (stored on disk by sbx login). Only sbx exec (which runs
commands inside the sandbox) gets the sanitized environment.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: add sbx connectivity diagnostics before agent launch
Run a diagnostic check inside the sandbox after creation to verify:
- Network interfaces and DNS config
- Proxy connectivity to Squid
- Direct connectivity (should fail if iptables are working)
- Environment variables (sans secrets)
Also adds logging around the agent command execution to help
identify where hangs occur.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: add timeouts and verbose logging to sbx daemon/create/exec
The previous run hung for 14 minutes with zero output after
'Configuring sbx daemon proxy'. This adds:
- 30s timeouts on all sbx daemon operations (status/stop/start)
- 2min timeout on sbx create
- Per-step [sbx-daemon] log messages with stdout/stderr capture
- Error output capture on sbx create failure
- Connectivity diagnostics inside sandbox before agent launch
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: remove sbx daemon restart, pass proxy via env to sbx create
sbx daemon start runs in foreground (blocks forever), not as a
background service launcher. The previous approach of stopping and
restarting the daemon was hanging the CI run for 14 minutes.
Instead, pass DOCKER_SANDBOXES_PROXY as an environment variable
directly to the sbx create command. The daemon is already running
(started by sbx login/install), so we just need the proxy env var
set when creating the sandbox.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: add auth/daemon diagnostics before sbx create
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: background sbx daemon with nohup+disown for cross-step persistence
sbx auth requires a running daemon. The daemon is a foreground process
that must be backgrounded with nohup+disown to survive across GitHub
Actions steps. Added daemon startup with polling wait, then login, then
auth verification.
Also replaced diagnostic dumps with a proper auth pre-check that fails
fast with an actionable error message.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: replace nonexistent 'sbx auth status' with 'sbx ls' probe
sbx has no 'auth status' subcommand. Use 'sbx ls' which requires
auth and returns exit 0 when authenticated.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: initialize sbx network policy before sandbox creation
sbx requires a global network policy to be set before 'sbx create'
can succeed. Try multiple policy initialization approaches as the
exact syntax may vary by version.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: use correct 'sbx policy init' (no --global flag)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: add sbx help output for policy/create syntax discovery
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: use 'sbx policy init allow-all' for network policy
Correct syntax is: sbx policy init <allow-all|balanced|deny-all>
Using allow-all since AWF's Squid proxy handles domain filtering.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: pipe 'y' to sbx create stdin for interactive confirmation
sbx create prompts for user confirmation. With stdin as /dev/null
it fails with 'user cancelled operation'. Pipe 'y' via input option.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: use 'yes | sbx create' to bypass interactive TTY check
sbx create checks if stdin is a TTY for confirmation. Even piping
'y' via execa input fails because it's not a TTY. Use 'yes |' via
bash shell to provide continuous confirmation stream.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: add docker login for template image pulls in sbx create
sbx create shell pulls docker/sandbox-templates:shell-docker from Docker Hub
and needs registry credentials in Docker's credential store (separate from
sbx login which authenticates with the sbx service).
Also dumps sbx create --help for flag reference.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: validate Docker Hub credentials before sbx auth
Adds pre-validation step that:
1. Checks secret env vars are non-empty (with length output)
2. Tests docker login first (validates creds work for registry)
3. Then does sbx login (service auth)
This ensures registry credentials are in Docker's credential store
before sbx create tries to pull docker/sandbox-templates:shell-docker.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: remove DOCKER_SANDBOXES_PROXY from sbx create env
The DOCKER_SANDBOXES_PROXY env var was being picked up by the sbx CLI
itself, routing its Docker Hub auth/registry requests through Squid.
This broke credential lookup ('no default account profile set').
The proxy is for sandbox egress, not for host-side management ops.
It's already configured inside the sandbox via buildAgentEnvironment()
which sets HTTP_PROXY/HTTPS_PROXY and passes them to sbx exec --env.
Security note: process.env (which may contain DOCKER_PAT) is safe to
pass to sbx create because it's a host-side CLI command. The sandbox
is a KVM microVM with hardware isolation — host env vars never reach
the sandbox interior. Only sanitizeEnvForSbx()-filtered vars are
passed to sbx exec.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: use printf for sbx login, add sbx diagnose
- printf '%s' avoids trailing newline that echo adds to PAT
- sbx diagnose gives full system state dump for debugging
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: sbx create --debug logging + pre-agent create test
- Log sbx create stdout/stderr at info level (was debug, invisible)
- Add --debug flag to sbx create for verbose daemon output
- Add DOCKER_CONFIG env var pointing at ~/.docker
- Test sbx create directly in auth step to isolate env vs auth issue
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: use workspace dir for sbx create test, dump policy help
/tmp was blocked by mount policy. Try workspace dir instead and
dump 'sbx policy --help' to see available policy subcommands.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: convert Docker mount format to sbx positional format
sbx uses positional workspace paths (host path = VM path) with
optional :ro suffix. AWF's --mount flags use Docker-style
'host:container:mode' format. Convert by extracting host path
and preserving :ro mode.
Also note: sbx cannot remap paths (/host prefix from chroot
convention is not applicable in microVM context).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: add fs mount policies and pre-pull template image
Two issues discovered:
1. sbx policy init allow-all only covers network, not filesystem
mounts. Added sbx policy allow for fs:mount:read/write.
2. AWF's sbx create can't pull template from Docker Hub because
the step doesn't have DOCKER_PAT in env (daemon credential
lookup fails). Pre-pull the image in the auth step so sbx
create uses the cached image.
Also dumps 'sbx policy allow --help' and 'sbx policy ls' for
debugging the correct policy syntax.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: dump policy profile/inspect/init help for mount policy
allow-all sets network + fs read/write but NOT fs:mount:read/write.
Need to understand the policy model to enable host path mounts.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: inspect policy details, try --clone and bare create
Trying multiple approaches:
1. Inspect local-policy to see actual rules
2. List available profiles
3. Try --clone (might bypass host mount policy)
4. Try bare create without workspace path
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: check KVM, try --clone and direct mount with --debug
--clone bypasses mount policy but hits 500 error — might be KVM.
Adding KVM diagnostics and --debug to both create paths.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: early exit after auth step to speed up iteration
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: explore mount policy config, daemon logs, sbx setup
Investigating:
- sbx setup --help (might have mount config)
- daemon config files and policy store
- daemon log for mount denial details
- sbx create with . vs absolute path
- sbx run (one-step, might handle mounts differently)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: structured sbx mount policy diagnostics
Replaces ad-hoc debugging with structured diagnostic script:
1. Version + initial policy state (--wide, --type filesystem, --include-inactive)
2. Full policy reset + re-init cycle with daemon restart
3. Resulting policy state after reset
4. Workspace path verification
5. Clone-based sandbox test with --debug
6. Direct mount sandbox test with --debug
7. Daemon log for policy evaluation details
Uses set -uxo pipefail (no -e) to collect all diagnostics.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: chmod /dev/kvm for sbx microVM access
Mount policy is solved after policy reset cycle. The actual blocker
was KVM permission denied (os error 13) — runner user not in kvm group.
Fix: sudo chmod 666 /dev/kvm before sbx create.
Daemon log confirmed:
- mount policy: path allowed (fs:mount:read + fs:mount:write)
- failed to create VM: KVM error: Permission denied (os error 13)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: sbx create works! Remove early exit, add exec test
sbx create succeeded:
✓ Created sandbox 'test-sandbox-direct'
Workspace: /home/runner/work/gh-aw-firewall/gh-aw-firewall (direct mount)
Agent: shell / Status: running
Fixes:
- Move KVM chmod to Install step (before daemon start)
- Remove early exit 1 to let full AWF flow run
- Add sbx exec test (uname -a) to verify VM is functional
- Fix broken pipe false failure (bash -c isolation)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: add credential state diagnostics + fix broken pipe exit code
sbx create succeeded in auth step but fails in AWF step with 'no default
account profile set: secret not found'. Adding diagnostics:
- Dump HOME, credential dir, Docker config dir, daemon socket
- Fix broken pipe false failure: check stdout for 'Created sandbox'
- Track SBX_EXIT_CODE separately from bash pipeline exit code
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: refresh sbx credentials immediately before AWF execution
Docker Hub OAuth tokens from 'sbx login' expire between workflow steps.
Add a credential refresh step right before 'Execute GitHub Copilot CLI'
to ensure sbx create can authenticate with Docker Hub.
Auth step confirmed working: sbx create succeeds there.
AWF step fails with 'secret not found' minutes later.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: remove XDG_CONFIG_HOME from sbx create env
The AWF execution step sets XDG_CONFIG_HOME=$HOME (/home/runner) for
Copilot CLI. This breaks sbx credential lookup — sbx stores encrypted
secrets at $XDG_CONFIG_HOME/sandboxes/ which defaults to ~/.config/sandboxes/.
When XDG_CONFIG_HOME=/home/runner, sbx looks at /home/runner/sandboxes/
instead of /home/runner/.config/sandboxes/, causing 'secret not found'.
Fix: unset XDG_CONFIG_HOME when it equals HOME before calling sbx create.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug: unset XDG_CONFIG_HOME in bash + find credential files
XDG_CONFIG_HOME removal via env object didn't fix it. Try unsetting
inside bash itself. Also improved diagnostics to find all credential-
related files on disk (state, config, docker dirs) to determine where
sbx actually stores secrets.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: mount /tmp and /usr/local/bin into sbx, deduplicate mounts, clean up
Agent command failed because /usr/local/bin/copilot and /tmp/gh-aw/
(prompts, logs) were not mounted into the microVM.
Changes:
- Add /tmp and /usr/local/bin as default mounts in createSandbox()
- Deduplicate mount paths (same path was passed twice)
- Remove debug diagnostics (find credential files, etc.)
- Clean up auth step: remove verbose echo/policy dumps, keep essentials
- Keep 'Refresh sbx credentials' step as insurance
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: mount $HOME into sbx for agent writable dirs (.cache, etc.)
Copilot CLI needs writable access to ~/.cache to extract its bundled
package. Without $HOME mounted, the microVM has no /home/runner and
mkdir fails with EACCES.
Progress: binary found ✓, prompt file found ✓, now need HOME writable.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* diag: probe sbx network routes and gateway to find host access
sbx microVM can't reach Docker Compose containers at 172.30.0.10.
Need to find the sbx gateway IP to route through Squid published
on host port 3128.
Testing: route table, common gateway IPs (192.168.127.1, 10.0.2.2,
172.17.0.1), direct outbound, and host.docker.internal.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* diag: test DNS resolution and raw IP connectivity from sbx
Direct internet and proxy both time out from sbx microVM.
Adding: nslookup, getent, curl with --resolve (raw IP bypass DNS),
and gateway IP tests on 172.17.0.0 and 172.17.0.1.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sbx): route proxy through sbx gateway IP + publish api-proxy ports
The sbx microVM can't reach Docker-internal IPs (172.30.0.x).
Diagnostics confirmed that the sbx gateway IP (172.17.0.0) with
Squid's published port 3128 returns HTTP 200.
Changes:
- Use SBX_GATEWAY_IP (172.17.0.0) for proxy env vars in sbx mode
instead of the Docker-internal SQUID_IP (172.30.0.10)
- Publish api-proxy ports (10000-10004) to host when agent runs
outside compose (microVM runtimes like sbx)
- Simplify sbx diagnostics to a quick proxy connectivity check
- Add test for api-proxy port publishing with sbx runtime
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* diag: log sbx env vars and test api-proxy port reachability
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sbx): merge credential isolation env vars for api-proxy routing
buildAgentEnvironment() does not include the credential isolation env
vars (COPILOT_API_URL, COPILOT_PROVIDER_BASE_URL, OPENAI_BASE_URL, etc.)
because in Docker mode they are merged by assembleOptionalServices()
during compose generation.
For sbx, call buildAgentCredentialEnv() directly with the sbx gateway IP
so the Copilot CLI enters BYOK/offline mode and routes through the
api-proxy sidecar instead of attempting direct PAT validation against
api.github.com.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sbx): wait for api-proxy health + dump logs on failure
Add health check polling (up to 30s) before launching the agent in sbx
mode. In Docker mode, depends_on: service_healthy gates this; for sbx
we must poll manually from within the microVM.
Also dump api-proxy container logs when the agent command fails to help
diagnose the 'connection closed before message completed' issue.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sbx): attach api-proxy to awf-ext network for port publishing
In network-isolation mode, awf-net is an internal Docker network with no
route to the host. Port publishing on containers only attached to an
internal network doesn't work — the host (and thus the sbx microVM)
cannot reach them.
Fix: when the agent runs in a microVM and network isolation is active,
also attach api-proxy to the awf-ext bridge network (same as Squid).
This makes published ports (10000-10004) reachable from the sbx gateway.
Root cause of 'connection closed before message completed' — the sbx VM
could TCP-connect to the published port (Docker accepts the SYN) but the
internal-only container never received the forwarded traffic.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* debug(sbx): add port reachability diagnostics from sbx VM
Try multiple candidate IPs (172.17.0.0, 10.0.2.2, 172.17.0.1) from
inside the sbx to identify which address reaches Docker published ports.
Also dumps docker port and network info from host perspective.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sbx): use host.docker.internal for api-proxy from microVM
The sbx microVM cannot reach Docker-published ports via the gateway IP
(172.17.0.0) for the api-proxy — port publishing isn't effective for
containers on an internal Docker network. However, host.docker.internal
resolves to the docker0 bridge (172.17.0.1) inside the sbx VM, which
CAN route to containers on the awf-ext bridge network.
Diagnostics proved:
- 172.17.0.0:10000 → FAIL (timeout, no port publishing)
- 172.17.0.1:10000 → OK (instant, docker0 bridge routes to awf-ext)
- 172.17.0.0:3128 → OK (Squid has native port publishing)
Use host.docker.internal for api-proxy URLs (COPILOT_API_URL,
COPILOT_PROVIDER_BASE_URL, etc.) while keeping 172.17.0.0 for Squid
proxy which has working port publishing.
Also simplify health check to use host.docker.internal and remove
the multi-IP diagnostic probing.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sbx): route MCP gateway through host.docker.internal
The MCP gateway runs as a Docker container published on the host. From
inside the sbx microVM, Docker container names (awmg-mcpg) are not
resolvable, so the Copilot CLI couldn't reach the gateway to call
safe-output tools (noop, add-comment, add-labels).
Changes:
- Use host.docker.internal as the gateway domain in mcp-config.json
- Bind MCP gateway to 0.0.0.0 (needed for host.docker.internal access)
- Set MCP_GATEWAY_HOST_DOMAIN to host.docker.internal
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix(sbx): use host.docker.internal for MCP CLI wrappers
The mount_mcp_as_cli step generates CLI wrapper scripts that the Copilot
CLI calls to invoke MCP tools (safe-outputs). The wrappers use
MCP_GATEWAY_DOMAIN to build the URL. In the Docker agent case, this is
the container name (awmg-mcpg) resolvable within the Docker network. In
the sbx case, Docker names aren't resolvable from the microVM —
host.docker.internal must be used instead.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* fix: avoid shell-based sbx create command injection path
* fix: avoid clear-text logging of sensitive env vars (CodeQL)
Use a redactSecret() helper that only reports whether a secret is set
and its length, without passing the secret value into the log template
literal. This avoids the js/clear-text-logging CodeQL alert.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>1 parent 47458f0 commit 8020b63
15 files changed
Lines changed: 855 additions & 36 deletions
File tree
- .github/workflows
- docs
- scripts/ci
- src
- commands
- services
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
183 | 183 | | |
184 | 184 | | |
185 | 185 | | |
186 | | - | |
| 186 | + | |
187 | 187 | | |
188 | 188 | | |
189 | 189 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
622 | 622 | | |
623 | 623 | | |
624 | 624 | | |
625 | | - | |
626 | | - | |
| 625 | + | |
| 626 | + | |
627 | 627 | | |
628 | 628 | | |
629 | 629 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
75 | 75 | | |
76 | 76 | | |
77 | 77 | | |
78 | | - | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
79 | 82 | | |
80 | 83 | | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
85 | | - | |
| 84 | + | |
| 85 | + | |
86 | 86 | | |
87 | 87 | | |
88 | 88 | | |
| |||
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
622 | 622 | | |
623 | 623 | | |
624 | 624 | | |
625 | | - | |
626 | | - | |
| 625 | + | |
| 626 | + | |
627 | 627 | | |
628 | 628 | | |
629 | 629 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
171 | 171 | | |
172 | 172 | | |
173 | 173 | | |
174 | | - | |
175 | | - | |
176 | | - | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
177 | 178 | | |
178 | 179 | | |
179 | 180 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
36 | 37 | | |
37 | 38 | | |
38 | 39 | | |
| |||
45 | 46 | | |
46 | 47 | | |
47 | 48 | | |
| 49 | + | |
48 | 50 | | |
49 | 51 | | |
50 | 52 | | |
| |||
57 | 59 | | |
58 | 60 | | |
59 | 61 | | |
| 62 | + | |
60 | 63 | | |
61 | 64 | | |
62 | 65 | | |
| |||
108 | 111 | | |
109 | 112 | | |
110 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
111 | 118 | | |
112 | 119 | | |
113 | 120 | | |
| |||
292 | 299 | | |
293 | 300 | | |
294 | 301 | | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
295 | 341 | | |
296 | 342 | | |
297 | 343 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
29 | 31 | | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
30 | 42 | | |
31 | 43 | | |
32 | 44 | | |
| |||
89 | 101 | | |
90 | 102 | | |
91 | 103 | | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
92 | 113 | | |
93 | 114 | | |
94 | 115 | | |
| |||
231 | 252 | | |
232 | 253 | | |
233 | 254 | | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
234 | 395 | | |
235 | 396 | | |
236 | 397 | | |
237 | 398 | | |
238 | 399 | | |
239 | 400 | | |
240 | | - | |
241 | | - | |
| 401 | + | |
| 402 | + | |
242 | 403 | | |
243 | 404 | | |
244 | 405 | | |
| |||
0 commit comments