diff --git a/.ciagent/CHECKPOINT.json b/.ciagent/CHECKPOINT.json index fb950c1..108383b 100644 --- a/.ciagent/CHECKPOINT.json +++ b/.ciagent/CHECKPOINT.json @@ -1,11 +1,11 @@ { "phase": 0, - "stage": "plan", + "stage": "mvp_ux_check", "milestone": "v0.4", "milestone_type": "nfr", "tag_base": "v0.3.x", "phase_role": "pre_execution", "project": "oy", "attempts": 0, - "updated_at": "2026-08-17T22:48:00Z" + "updated_at": "2026-08-17T22:50:00Z" } \ No newline at end of file diff --git a/.ciagent/oy/PLANS.md b/.ciagent/oy/PLANS.md index 4c2bf06..8df6a07 100644 --- a/.ciagent/oy/PLANS.md +++ b/.ciagent/oy/PLANS.md @@ -996,4 +996,51 @@ None. P1, P2, P3 are independent vertical slices. P4 depends on P1+P2+P3 complet | D-050 | REQ-031 = document only, no feat: enum additions | P2-01-01, P2-02-01 | | D-051 | REQ-032 docs CI = .gitea/workflows build+artifact, no Pages | P3-01-01 | | D-052 | Phase ordering P1→P2→P3→P4 | Phase ordering | -| D-053 | No IDEATE in v0.4 (no --ideate flag) | (no IDEATE stage run) | \ No newline at end of file +| D-053 | No IDEATE in v0.4 (no --ideate flag) | (no IDEATE stage run) | + +--- + +## MVP/UX Check (REQ-MVP-UX-001) — v0.4 NFR Milestone + +> Auto-generated at full autonomy per run.md §MVP/UX CHECK. The three required +> sections below name at least one user-facing surface, a happy path written +> BEFORE execute, and explicit UX acceptance criteria. v0.4 is an NFR milestone, +> so "user-facing surface" is developer-facing (the lexicon firewall, the +> cross-const test, the CI workflow) and the docs site build (end-user-facing +> via the published docs artifact). + +### User-Facing Surface + +1. **Lexicon firewall (developer-facing)**: `go test ./lexicon_meta... ./lexicon_meta_docs/...` — the green test output is the surface a developer sees on every `go test ./...` run. After REQ-029, both meta-tests consume `lexicon.SyntheticBannedStrings()`; a future banned-term addition updates both firewalls from one place. +2. **Cross-const drift test (developer-facing)**: `go test ./x/hub/types/...` — `TestConstsAreMissionLocked800And0` is the surface a developer sees if the hub↔bond mission-locked consts ever drift. +3. **Docs build CI (end-user-facing via artifact)**: `.gitea/workflows/docs-build.yml` produces a `site/` artifact on every push. A maintainer downloads the artifact to preview the docs site without running `mkdocs build` locally. +4. **ARCHITECTURE.md divergence section (developer-facing)**: a contributor reading `.ciagent/oy/ARCHITECTURE.md` finds the "Council Voice/Council Interface — Lifecycle Type Divergence Decisions (v0.4)" subsection explaining why `SignalKind` is 4-not-5 and why `Proposal`/`VoteOption` are absent. + +### Happy Path + +**Scenario: a contributor adds an 11th banned term to the lexicon firewall.** + +1. The contributor edits `lexicon/lexicon.go` to add a new fragment pair to `fragments` (e.g., a new banned term). +2. `lexicon.BannedTerms()` now returns 11 strings. +3. `lexicon.SyntheticBannedStrings()` (REQ-029) is the single source — the contributor does NOT need to update two meta-test tables (the v0.3 drift risk). +4. `go test ./lexicon_meta... ./lexicon_meta_docs/...` — both meta-tests consume the helper; the `len(terms) == 10` assertion in BOTH meta-tests now fails (expecting 11), alerting the contributor to update the count assertion in both files. +5. The contributor updates the `len(terms) == 11` assertion in both meta-tests (the G-014 minimum — both already derive count from `BannedTerms()`). +6. Both meta-tests pass; the new banned term is now enforced in BOTH the `x/**/*.go` firewall AND the `docs/**/*.md` firewall from one source change. +7. The contributor pushes; `.gitea/workflows/docs-build.yml` (REQ-032) runs `go-test` (green) → `docs-build` (green, G-016 gating) → `site/` artifact uploaded. + +**Scenario: a contributor accidentally changes `x/bond.CouponCapBps` from 800 to 900 without updating `x/hub.LendingCouponCapBps`.** + +1. `go test ./x/hub/types/...` — `TestLendingCouponCapMatchesBondCap` (REQ-030) fails: `hub.LendingCouponCapBps (800) != bond.CouponCapBps (900)`. +2. `TestConstsAreMissionLocked800And0` (G-015) ALSO fails: `bond.CouponCapBps (900) != 800`. +3. The contributor sees two failures pointing at the same root cause; the mission-locked 8% cap is defended by the cross-const test. The v0.3 A-304 drift risk is closed. + +### UX Acceptance Criteria + +The v0.4 deliverable MUST meet these explicit criteria (verified in P4 audit): + +1. **REQ-029**: `lexicon.SyntheticBannedStrings()` exists; both `lexicon_meta_test.go` and `lexicon_meta_docs/lexicon_meta_docs_test.go` consume it; the duplicated 10-string table is gone (grep for the old literal sentence fragments returns zero matches in meta-test files). +2. **REQ-030**: `x/hub/types/cross_const_test.go` exists; `TestLendingCouponCapMatchesBondCap`, `TestLendingCouponFloorMatchesBondFloor`, and `TestConstsAreMissionLocked800And0` all pass (G-015); no production `.go` file in `x/hub/types/` imports `x/bond/types` (G-003 production firewall intact). +3. **REQ-031**: ARCHITECTURE.md has the Council lifecycle divergence subsection; `TestSignalKindShapeIntentional` in `x/council/types/types_test.go` passes and documents the 4-signal rationale; `SignalKindCount` unchanged (still 4); no production `.go` files modified in P2. +4. **REQ-032**: `.gitea/workflows/docs-build.yml` parses; runs `go test ./...` then `mkdocs build` (G-016: `docs-build` needs `go-test`); `go.mod` unchanged. +5. **NFR purity gate**: zero `feat:` commits in the v0.4 milestone range (P4 audit enforces). +6. **No regression**: `go test ./...` green; v0.3 coverage floor (93.3%) not reduced on any modified package. \ No newline at end of file