Skip to content

feat: add automation#16

Merged
pedronauck merged 20 commits into
mainfrom
automation
Apr 11, 2026
Merged

feat: add automation#16
pedronauck merged 20 commits into
mainfrom
automation

Conversation

@pedronauck
Copy link
Copy Markdown
Member

@pedronauck pedronauck commented Apr 11, 2026

Summary by CodeRabbit

  • New Features

    • Full automation platform: scheduled jobs (cron/interval/one‑time), event-driven triggers, webhooks, retries/backoff, fire‑limits, replay protection, and manual trigger.
    • New HTTP API endpoints for automation and webhooks; automation included in health/status and OpenAPI.
    • CLI commands to manage jobs, triggers, and runs with multiple output formats.
  • Tests

    • Broad unit and integration coverage across automation runtime, scheduler, dispatcher, trigger engine, webhooks, and CLI.

@pedronauck pedronauck self-assigned this Apr 11, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 11, 2026

Walkthrough

Adds a full automation subsystem: domain model, validation and template tooling, dispatcher/scheduler/trigger engine, manager runtime, API + CLI surfaces (including webhook endpoints), TOML config support, extensive tests, and Go module dependency updates.

Changes

Cohort / File(s) Summary
Go module
go.mod
Promoted several indirect deps to direct and added scheduling/cron/cli libs (github.com/go-co-op/gocron/v2, github.com/jonboulle/clockwork, github.com/robfig/cron/v3, github.com/spf13/cobra).
API contracts & responses
internal/api/contract/automation.go, internal/api/contract/responses.go, internal/api/contract/contract_test.go
Added automation DTOs (jobs/triggers/runs/webhook payloads/requests), HasChanges helpers, response wrappers, extended HealthResponse, and contract tests.
API core & handlers
internal/api/core/automation.go, internal/api/core/conversions.go, internal/api/core/errors.go, internal/api/core/interfaces.go, internal/api/core/handlers.go
New Gin handlers, query parsers, conversion helpers, automation error→HTTP mapping, AutomationManager interface, and wiring into BaseHandlers.
API tests & testutil
internal/api/core/*.go, internal/api/testutil/apitest.go, internal/api/core/test_helpers_test.go
Unit and integration tests for handlers, helper fixtures, and a StubAutomationManager test double.
HTTP/UDS server & routes
internal/api/httpapi/*, internal/api/udsapi/*, internal/api/httpapi/routes.go, internal/api/udsapi/routes.go, internal/api/httpapi/server.go, internal/api/udsapi/server.go
Added server options to inject automation manager, registered /api/automation/* and /api/webhooks/* routes, and updated route tests.
OpenAPI spec
internal/api/spec/spec.go, internal/api/spec/spec_test.go
Added automation/webhook operations, header parameter support, enum schema generation, and spec tests.
Automation domain model & persistence
internal/automation/model/*, internal/automation/model/persistence.go, internal/automation/persistence.go, internal/automation/types.go
New model types/enums, persistence query/overlay types, sentinel errors, and re-exported aliases.
Model validation & templates
internal/automation/model/validate.go, internal/automation/model/template.go, internal/automation/template.go, internal/automation/validate.go
Comprehensive validation (schedules/retry/fire-limit/scope/filter) and strict trigger prompt template parsing/validation with public wrappers.
Dispatcher, TriggerEngine, Scheduler, Manager
internal/automation/dispatch.go, internal/automation/trigger.go, internal/automation/schedule.go, internal/automation/manager.go
New Dispatcher (concurrency, retries, fire-limits), TriggerEngine (webhook auth/replay/filtering), Scheduler (gocron-backed), and Manager (config sync, lifecycle, CRUD, webhook handling).
Scheduler & dispatcher tests
internal/automation/*_test.go, internal/automation/*_integration_test.go
Extensive unit and integration tests for dispatcher, scheduler, trigger engine and manager (many new test files, including integration-tagged suites).
CLI surface & client
internal/cli/automation.go, internal/cli/client.go, internal/cli/*_test.go, internal/cli/root.go
New automation Cobra command (jobs/triggers/runs), client methods and type aliases, parsing/formatting, and many CLI tests/integration updates.
Configuration
internal/config/automation.go, internal/config/automation_integration_test.go
TOML-backed automation config structs, validation, overlay merging logic, and integration tests.
Extension API
internal/automation/extension.go, internal/automation/extension_test.go
Added extension trigger request type and validation requiring ext. prefix.
Test scaffolding updates
many files under internal/api/*, internal/cli/*, internal/automation/*
Test helpers wired to accept/inject automation manager; many tests added/updated to cover automation surface.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client/CLI
    participant API as API Server
    participant Manager as Automation Manager
    participant Dispatcher as Dispatcher
    participant Store as Run Store
    participant Session as Session Manager

    Client->>API: POST /api/automation/jobs/:id/trigger
    API->>Manager: TriggerJob(ctx, id)
    Manager->>Dispatcher: Dispatch(Request{Kind: Manual, Job: ...})
    Dispatcher->>Store: CreateRun(status=scheduled)
    Dispatcher->>Session: Create(sessionOpts)
    Session-->>Dispatcher: sessionID
    Dispatcher->>Session: Prompt(sessionID, prompt)
    Dispatcher->>Store: UpdateRun(status=completed/failed)
    Dispatcher-->>Manager: run result
    Manager-->>API: RunPayload
    API-->>Client: 200 { run }
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

  • compozy/compozy#241: Related webhook handling additions (endpoints, signature/timestamp headers, size limits, dispatch) that overlap webhook/auth/replay logic.
  • feat: improve hooks system #10: Related subsystem wiring and API surface changes similar to the automation manager and webhook integrations added here.
  • refactor: project structure #7: Related API contract/core refactor that this PR builds upon (contracts, conversions, and handler wiring).
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch automation

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/api/udsapi/handlers_test.go (1)

67-147: 🛠️ Refactor suggestion | 🟠 Major

Refactor this route-coverage test into t.Run("Should...") subtests.

The updated test is still a single-case function; project test policy requires subtests by default, and this case is a good candidate for a “Should register all tech-spec routes” subtest wrapper (or table-driven variants for route groups).

As per coding guidelines, "Use table-driven tests with subtests (t.Run) as default" and "MUST use t.Run("Should...") pattern for ALL test cases".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/udsapi/handlers_test.go` around lines 67 - 147, Refactor
TestRegisterRoutesCoversTechSpecEndpoints into a subtest by wrapping the
existing setup and assertions in t.Run("Should register all tech-spec routes",
func(t *testing.T) { ... }), keeping the current calls to newTestHomePaths,
newTestHandlers, newTestRouter and the route collection/assertion logic intact
but executed inside the subtest; if you prefer clearer structure, extract the
expected routes slice into a local variable and/or use a small table-driven
subtest loop for route groups, but ensure the main test function only defines
the subtest(s) via t.Run and preserves the same comparisons and failure
behavior.
🧹 Nitpick comments (11)
internal/api/contract/contract_test.go (1)

249-268: Cover zero-value PATCH fields in HasChanges() tests.

The risky case for pointer-based update DTOs is an explicit zero value like Enabled: ptr(false): it should still count as a change. Right now this only proves string-backed fields, so a regression in bool handling would still pass.

Suggested test additions
 func TestAutomationUpdateRequestsHasChanges(t *testing.T) {
 	t.Parallel()

 	name := "updated"
 	secret := "secret"
+	disabled := false

 	if (contract.UpdateJobRequest{}).HasChanges() {
 		t.Fatal("UpdateJobRequest{}.HasChanges() = true, want false")
 	}
 	if !(contract.UpdateJobRequest{Name: &name}).HasChanges() {
 		t.Fatal("UpdateJobRequest{Name}.HasChanges() = false, want true")
 	}
+	if !(contract.UpdateJobRequest{Enabled: &disabled}).HasChanges() {
+		t.Fatal("UpdateJobRequest{Enabled:false}.HasChanges() = false, want true")
+	}

 	if (contract.UpdateTriggerRequest{}).HasChanges() {
 		t.Fatal("UpdateTriggerRequest{}.HasChanges() = true, want false")
 	}
 	if !(contract.UpdateTriggerRequest{WebhookSecret: &secret}).HasChanges() {
 		t.Fatal("UpdateTriggerRequest{WebhookSecret}.HasChanges() = false, want true")
 	}
+	if !(contract.UpdateTriggerRequest{Enabled: &disabled}).HasChanges() {
+		t.Fatal("UpdateTriggerRequest{Enabled:false}.HasChanges() = false, want true")
+	}
 }

As per coding guidelines, "MUST test meaningful business logic, not trivial operations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/contract/contract_test.go` around lines 249 - 268, Add test
cases to TestAutomationUpdateRequestsHasChanges that cover pointer-based fields
with explicit zero values so HasChanges() treats them as changes; specifically,
assert that UpdateJobRequest{Enabled: ptr(false)}.HasChanges() returns true and
similarly assert for any boolean pointer fields on UpdateTriggerRequest (e.g.,
Enabled or other bool pointers) using a ptr(false) value. Locate the existing
TestAutomationUpdateRequestsHasChanges and extend it by creating local bool
variables (or a helper ptr function) and adding assertions analogous to the
existing string-pointer checks to ensure zero-value pointers are counted as
changes.
internal/cli/client_test.go (1)

411-676: Split the automation client E2E test into focused t.Run("Should...") cases.

This test exercises a large slice of the client surface in one flow, so the first failure hides the rest of the regressions and makes the failing capability harder to isolate. Breaking it up by operation (Should list jobs, Should create job, Should list runs, etc.) will keep failures actionable and aligns with the repo's test conventions.

As per coding guidelines, "Use table-driven tests with subtests (t.Run) as default" and "MUST use t.Run("Should...") pattern for ALL test cases".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cli/client_test.go` around lines 411 - 676, The single large
TestUnixSocketClientAutomationMethods should be split into focused subtests
using t.Run("Should ...") for each operation so failures are isolated; refactor
the test body into multiple subtests that each exercise one client method or
logical group (e.g. "Should list jobs" -> ListAutomationJobs, "Should create
job" ->
CreateAutomationJob/GetAutomationJob/UpdateAutomationJob/DeleteAutomationJob,
"Should trigger and list job runs" -> TriggerAutomationJob/AutomationJobRuns,
"Should manage triggers" ->
ListAutomationTriggers/CreateAutomationTrigger/GetAutomationTrigger/UpdateAutomationTrigger/AutomationTriggerRuns/DeleteAutomationTrigger,
and "Should list and get runs" -> ListAutomationRuns/GetAutomationRun), keep the
same request mock behavior and assertions but move them into the appropriate
t.Run blocks, sharing the same test httpClient setup and ctx while ensuring each
subtest calls t.Parallel() only where safe.
internal/automation/trigger_test.go (1)

445-472: Use named subtests for these table cases.

Both loops stop on the first failure and make it harder to see which scenario broke. Wrapping each case in t.Run("Should...") and calling t.Parallel() inside independent subtests would make the failures much easier to triage.

As per coding guidelines, "Use table-driven tests with subtests (t.Run) as default" and "Use t.Parallel() for independent subtests".

Also applies to: 479-510

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/trigger_test.go` around lines 445 - 472, The table-driven
loop over testCases should be converted into named subtests so failures are
isolated and parallelizable: for each entry in testCases, call t.Run with a
descriptive name (e.g., the path or expectation) and inside the subtest call
t.Parallel(); then execute envelopeFilterValue(envelope, tc.path) and perform
the same ok/got assertions there. Apply the same refactor to the other
table-driven cases later in the file so each scenario runs as an independent,
parallel subtest.
internal/api/testutil/apitest.go (1)

142-163: Add compile-time verification for StubAutomationManager.

This new stub is meant to satisfy core.AutomationManager, but unlike the other stubs in this file it is not pinned with a var _ ... assertion. Adding one will catch interface drift earlier as the automation surface evolves.

♻️ Proposed change
 var _ core.SessionManager = StubSessionManager{}
 var _ core.Observer = StubObserver{}
+var _ core.AutomationManager = StubAutomationManager{}
 var _ core.WorkspaceService = StubWorkspaceService{}

As per coding guidelines, "Use compile-time interface verification: var _ Interface = (*Type)(nil)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/testutil/apitest.go` around lines 142 - 163, The
StubAutomationManager type is missing a compile-time interface assertion to
ensure it implements core.AutomationManager; add the standard verification line
referencing those symbols (e.g., var _ core.AutomationManager =
(*StubAutomationManager)(nil)) adjacent to the StubAutomationManager declaration
so changes to the automation interface will fail at compile time.
internal/automation/trigger_integration_test.go (1)

94-99: Guard promptCalls() before indexing it.

Both assertions read [0] without first checking the slice length. If dispatch creates the session but never reaches Prompt, the test fails with an index panic instead of a clear assertion.

♻️ Proposed change
+	if got, want := len(creator.promptCalls()), 1; got != want {
+		t.Fatalf("len(Prompt calls) = %d, want %d", got, want)
+	}
 	if got, want := creator.promptCalls()[0].message, "Digest fresh context"; got != want {
 		t.Fatalf("Prompt().message = %q, want %q", got, want)
 	}

Also applies to: 160-165

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/trigger_integration_test.go` around lines 94 - 99, The
test indexes creator.promptCalls()[0] without checking the slice length, which
can cause an index panic; update the assertions that reference
creator.promptCalls()[0] (and the similar checks later around the other block)
to first assert the length of creator.promptCalls() (e.g., check
len(creator.promptCalls()) == expected) and only then inspect
promptCalls()[0].message (and other fields) so failures produce clear test
errors instead of panics; ensure you modify both the block around the
createCalls() check and the similar assertions in the later section (the lines
referencing creator.promptCalls()[0] and Prompt().message).
internal/cli/automation_test.go (1)

467-490: Assert the webhook fields on trigger update.

This case passes --event webhook, --webhook-id, and --endpoint-slug, but the test only checks Retry, Filter, and WebhookSecret. If any of those new flags stopped being wired into updateTriggerRequest, this test would still pass.

As per coding guidelines, "Focus on critical paths: workflow execution, state management, error handling".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cli/automation_test.go` around lines 467 - 490, The test calls
executeRootCommand to update a trigger with --event webhook, --webhook-id and
--endpoint-slug but assertions only verify Retry, Filter and WebhookSecret;
update the test (after json.Unmarshal into updated and with access to
updateTriggerRequest) to also assert that updateTriggerRequest.Event ==
"webhook" (or the enum/value used), updateTriggerRequest.WebhookID == "wbh_123"
and updateTriggerRequest.EndpointSlug == "branch-review" and that the returned
updated.ID == "trg-1"; reference the existing symbols updatedTriggerJSON,
executeRootCommand, updateTriggerRequest and TriggerRecord (and
automationpkg.RetryStrategyBackoff) when adding these checks so the test fails
if webhook flags are not wired through.
internal/automation/manager_test.go (1)

1024-1075: Make the nil-context assertions specific.

Right now any error satisfies these branches, so a validation or persistence regression would still look like a passing nil-context test. Please match the sentinel or message the manager is expected to return for nil contexts.

As per coding guidelines, "MUST have specific error assertions (ErrorContains, ErrorAs)".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 1024 - 1075, The
nil-context tests currently only check for a non-nil error; change each
assertion to verify the specific sentinel or message the manager returns for
missing contexts (e.g., use errors.Is(err, ErrMissingContext) or
require.ErrorContains(t, err, "missing context")/assert.ErrorContains as your
codebase uses). Update the checks for all manager methods listed (CreateJob,
ListJobs, GetJob, UpdateJob, DeleteJob, TriggerJob, SetJobEnabled,
CreateTrigger, ListTriggers, GetTrigger, UpdateTrigger, DeleteTrigger,
SetTriggerEnabled, ListRuns, GetRun, Status) to assert the exact expected error
by using ErrorIs/ErrorAs or ErrorContains instead of err == nil.
internal/automation/validate_test.go (1)

460-515: Assert which validation failed, not just that something failed.

These cases only check err != nil, so they still pass if validation breaks for an unrelated field or rule. Please carry a wantErr/field path per case and assert it, like the earlier table-driven sections in this file already do.

As per coding guidelines, "MUST have specific error assertions (ErrorContains, ErrorAs)".

Also applies to: 621-732, 734-787

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/validate_test.go` around lines 460 - 515, The
table-driven test TestJobValidateRejectsMissingRequiredFields currently only
checks err != nil; update each test case to include a wantErr string (or
expected field path) that identifies which validation must fail (e.g., "name",
"agent_name", "prompt"), call tc.job.Validate("job"), and assert the returned
error contains the expected substring using a specific assertion (ErrorContains
/ require.ErrorContains) rather than a nil-check; reference Job.Validate and the
test cases in TestJobValidateRejectsMissingRequiredFields and mirror the pattern
used in earlier table-driven sections that include wantErr to ensure the test
fails if a different validation rule breaks.
internal/cli/automation.go (1)

1016-1023: Potential unnecessary time.Now() call when now function is provided.

The code calls time.Now() unconditionally before checking if a custom now function is provided. While functionally correct (it gets overwritten), this is slightly wasteful and could be simplified.

♻️ Suggested simplification
-	current := time.Now().UTC()
-	if now != nil {
-		current = now().UTC()
-	}
+	var current time.Time
+	if now != nil {
+		current = now().UTC()
+	} else {
+		current = time.Now().UTC()
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cli/automation.go` around lines 1016 - 1023, The code
unconditionally calls time.Now() before checking the optional now function;
change the logic in the function that computes the time (using the current, now
and duration variables) to only call time.Now() when now is nil: set current
from now().UTC() if now != nil, otherwise set current to time.Now().UTC(), then
return current.Add(-duration), nil. This removes the unnecessary unconditional
time.Now() invocation while preserving behavior.
internal/config/automation.go (2)

255-281: Unused error return value.

toAutomationTrigger always returns nil error but the signature includes an error return. Same consideration as toAutomationJob above.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/config/automation.go` around lines 255 - 281, The
toAutomationTrigger method (parsedAutomationTrigger.toAutomationTrigger)
currently returns an error but never produces one; remove the unused error
return from its signature and update all callers to expect only
(AutomationTrigger) instead of (AutomationTrigger, error); alternatively, if you
prefer to keep the error return for future validation, add appropriate
validation logic that can return a non-nil error before the final return—ensure
consistency with toAutomationJob's approach and update references to trigger :=
parsedAutomationTrigger.toAutomationTrigger(...) accordingly.

227-253: Unused error return value.

toAutomationJob always returns nil error but the signature includes an error return. If this is intentional for future extensibility, consider documenting it; otherwise, simplify the signature.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/config/automation.go` around lines 227 - 253, The function
parsedAutomationJob.toAutomationJob declares an error return but never returns a
non-nil error; either remove the error from the signature or implement
validation that can produce meaningful errors. If you choose to simplify, change
toAutomationJob to return only (AutomationJob) and update all callers to stop
expecting an error; if you choose to keep it for future extensibility, add input
validation (e.g., validate required fields like Name, Scope, AgentName, Prompt,
Schedule) inside toAutomationJob and return a descriptive error when validation
fails so the error return is used consistently. Ensure you update all references
to parsedAutomationJob.toAutomationJob or toAutomationJob accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/api/core/automation.go`:
- Around line 618-621: The code uses io.ReadAll(c.Request.Body) which is
unbounded; replace it with a size-limited read by wrapping c.Request.Body with a
MaxBytesReader or LimitReader before reading: define a constant (e.g.
maxWebhookBodySize) and do c.Request.Body = http.MaxBytesReader(c.Writer,
c.Request.Body, maxWebhookBodySize) (or use io.LimitReader) and then call
io.ReadAll on that wrapped reader; update the error handling around the existing
payload, err block to return a clear error when the body exceeds the limit.

In `@internal/api/core/errors.go`:
- Around line 97-121: StatusForAutomationError currently falls through to 500
for the new overlay sentinel errors; add explicit mappings in
StatusForAutomationError so these domain outcomes return the intended statuses:
check errors.Is(err, automationpkg.ErrOverlayRequiresConfigSource) and return
http.StatusConflict, and check errors.Is(err,
automationpkg.ErrJobOverlayNotFound) and errors.Is(err,
automationpkg.ErrTriggerOverlayNotFound) and return http.StatusNotFound; insert
these cases before the default branch in the StatusForAutomationError switch so
overlay failures no longer produce 500.
- Around line 89-94: The NewAutomationValidationError function wraps an incoming
error but currently uses "%v" which loses the original error in the chain;
change the fmt.Errorf call in NewAutomationValidationError to use two %w verbs
so both ErrAutomationValidation and the provided err are wrapped (use
fmt.Errorf("%w: %w", ErrAutomationValidation, err)) to preserve error unwrapping
via errors.Is/errors.As.

In `@internal/api/udsapi/udsapi_integration_test.go`:
- Around line 246-260: The test currently reads run history immediately after
stopIntegrationSession and can flake; modify the section after
stopIntegrationSession(t, runtime, sessionID) to poll the runs endpoint (use
mustUnixRequest with http.MethodGet to
"http://unix/api/automation/triggers/"+created.Trigger.ID+"/runs") until
contract.RunsResponse.Runs is non-empty or a deadline expires (e.g., now+several
seconds), sleeping briefly between attempts (e.g., 100–200ms); on each attempt
decodeHTTPJSON into contract.RunsResponse, ensure response bodies are closed,
and if the deadline is reached call t.Fatalf reporting no run found. Use the
existing identifiers createIntegrationSession, stopIntegrationSession,
mustUnixRequest, decodeHTTPJSON, and contract.RunsResponse to locate and update
the code.

In `@internal/automation/dispatch.go`:
- Around line 526-552: These post-fire hook calls currently ignore returned
errors (in dispatchPostFireHook and the other post/lifecycle dispatches) causing
failures to be silent; capture the error returned by each hook call (e.g., the
calls to DispatchAutomationJobPostFire, DispatchAutomationTriggerPostFire,
DispatchAutomationRunCompleted, DispatchAutomationRunFailed), then handle it
instead of using "_, _ =" — at minimum call the dispatcher logger (e.g.,
d.logger.Errorf or similar logger on the Dispatcher) with a clear message and
error details including the relevant IDs (JobID/TriggerID/RunID), or propagate
the error by returning it from the function if the call site expects error
handling. Ensure you replace each "_, _ =" usage with proper err checking (if
err != nil { ... }) referencing the specific function names above.
- Around line 759-777: collectPromptError currently blocks reading from events
until the channel closes and doesn't respect context cancellation; update
collectPromptError to use a select loop that watches both ctx.Done() and the
events channel (e.g., for { select { case <-ctx.Done(): return ctx.Err() case
event, ok := <-events: if !ok { break out of loop } ... } }) so you stop
draining when context is canceled, still collect trimmed event.Error into errs
(as currently) when events are received, and after the loop return
errors.Join(errs...) or ctx.Err() appropriately; reference the
collectPromptError function and the errs slice and event.Error symbols when
applying the change.

In `@internal/automation/extension_test.go`:
- Around line 14-28: Update the table-driven tests in
internal/automation/extension_test.go so each test name follows the "Should..."
pattern (e.g., "Should reject built-in event names") and for the case where
Event is "session.stopped" (and generally any non-`ext.` event) replace the
loose wantErr check with a specific assertion that the validation failure
contains the ext-prefix error (use ErrorContains/ErrorAs helper) when calling
Validate("trigger_fire") on the ExtensionTriggerRequest; refer to the table
entries and the ExtensionTriggerRequest struct to locate and modify the failing
subtests.

In `@internal/automation/extension.go`:
- Around line 17-27: The Validate method on ExtensionTriggerRequest currently
trims r.Event only for checks but leaves the original value intact; change
Validate (in ExtensionTriggerRequest.Validate) to first compute trimmed :=
strings.TrimSpace(r.Event), then if trimmed == "" return the existing required
error, then if trimmed != r.Event return an error indicating surrounding
whitespace is not allowed (use nestedPath(path, "event") in the message), and
then proceed to use trimmed for the HasPrefix("ext.") check and the rest of
validation (including the existing ValidateScopeBinding call).

In `@internal/automation/manager.go`:
- Around line 365-387: The cleanup calls currently swallow errors and use
context.Background(); update the error handling in the startup/cleanup sequence
around m.loadSchedulerRegistrations, m.loadTriggerRegistrations,
triggerEngine.Start and scheduler.Start so that Shutdown(...) returns are
checked and handled (log the error and/or aggregate/return a wrapped error)
instead of using `_`, and replace context.Background() with the provided ctx or
a derived context with timeout/cancellation; ensure runtimeCancel() is still
called, then call scheduler.Shutdown(ctx) and triggerEngine.Shutdown(ctx) (or
ctxWithTimeout) and propagate or log any shutdown error rather than discarding
it.
- Around line 1682-1705: The session trigger calls currently ignore errors from
engine.FireSessionCreated and engine.FireSessionStopped; update
fireSessionCreated and fireSessionStopped to capture the returned error, check
if err != nil, and log the failure (including the error and relevant session
info) using the Manager's logger consistent with trigger.go's pattern; keep the
existing triggerRuntime and mergedRuntimeContext usage and defer cancel, but
replace "_, _ = ..." with "if _, err := engine.FireSessionCreated(...); err !=
nil { m.log.Errorf(..., err) }" (and similarly for FireSessionStopped),
referencing the functions fireSessionCreated, fireSessionStopped,
triggerRuntime, mergedRuntimeContext, and the
engine.FireSessionCreated/FireSessionStopped calls.
- Around line 358-387: The Start method currently creates runtimeCtx with
context.WithCancel(context.Background()), severing the caller's context chain;
change it to derive from the incoming ctx using context.WithoutCancel(ctx)
(i.e., runtimeCtx, runtimeCancel := context.WithoutCancel(ctx)) and update the
call to m.buildRuntimes to accept the parent ctx so buildRuntimes can also use
context.WithoutCancel(ctx) instead of context.Background(); ensure all
shutdown/cancel logic still uses runtimeCancel and that buildRuntimes signature
and its internal uses are updated accordingly (reference: Start method,
runtimeCtx, runtimeCancel, m.buildRuntimes, buildRuntimes).

In `@internal/automation/model/template.go`:
- Around line 153-171: The validator currently skips VariableNode roots, so
update validateTemplateArg to explicitly handle *parse.VariableNode* and return
an error (or otherwise reject) when a variable is used as a root for field
lookups or indexing; also adjust templateFieldPath and validateIndexArgs to
treat a VariableNode root as a disallowed/invalid path (i.e., return an error or
false that causes validation failure) instead of silently returning ok, ensuring
functions named validateTemplateArg, templateFieldPath, validateIndexArgs,
validateActivationFieldPath (and the callers
validatePipeNode/validateCommandNode) will conservatively reject any $var.Field
or index $var "field" usages.

In `@internal/automation/trigger.go`:
- Around line 99-108: The webhook handler is vulnerable to replay because
WebhookRequest lacks a delivery identifier and HandleWebhook only validates
HMAC+timestamp; add an explicit DeliveryID (string) field to WebhookRequest and
make HandleWebhook verify that DeliveryID is present, check a durable/fast dedup
store (e.g., Redis or in-memory cache with TTL) for prior processing, and
atomically mark the DeliveryID as seen with an expiration equal to your
freshness window to reject duplicates; ensure the signature validation still
runs and that HandleWebhook returns a clear error for already-seen DeliveryIDs
so replays are dropped.

In `@internal/cli/cli_integration_test.go`:
- Around line 865-879: Start the automation manager with the surrounding ctx
(not context.Background()) and register its cleanup immediately after Start
returns; i.e., call automationManager.Start(ctx) and right after a successful
start immediately defer automationManager.Stop(ctx) (or the manager's
appropriate shutdown method) before creating udsapi.New() or calling
server.Start(), then continue to append automationManager.SessionObserver() to
fanout.notifiers—this ensures the automationManager is tied to the daemon
context and always cleaned up if subsequent initialization fails.

---

Outside diff comments:
In `@internal/api/udsapi/handlers_test.go`:
- Around line 67-147: Refactor TestRegisterRoutesCoversTechSpecEndpoints into a
subtest by wrapping the existing setup and assertions in t.Run("Should register
all tech-spec routes", func(t *testing.T) { ... }), keeping the current calls to
newTestHomePaths, newTestHandlers, newTestRouter and the route
collection/assertion logic intact but executed inside the subtest; if you prefer
clearer structure, extract the expected routes slice into a local variable
and/or use a small table-driven subtest loop for route groups, but ensure the
main test function only defines the subtest(s) via t.Run and preserves the same
comparisons and failure behavior.

---

Nitpick comments:
In `@internal/api/contract/contract_test.go`:
- Around line 249-268: Add test cases to TestAutomationUpdateRequestsHasChanges
that cover pointer-based fields with explicit zero values so HasChanges() treats
them as changes; specifically, assert that UpdateJobRequest{Enabled:
ptr(false)}.HasChanges() returns true and similarly assert for any boolean
pointer fields on UpdateTriggerRequest (e.g., Enabled or other bool pointers)
using a ptr(false) value. Locate the existing
TestAutomationUpdateRequestsHasChanges and extend it by creating local bool
variables (or a helper ptr function) and adding assertions analogous to the
existing string-pointer checks to ensure zero-value pointers are counted as
changes.

In `@internal/api/testutil/apitest.go`:
- Around line 142-163: The StubAutomationManager type is missing a compile-time
interface assertion to ensure it implements core.AutomationManager; add the
standard verification line referencing those symbols (e.g., var _
core.AutomationManager = (*StubAutomationManager)(nil)) adjacent to the
StubAutomationManager declaration so changes to the automation interface will
fail at compile time.

In `@internal/automation/manager_test.go`:
- Around line 1024-1075: The nil-context tests currently only check for a
non-nil error; change each assertion to verify the specific sentinel or message
the manager returns for missing contexts (e.g., use errors.Is(err,
ErrMissingContext) or require.ErrorContains(t, err, "missing
context")/assert.ErrorContains as your codebase uses). Update the checks for all
manager methods listed (CreateJob, ListJobs, GetJob, UpdateJob, DeleteJob,
TriggerJob, SetJobEnabled, CreateTrigger, ListTriggers, GetTrigger,
UpdateTrigger, DeleteTrigger, SetTriggerEnabled, ListRuns, GetRun, Status) to
assert the exact expected error by using ErrorIs/ErrorAs or ErrorContains
instead of err == nil.

In `@internal/automation/trigger_integration_test.go`:
- Around line 94-99: The test indexes creator.promptCalls()[0] without checking
the slice length, which can cause an index panic; update the assertions that
reference creator.promptCalls()[0] (and the similar checks later around the
other block) to first assert the length of creator.promptCalls() (e.g., check
len(creator.promptCalls()) == expected) and only then inspect
promptCalls()[0].message (and other fields) so failures produce clear test
errors instead of panics; ensure you modify both the block around the
createCalls() check and the similar assertions in the later section (the lines
referencing creator.promptCalls()[0] and Prompt().message).

In `@internal/automation/trigger_test.go`:
- Around line 445-472: The table-driven loop over testCases should be converted
into named subtests so failures are isolated and parallelizable: for each entry
in testCases, call t.Run with a descriptive name (e.g., the path or expectation)
and inside the subtest call t.Parallel(); then execute
envelopeFilterValue(envelope, tc.path) and perform the same ok/got assertions
there. Apply the same refactor to the other table-driven cases later in the file
so each scenario runs as an independent, parallel subtest.

In `@internal/automation/validate_test.go`:
- Around line 460-515: The table-driven test
TestJobValidateRejectsMissingRequiredFields currently only checks err != nil;
update each test case to include a wantErr string (or expected field path) that
identifies which validation must fail (e.g., "name", "agent_name", "prompt"),
call tc.job.Validate("job"), and assert the returned error contains the expected
substring using a specific assertion (ErrorContains / require.ErrorContains)
rather than a nil-check; reference Job.Validate and the test cases in
TestJobValidateRejectsMissingRequiredFields and mirror the pattern used in
earlier table-driven sections that include wantErr to ensure the test fails if a
different validation rule breaks.

In `@internal/cli/automation_test.go`:
- Around line 467-490: The test calls executeRootCommand to update a trigger
with --event webhook, --webhook-id and --endpoint-slug but assertions only
verify Retry, Filter and WebhookSecret; update the test (after json.Unmarshal
into updated and with access to updateTriggerRequest) to also assert that
updateTriggerRequest.Event == "webhook" (or the enum/value used),
updateTriggerRequest.WebhookID == "wbh_123" and
updateTriggerRequest.EndpointSlug == "branch-review" and that the returned
updated.ID == "trg-1"; reference the existing symbols updatedTriggerJSON,
executeRootCommand, updateTriggerRequest and TriggerRecord (and
automationpkg.RetryStrategyBackoff) when adding these checks so the test fails
if webhook flags are not wired through.

In `@internal/cli/automation.go`:
- Around line 1016-1023: The code unconditionally calls time.Now() before
checking the optional now function; change the logic in the function that
computes the time (using the current, now and duration variables) to only call
time.Now() when now is nil: set current from now().UTC() if now != nil,
otherwise set current to time.Now().UTC(), then return current.Add(-duration),
nil. This removes the unnecessary unconditional time.Now() invocation while
preserving behavior.

In `@internal/cli/client_test.go`:
- Around line 411-676: The single large TestUnixSocketClientAutomationMethods
should be split into focused subtests using t.Run("Should ...") for each
operation so failures are isolated; refactor the test body into multiple
subtests that each exercise one client method or logical group (e.g. "Should
list jobs" -> ListAutomationJobs, "Should create job" ->
CreateAutomationJob/GetAutomationJob/UpdateAutomationJob/DeleteAutomationJob,
"Should trigger and list job runs" -> TriggerAutomationJob/AutomationJobRuns,
"Should manage triggers" ->
ListAutomationTriggers/CreateAutomationTrigger/GetAutomationTrigger/UpdateAutomationTrigger/AutomationTriggerRuns/DeleteAutomationTrigger,
and "Should list and get runs" -> ListAutomationRuns/GetAutomationRun), keep the
same request mock behavior and assertions but move them into the appropriate
t.Run blocks, sharing the same test httpClient setup and ctx while ensuring each
subtest calls t.Parallel() only where safe.

In `@internal/config/automation.go`:
- Around line 255-281: The toAutomationTrigger method
(parsedAutomationTrigger.toAutomationTrigger) currently returns an error but
never produces one; remove the unused error return from its signature and update
all callers to expect only (AutomationTrigger) instead of (AutomationTrigger,
error); alternatively, if you prefer to keep the error return for future
validation, add appropriate validation logic that can return a non-nil error
before the final return—ensure consistency with toAutomationJob's approach and
update references to trigger := parsedAutomationTrigger.toAutomationTrigger(...)
accordingly.
- Around line 227-253: The function parsedAutomationJob.toAutomationJob declares
an error return but never returns a non-nil error; either remove the error from
the signature or implement validation that can produce meaningful errors. If you
choose to simplify, change toAutomationJob to return only (AutomationJob) and
update all callers to stop expecting an error; if you choose to keep it for
future extensibility, add input validation (e.g., validate required fields like
Name, Scope, AgentName, Prompt, Schedule) inside toAutomationJob and return a
descriptive error when validation fails so the error return is used
consistently. Ensure you update all references to
parsedAutomationJob.toAutomationJob or toAutomationJob accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 587e0339-c0e2-4e67-b7f2-7b9f7b7bd2ac

📥 Commits

Reviewing files that changed from the base of the PR and between 4c5ecd0 and 33c6757.

⛔ Files ignored due to path filters (28)
  • .compozy/tasks/automation/_meta.md is excluded by !**/*.md
  • .compozy/tasks/automation/_tasks.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/MEMORY.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_01.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_02.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_03.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_04.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_05.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_06.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_07.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_08.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_09.md is excluded by !**/*.md
  • .compozy/tasks/automation/memory/task_10.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_01.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_02.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_03.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_04.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_05.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_06.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_07.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_08.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_09.md is excluded by !**/*.md
  • .compozy/tasks/automation/task_10.md is excluded by !**/*.md
  • bun.lock is excluded by !**/*.lock
  • go.sum is excluded by !**/*.sum
  • openapi/agh.json is excluded by !**/*.json
  • sdk/typescript/src/generated/contracts.ts is excluded by !**/generated/**
  • web/src/generated/agh-openapi.d.ts is excluded by !**/generated/**
📒 Files selected for processing (123)
  • go.mod
  • internal/api/contract/automation.go
  • internal/api/contract/contract_test.go
  • internal/api/contract/responses.go
  • internal/api/core/automation.go
  • internal/api/core/automation_test.go
  • internal/api/core/conversions.go
  • internal/api/core/errors.go
  • internal/api/core/handlers.go
  • internal/api/core/interfaces.go
  • internal/api/core/test_helpers_test.go
  • internal/api/httpapi/handlers.go
  • internal/api/httpapi/handlers_test.go
  • internal/api/httpapi/helpers_test.go
  • internal/api/httpapi/httpapi_integration_test.go
  • internal/api/httpapi/routes.go
  • internal/api/httpapi/server.go
  • internal/api/spec/spec.go
  • internal/api/spec/spec_test.go
  • internal/api/testutil/apitest.go
  • internal/api/udsapi/handlers_test.go
  • internal/api/udsapi/helpers_test.go
  • internal/api/udsapi/routes.go
  • internal/api/udsapi/server.go
  • internal/api/udsapi/udsapi_integration_test.go
  • internal/automation/dispatch.go
  • internal/automation/dispatch_hooks_test.go
  • internal/automation/dispatch_integration_test.go
  • internal/automation/dispatch_test.go
  • internal/automation/doc.go
  • internal/automation/extension.go
  • internal/automation/extension_test.go
  • internal/automation/manager.go
  • internal/automation/manager_test.go
  • internal/automation/model/doc.go
  • internal/automation/model/persistence.go
  • internal/automation/model/template.go
  • internal/automation/model/types.go
  • internal/automation/model/validate.go
  • internal/automation/persistence.go
  • internal/automation/schedule.go
  • internal/automation/schedule_integration_test.go
  • internal/automation/schedule_test.go
  • internal/automation/template.go
  • internal/automation/template_test.go
  • internal/automation/trigger.go
  • internal/automation/trigger_integration_test.go
  • internal/automation/trigger_test.go
  • internal/automation/types.go
  • internal/automation/validate.go
  • internal/automation/validate_test.go
  • internal/cli/automation.go
  • internal/cli/automation_test.go
  • internal/cli/cli_integration_test.go
  • internal/cli/client.go
  • internal/cli/client_test.go
  • internal/cli/helpers_test.go
  • internal/cli/root.go
  • internal/config/automation.go
  • internal/config/automation_integration_test.go
  • internal/config/automation_test.go
  • internal/config/config.go
  • internal/config/merge.go
  • internal/daemon/boot.go
  • internal/daemon/daemon.go
  • internal/daemon/daemon_integration_test.go
  • internal/daemon/daemon_test.go
  • internal/daemon/hooks_bridge.go
  • internal/extension/capability.go
  • internal/extension/capability_test.go
  • internal/extension/contract/host_api.go
  • internal/extension/contract/host_api_test.go
  • internal/extension/contract/sdk.go
  • internal/extension/host_api.go
  • internal/extension/host_api_integration_test.go
  • internal/extension/host_api_test.go
  • internal/extension/protocol/host_api.go
  • internal/extension/protocol/host_api_test.go
  • internal/hooks/dispatch.go
  • internal/hooks/events.go
  • internal/hooks/events_test.go
  • internal/hooks/introspection.go
  • internal/hooks/introspection_test.go
  • internal/hooks/matcher.go
  • internal/hooks/matcher_test.go
  • internal/hooks/payloads.go
  • internal/hooks/payloads_test.go
  • internal/observe/hooks_test.go
  • internal/store/globaldb/global_db.go
  • internal/store/globaldb/global_db_automation.go
  • internal/store/globaldb/global_db_automation_integration_test.go
  • internal/store/globaldb/global_db_automation_test.go
  • web/src/components/app-sidebar.test.tsx
  • web/src/components/app-sidebar.tsx
  • web/src/routeTree.gen.ts
  • web/src/routes/_app/-automation.integration.test.tsx
  • web/src/routes/_app/automation.tsx
  • web/src/systems/automation/adapters/automation-api.test.ts
  • web/src/systems/automation/adapters/automation-api.ts
  • web/src/systems/automation/components/automation-detail-panel.test.tsx
  • web/src/systems/automation/components/automation-detail-panel.tsx
  • web/src/systems/automation/components/automation-form-primitives.tsx
  • web/src/systems/automation/components/automation-job-form.test.tsx
  • web/src/systems/automation/components/automation-job-form.tsx
  • web/src/systems/automation/components/automation-list-panel.test.tsx
  • web/src/systems/automation/components/automation-list-panel.tsx
  • web/src/systems/automation/components/automation-run-history.tsx
  • web/src/systems/automation/components/automation-trigger-form.test.tsx
  • web/src/systems/automation/components/automation-trigger-form.tsx
  • web/src/systems/automation/hooks/use-automation-actions.test.tsx
  • web/src/systems/automation/hooks/use-automation-actions.ts
  • web/src/systems/automation/hooks/use-automation.test.tsx
  • web/src/systems/automation/hooks/use-automation.ts
  • web/src/systems/automation/index.ts
  • web/src/systems/automation/lib/automation-drafts.test.ts
  • web/src/systems/automation/lib/automation-drafts.ts
  • web/src/systems/automation/lib/automation-formatters.test.ts
  • web/src/systems/automation/lib/automation-formatters.ts
  • web/src/systems/automation/lib/query-keys.test.ts
  • web/src/systems/automation/lib/query-keys.ts
  • web/src/systems/automation/lib/query-options.test.ts
  • web/src/systems/automation/lib/query-options.ts
  • web/src/systems/automation/types.ts

Comment thread internal/api/core/automation.go
Comment thread internal/api/core/errors.go
Comment thread internal/api/udsapi/udsapi_integration_test.go
Comment thread internal/automation/dispatch.go
Comment thread internal/automation/dispatch.go Outdated
Comment thread internal/automation/manager.go Outdated
Comment thread internal/automation/manager.go Outdated
Comment thread internal/automation/model/template.go Outdated
Comment thread internal/automation/trigger.go
Comment thread internal/cli/cli_integration_test.go
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/api/contract/contract_test.go`:
- Around line 159-275: The new tests (TestAutomationJobPayloadJSONShape,
TestAutomationTriggerPayloadJSONShape, TestAutomationUpdateRequestsHasChanges)
must be refactored to use t.Run subtests with the "Should..." naming convention
and table-driven style: wrap each assertion block in a t.Run("Should ...") call
(e.g., t.Run("Should marshal next_run and scope for JobPayload") and
t.Run("Should include endpoint_slug and webhook_id for TriggerPayload")), and
convert TestAutomationUpdateRequestsHasChanges into a table-driven test where
each case contains an input (e.g., contract.UpdateJobRequest{Name: &name}) and
expected bool, looping over cases and calling t.Run("Should ...", func(t
*testing.T){ ... assert case.HasChanges() == expected }), keeping existing
helpers like marshalJSON and referencing the same types (contract.JobPayload,
contract.TriggerPayload, contract.UpdateJobRequest/UpdateTriggerRequest) and
fields to locate the code.

In `@internal/api/core/automation.go`:
- Around line 86-92: The call to h.automationNextRunByJobID (used after
persisting a job in the create/update handlers) must be treated as best-effort
so its failure doesn't turn a successful write into an error response; update
the code around the call (the block that assigns nextRunByID and currently
returns on err) to instead log the error (or use h.logger) and set nextRunByID
to nil/empty so JobPayloadFromJob/timePointerFromMap receives nil for next_run;
apply the same change for the second occurrence (the similar block around lines
161-167) to ensure manager.Status()/automationNextRunByJobID errors are
non-fatal and the handler still returns the created/updated job with
next_run=null.

In `@internal/api/core/errors.go`:
- Around line 96-128: StatusForAutomationError currently falls through to 500
for two expected domain sentinels; add explicit mappings: detect
automationpkg.ErrWebhookSecretRequired with errors.Is and return
http.StatusBadRequest, and detect automationpkg.ErrDefinitionReadOnly with
errors.Is and return http.StatusConflict. Update the switch in
StatusForAutomationError to include these two cases (using errors.Is checks)
before the default branch so user/config validation errors produce 400/409
instead of 500.

In `@internal/automation/manager.go`:
- Around line 314-316: The NewDispatcher constructor error is returned raw; wrap
it with context before returning so failures indicate the failing phase. Replace
the bare "return nil, err" after the NewDispatcher(...) call with a wrapped
error like fmt.Errorf("create dispatcher: %w", err). Apply the same pattern to
other constructor/startup error returns in this file (the block around lines
1117-1129) so functions such as NewDispatcher and the manager New/Start paths
return errors wrapped with descriptive context using fmt.Errorf("%s: %w", ...).
- Around line 1247-1254: The loop that calls m.store.DeleteJob (and the similar
trigger removal at lines ~1292-1299) only removes base rows and leaves persisted
overlays and webhook secrets behind; replace direct
store.DeleteJob/DeleteTrigger calls with the manager-level deletion routines
that perform full cleanup (e.g., call m.DeleteJob(ctx, id) and
m.DeleteTrigger(ctx, id) or the manager methods that encapsulate overlay and
secret removal) so overlays and trigger secrets are explicitly removed when
config-backed definitions disappear. Ensure the removed++ accounting stays
correct and propagate errors from the manager-level calls as before.

In `@internal/automation/model/template.go`:
- Around line 146-152: The validation currently returns nil when
templateFieldPath(args[0]) fails or yields an empty path, allowing unsupported
index targets to slip through; change the early return so it returns the same
kind of error as the subsequent check. Specifically, in the block that calls
templateFieldPath (the variables path, ok), replace the "return nil" with a
formatted error (using fmt.Errorf) indicating the unsupported index target and
that only .Data is allowed (use dottedPath(path) or args[0] to populate the %q),
so both failure-to-normalize and empty-path cases are rejected consistently
before the later path[0] check.

In `@internal/automation/trigger.go`:
- Around line 415-420: The current flow calls
e.claimWebhookDelivery(registration.Trigger.ID, request.DeliveryID) before
dispatchMatches, causing a permanent claim even if dispatch fails; change to
either (A) make the claim "in-flight" and finalize it only after dispatchMatches
returns successfully (e.g., call a finalizeClaim/confirmClaim method after
dispatch), or (B) keep the existing claim but immediately release/rollback it if
dispatchMatches returns an error (e.g., call an unclaim/release method in the
error path). Update the logic around webhookEnvelope(...) and
e.dispatchMatches(...) so the delivery ID is only permanently marked claimed
after a successful dispatch or is explicitly released on dispatch failure; use
the unique symbols e.claimWebhookDelivery, e.dispatchMatches, webhookEnvelope,
TriggerRegistration and ensure TriggerResult error paths unclaim when needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 13015e78-7de3-4866-bc59-01a890737727

📥 Commits

Reviewing files that changed from the base of the PR and between 33c6757 and f066648.

⛔ Files ignored due to path filters (26)
  • .compozy/tasks/automation/reviews-001/_meta.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_001.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_002.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_003.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_004.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_005.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_006.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_007.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_008.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_009.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_010.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_011.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_012.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_013.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_014.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_015.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_016.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_017.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_018.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_019.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_020.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_021.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_022.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_023.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_024.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-001/issue_025.md is excluded by !**/*.md
