Files
correx/docs/modules/core/core-artifacts.adoc
T
kami 9734eec63c docs: add module documentation in AsciiDoc with PlantUML diagrams
Generated by per-group subagents covering all 52 modules across:
core (18), infrastructure (10), apps (5), interfaces (3),
plugins (7), testing (9)

Documentation format:
- AsciiDoc (.adoc) files in docs/modules/<group>/
- PlantUML (.puml) files in docs/diagrams/
- .adoc files reference diagrams via include:: directives

Each doc covers: purpose, responsibilities, non-responsibilities,
key types, event flow, integration points, invariants, PlantUML
diagram, known issues, and open questions.
2026-05-26 16:59:21 +04:00

152 lines
7.1 KiB
Plaintext

= core-artifacts
== purpose
Defines the artifact model — a structured output produced during a workflow stage. Manages artifact lifecycle phases (created → validating → validated/rejected → superseded/archived) as event-sourced state, provides a kind system for typed artifact payloads (file_written, process_result), and supports materialization of file artifacts to disk.
== responsibilities
* Defining the `Artifact` sealed interface and its common fields (id, session, stage, lifecycle phase, lineage, metadata)
* Managing artifact lifecycle phase transitions with state machine validation
* Tracking artifact lineage (parent IDs, relationships, validation report IDs)
* Defining and registering `ArtifactKind` implementations for typed payloads
* Providing JSON schema derivation for each artifact kind
* Materializing file artifacts to disk via `MaterializingArtifactWriter`
* Providing a repository interface for querying artifact state by session, stage, or ID
== non-responsibilities
* Does not manage binary blob storage — that is delegated to `:core:artifacts-store` via `ArtifactStore`
* Does not validate artifact payloads — validation is handled by `:core:validation` via `ArtifactPayloadValidator`
* Does not produce artifacts — they are created by the orchestrator or infrastructure adapters
* Does not manage the full artifact content — only metadata and lifecycle state are projected
== key types
=== Artifact
* **kind**: sealed interface
* **purpose**: Base type for all artifacts. Declares common fields.
* **fields**: `id`, `sessionId`, `stageId`, `schemaVersion`, `createdAt`, `lifecyclePhase`, `lineage`, `metadata`
=== ArtifactState
* **kind**: data class
* **purpose**: Event-sourced projection of a single artifact's lifecycle state.
* **fields**: `phase` (ArtifactLifecyclePhase), `lineage` (ArtifactLineage)
=== ArtifactReducer / DefaultArtifactReducer
* **kind**: interface / class
* **purpose**: Transforms `ArtifactState` given a stored event. Validates lifecycle phase transitions and returns `Result.Failure` for illegal transitions. Handles `ArtifactCreatedEvent`, `ArtifactValidatingEvent`, `ArtifactValidatedEvent`, `ArtifactRejectedEvent`, `ArtifactSupersededEvent`, `ArtifactArchivedEvent`, `ArtifactRelationshipAddedEvent`.
=== ArtifactProjector
* **kind**: class
* **purpose**: Wraps `ArtifactReducer` as a `Projection<ArtifactState>`. Invalid lifecycle transitions are logged as warnings and do not crash replay.
=== ArtifactLineage
* **kind**: data class
* **purpose**: Tracks an artifact's provenance.
* **fields**: `parentIds`, `relationships` (list of ArtifactRelationship), `validationReportIds`
=== ArtifactRelationship
* **kind**: data class
* **purpose**: A directed, typed relationship between two artifacts.
* **fields**: `sourceId`, `targetId`, `type` (ArtifactRelationshipType)
=== ArtifactKind
* **kind**: interface
* **purpose**: Declares a type of artifact with a payload serializer and JSON schema.
* **fields**: `id`, `payloadSerializer`, `llmEmitted`
=== ArtifactKindRegistry / DefaultArtifactKindRegistry
* **kind**: interface / class
* **purpose**: Maps artifact kind IDs to `ArtifactKind` instances. Pre-registers `FileWrittenKind` and `ProcessResultKind`.
=== FileWrittenKind
* **kind**: object
* **purpose**: Artifact kind for files written to disk. Declares a JSON schema with `path`, `content`, `mode`.
=== FileWrittenPayload
* **kind**: data class
* **purpose**: Input payload for a file write operation (before materialization).
* **fields**: `path`, `content`, `mode`
=== FileWrittenArtifact
* **kind**: data class
* **purpose**: Canonical form of a written file after materialization (content-addressed by hash).
* **fields**: `path`, `contentHash`, `size`, `mode`
=== ProcessResultKind
* **kind**: object
* **purpose**: Artifact kind for process execution results. Declares a JSON schema with `command`, `exitCode`, `stdout`, `stderr`, `durationMs`.
=== ProcessResultArtifact
* **kind**: data class
* **purpose**: Record of a process execution.
* **fields**: `command`, `exitCode`, `stdout`, `stderr`, `durationMs`
=== TypedArtifactSlot
* **kind**: data class
* **purpose**: Associates a named artifact slot with its expected kind.
* **fields**: `name` (ArtifactId), `kind` (ArtifactKind)
=== MaterializingArtifactWriter
* **kind**: interface
* **purpose**: Writes a `FileWrittenPayload` to disk within a sandbox root and returns a `FileWrittenArtifact`. Supports content-addressed storage by returning a hash.
=== MaterializationResult
* **kind**: sealed interface
* **purpose**: Outcome of a materialization attempt.
* **variants**: `Success(artifact, resolvedPath)`, `Failure(reason)`
=== ArtifactRepository
* **kind**: interface
* **purpose**: Queries artifact state by session, stage, or ID.
=== JsonSchema / JsonSchemaProperty
* **kind**: data classes
* **purpose**: JSON Schema representation for artifact kind derived schemas.
== event flow
*inbound:*
* `ArtifactCreatedEvent` → sets phase to `CREATED`
* `ArtifactValidatingEvent` → transitions from `CREATED` to `VALIDATING` (fails if phase is not `CREATED`)
* `ArtifactValidatedEvent` → transitions from `VALIDATING` to `VALIDATED`
* `ArtifactRejectedEvent` → transitions from `VALIDATING` to `REJECTED`
* `ArtifactSupersededEvent` → transitions from `VALIDATED` to `SUPERSEDED`
* `ArtifactArchivedEvent` → transitions from `VALIDATED` or `REJECTED` to `ARCHIVED`
* `ArtifactRelationshipAddedEvent` → adds a relationship to the lineage
*outbound:*
* None. This module is purely a projection.
== integration points
* `:core:events` — `StoredEvent`, artifact lifecycle event types, `ArtifactId`, `ArtifactLifecyclePhase`, `ArtifactRelationshipType`
== invariants
* Lifecycle phase transitions follow a strict state machine: `CREATED → VALIDATING → {VALIDATED, REJECTED}`, then `VALIDATED → {SUPERSEDED, ARCHIVED}`, `REJECTED → ARCHIVED`
* Invalid transitions return `Result.Failure` from the reducer — they do not crash the projector
* `ArtifactProjector` catches `IllegalStateException` from invalid transitions, logs a warning, and leaves state unchanged during replay
* `ArtifactKind` registrations are idempotent — the registry is a map, so re-registering overwrites the previous entry
== PlantUML diagram
[plantuml, core-artifacts, "png"]
----
include::../../diagrams/core-artifacts.puml[]
----
== known issues
* `Artifact` sealed interface has no concrete subclasses in the current codebase. The `artifactModule` serializers module has a polymorphic block for `Artifact::class` with no subclass registrations. Concrete artifact types are needed before polymorphic serialization works.
* `ArtifactState` is a single-artifact projection — each `ArtifactState` tracks one artifact's lifecycle. The `ArtifactRepository` interface returns maps keyed by `ArtifactId`, which suggests the caller is responsible for aggregating multiple states.
== open questions
* How are multiple artifact states (one per artifact) stored and queried? The repository returns maps, but the event replayer typically rebuilds a single state per session. The bridge between them is not visible in this module.
* What concrete `Artifact` subclasses are planned? (The sealed interface exists but has no implementations.)