1b58bc325e
This branch's uncommitted WIP, committed together (entangled at file level). Distinct pieces of work: Freestyle QA fixes (this session): - FileEditTool: pre-validate replace anchor in validateRequest — reject a missing/ambiguous target BEFORE the approval gate, mirroring read/write's file-not-found / read-before-write pre-checks. Shared not-found/ambiguous messages between validate and execute so they can't drift. - PlanGrounder: add `scanned` flag; when no RepoMapComputedEvent was recorded, repoMapPaths is "unknown" not "empty workspace" — skip scope grounding (which proves a path ABSENT) so real paths (apps/server/**) aren't falsely rejected. Build-manifest check still runs. - FreestyleDriver: wire scanned=(repoMap!=null); on plan rejection emit a session-terminal WorkflowFailedEvent so a rejected run reads FAILED, not the COMPLETED-lie (last verdict was the planning-phase WorkflowCompleted). - ServerModule: resolve project-memory workspace root from the session's bound workspace (sessionWorkspaceRoot) instead of boot-static pm.repoRoot(), fixing the workspace-binding divergence (correx vs empty scratch dir). Retire tracked in Vikunja #266. - LaunchRegistrationRaceTest: join registered jobs before asserting launchCount — computeIfAbsent returns the Job immediately but the fire-and-forget launch body lagged awaitAll (the 49-vs-50 flake). ACR concept-compiler experiment (pre-existing WIP on this branch): - ExecutionPlanCompiler/Model/PlanLinter, #264 needs-seam (sessionArtifacts), LSP diagnostics subsystem (LspDiagnosticEvents/Runner/Lsp4j), BootWorkspace, config surface, workflow prompts/schemas, orchestrator advance-don't-rerun. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
47 lines
3.3 KiB
Markdown
47 lines
3.3 KiB
Markdown
# core/events — AGENTS.md
|
|
|
|
## Purpose
|
|
|
|
Foundational event-sourcing infrastructure: all `EventPayload` definitions for every domain, the serialization registry, the `EventStore` interface, the `EventReplayer` contract, and shared identity/vocabulary types used across the entire `core/` layer.
|
|
|
|
## Ownership
|
|
|
|
CORREX kernel team. This is the most cross-cutting module in the codebase — changes here can break every other module. Coordinate before adding or renaming event types.
|
|
|
|
## Local Contracts
|
|
|
|
- `EventPayload` — sealed interface that every domain event implements.
|
|
- `StoredEvent` / `EventEnvelope` / `EventMetadata` — envelope types wrapping payloads for storage and replay.
|
|
- `EventStore` — interface for appending and querying events. Implementations in `infrastructure/`.
|
|
- `EventReplayer<S>` / `DefaultEventReplayer<S>` — replays a filtered event stream through a `Projection<S>` to rebuild state.
|
|
- `Projection<S>` — interface: `initial(): S` + `apply(state, event): S`.
|
|
- `StateBuilder` / `DefaultStateBuilder` — convenience builder over `EventReplayer`.
|
|
- `Serialization.kt` — the `eventModule` polymorphic block. **Every new `EventPayload` subclass must be registered here.** Missing registration = silent deserialization failure.
|
|
- `JsonEventSerializer` / `EventSerializer` — serialize/deserialize `StoredEvent` to JSON.
|
|
- `EventDispatcher` — broadcasts events to in-process listeners.
|
|
- Domain event files: `ApprovalEvents`, `ArtifactEvents`, `ContextEvents`, `InferenceEvents`, `OrchestrationEvents`, `RouterEvents`, `SessionEvents`, `TaskEvents`, `ToolEvents`, `IntentEvents`, `RiskAssessedEvent`, `JournalCompactedEvent`, and many more — all payload definitions live here.
|
|
- `LspDiagnosticsCompletedEvent` records pulled language-server diagnostics or a graceful skip reason; replay consumes this observation and never contacts the server.
|
|
- Shared vocabulary: `IdentityTypes` (SessionId, TaskId, etc.), `Tier`, `TokenUsage`, `ToolReceipt`, `ToolRequest`, `RiskLevel`, `RetryPolicy`, `GrantScope`, `GrantLedger`.
|
|
|
|
## Work Guidance
|
|
|
|
- **SILENT FAILURE TRAP**: After adding any `EventPayload` subclass, immediately add it to `Serialization.kt` `eventModule` block. Run `./gradlew check` to verify. Tests may pass without it but runtime replay will fail silently.
|
|
- `AnyMapSerializer` — custom serializer for `Map<String, Any?>`; use it for dynamic payloads, don't roll another.
|
|
- Event classes are `@Serializable data class` with no mutable state. No methods beyond data accessors.
|
|
- `RunBranchPushedEvent` records an optional server Git transport push only after it succeeds; its branch/base/head SHAs are observations, not values replay recalculates.
|
|
- `RepoMapEntry.descriptor` is a bounded source-purpose observation recorded with the repo map and used when constructing semantic L3 embeddings.
|
|
- Do not add domain logic to events. They are records, not actors.
|
|
- `EgressAllowlistProjection` — special projection kept in this module because it is used by both `core:toolintent` and `core:events` consumers; it is a shared cross-cutting projection.
|
|
|
|
## Verification
|
|
|
|
```bash
|
|
./gradlew :core:events:test --rerun-tasks
|
|
```
|
|
|
|
Tests in `testing/contracts/` (EventsTest, EventStoreContractTest) and `testing/replay/` (serialization round-trips, replay integration).
|
|
|
|
## Child DOX Index
|
|
|
|
No child AGENTS.md (leaf module).
|