Files
alkstore/tasks/core-engine-value-constructors.md
glm-5.3-flash 5474141f2b Core: #[doc(hidden)] engine-side constructors for Job, StreamEvent, Schedule, Wake
Task core-engine-value-constructors (wave-3 pre-work). All four value
types are #[non_exhaustive] (ADR-017 §3), so downstream engine crates
cannot struct-literal-construct them (E0639). Give engines a sanctioned
construction path without weakening the consumer posture: pub
#[doc(hidden)] full-field constructors (Job::from_row, StreamEvent::
from_row, Schedule::new, Wake::new), each doc-commented as engine-
construction-only — not contract surface, not covered by ADR-017's
semver-minor field-addition promise; a field addition changes the
signature and is a lockstep-duty event (ADR-017 §5). Core tests now
construct through the new constructors; no behavior change.
2026-10-08 11:07:53 +00:00

4.1 KiB

id, name, status, depends_on, scope, risk, impact, level, tags
id name status depends_on scope risk impact level tags
core-engine-value-constructors Core — engine-side constructors for the non_exhaustive value types completed
narrow low component implementation
wave-3
core
pre-work

Description

The engine crates must produce Job, StreamEvent, Schedule, and Wake — but all four are #[non_exhaustive] (ADR-017 §3), which bans struct-literal construction from outside the defining crate (E0639). Wave 3's engine is the first code that must build these values from row data, and it cannot. Give the engine crates a sanctioned construction path without weakening the consumer posture.

Add #[doc(hidden)] constructors on each type — e.g. Job::from_row(...), StreamEvent::from_row(...), Schedule::new(...), Wake::new(...) — taking the full field set, pub (engines are ordinary downstream crates, not in-crate) but #[doc(hidden)] so they stay out of the consumer-facing docs and are visibly not contract surface. Doc-comment each with its posture: engine-construction-only, not covered by ADR-017's semver-minor field-addition promise (an engine breaking on a field addition is a lockstep-duty event, ADR-017 §5 — engines are in-repo and updated with core).

Alternative considered and rejected: making the fields pub(crate) + engine #[cfg] tricks, or a builder trait — both add machinery for a problem a hidden constructor solves; the non_exhaustive posture for consumers is untouched either way.

This is deliberately a separate pre-work task (not folded into the first engine task): it touches core's contract-adjacent surface, is consumed by both engines (wave 4 needs the same constructors), and is cheap to review in isolation.

Acceptance Criteria

  • Job, StreamEvent, Schedule, Wake each carry a #[doc(hidden)] full-field constructor, documented as engine-construction-only (not consumer API, not semver-covered)
  • No change to the consumer posture: the types stay #[non_exhaustive]; consumers cannot reach the constructors in docs (spot-check cargo doc)
  • Core tests construct through the new constructors where natural (no behavior change; existing tests keep passing)
  • cargo build, cargo test -p alkstore, clippy -D warnings, fmt clean

References

  • docs/architecture/decisions/017-contract-versioning.md §3, §5
  • docs/architecture/decisions/019-mechanism-handle-surfaces.md §3
  • alkstore/src/job.rs, stream.rs, schedule.rs, wake.rs

Notes

  • Names pinned as Job::from_row and StreamEvent::from_row (row-shaped values) but Schedule::new and Wake::new (not row-shaped) — matching the task's own examples.
  • Job::from_row takes 18 args and carries an explicit #[allow(clippy::too_many_arguments)] — the task pins "taking the full field set" as the posture, so arg count is intrinsic, not a smell to engineer around (no opts struct / builder introduced).
  • Doc-comments follow the crate's # Contract posture section style (see job.rs / stream.rs), naming ADR-017 §3 and §5 explicitly.
  • Core tests updated to construct through the new constructors: value_type_tests.rs (sample_job, sample_event, wake_test) and trait_probe_tests.rs (schedule() return). All 25 core tests still pass.

Summary

Added #[doc(hidden)] full-field constructors to core's four #[non_exhaustive] value types: Job::from_row (18 fields), StreamEvent::from_row (5 fields), Schedule::new (4 fields), Wake::new (1 field) — each pub with a "Contract posture" doc comment pinning engine-construction-only status, exclusion from the contract surface and ADR-017's semver-minor field-addition promise, and the ADR-017 §5 lockstep duty for field additions. #[non_exhaustive] left untouched on all four; consumer posture unchanged. Verified: cargo build, cargo test (workspace; core unchanged-behavior), cargo clippy --all-targets -- -D warnings, cargo fmt --check all clean. cargo doc spot-check: none of the four constructors appears in the generated struct.*.html pages; the only rustdoc warnings are three pre-existing unresolved intra-doc links in validation.rs, untouched by this task.