Commit Graph
47 Commits
Author SHA1 Message Date
shadow-testandClaude Opus 5 98a6c8fd56 CI: build NSIS only on Windows, dropping the MSI target
The MSI target needs WiX, whose candle.exe and light.exe are 32-bit. On
a runner running as SYSTEM, Tauri caches the WiX toolset under
%LOCALAPPDATA% = C:\Windows\system32\config\systemprofile\..., and WOW64
redirection points 32-bit processes at SysWOW64, where that directory
does not exist. candle.exe cannot see its own folder, the CLR fails to
start, and it exits 0x80131700 — surfaced only as "failed to run
candle.exe".

Proven by running the identical toolset, as the same SYSTEM identity,
from C:\wixtest (exit 0) versus the systemprofile path (0x80131700).

Because Tauri aborts the entire bundle when one target fails, the MSI
was also suppressing the NSIS installer — so Windows produced no
artifact at all. NSIS is what the project already relies on for Windows
upgrades, so dropping MSI costs the .msi asset and nothing else.

Removes the .NET 3.5 gate, which only existed for WiX. The MSVC step
stays: that is what makes the app link, and it works.

Artifact collection now fails when no NSIS installer is present instead
of tolerating an empty directory with 2>nul, so a silent packaging
regression cannot pass as a green build again.

To restore the MSI later, run the runner as a normal user — whose
LOCALAPPDATA sits outside System32 — and set --bundles msi,nsis.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 22:24:29 -07:00
shadow-testandClaude Opus 5 c71e54a35f Revert: LOCALAPPDATA override does not move Tauri's WiX cache
It looked right and did nothing. Rust's `dirs` crate resolves
LOCALAPPDATA on Windows through SHGetKnownFolderPath, which reads the
process token rather than the environment, so Tauri still cached the WiX
toolset under the SYSTEM profile and 32-bit candle.exe still hit WOW64
redirection.

Removing it rather than leaving a plausible-looking non-fix in the
workflow. The diagnosis in the previous commit stands; only the remedy
was wrong. Running the runner as a normal user, whose token resolves
LOCALAPPDATA outside System32, is the actual fix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 22:18:58 -07:00
shadow-testandClaude Opus 5 b41077e799 CI: keep the WiX toolset out of System32 so 32-bit candle.exe can run
build-windows compiled and linked fine but died at bundling with only
"failed to run candle.exe". The real cause was neither .NET nor the
runner identity, both of which I chased first and was wrong about.

candle.exe and light.exe are 32-bit. A runner running as SYSTEM has
%LOCALAPPDATA% = C:\Windows\system32\config\systemprofile\AppData\Local,
which is where Tauri caches the WiX toolset. WOW64 redirection sends any
32-bit process reading C:\Windows\System32 to C:\Windows\SysWOW64 — and
the WixTools directory exists only in the 64-bit view. So candle.exe
could not see its own directory, the CLR failed to start, and the
process exited 0x80131700, surfaced in the Application event log as
".NET Runtime version 4.0.30319.0 - This application could not be
started."

Proven rather than assumed: copying the identical toolset to C:\wixtest
and running it as the same SYSTEM identity exits 0, while the
systemprofile path exits 0x80131700. Test-Path confirms the WOW64 view
of that directory does not exist.

Pointing LOCALAPPDATA at a path outside System32 avoids redirection.
This fixes it for any runner running as a service or as SYSTEM, without
needing a stored user credential, and is a no-op where the runner
already runs as a normal user.

For the record, two earlier theories were wrong. .NET 3.5 was missing
and is now installed from the ISO payload, but candle targets .NET 4.x
(its config uses loadFromRemoteSources, a 4.0-only element) so that was
never the blocker. Adding explicit supportedRuntime entries changed
nothing. Both are documented here so the next person does not repeat
them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 22:12:11 -07:00
shadow-testandClaude Opus 5 704d3b8f79 CI: fix the MSVC exit-code check and verify .NET 3.5 before bundling
Two follow-ups to the provisioning step.

