diff --git a/.ciagent/CHECKPOINT.json b/.ciagent/CHECKPOINT.json index 5df6f7c..4c46484 100644 --- a/.ciagent/CHECKPOINT.json +++ b/.ciagent/CHECKPOINT.json @@ -6,9 +6,9 @@ "project": "oy", "phase": 0, "phase_role": "pre_execution", - "stage": "research", + "stage": "plan", "attempts": 0, - "updated_at": "2026-08-19T00:02:00Z", + "updated_at": "2026-08-19T00:03:00Z", "next_milestone": null, "previous_milestone": { "milestone": "v0.6", diff --git a/.ciagent/oy/PLANS.md b/.ciagent/oy/PLANS.md index 37b1a34..fc74848 100644 --- a/.ciagent/oy/PLANS.md +++ b/.ciagent/oy/PLANS.md @@ -2149,4 +2149,249 @@ The v0.6 deliverable MUST meet these explicit criteria (verified in P6 audit): 5. **Standing score computed from locked formula constants**: the Standing screen score uses `x/standing/types` constants (`PriorMean=4.0`, `PriorWeight=10`, decay buckets, `ComputeDiversityBonus`, `GetVoucherWeight`, `GetStandingBucket`) — NOT hardcoded; the standing-score computed-from-locked-constants test (P4-03-01) asserts this. 6. **Freeholder-eligible badge reflects `IsFreeholderEligible()`**: the Standing screen badge is green when `FreeholderSignals.IsFreeholderEligible()==true` and grey when false; the Freeholder-eligible badge test (P4-03-01) asserts the rendered badge matches the method output. 7. **Window lifecycle transitions match `Window.Activate/Revoke/Expire`**: the Window screen lifecycle buttons call the real `x/window/types.Window.Activate/Revoke/Expire` methods (NOT a reimplementation); `Revoke()` on an Expired window is a no-op (v0.2 type contract); the lifecycle correctness test (P3-03-01) asserts the real methods are invoked. -8. **No banned terms in any rendered page**: the per-handler rendered-HTML lexicon checks (P1-04-03, P2-03-01, P3-03-01, P4-03-01, P5-03-01) scan each screen's HTTP response body via `lexicon.FindBannedTerm` and pass; the `lexicon_meta_web/` file-scan firewall passes on all `web/**/*.{html,js,go}` files. \ No newline at end of file +8. **No banned terms in any rendered page**: the per-handler rendered-HTML lexicon checks (P1-04-03, P2-03-01, P3-03-01, P4-03-01, P5-03-01) scan each screen's HTTP response body via `lexicon.FindBannedTerm` and pass; the `lexicon_meta_web/` file-scan firewall passes on all `web/**/*.{html,js,go}` files. + +--- + +# Plans: OpenYield (oy) — v0.7 (Fraternal Groups Foundation) + +## Milestone Summary + +- **Milestone**: v0.7 — Fraternal Groups Foundation +- **Type**: Feature (≥1 `feat` phase; REQ-046..REQ-066 are feat-class primitives + a test adjunct for the Anti-Crowding-Out firewall in P1) +- **Tag base**: `v0.6.x` patch line (P0 ships as `v0.6.0`; execution phases `v0.6.1..v0.6.5`; final phase `v0.6.6` IS the v0.7 milestone release per D-008) +- **Phases**: 6 — P1..P5 (execution) + P6 (final review/audit/ship). Phase 0 (PLAN) is in progress. +- **Depth**: simtest-grade runtime (D-054 continues) — keeper MsgServer handlers + simtest end-to-end flows for `x/cover` (NEW) + extensions to `x/bond`, `x/guild`, `x/standing`, `x/stand`. No live chain launch, no `app.go`/`cmd/oyd`. +- **Coverage target**: ≥80% on `x/cover` + extensions (D-033 carries forward); lexicon assertion (REQ-012) in `x/cover` test file + the 4th meta-test (`lexicon_meta_cover`) for the Anti-Crowding-Out firewall doc-drift (D-079). +- **New modules**: 1 (`x/cover` — Cover Pool Factory + Anti-Crowding-Out firewall + Anti-Capture Bill of Rights + Cover Claims Voucher). **Extended**: 4 (`x/bond` MAB, `x/guild` Chapter Federation, `x/standing` Shadow vouch + slash reason, `x/stand` Household/Confederation keeper logic + Stand→Pier const). **Unchanged**: 1 (`x/pact` — PactCover enum stays as cross-reference, D-084). +- **Phase ordering** (D-082): P1 Cover Pool Factory + firewall + locked floors + gates + tagging (firewall-first) → P2 Cover-Charter + Pool governance + category staging → P3 Guild Charter + Chapter Federation + Household/Confederation + disclaimer → P4 MAB + Cover Claims Voucher + Shadow vouch + MAB seniority → P5 Anti-Capture Bill + secession cooling + Stand→Pier boundary + Pier selection → P6 final review/audit/ship. +- **Personas**: backend-engineer (all phases), lead-developer (all phases — coordination + D-085 escalation + pen-test assumption), security-engineer (all phases — highest security density since v0.5), cosmos-engineer (all phases — advisory; x/cover follows x/hub pattern). + +### Cross-Phase Dependency Map + +``` +P1 (x/cover Factory + firewall + floors + gates + tagging) + │ + ├─► P2 (x/cover Charter + governance hybrid + category staging) + │ │ + │ └─► P3 (x/guild Chapter Federation + Household + Confederation + disclaimer) + │ │ (Chapter liens reference Cover Pool covenants) + │ │ + │ └─► P5 (x/cover Anti-Capture Bill + x/guild secession cooling + x/stand Pier boundary + Pier selection) + │ + └─► P4 (x/bond MAB + x/cover Cover Claims Voucher + x/standing Shadow vouch + MAB seniority) + │ (MAB depends on Cover Pool reserve for use-of-proceeds; + │ Voucher slash depends on x/standing.Slash existing) + │ + └─► P5 (Anti-Capture Bill constrains MAB no-Voice + Voucher independence + secession) +``` + +### v0.7 Locked-Const Firewall Additions (pending GRILL ratification at P0) + +11 new locked consts (all net-new, no amendments to existing consts — per oy-state §3 + ARCHITECTURE.md v0.7 section): + +| Const | Value | Module | REQ | Locked? | +|-------|-------|--------|-----|---------| +| CoverReserveFloorAnnualContribX | 1.5 | x/cover | REQ-047 | yes | +| CoverReserveCeilingAnnualContribX | 2.5 | x/cover | REQ-048 | no (bounded [1.5, 2.5]) | +| CoverStandingGateTrusted | 4.0 | x/cover | REQ-049 | yes | +| CoverStandingGatePreferred | 4.5 | x/cover | REQ-049 | yes | +| MABIssuanceCeilingAnnualSurplusMultiple | 3 | x/bond | REQ-054 | yes | +| CoolingSecessionCoverActiveDays | 21 | x/guild | REQ-064 | yes | +| CoolingSecessionNonCoverDays | 14 | x/guild | REQ-064 | yes | +| StandPierEscalationAnnualPassVolumeCents | 10000000 | x/stand | REQ-059 | no | +| CoverClaimsVoucherBondMultipleAvgCall | 10 | x/cover | REQ-055 | no | +| AntiCaptureBillOfRightsCount | 13 | x/cover | REQ-056 | yes | +| ShadowVouchWeightMultiplier | 0.5 | x/standing | REQ-060 | yes | + +--- + +## Phase P0 — Pre-Execution + +- **Type**: docs +- **Tag**: `v0.6.0` +- **REQs**: none (pre-execution) +- **Status**: IN PROGRESS (SPECIFY ✓, CLARIFY ✓, RESEARCH ✓, PLAN in progress, GRILL pending, MVP/UX pending, SHIP pending) + +--- + +## Phase P1 — Cover Pool Factory + Firewall + Locked Floors + Gates + Tagging + +- **Type**: feat + test (firewall-first vertical slice) +- **Tag**: `v0.6.1` +- **REQs**: REQ-046, REQ-047, REQ-049, REQ-050 +- **Module**: NEW `x/cover` (mirrors x/hub D-039 layout) +- **Personas**: backend-engineer (types + keeper + module + simtest), security-engineer (firewall + locked floors + gates), cosmos-engineer (AppModule + expected_keepers + Msg*), lead-developer (regression guards) + +### P1 Must-Haves + +1. **`x/cover` module skeleton** — `x/cover/types/types.go` (CoverPool, CoverFeeTag, CoverCategory, CoverCategoryPhase structs + locked consts), `x/cover/types/expected_keepers.go` (StandingKeeper, WatcherKeeper, BondKeeper, StillKeeper interfaces — G-003 shims), `x/cover/types/msg_cover.go` (MsgLaunchCoverPool, MsgRouteCoverFee, MsgFileCoverCall — `sdk.Msg` impls with ValidateBasic), `x/cover/keeper/keeper.go` (store-backed), `x/cover/keeper/msg_server.go` (one handler per Msg*), `x/cover/keeper/firewall.go` (Anti-Crowding-Out firewall enforcement), `x/cover/module.go` (AppModule + RegisterServices + MsgServer() accessor). Layout mirrors `x/hub/` (D-039 precedent). +2. **Anti-Crowding-Out firewall (D-079)** — `x/cover/firewall/` subpackage with `CheckCoverFeeRouting(path) error` that rejects any code path routing Cover-Fees outside contributor-pool semantics. Called at the start of every `MsgRouteCoverFee` handler. PLUS `lexicon_meta_cover/` meta-test (4th lexicon meta-test, mirrors `lexicon_meta_web/` pattern) scanning `x/cover/**` docstrings + `x/cover/firewall/**` for doc drift. Defense in depth: runtime rejects code path, meta-test rejects doc drift. +3. **Reserve floor 1.5× (REQ-047 locked)** — `CoverReserveFloorAnnualContribX = 1.5` const in `x/cover/types`. `MsgRouteCoverFee` handler invokes `checkReserveFloor(ctx, poolID)`; if `pool.ReserveAnnualContribRatio < 1.5`, REJECT routing AND emit `PoolBelowFloor` event that triggers auto-pause for subsequent routings until reserve replenished. Below-floor auto-pause = the handler sets a `PoolPaused bool` on the CoverPool; subsequent `MsgRouteCoverFee` handlers reject while paused. +4. **Standing gate minimums (REQ-049 locked, D-077)** — `CoverStandingGateTrusted = 4.0` + `CoverStandingGatePreferred = 4.5` consts in `x/cover/types` (cross-documented to `x/standing.BucketTrusted`/`BucketPreferred`). `MsgLaunchCoverPool` handler invokes `StandingKeeper.GetStandingBucket(hostReachID, category)` for each category the Pool covers; if any category's gate is below the locked minimum (Trusted 4.0 for Travel, Preferred 4.5 for Health-MCS), REJECT the launch. Gate binds at Factory runtime (D-077). Pool MAY tighten (a `PoolStandingGate` Params field ≥ protocol minimum); NEVER loosen (the const floor). +5. **Cover-Fee category tagging (REQ-050 locked)** — `CoverFeeTag` struct in `x/cover/types` (`{GrainAmount int64, CategoryTag string, PoolID string}`). `MsgRouteCoverFee` handler validates the tag against the Pool's allowed categories; category-mismatch → REJECT (FR-COVER-11). Pool-level fungibility preserved for net-reserve accounting. +6. **Factory runtime (REQ-046)** — `MsgLaunchCoverPool` handler: validates reserve floor (REQ-047), validates Standing gate per category (REQ-049), validates category is in an allowed phase (REQ-065 staging — placeholder in P1, full staging lands in P2), witnesses Cover-Charter (REQ-052 — Charter hash placeholder in P1, full Charter lands in P2). Watcher attestation pipeline: `WatcherKeeper.Attest(poolID, launchPayload)` called at launch; stubbed in simtest. +7. **Simtest** — `x/cover/keeper/msg_server_simtest_test.go` exercising: (a) successful Pool launch with valid Standing + reserve; (b) rejected launch below Standing gate; (c) rejected launch below reserve floor; (d) rejected Cover-Fee routing with category mismatch; (e) auto-pause on below-floor + recovery on reserve replenishment; (f) firewall rejection of an out-of-pool routing path. +8. **Lexicon + locked-const regression** — `x/cover/types/types_test.go` asserts the 4 new consts + lexicon assertion (no banned terms in `x/cover/**` — "Cover", "Cover-Fee", "Cover Call", "Cover-Charter" are the lexicon-clean names; NOT "insurance", "premium", "claim", "policy"). The `lexicon_meta_cover/` meta-test is the 4th lexicon firewall. +9. **Coverage ≥80%** on `x/cover/types` + `x/cover/keeper` + `x/cover/firewall`. + +### P1 Firewall-First Rationale + +P1 lands the Anti-Crowding-Out firewall + locked floors + Standing gates BEFORE any Cover surface that could route around them (P2 Charter, P3 Federation, P4 MAB, P5 Bill of Rights). This is the D-044/D-069 firewall-first pattern: the firewall is in place before the content it guards. + +--- + +## Phase P2 — Cover-Charter + Pool Governance Hybrid + Category Staging + +- **Type**: feat +- **Tag**: `v0.6.2` +- **REQs**: REQ-048, REQ-052, REQ-062, REQ-065 +- **Modules**: extends `x/cover` (Charter + governance + staging) + `x/council` (Pool Council seat — no struct change, keeper logic) +- **Personas**: backend-engineer (Charter + staging types + keeper), security-engineer (Charter validation + governance observer quorum), cosmos-engineer (Msg* + keeper handlers) + +### P2 Must-Haves + +1. **Cover-Charter (REQ-052 locked)** — `CoverCharter` struct in `x/cover/types` (`{CharterID, PoolID, StatementOfBeliefsHash []byte, DisputePath string, Gate string, HoldingPeriodDays uint32, HostReachID string, WatcherWitnessHash []byte, Amendments []CharterAmendment}`). `MsgSignCoverCharter` handler: signed by Pool Host + witnessed by Watcher. Amendments require Pool supermajority + 7-day cooling + Watcher + Counsel (a `CharterAmendment` struct with `Status` enum: Proposed/Cooled/Ratified). **Protocol does NOT enforce SoB content** (FR-CHTR-5) — the `StatementOfBeliefsHash` is opaque bytes; validation checks structural fields only. +2. **Reserve ceiling 2.5× (REQ-048 not locked)** — `CoverReserveCeilingAnnualContribX = 2.5` const (the bounded upper limit). Pool Council MAY vote within [1.5×, 2.5×] via a `PoolReserveTarget` Params field. Watcher escalation to 2.5× after 12 months operating history (a `MsgEscalateReserveCeiling` handler requiring Watcher attestation + 12-month age check). The 1.5× floor (P1) is NOT tunable; only the target within the bounded range. +3. **Pool governance hybrid (REQ-062 locked)** — `PoolCouncil` struct in `x/cover/types` (`{PoolID, HostReachID, ElectedMasonReachIDs [3]string, WatcherObserverReachID string}`). `MsgElectPoolMason` handler (Pool-eligible Masons elect 3). `MsgVoteCoverCall` handler: majority required with Watcher observer present (a `WatcherObserverPresent bool` field on the vote; if false, vote rejects). **No Anchor seat** (§5). No MAB-holder seat (REQ-063 — lands in P4 but the governance struct excludes them now). +4. **Category staging (REQ-065 locked)** — `CoverCategoryPhase` enum in `x/cover/types` (`Phase2`/`Phase3`/`Phase4`). `CoverCategory` enum (`Travel`/`HealthMCS`/`IncomePause`/`EquipmentLoss`/`LifeBurial`/`RoadSide`/`CyberSkimming`/`GuildInternalMutualAid`). Phase 2 = Travel + HealthMCS + IncomePause; Phase 3 = EquipmentLoss + LifeBurial + RoadSide; Phase 4 = CyberSkimming + GuildInternalMutualAid. `FactoryAllowedPhases` Params field. `MsgLaunchCoverPool` handler (extended from P1) rejects out-of-phase launches. +5. **Simtest** — (a) successful Charter signing + Watcher witness; (b) Charter amendment with 7-day cooling + supermajority; (c) Pool Council election (3 Masons); (d) Cover Call vote with Watcher observer present (succeeds) + absent (rejects); (e) Factory rejects out-of-phase category launch; (f) reserve ceiling escalation after 12-month age check. +6. **Lexicon + locked-const regression** — `x/cover/types/types_test.go` extended with the ceiling + phase + category consts. Lexicon assertion on new Msg* names. +7. **Coverage ≥80%** on the extended `x/cover` surface. + +--- + +## Phase P3 — Guild Charter + Chapter Federation + Household/Confederation + Disclaimer + +- **Type**: feat +- **Tag**: `v0.6.3` +- **REQs**: REQ-051, REQ-053, REQ-057, REQ-058, REQ-061 +- **Modules**: extends `x/guild` (Parent/Chapter + secession terms + liens + Household + Confederation) + `x/stand` (Household/Confederation keeper logic) +- **Personas**: backend-engineer (Guild extension + keeper), security-engineer (lien bounding + secession cooling consts), cosmos-engineer (Msg* + keeper handlers) + +### P3 Must-Haves + +1. **Guild Charter + Common Bond (REQ-051 locked)** — extend `x/guild/types.Guild` with `CommonBondHash []byte` + `PublicProfile GuildPublicProfile` fields. `GuildPublicProfile` struct (`{BondSummary string, Disclaimers []string, MasonCount uint32_or_Private bool, PierWrapperID string}`). `MsgCreateGuild` handler (extended): Common Bond declared + hash-pinned at creation; Public Profile published. `MasonCount` is either a count or a `"private"` sentinel. +2. **Chapter Federation (REQ-053)** — extend `x/guild/types.Guild` with `ParentGuildID string` (empty for Parent Guilds) + `IsChapter bool` + `SecessionTermsHash []byte` + `GoodStandingLiens []Lien`. `Lien` struct (`{Amount int64, CreditorReachID string, SecuredAtFounding bool}`). `MsgCreateChapter` handler: Parent Guild + Chapter model; Chapter inherits Parent's policies + MAY tighten but NOT loosen. Secession terms coded at founding (a `SecessionTerms` struct: `{CoolingCoverActiveDays uint32, CoolingNonCoverDays uint32, LienAuditRequired bool, CovenantClearanceRequired bool}` — hash-pinned at creation, immutable). Good-standing liens at founding (NOT freely increasable — `SecuredAtFounding=true` liens reject `MsgAddLien`). Chapter retains mesh-level Voice (Pier does NOT carry Voice per FR-VOICE-6 — a `PierCarriesVoice bool` const `false` in `x/guild/types`). +3. **Household simplified (REQ-057)** — `x/stand` keeper: `IsHousehold(standID)` check (switch on `StandType == StandHousehold`). Household Stands skip the formal-Council requirement. `MsgOneTapExitStand` handler — the dispute path for Household. One-tap exit = the Stand is dissolved + assets returned to the Holder's Stash; no Council vote required. +4. **Confederation Voice (REQ-058 locked)** — `x/stand` keeper: `GetConfederationVoice(confederationStandID) []Voice` aggregates member-Stand Voice one-per-Stand. Internal bundle delegation via §19 delegation (existing `x/council` Voice mechanics — a `MsgDelegateConfederationVoice` handler). One-Stand-one-Vote: each member Stand gets exactly 1 Voice in the Confederation's aggregate, regardless of size. +5. **Disclaimer cadence (REQ-061 locked)** — `MsgCreateGuild` + `MsgCreateChapter` + `MsgSignCoverCharter` handlers all surface a jurisdictional disclaimer at every charter signing (a `Disclaimer string` field on each Msg; the handler returns the disclaimer in the response). NOT session-bounded. +6. **Simtest** — (a) Guild creation with Common Bond hash + Public Profile; (b) Chapter creation with secession terms hash-pinned + good-standing liens; (c) Chapter inherits Parent policy + tightens (allowed) + loosens (rejected); (d) Household one-tap exit; (e) Confederation Voice aggregation (one-per-Stand); (f) disclaimer surfaced at every signing. +7. **Lexicon + locked-const regression** — `x/guild/types/types_test.go` extended with the cooling consts (`CoolingSecessionCoverActiveDays=21`, `CoolingSecessionNonCoverDays=14`). Lexicon assertion on new Msg* names. +8. **Coverage ≥80%** on the extended `x/guild` + `x/stand` surfaces. + +--- + +## Phase P4 — Mutual Aid Bond + Cover Claims Voucher + Shadow Vouch + MAB Seniority + +- **Type**: feat +- **Tag**: `v0.6.4` +- **REQs**: REQ-054, REQ-055, REQ-060, REQ-063 +- **Modules**: extends `x/bond` (MAB), `x/cover` (Cover Claims Voucher + MAB seniority waterfall), `x/standing` (Shadow vouch weight + slash reason) +- **Personas**: backend-engineer (MAB + Voucher + Shadow vouch types + keeper), security-engineer (MAB use-of-proceeds lock + Voucher slashing + Shadow vouch const), cosmos-engineer (Msg* + keeper handlers) + +### P4 Must-Haves + +1. **Mutual Aid Bond (REQ-054 locked)** — `MAB` struct in `x/bond/types` (anonymous embed of `Bond` + `CouponKind CouponDenom` + `AnnualSurplusAtIssuance int64` + `UseOfProceedsTag string`). `CouponDenom` enum (`CouponDenomCoverCall`/`CouponDenomMutualAidCredit`/`CouponDenomBread` — the last exists ONLY to be rejected at `ValidateBasic` with "FR-MAB-3: MAB coupons NEVER Bread", mirroring `MissionLockAmendmentRejected`). `MABIssuanceCeilingAnnualSurplusMultiple = 3` const in `x/bond/types`. `MsgIssueMAB` handler: `checkMABIssuanceCeiling(ctx, poolID, newPrincipal)` asserts `sum(issuedMABPrincipal) + newPrincipal <= 3 × AnnualSurplus` (re-check at every issuance). Coupon rate bounded by `CouponCapBps=800` (existing locked const — no new const, cross-const test extends). +2. **D-080 tagged streaming + Watcher-witnessed release** — `UseOfProceedsTag` field locked to `"reserve_build_out"` (a const `MABUseOfProceedsReserveBuildOut`). `MsgDebitMABProceeds` handler: checks destination account is the Pool's `ReserveAccount`; else invokes `StillKeeper.Still(poolID, "MAB misuse")` for auto-Still. `MsgWitnessMABProceedsRelease` handler: requires Watcher quorum (6-of-9, `x/watcher/types/types.go:23` `Quorum=6`) before proceeds move from tagged staging to reserve. Watcher attestation at deployment + quarterly audit (a `MsgWatcherAttestMAB` handler). +3. **Cover Claims Voucher (REQ-055)** — `CoverClaimsVoucher` struct in `x/cover/types` (`{VoucherReachID string, PoolID string, BondAmount int64, BondMultipleAvgCall uint32}`). `CoverClaimsVoucherBondMultipleAvgCall = 10` const. Bond = 10× avg Call size per Pool. `MsgRegisterCoverClaimsVoucher` handler: bonds the Voucher. `MsgFileCoverCall` handler: assigns a Call to a Voucher; **no self-adjudication** (FR-CPCV-2) — rejects if `voucherReachID == claimantReachID`. Slashing via existing `x/standing.Slash` struct with new `SlashReasonFraudulentCoverCall` const — cross-Pool applicability (the slash drops the Voucher's Standing bucket, disqualifying them from other Pools). Bounded earnings (a `MaxVoucherEarningsPerCall` Params field). +4. **Shadow vouch 50% weight (REQ-060 locked)** — extend `x/standing/types.Vouch` with `IsShadow bool` field. `ShadowVouchWeightMultiplier = 0.5` const in `x/standing/types`. Modify `GetVoucherWeight` to apply the multiplier as a post-step: `if isShadow { weight *= ShadowVouchWeightMultiplier }`. The const makes the 0.5× mission-locked (REQ-060 locked) and regression-testable. New test `TestShadowVouchWeight` in `x/standing/types/types_test.go`. +5. **MAB holder seniority no-Voice (REQ-063 locked)** — `PoolDissolutionWaterfall` function in `x/cover/keeper`: returns `[{Tier: "CoverFeeContributors", ...}, {Tier: "MABHolders", ...}, {Tier: "BreadHolders", ...}]` (FR-MAB-4 seniority chain). MAB holders excluded from the Pool Council voice set (the `PoolCouncil` struct from P2 already excludes them; P4 adds the waterfall + a `MsgDissolveCoverPool` handler that invokes the waterfall). MAB holders have NO Voice in dissolution decisions. +6. **Simtest** — (a) MAB issuance with valid Cover-Call coupons; (b) MAB issuance rejected with Bread coupons (FR-MAB-3); (c) MAB issuance rejected above 3× annual surplus ceiling; (d) tagged streaming misuse → auto-Still; (e) Watcher-witnessed release (quorum present: succeeds; absent: rejects); (f) Cover Claims Voucher registration + bond; (g) Cover Call adjudication (no self-adjudication); (h) Voucher slash for fraudulent Call → Standing bucket drop; (i) Shadow vouch 0.5× weight applied; (j) Pool dissolution waterfall (Cover-Fee contributors > MAB > Bread holders). +7. **Lexicon + locked-const regression** — `x/bond/types/types_test.go` extended with `MABIssuanceCeilingAnnualSurplusMultiple=3` + `CouponDenom` enum count. `x/standing/types/types_test.go` extended with `ShadowVouchWeightMultiplier=0.5`. `x/cover/types/types_test.go` extended with `CoverClaimsVoucherBondMultipleAvgCall=10`. Cross-const test: MAB coupon cap == `CouponCapBps` (extends REQ-030 pattern). +8. **Coverage ≥80%** on the extended `x/bond` + `x/cover` (Voucher + waterfall) + `x/standing` (Shadow vouch) surfaces. + +--- + +## Phase P5 — Anti-Capture Bill of Rights + Secession Cooling + Stand→Pier Boundary + Pier Selection + +- **Type**: feat +- **Tag**: `v0.6.5` +- **REQs**: REQ-056, REQ-059, REQ-064, REQ-066 +- **Modules**: extends `x/cover` (Anti-Capture Bill of Rights + Pier Selection Index), `x/guild` (secession cooling enforcement), `x/stand` (Stand→Pier boundary const + escalation) +- **Personas**: backend-engineer (Bill of Rights + secession + Pier types + keeper), security-engineer (Bill of Rights firewall + secession lien audit + Pier Selection Index), lead-developer (D-085 escalation — 13th right identification before P5 lands), cosmos-engineer (Msg* + keeper handlers) + +### P5 Must-Haves + +1. **Anti-Capture Bill of Rights v0.2 (REQ-056 locked)** — `x/cover/types/rights.go`: 13 `RightID` consts + 13 `Waivable*` bool consts (all `false`) + `RightIsWaivable(id RightID) bool` function that always returns `false`. `AntiCaptureBillOfRightsCount = 13` const. The 12 enumerated rights: `RightOneTapExit`, `RightNoTaxOnPersonalStash`, `RightAuditableVoice`, `RightCooling`, `RightWatcherInspection`, `RightFreeholderVoucher`, `RightCounselEscalation`, `RightAnchoredBreadConversion`, `RightWayfarersRecord`, `RightSecessionFoundingTerms`, `RightNonCoverAccess`, `RightCategoryMismatchRefusal`. **The 13th right** — D-085 escalation candidate: `RightNonParticipationNoDenial` (confidence 0.55; "non-participation MUST NOT deny other mesh products" per REQ-085/FR-NORM-4). **Lead-developer surfaces D-085 to PO before P5 lands.** If unresolved at full autonomy, log as assumption with `RightNonParticipationNoDenial` and proceed. +2. **Dual firewall (const + ValidateBasic)** — `MsgSignCoverCharter.ValidateBasic` (extended from P2): checks the charter's `WaivedRights []RightID` field; if ANY right is in the list, REJECT with "REQ-056: rights non-amendable, non-waivable by any Charter". Mirrors `MissionLockAmendable=false` + `MissionLockAmendmentRejected` (D-064). The 13 `Waivable*` consts are the const firewall; the `ValidateBasic` gate is the runtime firewall. +3. **Secession cooling enforcement (REQ-064 locked)** — `x/guild/keeper`: `MsgInitiateSecession` handler records `secessionStartedAt` + invokes `lienAudit(poolID)`. `MsgCompleteSecession` handler checks: (a) `now >= secessionStartedAt + coolingSeconds` where `coolingSeconds = CoolingSecessionCoverActiveDays*86400` (21d) if the Chapter is Cover-active, else `CoolingSecessionNonCoverDays*86400` (14d); (b) lien-audit-passed; (c) Cover Call / Bond covenant clearance passed. Cooling secured at founding (the `SecessionTerms` from P3 is immutable), NOT reducible. Parent Guild Treasury receives pro-rata Cover-Fee settlement for in-flight Cover Calls (a `ProRataSettlement` function in `x/cover/keeper`). +4. **Stand→Pier boundary (REQ-059, D-074)** — `StandPierEscalationAnnualPassVolumeCents = 10000000` const in `x/stand/types` (placeholder for $100k in Grain-cents at simtest; the PO ruling D-074 is $100k USD which is converted at the current USD/Grain oracle rate — but no oracle exists in simtest). The handler `MsgEscalateStandToPier` (or a keeper-level `checkStandPierEscalation(standID)` invoked on Pass routing): when annual Pass volume > the const, the Stand is *invited* to Hub API (a `StandPierEligible bool` flag + a `MsgAcceptPierInvitation` handler). Soft upgrade, not a ban — the Stand may decline. +5. **Pier selection (REQ-066)** — `PierSelectionIndex` struct in `x/cover/types` (`{PierID string, JurisdictionalReliabilityScore float64, FiduciaryRecordHash []byte, IntegrationQualityScore float64, OverallScore float64}`). `MsgSelectPier` handler: Guild Council chooses Pier at formation. `MsgRevokePierSelection` handler: reversible by Cover Pool supermajority + Counsel witness. Mesh maintains the Pier Selection Index (a keeper-level `GetPierSelectionIndex(pierID)` query). **Pier-Routed Legal Wrapper is OPTIONAL** (§5 default-no-wrapper — no code required; a `PierWrapperID string` field on Guild from P3 is optional, empty by default). +6. **Simtest** — (a) Charter signing with waived rights → REJECT (dual firewall); (b) Charter signing with no waived rights → succeeds; (c) `RightIsWaivable` returns false for all 13 rights; (d) secession initiation + 21d cooling (Cover-active) + lien audit + covenant clearance + completion; (e) secession rejected before cooling expires; (f) secession rejected with outstanding liens; (g) Stand→Pier escalation at >10M Grain-cents annual Pass volume; (h) Stand declines Pier invitation (soft upgrade); (i) Pier selection by Guild Council; (j) Pier selection revoked by Cover Pool supermajority + Counsel. +7. **Lexicon + locked-const regression** — `x/cover/types/types_test.go` extended with `AntiCaptureBillOfRightsCount=13` + 13 `Waivable*` consts all false. `x/stand/types/types_test.go` extended with `StandPierEscalationAnnualPassVolumeCents=10000000`. Lexicon assertion on new Msg* names. +8. **Coverage ≥80%** on the extended `x/cover` (Bill of Rights + Pier Index) + `x/guild` (secession) + `x/stand` (Pier boundary) surfaces. + +--- + +## Phase P6 — Final Review + Audit + Milestone Ship + +- **Type**: final (REVIEW + AUDIT + milestone SHIP) +- **Tag**: `v0.6.6` (= v0.7 milestone release per D-008) +- **REQs**: all REQ-046..REQ-066 marked complete +- **Personas**: lead-developer (review + audit + ship), ci-security-auditor (REACTIVATED — feature purity gate + pen-test), backend-engineer (P1+ fixes if review flags), security-engineer (P1+ fixes if review flags) + +### P6 Must-Haves + +1. **`ciagent-review`** — multi-persona code review across P1..P5. Reviews all changes in `milestone/v0.7-fraternal-groups`. Auto-applies P0 fixes, flags P1+ for post-hoc review. If P1+ issues found: fix in P6. +2. **`ciagent-audit`** — reconstruction test (git log matches `.ciagent/` files), `.ciagent/` file discipline, branch hygiene, commit discipline. +3. **Feature purity gate** — no breaking schema changes to EXISTING locked consts; G-003 production firewall intact; G-006/G-028 go.mod diff EMPTY; lexicon firewall green (4 meta-tests: x/, docs/, web/, cover/). The 11 new locked consts are net-new (not amendments). +4. **§7 acceptance criteria verified**: + - ≥1 Cover Pool live on testnet with reserve enforcement + Standing gate + category tagging (simtest-grade — P1+P2) + - ≥1 Parent Guild with Chapter in secession-eligible formation with good-standing liens declared at founding (P3) + - ≥1 Mutual Aid Bond issuance with Cover-Call coupon settlement + use-of-proceeds lock to reserve build-out (P4) + - Anti-Capture Bill v0.2 reviewed by bonded Counsel (simtest — the Counsel review is a `MsgCounselReviewBillOfRights` handler; "bonded" = the Counsel's Standing bond is staked) + - **pen-test ≥1 independent third party** — at full autonomy with no external third party available, run self-administered adversarial review (ci-griller persona) and log as assumption (oy-state §7 remaining-open item 4). The ci-griller red-teams the Anti-Capture Bill + Anti-Crowding-Out firewall + MAB use-of-proceeds lock + secession cooling + Voucher slashing. + - high/critical findings remediated (the ci-griller's binding P0 fixes are applied in P6; P1+ flagged for post-hoc review) +5. **`ciagent-ship` (milestone ship)** — merge `phase/06` → `milestone/v0.7-fraternal-groups` → `main`. Tag `v0.6.6` (= v0.7 milestone release). Create release with full milestone summary. Delete all milestone branches (local + remote). +6. **Milestone completion** — REQUIREMENTS.md marks REQ-046..REQ-066 complete. ROADMAP.md marks v0.7 complete. Commit `docs(milestone): complete v0.7-fraternal-groups-foundation`. Clear CHECKPOINT.json. + +--- + +## User-Facing Surface + +(MVP/UX CHECK section 1 of 3 — per run.md MVP/UX CHECK gate) + +v0.7 is a protocol milestone with NO user-facing UI surface (the v0.6 web UI is complete; v0.7 does not touch `web/`). The user-facing surface for v0.7 is the **simtest** — the `x/cover/keeper/msg_server_simtest_test.go` file is the executable demonstration that a Cover Pool can be launched, a Charter signed, a MAB issued, a Cover Call adjudicated, and a Chapter seceded. The simtest IS the "user-facing surface" for a protocol milestone: it's the artifact a developer reads to understand the Cover Pool lifecycle. + +- **CLI flag**: none (no `oyd` daemon exists; D-020 continues). The simtest is run via `go test ./x/cover/keeper/...`. +- **README quickstart**: the v0.7 milestone adds a section to `docs/reference/` (lead-developer territory, not v0.7 scope — docs-content is deactivated per PERSONAS.md; the ARCHITECTURE.md v0.7 section is the reference). The simtest is the quickstart. +- **Docs**: `.ciagent/oy/ARCHITECTURE.md` v0.7 section (the component index + cross-component dependencies + locked-const additions) is the developer-facing reference for the Cover Pool surface. +- **`.feature` Scenario**: the simtest functions are named as scenarios: `TestCoverPoolLaunch_ValidStanding`, `TestCoverPoolLaunch_BelowStandingGate_Rejected`, `TestMABIssuance_BreadCoupons_Rejected`, `TestSecession_21DayCooling_CoverActive`, `TestAntiCaptureBill_WaivedRights_Rejected`, etc. + +## Happy Path + +(MVP/UX CHECK section 2 of 3 — per run.md MVP/UX CHECK gate) + +The v0.7 happy path (end-to-end scenario, written BEFORE execute, verified by simtest in P6): + +1. **A Guild Council creates a Cover Pool** via `MsgLaunchCoverPool` for the Travel category (Phase 2). The Factory validates: reserve floor 1.5× (REQ-047), Standing gate Trusted 4.0 for the Pool Host (REQ-049), category Travel is in Phase 2 (REQ-065). The Watcher attests the launch. The Pool is live (simtest-grade). +2. **The Pool Host signs a Cover-Charter** via `MsgSignCoverCharter` with a Statement-of-Beliefs hash, a dispute path, a 30-day holding period, and a Watcher witness. The Charter is distinct from the Guild's governance charter. The protocol does NOT parse the SoB content (FR-CHTR-5). The Anti-Capture Bill of Rights is non-waivable — the Charter's `WaivedRights` field is empty (REQ-056). +3. **Pool-eligible Masons elect 3 Masons to the Pool Council** via `MsgElectPoolMason`. The Pool Council = Pool Host + 3 elected + Watcher observer. No Anchor seat (§5). No MAB-holder seat (REQ-063). +4. **Cover-Fees are routed to the Pool** via `MsgRouteCoverFee` with a `CoverFeeTag{CategoryTag: "Travel", PoolID: "pool-1"}`. The Anti-Crowding-Out firewall (D-079) checks the routing path — the fee goes to the Pool's contributor-pool reserve, NOT to Root-Pool operating expenses. The reserve floor check passes (1.5×). The category-tag matches the Pool's allowed categories (FR-COVER-11). +5. **The Pool issues a Mutual Aid Bond** via `MsgIssueMAB` with `CouponKind: CouponDenomCoverCall`, `PrincipalGrain: 50000000`, `UseOfProceedsTag: "reserve_build_out"`. The issuance ceiling check passes (`sum(existing MAB principal) + 50M <= 3 × AnnualSurplus`). The coupon rate is bounded by `CouponCapBps=800` (8%). The proceeds are tagged for reserve build-out (D-080). +6. **The MAB proceeds are released** via `MsgWitnessMABProceedsRelease` — the Watcher quorum (6-of-9) witnesses the release. The proceeds move from the tagged staging account to the Pool's reserve account. If the proceeds were routed elsewhere, the auto-Still would fire (simtest tests this in a negative case). +7. **A Cover Call is filed** via `MsgFileCoverCall` — a Holder files a Cover Call against the Travel Pool. A Cover Claims Voucher is assigned (bond 10× avg Call size). The Voucher is NOT the claimant (FR-CPCV-2 no self-adjudication). The Voucher adjudicates the Call. If the Voucher commits fraud, they are slashed via `x/standing.Slash` with `SlashReasonFraudulentCoverCall` — the Standing bucket drops, disqualifying them from other Pools (cross-Pool applicability). +8. **A Parent Guild's Chapter secedes** — the Chapter was founded with `SecessionTerms{CoolingCoverActiveDays: 21, LienAuditRequired: true, CovenantClearanceRequired: true}` + a good-standing lien secured at founding. The Chapter initiates secession via `MsgInitiateSecession`. After 21 Mesh-days (Cover-active), the lien audit passes, the Cover Call / Bond covenants are cleared, and the secession completes via `MsgCompleteSecession`. The Parent Guild Treasury receives pro-rata Cover-Fee settlement for in-flight Cover Calls. +9. **A Stand's annual Pass volume exceeds $100k** (10M Grain-cents) — the Stand is invited to the Hub API via `MsgEscalateStandToPier`. The Stand accepts the Pier invitation. The Stand→Pier boundary is a soft upgrade, not a ban. +10. **The Pool dissolves** — the Pool Council (Host + 3 elected + Watcher observer, MAB holders excluded) votes to dissolve. The `PoolDissolutionWaterfall` pays: Cover-Fee contributors first, MAB holders second, Bread holders third (FR-MAB-4 seniority). MAB holders have NO Voice in the dissolution decision (REQ-063). + +This happy path is verified by the P6 simtest suite. The simtest is the executable spec. + +## UX Acceptance Criteria + +(MVP/UX CHECK section 3 of 3 — per run.md MVP/UX CHECK gate) + +The v0.7 deliverable MUST meet these explicit criteria (verified in P6 audit): + +1. **`go build ./...` + `go test ./...` GREEN** — all packages (v0.1-v0.6 baseline + v0.7 `x/cover` + extensions). No FAIL. The simtest is the executable demonstration. +2. **`x/cover` module exists with the full Cover surface** — Factory + firewall + floors + gates + tagging (P1) + Charter + governance + staging (P2) + Bill of Rights + Voucher + Pier Index (P5). Layout mirrors `x/hub` (D-039 precedent verified at `x/hub/types/types.go:33-57`). +3. **Anti-Crowding-Out firewall operational** — `x/cover/firewall/` subpackage rejects any code path routing Cover-Fees outside contributor-pool semantics; `lexicon_meta_cover/` meta-test rejects doc drift. 4 lexicon meta-tests green (x/, docs/, web/, cover/). Defense in depth (D-079). +4. **11 new locked consts in place + regression tests** — all 11 consts from the v0.7 const firewall additions table, with regression tests asserting their values. No existing locked consts amended. +5. **MAB coupons NEVER Bread** — `CouponDenomBread` rejected at `ValidateBasic` (FR-MAB-3). The simtest `TestMABIssuance_BreadCoupons_Rejected` passes. MAB issuance ceiling 3× annual surplus enforced at keeper (`TestMABIssuance_AboveCeiling_Rejected` passes). +6. **Anti-Capture Bill of Rights = 13 rights, non-amendable, non-waivable** — `RightIsWaivable` always returns false; Charter `WaivedRights` field rejected at `ValidateBasic` (REQ-056). `AntiCaptureBillOfRightsCount=13` regression test passes. D-085 (13th right) logged as assumption with `RightNonParticipationNoDenial` candidate if PO did not rule before P5. +7. **Coverage ≥80%** on `x/cover` + all extensions (`x/bond`, `x/guild`, `x/standing`, `x/stand`). +8. **G-003 production firewall intact** — `x/cover` references `x/standing`/`x/watcher`/`x/bond`/`x/still` via `expected_keepers.go` shims; no struct imports across `x//types`. Verified by the lexicon_meta + a G-003 regression test. `x/pact.PactCover` stays as cross-reference (D-084). +9. **G-006/G-028 go.mod diff EMPTY** — no new Go deps; `x/cover` uses existing cosmos-sdk v0.50.8 + ibc-go v8.2.1. `git diff v0.5.6..v0.6.6 -- go.mod` shows no new require lines. +10. **Pen-test (self-administered adversarial review via ci-griller)** — the ci-griller red-teams the Anti-Capture Bill + Anti-Crowding-Out firewall + MAB use-of-proceeds lock + secession cooling + Voucher slashing. High/critical findings remediated in P6; P1+ flagged for post-hoc review. Logged as assumption per oy-state §7 remaining-open item 4. +11. **§7 acceptance criteria met** — ≥1 Cover Pool live (simtest), ≥1 Parent+Chapter secession-eligible (simtest), ≥1 MAB issuance (simtest), Anti-Capture Bill reviewed by bonded Counsel (simtest `MsgCounselReviewBillOfRights` handler), pen-test complete (self-administered), high/critical remediated. \ No newline at end of file