trainlog/docs/reviews/gate0_review_01.md
2026-09-05 19:16:08 +02:00

159 lines
3.7 KiB
Markdown

# Gate 0 Review #1
## Status
```text
GATE_0_REVIEW_01=PASS
GATE_0=PASS
TRAINLOG_FORMAT_V1=DRAFT
```
## Scope
This review hardens the initial project contract before any C17 or Android implementation begins.
## Findings corrected
### G0-R1-01 — Completed timestamp was structurally mandatory
The initial schema required `ended_at`.
That contradicted the architecture requirement to preserve an active or interrupted session without inventing a completion time.
Correction:
- `ended_at` is optional;
- when present, semantic validation requires it to be strictly later than `started_at`.
### G0-R1-02 — Repetitions and duration were not exclusive
The initial schema used `anyOf`.
A target or set containing both `reps` and `duration_seconds` therefore satisfied both alternatives and could be accepted.
Correction:
- schema uses an exclusive representation;
- every target/set contains exactly one activity mode.
### G0-R1-03 — Exercise identifier uniqueness was undocumented executable behavior
JSON Schema cannot enforce uniqueness of one property across different objects in an array.
Correction:
- semantic validator rejects duplicate `exercise_id` values;
- negative fixture added.
### G0-R1-04 — Display-name duplicates could create duplicate exercises
Stable identifiers alone do not prevent accidental creation of two exercises with visually equivalent names.
Correction:
- semantic normalization algorithm documented;
- semantic validator rejects duplicate normalized display names;
- negative fixture added.
### G0-R1-05 — Session exercise references were not checked against the catalog
JSON Schema cannot validate this cross-reference.
Correction:
- semantic validator requires every session exercise to exist in the top-level catalog;
- negative fixture added.
### G0-R1-06 — Duplicate exercise entries inside one workout were ambiguous
A session could contain the same exercise twice, complicating editing and analytics.
Correction:
- v1 requires one workout entry per `exercise_id`;
- all actual sets belong to that entry;
- negative fixture added.
### G0-R1-07 — Target and actual set modes could disagree
A repetition target could contain duration-based actual sets or vice versa.
Correction:
- semantic validator enforces mode consistency;
- negative fixture added.
### G0-R1-08 — Timestamp offset and chronology required semantic enforcement
The contract requires explicit timezone information and meaningful ordering.
Correction:
- validator rejects offset-less timestamps;
- validator rejects `ended_at <= started_at`;
- negative fixtures added.
### G0-R1-09 — Unknown-field behavior was not frozen
Silently accepting misspelled fields would risk data loss.
Correction:
- v1 draft explicitly rejects unknown fields;
- schema keeps `additionalProperties: false`;
- negative fixture added.
## Validation command
```bash
python tools/validate_json.py
git diff --check
```
Expected result:
- every valid fixture reports `PASS valid`;
- every invalid fixture reports `PASS invalid`;
- `git diff --check` prints nothing.
## Validation evidence
Canonical local validation reported:
```text
python tools/validate_json.py
PASS
```
Every positive fixture was accepted.
Every negative fixture was rejected for the intended reason.
`git diff --check` produced no output.
Reviewed commit:
```text
bc54d6b4ce10d098916823b6a79f72b39d9c7703
Harden Trainlog v1 exchange contract
```
The pushed GitHub mirror was read back and the review changes were verified.
## Gate decision
```text
GATE_0_REVIEW_01=PASS
GATE_0=PASS
```
Gate 0 is closed.
The exchange format remains deliberately unfrozen:
```text
TRAINLOG_FORMAT_V1=DRAFT
```
Gate 1 is responsible for completing the remaining format decisions and
freezing `TRAINLOG_FORMAT_V1`.