The exit-code check never worked. %VSEXIT% and %ERRORLEVEL% inside a
parenthesised cmd block are substituted when the block is PARSED, not
when it runs, so the installer's real result was never read — the log
printed "installer failed with " with an empty code, then continued
anyway. It happened to be harmless because the install had in fact
succeeded, but a genuine failure would have sailed past. Now uses
delayed expansion.

Added a .NET 3.5 check. WiX 3.x candle.exe is a .NET 2.0/3.5
application, and Tauri aborts the entire bundle when the MSI target
fails — so a missing runtime silently costs the NSIS installer too, not
just the MSI. Windows 11 ships NetFx3 as DisabledWithPayloadRemoved and
Windows Update could not supply the payload on our runner even across a
reboot; it needed /Source from a mounted ISO. Rather than guess, the job
now fails early with the exact dism command.

Verified on the runner: MSVC Build Tools 2022 installed, the Rust build
completed in 3m59s and produced triple-c.exe, and NetFx3 is now Enabled
with v2.0.50727 present.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 21:50:02 -07:00
shadow-testandClaude Opus 5 2de00b3c55 Fix review findings: secrets in snapshots, URL spoofing, migration data loss
Adversarial review of the branch produced findings across four areas.
This addresses them, plus the Windows CI environment.

Secrets. commit_container_snapshot baked the container's full env into
the per-project snapshot image, so the shared OAuth token — and the AWS
keys, git token and gateway master key — outlived revocation and were
readable via docker inspect. Verified against Engine 29.6 that a commit
body's config merges over the container's: keys cannot be dropped but
can be overwritten, so all of them now commit as KEY=. clear_claude_token
additionally rewrites images from earlier builds and reports honestly
when a tag could not be rewritten.

The recommendation to move the token out of env entirely was not taken,
with reasoning: apiKeyHelper is a different auth method that outranks
CLAUDE_CODE_OAUTH_TOKEN rather than a transport for it, and no
file-based delivery exists. The durable exposure — the image — is what
is closed here. Separately noted, not fixed: entrypoint.sh captures the
token into the scheduler's .env inside the persisted volume.

URL spoofing. Three call sites reached openUrl with container-controlled
strings, one of which the review missed (the WebLinksAddon handler).
The sign-in URL was scraped from container output with a longest-match
tie-break and no userinfo check, so claude.ai@evil.tld rendered as
"claude.ai…" in a truncating element. There is now one sanitizer in
front of every sink — scheme allowlist, no userinfo, C0/C1 and quote
rejection, host allowlist for the sign-in case, first-match — and the
origin renders un-truncated. The toast is keyed so a changed URL
remounts, closing a bait-and-switch where the user read one URL and
clicked another.

Migration. The rollback pin was best-effort: a tag failure was logged
and the migration continued past remove_container, after which the
final commit overwrote the only copy of the old system layer. It now
aborts before anything destructive and reads the tag back. /var was
destroyed while the ordinary recreate path preserves it — making the
"safe" alternative to Reset more destructive than Reset's alternative;
data-bearing subtrees are now detected and disclosed in the pre-flight
rather than copied, since tarring a live database onto a different
base's packages is a corruption risk. resume_migration now verifies the
migration-state label instead of reporting success for a container that
never swapped. dismiss actually resolves the record rather than leaving
the feature permanently refusing to migrate. Start and Reset are guarded
while a migration is live.

Lifecycle. The gateway no longer publishes on 0.0.0.0 — bind address and
advertised URL are derived together so they cannot drift. Disabling it
now stops it. App exit runs teardown concurrently under a budget with a
visible shutting-down state instead of blocking for minutes. Auto-starts
retry when Docker is not up yet, and the polling-recovery path now
reconciles, so interrupted migrations are still recovered. Auth-bridge
forwards are capped, closing a container-driven fd exhaustion.

Windows CI. build-windows failed on this branch with "linker link.exe
not found". The runner had no MSVC build tools and the workflow assumed
a hand-provisioned machine, so a bare runner registers, accepts jobs and
fails at link time after downloading the whole crate graph. The job now
installs the VC++ workload when vswhere cannot find it, matching how it
already conditionally installs Rust and Node.

192 Rust tests, 274 frontend tests, both builds clean, zero warnings.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 19:35:39 -07:00
shadow-testandClaude Opus 4.8 997e1ab3a9 Fix Windows release upload: idempotent get-or-create + fail-loud
Build App / compute-version (pull_request) Successful in 9s
Build App / build-macos (pull_request) Successful in 2m36s
Build App / build-windows (pull_request) Successful in 2m50s
Build App / build-linux (pull_request) Successful in 6m26s
Build App / create-tag (pull_request) Has been skipped
Build App / sync-to-github (pull_request) Has been skipped
The cmd-batch upload step POSTed to /releases unconditionally. On a
re-run the v{VERSION}-win tag already exists, so Gitea returns 409, the
findstr id parse yields an empty RELEASE_ID, and uploads go to a
malformed .../releases//assets URL -- all silently swallowed by cmd and
`curl -s`, so the step reported success while attaching no assets.

Rewrite in PowerShell mirroring the macOS job: look the release up by
tag first and create only on 404, throw if the id can't be resolved,
delete same-named assets left over from partial runs before re-upload,
and fail loudly (ErrorActionPreference=Stop, curl.exe -fsS with retries,
$LASTEXITCODE check).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 09:22:55 -07:00
shadow-testandClaude Opus 4.7 4588bdf40c Make macOS release upload idempotent across re-runs
Build App / compute-version (push) Successful in 2s
Build App / build-macos (push) Successful in 2m25s
Build App / build-windows (push) Successful in 4m42s
Build App / build-linux (push) Successful in 8m54s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 10s
Previous fix only addressed the network flake; a re-run after any
upload failure still tripped over the leftover release record. The
naive POST /releases got 409 from Gitea, the grep-pipe parser yielded
an empty RELEASE_ID, and pipefail aborted with an opaque exit 1.

Now:
- Look up the release by tag first; reuse on 200, create on 404, fail
  loudly on anything else.
- Validate RELEASE_ID is non-empty and surface the response body if
  parsing fails.
- Before uploading each asset, check whether the release already has
  an asset with that name (from a partial prior run) and DELETE it so
  the POST is replace-not-conflict.
- Set -euo pipefail explicitly so the script's failure modes are
  predictable rather than dependent on the runner's default flags.

Network hardening from the previous commit (HTTP/1.1, retries, -f) is
preserved. Linux and Windows blocks unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 18:13:25 -07:00
shadow-testandClaude Opus 4.7 b607cf3681 Harden macOS release upload against curl exit 92
Build App / compute-version (push) Successful in 3s
Build App / build-windows (push) Successful in 4m5s
Build App / build-linux (push) Successful in 9m53s
Build App / build-macos (push) Failing after 2m30s
Build App / create-tag (push) Has been skipped
Build App / sync-to-github (push) Has been skipped
macOS upload has been intermittently failing with curl exit 92
("HTTP/2 stream not closed cleanly") for several releases (v0.3.12,
v0.3.10, v0.3.1 all landed with empty asset arrays despite the per-tag
release record being created). It is not a size issue — Linux uploads
the 81MB AppImage on the same Gitea instance without trouble while the
Mac dmg is only 13.6MB.

Adds `--http1.1` to sidestep HTTP/2 stream multiplexing flakes on the
macOS runner, `-f` so HTTP errors no longer fail silently under `-s`,
and `--retry 5 --retry-all-errors --retry-delay 5 --max-time 600` to
absorb transient drops. Linux and Windows blocks unchanged; an inline
note in the YAML calls out where to mirror this if those start
failing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:28:08 -07:00
shadow-testandClaude Opus 4.7 5360f22b65 Make preview build workflow manual-only
Trigger is workflow_dispatch exclusively so builds happen only when
explicitly requested from the Actions UI, not on every branch push.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:22:11 -07:00
shadow-testandClaude Opus 4.7 0316234329 Add preview build workflow for non-main branches
Build App (Preview) / compute-version (push) Successful in 2s
Build App (Preview) / build-macos (push) Failing after 2m28s
Build App (Preview) / build-windows (push) Failing after 4m29s
Build App (Preview) / build-linux (push) Failing after 8m4s
Mirrors build-app.yml's three-platform matrix (Linux/macOS/Windows)
but uploads the bundles as workflow artifacts instead of creating
Gitea releases or syncing to GitHub, so feature branches can be
smoke-tested without cluttering the release streams.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-24 10:21:17 -07:00
shadow-testandClaude Opus 4.6 d60124f1bd Fix CI: harden version computation and Dockerfile apt retries
Build App / compute-version (push) Successful in 3s
Build App / build-macos (push) Successful in 2m44s
Build App / build-windows (push) Successful in 5m18s
Build App / build-linux (push) Successful in 46m30s
Build App / create-tag (push) Successful in 2s
Build App / sync-to-github (push) Successful in 11s
Build Container / build-container (push) Failing after 3m14s
Two fixes for the v0.3.x initial build failures:

1. **Compute Version step**: When no tags match v0.3.*, `grep` returns
   exit 1 which under `pipefail` killed the step before the empty-tag
   fallback could run. Added `|| true` to the pipeline so the fallback
   (`git rev-list --count HEAD`) runs correctly on first 0.3.x build.

2. **Dockerfile apt-get update**: Transient archive.ubuntu.com mirror
   sync failures (stale Packages.gz with mismatched hash) broke the
   GitHub CLI install step. Added a shell retry loop (5 attempts with
   10s sleep, clearing /var/lib/apt/lists/* between retries) to both
   the main system packages step and the GitHub CLI step, plus
   Acquire::Retries=3 on the other apt-get update calls for transient
   network failures.

Also includes the Cargo.lock 0.2.0 → 0.3.0 rev that went with the
previous version bump commit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 09:09:30 -07:00
shadow-testandClaude Opus 4.6 532de77927 Add speech-to-text feature using Faster Whisper container
Build App / compute-version (pull_request) Successful in 3s
Build App / build-macos (pull_request) Successful in 2m28s
Build STT Container / build-stt-container (pull_request) Successful in 3m18s
Build App / build-windows (pull_request) Successful in 4m40s
Build App / build-linux (pull_request) Failing after 1m46s
Build App / create-tag (pull_request) Has been skipped
Build App / sync-to-github (pull_request) Has been skipped
Adds a mic button to the terminal UI that captures speech, transcribes
it via a Faster Whisper sidecar container, and injects the text into
the terminal input. Includes settings panel for model selection
(tiny/small/medium), port config, and container lifecycle management.

- stt-container/: Dockerfile + FastAPI server for Whisper transcription
- Rust backend: STT container management, transcribe_audio IPC command
- Frontend: useSTT hook, SttButton, SttSettings, WAV encoder
- CI: Gitea Actions workflow for multi-arch STT image builds

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 20:02:39 -07:00
shadow-testandClaude Opus 4.6 8301fd3690 Add workflow to clean up old releases
Manual workflow that deletes old Gitea and GitHub releases,
keeping only the N most recent versions. Defaults to dry-run
mode for safe preview before deletion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 08:19:31 -07:00
shadow-testandClaude Opus 4.6 bab1df1c57 Switch distribution from Gitea to GitHub/GHCR
Build App / compute-version (push) Successful in 6s
Build Container / build-container (push) Successful in 1m44s
Build App / build-macos (push) Successful in 2m21s
Build App / build-windows (push) Successful in 3m30s
Build App / build-linux (push) Successful in 4m52s
Build App / create-tag (push) Successful in 3s
Build App / sync-to-github (push) Successful in 10s
Work VPN blocks repo.anhonesthost.net, breaking update checks and image
pulls. Move all user-facing distribution to GitHub (releases API) and
GHCR (container images) while keeping Gitea as the source of truth for
development and CI.

- CI: push container images to GHCR alongside Gitea registry
- App updates: switch releases API to api.github.com, filter by asset
  filename instead of tag suffix for unified releases
- Image updates: switch registry to ghcr.io with anonymous token auth
- Container pull: point REGISTRY_IMAGE to ghcr.io/shadowdao/triple-c-sandbox
- Rename GiteaRelease/GiteaAsset structs to GitHubRelease/GitHubAsset

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:55:41 -07:00
shadow-testandClaude Opus 4.6 beae0942a1 Add dynamic versioning with VERSION file and tag-based patch counting
Build App / compute-version (push) Successful in 3s
Build App / build-macos (push) Successful in 2m19s
Build App / build-windows (push) Successful in 3m22s
Build App / build-linux (push) Successful in 6m14s
Build App / create-tag (push) Successful in 8s
Build App / sync-to-github (push) Successful in 10s
- Create VERSION file (currently `0.2`) as the single source of truth for major.minor
- Add compute-version job that reads VERSION and counts commits since the last
  matching v{major.minor}.N tag to derive the patch number
- Patch resets automatically when VERSION is bumped (no matching tags exist yet)
- Add create-tag job that tags the repo after all platform builds succeed,
  so subsequent builds count from the new tag
- All platform jobs now consume the shared version instead of computing their own
- VERSION file changes trigger the build workflow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:11:04 -07:00
shadow-testandClaude Opus 4.6 6b49981b3a Update build workflow version from 0.1.x to 0.2.x
Build App / build-macos (push) Successful in 2m22s
Build App / build-windows (push) Successful in 3m19s
Build App / build-linux (push) Successful in 6m37s
Build App / sync-to-github (push) Successful in 13s
The computed build version was hardcoded as 0.1.${COMMIT_COUNT} across all
three platform jobs (Linux, macOS, Windows), producing 0.1.x releases even
though the source files were bumped to 0.2.0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:03:53 -07:00
shadow-testandClaude Opus 4.6 b7585420ef Reconcile project statuses against Docker on startup, update docs and CI
Build App / build-macos (push) Successful in 2m40s
Build App / build-windows (push) Successful in 4m12s
Build App / build-linux (push) Successful in 5m4s
Build Container / build-container (push) Successful in 2m41s
Build App / sync-to-github (push) Successful in 10s
- Add reconcile_project_statuses command that checks actual Docker container
  state on startup, preserving Running status for containers that are genuinely
  still running and resetting stale statuses to Stopped
- Add is_container_running helper using Docker inspect API
- Frontend calls reconciliation after Docker is confirmed available
- Update TECHNICAL.md project structure, auth modes, and file listings to
  match current codebase
- Update README.md and HOW-TO-USE.md with MCP servers, Mission Control,
  file manager, bash shells, clipboard/audio shims, and progress modal docs
- Add workflow file self-triggers to CI path filters for build-app.yml
  and build.yml
- Install Mission Control skills to ~/.claude/skills/ in entrypoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 08:29:06 -07:00
shadow-testandClaude Opus 4.6 574fca633a fix: sync build artifacts to GitHub instead of empty source archives
Build App / build-macos (push) Successful in 2m22s
Build App / build-windows (push) Successful in 3m21s
Build App / build-linux (push) Successful in 4m37s
Build App / sync-to-github (push) Successful in 11s
Move GitHub release sync into build-app.yml as a final sync-to-github
job that runs after all 3 platform builds complete. This eliminates the
race condition where sync-release.yml triggered before artifacts were
uploaded to Gitea. The old sync-release.yml is changed to manual-only.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:57:27 -08:00
shadowdaoandClaude Opus 4.6 d642cc64de fix: use browser_download_url for Gitea asset downloads
The API endpoint /releases/assets/{id} returns JSON metadata, not the
binary file. Use the browser_download_url from the asset object instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:09:41 -08:00
shadowdaoandClaude Opus 4.6 4f41f0d98b feat: add Gitea actions to sync releases to GitHub
Add two new workflows:
- sync-release.yml: automatically mirrors releases (with assets) to GitHub when published on Gitea
- backfill-releases.yml: manual workflow to bulk-sync all existing Gitea releases to GitHub

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:06:29 -08:00
shadow-testandClaude Opus 4.6 c9dc232fc4 fix: remove Node.js from actual path location on Act runner
Build App / build-windows (push) Successful in 3m40s
Build App / build-linux (push) Successful in 7m4s
Build App / build-macos (push) Failing after 11m34s
The Act runner has Node 18 at /opt/acttoolcache/node/18.20.3/x64/bin/,
not at /usr/local/bin/. Use $(dirname "$(which node)") to find and
remove the actual binary location before installing Node 22.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:08:46 -08:00
shadow-testandClaude Opus 4.6 2d4fce935f fix: remove old Node.js before installing v22 on Linux runner
Build App / build-linux (push) Failing after 2m34s
Build App / build-windows (push) Successful in 3m40s
Build App / build-macos (push) Has been cancelled
The Act runner has Node 18 at /usr/local/bin/node which takes
precedence over the apt-installed /usr/bin/node. Even after
running nodesource setup and apt-get install, the old Node 18
binary remained in the PATH. Now removes old binaries and uses
hash -r to force path re-lookup. Also removes package-lock.json
before npm install to ensure correct platform-specific bindings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:03:31 -08:00
shadow-testandClaude Opus 4.6 e739f6aaff fix: check Node.js version, not just presence, in CI
Build App / build-macos (push) Successful in 2m23s
Build App / build-linux (push) Failing after 3m38s
Build App / build-windows (push) Successful in 4m1s
The Act runner has Node.js v18 pre-installed, so the check
`command -v node` passes and skips installing v22. Node 18 is
too old for dependencies like vitest, jsdom, and tailwindcss/oxide.
Now checks the major version and upgrades if < 22.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:54:36 -08:00
shadow-testandClaude Opus 4.6 550159fc63 Fix native binding error: use npm install instead of npm ci
Build App / build-linux (push) Failing after 2m25s
Build App / build-macos (push) Successful in 2m34s
Build App / build-windows (push) Successful in 4m8s
@tailwindcss/oxide has platform-specific native bindings. The
package-lock.json was generated on a different platform, so npm ci
installs the wrong native binary. Switching to rm -rf node_modules
+ npm install lets npm resolve the correct platform-specific
optional dependency (e.g., @tailwindcss/oxide-linux-x64-gnu on
Linux, oxide-darwin-arm64 on macOS).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:44:03 -08:00
shadow-testandClaude Opus 4.6 e3c874bc75 Fix cargo PATH: use explicit export in every step that needs it
Build App / build-macos (push) Successful in 2m22s
Build App / build-windows (push) Successful in 4m1s
Build App / build-linux (push) Failing after 1m30s
The Gitea Act runner's Docker container does not reliably support
$GITHUB_PATH or sourcing ~/.cargo/env across steps. Both mechanisms
failed because the runner spawns a fresh shell for each step.

Adopted the same pattern that already works for the Windows job:
explicitly set PATH at the top of every step that calls cargo or
npx tauri. This is the most portable approach across all runner
environments (Act Docker containers, bare metal macOS, Windows).

Build history shows Linux succeeded through run#46 (JS-based
actions) and failed from run#49 onward (shell-based installs).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:36:02 -08:00
shadow-testandClaude Opus 4.6 6cae0e7feb Source cargo env before using rustup in install step
Build App / build-macos (push) Successful in 2m22s
Build App / build-linux (push) Has been cancelled
Build App / build-windows (push) Has been cancelled
GITHUB_PATH only takes effect in subsequent steps, but rustup/rustc/cargo
are called within the same step. Adding `. "$HOME/.cargo/env"` immediately
after install puts cargo/rustup in PATH for the remainder of the step.
Fixed in both Linux and macOS jobs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:32:28 -08:00
shadow-testandClaude Opus 4.6 601a2db3cf Move Node.js install before checkout in Linux build
Build App / build-macos (push) Failing after 6s
Build App / build-windows (push) Successful in 3m38s
Build App / build-linux (push) Failing after 3m56s
The Gitea Linux runner also lacks Node.js, causing actions/checkout@v4
(a JS action) to fail with "node: executable file not found in PATH".
Same fix as the macOS job: install Node.js via shell before any
JS-based actions run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:28:02 -08:00
shadow-testandClaude Opus 4.6 b795e27251 Fix Linux build PATH and add ARM64 container support
Build App / build-linux (push) Failing after 2s
Build App / build-macos (push) Failing after 11s
Build App / build-windows (push) Successful in 3m38s
Linux app build: cargo was not in PATH for subsequent steps after
shell-based install. Fixed by adding $HOME/.cargo/bin to GITHUB_PATH
(persists across steps) and setting it in the job-level env. Also
removed the now-unnecessary per-step PATH override in the macOS job.

Container build: added QEMU setup and platforms: linux/amd64,linux/arm64
to produce a multi-arch manifest. The Dockerfile already uses
arch-aware commands (dpkg --print-architecture, uname -m) so it
builds natively on both architectures. This fixes the "no matching
manifest for linux/arm64/v8" error on Apple Silicon Macs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:16:45 -08:00
shadow-testandClaude Opus 4.6 19d4cbce27 Use shell-based check-before-install for all build jobs
Build App / build-macos (push) Successful in 2m34s
Build App / build-windows (push) Successful in 2m33s
Build App / build-linux (push) Failing after 3m40s
Replace JS-based GitHub Actions (dtolnay/rust-toolchain,
actions/setup-node) in the Linux job with shell commands that
check if Rust and Node.js are already present before installing.
All three jobs (Linux, macOS, Windows) now use the same pattern:
skip installation if the tool is already available on the runner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:03:17 -08:00
shadow-testandClaude Opus 4.6 946ea03956 Fix macOS CI build and add macOS build instructions
Build App / build-windows (push) Has started running
Build App / build-linux (push) Has been cancelled
Build App / build-macos (push) Has been cancelled
The macOS Gitea runner lacks Node.js, causing actions/checkout@v4
(a JS action) to fail with "Cannot find: node in PATH". Fixed by
installing Node.js via Homebrew before checkout and replacing all
JS-based actions (setup-node, rust-toolchain, rust-cache) with
shell equivalents.

Also adds macOS section to BUILDING.md covering Xcode CLI tools,
universal binary targets, and Gatekeeper bypass instructions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:00:48 -08:00
shadow-testandClaude Opus 4.6 ba4cb4176d Add macOS build job to app build workflow
Build App / build-macos (push) Failing after 48s
Build App / build-windows (push) Successful in 3m9s
Build App / build-linux (push) Has been cancelled
Builds a universal binary (aarch64 + x86_64) targeting both Apple
Silicon and Intel Macs. Produces .dmg and .app.tar.gz artifacts,
uploaded to a separate Gitea release tagged with -mac suffix.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 16:57:35 -08:00
shadow-testandClaude Opus 4.6 854f59a95a Fix Docker/CI: reproducible Windows build, Dockerfile cleanup
- Fix Windows CI build to use npm ci instead of deleting lockfile and
  running npm install, ensuring reproducible cross-platform builds
- Remove duplicate uv/ruff root installations from Dockerfile (only
  need the claude user installations)
- Make AWS CLI install architecture-aware using uname -m for arm64
  compatibility
- Remove unused SiblingContainers component (dead code)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 20:43:14 +00:00
shadow-testandClaude Opus 4.6 b77b9679b1 Auto-increment app version using git commit count in CI builds
Build App / build-windows (push) Successful in 3m11s
Build App / build-linux (push) Successful in 4m7s
Version is computed as 0.1.{commit_count} and patched into
tauri.conf.json, package.json, and Cargo.toml at build time.
Release tags now use v0.1.N format instead of build-{sha}.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:12:24 -08:00
shadow-testandClaude Opus 4.6 9454f30b4d Fix Windows upload: rewrite release upload in cmd instead of bash
Build App / build-windows (push) Successful in 3m6s
Build App / build-linux (push) Successful in 4m17s
The Windows runner doesn't have bash. Rewrite the Gitea release
API upload step using cmd batch syntax.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 08:13:20 -08:00
shadow-testandClaude Opus 4.6 fb8161dc0d Replace upload-artifact with Gitea release API
Build App / build-windows (push) Failing after 3m8s
Build App / build-linux (push) Has been cancelled
upload-artifact@v4 doesn't support Gitea (GHES). Use the Gitea
REST API to create releases and upload build artifacts directly.
Each successful push creates a tagged release with the build outputs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 08:08:57 -08:00
shadow-testandClaude Opus 4.6 476d3a9727 Fix Windows build: set npm os=win32 before installing
Build App / build-windows (push) Failing after 1m47s
Build App / build-linux (push) Has been cancelled
The Gitea act runner sets npm's os config to linux even on Windows,
causing npm to skip Windows-specific optional deps like rollup and
esbuild native bindings. Explicitly set os=win32 before npm install.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:59:17 -08:00
shadow-testandClaude Opus 4.6 3f96c45d9e Fix Windows build: explicitly install rollup and esbuild native bindings
Build App / build-windows (push) Failing after 18s
Build App / build-linux (push) Has been cancelled
npm's optional dependency resolution fails to install the Windows
platform-specific native bindings. Install them explicitly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:56:59 -08:00
shadow-testandClaude Opus 4.6 dd6e63bbf6 Fix Windows build: build frontend separately from Tauri
Build App / build-windows (push) Failing after 22s
Build App / build-linux (push) Has been cancelled
The beforeBuildCommand in tauri.conf.json spawns a subprocess
that inherits a broken rollup native binding. Build the frontend
as a separate CI step, then skip beforeBuildCommand via
TAURI_CONFIG override when running cargo tauri build.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:55:08 -08:00
shadow-testandClaude Opus 4.6 fe978be5fe Fix Linux build: add xdg-utils for AppImage bundling
Build App / build-windows (push) Failing after 24s
Build App / build-linux (push) Has been cancelled
The AppImage bundler requires xdg-open to be present.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:51:58 -08:00
shadow-testandClaude Opus 4.6 439c84ed13 Fix Windows build: remove lockfile before npm install
Build App / build-windows (push) Failing after 28s
Build App / build-linux (push) Has been cancelled
The lockfile was generated on Linux and doesn't include Windows
platform-specific optional deps (rollup, esbuild, etc). Delete
package-lock.json and node_modules so npm resolves fresh.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:50:20 -08:00
shadow-testandClaude Opus 4.6 03fb832fa2 Fix Windows build: quote cargo version specifier
Build App / build-windows (push) Failing after 4m2s
Build App / build-linux (push) Failing after 4m51s
The caret in ^2 needs quoting in cmd shell to avoid being
interpreted as an escape character.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:45:19 -08:00
shadow-testandClaude Opus 4.6 5a69b54d5c Fix Windows build: install Tauri CLI via cargo, use npm install
Build App / build-windows (push) Failing after 13s
Build App / build-linux (push) Has been cancelled
The npm @tauri-apps/cli package uses platform-specific optional
dependencies that don't resolve correctly when the lockfile was
generated on Linux. Install tauri-cli via cargo instead, and use
npm install (not npm ci) to resolve Windows-native packages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:44:23 -08:00
shadow-testandClaude Opus 4.6 276179339e Fix Windows build: use cmd shell with explicit PATH
Build App / build-windows (push) Failing after 32s
Build App / build-linux (push) Has been cancelled
GITHUB_PATH file isn't picked up between steps on the Gitea runner.
Switch to cmd shell and prepend cargo/node to PATH in each step.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:42:57 -08:00
shadow-testandClaude Opus 4.6 da0b913c63 Fix Windows build: use powershell instead of pwsh
Build App / build-windows (push) Failing after 55s
Build App / build-linux (push) Has been cancelled
The runner doesn't have PowerShell Core (pwsh) installed.
Fall back to Windows PowerShell (powershell) which is always available.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:40:33 -08:00
shadow-testandClaude Opus 4.6 a8a02b7c6c Fix Windows build: use PowerShell instead of bash-based actions
Build App / build-windows (push) Failing after 12s
Build App / build-linux (push) Has been cancelled
The Gitea runner on Windows doesn't have bash available for
composite actions. Replace dtolnay/rust-toolchain and
actions/setup-node with direct PowerShell commands.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:39:32 -08:00
shadow-testandClaude Opus 4.6 7ce707e0fa Add Gitea Action to build app for Linux and Windows
Build App / build-windows (push) Failing after 1m34s
Build App / build-linux (push) Has been cancelled
Triggers on pushes to app/ directory. Builds Tauri app on both
platforms with Rust caching, uploads .AppImage/.deb/.rpm for Linux
and .msi/.exe for Windows as artifacts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 07:35:45 -08:00
shadow-testandClaude Opus 4.6 97a0745ead Initial commit: Triple-C app, container, and CI
Tauri v2 desktop app (React/TypeScript + Rust) for managing
containerized Claude Code environments. Includes Gitea Actions
workflow for building and pushing the sandbox container image,
and a BUILDING.md guide for manual app builds on Linux and Windows.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 04:29:51 +00:00