Commit Graph

8 Commits

Author SHA1 Message Date
Harshit Singh Bhandari 2cd3b88cfa
fix(ci): Windows publish shell + fresh-install smoke check (#2267) (#2269)
* fix(ci): pin publish step to bash so the retry loop runs on Windows

The 3x retry wrapper added in #2266 is bash syntax, but the release
matrix Publish step inherited the runner default shell, which is
PowerShell on windows-latest. That made every Windows publish fail with
a ParserError. Pin shell: bash on all four publish steps.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ci): point fresh-install smoke check at an empty release repo (#2267)

The container check asserts `ao start` fails cleanly on a fresh box with
no published asset. Now that AgentWrapper publishes a linux-x64 AppImage,
an unpinned smoke binary downloads it and exits 0, tripping the
assertion. Build the smoke binary against a release repo with no assets
so the fetch path deterministically 404s and start exits non-zero with a
clear error, preserving the test's intent without depending on what the
real repo publishes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 15:44:30 +05:30
Harshit Singh Bhandari bc84b6d2a3
feat(cli): ao start fetch/open for Windows and Linux (T6/T7) (#2204)
* feat(start): implement ao start fetch/open for Windows and Linux

Fill in the non-darwin branches of the bootstrapper (T6/T7):

- assetName() selects the per-GOOS stable release asset: windows ->
  agent-orchestrator-win32-x64.exe (NSIS installer), linux ->
  agent-orchestrator-linux-x64.AppImage. amd64-only for now via
  requireAMD64(), which returns a clear unsupported-arch error.
- fetchApp() dispatches per GOOS. Windows downloads the NSIS installer and
  runs it silently (/S) to the default per-user dir, then resolves the
  installed exe under %LOCALAPPDATA%\Programs. Linux downloads the AppImage
  to a stable path under ~/.ao (atomic temp+rename), chmods it executable,
  and skips any install step so re-runs resolve without re-fetching.
- knownAppLocations() scans the per-user and per-machine Windows install
  dirs and the stable Linux AppImage path.
- isUsableBundle() treats a win exe / linux AppImage as a regular file
  (darwin stays a directory).
- openApp() launches win/linux detached via the existing StartProcess seam,
  forwarding --installed-via=npm-bootstrap, and falls back to manual-open on
  spawn failure.

The Windows silent-install path is marked ponytail (untestable on the macOS
build host); a wrong install dir surfaces as a clear not-found error. Tests
cover asset naming, arch gating, scan locations, regular-file vs dir, and
the detached-spawn + fallback paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(release): build + publish a Linux AppImage for ao start (T7)

AppImage is the Linux fetch-and-run artifact for the bootstrapper (spec
§11.3): a single self-contained executable ao start downloads and runs
directly, no system package manager.

- makers/maker-appimage.ts: a MakerBase subclass bridging to
  electron-builder's buildForge (appImage target), mirroring maker-nsis.ts,
  since Forge has no first-party AppImage maker. publish:null so Forge owns
  release uploads.
- forge.config.ts: register MakerAppImage for linux; keep deb/rpm for users
  who want a system package.
- frontend-release.yml: on ubuntu-latest, copy the built AppImage to the
  stable, space-free name agent-orchestrator-linux-x64.AppImage and upload
  it to the v<version> release with --clobber, mirroring the Windows step.

Build-untested on this macOS host: the first ubuntu CI run must confirm the
electron-builder AppImage target token and the out/make/*.AppImage output
glob.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(ci): green up ao start Win/Linux PR (lint, cross-OS test, container smoke)

Five golangci-lint findings in start.go, two cross-OS test failures, and the
fresh-install container smoke were broken by the Win/Linux bootstrapper diff.

Go lint (start.go):
- gocritic filepathJoin: build "/Applications/<bundle>" as a literal instead of
  filepath.Join with a separator-bearing arg.
- gocritic httpNoBody: pass http.NoBody, not nil, to NewRequestWithContext.
- gosec G302: annotate the AppImage chmod 0755 with a nolint; an AppImage is a
  self-contained executable and must be executable.
- nilerr: annotate openApp's intentional (false, nil) on launch failure; the
  failure is reported via the bool, not as an error.
- unparam: resolveApp's error result was always nil; drop it and update callers.

Cross-OS tests (start_test.go):
- makeBundle created a directory, which only stats as usable on macOS. Make it a
  regular file on Windows/Linux so the marker/scan resolve tests pass there,
  matching isUsableBundle's per-OS rule.

Container fresh-install smoke (test/cli/install-check.sh, Dockerfile):
- ao start is now the desktop-app launcher and no longer runs a daemon, so the
  old daemon status/shutdown/stop assertions could never pass. Assert instead
  that on a fresh box start reaches the fetch path and exits non-zero with a
  clear error (404 download on amd64, unsupported-arch on arm64). Refresh the
  stale daemon-reaping comments in the Dockerfile.

Verified locally: go build/vet ok, golangci-lint v2.12.2 reports 0 issues,
go test -tags e2e ./internal/cli/... passes (the only remaining failure,
TestE2E_Lifecycle, is a pre-existing daemon-shutdown flake that fails the same
way on upstream/main on this host), and the container smoke passes on both
linux/arm64 and linux/amd64.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 20:50:30 +05:30
yyovil 5982051651
chore: add prettier config and CI auto-formatter (#166)
* chore: add prettier config and CI auto-formatter

Adds .prettierrc and .prettierignore (config only, no local enforcement).
Formatting runs in CI via the prettier.yml workflow: on every push to a
non-main branch, Prettier rewrites changed files and commits the result back
using GITHUB_TOKEN. Developers never need to run Prettier locally.

Intentionally excludes husky/lint-staged — local pre-commit hooks are the
wrong layer for a formatter that the whole team doesn't need installed.

Also adds .envrc.local to .gitignore for personal local shell overrides.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Entire-Checkpoint: 27336650d2ee

* chore: format with prettier [skip ci]

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-10 09:09:17 +05:30
prateek a34094e7d8
refactor: simplify session lifecycle and zellij runtime (#62)
* refactor: remove canonical lifecycle state

* refactor: move sqlite stores into subpackage (#62)

* refactor: strengthen sqlite generated model types (#62)

* refactor: remove lifecycle notifications (#62)

* docs: remove notification cleanup leftovers (#62)

* refactor: narrow lifecycle manager scope (#62)

* refactor: keep PR nudges in lifecycle (#62)

* refactor: trim unused storage and lifecycle contracts (#62)

* refactor: align storage and runtime observation surfaces (#62)

* refactor: remove stale daemon and adapter bloat (#62)

* test: fix terminal ring race assertion (#62)

* refactor: trim lifecycle and http boilerplate (#62)

* refactor: expose sqlite CDC source directly (#62)

* refactor: share process liveness checks (#62)

* test: trim lifecycle store fake surface (#62)

* refactor: separate PR observations from storage rows (#62)

* refactor: trim remaining cleanup surfaces (#62)

* refactor: narrow observation and PR display APIs (#62)

* refactor: move PR write DTOs out of domain (#62)

* refactor: normalize PR domain storage types (#62)

* refactor: remove unused session port interface (#62)

* fix: reject unexpected CLI arguments (#62)

* refactor: use session metadata for spawn completion (#62)

* refactor: narrow session runtime dependency (#62)

* fix: validate zellij version in doctor (#62)

* refactor: split observation port DTOs (#62)

* chore: add sqlc generation script (#62)

* refactor: clarify terminal mux naming (#62)

* fix: tolerate nil loggers (#62)

---------

Co-authored-by: itrytoohard <ayetrytoohard@gmail.com>
2026-06-01 08:42:49 +05:30
itrytoohard c0bf99eb22 test(cli): port the E2E suite to cross-platform Go; slim the Docker harness
Replaces the growing bash smoke test with a Go os/exec suite behind the `e2e`
build tag (backend/internal/cli/e2e_test.go). It builds the real binary and
drives start/status/doctor/stop + the daemon-control HTTP surface against
isolated state (temp dir + OS-assigned free port), and now runs natively on
ubuntu + macOS + WINDOWS in CI — finally covering the Windows
CREATE_NEW_PROCESS_GROUP detach path and per-OS os.UserConfigDir resolution
that a Linux container can't observe. `go test -tags e2e -v` logs every command
and its output, replacing the bash -v flag.

- backend/internal/cli/e2e_test.go: 8 table-style TestE2E_* cases; strips any
  inherited AO_* env so a real daemon's AO_PORT can't leak in.
- test/cli/install-check.sh: small, linear fresh-install proof the Dockerfile
  runs (binary on PATH, no toolchain) — kept as the hardening tier.
- test/cli/Dockerfile: run install-check.sh instead of the full bash suite.
- .github/workflows/cli-e2e.yml: `native` is now a go test matrix over
  ubuntu+macos+windows; `container` builds the image and runs it with --init.
- Removes test/cli/smoke.sh and test/cli/run-local.sh (superseded by `go test`).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 03:14:08 +05:30
itrytoohard 4f13dd1b83 test(cli): add -v/--verbose mode that prints each command and full output
run-local.sh -v (or AO_SMOKE_VERBOSE=1) makes smoke.sh echo every command and
its complete output, indented, alongside the PASS/FAIL — for auditing exactly
what the suite runs and what the CLI returns. Default output is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 03:04:54 +05:30
itrytoohard a9e83011f1 docs(test): correct --init rationale (suite uses a fabricated dead PID)
The stale-daemon assertion does not depend on container PID-1 reaping — it
writes a fabricated dead PID rather than killing a real process. --init is
still run so the real daemon spawned by the `start` test (detached via setsid)
is reaped after `stop` instead of lingering as a zombie. Reword the README,
Dockerfile, and workflow comments to say that accurately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 02:37:51 +05:30
itrytoohard 3680ac5474 test(cli): add end-to-end smoke test + Docker/CI harness
Adds a fresh-machine, install→use→verify E2E test for the `ao` CLI and wires
it into CI. The suite drives the real binary (start/status/doctor/stop + the
daemon-control HTTP surface) against fully isolated state — its own temp
run-file, data dir, and an auto-picked free loopback port — so it never
collides with a developer's real AO install or daemon.

- test/cli/smoke.sh: 40 assertions covering install resolution, version/help
  (daemon hidden), doctor text+json (and that it does NOT migrate SQLite),
  status stopped/stale/ready, start fresh+idempotent, daemon-created store,
  /healthz identity, the /shutdown CSRF + DNS-rebinding guard (403 + survives),
  graceful/stale/idempotent stop, run-file ownership cleanup, exit codes
  (2 usage / 1 runtime), and completion for all four shells. It deliberately
  ignores an inherited AO_PORT and self-allocates a free port for isolation.
- test/cli/Dockerfile: models installing ao on a fresh machine — builds the
  binary, drops it on PATH in a clean Debian image with only runtime deps
  (git/tmux/curl), runs the suite as a non-root user.
- test/cli/run-local.sh: build-from-source + native run convenience wrapper.
- .github/workflows/cli-e2e.yml: two tiers — `native` runs the suite on a
  ubuntu+macos runner matrix (the real VMs, to cover the unix setsid detach and
  macOS os.UserConfigDir paths a Linux container can't), and `container` runs
  the fresh-machine Docker image with --init (real PID-1 reaper so the
  stale-daemon assertion is reliable).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 02:33:56 +05:30