docs: formalize save/restore field-completeness as a standing invariant
Prompted by rediscovering the same bug class in two places this
session: the controller's WAL already has this documented for one
mechanism (persistence.md's APPLY_CLEAN/bug-1678 section, xce-audit-
invariants controller dimension 7) but the scheduler's separate
snapshot save/load mechanism had the identical gap (job->allocs, this
session's scheduler-snapshot-job-allocation brief) with no equivalent
tracking. Closes that gap and makes the invariant self-reinforcing
going forward rather than something that has to be independently
rediscovered per persistence mechanism:
- xce-audit-invariants: new scheduler dimension 4 ("Field-complete
snapshot save/load parity"), sibling of controller dimension 7,
scoped to snapshot.c/snapshot_wire.c/snapshot_load.c.
- persistence.md: new "Snapshot Save/Load Field-Completeness
(Scheduler)" section cross-referencing the WAL-side bug-1678 writeup
and the new scheduler dimension.
- CLAUDE.md: new top-level Key Rules bullet stating the invariant
plainly, plus adding persistence.md to the steering-file pointer
table (it was missing).
- kiro-spec-design's design-review-gate.md (the mandatory pre-write
gate) and kiro-validate-design's design-review.md (the optional deep
review): new conditional review sections -- applies only when a
design touches a save/restore mechanism, requires enumerating every
persisted field's capture status rather than trusting an aggregate
"state looks right" check. Catches this class of gap at design time,
before implementation, rather than only via a later audit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AgYRU3zDTqNGV5Jk8aiKLg
This commit is contained in:
parent
c0ad576838
commit
d32f06e5fc
6 changed files with 92 additions and 0 deletions
|
|
@ -33,6 +33,13 @@ Before writing `design.md`, review the draft design and repair local issues unti
|
|||
- Avoid speculative abstraction: remove components, adapters, or interfaces that exist only for hypothetical future scope.
|
||||
- If a section is too vague for tasks to reference directly, rewrite it before finalizing the design.
|
||||
|
||||
## Persistence / Save-Restore Completeness Review (when applicable)
|
||||
|
||||
- If the design adds or modifies any save/restore mechanism (a durable log entry, a snapshot/checkpoint format, a cache, or any other persist-then-later-reconstruct path), the design must enumerate every field of the entity being persisted and state explicitly, per field, whether it is captured on write and restored on every read/apply path — an implicit "the rest just works" is not sufficient.
|
||||
- A state that reports as "recovered correctly" (right status, right row count, right cursor position) while silently missing a field it depends on is a design gap, not an acceptable simplification — a passing high-level check (row counts, cursor position) does not prove per-field completeness.
|
||||
- An omitted field is acceptable ONLY if the design explicitly documents it as a deliberate scope decision with a stated reason — a silent omission discovered later is treated as a defect, not a scope choice made after the fact.
|
||||
- If this project has a persistence steering doc (e.g. `persistence.md`) or an invariant-audit skill (e.g. `xce-audit-invariants`) covering this exact concern, cross-check the design against it and cite the relevant section/dimension rather than re-deriving the principle from scratch.
|
||||
|
||||
## Mechanical Checks
|
||||
|
||||
Before applying judgment, verify these mechanically:
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@ Conduct interactive quality review of technical design documents to ensure they
|
|||
- Clear API boundaries and data structures
|
||||
- Input validation and error handling coverage
|
||||
|
||||
### 5. Persistence / Save-Restore Field-Completeness (when applicable)
|
||||
- Applies only when the design adds or modifies a save/restore mechanism (durable log entry, snapshot/checkpoint, cache, or any persist-then-reconstruct path); skip entirely otherwise.
|
||||
- Every field of the persisted entity is either captured on write and restored on every read/apply path, or explicitly documented as a deliberate, reasoned omission — not silently dropped.
|
||||
- A design that only checks aggregate signals (row counts, cursor position, "state looks right") without addressing per-field completeness should be flagged here, not waved through as a detail for implementation.
|
||||
- Cross-check against this project's own persistence steering doc / invariant-audit skill if one exists, and cite the specific section rather than re-deriving the principle.
|
||||
|
||||
## Review Process
|
||||
|
||||
### Step 1: Analyze
|
||||
|
|
|
|||
|
|
@ -171,6 +171,26 @@ bug-1613/bug-1681 and confirm bug-1611's partial-fix status):
|
|||
does anything raise the `jbuf` cbuf capacity above 1, or bypass the
|
||||
rendezvous with a second concurrent producer/consumer? Re-derive Req 5 AC
|
||||
7 in `.kiro/specs/scheduler-core/requirements.md` before touching this.
|
||||
4. **Field-complete snapshot save/load parity** (new 2026-08-27, sibling of
|
||||
controller dimension 7 / bug-1678 — same invariant, separate persistence
|
||||
mechanism, does NOT share code or fixes with the WAL side) — for every
|
||||
entity `xce_sched_core_save_snapshot()`/`xce_sched_core_load_snapshot()`
|
||||
round-trips (job/queue/worker/user/project), is every field the live
|
||||
entity carries actually (a) written into the wire type in
|
||||
`snapshot_wire.c`'s `build_wire_*()` functions, not just held in the
|
||||
in-memory struct, and (b) read back and adopted in
|
||||
`snapshot_load.c`'s `xce_sched_core_load_snapshot()`? `snapshot.c`'s own
|
||||
"Scope decisions" header documents several KNOWN, deliberate gaps (e.g.
|
||||
`job->priority`, queue `project_name`/`job_pick_plugin`) — those are
|
||||
fine, they're explicit; the audit is for UNDOCUMENTED gaps. Confirmed
|
||||
instance: `job->allocs`/`job->accounts` were silently not captured
|
||||
(`snapshot_wire.c:167`'s own comment flags it, but nothing closed the
|
||||
gap until `scheduler-snapshot-job-allocation`) — a snapshot-restored
|
||||
RUNNING job's resource allocation was permanently lost, matching
|
||||
bug-1678's controller-side symptom shape exactly (state recovers
|
||||
correctly, allocation/assignment silently doesn't). Cross-check
|
||||
`persistence.md`'s "Snapshot Save/Load Field-Completeness (Scheduler)"
|
||||
note for the shared underlying principle.
|
||||
|
||||
Each subagent must report file:line evidence for every claimed violation —
|
||||
no speculative findings. Use the Agent tool directly (general-purpose or
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue