* 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>