📒 Files selected for processing (23)
  • internal/api/contract/contract_test.go
  • internal/api/core/automation.go
  • internal/api/core/automation_test.go
  • internal/api/core/errors.go
  • internal/api/httpapi/httpapi_integration_test.go
  • internal/api/testutil/apitest.go
  • internal/api/udsapi/udsapi_integration_test.go
  • internal/automation/dispatch.go
  • internal/automation/dispatch_test.go
  • internal/automation/extension.go
  • internal/automation/extension_test.go
  • internal/automation/manager.go
  • internal/automation/manager_test.go
  • internal/automation/model/template.go
  • internal/automation/trigger.go
  • internal/automation/trigger_integration_test.go
  • internal/automation/trigger_test.go
  • internal/automation/validate_test.go
  • internal/cli/automation.go
  • internal/cli/automation_test.go
  • internal/cli/cli_integration_test.go
  • internal/cli/client_test.go
  • internal/config/automation.go
✅ Files skipped from review due to trivial changes (4)
  • internal/automation/extension_test.go
  • internal/api/core/automation_test.go
  • internal/automation/validate_test.go
  • internal/automation/dispatch.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • internal/api/udsapi/udsapi_integration_test.go
  • internal/automation/extension.go
  • internal/automation/trigger_integration_test.go
  • internal/api/testutil/apitest.go
  • internal/automation/dispatch_test.go

