agent-orchestrator/backend/internal/cli
neversettle 7880f59cf5
refactor(backend): LLD maintainability fixes in controllers/service layers (#95) (#96)
* refactor(backend): LLD maintainability fixes in controllers/service layers

Addresses the high + medium severity findings from the LLD review of
backend/internal/httpd and backend/internal/service (#95):

1. Controllers no longer import internal/session_manager. Session sentinel
   errors are now *domain.ServiceError values carrying their own HTTP mapping,
   so the controller translates them with one generic errors.As — no
   cross-package sentinel imports.
2. One error pattern across services: project.Error is now an alias of the
   shared domain.ServiceError, and session_manager sentinels use it too. A
   single writeServiceError replaces the per-resource error switches.
3. Clean-orchestrator business logic moved out of the controller into
   session.Service.SpawnOrchestrator(ctx, projectID, clean).
4. isGitRepo no longer treats case-different paths as equal on case-sensitive
   filesystems; case-insensitive compare is gated to darwin/windows via samePath.
5. Project repo check sits behind an injectable GitChecker, so the service is
   testable without a real git binary.
6. httpd exports only the production constructors (NewWithDeps,
   NewRouterWithControl); the 3 test-only wrappers are removed and the
   "router with empty deps" convenience moved to an unexported test helper.

Closes #95

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

* refactor(backend): standardize service errors on internal/httpd/errors

Replace the domain.ServiceError approach with a REST-API-scoped error package
and a single envelope renderer, per review feedback:

- Add internal/httpd/errors (package errors, aliased apierr): one structured
  Error type with semantic Kinds (Internal/Invalid/NotFound/Conflict) and
  constructors. Imports nothing, so any layer can depend on it.
- envelope.WriteError is now the single path from a service error to the wire
  APIError, and the only place a Kind becomes an HTTP status/word. The
  per-resource writeProjectError/writeSessionError translators are gone.
- Delete domain/errors.go (keeps domain pure of HTTP-flavored kinds) and
  service/project/errors.go (no per-service error files); services build
  errors inline via apierr constructors.
- session_manager sentinels are apierr.Error values (pointer identity still
  works with errors.Is).

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

* revert(backend): drop GitChecker seam and isGitRepo case-sensitivity change

Defer findings #4 (isGitRepo case-sensitivity) and #5 (GitChecker seam) out
of this PR. Restores the original exec-based isGitRepo and the New(store)
constructor; removes git.go, git_test.go, and the test-only export shims. The
error-standardization and other findings are unaffected.

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

* refactor(session): translate engine errors to API errors at the facade

The session_manager is the internal command engine and must not depend on the
REST API error vocabulary. Revert its sentinels to plain errors.New values and
move the engine→API translation into the service/session facade (toAPIError),
which is the correct boundary. Controllers still see apierr.Error and never
import the engine; the engine no longer imports internal/httpd/errors.

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

* docs(session): tighten error comments to state what the code does

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

* style(envelope): make KindInternal an explicit case in httpStatus

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

* refactor(apierr): rename package, test SpawnOrchestrator, parity fixes

Address review feedback on PR #96:
- Rename internal/httpd/errors → internal/httpd/apierr (package apierr) so
  importers no longer alias around the stdlib errors package.
- Add a commander seam to session.Service and unit-test the relocated
  clean-orchestrator rule: clean=true kills all active orchestrators before
  spawning; clean=false spawns without kills.
- project.Add: wrap the UpsertProject store error in apierr.Internal for parity
  with its sibling paths (was a raw 500).
- Document that KindInternal is iota's zero value, so a zero-value Error
  defaults to 500.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 18:09:02 +05:30
..
client.go feat: add light backend CLI commands (#98) 2026-06-03 16:18:00 +05:30
client_test.go Add `ao spawn` + `ao project add` (spawn a real worker end-to-end) (#77) 2026-06-02 18:39:13 +05:30
completion.go fix(cli): harden daemon control surface and stop CLI from writing the store 2026-06-01 01:55:14 +05:30
doctor.go feat(cli): enrich ao doctor (#90) (#99) 2026-06-03 16:50:54 +05:30
doctor_test.go feat(cli): enrich ao doctor (#90) (#99) 2026-06-03 16:50:54 +05:30
dto_drift_e2e_test.go refactor(backend): LLD maintainability fixes in controllers/service layers (#95) (#96) 2026-06-03 18:09:02 +05:30
e2e_test.go feat(cli): enrich ao doctor (#90) (#99) 2026-06-03 16:50:54 +05:30
exitcode_test.go test(cli): pin ExitCode mapping (usage=2, runtime=1, nil=0) 2026-06-01 02:38:25 +05:30
orchestrator.go feat: add light backend CLI commands (#98) 2026-06-03 16:18:00 +05:30
orchestrator_test.go feat: add light backend CLI commands (#98) 2026-06-03 16:18:00 +05:30
output.go feat(backend): add cobra cli foundation 2026-06-01 01:44:43 +05:30
process.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
process_unix.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
process_windows.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
project.go feat(cli): add ao project ls/get/rm (#90) (#91) 2026-06-03 04:46:55 +05:30
project_test.go feat(cli): add ao project ls/get/rm (#90) (#91) 2026-06-03 04:46:55 +05:30
root.go feat(cli): enrich ao doctor (#90) (#99) 2026-06-03 16:50:54 +05:30
root_test.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
send.go fix: prefix ao send messages with sender session (#85) 2026-06-02 21:39:21 +05:30
send_test.go fix: prefix ao send messages with sender session (#85) 2026-06-02 21:39:21 +05:30
session.go feat: add light backend CLI commands (#98) 2026-06-03 16:18:00 +05:30
session_test.go feat: add light backend CLI commands (#98) 2026-06-03 16:18:00 +05:30
spawn.go Add `ao spawn` + `ao project add` (spawn a real worker end-to-end) (#77) 2026-06-02 18:39:13 +05:30
spawn_test.go Add `ao spawn` + `ao project add` (spawn a real worker end-to-end) (#77) 2026-06-02 18:39:13 +05:30
start.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
status.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
stop.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
stop_test.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30
version.go refactor: simplify session lifecycle and zellij runtime (#62) 2026-06-01 08:42:49 +05:30