Comment thread internal/api/contract/contract_test.go
Comment thread internal/api/core/automation.go Outdated
Comment thread internal/api/core/errors.go
Comment thread internal/automation/manager.go Outdated
Comment thread internal/automation/manager.go
Comment thread internal/automation/model/template.go Outdated
Comment thread internal/automation/trigger.go Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (7)
internal/api/contract/contract_test.go (1)

267-287: Expand HasChanges() cases to cover all mutable fields.

Current cases are valid, but they only sample a subset of mutable fields. Adding one positive case per mutable field would make regressions in HasChanges() much harder to miss.

Suggested test expansion (pattern)
 		testCases := []struct {
 			name string
 			req  contract.UpdateJobRequest
 			want bool
 		}{
 			{
 				name: "Should return false for an empty job update",
 				req:  contract.UpdateJobRequest{},
 				want: false,
 			},
 			{
 				name: "Should return true when the job name is set",
 				req:  contract.UpdateJobRequest{Name: &name},
 				want: true,
 			},
+			{
+				name: "Should return true when the agent name is set",
+				req:  contract.UpdateJobRequest{AgentName: &name},
+				want: true,
+			},
+			{
+				name: "Should return true when the workspace ID is set",
+				req:  contract.UpdateJobRequest{WorkspaceID: &name},
+				want: true,
+			},
+			// ...add Prompt, Schedule, Retry, FireLimit
 			{
 				name: "Should return true when the job enabled flag is set",
 				req:  contract.UpdateJobRequest{Enabled: &disabled},
 				want: true,
 			},
 		}
 		testCases := []struct {
 			name string
 			req  contract.UpdateTriggerRequest
 			want bool
 		}{
 			{
 				name: "Should return false for an empty trigger update",
 				req:  contract.UpdateTriggerRequest{},
 				want: false,
 			},
 			{
 				name: "Should return true when the webhook secret is set",
 				req:  contract.UpdateTriggerRequest{WebhookSecret: &secret},
 				want: true,
 			},
+			{
+				name: "Should return true when event is set",
+				req:  contract.UpdateTriggerRequest{Event: &name},
+				want: true,
+			},
+			{
+				name: "Should return true when webhook ID is set",
+				req:  contract.UpdateTriggerRequest{WebhookID: &name},
+				want: true,
+			},
+			// ...add Name, AgentName, WorkspaceID, Prompt, Filter, Retry, FireLimit, EndpointSlug
 			{
 				name: "Should return true when the trigger enabled flag is set",
 				req:  contract.UpdateTriggerRequest{Enabled: &disabled},
 				want: true,
 			},
 		}
As per coding guidelines, `**/*_test.go`: "MUST test meaningful business logic, not trivial operations" and "Must Check: Focus on critical paths: workflow execution, state management, error handling".

Also applies to: 304-324

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/api/contract/contract_test.go` around lines 267 - 287, The
HasChanges() tests only cover Name and Enabled; add one positive test case per
mutable field on contract.UpdateJobRequest so HasChanges() is exercised for
every updatable property (e.g., Schedule, Metadata, RuntimeVersion,
BackoffPolicy, Resources — use the actual mutable field names present in
UpdateJobRequest) and keep the existing empty-request and other positives;
update the testCases slice in contract_test.go to include a case for each field
(referencing UpdateJobRequest and HasChanges()) that sets that single field and
expects want: true, ensuring each mutable field change is asserted.
internal/automation/manager_test.go (6)

663-664: Missing t.Parallel() declaration.

Same issue as TestManagerHandleWebhookWithSecretResolver - this test should declare t.Parallel() for consistency with other tests in the file.

As per coding guidelines: "Use t.Parallel() for independent subtests in Go tests".

Proposed fix
 func TestManagerHandleWebhookWithConfigSecretEnv(t *testing.T) {
+	t.Parallel()
+
 	h := newManagerHarness(t)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 663 - 664, The test
TestManagerHandleWebhookWithConfigSecretEnv is missing t.Parallel(); add a call
to t.Parallel() as the first statement inside the test function (similar to
TestManagerHandleWebhookWithSecretResolver) to mark it as an independent
parallelizable test; locate the function
TestManagerHandleWebhookWithConfigSecretEnv and insert t.Parallel() immediately
after the existing t := newManagerHarness(t) setup or at the top of the function
body per file convention.

840-842: Constructor test checks only != nil without verifying meaningful state.

This assertion only verifies the ID is non-empty, which is a weak test. Consider asserting on meaningful business properties like Source, Scope, or WorkspaceID that confirm correct initialization.

As per coding guidelines: "Constructor tests that only check != nil" is listed as an anti-pattern to reject.

Proposed enhancement
 	if created.ID == "" {
 		t.Fatal("manager.CreateJob() id = empty, want non-empty")
 	}
+	if got, want := created.Source, JobSourceDynamic; got != want {
+		t.Fatalf("manager.CreateJob() source = %q, want %q", got, want)
+	}
+	if got, want := created.WorkspaceID, h.workspace.ID; got != want {
+		t.Fatalf("manager.CreateJob() workspace_id = %q, want %q", got, want)
+	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 840 - 842, The test
currently only checks created.ID is non-empty after calling manager.CreateJob(),
which is too weak; extend the assertions to verify meaningful fields on the
returned job (e.g., check created.Source, created.Scope, created.WorkspaceID and
any other business-critical fields set by CreateJob or the Job constructor) to
ensure correct initialization, and assert their expected values (non-empty or
specific expected constants) alongside the existing ID check so the constructor
behavior is validated beyond nil/empty ID.

590-591: Missing t.Parallel() declaration.

This test modifies environment variables with t.Setenv() but doesn't call t.Parallel(). While t.Setenv() is safe in parallel tests (it automatically marks the test as incompatible with parallel execution), the missing t.Parallel() is inconsistent with other tests in this file.

As per coding guidelines: "Use t.Parallel() for independent subtests in Go tests".

Proposed fix
 func TestManagerHandleWebhookWithSecretResolver(t *testing.T) {
+	t.Parallel()
+
 	h := newManagerHarness(t)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 590 - 591, Add t.Parallel()
at the start of the TestManagerHandleWebhookWithSecretResolver test to match
other tests and mark it as safe for parallel execution; locate the
TestManagerHandleWebhookWithSecretResolver function (which calls
newManagerHarness(t) and uses t.Setenv()) and insert t.Parallel() immediately
after the function's first line so the test is consistently declared parallel
with the rest of the file.

1789-1823: Tests verify trivial helper behavior with minimal business value.

This test function verifies nil-safe observer calls and basic sorting — functionality that's unlikely to regress and provides limited confidence in the system. Consider removing these in favor of tests that exercise the helpers through actual business flows, or consolidate them into a single focused helper verification test.

As per coding guidelines: "Getter/setter tests without business logic" and "Tests that verify Go standard library functionality" are anti-patterns to reject.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 1789 - 1823, Remove or
consolidate the low-value TestManagerObserverNoopsAndSortHelpers test: either
delete the entire TestManagerObserverNoopsAndSortHelpers function, or replace it
with a single focused helper-verification test that briefly asserts the nil-safe
no-op observer calls (managerHookTelemetrySink.WriteHookRecord and
managerMemoryObserver.OnMemoryConsolidated) and that the sort helpers (sortJobs
and sortTriggers) produce the expected deterministic ordering; keep the minimal
assertions only and avoid duplicative checks of standard library behavior.

1128-1137: Error comparison uses string matching instead of errors.Is().

The assertContextError helper compares error messages using err.Error() != want, which is fragile and violates the coding guidelines. Consider using sentinel errors and errors.Is() for type-safe error matching, or at minimum use strings.Contains() if the exact message format might change.

As per coding guidelines: "Use errors.Is() and errors.As() for error matching — never compare error strings".

Alternative approach using strings.Contains
 	assertContextError := func(name string, err error, want string) {
 		t.Helper()
 		if err == nil {
 			t.Fatalf("%s error = nil, want %q", name, want)
 		}
-		if err.Error() != want {
+		if !strings.Contains(err.Error(), want) {
 			t.Fatalf("%s error = %q, want %q", name, err.Error(), want)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 1128 - 1137, The helper
assertContextError currently compares error text using err.Error() != want which
is fragile; update assertContextError (used alongside nilContextForTests) to
accept a target error value instead of a string and use errors.Is(err, target)
for comparison (or, if a sentinel error is not available, use
strings.Contains(err.Error(), wantSubstring)); adjust all calls to
assertContextError to pass the sentinel/target error (or substring) so tests use
errors.Is/errors.Contains rather than direct string equality.

25-127: Consider using table-driven subtests for improved test organization.

This test and others in the file use a flat structure without t.Run() subtests. While the test logic is sound, the coding guidelines require using t.Run("Should...") pattern. This would improve:

  • Test output readability (each subtest is named)
  • Ability to run specific scenarios in isolation
  • Failure localization

As per coding guidelines: "MUST use t.Run('Should...') pattern for ALL test cases".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 25 - 127, Split
TestManagerStartSyncsConfigDefinitionsAndPreservesDynamicEntries into named
t.Run subtests: wrap setup and each assertion group (e.g., "starts manager and
preserves dynamic jobs", "config job resolved and marked JobSourceConfig",
"triggers preserved and config trigger resolved") in separate t.Run blocks so
failures are localized; keep shared setup (newManagerHarness, creating
dynamicJob/dynamicTrigger, manager.Start, and cleanup) in the parent test body
and move only the related checks into their respective t.Run closures,
referencing the existing functions and methods like manager.Start, manager.Jobs,
manager.Triggers, resolveConfigJob, and resolveConfigTrigger to locate the
assertions to move.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/api/core/errors.go`:
- Around line 97-131: StatusForAutomationError currently falls through for
automationpkg.ErrWebhookEndpointInvalid and returns 500; update the function
(StatusForAutomationError) to map automationpkg.ErrWebhookEndpointInvalid to
http.StatusBadRequest (400). Add errors.Is(err,
automationpkg.ErrWebhookEndpointInvalid) into the BadRequest branch (the same
branch that handles ErrAutomationValidation and
automationpkg.ErrWebhookSecretRequired) or add a dedicated case returning
http.StatusBadRequest so malformed webhook endpoint input is treated as a client
error.

In `@internal/api/testutil/apitest.go`:
- Line 618: Change the compile-time interface assertion from a value literal to
the pointer-form pattern: replace the line setting var _ core.AutomationManager
= StubAutomationManager{} with var _ core.AutomationManager =
(*StubAutomationManager)(nil) so the interface compliance check uses a nil
pointer to StubAutomationManager instead of a value.

In `@internal/automation/model/template.go`:
- Around line 26-27: The calls that return raw errors from validateTemplateNode
(e.g., the check using validateTemplateNode(subtemplate.Root)) should wrap the
propagated error with local context before returning so callers know where
validation failed; update the return paths to use fmt.Errorf with descriptive
context (for example: "validate template root: %w") and apply the same wrapping
pattern to the other similar return(s) around the template validation checks
(referencing validateTemplateNode and subtemplate.Root).
- Line 85: The field/chain validation in validateTemplateNodeWithState is using
unscoped paths; change those checks to use scopedTemplateFieldPath (the same
helper used in validateIndexArgs) so lookups inside a {{with .Data}} are
resolved relative to the current dot (e.g., `.foo` -> `.Data.foo`). Also update
the two call sites that currently propagate validation errors directly (the
returns that do `return err`) to wrap the error with context using
fmt.Errorf("validate template: %w", err) (or equivalent) so validation failures
include caller context instead of raw errors.

In `@internal/automation/trigger.go`:
- Around line 384-390: The FireHookCompletion method should validate that ctx is
non-nil before calling hookCompletionEnvelope to prevent a nil-context from
reaching HookSessionResolver.Status; modify TriggerEngine.FireHookCompletion to
check if ctx == nil and return a clear error (e.g., fmt.Errorf("nil context") or
a package-specific error) before invoking hookCompletionEnvelope or Fire so the
early guard protects downstream calls.

---

Nitpick comments:
In `@internal/api/contract/contract_test.go`:
- Around line 267-287: The HasChanges() tests only cover Name and Enabled; add
one positive test case per mutable field on contract.UpdateJobRequest so
HasChanges() is exercised for every updatable property (e.g., Schedule,
Metadata, RuntimeVersion, BackoffPolicy, Resources — use the actual mutable
field names present in UpdateJobRequest) and keep the existing empty-request and
other positives; update the testCases slice in contract_test.go to include a
case for each field (referencing UpdateJobRequest and HasChanges()) that sets
that single field and expects want: true, ensuring each mutable field change is
asserted.

In `@internal/automation/manager_test.go`:
- Around line 663-664: The test TestManagerHandleWebhookWithConfigSecretEnv is
missing t.Parallel(); add a call to t.Parallel() as the first statement inside
the test function (similar to TestManagerHandleWebhookWithSecretResolver) to
mark it as an independent parallelizable test; locate the function
TestManagerHandleWebhookWithConfigSecretEnv and insert t.Parallel() immediately
after the existing t := newManagerHarness(t) setup or at the top of the function
body per file convention.
- Around line 840-842: The test currently only checks created.ID is non-empty
after calling manager.CreateJob(), which is too weak; extend the assertions to
verify meaningful fields on the returned job (e.g., check created.Source,
created.Scope, created.WorkspaceID and any other business-critical fields set by
CreateJob or the Job constructor) to ensure correct initialization, and assert
their expected values (non-empty or specific expected constants) alongside the
existing ID check so the constructor behavior is validated beyond nil/empty ID.
- Around line 590-591: Add t.Parallel() at the start of the
TestManagerHandleWebhookWithSecretResolver test to match other tests and mark it
as safe for parallel execution; locate the
TestManagerHandleWebhookWithSecretResolver function (which calls
newManagerHarness(t) and uses t.Setenv()) and insert t.Parallel() immediately
after the function's first line so the test is consistently declared parallel
with the rest of the file.
- Around line 1789-1823: Remove or consolidate the low-value
TestManagerObserverNoopsAndSortHelpers test: either delete the entire
TestManagerObserverNoopsAndSortHelpers function, or replace it with a single
focused helper-verification test that briefly asserts the nil-safe no-op
observer calls (managerHookTelemetrySink.WriteHookRecord and
managerMemoryObserver.OnMemoryConsolidated) and that the sort helpers (sortJobs
and sortTriggers) produce the expected deterministic ordering; keep the minimal
assertions only and avoid duplicative checks of standard library behavior.
- Around line 1128-1137: The helper assertContextError currently compares error
text using err.Error() != want which is fragile; update assertContextError (used
alongside nilContextForTests) to accept a target error value instead of a string
and use errors.Is(err, target) for comparison (or, if a sentinel error is not
available, use strings.Contains(err.Error(), wantSubstring)); adjust all calls
to assertContextError to pass the sentinel/target error (or substring) so tests
use errors.Is/errors.Contains rather than direct string equality.
- Around line 25-127: Split
TestManagerStartSyncsConfigDefinitionsAndPreservesDynamicEntries into named
t.Run subtests: wrap setup and each assertion group (e.g., "starts manager and
preserves dynamic jobs", "config job resolved and marked JobSourceConfig",
"triggers preserved and config trigger resolved") in separate t.Run blocks so
failures are localized; keep shared setup (newManagerHarness, creating
dynamicJob/dynamicTrigger, manager.Start, and cleanup) in the parent test body
and move only the related checks into their respective t.Run closures,
referencing the existing functions and methods like manager.Start, manager.Jobs,
manager.Triggers, resolveConfigJob, and resolveConfigTrigger to locate the
assertions to move.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 801b8957-6c2d-4c30-955d-210dc3b449d3

📥 Commits

Reviewing files that changed from the base of the PR and between f066648 and eb98bef.

⛔ Files ignored due to path filters (16)
  • .agents/skills/cy-idea-factory/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/cy-idea-factory/references/council.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/tmux/SKILL.md is excluded by !**/*.md, !.agents/**
  • .agents/skills/tmux/scripts/find-sessions.sh is excluded by !.agents/**
  • .agents/skills/tmux/scripts/wait-for-text.sh is excluded by !.agents/**
  • .compozy/tasks/automation/_techspec.md is excluded by !**/*.md
  • .compozy/tasks/automation/qa/review_001.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/_meta.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/issue_001.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/issue_002.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/issue_003.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/issue_004.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/issue_005.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/issue_006.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-002/issue_007.md is excluded by !**/*.md
  • skills-lock.json is excluded by !**/*.json
📒 Files selected for processing (20)
  • internal/api/contract/contract_test.go
  • internal/api/core/automation.go
  • internal/api/core/automation_test.go
  • internal/api/core/errors.go
  • internal/api/core/interfaces.go
  • internal/api/testutil/apitest.go
  • internal/automation/dispatch.go
  • internal/automation/dispatch_test.go
  • internal/automation/manager.go
  • internal/automation/manager_test.go
  • internal/automation/model/template.go
  • internal/automation/template_test.go
  • internal/automation/trigger.go
  • internal/automation/trigger_test.go
  • internal/config/automation.go
  • internal/config/automation_test.go
  • internal/session/session.go
  • internal/session/stop_cause.go
  • internal/session/stop_reason.go
  • internal/session/stop_reason_test.go
✅ Files skipped from review due to trivial changes (3)
  • internal/automation/template_test.go
  • internal/automation/dispatch.go
  • internal/automation/manager.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • internal/api/core/interfaces.go
  • internal/api/core/automation_test.go
  • internal/automation/dispatch_test.go
  • internal/api/core/automation.go

Comment thread internal/api/core/errors.go
Comment thread internal/api/testutil/apitest.go Outdated
Comment thread internal/automation/model/template.go Outdated
Comment thread internal/automation/model/template.go
Comment thread internal/automation/trigger.go
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (4)
internal/automation/manager_test.go (4)

1301-1307: Consider simplifying the error check condition.

The double-negative condition !errors.Is(err, ...) && err != nil is harder to parse. This could be inverted for clarity.

Suggested fix
 	resolvedSecret, err := resolver.SecretForTrigger(h.ctx, webhookTrigger)
-	if !errors.Is(err, ErrTriggerWebhookSecretNotFound) && err != nil {
-		t.Fatalf("storeWebhookSecretResolver.SecretForTrigger() error = %v", err)
+	if err != nil && !errors.Is(err, ErrTriggerWebhookSecretNotFound) {
+		t.Fatalf("storeWebhookSecretResolver.SecretForTrigger() unexpected error = %v", err)
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 1301 - 1307, Invert and
simplify the error check in the test: instead of the double-negative
`!errors.Is(err, ErrTriggerWebhookSecretNotFound) && err != nil`, reorder to
first check `err != nil` and then `!errors.Is(err,
ErrTriggerWebhookSecretNotFound)` (or explicitly branch: if errors.Is(err,
ErrTriggerWebhookSecretNotFound) { /* expected */ } else if err != nil {
t.Fatalf... }) when calling resolver.SecretForTrigger; update the condition
surrounding resolver.SecretForTrigger(h.ctx, webhookTrigger) and the subsequent
t.Fatalf to use this clearer logic referencing resolver.SecretForTrigger and
ErrTriggerWebhookSecretNotFound.

590-591: Missing t.Parallel() call.

This test function is missing the t.Parallel() call that's present in most other tests in this file. Since t.Setenv (line 592) is used, ensure Go 1.17+ is the minimum version, as t.Setenv combined with t.Parallel() is safe from that version onwards.

Suggested fix
 func TestManagerHandleWebhookWithSecretResolver(t *testing.T) {
+	t.Parallel()
+
 	h := newManagerHarness(t)

As per coding guidelines: "Use t.Parallel() for independent subtests in Go tests"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 590 - 591,
TestManagerHandleWebhookWithSecretResolver is missing a t.Parallel() call;
update the test by adding t.Parallel() near the start of
TestManagerHandleWebhookWithSecretResolver (before calling newManagerHarness) so
the test runs in parallel like the others—ensure this is compatible with the
existing use of t.Setenv in the test.

663-664: Missing t.Parallel() call.

Same issue as the previous webhook test—this test is missing t.Parallel().

Suggested fix
 func TestManagerHandleWebhookWithConfigSecretEnv(t *testing.T) {
+	t.Parallel()
+
 	h := newManagerHarness(t)

As per coding guidelines: "Use t.Parallel() for independent subtests in Go tests"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 663 - 664, The test
function TestManagerHandleWebhookWithConfigSecretEnv is missing t.Parallel();
add a call to t.Parallel() as the first statement inside the
TestManagerHandleWebhookWithConfigSecretEnv function (before calling
newManagerHarness or other setup) so the test runs in parallel with other
independent tests.

1140-1149: Fragile exact error string comparison.

The assertContextError helper uses exact string comparison (err.Error() != want) which is brittle—error messages may change without breaking functionality. Consider using strings.Contains to check for key substrings instead.

Suggested fix
 	assertContextError := func(name string, err error, want string) {
 		t.Helper()
 		if err == nil {
 			t.Fatalf("%s error = nil, want %q", name, want)
 		}
-		if err.Error() != want {
+		if !strings.Contains(err.Error(), want) {
 			t.Fatalf("%s error = %q, want %q", name, err.Error(), want)
 		}
 	}

As per coding guidelines: "MUST have specific error assertions (ErrorContains, ErrorAs)" and "never compare error strings"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/automation/manager_test.go` around lines 1140 - 1149, The helper
assertContextError currently compares error strings exactly which is brittle;
update assertContextError to assert that the actual error contains the expected
substring (using strings.Contains(err.Error(), want)) or, where a specific error
type is intended, use errors.Is/errors.As to match the error type instead of
string equality; update the helper (assertContextError) to call t.Fatalf when
!strings.Contains(...) (and add the strings import) or to perform
errors.Is/errors.As checks as appropriate for each call site.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/automation/manager_test.go`:
- Around line 1301-1307: Invert and simplify the error check in the test:
instead of the double-negative `!errors.Is(err, ErrTriggerWebhookSecretNotFound)
&& err != nil`, reorder to first check `err != nil` and then `!errors.Is(err,
ErrTriggerWebhookSecretNotFound)` (or explicitly branch: if errors.Is(err,
ErrTriggerWebhookSecretNotFound) { /* expected */ } else if err != nil {
t.Fatalf... }) when calling resolver.SecretForTrigger; update the condition
surrounding resolver.SecretForTrigger(h.ctx, webhookTrigger) and the subsequent
t.Fatalf to use this clearer logic referencing resolver.SecretForTrigger and
ErrTriggerWebhookSecretNotFound.
- Around line 590-591: TestManagerHandleWebhookWithSecretResolver is missing a
t.Parallel() call; update the test by adding t.Parallel() near the start of
TestManagerHandleWebhookWithSecretResolver (before calling newManagerHarness) so
the test runs in parallel like the others—ensure this is compatible with the
existing use of t.Setenv in the test.
- Around line 663-664: The test function
TestManagerHandleWebhookWithConfigSecretEnv is missing t.Parallel(); add a call
to t.Parallel() as the first statement inside the
TestManagerHandleWebhookWithConfigSecretEnv function (before calling
newManagerHarness or other setup) so the test runs in parallel with other
independent tests.
- Around line 1140-1149: The helper assertContextError currently compares error
strings exactly which is brittle; update assertContextError to assert that the
actual error contains the expected substring (using
strings.Contains(err.Error(), want)) or, where a specific error type is
intended, use errors.Is/errors.As to match the error type instead of string
equality; update the helper (assertContextError) to call t.Fatalf when
!strings.Contains(...) (and add the strings import) or to perform
errors.Is/errors.As checks as appropriate for each call site.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b03b0fb1-0dc6-4620-a218-9cc4f2b184f3

📥 Commits

Reviewing files that changed from the base of the PR and between eb98bef and 8ff829a.

⛔ Files ignored due to path filters (13)
  • .compozy/tasks/automation/reviews-003/_meta.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_001.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_002.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_003.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_004.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_005.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_006.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_007.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_008.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_009.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_010.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_011.md is excluded by !**/*.md
  • .compozy/tasks/automation/reviews-003/issue_012.md is excluded by !**/*.md
📒 Files selected for processing (9)
  • internal/api/contract/contract_test.go
  • internal/api/core/automation_test.go
  • internal/api/core/errors.go
  • internal/api/testutil/apitest.go
  • internal/automation/manager_test.go
  • internal/automation/model/template.go
  • internal/automation/template_test.go
  • internal/automation/trigger.go
  • internal/automation/trigger_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/api/contract/contract_test.go
  • internal/automation/template_test.go
  • internal/api/core/automation_test.go

@pedronauck pedronauck merged commit 9b6c7d7 into main Apr 11, 2026
1 check passed
pedronauck added a commit that referenced this pull request May 26, 2026
## Release v0.0.1

This PR prepares the release of version v0.0.1.

### Changelog

## 0.0.1 - 2026-05-26



### Other Changes

- Lessons learned



### ♻️ Refactoring

- Project structure (#7)
- Kb improvements (#12)
- Rename spaces to channels (#17)
- Add extensions gaps (#21)
- Improve tool calls ui (#22)
- Remove web app header
- Module improvements (#29)
- Memory improvements (#35)
- Storybook for web and ui (#38)
- Enable AGH network by default for new installs (#57)
- Hermes adjustments (#69)
- Badges design (#84)
- Storybook scenario and logos gallery
- Migrate typescript tests (#114)
- Internal go packages (#120)
- Ui patterns (#127)
- Improve e2e tests (#130)
- Ui redesign
- Workspace isolation across runtime surfaces (#145)
- Prod ready applies (#162)
- Tool card ui (#164)
- Alpha on logo
- Prod ready features (#167)
- Thread sheet (#202)



### 🎉 Features

- Implement config foundation packages
- Implement sqlite store package
- Add ACP client package
- Add session lifecycle manager
- Implement observe package
- Add daemon composition root
- Add uds api server
- Implement cli package
- Add http api server
- Add system design
- Add foundation types, schemas, and layout shell for web client
- Add daemon health polling and agent sidebar systems for web client
- Add session system CRUD, streaming core, and session store for web
client
- Add chat view, messages, and composer tests for web client
- Add tool cards and renderers for web client
- Add file-backed memory store core
- Scaffold memory session seams
- Add memory dream consolidation service
- Wire memory assembler into daemon
- Add memory api and cli
- New skills system (#1)
- Add workspace entity (#5)
- Add new skill capabilities (#8)
- Web ui v2 (#9)
- Improve hooks system (#10)
- Session resilience (#11)
- Add extensability (#13)
- Add automation (#16)
- Add channels (#14)
- Add network implementation (#15)
- Add network, bridges and automations web pages (#18)
- Ext registry (#20)
- Add core tasks (#19)
- Bridge adapters (#23)
- Add site (#26)
- Add ext refac and sandbox (#25)
- Settings ui (#37)
- Tasks ui (#36)
- Harness improvements (#44)
- Agent capabilities (#49)
- Redesign ui (#48)
- Unify capability (#53)
- Redesign network workspace (#59)
- Add task deletion and split session delete from stop (#58)
- Session provider selection (#60)
- Production grade adjustments (#66)
- Autonomous system (#75)
- Add agent session route (#80)
- Tools registry (#85)
- Agents soul (#88)
- Add network threads (#105)
- Orchestration improvements (#106)
- Memory v2 (#108)
- Agent categories (#113)
- Providers model (#118)
- Add canonical AGH bundled skill (#143)
- Onboarding and improvements (#198)
- Onboarding and improvements (#201)



### 🐛 Bug Fixes

- Review round
- Review rounds
- Resolve memory extensibility review batch
- Embed web into daemon
- Defaults agents
- Acp integration (#4)
- Lint errors
- Prd folder
- Remove orphan web actions and dead surfaces (#55)
- Qa testing and fixes (#73)
- New review rounds (#82)
- Security audit (#90)
- Release qa round (#95)
- Add missing tools (#141)
- New qa round (#147)
- Advanced qa round (#149)
- Homebrew tap
- Final review round (#151)
- Daemon healthy
- Reasoning models (#158)
- Lint errors (#160)
- Review round (#168)
- Release adjustments (#171)
- Stabilize release ci fixtures
- Stabilize release integration gate
- Stabilize release verify gates
- Stabilize release integration flows
- Stabilize release verify gates
- Stabilize main verify shutdown
- Ignore stale acpmock cancel
- Marketplace search focus and filtering (#193)
- Website video
- Workspace command select



### 📚 Documentation

- Update agents.md
- Update prd
- Update skills
- Update compozy tasks
- Update compozy
- Update compozy
- Add new skills
- Archive prd
- Update prds
- Update rfc
- Update prds
- Update prds
- Add automation prd
- Channels prd
- Update prd
- Update prd
- New prds
- Archive prds
- Bridges adapters prd
- Sandbox prd
- Update
- Archive prd
- Update
- Add new prd
- New design
- Update prd
- Archive prds
- Update prds
- Tasks-ui prd tasks
- Update prd
- Update design docs
- Agent capabilities prd
- Improve site docs
- Remove old design references
- Udpate
- Autonomous prd
- Update skills
- Blog design
- Agent sould prd
- Final qa plan
- Update
- Remove codex ledgers from gitignore
- Remove not needed files
- Udpate ledger
- Update cy-codex-loop skill
- Orchestration improves prd
- Update prds
- Orch improvs prd
- Memv2 prd
- Providers model prd
- Update refacs prd
- New design proposal
- Update rules
- Update skills
- New blog posts (#173)
- Format docs
- Remove old design files
- Remove old
- Skeeper update



### 📦 Build System

- Initial structure
- Commitlint
- Frontend base structure
- Update vscode settings
- Add subagents
- Coderabbit
- Prd and tooling
- Bun lock
- Lint tooling
- Copy.md and tooling adjusts
- Add repoclone rc
- Upgrade skeeper to v0.2.0
- Update go.mod
- Adopt task artifacts into skeeper
- Sync codex plans with skeeper
- Skeeper lock
- Skeeper lock
- New skills
- Skeeper lock
- Skeeper lock
- Skeeper lock
- Update deps and go
- Regenerate daytona sidecar assets for go 1.26.3
- Fix cliff
- Ignore docs on fmt
- Build web assets before goreleaser
- Extend release dry-run timeout



### 🔧 CI/CD

- Lint errors
- Fint release pr
- Fix goreleaser



### 🧪 Testing

- Add e2e tests (#27)
- Qa rounds (#78)
- Improve test suite (#138)
- Harden daemon-served restart reloads
- Harden daemon-served readiness waits
- Stabilize dashboard focus assertion
- Stabilize release integration gates
- Stabilize release e2e markers
- Stabilize release e2e flows

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This was referenced May 26, 2026
pedronauck added a commit that referenced this pull request May 26, 2026
## Release v0.0.1

This PR prepares the release of version v0.0.1.

### Changelog

## 0.0.1 - 2026-05-26



### Other Changes

- Lessons learned



### ♻️ Refactoring

- Project structure (#7)
- Kb improvements (#12)
- Rename spaces to channels (#17)
- Add extensions gaps (#21)
- Improve tool calls ui (#22)
- Remove web app header
- Module improvements (#29)
- Memory improvements (#35)
- Storybook for web and ui (#38)
- Enable AGH network by default for new installs (#57)
- Hermes adjustments (#69)
- Badges design (#84)
- Storybook scenario and logos gallery
- Migrate typescript tests (#114)
- Internal go packages (#120)
- Ui patterns (#127)
- Improve e2e tests (#130)
- Ui redesign
- Workspace isolation across runtime surfaces (#145)
- Prod ready applies (#162)
- Tool card ui (#164)
- Alpha on logo
- Prod ready features (#167)
- Thread sheet (#202)



### 🎉 Features

- Implement config foundation packages
- Implement sqlite store package
- Add ACP client package
- Add session lifecycle manager
- Implement observe package
- Add daemon composition root
- Add uds api server
- Implement cli package
- Add http api server
- Add system design
- Add foundation types, schemas, and layout shell for web client
- Add daemon health polling and agent sidebar systems for web client
- Add session system CRUD, streaming core, and session store for web
client
- Add chat view, messages, and composer tests for web client
- Add tool cards and renderers for web client
- Add file-backed memory store core
- Scaffold memory session seams
- Add memory dream consolidation service
- Wire memory assembler into daemon
- Add memory api and cli
- New skills system (#1)
- Add workspace entity (#5)
- Add new skill capabilities (#8)
- Web ui v2 (#9)
- Improve hooks system (#10)
- Session resilience (#11)
- Add extensability (#13)
- Add automation (#16)
- Add channels (#14)
- Add network implementation (#15)
- Add network, bridges and automations web pages (#18)
- Ext registry (#20)
- Add core tasks (#19)
- Bridge adapters (#23)
- Add site (#26)
- Add ext refac and sandbox (#25)
- Settings ui (#37)
- Tasks ui (#36)
- Harness improvements (#44)
- Agent capabilities (#49)
- Redesign ui (#48)
- Unify capability (#53)
- Redesign network workspace (#59)
- Add task deletion and split session delete from stop (#58)
- Session provider selection (#60)
- Production grade adjustments (#66)
- Autonomous system (#75)
- Add agent session route (#80)
- Tools registry (#85)
- Agents soul (#88)
- Add network threads (#105)
- Orchestration improvements (#106)
- Memory v2 (#108)
- Agent categories (#113)
- Providers model (#118)
- Add canonical AGH bundled skill (#143)
- Onboarding and improvements (#198)
- Onboarding and improvements (#201)



### 🐛 Bug Fixes

- Review round
- Review rounds
- Resolve memory extensibility review batch
- Embed web into daemon
- Defaults agents
- Acp integration (#4)
- Lint errors
- Prd folder
- Remove orphan web actions and dead surfaces (#55)
- Qa testing and fixes (#73)
- New review rounds (#82)
- Security audit (#90)
- Release qa round (#95)
- Add missing tools (#141)
- New qa round (#147)
- Advanced qa round (#149)
- Homebrew tap
- Final review round (#151)
- Daemon healthy
- Reasoning models (#158)
- Lint errors (#160)
- Review round (#168)
- Release adjustments (#171)
- Stabilize release ci fixtures
- Stabilize release integration gate
- Stabilize release verify gates
- Stabilize release integration flows
- Stabilize release verify gates
- Stabilize main verify shutdown
- Ignore stale acpmock cancel
- Marketplace search focus and filtering (#193)
- Website video
- Workspace command select



### 📚 Documentation

- Update agents.md
- Update prd
- Update skills
- Update compozy tasks
- Update compozy
- Update compozy
- Add new skills
- Archive prd
- Update prds
- Update rfc
- Update prds
- Update prds
- Add automation prd
- Channels prd
- Update prd
- Update prd
- New prds
- Archive prds
- Bridges adapters prd
- Sandbox prd
- Update
- Archive prd
- Update
- Add new prd
- New design
- Update prd
- Archive prds
- Update prds
- Tasks-ui prd tasks
- Update prd
- Update design docs
- Agent capabilities prd
- Improve site docs
- Remove old design references
- Udpate
- Autonomous prd
- Update skills
- Blog design
- Agent sould prd
- Final qa plan
- Update
- Remove codex ledgers from gitignore
- Remove not needed files
- Udpate ledger
- Update cy-codex-loop skill
- Orchestration improves prd
- Update prds
- Orch improvs prd
- Memv2 prd
- Providers model prd
- Update refacs prd
- New design proposal
- Update rules
- Update skills
- New blog posts (#173)
- Format docs
- Remove old design files
- Remove old
- Skeeper update



### 📦 Build System

- Initial structure
- Commitlint
- Frontend base structure
- Update vscode settings
- Add subagents
- Coderabbit
- Prd and tooling
- Bun lock
- Lint tooling
- Copy.md and tooling adjusts
- Add repoclone rc
- Upgrade skeeper to v0.2.0
- Update go.mod
- Adopt task artifacts into skeeper
- Sync codex plans with skeeper
- Skeeper lock
- Skeeper lock
- New skills
- Skeeper lock
- Skeeper lock
- Skeeper lock
- Update deps and go
- Regenerate daytona sidecar assets for go 1.26.3
- Fix cliff
- Ignore docs on fmt
- Build web assets before goreleaser
- Extend release dry-run timeout



### 🔧 CI/CD

- Lint errors
- Fint release pr
- Fix goreleaser
- Fix release



### 🧪 Testing

- Add e2e tests (#27)
- Qa rounds (#78)
- Improve test suite (#138)
- Harden daemon-served restart reloads
- Harden daemon-served readiness waits
- Stabilize dashboard focus assertion
- Stabilize release integration gates
- Stabilize release e2e markers
- Stabilize release e2e flows

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
pedronauck added a commit that referenced this pull request May 26, 2026
## Release v0.0.2

This PR prepares the release of version v0.0.2.

### Changelog

## 0.0.2 - 2026-05-26



### Other Changes

- Lessons learned



### ♻️ Refactoring

- Project structure (#7)
- Kb improvements (#12)
- Rename spaces to channels (#17)
- Add extensions gaps (#21)
- Improve tool calls ui (#22)
- Remove web app header
- Module improvements (#29)
- Memory improvements (#35)
- Storybook for web and ui (#38)
- Enable AGH network by default for new installs (#57)
- Hermes adjustments (#69)
- Badges design (#84)
- Storybook scenario and logos gallery
- Migrate typescript tests (#114)
- Internal go packages (#120)
- Ui patterns (#127)
- Improve e2e tests (#130)
- Ui redesign
- Workspace isolation across runtime surfaces (#145)
- Prod ready applies (#162)
- Tool card ui (#164)
- Alpha on logo
- Prod ready features (#167)
- Thread sheet (#202)



### 🎉 Features

- Implement config foundation packages
- Implement sqlite store package
- Add ACP client package
- Add session lifecycle manager
- Implement observe package
- Add daemon composition root
- Add uds api server
- Implement cli package
- Add http api server
- Add system design
- Add foundation types, schemas, and layout shell for web client
- Add daemon health polling and agent sidebar systems for web client
- Add session system CRUD, streaming core, and session store for web
client
- Add chat view, messages, and composer tests for web client
- Add tool cards and renderers for web client
- Add file-backed memory store core
- Scaffold memory session seams
- Add memory dream consolidation service
- Wire memory assembler into daemon
- Add memory api and cli
- New skills system (#1)
- Add workspace entity (#5)
- Add new skill capabilities (#8)
- Web ui v2 (#9)
- Improve hooks system (#10)
- Session resilience (#11)
- Add extensability (#13)
- Add automation (#16)
- Add channels (#14)
- Add network implementation (#15)
- Add network, bridges and automations web pages (#18)
- Ext registry (#20)
- Add core tasks (#19)
- Bridge adapters (#23)
- Add site (#26)
- Add ext refac and sandbox (#25)
- Settings ui (#37)
- Tasks ui (#36)
- Harness improvements (#44)
- Agent capabilities (#49)
- Redesign ui (#48)
- Unify capability (#53)
- Redesign network workspace (#59)
- Add task deletion and split session delete from stop (#58)
- Session provider selection (#60)
- Production grade adjustments (#66)
- Autonomous system (#75)
- Add agent session route (#80)
- Tools registry (#85)
- Agents soul (#88)
- Add network threads (#105)
- Orchestration improvements (#106)
- Memory v2 (#108)
- Agent categories (#113)
- Providers model (#118)
- Add canonical AGH bundled skill (#143)
- Onboarding and improvements (#198)
- Onboarding and improvements (#201)



### 🐛 Bug Fixes

- Review round
- Review rounds
- Resolve memory extensibility review batch
- Embed web into daemon
- Defaults agents
- Acp integration (#4)
- Lint errors
- Prd folder
- Remove orphan web actions and dead surfaces (#55)
- Qa testing and fixes (#73)
- New review rounds (#82)
- Security audit (#90)
- Release qa round (#95)
- Add missing tools (#141)
- New qa round (#147)
- Advanced qa round (#149)
- Homebrew tap
- Final review round (#151)
- Daemon healthy
- Reasoning models (#158)
- Lint errors (#160)
- Review round (#168)
- Release adjustments (#171)
- Stabilize release ci fixtures
- Stabilize release integration gate
- Stabilize release verify gates
- Stabilize release integration flows
- Stabilize release verify gates
- Stabilize main verify shutdown
- Ignore stale acpmock cancel
- Marketplace search focus and filtering (#193)
- Website video
- Workspace command select



### 📚 Documentation

- Update agents.md
- Update prd
- Update skills
- Update compozy tasks
- Update compozy
- Update compozy
- Add new skills
- Archive prd
- Update prds
- Update rfc
- Update prds
- Update prds
- Add automation prd
- Channels prd
- Update prd
- Update prd
- New prds
- Archive prds
- Bridges adapters prd
- Sandbox prd
- Update
- Archive prd
- Update
- Add new prd
- New design
- Update prd
- Archive prds
- Update prds
- Tasks-ui prd tasks
- Update prd
- Update design docs
- Agent capabilities prd
- Improve site docs
- Remove old design references
- Udpate
- Autonomous prd
- Update skills
- Blog design
- Agent sould prd
- Final qa plan
- Update
- Remove codex ledgers from gitignore
- Remove not needed files
- Udpate ledger
- Update cy-codex-loop skill
- Orchestration improves prd
- Update prds
- Orch improvs prd
- Memv2 prd
- Providers model prd
- Update refacs prd
- New design proposal
- Update rules
- Update skills
- New blog posts (#173)
- Format docs
- Remove old design files
- Remove old
- Skeeper update



### 📦 Build System

- Initial structure
- Commitlint
- Frontend base structure
- Update vscode settings
- Add subagents
- Coderabbit
- Prd and tooling
- Bun lock
- Lint tooling
- Copy.md and tooling adjusts
- Add repoclone rc
- Upgrade skeeper to v0.2.0
- Update go.mod
- Adopt task artifacts into skeeper
- Sync codex plans with skeeper
- Skeeper lock
- Skeeper lock
- New skills
- Skeeper lock
- Skeeper lock
- Skeeper lock
- Update deps and go
- Regenerate daytona sidecar assets for go 1.26.3
- Fix cliff
- Ignore docs on fmt
- Build web assets before goreleaser
- Extend release dry-run timeout



### 🔧 CI/CD

- Lint errors
- Fint release pr
- Fix goreleaser
- Fix release
- Fix release process



### 🧪 Testing

- Add e2e tests (#27)
- Qa rounds (#78)
- Improve test suite (#138)
- Harden daemon-served restart reloads
- Harden daemon-served readiness waits
- Stabilize dashboard focus assertion
- Stabilize release integration gates
- Stabilize release e2e markers
- Stabilize release e2e flows
- Improve suite speed

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
pedronauck added a commit that referenced this pull request May 27, 2026
## Release v0.0.2

This PR prepares the release of version v0.0.2.

### Changelog

## 0.0.2 - 2026-05-26



### Other Changes

- Lessons learned



### ♻️ Refactoring

- Project structure (#7)
- Kb improvements (#12)
- Rename spaces to channels (#17)
- Add extensions gaps (#21)
- Improve tool calls ui (#22)
- Remove web app header
- Module improvements (#29)
- Memory improvements (#35)
- Storybook for web and ui (#38)
- Enable AGH network by default for new installs (#57)
- Hermes adjustments (#69)
- Badges design (#84)
- Storybook scenario and logos gallery
- Migrate typescript tests (#114)
- Internal go packages (#120)
- Ui patterns (#127)
- Improve e2e tests (#130)
- Ui redesign
- Workspace isolation across runtime surfaces (#145)
- Prod ready applies (#162)
- Tool card ui (#164)
- Alpha on logo
- Prod ready features (#167)
- Thread sheet (#202)



### 🎉 Features

- Implement config foundation packages
- Implement sqlite store package
- Add ACP client package
- Add session lifecycle manager
- Implement observe package
- Add daemon composition root
- Add uds api server
- Implement cli package
- Add http api server
- Add system design
- Add foundation types, schemas, and layout shell for web client
- Add daemon health polling and agent sidebar systems for web client
- Add session system CRUD, streaming core, and session store for web
client
- Add chat view, messages, and composer tests for web client
- Add tool cards and renderers for web client
- Add file-backed memory store core
- Scaffold memory session seams
- Add memory dream consolidation service
- Wire memory assembler into daemon
- Add memory api and cli
- New skills system (#1)
- Add workspace entity (#5)
- Add new skill capabilities (#8)
- Web ui v2 (#9)
- Improve hooks system (#10)
- Session resilience (#11)
- Add extensability (#13)
- Add automation (#16)
- Add channels (#14)
- Add network implementation (#15)
- Add network, bridges and automations web pages (#18)
- Ext registry (#20)
- Add core tasks (#19)
- Bridge adapters (#23)
- Add site (#26)
- Add ext refac and sandbox (#25)
- Settings ui (#37)
- Tasks ui (#36)
- Harness improvements (#44)
- Agent capabilities (#49)
- Redesign ui (#48)
- Unify capability (#53)
- Redesign network workspace (#59)
- Add task deletion and split session delete from stop (#58)
- Session provider selection (#60)
- Production grade adjustments (#66)
- Autonomous system (#75)
- Add agent session route (#80)
- Tools registry (#85)
- Agents soul (#88)
- Add network threads (#105)
- Orchestration improvements (#106)
- Memory v2 (#108)
- Agent categories (#113)
- Providers model (#118)
- Add canonical AGH bundled skill (#143)
- Onboarding and improvements (#198)
- Onboarding and improvements (#201)



### 🐛 Bug Fixes

- Review round
- Review rounds
- Resolve memory extensibility review batch
- Embed web into daemon
- Defaults agents
- Acp integration (#4)
- Lint errors
- Prd folder
- Remove orphan web actions and dead surfaces (#55)
- Qa testing and fixes (#73)
- New review rounds (#82)
- Security audit (#90)
- Release qa round (#95)
- Add missing tools (#141)
- New qa round (#147)
- Advanced qa round (#149)
- Homebrew tap
- Final review round (#151)
- Daemon healthy
- Reasoning models (#158)
- Lint errors (#160)
- Review round (#168)
- Release adjustments (#171)
- Stabilize release ci fixtures
- Stabilize release integration gate
- Stabilize release verify gates
- Stabilize release integration flows
- Stabilize release verify gates
- Stabilize main verify shutdown
- Ignore stale acpmock cancel
- Marketplace search focus and filtering (#193)
- Website video
- Workspace command select



### 📚 Documentation

- Update agents.md
- Update prd
- Update skills
- Update compozy tasks
- Update compozy
- Update compozy
- Add new skills
- Archive prd
- Update prds
- Update rfc
- Update prds
- Update prds
- Add automation prd
- Channels prd
- Update prd
- Update prd
- New prds
- Archive prds
- Bridges adapters prd
- Sandbox prd
- Update
- Archive prd
- Update
- Add new prd
- New design
- Update prd
- Archive prds
- Update prds
- Tasks-ui prd tasks
- Update prd
- Update design docs
- Agent capabilities prd
- Improve site docs
- Remove old design references
- Udpate
- Autonomous prd
- Update skills
- Blog design
- Agent sould prd
- Final qa plan
- Update
- Remove codex ledgers from gitignore
- Remove not needed files
- Udpate ledger
- Update cy-codex-loop skill
- Orchestration improves prd
- Update prds
- Orch improvs prd
- Memv2 prd
- Providers model prd
- Update refacs prd
- New design proposal
- Update rules
- Update skills
- New blog posts (#173)
- Format docs
- Remove old design files
- Remove old
- Skeeper update



### 📦 Build System

- Initial structure
- Commitlint
- Frontend base structure
- Update vscode settings
- Add subagents
- Coderabbit
- Prd and tooling
- Bun lock
- Lint tooling
- Copy.md and tooling adjusts
- Add repoclone rc
- Upgrade skeeper to v0.2.0
- Update go.mod
- Adopt task artifacts into skeeper
- Sync codex plans with skeeper
- Skeeper lock
- Skeeper lock
- New skills
- Skeeper lock
- Skeeper lock
- Skeeper lock
- Update deps and go
- Regenerate daytona sidecar assets for go 1.26.3
- Fix cliff
- Ignore docs on fmt
- Build web assets before goreleaser
- Extend release dry-run timeout



### 🔧 CI/CD

- Lint errors
- Fint release pr
- Fix goreleaser
- Fix release
- Fix release process
- Fix release sync
- Decouple release dry-run npm auth
- Persist web assets git auth



### 🧪 Testing

- Add e2e tests (#27)
- Qa rounds (#78)
- Improve test suite (#138)
- Harden daemon-served restart reloads
- Harden daemon-served readiness waits
- Stabilize dashboard focus assertion
- Stabilize release integration gates
- Stabilize release e2e markers
- Stabilize release e2e flows
- Improve suite speed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
* Updated web assets dependency to a newer version for improved
stability and performance.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/compozy/agh/pull/211?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
pedronauck added a commit that referenced this pull request May 27, 2026
## Release v0.0.2

This PR prepares the release of version v0.0.2.

### Changelog

## 0.0.2 - 2026-05-27



### Other Changes

- Lessons learned



### ♻️ Refactoring

- Project structure (#7)
- Kb improvements (#12)
- Rename spaces to channels (#17)
- Add extensions gaps (#21)
- Improve tool calls ui (#22)
- Remove web app header
- Module improvements (#29)
- Memory improvements (#35)
- Storybook for web and ui (#38)
- Enable AGH network by default for new installs (#57)
- Hermes adjustments (#69)
- Badges design (#84)
- Storybook scenario and logos gallery
- Migrate typescript tests (#114)
- Internal go packages (#120)
- Ui patterns (#127)
- Improve e2e tests (#130)
- Ui redesign
- Workspace isolation across runtime surfaces (#145)
- Prod ready applies (#162)
- Tool card ui (#164)
- Alpha on logo
- Prod ready features (#167)
- Thread sheet (#202)



### 🎉 Features

- Implement config foundation packages
- Implement sqlite store package
- Add ACP client package
- Add session lifecycle manager
- Implement observe package
- Add daemon composition root
- Add uds api server
- Implement cli package
- Add http api server
- Add system design
- Add foundation types, schemas, and layout shell for web client
- Add daemon health polling and agent sidebar systems for web client
- Add session system CRUD, streaming core, and session store for web
client
- Add chat view, messages, and composer tests for web client
- Add tool cards and renderers for web client
- Add file-backed memory store core
- Scaffold memory session seams
- Add memory dream consolidation service
- Wire memory assembler into daemon
- Add memory api and cli
- New skills system (#1)
- Add workspace entity (#5)
- Add new skill capabilities (#8)
- Web ui v2 (#9)
- Improve hooks system (#10)
- Session resilience (#11)
- Add extensability (#13)
- Add automation (#16)
- Add channels (#14)
- Add network implementation (#15)
- Add network, bridges and automations web pages (#18)
- Ext registry (#20)
- Add core tasks (#19)
- Bridge adapters (#23)
- Add site (#26)
- Add ext refac and sandbox (#25)
- Settings ui (#37)
- Tasks ui (#36)
- Harness improvements (#44)
- Agent capabilities (#49)
- Redesign ui (#48)
- Unify capability (#53)
- Redesign network workspace (#59)
- Add task deletion and split session delete from stop (#58)
- Session provider selection (#60)
- Production grade adjustments (#66)
- Autonomous system (#75)
- Add agent session route (#80)
- Tools registry (#85)
- Agents soul (#88)
- Add network threads (#105)
- Orchestration improvements (#106)
- Memory v2 (#108)
- Agent categories (#113)
- Providers model (#118)
- Add canonical AGH bundled skill (#143)
- Onboarding and improvements (#198)
- Onboarding and improvements (#201)



### 🐛 Bug Fixes

- Review round
- Review rounds
- Resolve memory extensibility review batch
- Embed web into daemon
- Defaults agents
- Acp integration (#4)
- Lint errors
- Prd folder
- Remove orphan web actions and dead surfaces (#55)
- Qa testing and fixes (#73)
- New review rounds (#82)
- Security audit (#90)
- Release qa round (#95)
- Add missing tools (#141)
- New qa round (#147)
- Advanced qa round (#149)
- Homebrew tap
- Final review round (#151)
- Daemon healthy
- Reasoning models (#158)
- Lint errors (#160)
- Review round (#168)
- Release adjustments (#171)
- Stabilize release ci fixtures
- Stabilize release integration gate
- Stabilize release verify gates
- Stabilize release integration flows
- Stabilize release verify gates
- Stabilize main verify shutdown
- Ignore stale acpmock cancel
- Marketplace search focus and filtering (#193)
- Website video
- Workspace command select



### 📚 Documentation

- Update agents.md
- Update prd
- Update skills
- Update compozy tasks
- Update compozy
- Update compozy
- Add new skills
- Archive prd
- Update prds
- Update rfc
- Update prds
- Update prds
- Add automation prd
- Channels prd
- Update prd
- Update prd
- New prds
- Archive prds
- Bridges adapters prd
- Sandbox prd
- Update
- Archive prd
- Update
- Add new prd
- New design
- Update prd
- Archive prds
- Update prds
- Tasks-ui prd tasks
- Update prd
- Update design docs
- Agent capabilities prd
- Improve site docs
- Remove old design references
- Udpate
- Autonomous prd
- Update skills
- Blog design
- Agent sould prd
- Final qa plan
- Update
- Remove codex ledgers from gitignore
- Remove not needed files
- Udpate ledger
- Update cy-codex-loop skill
- Orchestration improves prd
- Update prds
- Orch improvs prd
- Memv2 prd
- Providers model prd
- Update refacs prd
- New design proposal
- Update rules
- Update skills
- New blog posts (#173)
- Format docs
- Remove old design files
- Remove old
- Skeeper update



### 📦 Build System

- Initial structure
- Commitlint
- Frontend base structure
- Update vscode settings
- Add subagents
- Coderabbit
- Prd and tooling
- Bun lock
- Lint tooling
- Copy.md and tooling adjusts
- Add repoclone rc
- Upgrade skeeper to v0.2.0
- Update go.mod
- Adopt task artifacts into skeeper
- Sync codex plans with skeeper
- Skeeper lock
- Skeeper lock
- New skills
- Skeeper lock
- Skeeper lock
- Skeeper lock
- Update deps and go
- Regenerate daytona sidecar assets for go 1.26.3
- Fix cliff
- Ignore docs on fmt
- Build web assets before goreleaser
- Extend release dry-run timeout
- Fix release dry-run token contract



### 🔧 CI/CD

- Lint errors
- Fint release pr
- Fix goreleaser
- Fix release
- Fix release process
- Fix release sync
- Decouple release dry-run npm auth
- Persist web assets git auth
- Require npm auth before release merge



### 🧪 Testing

- Add e2e tests (#27)
- Qa rounds (#78)
- Improve test suite (#138)
- Harden daemon-served restart reloads
- Harden daemon-served readiness waits
- Stabilize dashboard focus assertion
- Stabilize release integration gates
- Stabilize release e2e markers
- Stabilize release e2e flows
- Improve suite speed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Chores**
  * Updated dependencies to latest versions.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/compozy/agh/pull/214?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant