docs(P00): complete pre-execution phase — v0.3 Bearers & Documentation

Phase 0 complete: SPECIFY -> CLARIFY -> RESEARCH -> IDEATE -> PLAN -> GRILL.
v0.3 milestone (feature type, tags v0.2.x) established. Bundles Bearers
skeleton (D-020 pattern) + docs site for nomads/freeholders + REQ-012
firewall extension to docs. 13 clarifications (D-034..D-046), 8 ideation
ideas ratified (IDEATE-01..08 -> REQ-010/REQ-022..REQ-028), 50-task plan
across P1-P6, 4 grill binding decisions (G-011..G-014).

---ci---
project: oy
phase: 0
milestone: v0.3
status: complete
tag_base: v0.2.x
milestone_type: feature
phase_role: pre_execution
requirements:
  covered: []
  partial: []
---/ci---
This commit is contained in:
2026-08-17 22:06:50 +00:00
parent 47fa79148c
commit 8248eb09e3
10 changed files with 1625 additions and 160 deletions
+7 -9
View File
@@ -1,14 +1,12 @@
{
"phase": 5,
"stage": "complete",
"milestone": "v0.2",
"phase": 0,
"stage": "grill",
"milestone": "v0.3",
"milestone_type": "feature",
"tag_base": "v0.1.x",
"phase_role": "final",
"tag_base": "v0.2.x",
"phase_role": "pre_execution",
"project": "oy",
"attempts": 0,
"updated_at": "2026-08-17T22:00:00Z",
"milestone_complete": true,
"milestone_release_tag": "v0.1.5",
"release_id": 732
"updated_at": "2026-08-17T23:30:00Z",
"milestone_complete": false
}
+2 -2
View File
@@ -6,9 +6,9 @@
}
],
"active_project": "oy",
"milestone": "v0.2",
"milestone": "v0.3",
"milestone_type": "feature",
"tag_base": "v0.1.x",
"tag_base": "v0.2.x",
"autonomy": {
"level": "full",
"escalation_hooks": ["deploy", "delete_data", "merge_to_main"],
+127 -1
View File
@@ -57,4 +57,130 @@ Fee Covenant (13) blocks {Pacts (8), Orgs (10), Partners (11), Bearers (12)}
## Phase 0 Architecture Deliverables
- This index file
- Persona assessment (created during RESEARCH stage)
- Phase plans (created during PLAN stage)
- Phase plans (created during PLAN stage)
---
## v0.3 Architecture (Bearers & Documentation)
This section appends the v0.3 component map to the v0.1/v0.2 index above. It does
NOT rewrite or supersede the earlier content; the Phase 1/2/3 columns in the
component index above describe the *full* runtime target, while the v0.3 columns
below describe the *v0.3 skeleton+tests* deliverable (D-020 pattern continued,
D-035) plus the documentation deliverable (D-042).
### v0.3 Component Index (new + extended modules)
| # | Component | Vision § | v0.3 Module | New/Ext | Phase | v0.3 Skeleton Depth |
|---|---|---|---|---|---|---|
| 2 | Cross-Chain & Exit (Layer 3) — DEX swaps | §7 | `x/exit` | New | P4 | ExitRoute + DEXSwap types, ExitStatus enum |
| 2 | Cross-Chain & Exit (Layer 3) — L2↔L1 bridges | §7 | `x/bridge` | New | P4 | BridgeRoute + BridgeStatus enum; references x/satellite L2Chain by ID (G-003) |
| 12 | Bearers expansion (OY-SAT + OY-QR) | §14 | `x/bearers` | Extended | P4 | OYSATLink + OYQRCode transport types (BearerTransport impls); BearerType enum already complete from v0.2 |
| 11 | Anchors (institutional Partner tier) | §13 | `x/partner` | Extended | P4 | AnchorCredential struct fields on the Anchor tier (REQ-018 enum unchanged); ListByTier(Anchor) round-trip |
| 8 | Hub API (Pact #6 expanded) | §13, §16 | `x/hub` | New | P5 | HubService enum (Custody/LendingPrimitive/Compliance) + per-service struct stubs + keeper stub |
| — | Services (Care/SIM/Vault/Mail) | §13 | `x/services` | New | P5 | ServiceKind enum (4) + per-service struct stubs + keeper stub |
| 8 | Bond market depth (Growth Bonds + secondary) | §17 | `x/bond` | Extended | P5 | GrowthBond struct + SecondaryOrder types; 8%/0% consts (D-028) unchanged; Clamp reused |
> The Hub API is Pact #6 (Hub-API) per REQ-020/D-027. v0.2 stubbed it as a PactType
> enum value inside `x/pact`; v0.3 promotes it to its own `x/hub` module for the
> B2B type scaffold (D-039). The `x/pact` HubAPI enum value stays as a
> cross-reference; `x/hub` owns the service-shape types.
### v0.3 Cross-Component Dependencies (within v0.3)
Per the v0.2 G-003 invariant (by-ID-string inter-module references; no struct
imports across `x/<module>/types`), v0.3 components reference each other and the
v0.2 baseline by ID string only. The dependency edges that affect v0.3 phase
ordering:
```
x/bridge ──(L2Chain by id)──► x/satellite (v0.2 baseline; ref only, no struct import)
x/exit ──(BridgeRoute by id)──► x/bridge (P4: exit references bridge routes)
x/hub ──(Anchor by id)──► x/partner (P5: Hub custody/compliance references Anchor partners)
x/bond ──(Stand by id)──► x/stand (v0.2 baseline; GrowthBond issuer-stand-id, unchanged)
x/services ──(Window by id)──► x/window (v0.2 baseline; service-grant references a Window)
x/bearers ──(BearerTransport)──► (none; OY-SAT/OY-QR are transport stubs, no new deps)
```
**Phase-ordering implication (informs D-044):** `x/exit` references `x/bridge`
routes, so both must land in the same phase (P4) and `x/bridge` types must exist
before `x/exit` tests that reference a BridgeRoute. `x/hub` references Anchor
partner-ids, so `x/partner` Anchor extension (P4) must precede `x/hub` (P5). This
confirms the D-044 P4→P5 split: P4 = exit/bridge/bearers/partner-Anchor,
P5 = hub/services/bond. Reversing P4/P5 would force `x/hub` to reference an Anchor
tier that does not yet exist.
### v0.3 Interface Contracts (6 cross-component — unchanged from v0.2)
The six cross-component interfaces (Standing API, Forge/Fold, Watcher Attestation,
Window Lifecycle, Fee Covenant, Voice/Council) are NOT extended in v0.3 — v0.3
adds *type scaffolds* that will *consume* them at runtime in v0.4+:
- **Window Lifecycle Interface** — `x/services` service-grants reference a Window
by ID (the service opens a Window on the holder's behalf). Skeleton only.
- **Fee Covenant Interface** — `x/bridge`/`x/exit` exit routes carry an
`exit-fee-bps` field clamped by the Fee Covenant ceiling/floor (the field is
typed in v0.3; the Clamp is NOT invoked in the skeleton — deferred to v0.4
runtime to avoid cross-module calls in the skeleton layer).
- **Standing API** — `x/hub` compliance service stub references a partner's
Standing by reach-id (skeleton: by-ID-string field, no query).
- **Watcher Attestation** — `x/bridge` BridgeStatus has an `Attested` state; the
attestation itself is not modeled in v0.3 (Watchers are v0.1 baseline; the
bridge references a Watcher quorum by ID at runtime, deferred to v0.4).
### Documentation Architecture (v0.3 deliverable B)
v0.3 introduces a documentation deliverable alongside the Bearers skeleton. This
is a NEW architecture surface (no docs site existed in v0.1/v0.2).
**Layout:**
```
oy/
├── README.md # repo-root project overview (lexicon-clean)
├── mkdocs.yml # MkDocs Material config (site_name, nav, theme)
└── docs/
├── nomads/ # audience: nomads (Reach path, Stash, bearers, Maps/Pay, Pacts, standing basics)
├── freeholders/ # audience: freeholders (4 signals, Bayesian Standing, Stands/Guilds, Councils/Voice, Bonds, Partner spectrum)
├── shared/ # cross-audience (Six Principles, Bread Scale, Storage pools, Watchers/Mirror, Lexicon glossary, Vision overview)
└── reference/ # architecture index + component map
```
**mkdocs.yml (minimal config):** `site_name: OpenYield`, `theme: readthedocs` or
`theme: material` (D-042 chose Material), `nav:` with the four audience
sections, `markdown_extensions: [admonition, toc, pymdownx.superfences]`. Build-
only Python dep (`mkdocs` + `mkdocs-material`); `go.mod` stays zero-dep (G-006 —
the docs toolchain is NOT a Go dependency). No publishing CI in v0.3 (D-046);
README documents `mkdocs serve` / `mkdocs build`.
**Audience-organized nav (D-042, D-045):** nomads 5-8 pages, freeholders 5-8
pages, shared 5-6 pages, reference 2 pages (~20-25 total). Pages map to REQs:
nomads cover REQ-007/013/014/015/019/020; freeholders cover REQ-005/006/016/017/
011/021/018; shared covers REQ-001/003/004/012; reference covers the architecture
index.
**Lexicon-clean by construction (REQ-012 extension, D-043):** docs are user-
facing and must be lexicon-clean. The highest-risk banned term in docs is
"yield" (PROJECT.md uses "real yield" but docs must say "real production" / "real
return" — the word-boundary regex in `lexicon.FindBannedTerm` bans standalone
"yield" while allowing "OpenYield"). Other high-risk terms in docs: "account"
(use "Holder"/"Reach"), "bank"/"deposit"/"savings" (use "Stash"/"Vault"/
"Root-Pool"). The firewall lands in P1 BEFORE content (P2/P3) so docs are checked
as authored (D-044 firewall-first ordering).
**Firewall extension (D-043):** a NEW sibling test `lexicon_meta_docs_test.go`
(package `lexicon_meta_docs`) mirrors `lexicon_meta_test.go` (package
`lexicon_meta`) exactly — same `lexicon.FindBannedTerm`, same word-boundary
regex, same fragment-assembled self-test table, same self-exclusion of the meta-
test file — but scans `README.md` + `docs/**/*.md` instead of `x/**/*.go`. The
existing `lexicon_meta_test.go` is NOT modified (preserves v0.2 coverage). The
new meta-test walks the repo root for `README.md` + the `docs/` tree, excludes
`.ciagent/` and `.git/` (firewall meta-files are not user-facing docs), and
excludes itself. Per-package lexicon assertions in the new `x/*` modules follow
the v0.2 pattern (`TestLexiconNoBannedTermsIn<Module>Package` scanning the
module's production `.go` files).
> The `.ciagent/` directory holds firewall META-files (PROJECT.md, RESEARCH.md,
> this file) that discuss the banned terms by name for governance reasons — they
> are NOT user-facing docs and are explicitly excluded from the docs firewall
> scan. This mirrors how `lexicon_meta_test.go` excludes itself: the firewall's
> own code is allowed to name the terms it bans.
+135 -1
View File
@@ -181,4 +181,138 @@ Per-axis verdicts:
Binding decisions: 10 (G-001..G-010)
Escalations: 0
Overall: SHIP Phase 0 with binding changes (confidence 0.83)
```
```
---
## v0.3 Grill (Phase 0)
> **Reviewer**: CIAgent adversarial grill (red-team, full autonomy)
> **Date**: 2026-08-17
> **Target**: v0.3 Phase 0 artifacts (PROJECT.md D-034..D-046, ROADMAP.md v0.3 table, REQUIREMENTS.md REQ-010/022..028, ARCHITECTURE.md v0.3 section, PERSONAS.md v0.3 roster, RESEARCH.md A-301..A-315, PLANS.md v0.3 plan 50 tasks P1-P6) + v0.1/v0.2 codebase baseline
> **Milestone**: v0.3 — Bearers & Documentation
> **Autonomy**: full (decision_confidence_threshold = 0.60)
> **Mode**: multi-project (slug `oy`)
### Evidence baseline (verified against the actual repo, not the docs)
- `go.mod`: `module github.com/oy/openyield`, `go 1.22`, **zero dependencies** (confirmed — no require lines).
- `x/` modules: **25** (confirmed via `ls x/ | wc -l`). v0.1 = 15 + v0.2 added 10 = 25. v0.3 adds 4 new (exit/bridge/hub/services) + extends 3 (bearers/partner/bond) = 29 distinct after v0.3. PLANS.md P6-01-01 says "29 packages" — correct.
- Test functions: **299** `func Test*` across **23** test files (counted `grep -rn "^func Test" x/ | wc -l`). v0.2 grill G-001 corrected to 53/11; v0.2 added ~246 more. The v0.3 plan's "~303" reference (REQUIREMENTS IDEATE notes) is close to current 299 — minor, not material.
- `lexicon/lexicon.go`: `BannedTerms()` returns **10** (verified `if len(terms) != 10` at lexicon.go). The v0.2 `lexicon_meta_test.go` header comment still says "9 banned terms" (line 7) — a **pre-existing v0.2 documentation defect**, not v0.3's, but the v0.3 docs firewall must use 10 (it does — P1-01-01 says exactly 10). No v0.3 binding needed; note for v0.2 housekeeping.
- `lexicon_meta_test.go` EXISTS at repo root, package `lexicon_meta`, with the **G-009 self-test table** (synthetic strings, `len(synthetic) != len(terms)` guard). The self-test verifies **detection** but does NOT verify the **walk** (which files are scanned). The v0.3 docs firewall inherits this gap — G-013 below.
- G-003 import-invariant test EXISTS: `x/window/types/types_test.go:431-456` uses `go/parser` (ImportsOnly) to scan all non-test `.go` under `x/` and assert no cross-`x/<module>/types` struct imports. **Confirmed production code is cycle-free** (`grep -rn "openyield/x/" x/ --include="*.go" | grep -v "_test.go"` returns empty). The v0.3 by-ID-string refs (exit→bridge, hub→partner, services→window) will be auto-covered by this existing test — no new G-003 work needed in v0.3 (P4/P5 test tasks correctly say "G-003 import-invariant green" not "add a new one").
- `x/bond/types/types.go`: `CouponCapBps = 800`, `CouponFloorBps = 0`, `func Clamp(couponBps uint32) uint32` all exist. The D-028 regression firewall is real and the v0.3 GrowthBond extension reuses the same package (no G-003 concern, correct).
- `x/partner/types/types.go`: `TierAnchor PartnerTier = "Anchor"` exists; no `AnchorCredential` yet (v0.3 P4 adds it). The 4-tier enum is locked — P4 extension adds a struct, not a tier. Correct.
- `x/bearers/types/types.go`: `BearerOYSAT` and `BearerOYQR` are ALREADY in `AllBearers()` (lines 20-21, 39-40) since v0.1; `BearerTransport` interface + `OYLRLink` + `SurveillanceResistant` exist since v0.2. P4 adds `OYSATLink`/`OYQRCode` transport structs only — `AllBearers()` count (6) stays unchanged. Correct.
- `x/window`, `x/stand`, `x/satellite` (L2Chain/TransferChannel), `x/watcher`, `x/identity` (Reach) all exist as v0.1/v0.2 baseline — the v0.3 by-ID-string refs to them (bridge→satellite/watcher, services→window/identity, bond→stand) have real targets. No phantom refs.
- **No `docs/`, no `README.md`, no `mkdocs.yml` exist** today. The firewall-first ordering is clean: `lexicon_meta_docs_test.go` passes vacuously with zero docs to scan (no hits possible). The "chicken-and-egg between firewall test and README" risk raised in the grill brief is a **non-issue** — verified by walk logic (zero files = zero hits).
These baseline facts confirm the v0.3 plan's architecture and ordering claims against the actual codebase, not just the docs. The plan is unusually well-grounded; the binding decisions below are mostly small correctness fixes, not scope rework.
### Per-Axis Verdicts
#### Axis 1 — Feasibility (50 tasks / 6 phases at full autonomy) — **PASS** (confidence 0.82)
50 tasks across 6 phases is large but proportionate to the deliverable: 26 docs pages (P1-P3) + 7 x/* packages (P4-P5) + audit/ship (P6). v0.2 shipped 31 tasks / 5 phases for 10 packages at full autonomy and closed clean (per REQUIREMENTS.md v0.2 summary). v0.3 adds the docs surface (a genuinely new artifact type) and 4 new + 3 extended Go packages. The docs phases (P1-P3) are low-risk Markdown authoring gated by a Go firewall; the Bearers phases (P4-P5) are pure skeleton+tests, the proven v0.1/v0.2 pattern. No phase exceeds 12 tasks (P3 is largest at 12, all docs). The firewall-first claim is achievable: a firewall that scans zero files passes trivially (verified — no docs exist yet). Reject the "50 tasks is too many" hypothesis — it matches the deliverable surface.
#### Axis 2 — Scope (Bearers + docs bundle, ~22 pages) — **PASS** (confidence 0.78)
D-034 (bundle Bearers + docs under one feature milestone) is defensible: the user's `--ideate` request was docs-only, but ROADMAP Phase 3 (Bearers) is the next queued feature work; bundling keeps the milestone cadence and avoids a docs-only NFR milestone that would not advance the protocol. The alternative (separate v0.3 docs NFR + v0.4 Bearers) would split a coherent unit of work into two milestones and delay the Bearers skeleton a full cycle. The ~20-25 page docs depth (D-045) is bounded — not gold-plating; each page maps to a REQ (REQUIREMENTS.md IDEATE traceability table). The one scope concern: the **mkdocs.yml nav in RESEARCH §2.1 is missing 2 pages** the plan creates — `nomads/window.md` (P2-01-07) and `freeholders/anchor-preview.md` (P3-01-07). This is a documentation/plan inconsistency, not a scope defect — **binding fix G-011** requires the nav to list all created pages. Confidence holds.
#### Axis 3 — Cost (MkDocs Material, firewall extension) — **PASS** (confidence 0.85)
MkDocs Material is the right cost: Markdown-native (docs-writer authors `.md`, not YAML/HTML), build-only Python dep that does NOT touch `go.mod` (verified zero require lines; G-006 holds). Plain-Markdown-no-generator would be cheaper but loses nav/search/theme — for a user-facing docs site for nomads/freeholders, Material's search + audience nav is real value, not gold-plating. The firewall extension (D-043: a whole new sibling test `lexicon_meta_docs_test.go` + self-test table) is more than "could review manually" — manual review is not durable; the sibling test is the firewall that keeps the docs site lexicon-clean over time (the top risk per Axis 5). The cost is justified. Reject the "firewall is over-engineered for docs" hypothesis — REQ-012 is `All` phases and docs are user-facing; a manual review would rot.
#### Axis 4 — Technical soundness (by-ID-string refs, ClampGrowth, LendingCouponCapBps) — **CONDITIONAL** (confidence 0.72)
The by-ID-string refs (G-003) between bridge/exit/partner/hub/services are cycle-free by construction (verified: the existing G-003 import-invariant test in `x/window/types/types_test.go` scans all non-test `x/**/*.go` and will auto-cover the v0.3 files; production code has zero cross-`x/` imports today). The `x/hub` `LendingCouponCapBps = 800` LOCAL const (A-304) is a real invariant — it's a local copy cross-documented to D-028, exactly mirroring how v0.2 `x/guild` cross-docs `x/feecovenant.WaiverHandPassGuild` (verified pattern). The one technical defect: **`ClampGrowth(currentBps, growthBps uint32) uint32` as specified in RESEARCH §1.7 / PLANS P5-03-01 returns `min(CouponCapBps - currentBps, growthBps)`, which underflows when `currentBps > CouponCapBps`** (uint32 subtraction wraps to a huge value, then `min` picks `growthBps` — wrong) or when `currentBps == cap` (returns 0, correct) but is fragile. The invariant "post-growth coupon ≤ 800" only holds if the caller guarantees `currentBps ≤ cap`. The spec does not state this precondition, and a GrowthBond whose current coupon is already at cap would silently allow unbounded growth via the `growthBps` path if the helper is misused. **Binding fix G-012** requires `ClampGrowth` to guard `currentBps > CouponCapBps` explicitly (return 0 or error) so the invariant holds unconditionally. Confidence holds after the fix.
#### Axis 5 — Risk (lexicon drift, "yield" in docs) — **CONDITIONAL** (confidence 0.74)
The top risk is correctly identified: "yield" is banned as a standalone word but "OpenYield" is safe (word-boundary regex, verified `TestLexiconMetaNoFalsePositiveOnOpenYield`); PROJECT.md uses "real yield" but docs must say "real production"/"real return". The firewall-first ordering (D-044: P1 firewall before P2/P3 content) is the correct mitigation — a banned term slipped into a P2 nomads page fails the P2 build, not the P6 review. The firewall extension (D-043) is sufficient to CATCH drift at build time. The gap: the firewall does not PREVENT the docs-writer from authoring a banned term in the first place — it fails the phase build, requiring a rewrite. For 26 pages this is acceptable (the failure is loud and local); for 100+ pages it would be painful. At the v0.3 scale, the firewall is sufficient. The deeper risk: **the docs firewall self-test table (G-009 for docs) verifies DETECTION but not the WALK** — if the walk logic misses `docs/nomads/` (e.g., a path-prefix bug), the self-test still passes (it tests `FindBannedTerm` on synthetic strings, not the file walk). **Binding fix G-013** requires the docs firewall to include a walk-coverage assertion: a test that injects a synthetic banned-term `.md` into a temp `docs/` subtree (or uses a fixture) and asserts the walk FINDS it. Without this, the docs firewall could silently scan zero files and report green. Confidence holds after the fix.
#### Axis 6 — Dependency (intra-P4, P4→P5, hidden edges) — **PASS** (confidence 0.80)
The intra-P4 edge (bridge→exit) and the P4→P5 edge (partner-Anchor→hub) are the only v0.3-internal ordering constraints, and both are correctly handled (P4 Wave 1 = bridge before exit Wave 2; P4 before P5 for Anchor→hub). The RESEARCH §3 cross-component dependency list is complete for the v0.3 surface. Verified the "hidden edges" raised in the grill brief:
- **Does x/services need x/window types?** Yes, by-ID-string (`window-id` field) — but x/window is v0.2 baseline, already shipped. Not a v0.3 phase-ordering concern. Correctly noted in RESEARCH §3.
- **Does x/bond GrowthBond need x/anything?** No — GrowthBond embeds the v0.2 Bond (same package, `x/bond/types`), and `ClampGrowth` reuses the same-package consts. No G-003 concern. Correct.
- **Does x/hub need x/bond?** No — it uses a LOCAL const `LendingCouponCapBps = 800` (A-304) to avoid the import. Correct (verified pattern matches v0.2 guild/feecovenant).
- **Does x/exit need x/bread?** No — `amount-grain` is int64, "Grain" by name only (P4-02-01 explicitly says "NOT a `x/bread` import"). Correct.
No hidden edges. The P5 "no intra-phase ordering" claim (hub/services/bond independent) is correct — they reference only v0.1/v0.2 baseline modules by ID-string, not each other.
#### Axis 7 — Testing (≥80% on skeletons, docs phases no Go coverage) — **CONDITIONAL** (confidence 0.70)
≥80% coverage on skeleton type packages is achievable but borders on coverage theater (testing getters/constructors/enum-round-trips on trivial types). v0.2 hit ≥95.9% on 8 of 10 packages at this bar, so it's not theater in practice — the locked-const + invariant + lexicon assertions carry real regression value. The plan correctly applies the ≥80% bar only to the 7 x/* packages (P4/P5), NOT to the docs phases (P1-P3 produce no Go code except the firewall test, which is itself the coverage). The one gap: **P1-01-01 (the docs firewall) and P4/P5 test files have no explicit coverage target** — the firewall test's own coverage is not asserted. A firewall test that scans zero files (walk bug) would still have high coverage on its detection logic. **Binding fix G-013** (walk-coverage assertion, from Axis 5) addresses this — the injected-fixture test forces the walk to actually execute. No separate coverage bar needed for docs phases. Confidence holds.
#### Axis 8 — Maintainability (docs lexicon over time, sibling test drift) — **CONDITIONAL** (confidence 0.72)
The docs site will stay lexicon-clean over time ONLY if the firewall runs on every change. D-046 defers publishing CI to v0.4, but the firewall is a `go test` — it runs locally and in any CI that runs `go test ./...`. The risk is not "no CI" (the firewall runs wherever `go test` runs) but "the sibling test `lexicon_meta_docs_test.go` drifts from `lexicon_meta_test.go`". D-043 chose a sibling (not an extension) to preserve v0.2 coverage — defensible — but two meta-tests sharing detection logic via the same `lexicon.FindBannedTerm` is good; sharing the self-test table by DUPLICATION (not by a shared helper) is the drift risk. If `lexicon_meta_test.go`'s self-test table is updated (e.g., a new banned term added) and `lexicon_meta_docs_test.go`'s copy is not, the docs firewall silently loses coverage. **Binding fix G-014**: the docs firewall's self-test table and banned-term count assertion should DERIVE from `lexicon.BannedTerms()` (which both already do for the count — good) and ideally share the synthetic-string table via a `lexicon` package helper rather than duplicating it. At minimum, both must assert `len(terms) == 10` from the single source `lexicon.BannedTerms()` so a count change breaks both. This is a low-severity maintainability note, not a blocker. Confidence holds.
#### Axis 9 — Adversarial (what makes v0.3 fail to ship) — **PASS** (confidence 0.78)
The four failure modes raised in the grill brief:
1. **Firewall blocks docs content mid-authoring** — MITIGATED by firewall-first (P1 firewall passes vacuously with zero docs; P2/P3 content fails fast and local, not at P6). Not a ship-blocker.
2. **By-ID-string ref breaks when a target module is renamed** — LOW. The targets (satellite/watcher/identity/window/stand) are v0.1/v0.2 baseline, locked. v0.3 does not rename them. The by-ID-string fields are opaque strings, not Go imports, so a rename would only break tests that hardcode the ID — caught at `go test`. Not a ship-blocker.
3. **MkDocs build fails on Gitea Pages** — NON-ISSUE for v0.3. D-046 explicitly defers publishing CI to v0.4; v0.3 ships the source + a `mkdocs build` invocation in the README. A Gitea Pages failure is a v0.4 concern, not v0.3's. Not a ship-blocker.
4. **Coverage drops below 80% on a skeleton package with trivial types** — MITIGATED. v0.2 hit ≥95.9% on 8/10 packages at this bar; the locked-const + invariant + lexicon assertions provide real coverage. The v0.3 packages (bridge/exit/hub/services) follow the v0.2 satellite/forex pattern that hit 100%. Not a ship-blocker.
The actual highest ship-risk is **ClampGrowth underflow (G-012)** if a test constructs a GrowthBond at cap and the helper misbehaves — but this is caught by the invariant test (post-growth ≤ 800) if the test exercises the cap boundary. **Binding fix G-012** makes the helper robust; the test must cover `currentBps == cap` and `currentBps > cap`. No escalation.
---
### Binding Decisions
These are **binding** — the orchestrator MUST apply them before P1 begins. Numbered G-011..G-014 (continuing from the v0.2 grill G-001..G-010).
| ID | Decision | Rationale | Confidence | Affects |
|----|----------|-----------|------------|---------|
| **G-011** | `mkdocs.yml` nav MUST list every page the plan creates. RESEARCH §2.1's sample `mkdocs.yml` is missing `nomads/window.md` (P2-01-07) and `freeholders/anchor-preview.md` (P3-01-07). P1-01-02 (mkdocs.yml authoring) must include all 26 pages in the nav (or the nav is incomplete at P3 ship). The nav may reference not-yet-existing pages at P1 (mkdocs.yml is config, not Go-tested) but must be complete by P3-03-01 ship. | The RESEARCH sample nav and the PLANS page list disagree by 2 pages. A stale nav ships a docs site with orphaned pages (created but not linked). | 0.85 | P1-01-02 (mkdocs.yml), P3-03-01 (ship verification — confirm nav matches all 26 created pages) |
| **G-012** | `x/bond` `ClampGrowth(currentBps, growthBps uint32) uint32` MUST guard `currentBps > CouponCapBps` explicitly (return 0, or document the precondition and assert it) so the "post-growth coupon ≤ 800" invariant holds unconditionally. The spec's `min(CouponCapBps - currentBps, growthBps)` underflows when `currentBps > cap` (uint32 wrap → huge value → `min` picks `growthBps` → invariant violated). The P5-03-01 test MUST cover `currentBps == cap` (returns 0) and `currentBps > cap` (returns 0 or is rejected) as explicit cases. | The spec'd helper has a uint32 underflow trap that breaks the stated invariant under misuse. The v0.2 `Clamp` has no such trap (it's a simple min/max); `ClampGrowth` adds the subtraction. A latent underflow in a locked-const firewall is a real defect. | 0.82 | P5-03-01 (ClampGrowth helper + invariant test) |
| **G-013** | `lexicon_meta_docs_test.go` MUST include a **walk-coverage assertion**: a test that places a synthetic banned-term `.md` in a temp/fixture `docs/` subtree (or uses an in-memory walk target) and asserts the walk FINDS it. The G-009 self-test table (which both firewalls share) verifies DETECTION (`FindBannedTerm` on synthetic strings) but NOT the WALK (which files are scanned). A walk bug (e.g., wrong path prefix, missing `docs/` recursion) would report green on zero files scanned. The walk-coverage test closes this gap. | The docs firewall's failure mode is "silently scans nothing and reports green" — undetectable by the self-test table alone. v0.3 has no docs today, so a broken walk passes trivially at P1 and would only surface when a real banned term slips into a real P2/P3 page AND the walk happens to miss that file. A walk-coverage test forces the walk to execute against a known-bad fixture. | 0.80 | P1-01-01 (lexicon_meta_docs_test.go) |
| **G-014** | `lexicon_meta_docs_test.go` and `lexicon_meta_test.go` MUST derive the banned-term count from the single source `lexicon.BannedTerms()` (both already assert `len(terms) == 10` from it — good; verified). The synthetic self-test table should ideally be shared via a `lexicon` package helper (e.g., `lexicon.SyntheticBannedStrings() []string`) rather than duplicated across the two meta-tests, so a future banned-term addition updates both firewalls from one place. If a shared helper is not added in v0.3, the two tables MUST be kept in sync by a comment cross-reference. | D-043 chose a sibling test to preserve v0.2 coverage — defensible — but two copies of the self-test table drift silently. A shared helper is the durable fix; a cross-reference comment is the minimum. | 0.70 | P1-01-01 (lexicon_meta_docs_test.go), optionally `lexicon/lexicon.go` (shared helper) |
---
### Escalations
**None.** All nine axes resolved at confidence ≥ 0.60 after the binding fixes G-011..G-014 are applied. No axis required escalation to the human. At full autonomy, the orchestrator applies the binding decisions and proceeds to P1.
---
### Overall Verdict
#### **SHIP Phase 0 with binding changes**
The v0.3 Phase 0 plan is fundamentally sound and unusually well-grounded: the architecture and ordering claims were verified against the actual codebase (25 x/* modules, zero deps, G-003 import-invariant test exists and is green, bond consts/Clamp exist, bearers/partner extension points exist, baseline modules for all by-ID-string refs exist). The firewall-first ordering is clean (firewall passes vacuously with zero docs — no chicken-and-egg). The scope (Bearers + docs bundle) is defensible, not over-scoped. The 50-task / 6-phase plan is proportionate to the deliverable surface (26 docs pages + 7 x/* packages).
The binding changes are **small correctness fixes**, not scope rework:
- **G-011** (mkdocs.yml nav completeness) — documentation/plan consistency.
- **G-012** (ClampGrowth uint32 underflow guard) — the single real technical defect; a latent invariant-breaking trap in a locked-const firewall.
- **G-013** (docs firewall walk-coverage test) — closes the "silently scans nothing" failure mode the G-009 self-test table does not cover.
- **G-014** (shared synthetic-string helper / cross-reference) — maintainability of the two sibling firewalls.
None of these rise to "rethink" or "reduce scope" — the architecture, scope, ordering, and persona assignments are correct. Apply the 4 binding decisions and proceed to Phase P1.
**Confidence in overall verdict: 0.80**
---
### Summary Block
```
Per-axis verdicts (v0.3):
1. Feasibility — PASS (0.82)
2. Scope — PASS (0.78) → strengthened by G-011
3. Cost — PASS (0.85)
4. Technical soundness — CONDITIONAL (0.72) → fixed by G-012
5. Risk — CONDITIONAL (0.74) → fixed by G-013
6. Dependency — PASS (0.80)
7. Testing — CONDITIONAL (0.70) → fixed by G-013 (walk-coverage)
8. Maintainability — CONDITIONAL (0.72) → fixed by G-014
9. Adversarial — PASS (0.78)
Binding decisions: 4 (G-011..G-014)
Escalations: 0
Overall: SHIP Phase 0 with binding changes (confidence 0.80)
```
+78 -81
View File
@@ -3,124 +3,121 @@ active_personas:
- id: backend-engineer
active: true
phase_specific: false
reason: Go/Cosmos module skeletons for v0.2 components — owns the non-Cosmos-mirroring modules (pact, partner, bond) per G-007. Owns the bulk of bespoke-type skeleton + tests work.
frameworks: [Go, Cosmos SDK, IBC, CosmWasm]
territory: ["x/pact/**", "x/partner/**", "x/bond/**", "x/**/types/**", "x/**/keeper/**", "x/**/module.go"]
constraints: [lexicon compliance (REQ-012), skeleton+tests pattern (D-020), ≥80% coverage on new packages (D-033), no live-chain side effects in skeleton, locked-const invariants, no fractional reserve, no leverage/futures, go.mod is read-only in v0.2 (G-006 — any change is an escalation)]
- id: data-engineer
active: true
phase_specific: false
reason: Genesis/state schema design for new modules — Window audit log, Stand membership sets, Bond issuance state, Council Voice tally state. Shapes ValidateGenesis upgrades. Owns genesis SCHEMA only (G-008); test assertions are security-engineer's.
frameworks: [Go, encoding/json, Cosmos SDK state]
territory: ["x/**/types/genesis.go", "x/**/genesis.go"]
constraints: [append-only audit logs (Window), ID-uniqueness in ValidateGenesis, lexicon compliance, no state identity beyond Reach, does NOT own *_test.go files (G-008)]
reason: Owns ALL Bearers skeleton Go modules in v0.3 (x/exit, x/bridge, x/bearers ext, x/partner ext, x/hub, x/services, x/bond ext). The v0.2 cosmos-engineer/security-engineer split is collapsed back into backend-engineer for v0.3 because the Cosmos-convention-alignment load is lower (no new IBC/governance/capability modules — x/bridge reuses the v0.2 satellite ICS-20 shape, x/hub is a fresh B2B scaffold). v0.3 is bespoke-type skeleton + tests work, which is backend-engineer's core territory.
frameworks: [Go 1.22 stdlib, Cosmos-style types (zero-dep)]
territory: ["x/exit/**", "x/bridge/**", "x/hub/**", "x/services/**", "x/bearers/**", "x/partner/**", "x/bond/**", "x/**/types/**", "x/**/keeper/**"]
constraints: ["zero external deps (G-006 — go.mod read-only)", "D-020 skeleton+tests pattern (D-035 continues)", "≥80% coverage on new/extended packages", "per-package lexicon assertion (REQ-012) in every new/extended test file", "by-ID-string inter-module refs (G-003 — no struct imports across x/<module>/types)", "locked-const invariants (HubService count, ServiceKind count, BridgeStatus count, ExitStatus count, Anchor credential fields)", "no live chain / no real IBC / no real bearer transports / no live B2B runtime"]
- id: lead-developer
active: true
phase_specific: false
reason: Multi-component orchestration across 10 new packages, dependency sequencing per D-031 blocker chain, vertical-slice integrity per phase.
reason: Coordinates the v0.3 phase decomposition (P1 firewall+docs foundation → P2 nomads → P3 freeholders → P4 Bearers I → P5 Bearers II → P6 review/ship), territory enforcement (warn mode per config.json), and final review. Owns the cross-component dependency finding (x/exit→x/bridge in P4; x/partner-Anchor→x/hub across P4→P5) that constrains phase ordering.
frameworks: [cross-cutting]
territory: ["**"]
constraints: [blocked-by chain enforcement (D-031), milestone versioning (v0.2 / tag_base v0.1.x), lexicon gate on merge, persona territory warn-mode enforcement]
territory: [".ciagent/**", "**"]
constraints: ["D-044 phase ordering (firewall-first; P4 before P5 for Anchor→hub dep)", "milestone versioning (v0.3 / tag_base v0.2.x)", "lexicon gate on merge (REQ-012 extends to docs/)", "persona territory warn-mode enforcement", "zero Go deps invariant (G-006); docs build-deps are allowed (D-042)"]
- id: cosmos-engineer
- id: frontend-engineer
active: true
phase_specific: true
reason: v0.2 introduces IBC (satellite), governance (council), capability (window), group (stand/guild), oracle (forex) patterns that map directly to Cosmos SDK modules (x/gov, x/group, x/authz, x/feegrant, x/capability, x/ibc-transfer). Phase-specific to v0.2 execution phases where Cosmos-convention alignment matters for future wiring.
frameworks: [cosmos-sdk, ibc-go, CosmWasm, CometBFT]
territory: ["x/satellite/**", "x/council/**", "x/window/**", "x/stand/**", "x/guild/**", "x/forex/**", "x/bearers/**"]
constraints: [lexicon compliance (REQ-012), no live-chain side effects in skeleton, mirror x/gov TallyResult / x/group DecisionPolicy / x/authz Grant shapes for future wiring, zero external deps in v0.2 skeleton, by-ID-string inter-module references to avoid import cycles (G-003 tested invariant), go.mod is read-only in v0.2 (G-006)]
reason: v0.3 introduces the docs site (REQ-027) — the first non-skeleton, non-Go deliverable since v0.1's Mesh Experience. frontend-engineer owns the docs territory (docs/**, mkdocs.yml, README.md) and the docs firewall test (lexicon_meta_docs_test.go). Phase-specific: ACTIVE only for P1-P3 (docs phases); removed after P3 once the docs site is complete and the Bearers skeleton phases (P4/P5) are pure Go.
frameworks: [MkDocs Material, Markdown]
territory: ["docs/**", "mkdocs.yml", "README.md", "lexicon_meta_docs_test.go"]
constraints: ["lexicon-clean by construction (REQ-012 extended to docs via D-043 — 10 banned terms must not appear in docs/*.md or README.md; 'yield' banned as standalone word, 'OpenYield' safe via word-boundary regex)", "audience-organized nav (nomads/freeholders/shared/reference per D-042)", "~20-25 pages total per D-045", "no publishing CI in v0.3 (D-046 — mkdocs.yml buildable locally only)", "mkdocs.yml is build-only Python dep; go.mod stays zero-dep (G-006)"]
removed_after: P3
- id: security-engineer
- id: docs-writer
active: true
phase_specific: true
reason: v0.2 enforces Mission Lock (council), fee/bond coupon clamps (clamp invariants), 9-stand / 4-tier / 6-pact locked-const tests, and Window revoke/expire lifecycle invariants. Phase-specific to v0.2 where invariant/locked-const test density is highest.
frameworks: [Go testing, table-driven tests, invariant tests]
territory: ["x/**/types/**_test.go", "x/**/keeper/**_test.go", "x/**/genesis_test.go", "x/**/*_test.go"]
constraints: [invariant tests for all locked constants (Mission Lock non-amendable, bond 8% cap / 0% floor, fee ceiling/floor), locked-const tests for every enum count (9 stands, 4 partner tiers, 6 pacts), lexicon assertion in every new test file (D-033), ≥80% coverage on new packages, owns ALL *_test.go files including genesis_test.go (G-008)]
reason: Custom persona for the docs content authoring load (REQ-027, D-045 ~20-25 pages across 4 audiences). Folded as a SEPARATE persona rather than into frontend-engineer because the skills differ: frontend-engineer owns the docs TOOLCHAIN (mkdocs.yml config, theme, nav structure, firewall test wiring) while docs-writer owns the CONTENT (the actual Markdown pages: nomads Reach/Stash/bearers pages, freeholders Standing/Bonds pages, shared Principles/Bread-Scale pages, reference architecture-index). Splitting keeps the toolchain-vs-content boundary explicit so a toolchain change does not entangle content review. Phase-specific: ACTIVE only for P1-P3; removed after P3.
frameworks: [Markdown, MkDocs Material (content authoring only)]
territory: ["docs/nomads/**/*.md", "docs/freeholders/**/*.md", "docs/shared/**/*.md", "docs/reference/**/*.md"]
constraints: ["lexicon-clean by construction (same REQ-012 extension — 'real production'/'real return' not 'real yield'; 'Holder'/'Reach' not 'account'; 'Stash'/'Vault'/'Root-Pool' not 'bank'/'deposit'/'savings')", "audience-organized (each page belongs to exactly one of nomads/freeholders/shared/reference)", "page-count budget per D-045", "no banned-term literals in page source (the docs firewall scans .md files directly, unlike .go which uses fragment assembly)"]
removed_after: P3
deactivated:
- id: frontend-engineer
reason: No UI in v0.2 (skeleton+tests only; Mesh Experience UI is v0.1-complete and v0.3+ for new UI). Deactivate to avoid persona territory noise. Reactivate in v0.3.
- id: data-engineer
reason: INACTIVE for v0.3. The project has zero external deps and no database; the v0.2 data-engineer owned genesis.go schema helpers, which are a thin layer in v0.3's new modules (x/exit, x/bridge, x/hub, x/services each get a small GenesisState + ValidateGenesis following the v0.2 A-212 pattern). That work is owned by backend-engineer in v0.3 (the genesis schema is part of the skeleton type authoring, not a separate schema-design discipline). Reactivate if a future milestone adds a real store/migration.
- id: cosmos-engineer
reason: The v0.2 custom persona is NOT reactivated for v0.3. v0.3's new modules do not map onto new Cosmos SDK modules the way v0.2's did (x/gov, x/group, x/authz, x/capability, x/ibc-transfer). x/bridge reuses the v0.2 satellite ICS-20 shape (already aligned); x/hub/x/services/x/exit are bespoke B2B/service scaffolds with no direct Cosmos analog. The Cosmos-convention-alignment load drops below the threshold that justified a separate persona. backend-engineer absorbs the work.
- id: security-engineer
reason: The v0.2 custom persona is NOT reactivated for v0.3. v0.3's invariant density is lower than v0.2's (no Mission Lock, no new fee/bond clamp — the 8%/0% consts are reused unchanged from v0.2; the new locked-consts are enum counts: HubService=3, ServiceKind=4, BridgeStatus, ExitStatus). The locked-const + invariant tests are absorbed by backend-engineer's per-package test authoring. The docs firewall (lexicon_meta_docs_test.go) is frontend-engineer's territory. Reactivate in v0.4 if a new Mission-Lock-class invariant lands.
- id: ci-security-auditor
reason: Default deactivated; activate in P5 (review/ship) phase for the milestone audit. Not needed during P1-P4 skeleton authoring.
reason: Default deactivated; activate in P6 (review/ship) for the v0.3 milestone audit.
- id: mesh-engineer
reason: v0.1 listed as future; still not needed in v0.2 (Bearers OY-LR + Beacon are type stubs only, no hardware/RF). Activate in v0.3 for real bearer runtime.
reason: Still not needed in v0.3 (OY-SAT/OY-QR are type stubs only; no hardware/RF runtime). Activate in v0.4+ for real bearer runtime.
custom_personas:
- id: cosmos-engineer
rationale: v0.2 components map onto specific Cosmos SDK modules (x/gov, x/group, x/authz, x/feegrant, x/capability, x/ibc-transfer). A dedicated persona ensures skeleton types mirror the eventual runtime shapes, reducing Phase 3 wiring refactor cost. Distinct from backend-engineer because it carries Cosmos-specific convention knowledge (tally shapes, decision policy, capability, ICS-20 packet shape).
- id: security-engineer
rationale: v0.2 has the highest locked-const + invariant density in the project (Mission Lock, bond cap, 6 Pact types, 9 Stand types, 4 Partner tiers, Window revoke idempotency). A dedicated persona ensures invariant tests and lexicon assertions are not an afterthought. Distinct from backend-engineer because it owns test-file territory and invariant-first design.
- id: docs-writer
rationale: v0.3's docs deliverable (~20-25 pages across 4 audiences per D-045) is a substantial content-authoring load distinct from the docs toolchain work. A dedicated docs-writer keeps the content-vs-toolchain boundary explicit: frontend-engineer owns mkdocs.yml/nav/theme/firewall-wiring; docs-writer owns the page content. This split means a toolchain PR (e.g., adding a markdown extension) does not entangle a content review (e.g., a nomads Reach-page rewrite), and vice versa. Distinct from frontend-engineer because content authoring (prose, audience voice, lexicon-safe phrasing) is a different skill from toolchain config (YAML, theme, nav, Go test wiring). Removed after P3 when the docs site is complete.
---
# Personas: OpenYield (oy) — v0.2 (The Mesh)
# Personas: OpenYield (oy) — v0.3 (Bearers & Documentation)
> This file supersedes the v0.2 PERSONAS.md for the v0.3 milestone. The v0.2
> custom personas (cosmos-engineer, security-engineer) are NOT reactivated for
> v0.3 — see Deactivated below for rationale. The default four personas are
> backend-engineer, data-engineer, frontend-engineer, lead-developer; v0.3
> activates backend-engineer + lead-developer + frontend-engineer (phase-
> specific) and adds one custom persona (docs-writer, phase-specific).
## Active Roster
### backend-engineer
- **Domain**: Go/Cosmos module skeletons for v0.2owns the **non-Cosmos-mirroring** modules (pact, partner, bond) per G-007, plus shared `types/`+`keeper/`+`module.go` authoring.
- **Frameworks**: Go, Cosmos SDK, IBC, CosmWasm.
- **Territory**: `x/pact/**`, `x/partner/**`, `x/bond/**`, `x/**/types/**`, `x/**/keeper/**`, `x/**/module.go`. (`go.mod` is read-only in v0.2 per G-006.)
- **Constraints**: lexicon compliance (REQ-012), skeleton+tests pattern (D-020), ≥80% coverage on new packages (D-033), no live-chain side effects in skeleton, locked-const invariants, no fractional reserve, no leverage/futures.
### data-engineer
- **Domain**: Genesis/state schema design — Window audit log, Stand membership sets, Bond issuance state, Council Voice tally state. Shapes `ValidateGenesis` upgrades (v0.1's no-op → v0.2 ID-uniqueness checks). Owns genesis **schema** only (G-008); genesis **test assertions** are security-engineer's.
- **Frameworks**: Go, `encoding/json`, Cosmos SDK state.
- **Territory**: `x/**/types/genesis.go`, `x/**/genesis.go` (excludes `*_test.go` per G-008).
- **Constraints**: append-only audit logs (Window), ID-uniqueness in `ValidateGenesis`, lexicon compliance, no state identity beyond Reach.
- **Domain**: All Bearers skeleton Go modules in v0.3`x/exit`, `x/bridge`, `x/hub`, `x/services` (new); `x/bearers`, `x/partner`, `x/bond` (extended). Owns the D-020 skeleton+tests pattern (D-035 continues): Go types + keeper stubs + invariant tests, no live chain. Absorbs the v0.2 cosmos-engineer/security-engineer split because v0.3's Cosmos-convention and invariant density are lower.
- **Frameworks**: Go 1.22 stdlib, Cosmos-style types (zero-dep).
- **Territory**: `x/exit/**`, `x/bridge/**`, `x/hub/**`, `x/services/**`, `x/bearers/**`, `x/partner/**`, `x/bond/**`, `x/**/types/**`, `x/**/keeper/**`. (`go.mod` is read-only per G-006.)
- **Constraints**: zero external deps (G-006), D-020 skeleton+tests (D-035), ≥80% coverage on new/extended packages, per-package lexicon assertion (REQ-012), by-ID-string inter-module refs (G-003), locked-const invariants (HubService/ServiceKind/BridgeStatus/ExitStatus counts + Anchor credential fields), no live chain/IBC/bearer/B2B runtime.
### lead-developer
- **Domain**: Multi-component orchestration across 10 new packages, dependency sequencing per D-031 blocker chain, vertical-slice integrity per phase.
- **Domain**: v0.3 phase decomposition (P1 firewall+docs foundation → P2 nomads → P3 freeholders → P4 Bearers I → P5 Bearers II → P6 review/ship), territory enforcement (warn mode), final review. Owns the cross-component dependency finding that constrains phase ordering: `x/exit``x/bridge` (same phase P4); `x/partner`-Anchor→`x/hub` (P4 before P5).
- **Frameworks**: cross-cutting.
- **Territory**: `**`.
- **Constraints**: blocked-by chain enforcement (D-031), milestone versioning (v0.2 / tag_base v0.1.x), lexicon gate on merge, persona territory warn-mode enforcement.
- **Territory**: `.ciagent/**`, `**`.
- **Constraints**: D-044 phase ordering (firewall-first; P4→P5 for Anchor→hub dep), milestone versioning (v0.3 / tag_base v0.2.x), lexicon gate on merge (REQ-012 extends to docs/), persona territory warn-mode, zero Go deps (G-006; docs build-deps allowed per D-042).
### cosmos-engineer (custom, phase-specific to v0.2)
- **Domain**: v0.2 components map onto Cosmos SDK modules — `x/gov` (council tally), `x/group` (stand/guild decision policy), `x/authz`/`x/feegrant` (window), `x/capability` (window unforgeable ref), `x/ibc-transfer` ICS-20 (satellite). Ensures skeleton types mirror runtime shapes for low-friction Phase 3 wiring.
- **Frameworks**: cosmos-sdk, ibc-go, CosmWasm, CometBFT.
- **Territory**: `x/satellite/**`, `x/council/**`, `x/window/**`, `x/stand/**`, `x/guild/**`, `x/forex/**`, `x/bearers/**` (Cosmos-convention-mirroring modules per G-007; `x/pact`/`x/partner`/`x/bond` are backend-engineer's). `go.mod` read-only per G-006.
- **Constraints**: lexicon compliance (REQ-012), no live-chain side effects in skeleton, mirror `x/gov` `TallyResult` / `x/group` `DecisionPolicy` / `x/authz` `Grant` shapes, zero external deps in v0.2 skeleton, by-ID-string inter-module references (G-003 tested invariant).
### frontend-engineer (phase-specific: P1-P3 only)
- **Domain**: v0.3 docs TOOLCHAIN — `mkdocs.yml` (site_name, nav, theme: material, markdown_extensions), the audience-based nav structure (nomads/freeholders/shared/reference per D-042), and the docs firewall test wiring (`lexicon_meta_docs_test.go` mirroring `lexicon_meta_test.go` with `lexicon.FindBannedTerm` + word-boundary regex + self-test table + self-exclusion, scanning `README.md` + `docs/**/*.md`). Owns the firewall landing in P1 BEFORE content (D-044 firewall-first). Removed after P3.
- **Frameworks**: MkDocs Material, Markdown, Go testing (for the firewall test).
- **Territory**: `docs/**` (toolchain), `mkdocs.yml`, `README.md`, `lexicon_meta_docs_test.go`.
- **Constraints**: lexicon-clean by construction (REQ-012 extended via D-043; 10 banned terms absent from docs; "yield" banned standalone, "OpenYield" safe), audience-organized nav, ~20-25 pages total (D-045), no publishing CI in v0.3 (D-046), mkdocs.yml build-only Python dep (go.mod stays zero-dep per G-006).
- **Removed after**: P3.
### security-engineer (custom, phase-specific to v0.2)
- **Domain**: Invariant + locked-const test authorship. Owns **all** test-file territory across v0.2 packages (including `genesis_test.go` per G-008). Highest invariant density in the project: Mission Lock non-amendable, bond 8% cap / 0% floor clamp, fee ceiling/floor clamp, 6 Pact types, 9 Stand types, 4 Partner tiers, Window revoke/expire idempotency, lexicon assertion per module.
- **Frameworks**: Go testing, table-driven tests, invariant tests.
- **Territory**: `x/**/types/**_test.go`, `x/**/keeper/**_test.go`, `x/**/genesis_test.go`, `x/**/*_test.go` (all test files per G-008).
- **Constraints**: invariant tests for all locked constants, locked-const tests for every enum count (9 stands, 4 partner tiers, 6 pacts, 3 councils), lexicon assertion in every new test file (D-033), ≥80% coverage on new packages, Window lifecycle idempotency tests (revoke-after-expire, double-revoke).
### docs-writer (custom, phase-specific: P1-P3 only)
- **Domain**: v0.3 docs CONTENT — the actual Markdown pages across the four audiences (nomads: Reach/Stash/bearers/Maps-Pay/Pacts/standing-basics; freeholders: 4-signals/Bayesian-Standing/Stands-Guilds/Councils-Voice/Bonds/Partner-spectrum; shared: Six-Principles/Bread-Scale/Storage-pools/Watchers-Mirror/Lexicon-glossary/Vision-overview; reference: architecture-index/component-map). Split from frontend-engineer so content review and toolchain review do not entangle. Removed after P3.
- **Frameworks**: Markdown, MkDocs Material (content authoring only).
- **Territory**: `docs/nomads/**/*.md`, `docs/freeholders/**/*.md`, `docs/shared/**/*.md`, `docs/reference/**/*.md`.
- **Constraints**: lexicon-clean by construction (same REQ-012 extension; "real production"/"real return" not "real yield"; "Holder"/"Reach" not "account"; "Stash"/"Vault"/"Root-Pool" not "bank"/"deposit"/"savings"), audience-organized (each page in exactly one audience dir), page-count budget per D-045, no banned-term literals in page source (docs firewall scans .md directly, unlike .go fragment assembly).
- **Removed after**: P3.
## Deactivated
- **frontend-engineer** — No UI in v0.2 (skeleton+tests only). Mesh Experience UI is v0.1-complete; new UI is v0.3+. Reactivate in v0.3.
- **ci-security-auditor** — Default deactivated; activate in P5 (review/ship) for milestone audit.
- **mesh-engineer** v0.1 listed as future; still not needed in v0.2 (Bearers OY-LR + Beacon are type stubs only). Activate in v0.3 for real bearer runtime.
- **data-engineer** — INACTIVE for v0.3. Zero deps + no database; the v0.2 genesis.go schema work is a thin layer absorbed by backend-engineer in v0.3's new modules. Reactivate if a future milestone adds a real store/migration.
- **cosmos-engineer** (v0.2 custom) — NOT reactivated. v0.3's new modules do not map onto new Cosmos SDK modules (x/bridge reuses v0.2 satellite shape; x/hub/x/services/x/exit are bespoke). Cosmos-convention load drops below the threshold for a separate persona; backend-engineer absorbs.
- **security-engineer** (v0.2 custom) — NOT reactivated. v0.3's invariant density is lower (no new Mission-Lock/fee-clamp; 8%/0% consts reused unchanged; new locked-consts are enum counts). Locked-const + invariant tests absorbed by backend-engineer's per-package test authoring; docs firewall is frontend-engineer's. Reactivate in v0.4 if a new Mission-Lock-class invariant lands.
- **ci-security-auditor** — Default deactivated; activate in P6 (review/ship) for the milestone audit.
- **mesh-engineer** — Still not needed (OY-SAT/OY-QR are type stubs only). Activate in v0.4+ for real bearer runtime.
## Custom Personas
- **cosmos-engineer** — v0.2 components map onto specific Cosmos SDK modules. Dedicated persona ensures skeleton types mirror eventual runtime shapes, reducing Phase 3 wiring refactor cost. Distinct from backend-engineer: carries Cosmos-specific convention knowledge (tally shapes, decision policy, capability, ICS-20 packet shape).
- **security-engineer** — v0.2 has the highest locked-const + invariant density in the project. Dedicated persona ensures invariant tests and lexicon assertions are not an afterthought. Distinct from backend-engineer: owns test-file territory and invariant-first design.
- **docs-writer** — v0.3's docs deliverable (~20-25 pages, D-045) is a substantial content-authoring load distinct from the docs toolchain. A dedicated docs-writer keeps the content-vs-toolchain boundary explicit: frontend-engineer owns mkdocs.yml/nav/theme/firewall-wiring; docs-writer owns page content. This split means a toolchain PR does not entangle a content review and vice versa. Distinct from frontend-engineer because prose/audience-voice/lexicon-safe-phrasing is a different skill from YAML/theme/nav/Go-test wiring. Removed after P3 when the docs site is complete.
## Framework Alignment
- **Go 1.22** — all personas target Go 1.22 (`go.mod`).
- **cosmos-sdk** — cosmos-engineer targets cosmos-sdk v0.50.x (LTS) for future wiring; NOT vendored in v0.2 skeleton.
- **ibc-go** — cosmos-engineer targets ibc-go v8/v10 for satellite module shape; NOT vendored in v0.2 skeleton.
- **CosmWasm** — cosmos-engineer targets wasmvm v1.5/v2.0 for potential Pacts-as-contracts in Phase 3; NOT vendored in v0.2.
- **Go 1.22** — backend-engineer targets Go 1.22 (`go.mod`); zero external deps (G-006).
- **MkDocs Material** — frontend-engineer + docs-writer target MkDocs Material (D-042); build-only Python dep, NOT a Go dependency. No publishing CI in v0.3 (D-046).
## Territory Alignment
- Mapped to actual `x/<name>/` structure (15 v0.1 modules + 9 new v0.2 modules + 1 extended).
- backend-engineer owns `x/pact`, `x/partner`, `x/bond` (non-Cosmos-mirroring per G-007) + shared `types/`+`keeper/`+`module.go` authoring.
- data-engineer owns `genesis.go` schema only (G-008 — excludes `*_test.go`).
- cosmos-engineer owns the Cosmos-convention-mirroring modules (`x/satellite`, `x/council`, `x/window`, `x/stand`, `x/guild`, `x/forex`) + `x/bearers` extension (G-007).
- security-engineer owns **all** `*_test.go` files across the new packages (G-008 — including `genesis_test.go`).
- lead-developer owns `**` for cross-cutting coordination.
- `go.mod` is **read-only** in v0.2 (G-006) — no persona may modify it; any change is an escalation (would violate D-020/A-201 zero-dep invariant).
- backend-engineer owns all `x/*` Bearers-skeleton modules (new: exit/bridge/hub/services; extended: bearers/partner/bond) + shared `types/`+`keeper/` authoring.
- frontend-engineer owns the docs toolchain (`docs/**` config, `mkdocs.yml`, `README.md`, `lexicon_meta_docs_test.go`).
- docs-writer owns docs content (`docs/<audience>/**/*.md`).
- lead-developer owns `.ciagent/**` + `**` for cross-cutting coordination.
- `go.mod` is read-only in v0.3 (G-006) — no persona may modify it; docs build-deps are allowed (D-042) but live outside `go.mod`.
## Constraint Alignment
- **Lexicon (REQ-012)** — every persona carries it; security-engineer asserts it per test file.
- **Skeleton + tests pattern (D-020)** — backend-engineer + cosmos-engineer enforce.
- **≥80% coverage on new packages (D-033)** — security-engineer owns the gate.
- **Blocker chain (D-031)** — lead-developer enforces phase ordering.
- **No live-chain side effects in skeleton** — cosmos-engineer + backend-engineer enforce (no relayer, no CometBFT, no live oracle).
- **Locked-const invariants** — security-engineer owns; every locked constant has a dedicated test.
- **Lexicon (REQ-012)** — every active persona carries it; backend-engineer asserts per test file (x/*); frontend-engineer asserts via the docs firewall (docs/* + README.md). The firewall extension is a sibling test, NOT a modification of the v0.2 meta-test (D-043).
- **Skeleton + tests (D-020/D-035)** — backend-engineer enforces.
- **≥80% coverage** — backend-engineer owns the gate for x/* packages.
- **Phase ordering (D-044)** — lead-developer enforces; firewall-first (P1) before content (P2/P3); P4 (exit/bridge/bearers/partner) before P5 (hub/services/bond) for the Anchor→hub dependency.
- **Locked-const invariants** — backend-engineer owns; HubService=3, ServiceKind=4, BridgeStatus count, ExitStatus count, Anchor credential fields, 8%/0% bond consts (reused).
## Phase-Specific Personas
- **cosmos-engineer** — phase-specific to v0.2 execution phases (P1-P4). Remove or merge back into backend-engineer after v0.2 ships (Cosmos convention alignment is most critical during the first Mesh-era skeleton).
- **security-engineer** — phase-specific to v0.2 (highest invariant density). May persist into v0.3 if invariant-test density remains high; reassess at v0.3 PLAN.
- **frontend-engineer** — phase-specific to v0.3 P1-P3 (docs phases). Removed after P3; the Bearers skeleton phases (P4/P5) are pure Go (backend-engineer). Reassess at v0.4 if new docs work is queued.
- **docs-writer** — phase-specific to v0.3 P1-P3 (docs content). Removed after P3 with frontend-engineer.
+456 -1
View File
@@ -334,4 +334,459 @@ The Phase 0 grill (see `.ciagent/oy/GRILL.md`) returned 10 binding decisions, al
- **P1-02-01 (Stand types)** → blocks P2-01-01 (Pact StandRegistry stand-id-ref), P3-01-01 (Council Stand Council), P4-01-01 (Bond issuer-stand-id).
- **P1-03-01 (Guild types)** → blocks P3-01-01 (Council Guild Council).
- **P4-04-01 (P4 ship)** → blocks P5-01-01, P5-01-02, P5-01-03 (P5 audit).
- All P(N) phase-ship tasks block P(N+1) Wave 1 tasks (soft ordering for branch hygiene; types themselves only depend on the listed hard blockers).
- All P(N) phase-ship tasks block P(N+1) Wave 1 tasks (soft ordering for branch hygiene; types themselves only depend on the listed hard blockers).
---
## Milestone v0.3 — Bearers & Documentation — Phase Plan
> This section APPENDS the v0.3 milestone plan to the v0.1/v0.2 plan above. It
> does NOT rewrite or supersede the earlier content. v0.3 bundles two work-
> streams under one feature milestone (D-034): (A) Bearers skeleton+tests
> (D-020/D-035 pattern) and (B) a README.md + MkDocs Material docs site with
> the REQ-012 lexicon firewall extended to docs (D-043). Tags run on the
> `v0.2.x` patch line (config.json `tag_base: v0.2.x`): P0 → `v0.2.0`,
> P1..P5 → `v0.2.1..v0.2.5`, P6 → `v0.2.6` (= the v0.3 milestone release per
> D-008 — final phase patch IS the milestone release; no separate minor tag).
### Milestone Summary
- **Milestone**: v0.3 — Bearers & Documentation
- **Type**: Feature (Bearers phases P4/P5 are `feat`; docs phases P1-P3 are `docs`/`test`; P6 is `final`)
- **Tag base**: `v0.2.x` patch line (P0 ships as `v0.2.0`; execution phases `v0.2.1..v0.2.5`; final phase `v0.2.6` IS the milestone release)
- **Phases**: 7 — P0 (this PLAN) + P1..P3 (docs) + P4..P5 (Bearers feat) + P6 (final review/audit/ship).
- **Depth**: skeleton + tests layer (D-020/D-035) for Bearers; docs deliverable (D-042/D-045) for the docs site; zero external Go deps (G-006; mkdocs is a build-only Python dep, not a Go dep).
- **Coverage target**: ≥80% on each new/extended x/* package (D-033); lexicon assertion (REQ-012) in every new/extended test file (D-032); docs firewall (`lexicon_meta_docs_test.go`) green for `README.md` + `docs/**/*.md`.
- **New x/* modules**: 4 (`x/exit`, `x/bridge`, `x/hub`, `x/services`). **Extended**: 3 (`x/bearers`, `x/partner`, `x/bond`). **Docs surface**: new (`docs/`, `mkdocs.yml`, `README.md`). **Firewall**: 1 new sibling test (`lexicon_meta_docs_test.go`).
- **Phase ordering** (D-044): P1 docs foundation + firewall-first → P2 nomads docs → P3 freeholders docs → P4 Bearers I (exit/bridge/bearers/partner-Anchor) → P5 Bearers II (hub/services/bond) → P6 review/ship. Firewall lands in P1 BEFORE content (P2/P3) so docs are lexicon-clean by construction. P4 precedes P5 for the Anchor→hub dependency.
- **Personas**: backend-engineer (all Bearers Go modules), lead-developer (cross-cutting/ship), frontend-engineer (docs toolchain + firewall wiring, P1-P3 only), docs-writer (docs content, P1-P3 only). The v0.2 custom personas (cosmos-engineer, security-engineer) are NOT reactivated (A-315).
### Cross-Phase Dependency Map (v0.3)
```
P1 (firewall + docs foundation) ──┬──► P2 (nomads docs) [firewall scans docs/nomads/ as added]
└──► P3 (freeholders docs) [firewall scans docs/freeholders/ + docs/reference/]
P4 (Bearers I: bridge, exit, bearers ext, partner ext) ──► P5 (Bearers II: hub, services, bond ext)
│ x/bridge (Wave 1) ──► x/exit (Wave 2) [exit bridge-route-id refs bridge by ID]
│ x/partner Anchor (Wave 4) ──► x/hub (P5 Wave 1) [hub operator-partner-id refs Anchor by ID]
└──► P5 all waves
P5 (Bearers II) ──► P6 (review/audit/ship)
P1..P5 (all execution) ──► P6
```
Hard cross-phase blockers (by-ID-string refs, no import cycles — G-003):
- **P4 Wave 1 `x/bridge` types** → blocks P4 Wave 2 `x/exit` tests (exit's `bridge-route-id` references a BridgeRoute by ID-string — A-308/G-003).
- **P4 Wave 4 `x/partner` Anchor extension** → blocks P5 Wave 1 `x/hub` (hub's `operator-partner-id` references an Anchor partner by ID-string — A-304/G-003). This is the edge that forces P4 before P5 (D-044).
- **P1 Wave 1 docs firewall** → blocks P2/P3 docs content (firewall-first: a banned term slipped into a P2/P3 page fails the build, not the P6 review).
- **P5 ship** → blocks P6 audit/ship.
All other inter-module refs (x/services→x/window, x/bond→x/stand, x/bridge→x/satellite, x/bridge→x/watcher) are to v0.1/v0.2 baseline modules (no v0.3 phase-ordering concern).
---
## Phase P1 — Docs Foundation + Firewall Extension
- **Slug**: `docs-foundation-firewall`
- **Branch**: `oy/phase/01-docs-foundation-firewall`
- **REQs covered**: REQ-028 (lexicon firewall extension to docs), REQ-027 (README.md + docs site foundation: README + shared docs + index)
- **Tag**: `v0.2.1`
- **Type**: `feat/test+docs`
- **Personas**: frontend-engineer (toolchain + firewall), docs-writer (README + shared content)
- **Goal**: Land the docs lexicon firewall (`lexicon_meta_docs_test.go`) + the MkDocs Material scaffold (`mkdocs.yml`) + `README.md` + `docs/index.md` + `docs/shared/` pages BEFORE any audience docs content (P2/P3), so docs are lexicon-clean by construction (D-044 firewall-first).
### Wave 1 — Firewall + scaffold FIRST (parallel)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P1-01-01 | REQ-028 | frontend-engineer | `lexicon_meta_docs_test.go` (repo root, package `lexicon_meta_docs`) | **NEW sibling meta-test** mirroring `lexicon_meta_test.go` (D-043). Uses the SAME `lexicon.FindBannedTerm` (word-boundary, case-insensitive) — NO detection reimplementation. Walks the REPO ROOT (not `x/`): targets `README.md` (repo root) + every `*.md` under `docs/` (recursive). Excludes `.ciagent/` (firewall meta-files, not user-facing), `.git/` (VCS), the meta-test file itself (self-exclusion via `runtime.Caller(0)`), and non-`.md` files under `docs/`. Includes the G-009 self-test table (one synthetic string per banned term, assembled from `lexicon.BannedTerms()` fragments so the test file's own source has no banned-term literal), `TestLexiconMetaDocsBannedTermsCount` (exactly 10), and `TestLexiconMetaDocsNoFalsePositiveOnOpenYield` (word-boundary does not match "openyield"/"european"). The firewall PASSES at P1 time with zero docs (or with only README + docs/index.md + docs/shared/ from Wave 2). | `go test ./lexicon_meta_docs/...` green (invoked as `go test -run TestLexiconMetaDocs ./...` or via the repo-root file); self-test table passes for all 10 banned terms; `TestLexiconMetaDocsNoFalsePositiveOnOpenYield` green; a deliberately-injected banned term in a `docs/*.md` file fails the test | — |
| P1-01-02 | REQ-027 | frontend-engineer | `mkdocs.yml` (repo root) | MkDocs Material config (D-042): `site_name: OpenYield`; `theme: name: material` with `navigation.sections`/`navigation.expand`/`toc.integrate` features; `markdown_extensions: [admonition, toc (permalink: true), pymdownx.superfences]`; `nav:` skeleton with Home + Nomads + Freeholders + Shared + Reference sections (audience-organized per D-042). The nav references the P2/P3 pages by path (pages need not exist yet at P1 — mkdocs.yml is a config file, not validated by Go tests; the docs firewall does not validate nav, only `.md` content). Build-only Python dep; `go.mod` stays zero-dep (G-006). No publishing CI (D-046). | `mkdocs.yml` is valid YAML (parses; documented `mkdocs serve` / `mkdocs build` invocation goes in README P1-02-01); `go.mod` unchanged (zero require lines); nav has the 4 audience sections + Home | — |
### Wave 2 — README + docs/index.md + docs/shared/ (parallel; blocked-by Wave 1 firewall)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P1-02-01 | REQ-027 | frontend-engineer | `README.md` (repo root) | Repo-root project overview: one-paragraph OpenYield description (lexicon-clean — "real production"/"real return" not "yield"; "Holder"/"Reach" not "account"; "Stash"/"Vault"/"Root-Pool" not "bank"/"deposit"/"savings"); build instructions (`go build ./...`, `go test ./...`); docs build instructions (`mkdocs serve` / `mkdocs build` per D-046); link to `docs/` site; pointer to `.ciagent/oy/PROJECT.md` for governance. Lexicon-clean by construction (the P1-01-01 firewall scans README.md). | `README.md` exists; `go test ./lexicon_meta_docs/...` green (README is scanned); `go test ./...` green (no Go regression — README is not a Go file) | P1-01-01 |
| P1-02-02 | REQ-027 | docs-writer | `docs/index.md` | Site home page: one-paragraph OpenYield overview (lexicon-clean), links to the 4 audience sections (nomads/freeholders/shared/reference), pointer to README for build instructions. | `docs/index.md` exists; docs firewall green (index scanned) | P1-01-01 |
| P1-02-03 | REQ-027 | docs-writer | `docs/shared/six-principles.md` | Six Principles page (REQ-001): real value, sustainability, mission-lock, openness, ownership, self-service. Lexicon-clean (the firewall scans `docs/shared/**/*.md`). | Page exists; firewall green | P1-01-01 |
| P1-02-04 | REQ-027 | docs-writer | `docs/shared/bread-scale.md` | Bread Scale page (REQ-013): Grain → Crumb → Bread → Loaf → Batch → Cake → Bakery → Granary → Mill → Harvest → Earth. | Page exists; firewall green | P1-01-01 |
| P1-02-05 | REQ-027 | docs-writer | `docs/shared/storage-pools.md` | Storage Pools page (REQ-014): Stash (Holder), Vault (Stand), Root-Pool (treasury). Lexicon-clean ("Stash"/"Vault"/"Root-Pool" not "bank"/"deposit"/"savings"). | Page exists; firewall green | P1-01-01 |
| P1-02-06 | REQ-027 | docs-writer | `docs/shared/watchers-mirror.md` | Watchers / Mirror page (REQ-004): 9 Watchers, 6-of-9 quorum, daily attestations, 100,000 Bread bond each. | Page exists; firewall green | P1-01-01 |
| P1-02-07 | REQ-027 | docs-writer | `docs/shared/lexicon-glossary.md` | Lexicon Glossary page (REQ-012): the 10 banned terms named BY THEIR SAFE ALTERNATIVES (the page documents the safe phrasings — "real production"/"Holder"/"Stash"/"coupon" — NOT the banned literals; the firewall scans this page, so the banned terms must NOT appear as literals, only as the safe replacements described in prose). Cross-reference the firewall design (D-043). | Page exists; firewall green (no banned-term literals — the glossary describes replacements, not the banned words themselves) | P1-01-01 |
| P1-02-08 | REQ-027 | docs-writer | `docs/shared/vision-overview.md` | Vision Overview page: the OpenYield covenant (real production, anti-greed, jurisdiction-light, public-good mesh), pointer to `.ciagent/oy/PROJECT.md` for the full vision source. | Page exists; firewall green | P1-01-01 |
### Wave 3 — Phase verification + ship
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P1-03-01 | REQ-012, REQ-027, REQ-028 | lead-developer | (cross-cutting) | Run `go build ./...` + `go test ./...` across the whole repo (no Go regression — the docs firewall is a NEW Go test file but adds no x/* Go code); confirm `go test ./lexicon_meta_docs/...` green; confirm `mkdocs.yml` valid; confirm README.md + docs/index.md + 6 docs/shared/ pages exist and are lexicon-clean; tag `v0.2.1`. | `go test ./...` green (incl. v0.1/v0.2 baseline + the new docs firewall); docs firewall green; mkdocs.yml valid; 8 docs files (README + index + 6 shared) exist + lexicon-clean; git tag `v0.2.1` created | P1-01-01, P1-01-02, P1-02-01..08 |
### P1 Must-Haves
- [ ] `lexicon_meta_docs_test.go` exists at repo root (package `lexicon_meta_docs`); mirrors `lexicon_meta_test.go` detection (same `lexicon.FindBannedTerm` + word-boundary regex + self-test table G-009 + self-exclusion); scans `README.md` + `docs/**/*.md`; excludes `.ciagent/` + `.git/` + itself.
- [ ] `go test ./lexicon_meta_docs/...` green (firewall passes with README + docs/index.md + docs/shared/ present).
- [ ] `go test ./...` green across the whole repo (no Go regression; the v0.2 `lexicon_meta_test.go` is UNCHANGED per D-043).
- [ ] `mkdocs.yml` exists at repo root (Material theme, 4 audience sections in nav, admonition + toc + superfences extensions); `go.mod` unchanged (zero require lines).
- [ ] `README.md` exists (lexicon-clean; build/test/docs-build instructions).
- [ ] `docs/index.md` exists (site home).
- [ ] 6 `docs/shared/` pages exist (Six Principles, Bread Scale, Storage Pools, Watchers/Mirror, Lexicon Glossary, Vision Overview) — all lexicon-clean.
- [ ] Docs firewall self-test table passes for all 10 banned terms (G-009 for docs).
- [ ] `TestLexiconMetaDocsNoFalsePositiveOnOpenYield` green.
- [ ] Git tag `v0.2.1`.
### P1 Risks & Mitigations
- **Banned-term literals in the lexicon-glossary page** (highest P1 risk) → docs-writer must describe SAFE ALTERNATIVES, not the banned words themselves; the firewall scans `docs/shared/lexicon-glossary.md` directly (unlike `.go` fragment assembly). Mitigation: P1-01-01 firewall is the gate; a literal banned term fails the P1 build.
- **mkdocs.yml nav references non-existent P2/P3 pages** → mkdocs.yml is a config file, not Go-tested; nav can list future pages. The firewall scans `.md` content, not `nav`. Mitigation: P2/P3 create the referenced pages; missing pages are a `mkdocs build` warning, not a Go test failure.
- **README "yield" false positive** → the firewall word-boundary regex allows "OpenYield" but bans standalone "yield"; README must say "real production"/"real return". Mitigation: `TestLexiconMetaDocsNoFalsePositiveOnOpenYield` is the regression firewall.
---
## Phase P2 — Nomads Docs
- **Slug**: `nomads-docs`
- **Branch**: `oy/phase/02-nomads-docs`
- **REQs covered**: REQ-027 (nomads audience docs, 7 pages per D-045)
- **Tag**: `v0.2.2`
- **Type**: `docs`
- **Personas**: docs-writer (content); frontend-engineer (toolchain verify — firewall now scans the new docs/nomads/ files)
- **Goal**: Ship the 7-page nomads audience docs (`docs/nomads/`) covering the Reach path, Stash, bearers, Maps/Pay, six Pacts, standing basics, and the Window primitive — all lexicon-clean (the P1 firewall now scans these files as they are added).
### Wave 1 — Nomads content pages (parallel; all blocked-by P1 firewall landing)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P2-01-01 | REQ-027 (REQ-005 Reach) | docs-writer | `docs/nomads/reach.md` | What a Nomad is + the Reach path (REQ-005): how a person becomes a Holder via a Reach ID, no-KYC at protocol level, geographic-proximity FCFS (REQ-007). Lexicon-clean ("Holder"/"Reach" not "account"; "real production" not "yield"). | Page exists; docs firewall green (scans `docs/nomads/reach.md`) | P1-03-01 |
| P2-01-02 | REQ-027 (REQ-014 Stash) | docs-writer | `docs/nomads/stash.md` | Stash usage (REQ-014): the Holder-level storage pool, how Bread is held in a Stash, the 90-day Freeholder-signal Stash requirement. Lexicon-clean ("Stash" not "bank"/"deposit"/"savings"). | Page exists; firewall green | P1-03-01 |
| P2-01-03 | REQ-027 (REQ-019 bearers) | docs-writer | `docs/nomads/bearers.md` | Bearers for nomads (REQ-019): the six bearers (Internet, OY-LR, OY-BLE, OY-WiFi-Direct, OY-SAT, OY-QR) via the Unified Bearer Layer, first-to-deliver-wins, surveillance resistance. Lexicon-clean. | Page exists; firewall green | P1-03-01 |
| P2-01-04 | REQ-027 (Mesh Experience) | docs-writer | `docs/nomads/maps-pay.md` | Maps / Pay Mesh Experience: how a Nomad uses Maps and Pay day-to-day (Maya's Day deferred per PROJECT.md out-of-scope Q1). Lexicon-clean. | Page exists; firewall green | P1-03-01 |
| P2-01-05 | REQ-027 (REQ-020 Pacts) | docs-writer | `docs/nomads/pacts.md` | Six Pacts (REQ-020): Pause, Ground, Stance, Cover, Stand Registry, Hub API — what each means for a Nomad. Lexicon-clean. | Page exists; firewall green | P1-03-01 |
| P2-01-06 | REQ-027 (REQ-006 standing basics) | docs-writer | `docs/nomads/standing-basics.md` | Standing basics for nomads (REQ-006): what Bayesian Standing is in plain language, how it accrues, why it matters (no formula math — defer detail to freeholders/bayesian-standing). Lexicon-clean. | Page exists; firewall green | P1-03-01 |
| P2-01-07 | REQ-027 (REQ-015 Window) | docs-writer | `docs/nomads/window.md` | Window primitive (REQ-015): scope, duration, rate-limit, audit log, revoke — what a Window means for a Nomad delegating access to a partner/service. Lexicon-clean. | Page exists; firewall green | P1-03-01 |
| P2-01-08 | REQ-027 | docs-writer | `docs/nomads/index.md` | Nomads section index: one-paragraph intro + links to the 7 nomads pages. Lexicon-clean. | Page exists; firewall green | P1-03-01 |
### Wave 2 — Phase verification + ship
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P2-02-01 | REQ-012, REQ-027 | lead-developer | (cross-cutting) | Run `go test ./...` (docs firewall now scans the 8 new `docs/nomads/*.md` files and passes); confirm all 8 nomads pages lexicon-clean; tag `v0.2.2`. | `go test ./...` green (docs firewall green with nomads content); 8 `docs/nomads/*.md` exist + lexicon-clean; git tag `v0.2.2` | P2-01-01..08 |
### P2 Must-Haves
- [ ] 8 `docs/nomads/*.md` pages exist (index + reach + stash + bearers + maps-pay + pacts + standing-basics + window) — all lexicon-clean.
- [ ] `go test ./...` green (the P1 docs firewall now scans `docs/nomads/**/*.md` and passes).
- [ ] `go test ./lexicon_meta_docs/...` green specifically.
- [ ] No Go code changes (P2 is pure docs; `go build ./...` green by no-regression).
- [ ] Git tag `v0.2.2`.
### P2 Risks & Mitigations
- **"account"/"bank"/"deposit" drift in nomads prose** (Stash/Reach pages are highest-risk) → docs-writer uses "Holder"/"Reach"/"Stash"; the firewall is the gate (fails the P2 build, not P6 review — D-044 firewall-first value).
- **Standing-basics page over-promises formula detail** → defer math to freeholders/bayesian-standing (P3); nomads page stays conceptual.
---
## Phase P3 — Freeholders Docs + Reference
- **Slug**: `freeholders-docs-reference`
- **Branch**: `oy/phase/03-freeholders-docs-reference`
- **REQs covered**: REQ-027 (freeholders audience docs 7 pages + reference 2 pages; REQ-027 COMPLETE at end of P3)
- **Tag**: `v0.2.3`
- **Type**: `docs`
- **Personas**: docs-writer (content); frontend-engineer (toolchain verify — firewall now scans docs/freeholders/ + docs/reference/)
- **Goal**: Ship the 7-page freeholders audience docs (`docs/freeholders/`) covering the four signals, Bayesian Standing, Stands/Guilds, Councils/Voice, Bonds, Partner spectrum, Anchor preview — plus the 2-page reference section (`docs/reference/`). **REQ-027 (docs deliverable) is COMPLETE at the end of P3.** After P3, frontend-engineer and docs-writer are removed (phase-specific personas, P1-P3 only).
### Wave 1 — Freeholders content pages (parallel)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P3-01-01 | REQ-027 (REQ-005 four signals) | docs-writer | `docs/freeholders/four-signals.md` | Four Freeholder signals (REQ-005): 90d Stash, 4.5★+ in 3 categories, Capital, Vouch. Lexicon-clean. | Page exists; firewall green | P2-02-01 |
| P3-01-02 | REQ-027 (REQ-006 Bayesian Standing) | docs-writer | `docs/freeholders/bayesian-standing.md` | Bayesian Standing (REQ-006): the anti-gaming formula (Bayesian + time-decay + diversity + voucher-weighted slashes), why it resists gaming. Formula at conceptual depth (full sub-tables deferred per PROJECT.md Q2). Lexicon-clean. | Page exists; firewall green | P2-02-01 |
| P3-01-03 | REQ-027 (REQ-016/017 Stands/Guilds) | docs-writer | `docs/freeholders/stands-guilds.md` | Stands & Guilds (REQ-016/017): the 9 Stand types (Household…Shadow), Guilds with Hand-Passes at 0% protocol fee. Lexicon-clean ("Stash"/"Vault" not "bank"; "Hand-Pass"/"0% protocol fee" not "interest"). | Page exists; firewall green | P2-02-01 |
| P3-01-04 | REQ-027 (REQ-011 Councils/Voice) | docs-writer | `docs/freeholders/councils-voice.md` | Councils & Voice (REQ-011): the three Councils (Mesh, Guild, Stand), multi-source Voice, Mission Lock cannot be amended. Lexicon-clean. | Page exists; firewall green | P2-02-01 |
| P3-01-05 | REQ-027 (REQ-021 Bonds) | docs-writer | `docs/freeholders/bonds.md` | Bonds (REQ-021): the Mesh Bond Market, 8% upper coupon cap / 0% floor, Growth Bonds (preview of v0.3 P5 work). Lexicon-clean ("coupon"/"growth" not "interest"/"yield"). | Page exists; firewall green | P2-02-01 |
| P3-01-06 | REQ-027 (REQ-018 Partner spectrum) | docs-writer | `docs/freeholders/partner-spectrum.md` | Partner Spectrum (REQ-018): the four tiers (Op, Master Op, Pier, Anchor). Lexicon-clean ("Partner"/"Reach" not "account"). | Page exists; firewall green | P2-02-01 |
| P3-01-07 | REQ-027 (REQ-023 Anchor preview) | docs-writer | `docs/freeholders/anchor-preview.md` | Anchor preview (REQ-023): the first institutional Partner tier, the Anchor credential (preview of v0.3 P4 work), custody/compliance relationship. Lexicon-clean ("custody"/"compliance"/"jurisdiction" safe; not "bank"/"account"). | Page exists; firewall green | P2-02-01 |
| P3-01-08 | REQ-027 | docs-writer | `docs/freeholders/index.md` | Freeholders section index: one-paragraph intro + links to the 7 freeholders pages. Lexicon-clean. | Page exists; firewall green | P2-02-01 |
### Wave 2 — Reference pages (parallel; blocked-by Wave 1)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P3-02-01 | REQ-027 | docs-writer | `docs/reference/architecture-index.md` | Architecture index: the 14-component index (from `.ciagent/oy/ARCHITECTURE.md` Component Index), the 6 cross-component interfaces, the critical blocker chain. Lexicon-clean (rewrite the architecture terms in user-facing prose — do NOT copy `.ciagent/` content verbatim if it contains banned-term discussions; the firewall scans this page). | Page exists; firewall green | P3-01-01..08 |
| P3-02-02 | REQ-027 | docs-writer | `docs/reference/component-map.md` | Component map: a table of v0.1/v0.2/v0.3 modules (`x/<name>/`) mapped to vision sections and REQs. Lexicon-clean. | Page exists; firewall green | P3-01-01..08 |
### Wave 3 — Phase verification + ship (frontend-engineer + docs-writer removed after this phase)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P3-03-01 | REQ-012, REQ-027 | lead-developer | (cross-cutting) | Run `go test ./...` (docs firewall now scans `docs/freeholders/**/*.md` + `docs/reference/**/*.md` and passes); confirm all 10 new pages lexicon-clean; **REQ-027 COMPLETE** (total docs pages: 1 README + 1 index + 6 shared + 8 nomads + 8 freeholders + 2 reference = 26 pages, within D-045 20-25 budget +README/index); tag `v0.2.3`. Remove frontend-engineer + docs-writer personas (phase-specific, P1-P3 only). | `go test ./...` green (docs firewall green with all docs content); REQ-027 marked complete in REQUIREMENTS.md; git tag `v0.2.3`; personas removed | P3-01-01..08, P3-02-01..02 |
### P3 Must-Haves
- [ ] 8 `docs/freeholders/*.md` pages exist (index + four-signals + bayesian-standing + stands-guilds + councils-voice + bonds + partner-spectrum + anchor-preview) — all lexicon-clean.
- [ ] 2 `docs/reference/*.md` pages exist (architecture-index + component-map) — all lexicon-clean.
- [ ] `go test ./...` green (docs firewall scans the full `docs/` tree + README and passes).
- [ ] `go test ./lexicon_meta_docs/...` green.
- [ ] No Go code changes (P3 is pure docs; `go build ./...` green by no-regression).
- [ ] **REQ-027 marked COMPLETE** in REQUIREMENTS.md (docs deliverable done).
- [ ] frontend-engineer + docs-writer personas removed (phase-specific, P1-P3 only).
- [ ] Git tag `v0.2.3`.
### P3 Risks & Mitigations
- **"interest"/"yield" in bonds page** (highest P3 risk) → docs-writer uses "coupon"/"growth"/"real return"; firewall is the gate.
- **Architecture-index page copies `.ciagent/` banned-term discussions verbatim** → `.ciagent/` files discuss banned terms by name for governance but are excluded from the firewall; the reference page is NOT excluded, so it must use safe phrasings. Mitigation: docs-writer rewrites in user-facing prose; firewall scans `docs/reference/architecture-index.md`.
---
## Phase P4 — Bearers Skeleton I (exit/bridge/bearers/partner-Anchor)
- **Slug**: `bearers-skeleton-i`
- **Branch**: `oy/phase/04-bearers-skeleton-i`
- **REQs covered**: REQ-010 (Exit layer: x/bridge + x/exit), REQ-022 (Bearers OY-SAT/OY-QR), REQ-023 (Anchors — x/partner extension)
- **Tag**: `v0.2.4`
- **Type**: `feat`
- **Persona**: backend-engineer (all Go modules; the v0.2 cosmos-engineer/security-engineer split is collapsed per A-315)
- **Goal**: Ship the Bearers skeleton I: `x/bridge` (L2↔L1 bridge types) FIRST, then `x/exit` (exit routes + DEXSwap, referencing bridge by ID-string), then `x/bearers` extension (OY-SAT/OY-QR transport stubs), then `x/partner` extension (Anchor credential types — referenced by x/hub in P5).
### Wave 1 — x/bridge types FIRST (intra-P4 ordering: bridge before exit)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P4-01-01 | REQ-010 | backend-engineer | `x/bridge/types/types.go` + `x/bridge/types/genesis.go` | New `x/bridge/types/` module following the `x/satellite` pattern (D-036, A-302). `BridgeStatus` enum (Pending, Attested, Active, Closed) — exactly 4, locked-const `BridgeStatusCount = 4` (A-312 names HubServiceCount; BridgeStatusCount is the bridge analog). `AllBridgeStatuses() []BridgeStatus`. `BridgeRoute` struct (route-id, source-chain (L2Chain by-ID-string ref to `x/satellite` — G-003, no struct import), dest-chain (L2Chain by-ID-string), bridge-type (opaque string e.g. "ibc" — NOT a locked enum per A-308), transfer-channel-id (by-ID-string ref to a v0.2 satellite TransferChannel), watcher-quorum-id (by-ID-string ref to `x/watcher`, set when status becomes Attested), status). `Keeper` stub: AddBridgeRoute / GetBridgeRoute / ListByStatus. `Params`, `GenesisState` (routes), `DefaultGenesisState`, `ValidateGenesis` (reject dup route-ids, A-212). | `go build ./x/bridge/...` succeeds; `BridgeStatusCount == 4`; `AllBridgeStatuses()` returns 4 in vision order; `ValidateGenesis` rejects dup route-id; zero external deps (go.mod unchanged) | — |
### Wave 2 — x/exit types (blocked-by Wave 1 bridge)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P4-02-01 | REQ-010 | backend-engineer | `x/exit/types/types.go` + `x/exit/types/genesis.go` | New `x/exit/types/` module following `x/satellite` (D-036). `ExitStatus` enum (Proposed, InProgress, Settled, Failed, Refunded) — exactly 5, locked-const `ExitStatusCount = 5`. `AllExitStatuses() []ExitStatus`. `ExitRoute` struct (route-id, holder-reach-id (by-ID-string ref to `x/identity` — use "Holder"/"Reach" not "account"), source-asset (opaque string), dest-asset (opaque string), amount-grain (int64 — NOT a `x/bread` import; "Grain" by name only), min-received-grain, bridge-route-id (OPTIONAL, by-ID-string ref to `x/bridge` BridgeRoute for cross-chain exits — G-003), venue-hops []string, deadline, status). `DEXSwap` struct (swap-id, route-id (by-ID-string ref to ExitRoute), venue (opaque string — NOT a locked enum per A-308), input-asset, input-amount-grain, output-asset, output-amount-grain, executed-at). `Keeper` stub: AddExitRoute / GetExitRoute / ListByHolder. `Params`, `GenesisState` (routes + swaps), `DefaultGenesisState`, `ValidateGenesis` (reject dup route-ids + dup swap-ids, A-212). | `go build ./x/exit/...` succeeds; `ExitStatusCount == 5`; `AllExitStatuses()` returns 5 in vision order; `ValidateGenesis` rejects dup route-id + dup swap-id; the `bridge-route-id` field is a string (no `x/bridge` struct import — G-003 verified by the P1 G-003 import-invariant test, which now also scans the new x/exit + x/bridge files) | P4-01-01 |
### Wave 3 — x/exit tests + x/bridge tests (parallel; blocked-by Wave 1/2 types)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P4-01-02 | REQ-010, REQ-012 | backend-engineer | `x/bridge/types/types_test.go` (+ `genesis_test.go` if split) | Locked-const test: `BridgeStatusCount == 4`; `AllBridgeStatuses()` names match (Pending, Attested, Active, Closed); `BridgeRoute` struct round-trip (marshal/unmarshal); `bridge-route-id` references a satellite L2Chain by string (no `x/satellite` import — G-003 import-invariant test green); `watcher-quorum-id` is an opaque string (no `x/watcher` import); `ValidateGenesis` rejects dup route-id; **lexicon assertion** (no "bank"/"account"/"currency"/"dollar"/"euro" — use "Holder"/"Reach"/chain names); **G-003 import-invariant**: the P1-01-02 `go/parser` scan (extended to cover the new `x/bridge` + `x/exit` files) asserts NO production file imports another `x/<module>/types` by struct. | `go test ./x/bridge/...` passes; ≥80% coverage on `x/bridge/types`; BridgeStatusCount=4 locked-const; lexicon green; G-003 import-invariant green | P4-01-01 |
| P4-02-02 | REQ-010, REQ-012 | backend-engineer | `x/exit/types/types_test.go` (+ `genesis_test.go` if split) | Locked-const test: `ExitStatusCount == 5`; `AllExitStatuses()` names match (Proposed, InProgress, Settled, Failed, Refunded); `ExitRoute` struct round-trip; `DEXSwap` struct round-trip; the `bridge-route-id` field references a BridgeRoute by string (no `x/bridge` struct import — G-003 verified); `venue` is an opaque string (A-308 — not a locked enum, so no enum-count test); `ValidateGenesis` rejects dup route-id + dup swap-id; **lexicon assertion** (no "account"/"currency"/"dollar"/"euro" — use "Holder"/"Reach"/opaque asset strings). | `go test ./x/exit/...` passes; ≥80% coverage on `x/exit/types`; ExitStatusCount=5 locked-const; lexicon green; G-003 import-invariant green | P4-02-01 |
### Wave 4 — x/bearers extension + x/partner extension (parallel; independent of Waves 1-3)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P4-03-01 | REQ-022 | backend-engineer | `x/bearers/types/types.go` (EXTEND existing) | **EXTEND** `x/bearers` (do NOT create new module — A-209/D-037; the BearerType enum + BearerTransport interface are locked since v0.1/v0.2). Add `OYSATLink` struct (gateway-id, constellation (opaque string e.g. "iridium"), frequency-mhz, surveillance-resistant LOCKED true for OY-SAT — A-311). Add `OYQRCode` struct (qr-id, payload-bytes (the signed transfer), issuer-reach-id, expires-at, consumed (bool — OY-QR is one-shot, A-311)). Both are transport-shape stubs (matching D-029: the v0.2 OYLRLink/BeaconFrame are struct stubs, not BearerTransport impls; v0.3 keeps the same shape-only approach). The existing `BearerType` enum + `AllBearers()` (6 bearers, including BearerOYSAT + BearerOYQR since v0.1) is UNCHANGED — v0.3 adds transport structs only. `GenesisState` unchanged. | `go build ./x/bearers/...` succeeds; `OYSATLink` + `OYQRCode` structs present; `OYSATLink.SurveillanceResistant` is LOCKED true; `OYQRCode.Consumed` field exists; existing `AllBearers()` unchanged (6 bearers — regression); zero external deps | — |
| P4-04-01 | REQ-023 | backend-engineer | `x/partner/types/types.go` (EXTEND existing) | **EXTEND** `x/partner` (do NOT create new module — A-305; the 4-tier PartnerTier enum is locked since v0.2). Add `AnchorCredential` struct (partner-id (by-ID-string ref to the Anchor Partner), jurisdiction (opaque string e.g. "EU-MiCA"), custody-provider-id (by-ID-string ref to `x/hub` custody service — EMPTY in v0.3 skeleton per A-304, hub not live until P5/v0.4), attestation-refs []string (opaque URIs to Watcher/auditor attestations), onboarded-at). Add `Partner.AnchorCredential() *AnchorCredential` accessor stub returning nil for non-Anchor tiers (A-305 prefers the accessor over a second top-level type). Add `Keeper.AddAnchorCredential(partnerID, cred)` convenience method (rejects non-Anchor partner-id); `Keeper.ListAnchors()` = `ListByTier(TierAnchor)` alias. `PartnerTier` enum (4 tiers) UNCHANGED — v0.3 adds Anchor-specific fields, not a new tier. | `go build ./x/partner/...` succeeds; `AnchorCredential` struct present; `Partner.AnchorCredential()` returns nil for non-Anchor; `AddAnchorCredential` rejects non-Anchor partner-id; `AllPartnerTiers()` unchanged (4 tiers — regression); `custody-provider-id` field is a string (no `x/hub` import — G-003; x/hub does not exist yet, lands in P5) | — |
### Wave 5 — x/bearers + x/partner tests (parallel; blocked-by Wave 4)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P4-03-02 | REQ-022, REQ-012 | backend-engineer | `x/bearers/types/types_test.go` (EXTEND existing) | `OYSATLink` struct round-trip + `SurveillanceResistant == true` (LOCKED — A-311); `OYQRCode` struct round-trip + `Consumed` flips true (one-shot); BearerOYSAT + BearerOYQR still in `AllBearers()` (regression: existing v0.1/v0.2 bearers tests still green — 6 bearers unchanged); existing v0.2 OYLRLink/BeaconFrame tests still green (no regression); **lexicon assertion** (extend existing). | `go test ./x/bearers/...` passes; ≥80% coverage on `x/bearers/types`; OY-SAT surveillance-resistant LOCKED true; OY-QR one-shot; existing v0.1/v0.2 bearers tests green (no regression) | P4-03-01 |
| P4-04-02 | REQ-023, REQ-012 | backend-engineer | `x/partner/types/types_test.go` (EXTEND existing) | `AnchorCredential` struct round-trip; `Partner.AnchorCredential()` returns nil for non-Anchor tiers; `AddAnchorCredential` rejects non-Anchor partner-id; `ListAnchors()` returns only Anchor-tier partners; `AllPartnerTiers()` unchanged (4 tiers — regression: v0.2 partner tests still green); `custody-provider-id` is an opaque string (no `x/hub` import — G-003 import-invariant green); **lexicon assertion** (extend existing — no "bank"/"account"; "custody"/"jurisdiction"/"compliance" safe). | `go test ./x/partner/...` passes; ≥80% coverage on `x/partner/types`; Anchor accessor + AddAnchorCredential behavior; existing v0.2 partner tests green (no regression) | P4-04-01 |
### Wave 6 — Phase verification + ship
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P4-05-01 | REQ-012, REQ-010, REQ-022, REQ-023 | lead-developer | (cross-cutting) | Run `go build ./...` + `go test ./...` green (incl. v0.1/v0.2 baseline + docs firewall + new x/bridge, x/exit, x/bearers ext, x/partner ext); coverage ≥80% on the 4 P4 packages; 4 lexicon assertions present; G-003 import-invariant green (extended to scan the new x/bridge + x/exit + x/bearers + x/partner files); `lexicon_meta_test.go` (v0.2, x/*.go scan) green; `lexicon_meta_docs_test.go` (v0.3, docs scan) green; zero external deps (go.mod unchanged); tag `v0.2.4`. | `go test ./...` green; coverage ≥80% on `x/bridge/types`, `x/exit/types`, `x/bearers/types`, `x/partner/types`; 4 lexicon assertions; G-003 import-invariant green; zero require lines in go.mod; git tag `v0.2.4` | P4-01-02, P4-02-02, P4-03-02, P4-04-02 |
### P4 Must-Haves
- [ ] `x/bridge` (new), `x/exit` (new), `x/bearers` (extended), `x/partner` (extended) each have `types/types.go` + `types/types_test.go` (v0.1/v0.2 pattern, package `types`, zero external deps).
- [ ] `go build ./...` and `go test ./...` green — **including all v0.1/v0.2 baseline tests + docs firewall (no regression)**.
- [ ] ≥80% coverage on `x/bridge/types`, `x/exit/types`, `x/bearers/types`, `x/partner/types`.
- [ ] Bridge locked-const: `BridgeStatusCount == 4` (Pending, Attested, Active, Closed).
- [ ] Exit locked-const: `ExitStatusCount == 5` (Proposed, InProgress, Settled, Failed, Refunded).
- [ ] Exit `bridge-route-id` is a by-ID-string ref to `x/bridge` (G-003 — no struct import; import-invariant test green).
- [ ] Bearers: `OYSATLink` (surveillance-resistant LOCKED true) + `OYQRCode` (one-shot `consumed`); existing `AllBearers()` (6) unchanged.
- [ ] Partner: `AnchorCredential` struct + `Partner.AnchorCredential()` accessor (nil for non-Anchor); `PartnerTier` (4) unchanged.
- [ ] Partner Anchor `custody-provider-id` is an opaque string (no `x/hub` import — x/hub lands in P5).
- [ ] Lexicon assertion in all 4 P4 test files.
- [ ] `lexicon_meta_test.go` (v0.2, x/*.go) green; `lexicon_meta_docs_test.go` (v0.3, docs) green.
- [ ] Zero external deps (go.mod unchanged — G-006).
- [ ] Git tag `v0.2.4`.
### P4 Risks & Mitigations
- **Intra-P4 ordering (bridge before exit)** (A-308/G-003) → Wave 1 lands `x/bridge` types; Wave 2 lands `x/exit` (references bridge by ID); Wave 3 lands both tests. Reversing would force `x/exit` tests to reference a non-existent BridgeRoute type.
- **"venue" as a locked enum** (A-308) → `venue` is an opaque string, NOT a locked enum; venues are operational (uniswap-v3/v4, oy-dex) and locking now would create a false firewall. Test asserts no enum-count for venue.
- **Bearers extension regression** → existing v0.1/v0.2 bearers tests must stay green; `AllBearers()` count unchanged (6); test asserts no regression.
- **Partner Anchor → hub forward-reference** → `custody-provider-id` is an EMPTY string in v0.3 (hub not live until P5); the field exists so the shape is stable. This is the P4→P5 edge (D-044).
- **"account"/"currency"/"dollar"/"euro" lexicon drift in exit** → use "Holder"/"Reach"/opaque asset strings; lexicon assertion + meta-test are the gate.
---
## Phase P5 — Bearers Skeleton II (hub/services/bond)
- **Slug**: `bearers-skeleton-ii`
- **Branch**: `oy/phase/05-bearers-skeleton-ii`
- **REQs covered**: REQ-024 (Hub API — x/hub), REQ-025 (Services — x/services), REQ-026 (Bond market depth — x/bond extension)
- **Tag**: `v0.2.5`
- **Type**: `feat`
- **Persona**: backend-engineer
- **Goal**: Ship the Bearers skeleton II: `x/hub` (HubService enum + per-service stubs, referencing Anchor partners by ID), `x/services` (ServiceKind enum + per-service stubs, referencing Window by ID), and `x/bond` extension (GrowthBond + secondary-market order types; 8%/0% consts unchanged — D-028 regression firewall). P5 has NO intra-phase ordering (hub, services, bond are independent of each other).
### Wave 1 — x/hub types + tests (blocked-by P4 partner Anchor for the operator-partner-id reference)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P5-01-01 | REQ-024 | backend-engineer | `x/hub/types/types.go` + `x/hub/types/genesis.go` + `x/hub/types/types_test.go` (+ `genesis_test.go` if split) | New `x/hub/types/` module following `x/forex` (D-039, A-303). `HubService` enum (Custody, LendingPrimitive, Compliance) — exactly 3, locked-const `HubServiceCount = 3` (A-312); `AllHubServices() []HubService`. `HubServiceInfo` struct (service-id, kind (HubService), operator-partner-id (by-ID-string ref to `x/partner` Anchor — G-003, no struct import; the P4 Anchor must exist), name, status). `HubServiceStatus` enum (Pending, Active, Suspended, Revoked) — exactly 4 (local redefinition of the v0.2 PartnerStatus 4-state shape, no import). Per-service struct stubs: `CustodyService` (service-id, custody-provider-id, assets-supported []string), `LendingPrimitiveService` (service-id, primitive-kind (opaque string), coupon-cap-bps uint32 — LOCAL const `LendingCouponCapBps = 800` cross-documented to D-028/A-304, NOT an import of `x/bond.Clamp`), `ComplianceService` (service-id, jurisdiction, attestation-refs []string). `Keeper` stub: AddService / GetService / ListByKind. `Params`, `GenesisState` (services), `DefaultGenesisState`, `ValidateGenesis` (reject dup service-ids, A-212). **Tests**: HubServiceCount=3 locked-const; enum names; service round-trip; per-service struct fields; `LendingCouponCapBps == 800` (cross-doc to D-028); `operator-partner-id` is a string (no `x/partner` struct import — G-003 import-invariant green); `ValidateGenesis` rejects dup service-id; **lexicon assertion** (HIGH-RISK: "interest"/"yield"/"deposit"/"savings" banned — use "lending primitive"/"coupon"/"custody"/"compliance"; "lending" is NOT banned per RESEARCH §1.5). | `go build ./x/hub/...` succeeds; `go test ./x/hub/...` passes; ≥80% coverage; `HubServiceCount == 3`; `LendingCouponCapBps == 800`; lexicon green; G-003 import-invariant green | P4-05-01 |
### Wave 2 — x/services types + tests (parallel with Wave 1; independent)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P5-02-01 | REQ-025 | backend-engineer | `x/services/types/types.go` + `x/services/types/genesis.go` + `x/services/types/types_test.go` (+ `genesis_test.go` if split) | New `x/services/types/` module following `x/hub` (D-040, A-307). `ServiceKind` enum (Care, SIM, Vault, Mail) — exactly 4, locked-const `ServiceKindCount = 4` (A-307); `AllServiceKinds() []ServiceKind`. `ServiceInfo` struct (service-id, kind (ServiceKind), operator-reach-id (by-ID-string ref to `x/identity` Reach — G-003), name, status, window-id (by-ID-string ref to `x/window` — a service-grant opens a Window on the holder's behalf; the Window Lifecycle interface hook, typed in v0.3, invoked at runtime in v0.4)). `ServiceStatus` enum (Pending, Active, Suspended, Revoked) — exactly 4 (local redefinition). Per-service struct stubs: `CareService` (service-id, care-kind (opaque)), `SIMService` (service-id, carrier (opaque)), `VaultService` (service-id, storage-quota-grain), `MailService` (service-id, mailbox-id). `Keeper` stub: AddService / GetService / ListByKind. `Params`, `GenesisState` (services), `DefaultGenesisState`, `ValidateGenesis` (reject dup service-ids, A-212). **Tests**: ServiceKindCount=4 locked-const; enum names (Care, SIM, Vault, Mail); service round-trip; per-service struct fields; `window-id` is a string (no `x/window` struct import — G-003 import-invariant green); `operator-reach-id` is a string (no `x/identity` import); `ValidateGenesis` rejects dup service-id; **lexicon assertion** (no "account" — use service-id/operator-reach-id; "Mail"/"SIM"/"Care"/"Vault" safe). | `go build ./x/services/...` succeeds; `go test ./x/services/...` passes; ≥80% coverage; `ServiceKindCount == 4`; lexicon green; G-003 import-invariant green | P4-05-01 (P5 has no intra-phase dep; blocked-by P4 ship for branch hygiene + the G-003 import-invariant test scanning the new files) |
### Wave 3 — x/bond extension (GrowthBond + secondary market) + tests (parallel with Waves 1/2; independent)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P5-03-01 | REQ-026 | backend-engineer | `x/bond/types/types.go` (EXTEND) + `x/bond/types/genesis.go` (EXTEND) + `x/bond/types/types_test.go` (EXTEND) | **EXTEND** `x/bond` (do NOT create new module — D-041; the 8%/0% consts are locked since v0.2 and UNCHANGED in v0.3). Add `GrowthBond` struct embedding the v0.2 `Bond` + a `GrowthRateBps` field (per-period growth rate of the coupon). Add `ClampGrowth(currentBps, growthBps uint32) uint32` helper returning `min(CouponCapBps - currentBps, growthBps)` so the post-growth coupon is ≤ `CouponCapBps` (A-306 — reuses the v0.2 `CouponCapBps`/`CouponFloorBps` consts, same package, no G-003 concern). Add `SecondaryOrder` struct (order-id, bond-id (by-ID-string ref to the Bond), side (`OrderSide` enum), price-bps (fraction of principal in bps), quantity-grain, holder-reach-id, status (`OrderStatus` enum), created-at). Add `OrderSide` enum (Buy, Sell) — exactly 2, locked-const `OrderSideCount = 2` (A-313). Add `OrderStatus` enum (Open, Filled, Cancelled) — exactly 3, locked-const `OrderStatusCount = 3` (A-313). `AllOrderSides()` / `AllOrderStatuses()`. Extend `Keeper` stub: AddOrder / GetOrder / ListByBond / CancelOrder (no matching — full secondary-market matching deferred to v0.4). Extend `GenesisState` with `GrowthBonds []GrowthBond` + `Orders []SecondaryOrder`; `ValidateGenesis` checks growth-bond-id + order-id uniqueness (A-212). **Tests (extend existing)**: **REGRESSION: `CouponCapBps == 800` and `CouponFloorBps == 0` STILL (D-028 firewall — v0.3 must not change the v0.2 consts)**; `ClampGrowth` invariant (post-growth coupon ≤ 800, never below 0; current + growth where current+growth > cap → growth clamped to cap-current); `OrderSideCount == 2`; `OrderStatusCount == 3`; order round-trip; GrowthBond round-trip; `bond-id` is a string (no struct self-import — same package); existing v0.2 bond tests still green (Clamp, BondStatus, etc. — no regression); **lexicon assertion** (HIGH-RISK: "interest"/"yield"/"deposit"/"savings" banned — use "coupon"/"growth"/"secondary"/"order"; "growth" safe, "yield growth" banned — use "coupon growth"/"real-return-linked coupon"). | `go build ./x/bond/...` succeeds; `go test ./x/bond/...` passes; ≥80% coverage; **`CouponCapBps == 800` + `CouponFloorBps == 0` regression green**; `ClampGrowth` invariant green; `OrderSideCount == 2` + `OrderStatusCount == 3`; existing v0.2 bond tests green (no regression); lexicon green | P4-05-01 |
### Wave 4 — Phase verification + ship
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P5-04-01 | REQ-012, REQ-024, REQ-025, REQ-026 | lead-developer | (cross-cutting) | Run `go build ./...` + `go test ./...` green (incl. v0.1/v0.2 baseline + docs firewall + P4 + P5); coverage ≥80% on `x/hub/types`, `x/services/types`, `x/bond/types`; 3 lexicon assertions (hub, services, bond-ext); G-003 import-invariant green (extended to scan x/hub + x/services + x/bond); `lexicon_meta_test.go` (v0.2) + `lexicon_meta_docs_test.go` (v0.3) green; **D-028 regression: 8%/0% bond consts unchanged**; zero external deps (go.mod unchanged); tag `v0.2.5`. | `go test ./...` green; coverage ≥80% on `x/hub/types`, `x/services/types`, `x/bond/types`; 3 lexicon assertions; G-003 import-invariant green; `CouponCapBps == 800` + `CouponFloorBps == 0` regression green; zero require lines in go.mod; git tag `v0.2.5` | P5-01-01, P5-02-01, P5-03-01 |
### P5 Must-Haves
- [ ] `x/hub` (new), `x/services` (new), `x/bond` (extended) each have `types/types.go` + `types/types_test.go`.
- [ ] `go build ./...` and `go test ./...` green — including v0.1/v0.2 baseline + docs firewall + P4 (no regression).
- [ ] ≥80% coverage on `x/hub/types`, `x/services/types`, `x/bond/types`.
- [ ] Hub locked-const: `HubServiceCount == 3` (Custody, LendingPrimitive, Compliance); `LendingCouponCapBps == 800` (cross-doc to D-028, local const — no `x/bond` import).
- [ ] Hub `operator-partner-id` is a by-ID-string ref to `x/partner` Anchor (G-003 — no struct import; import-invariant green). This confirms P4→P5 ordering.
- [ ] Services locked-const: `ServiceKindCount == 4` (Care, SIM, Vault, Mail).
- [ ] Services `window-id` is a by-ID-string ref to `x/window` (G-003); `operator-reach-id` is a by-ID-string ref to `x/identity`.
- [ ] Bond: `GrowthBond` + `ClampGrowth` (post-growth coupon ≤ 800); `OrderSideCount == 2` (Buy/Sell); `OrderStatusCount == 3` (Open/Filled/Cancelled).
- [ ] **D-028 regression: `CouponCapBps == 800` and `CouponFloorBps == 0` unchanged** (v0.3 must not change v0.2 bond consts).
- [ ] Existing v0.2 bond tests still green (no regression).
- [ ] Lexicon assertion in all 3 P5 test files.
- [ ] `lexicon_meta_test.go` (v0.2, x/*.go) green; `lexicon_meta_docs_test.go` (v0.3, docs) green.
- [ ] Zero external deps (go.mod unchanged — G-006).
- [ ] Git tag `v0.2.5`.
### P5 Risks & Mitigations
- **Hub lending-primitive lexicon risk** (HIGHEST v0.3 lexicon risk after x/bond) → "interest"/"yield"/"deposit"/"savings" are natural fit-words for a lending primitive; use "lending primitive"/"coupon" (vision §13/§17). "lending" is NOT banned (RESEARCH §1.5); the lexicon assertion is the gate. The local `LendingCouponCapBps = 800` const cross-documents D-028 (A-304) to avoid importing `x/bond.Clamp` (G-003).
- **GrowthBond "yield growth" phrasing** → use "coupon growth"/"real-return-linked coupon"; "yield" is banned standalone (word-boundary); `TestLexiconMetaNoFalsePositiveOnOpenYield` allows "OpenYield" but bans "yield".
- **D-028 const regression** → the v0.3 GrowthBond must NOT change `CouponCapBps`/`CouponFloorBps`; the regression test (8%/0% unchanged) is the D-028 firewall.
- **ServiceKind "Vault" naming collision with `x/vault`** → the `Vault` enum value is a service kind (in `x/services`), not a module import; `VaultService` references `x/vault` by ID-string (G-003). No Go import cycle (concept-level collision only).
- **Hub → partner Anchor forward-reference** → P4 must ship before P5 (D-044); the P5-04-01 verification confirms `operator-partner-id` is a string (no `x/partner` struct import).
---
## Phase P6 — Final Review + Audit + Ship
- **Slug**: `final-review-audit-ship`
- **Branch**: `oy/phase/06-final-review-audit-ship`
- **REQs covered**: REQ-012 (lexicon, project-wide meta-test + docs firewall), all v0.3 REQs (REQ-010, REQ-022..REQ-028 audit confirmation)
- **Tag**: `v0.2.6` (= **milestone v0.3 release** — final phase patch IS the milestone release per D-008/D-034)
- **Type**: `final`
- **Personas**: lead-developer (review/ship), backend-engineer (audit assist), ci-code-reviewer + ci-doc-verifier + ci-debugger (CI personas, activated for P6)
- **Goal**: Run the full v0.3 milestone audit — project-wide lexicon meta-test + docs firewall, coverage gate across all 7 new/extended x/* packages, all locked-const invariants green (incl. D-028 regression), all docs pages lexicon-clean, all v0.3 REQs have skeleton+tests or docs — then ship the `v0.3` milestone release as tag `v0.2.6`.
### Wave 1 — ci-code-review (multi-persona review across P1-P5)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P6-01-01 | REQ-012, all v0.3 | lead-developer + ci-code-reviewer | (cross-cutting) | **Code review** across P1-P5: confirm `go build ./...` + `go test ./...` green; confirm `lexicon_meta_test.go` (v0.2, x/*.go) green AND scans all 22 x/* packages (v0.1 15 + v0.2 10 + v0.3 7 = 32? — recount: v0.1=15, v0.2 added 10 new/extended to 25, v0.3 adds 4 new + 3 extended = 7 → 25 + 4 new = 29 distinct packages; the 3 extended are already counted); confirm `lexicon_meta_docs_test.go` (v0.3, docs) green AND scans README.md + all `docs/**/*.md` (26 pages); confirm G-003 import-invariant green across all v0.3 x/* files (no struct imports across `x/<module>/types`); confirm zero external deps (go.mod: `module github.com/oy/openyield\ngo 1.22` with no require lines — G-006). | `go test ./...` green; both firewalls green; G-003 import-invariant green; go.mod zero-dep confirmed; coverage report generated | P5-04-01 |
### Wave 2 — ciagent-audit (reconstruction + discipline)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P6-02-01 | all v0.3 | lead-developer + ci-debugger | (cross-cutting) | **Reconstruction test**: confirm every v0.3 REQ maps to a shipped artifact (REQ-010 → x/bridge + x/exit; REQ-022 → x/bearers OYSATLink/OYQRCode; REQ-023 → x/partner AnchorCredential; REQ-024 → x/hub; REQ-025 → x/services; REQ-026 → x/bond GrowthBond/SecondaryOrder; REQ-027 → README + docs/ 26 pages; REQ-028 → lexicon_meta_docs_test.go). **File/branch/commit discipline**: confirm each phase P1..P5 shipped on its own branch (`oy/phase/0N-*`) with its patch tag (`v0.2.1..v0.2.5`); confirm no phase branch merged out of order (D-044: P1 firewall before P2/P3 content; P4 before P5 for Anchor→hub). **Locked-const audit**: HubServiceCount=3, ServiceKindCount=4, BridgeStatusCount=4, ExitStatusCount=5, OrderSideCount=2, OrderStatusCount=3, LendingCouponCapBps=800, **D-028 regression: CouponCapBps=800 + CouponFloorBps=0 unchanged**. | REQ→artifact map complete (each REQ has a file); branch/tag discipline confirmed (5 phase branches + 5 patch tags); all locked-consts green; D-028 regression green | P6-01-01 |
### Wave 3 — ciagent-ship (merge + tag + release + cleanup)
| Task ID | REQ | Persona | Files | Deliverable | Must-have verification | Blocked-by |
|---|---|---|---|---|---|---|
| P6-03-01 | (milestone) | lead-developer + ci-doc-verifier | `.ciagent/oy/REQUIREMENTS.md` + `.ciagent/oy/ROADMAP.md` | **Update REQUIREMENTS.md**: mark REQ-010, REQ-022, REQ-023, REQ-024, REQ-025, REQ-026 → Skeleton; REQ-027 → Complete; REQ-028 → Complete. **Update ROADMAP.md**: mark v0.3 milestone COMPLETE (all 7 phases P0..P6 checked); add the tag-line note that v0.3 shipped on the `v0.2.x` patch line (P0 → `v0.2.0`, P1..P5 → `v0.2.1..v0.2.5`, P6 → `v0.2.6` = milestone release, per D-008/D-034). | REQUIREMENTS.md status column updated for all 8 v0.3 REQs; ROADMAP.md v0.3 marked complete + tag-line note present | P6-02-01 |
| P6-03-02 | (milestone) | lead-developer | (cross-cutting) | **Final ship**: merge phase/06 → milestone/v0.3 → main; create milestone release tag `v0.2.6` (= v0.3 milestone release per D-008/D-034); delete the 5 phase branches (`oy/phase/01-*`..`oy/phase/05-*`) after merge (P6 branch retained until post-release cleanup); confirm `go build ./...` + `go test ./...` green at the `v0.2.6` tag. | `v0.2.6` tag created on main; `go test ./...` green at the tag; ROADMAP.md v0.3 complete; phase branches deleted (except P6); release notes reference v0.3 scope (Bearers skeleton I+II + docs site + firewall extension) | P6-03-01 |
### P6 Must-Haves
- [ ] Project-wide lexicon meta-test (`lexicon_meta_test.go`, x/*.go) scans all 29 x/* packages (v0.1 15 + v0.2 10 + v0.3 4 new; 3 extended already counted); green.
- [ ] Docs firewall (`lexicon_meta_docs_test.go`) scans README.md + all 26 `docs/**/*.md` pages; green.
- [ ] Coverage ≥80% on all 7 new/extended v0.3 x/* packages (bridge, exit, bearers-ext, partner-ext, hub, services, bond-ext).
- [ ] All locked-const invariants green: HubServiceCount=3, ServiceKindCount=4, BridgeStatusCount=4, ExitStatusCount=5, OrderSideCount=2, OrderStatusCount=3, LendingCouponCapBps=800, OYSATLink surveillance-resistant=true, OYQRCode one-shot consumed.
- [ ] **D-028 regression**: `CouponCapBps == 800`, `CouponFloorBps == 0` unchanged from v0.2.
- [ ] All v0.1/v0.2 baseline tests still green (no regression across 29 x/* packages + docs).
- [ ] G-003 import-invariant green (no struct imports across `x/<module>/types` in any v0.3 production file).
- [ ] Zero external deps (go.mod unchanged — G-006).
- [ ] REQUIREMENTS.md status column updated (REQ-010/022..026 → Skeleton; REQ-027/028 → Complete).
- [ ] ROADMAP.md v0.3 marked COMPLETE + tag-line note (`v0.2.x` patch line).
- [ ] `go build ./...` and `go test ./...` green at the `v0.2.6` tag.
- [ ] Git tag `v0.2.6` created (= v0.3 milestone release).
- [ ] Phase branches P1..P5 deleted post-merge (P6 retained until post-release cleanup).
### P6 Risks & Mitigations
- **Lexicon drift via copy-pasted comments in v0.3 x/* modules** → the v0.2 meta-test scans comments + strings + identifiers; v0.3 modules are automatically covered (no new meta-test work, just the existing scan).
- **D-028 const regression at the last mile** → P5-03-01 + P6-02-01 both assert 8%/0% unchanged; double firewall.
- **Milestone versioning confusion (v0.3 milestone = v0.2.6 tag)** → lead-developer enforces D-008/D-034: final phase patch IS the milestone release; no separate minor tag. ROADMAP tag-line note (P6-03-01) prevents `v0.2.6`/`v0.3.0` confusion.
---
## Coverage Targets (D-033) — v0.3
| Package | Phase | Target | Locked-const tests |
|---|---|---|---|
| `x/bridge/types` | P4 | ≥80% | BridgeStatusCount=4 (Pending, Attested, Active, Closed) |
| `x/exit/types` | P4 | ≥80% | ExitStatusCount=5 (Proposed, InProgress, Settled, Failed, Refunded) |
| `x/bearers/types` (ext) | P4 | ≥80% | OYSATLink surveillance-resistant=true (A-311); OYQRCode one-shot consumed; AllBearers()=6 unchanged (regression) |
| `x/partner/types` (ext) | P4 | ≥80% | AllPartnerTiers()=4 unchanged (regression); AnchorCredential accessor nil-for-non-Anchor |
| `x/hub/types` | P5 | ≥80% | HubServiceCount=3; LendingCouponCapBps=800 (cross-doc D-028/A-304) |
| `x/services/types` | P5 | ≥80% | ServiceKindCount=4 (Care, SIM, Vault, Mail) |
| `x/bond/types` (ext) | P5 | ≥80% | **CouponCapBps=800 + CouponFloorBps=0 unchanged (D-028 regression)**; ClampGrowth post-growth ≤ 800; OrderSideCount=2; OrderStatusCount=3 |
**Lexicon assertions (REQ-012)**: present in all 7 new/extended v0.3 test files (per-package) + project-wide `lexicon_meta_test.go` (v0.2, x/*.go — automatically covers v0.3 x/* files) + `lexicon_meta_docs_test.go` (v0.3, README.md + docs/**/*.md).
---
## Task Count Summary — v0.3
| Phase | Waves | Tasks | New/Extended Packages / Docs |
|---|---|---|---|
| P1 | 3 | 11 | lexicon_meta_docs_test.go + mkdocs.yml + README.md + docs/index.md + 6 docs/shared/ pages |
| P2 | 2 | 9 | 8 docs/nomads/ pages |
| P3 | 3 | 12 | 8 docs/freeholders/ pages + 2 docs/reference/ pages |
| P4 | 6 | 9 | x/bridge (new), x/exit (new), x/bearers (ext), x/partner (ext) |
| P5 | 4 | 5 | x/hub (new), x/services (new), x/bond (ext) |
| P6 | 3 | 4 | (audit/ship, 0 new — audit + REQUIREMENTS/ROADMAP update + tag) |
| **Total** | — | **50** | **4 new x/* + 3 extended x/* + 26 docs pages + 1 firewall test** |
## Per-Phase REQ Coverage — v0.3
| Phase | REQs | Components / Docs |
|---|---|---|
| P1 | REQ-028, REQ-027 | Docs firewall (lexicon_meta_docs_test.go) + mkdocs.yml + README + docs/index + docs/shared (6 pages) |
| P2 | REQ-027 | docs/nomads (8 pages: Reach, Stash, bearers, Maps/Pay, Pacts, standing-basics, Window, index) |
| P3 | REQ-027 | docs/freeholders (8 pages) + docs/reference (2 pages) — REQ-027 COMPLETE |
| P4 | REQ-010, REQ-022, REQ-023 | x/bridge + x/exit (Exit layer), x/bearers OY-SAT/OY-QR, x/partner Anchor |
| P5 | REQ-024, REQ-025, REQ-026 | x/hub, x/services, x/bond GrowthBond + secondary |
| P6 | REQ-012 + all v0.3 REQs (audit) | Both firewalls, coverage gate, D-028 regression, milestone ship |
## Cross-Phase Blockers (hard) — v0.3
- **P1-01-01 (docs firewall)** → blocks P1-02-* (README + shared content scanned by the firewall) and P2/P3 (audience content scanned).
- **P4-01-01 (x/bridge types)** → blocks P4-02-01 (x/exit — `bridge-route-id` refs BridgeRoute by ID-string, A-308/G-003).
- **P4-04-01 (x/partner Anchor extension)** → blocks P5-01-01 (x/hub — `operator-partner-id` refs Anchor by ID-string, A-304/G-003). This is the P4→P5 edge (D-044).
- **P5-04-01 (P5 ship)** → blocks P6-01-01 (P6 audit).
- All P(N) phase-ship tasks block P(N+1) Wave 1 tasks (soft ordering for branch hygiene; types themselves only depend on the listed hard blockers).
## v0.3 Decisions Applied (D-034..D-046 + A-301..A-315)
The v0.3 Phase 0 clarify/ideate/research stages produced 13 clarification decisions (D-034..D-046) and 15 research assumptions (A-301..A-315), all applied to this plan:
| ID | Decision / Assumption | Applied to |
|---|---|---|
| D-034 | v0.3 bundles Bearers skeleton + docs under one feature milestone; tags on v0.2.x | Milestone Summary, all phases |
| D-035 | Bearers skeleton continues D-020 pattern (no live chain) | P4, P5 |
| D-036 | REQ-010 = x/exit + x/bridge (two packages) | P4 Waves 1-3 |
| D-037 | REQ-022 = x/bearers OYSATLink + OYQRCode | P4 Wave 4 |
| D-038 | REQ-023 = x/partner AnchorCredential extension (no new tier) | P4 Wave 4 |
| D-039 | REQ-024 = x/hub new module (Pact #6 promoted) | P5 Wave 1 |
| D-040 | REQ-025 = x/services new module (4 kinds) | P5 Wave 2 |
| D-041 | REQ-026 = x/bond GrowthBond + secondary (8%/0% unchanged) | P5 Wave 3 |
| D-042 | MkDocs Material; audience-organized docs | P1-01-02, P2, P3 |
| D-043 | Docs firewall = sibling test lexicon_meta_docs_test.go (not modifying v0.2 meta-test) | P1-01-01 |
| D-044 | Phase ordering: firewall-first (P1) before content (P2/P3); P4 before P5 (Anchor→hub) | Cross-Phase Dependency Map, all phase goals |
| D-045 | Docs depth: ~20-25 pages across 4 audiences | P1/P2/P3 page counts |
| D-046 | No docs publishing CI in v0.3 | P1-01-02, P1-02-01 |
| A-304 | x/hub LendingCouponCapBps=800 local const (no x/bond import) | P5-01-01 |
| A-308 | x/exit venue is opaque string (not locked enum) | P4-02-01 |
| A-311 | OY-SAT surveillance-resistant LOCKED true; OY-QR one-shot | P4-03-01 |
| A-312 | HubServiceCount=3 | P5-01-01 |
| A-313 | OrderSideCount=2, OrderStatusCount=3 | P5-03-01 |
| A-315 | v0.2 cosmos-engineer/security-engineer NOT reactivated | Persona assignments (backend-engineer owns all P4/P5) |
+60 -23
View File
@@ -61,33 +61,46 @@ OpenYield (OY) is a durable, anti-greed, jurisdiction-light financial layer —
- D-009: Rebased history to fix v1.0 → v0.1 in ---ci--- blocks
## Milestone
v0.2The Mesh (active milestone; feature type; tags run on the v0.1.x patch line)
v0.3Bearers & Documentation (active milestone; feature type; tags run on the v0.2.x patch line)
### v0.2 Scope (The Mesh — ROADMAP Phase 2)
Target: $1B annual volume, 4 service categories. Implements the pending Mesh-era requirements:
- **REQ-009** Satellite chains (Layer 2) — wrapped Bread, Pass-Act propagation on Polygon/Base/Arbitrum/Optimism/Solana [§7]
- **REQ-011** Three Councils (Mesh, Guild, Stand) with Mission Lock — multi-source Voice [§19]
- **REQ-015** Window primitive — scope, duration, rate-limit, audit log, revoke [§10]
- **REQ-016** Nine Stand types (Household, Crew, Entity, Co-op, Circle, Trust, Foundation, Confederation, Shadow) [§11]
- **REQ-017** Guilds with Hand-Passes at 0% protocol fee [§12]
- **REQ-018** Four-tier Partner Spectrum (Op, Master Op, Pier, Anchor) [§13]
- **REQ-020** Six Pacts (Pause, Ground, Stance, Cover, Stand Registry, Hub API) [§16]
- **REQ-021** Mesh Bond Market with 8% upper coupon cap, 0% floor [§17]
- Bearers expansion: OY-LR + Beacon v1
- Forex Engine v1
### v0.3 Scope (Bearers skeleton + Docs site — ROADMAP Phase 3 partial, plus a docs deliverable)
This milestone bundles two parallel work-streams under one feature milestone:
**(A) Bearers skeleton (D-020 pattern continued)** — implements the v0.1 PROJECT.md
out-of-scope items now promoted to v0.3 (ROADMAP Phase 3 "The Bearers" subset),
as skeleton + tests (Go types + keeper stubs + invariant tests; no live chain):
- **REQ-010** Exit layer (Layer 3) — DEX swaps, bridges, off-mesh services (§7). Promoted from Skeleton to a fuller skeleton: `x/exit` (exit-route types) + `x/bridge` (L2↔L1 bridge types). Live runtime deferred to v0.4.
- **Bearers expansion** — OY-SAT (satellite) + OY-QR bearer transport types, extending `x/bearers` (D-029 pattern). Hardware integration deferred.
- **Anchors** — first institutional Partner tier (`x/partner` extension: Anchor credential types). REQ-018 promoted from Skeleton → fuller skeleton.
- **Hub API** — B2B backbone: custody, lending primitive, compliance types (`x/hub`). Full B2B suite deferred to v0.4.
- **Services** — Care / SIM / Vault / Mail service types (`x/services`). Live services deferred.
- **Bond market depth** — Growth Bonds + secondary-market types, extending `x/bond` (REQ-021 promoted from Skeleton → fuller skeleton). Full market depth deferred.
**(B) Documentation deliverable** — README.md + docs site in `docs/` for nomads and freeholders:
- Repo-root `README.md` (lexicon-clean project overview).
- MkDocs Material site (`mkdocs.yml` + `docs/`), organized by audience:
- `docs/nomads/` — Reach path, Stash, bearers, Maps/Pay, six Pacts, standing basics.
- `docs/freeholders/` — Four Freeholder signals, Bayesian Standing, Stands/Guilds, Councils/Voice, Bonds, Partner spectrum.
- `docs/shared/` — Six Principles, Bread Scale, Storage pools, Watchers/Mirror, Lexicon glossary, Vision overview.
- `docs/reference/` — architecture index, component map.
- **REQ-012 firewall extension** — extend the lexicon meta-test to scan `README.md` + `docs/**/*.md` (new sibling `lexicon_meta_docs_test.go`), so the docs site is durably lexicon-clean. This is a `feat/test` phase.
### Milestone Type
Feature (at least one `feat` phase). Phase 0 → `v0.1.0`; execution phases `v0.1.1..v0.1.N`; final phase patch IS the milestone release. No separate minor tag.
Feature (Bearers phases are feat; docs phases are docs/test). Phase 0 → `v0.2.0`; execution phases `v0.2.1..v0.2.5`; final phase patch `v0.2.6` IS the milestone release. No separate minor tag.
### Out of Scope (v0.2)
- Cross-chain exit / DEX integration (Phase 3 / v0.3)
- OY-SAT, OY-QR bearers (Phase 3)
- Full Hub API B2B suite (Phase 3)
- Yield Token, Travel + 11 service categories (Phase 4)
- Full Mesh Bond market depth (Phase 3+; v0.2 ships first Mesh Bonds only)
### Out of Scope (v0.3)
- Live chain launch / real IBC channels / real bearer transports (D-020 pattern continues)
- DEX integration runtime, full Hub API B2B suite runtime (types only in v0.3)
- Yield Token, Travel + 11 service categories (ROADMAP Phase 4)
- i18n / versioning in MkDocs (single-language v0.3)
- Cover Pool seniority mechanics (still deferred per PROJECT.md Q7)
### Prior Milestone
v0.1 — OpenYield Foundation Init (COMPLETE; pre-MVP foundation skeleton; released as v0.0.9 per run.md patch-line model)
### Prior Milestones
- v0.1 — OpenYield Foundation Init (COMPLETE; pre-MVP foundation skeleton; released as v0.0.9)
- v0.2 — The Mesh (COMPLETE; skeleton + tests; released as v0.1.5)
## Clarification Decisions (Phase 0 — CLARIFY, autonomy=full)
@@ -108,4 +121,28 @@ Auto-decided defaults logged per clarify workflow Step 4 (full autonomy → acce
| D-030 | **Forex Engine v1**: Forex pair type + rate-oracle interface + stub keeper; no live oracle integration | Live oracle integration depends on external partners (Piers), Phase 3. | 0.80 | [live oracle integration] |
| D-031 | **Phase ordering** follows ARCHITECTURE.md blocker chain: P1 Orgs+Window foundation → P2 Pacts+Partners → P3 Councils+Forex → P4 Bonds+Bearers+L2. The final phase (P5) is review/ship. | Respects dependency graph; vertical slices keep each phase independently shippable. | 0.80 | [different wave ordering] |
| D-032 | **Lexicon** enforced project-wide; all new modules must pass the lexicon assertion test (no banned terms). Non-negotiable. **Note (G-002)**: lexicon assertion tests are NEW in v0.2 — v0.1 is lexicon-clean in practice but has NO lexicon test firewall. v0.2 introduces the firewall (scaffolded in P1 per G-004, extended in P5). | REQ-012 is `All` phases. | 1.00 | [—] |
| D-033 | **Test coverage target**: ≥80% on new keeper/type packages. v0.1 baseline = **53 tests across 11 test files** (corrected per G-001; not 48). Add lexicon assertion to each new module's test file. | Consistency with v0.1 quality bar (53 tests verified); lexicon drift is the highest-severity regression. | 0.85 | [lower coverage bar] |
| D-033 | **Test coverage target**: ≥80% on new keeper/type packages. v0.1 baseline = **53 tests across 11 test files** (corrected per G-001; not 48). Add lexicon assertion to each new module's test file. | Consistency with v0.1 quality bar (53 tests verified); lexicon drift is the highest-severity regression. | 0.85 | [lower coverage bar] |
### v0.3 Clarification Decisions (Phase 0 — CLARIFY, autonomy=full)
Auto-decided defaults logged per clarify workflow Step 4 (full autonomy → accept defaults, log decisions).
| ID | Decision | Rationale | Confidence | Alternatives |
|----|----------|-----------|------------|--------------|
| D-034 | **v0.3 milestone bundles Bearers skeleton (D-020 pattern) + docs deliverable** under one feature milestone, rather than two separate NFR+feature milestones. Bearers phases are `feat`; docs phases are `docs`/`test`. Tags run on `v0.2.x`. | User request (--ideate) is docs-only but ROADMAP Phase 3 (Bearers) is the next queued feature work; bundling keeps the milestone cadence and avoids an NFR-only milestone that would not advance the protocol. Feature type because Bearers phases are feat. | 0.82 | [separate v0.3 docs NFR + v0.4 Bearers feature; or docs as patches on v0.2 line] |
| D-035 | **Bearers skeleton continues the D-020 skeleton+tests pattern** (Go types + keeper stubs + invariant tests; no live chain, no real IBC channels, no real bearer transports). Live runtime for any Bearers component deferred to v0.4+. | v0.1/v0.2 both shipped skeleton-first; v0.3 stays consistent. Live runtime needs Watchers + Root Basket backing (Year 3 target). | 0.85 | [fuller keeper implementations in v0.3] |
| D-036 | **REQ-010 Exit layer**: skeleton = `x/exit` (ExitRoute, DEXSwap types) + `x/bridge` (L2↔L1 bridge types, BridgeStatus enum). No live DEX integration. REQ-010 promoted from v0.1 Skeleton → v0.3 fuller skeleton (two packages instead of one). | Exit runtime needs Anchor partners + L2 bridges; v0.3 lands the typed shape. | 0.80 | [single x/exit package, defer all exit to v0.4] |
| D-037 | **REQ-022 Bearers OY-SAT + OY-QR**: extend `x/bearers/types` with `OYSAT` + `OYQR` bearer transport types (BearerTransport interface already in v0.2). No hardware/RF runtime. D-029 pattern continued. | Hardware integration is not a software deliverable; v0.3 completes the 6-bearer type set (v0.2 had 4: Internet/OY-BLE/OY-WiFi-Direct + OY-LR/Beacon). | 0.82 | [real bearer runtime, defer OY-SAT/OY-QR to v0.4] |
| D-038 | **REQ-023 Anchors**: extend `x/partner/types` with `Anchor` tier credential types (REQ-018 had the 4-tier enum; v0.3 adds Anchor-specific credential fields). No live institutional onboarding. | Anchors need Watchers + Hub API backing; v0.3 lands the credential shape. | 0.78 | [separate x/anchor module, defer Anchors to v0.4] |
| D-039 | **REQ-024 Hub API**: new `x/hub` module — custody, lending-primitive, compliance type stubs (HubService enum + per-service structs). No live B2B runtime. Full Hub API B2B suite deferred to v0.4. | Hub API needs Anchors + Watchers; v0.3 lands the typed scaffold. | 0.80 | [full Hub API runtime in v0.3] |
| D-040 | **REQ-025 Services**: new `x/services` module — Care/SIM/Vault/Mail service type stubs (ServiceKind enum + per-service structs). No live services. | Services are operational, not protocol-level; v0.3 lands the typed shape. | 0.78 | [full services runtime in v0.3] |
| D-041 | **REQ-026 Bond market depth**: extend `x/bond/types` with GrowthBond type + secondary-market order types. 8% cap / 0% floor consts (D-028) unchanged. Full secondary-market matching deferred to v0.4. | v0.2 shipped first issuance; v0.3 adds depth types without a live matching engine. | 0.80 | [full bond market in v0.3] |
| D-042 | **Docs deliverable (REQ-027)**: repo-root `README.md` + MkDocs Material site (`mkdocs.yml` + `docs/`). `mkdocs.yml` at repo root; `docs/` organized by audience: `docs/nomads/`, `docs/freeholders/`, `docs/shared/`, `docs/reference/`. Build-only Python dep (mkdocs + material); `go.mod` stays zero-dep. | User chose MkDocs Material + audience organization. MkDocs is Markdown-native, lightest toolchain; build-only dep does not affect Go modules (G-006). | 0.85 | [Hugo, Docusaurus, plain Markdown no generator] |
| D-043 | **REQ-028 lexicon firewall extension**: new sibling test `lexicon_meta_docs_test.go` (package `lexicon_meta_docs`) scanning `README.md` + `docs/**/*.md` for the 10 banned terms, using the same `lexicon.FindBannedTerm` + word-boundary regex. Self-exclusion + fragment pattern preserved. `.ciagent/` files are NOT scanned (they are firewall meta-files, not user-facing docs). | REQ-012 is `All` phases and docs are user-facing; the firewall must cover docs to be durable. Extending the existing meta-test (not modifying it) preserves v0.2 coverage. | 0.88 | [single combined meta-test scanning both x/ and docs/] |
| D-044 | **Phase ordering**: P1 docs foundation + firewall extension → P2 nomads docs → P3 freeholders docs → P4 Bearers skeleton I (exit/bridge/bearers/partner) → P5 Bearers skeleton II (hub/services/bond) → P6 final review/ship. Firewall lands in P1 BEFORE content (P2/P3) so docs are checked as authored. | Firewall-first ensures docs content is lexicon-clean by construction, not by retrofit. Bearers split across P4/P5 keeps each phase independently shippable (vertical slices). | 0.82 | [Bearers first then docs, or all docs in one phase] |
| D-045 | **Docs depth per audience**: each audience section (nomads, freeholders) gets 5-8 Markdown pages covering its core REQs (nomads: Reach/Stash/bearers/Maps-Pay/Pacts/standing-basics; freeholders: 4 signals/Bayesian Standing/Stands-Guilds/Councils-Voice/Bonds/Partner spectrum). `docs/shared/` gets 5-6 concept pages. `docs/reference/` gets architecture index + component map. Total ~20-25 pages. | Enough depth to be a real docs site, not a placeholder; bounded to keep P1-P3 phases shippable. | 0.80 | [deeper (40+ pages), shallower (10 pages)] |
| D-046 | **No docs-site publishing CI in v0.3**`mkdocs.yml` is buildable locally (`mkdocs serve` / `mkdocs build`); CI publishing to GitHub Pages/Gitea Pages is deferred to v0.4. v0.3 ships the source + a build invocation in the README. | Publishing CI needs deployment secrets + a hosting target; v0.3 lands the content. | 0.82 | [include publishing CI in v0.3] |
### Ideation outcome (Phase 0 — IDEATE stage, autonomy=full)
IDEATE stage ratified 8 ideas (IDEATE-01..IDEATE-08) at full autonomy, mapped to REQ-010/REQ-022..REQ-028. Docs deliverable (IDEATE-01/02) is the user's `--ideate` request; Bearers ideas (IDEATE-03..08) are the ROADMAP Phase 3 subset. Three ideation tiers ran (mechanical, backend-enriched, cross-project); mechanical tier found no `lessons:`/`compound:` tags in v0.1/v0.2 history (convention unused) and v0.2 closed clean (9/9 REQs, 303 tests, ≥95.9% coverage). Defaults accepted per full autonomy; traceability recorded in `.ciagent/oy/REQUIREMENTS.md` (IDEATE Traceability section).
+50
View File
@@ -26,6 +26,56 @@
| Bearers OY-LR + Beacon | (vision §14) | §14 | Medium | Skeleton | v0.2/P4 |
| Forex Engine v1 | (vision §13) | §13 | Medium | Skeleton | v0.2/P3 |
## v0.3 Milestone Requirements (Bearers & Documentation)
| ID | Requirement | Vision § | Priority | Status | Phase |
|----|-------------|----------|----------|--------|-------|
| REQ-010 | Exit layer (Layer 3) — DEX swaps, bridges, off-mesh services | §7 | Medium | Pending | v0.3/P4 |
| REQ-022 | Bearers expansion: OY-SAT + OY-QR bearer transports | §14 | Medium | Pending | v0.3/P4 |
| REQ-023 | Anchors — first institutional Partner tier | §13 | Medium | Pending | v0.3/P4 |
| REQ-024 | Hub API — B2B backbone: custody, lending primitive, compliance | §13 | Medium | Pending | v0.3/P5 |
| REQ-025 | Services — Care / SIM / Vault / Mail | §13 | Medium | Pending | v0.3/P5 |
| REQ-026 | Bond market depth — Growth Bonds + secondary market | §17 | Medium | Pending | v0.3/P5 |
| REQ-027 | README.md + docs site in docs/ for nomads and freeholders | (vision §8) | High | Pending | v0.3/P1-P3 |
| REQ-028 | Extend REQ-012 lexicon firewall to scan docs/ + README.md | §3 | High | Pending | v0.3/P1 |
> REQ-022 through REQ-028 are NEW in v0.3 (ratified during Phase 0 IDEATE as
> IDEATE-01..IDEATE-07, then assigned final REQ-IDs). REQ-010 is promoted from
> v0.1 Skeleton to a fuller v0.3 skeleton.
## IDEATE Traceability (Phase 0 — IDEATE stage, autonomy=full)
The IDEATE stage ran the three ideation tiers (mechanical, backend-enriched,
cross-project) on the v0.3 milestone scope and ratified 8 ideas (IDEATE-01..
IDEATE-08) at full autonomy. Each IDEATE-NN maps to a REQ-ID in the v0.3
requirements table above. Mechanical tier: no `lessons:`/`compound:` tags in
v0.1/v0.2 history (convention unused); one historical escalation (milestone
release pending — no remote) resolved in v0.2; v0.2 closed clean (9/9 REQs,
303 tests, ≥95.9% coverage). Backend-enriched + cross-project tiers confirmed
the docs deliverable + Bearers skeleton bundle (D-034) and the firewall-first
ordering (D-044). Defaults accepted per full autonomy.
| IDEATE ID | REQ-ID | Category | Source | Confidence | Phase |
|-----------|--------|----------|--------|------------|-------|
| IDEATE-01 | REQ-027 | improvement/docs | user `--ideate` request + D-042/D-045 | 0.90 | v0.3/P1-P3 |
| IDEATE-02 | REQ-028 | quality/security | D-043 + RESEARCH firewall-extension design | 0.88 | v0.3/P1 |
| IDEATE-03 | REQ-010 | coverage/architecture | ROADMAP Phase 3 + D-036 | 0.80 | v0.3/P4 |
| IDEATE-04 | REQ-022 | coverage | ROADMAP Phase 3 + D-037 | 0.82 | v0.3/P4 |
| IDEATE-05 | REQ-023 | coverage | ROADMAP Phase 3 + D-038 | 0.78 | v0.3/P4 |
| IDEATE-06 | REQ-024 | architecture | ROADMAP Phase 3 + D-039 | 0.80 | v0.3/P5 |
| IDEATE-07 | REQ-025 | coverage | ROADMAP Phase 3 + D-040 | 0.78 | v0.3/P5 |
| IDEATE-08 | REQ-026 | coverage | ROADMAP Phase 3 + D-041 | 0.80 | v0.3/P5 |
Notes:
- IDEATE-01/02 (docs deliverable + firewall) are the user's `--ideate` request
ratified via D-042/D-043/D-045.
- IDEATE-03..08 (Bearers skeleton) are the ROADMAP Phase 3 subset bundled into
v0.3 per D-034.
- IDEATE-02 lands in P1 (firewall-first) BEFORE IDEATE-01 content (P2/P3) per
D-044 — docs are lexicon-clean by construction.
- IDEATE-03..05 ship in P4 (Bearers skeleton I); IDEATE-06..08 ship in P5
(Bearers skeleton II) — vertical slices, each phase independently shippable.
## Milestone v0.1 Summary
- 10 REQs complete (skeleton + tests)
- 2 REQs skeleton (REQ-001 principles, REQ-008 chain)
+660 -1
View File
@@ -629,4 +629,663 @@ compiling with `go build ./...` and `go test ./...` using only stdlib. Rationale
| REQ-012 | Lexicon | (all) | all | Enforced everywhere — D-032 |
**New modules: 9. Extended modules: 1 (bearers). Total v0.2 packages: 10 new +
1 extended = 11 packages added to the v0.1 baseline of 15.**
1 extended = 11 packages added to the v0.1 baseline of 15.**
---
## v0.3 Research (Bearers & Documentation)
> This section appends v0.3 research to the v0.1/v0.2 baseline above. It does NOT
> rewrite or supersede the earlier content. v0.3 bundles two work-streams under
> one feature milestone (D-034): (A) Bearers skeleton+tests (D-020/D-035 pattern)
> and (B) a README.md + MkDocs Material docs site with the REQ-012 lexicon firewall
> extended to docs (D-043). Tags run on v0.2.x (config.json tag_base).
### v0.3 Scope Recap (from D-034..D-046)
v0.3 continues the skeleton+tests pattern (D-020/D-035): Go types + keeper stubs +
invariant tests, no live chain, no real IBC, no real bearer transports, no live
B2B runtime. The new/extended modules:
| Module | REQ | D-decision | New/Ext | Phase | Skeleton depth |
|---|---|---|---|---|---|
| `x/exit` | REQ-010 | D-036 | New | P4 | ExitRoute + DEXSwap + ExitStatus |
| `x/bridge` | REQ-010 | D-036 | New | P4 | BridgeRoute + BridgeStatus; ref x/satellite L2Chain by ID |
| `x/bearers` (ext) | REQ-022 | D-037 | Ext | P4 | OYSATLink + OYQRCode (BearerTransport impls) |
| `x/partner` (ext) | REQ-023 | D-038 | Ext | P4 | Anchor credential fields on the Anchor tier |
| `x/hub` | REQ-024 | D-039 | New | P5 | HubService enum (Custody/LendingPrimitive/Compliance) + struct stubs |
| `x/services` | REQ-025 | D-040 | New | P5 | ServiceKind enum (Care/SIM/Vault/Mail) + struct stubs |
| `x/bond` (ext) | REQ-026 | D-041 | Ext | P5 | GrowthBond + SecondaryOrder; 8%/0% consts unchanged |
| docs/ + README.md + mkdocs.yml | REQ-027 | D-042 | New | P1-P3 | ~20-25 pages, 4 audiences |
| `lexicon_meta_docs_test.go` | REQ-028 | D-043 | New | P1 | firewall sibling test |
---
## v0.3 §1. Bearers Skeleton Design — Per Module
### v0.3 §1.1 `x/exit` (Exit layer — DEX swaps, REQ-010, D-036)
**What it is:** The Layer 3 exit layer — Holder-initiated DEX swaps and off-mesh
service exits. v0.3 ships the type scaffold (ExitRoute, DEXSwap) + ExitStatus
enum; no live DEX integration (deferred to v0.4).
**Prior art / ecosystem references:**
- **DEX aggregators** — 1inch (off-chain path optimization), Paraswap, 0x API
(rfq + amm). An ExitRoute is closest to a 1inch "swap route" (a hop sequence:
source-asset → intermediate → destination-asset, each hop a venue).
- **Cosmos SDK** — no native DEX module; DEX swaps are CosmWasm or external. The
skeleton types are self-contained Go structs (zero-dep, same as v0.2 satellite).
- **Cross-chain swap** — THORChain, Chainflip; an exit that crosses a bridge is
a swap-with-bridge-hop. `x/exit` references a `x/bridge` BridgeRoute by ID for
cross-chain exits (the BridgeRoute is typed in x/bridge; x/exit holds a
bridge-route-id string field, G-003 by-ID-string ref).
**Recommendation for skeleton:** New `x/exit/types/` module following the v0.2
`x/satellite` pattern (locked-const enum + struct types + genesis + keeper stub):
- `ExitStatus` enum (Proposed, InProgress, Settled, Failed, Refunded) — exactly
5, locked-const `ExitStatusCount = 5` with a regression test.
- `ExitRoute` struct (route-id, holder-reach-id, source-asset, dest-asset,
amount-grain, min-received-grain, bridge-route-id (optional, by-ID-string ref
to x/bridge for cross-chain exits), venue-hops []string, deadline, status).
- `DEXSwap` struct (swap-id, route-id (by-ID-string ref to ExitRoute), venue,
input-asset, input-amount-grain, output-asset, output-amount-grain, executed-at).
The "venue" is an opaque string (e.g., "uniswap-v3", "oy-dex") — no enum locked
in v0.3 (venues are operational, not protocol-locked; locking now risks churn).
- `Keeper` stub: AddExitRoute / GetExitRoute / ListByHolder (by holder-reach-id).
- `GenesisState` + `ValidateGenesis` (route-id uniqueness, A-212 pattern).
- Tests: ExitStatusCount=5, enum names match, route round-trip, lexicon assertion,
genesis ID-uniqueness.
**Pattern followed:** `x/satellite` (new module with enum + structs + genesis +
keeper stub). The ExitStatus enum mirrors the v0.2 BondStatus/ChannelStatus
pattern (locked count + AllX() returning vision-order values).
**Cross-component dependency:** `x/exit` references `x/bridge` BridgeRoute by
ID-string (G-003). This is a P4 intra-phase dependency: `x/bridge` types must
exist before `x/exit` tests that reference a bridge-route-id. Both land in P4
(D-044); `x/bridge` is authored first within P4. No struct import (by-ID-string
only), so no import cycle. `x/exit` also references `x/bread` Grain by name only
(the amount-grain field is int64, not a bread.Bread import).
**Risk:** "DEX swap" terminology is lexicon-safe (no banned terms). "venue" is
not banned. Avoid "account" (use holder-reach-id), "currency"/"dollar"/"euro"
(use source-asset/dest-asset opaque strings). Test asserts no banned terms.
---
### v0.3 §1.2 `x/bridge` (L2↔L1 bridge types, REQ-010, D-036)
**What it is:** The L2↔L1 bridge type scaffold — bridge routes between OY Chain
(L1) and the v0.2 satellite L2 chains. v0.3 ships BridgeRoute + BridgeStatus
enum; no live bridge runtime (the v0.2 satellite ICS-20 channel types are the
IBC transport; x/bridge is the higher-level route abstraction over them).
**Prior art / ecosystem references:**
- **L2↔L1 bridges** — Hop Protocol (L2-L1 token bridge with bonder), Across
(repayer-based), Connext (interop), Cosmos IBC (the v0.2 satellite choice).
OY's bridge is IBC-native (D-021 chose IBC for L2); x/bridge is the route layer
over the IBC transfer channel.
- **Bridge status lifecycles** — Hop: Pending → Confirmed → Minted; Across:
Pending → Filled → Repaid; IBC: Init → TryOpen → Open → Closed (the v0.2
ChannelStatus). x/bridge's BridgeStatus is the route-level lifecycle (above
the channel handshake): Pending → Attested → Active → Closed.
- **Watcher attestation for bridges** — bridges are high-value exits; the vision
ties bridge activation to Watcher attestation (6-of-9 quorum, REQ-004). The
BridgeStatus `Attested` state references a Watcher quorum by ID (skeleton:
the attestation is a by-ID-string field, not a struct import).
**Recommendation for skeleton:** New `x/bridge/types/` module following `x/satellite`:
- `BridgeStatus` enum (Pending, Attested, Active, Closed) — exactly 4, locked-const
`BridgeStatusCount = 4`. `Attested` is the Watcher-quorum-confirmed state.
- `BridgeRoute` struct (route-id, source-chain (L2Chain by-ID-string ref to
x/satellite — G-003, no struct import), dest-chain, bridge-type (e.g., "ibc",
"oy-bridge" — opaque string, not a locked enum in v0.3), transfer-channel-id
(by-ID-string ref to a v0.2 satellite TransferChannel), watcher-quorum-id
(by-ID-string ref to x/watcher, set when status becomes Attested), status).
- `Keeper` stub: AddBridgeRoute / GetBridgeRoute / ListByStatus.
- `GenesisState` + `ValidateGenesis` (route-id uniqueness, A-212).
- Tests: BridgeStatusCount=4, enum names, route round-trip, lexicon assertion.
**Pattern followed:** `x/satellite` (the v0.2 L2/IBC module). x/bridge reuses the
satellite L2Chain enum by-ID-string reference — it does NOT redefine L2 chains.
**Cross-component dependency:** `x/bridge` references `x/satellite` (L2Chain by
ID-string, for source-chain/dest-chain fields) and `x/watcher` (watcher-quorum-id
by ID-string, for the Attested state). Both are v0.1/v0.2 baseline modules; no
new v0.3 dependency. x/bridge is authored FIRST in P4 (before x/exit) because
x/exit references a BridgeRoute by ID.
**Risk:** "bridge" is not a banned term. Avoid "currency"/"dollar"/"euro" (use
chain names: "Polygon"/"OY-Chain"). The watcher-quorum-id is an opaque string;
no Watcher struct import (avoids cycle with x/watcher).
---
### v0.3 §1.3 `x/bearers` extension (OY-SAT + OY-QR, REQ-022, D-037)
**What it is:** The remaining two bearer transports (OY-SAT satellite, OY-QR
paper/QR-code) completing the 6-bearer type set (v0.2 had 4: Internet, OY-LR,
OY-BLE, OY-WiFi-Direct + the Beacon transport-mode). v0.3 adds the OY-SAT and
OY-QR transport structs implementing the v0.2 `BearerTransport` interface. No
hardware/RF/paper-scan runtime.
**Prior art / ecosystem references:**
- **OY-SAT (satellite bearer)** — Starlink (consumer satellite), Iridium (low-
earth-orbit, global), Swarm (low-bandwidth satellite IoT). Helium Mobile +
satellite fallback. OY-SAT is global, surveillance-resistant (vision §14).
The transport struct mirrors the v0.2 OYLRLink shape (gateway-id, frequency,
surveillance-resistant flag).
- **OY-QR (paper/QR-code bearer)** — offline QR-code value transfer (the
"paper wallet" / "physical Bitcoin" analog). Closest: Bolt Card (NFC + QR
Lightning), OpenTimestamps QR proofs. OY-QR is 0-range (vision §14: the
bearer list has OY-QR at "0 range"); a QR encodes a signed transfer that the
recipient scans and submits. The transport struct mirrors BeaconFrame (a
payload + ttl, but for QR it's a one-shot signed payload, no ephemeral-id).
**Recommendation for skeleton:** Extend `x/bearers/types/types.go` (do NOT create
a new module — v0.1/v0.2 own the BearerType enum and BearerTransport interface).
Add:
- `OYSATLink` struct (gateway-id, constellation (e.g., "iridium" — opaque
string), frequency-mhz, surveillance-resistant (LOCKED true for OY-SAT)).
- `OYQRCode` struct (qr-id, payload-bytes (the signed transfer), issuer-reach-id,
expires-at, consumed (bool — a QR is one-shot)).
- Both implement `BearerTransport` (Send/Receive/Status) as stub methods (the
v0.2 OYLRLink/BeaconFrame are struct types but NOT BearerTransport impls in
v0.2 — they are transport-shape stubs; v0.3 keeps the same shape-only approach
for OY-SAT/OY-QR to match D-029. If the interface impl is desired, add stub
methods returning a "not-integrated" sentinel, mirroring forex StubOracle).
- Tests: BearerOYSAT and BearerOYQR are already in `AllBearers()` from v0.1
(asserted by the existing locked-const test — do NOT change the count). New
tests assert the OYSATLink/OYQRCode struct fields, surveillance-resistant is
LOCKED true for OY-SAT, OY-QR is one-shot (consumed flips to true), lexicon.
- The v0.2 `BearerTypeCount` / `AllBearers()` locked-const test stays unchanged
(6 bearers, already locked). v0.3 adds the transport structs only.
**Pattern followed:** D-029 (v0.2 bearers extension). The OYSATLink mirrors
OYLRLink; OYQRCode mirrors BeaconFrame with a one-shot consumed flag instead of
ttl.
**Cross-component dependency:** None new. x/bearers is a leaf (no refs to other
v0.3 modules). The BearerType enum is locked since v0.1.
**Risk:** Hardware/paper-scan runtime is explicitly deferred. Do not pull LoRa/
BLE/satellite/QR Go libraries. Pure types. "QR" / "SAT" are not banned terms.
---
### v0.3 §1.4 `x/partner` extension (Anchor credential types, REQ-023, D-038)
**What it is:** The Anchor tier (the 4th of the 4-tier Partner Spectrum, REQ-018)
gets institution-specific credential fields in v0.3. v0.2 defined the 4-tier
enum + Partner struct + CredentialRef; v0.3 adds an AnchorCredential struct
carrying the institutional onboarding metadata (regulatory jurisdiction,
custody-provider ref, attestation refs). No live institutional onboarding.
**Prior art / ecosystem references:**
- **Institutional onboarding** — MakerDAO RWA arrangers (legal repr, off-chain
agreements), Centrifuge senior/junior tranches with institutional sponsors,
Maple Finance institutional underwriting, Ondo Finance institutional wrappers.
The Anchor tier is OY's abstraction over institutional partners.
- **Regulatory credentials** — e-Residency (Estonia), MiCA compliance (EU),
SOC2/ISO27001 attestations. The AnchorCredential carries jurisdiction +
attestation refs (opaque URIs, like the v0.2 Pier CredentialRef).
- **Custody** — Anchors may custody assets; the custody-provider ref points to
a Hub custody service (x/hub, P5). This is the Anchor→hub dependency edge:
x/partner Anchor references a hub custody-service-id by string.
**Recommendation for skeleton:** Extend `x/partner/types/types.go`:
- `AnchorCredential` struct (partner-id (by-ID-string ref to the Anchor
Partner), jurisdiction (opaque string e.g. "EU-MiCA"), custody-provider-id
(by-ID-string ref to x/hub custody service — set in v0.4 when hub is live;
v0.3 field is a string, may be empty in skeleton), attestation-refs
[]string (opaque URIs to Watcher/auditor attestations), onboarded-at).
- A `Partner.AnchorCredential() *AnchorCredential` accessor stub returning nil
for non-Anchor tiers (or a separate AnchorPartner struct wrapping Partner —
prefer the accessor to avoid a second top-level type).
- `Keeper.ListAnchors()` = `ListByTier(TierAnchor)` (already exists from v0.2;
add a convenience alias + an `AddAnchorCredential(partnerID, cred)` method).
- Tests: AnchorCredential struct round-trip, non-Anchor Partner returns nil,
AddAnchorCredential rejects non-Anchor partner-id, lexicon assertion.
**Pattern followed:** v0.2 partner extension (add a struct + accessor, reuse
the existing Keeper). The PartnerTier enum (4 tiers, locked since v0.2) is
unchanged — v0.3 adds Anchor-specific fields, not a new tier.
**Cross-component dependency:** `x/partner` Anchor references `x/hub` custody
service by ID-string (G-003). This is a P4→P5 edge: x/partner Anchor lands in
P4, x/hub in P5. The custody-provider-id field is a string that is EMPTY in
the v0.3 skeleton (the hub is not live until P5/v0.4); the field exists so the
shape is stable. This is the dependency that forces P4 before P5 (D-044).
**Risk:** "custody" is not a banned term (the banned list is bank/deposit/
interest/yield/currency/dollar/euro/account/savings/depositor). "jurisdiction"
is safe. Avoid "account" (use partner-id). Test asserts no banned terms.
---
### v0.3 §1.5 `x/hub` (Hub API — B2B backbone, REQ-024, D-039)
**What it is:** The Hub API Pact (#6 per REQ-020/D-027) promoted to its own
module in v0.3. The B2B backbone: custody, lending-primitive, compliance
service types. v0.3 ships the HubService enum + per-service struct stubs +
keeper stub; no live B2B runtime (full suite deferred to v0.4).
**Prior art / ecosystem references:**
- **B2B API backbones** — Stripe API (modular resources), Plaid (bank-data
aggregation — note: Plaid is bank-data, OY's Hub is the anti-bank backbone, so
the analogy is structural not semantic), Coinbase Prime (institutional
custody + prime). The Hub is OY's on-chain B2B service registry.
- **Custody** — Fireblocks, Anchorage, BitGo (institutional custody). OY's
custody service is a Hub-service type that an Anchor partner operates.
- **Lending primitive** — Aave/Compound protocol-level lending; OY's "lending
primitive" is a Hub-service type (the protocol-level primitive, not a live
market). Lexicon note: "lending" is NOT banned (the banned list has "interest"
and "deposit" and "savings" but not "lending" or "loan"); use "lending
primitive" (vision §13) to stay aligned, avoid "interest"/"deposit".
- **Compliance** — on-chain compliance attestations (TRM Labs, Elliptic for
AML; Chainalysis). OY's compliance service is a Hub-service type an Anchor
or Pier operates.
**Recommendation for skeleton:** New `x/hub/types/` module following `x/forex`
(the v0.2 enum + struct + interface + stub-keeper pattern):
- `HubService` enum (Custody, LendingPrimitive, Compliance) — exactly 3,
locked-const `HubServiceCount = 3`. (Vision §13 names these three B2B
categories; full B2B suite deferred to v0.4 per D-039.)
- `HubServiceInfo` struct (service-id, kind (HubService), operator-partner-id
(by-ID-string ref to x/partner — typically an Anchor), name, status).
- `HubServiceStatus` enum (Pending, Active, Suspended, Revoked) — reuse the
v0.2 PartnerStatus shape (same 4-state lifecycle); locked-const count = 4.
Consider importing nothing and redefining locally (G-003 by-ID-string only;
enums are string types so a local redefinition is fine and avoids a struct
import of x/partner).
- Per-service struct stubs: `CustodyService` (service-id, custody-provider-id,
assets-supported []string), `LendingPrimitiveService` (service-id,
primitive-kind (opaque string), coupon-cap-bps uint32 — clamp-reusable from
x/bond Clamp? NO — the hub lending primitive references the bond cap by
const value 800, not by importing x/bond.Clamp; keep a local const
`LendingCouponCapBps = 800` cross-documented to D-028 to avoid the import),
`ComplianceService` (service-id, jurisdiction, attestation-refs []string).
- `Keeper` stub: AddService / GetService / ListByKind.
- `GenesisState` + `ValidateGenesis` (service-id uniqueness, A-212).
- Tests: HubServiceCount=3, enum names, service round-trip, per-service struct
fields, lexicon assertion (HIGH-RISK: "interest"/"deposit"/"savings" must not
appear; "lending"/"coupon"/"custody"/"compliance" are safe).
**Pattern followed:** `x/forex` (enum + struct + per-variant struct + stub
keeper + genesis). The local-const-copy for the coupon cap mirrors how x/guild
cross-documents x/feecovenant's WaiverHandPassGuild (v0.2 RESEARCH §1.5).
**Cross-component dependency:** `x/hub` references `x/partner` (operator-
partner-id by ID-string, typically an Anchor). This is the P4→P5 edge: x/partner
Anchor (P4) must precede x/hub (P5). The hub also cross-documents the bond
8%/0% cap (D-028) as a local const to avoid importing x/bond (G-003).
**Risk:** Lending primitive is the highest lexicon-risk in v0.3 (after x/bond).
"interest"/"yield"/"deposit"/"savings" are natural fit-words for a lending
primitive — use "lending primitive"/"coupon" (vision §13/§17 lexicon). The
lexicon assertion test is the gate. Do NOT use "borrower"/"lender" if they
imply banned concepts — vision §13 uses "lending primitive" as the service
name, so the struct/enum names follow vision.
---
### v0.3 §1.6 `x/services` (Care/SIM/Vault/Mail, REQ-025, D-040)
**What it is:** OY-protocol services beyond the financial layer — Care
(community care), SIM (subscriber identity module / connectivity), Vault
(storage service), Mail (messaging). v0.3 ships the ServiceKind enum + per-
service struct stubs + keeper stub; no live services.
**Prior art / ecosystem references:**
- **Care** — mutual aid societies, Gitcoin Grants rounds (care as public-good
funding). OY Care is a community-care service a Stand/Guild operates.
- **SIM** — Helium Mobile (DePIN connectivity), decentralized connectivity
(Pollen, Andrena). OY SIM is a connectivity service.
- **Vault** — the v0.2 x/vault is the Stand-level storage pool; an OY
"Vault service" is a higher-level storage offering (backup, attested
storage). Reference x/vault by ID-string (G-003).
- **Mail** — decentralized messaging (Session, Status, XMTP). OY Mail is a
bearer-routed messaging service.
**Recommendation for skeleton:** New `x/services/types/` module following
`x/hub` (enum + struct + per-variant struct + keeper stub + genesis):
- `ServiceKind` enum (Care, SIM, Vault, Mail) — exactly 4, locked-const
`ServiceKindCount = 4`. (Vision §13 / ROADMAP Phase 4 lists these four;
Yield Token + Travel + 11 more are Phase 4, out of v0.3 scope per D-040.)
- `ServiceInfo` struct (service-id, kind (ServiceKind), operator-reach-id (by-
ID-string ref to x/identity Reach), name, status, window-id (by-ID-string
ref to x/window — a service-grant opens a Window on the holder's behalf)).
- `ServiceStatus` enum (Pending, Active, Suspended, Revoked) — reuse the 4-
state shape (local redefinition, no import).
- Per-service struct stubs: `CareService`, `SIMService`, `VaultService`,
`MailService` — each carries service-id + service-specific fields (Care:
care-kind (opaque); SIM: carrier (opaque); Vault: storage-quota-grain;
Mail: mailbox-id). Keep these minimal — the shape is the v0.3 deliverable.
- `Keeper` stub: AddService / GetService / ListByKind.
- `GenesisState` + `ValidateGenesis` (service-id uniqueness, A-212).
- Tests: ServiceKindCount=4, enum names, service round-trip, per-service
fields, lexicon assertion.
**Pattern followed:** `x/hub` (and transitively `x/forex`).
**Cross-component dependency:** `x/services` references `x/identity` (operator-
reach-id by ID-string), `x/window` (window-id by ID-string — the service-grant),
and `x/vault` (for VaultService, by ID-string). All v0.1/v0.2 baseline; no new
v0.3 dependency. The window-id field is the hook for the Window Lifecycle
interface (Architecture §4.4) — typed in v0.3, invoked at runtime in v0.4.
**Risk:** "Vault" collides with the v0.2 `x/vault` module name — but the
ServiceKind enum value is "Vault" (a service kind, not a module import). The
VaultService struct lives in `x/services/types/`, references `x/vault` by ID-
string. The naming collision is at the concept level, not the package level (no
Go import cycle). "Mail"/"SIM"/"Care" are not banned terms. Avoid "account"
(use service-id / operator-reach-id).
---
### v0.3 §1.7 `x/bond` extension (Growth Bonds + secondary market, REQ-026, D-041)
**What it is:** Bond market depth — GrowthBond (a bond whose coupon grows with
protocol health, vision §17) + secondary-market order types. The 8% cap / 0%
floor consts (D-028) are UNCHANGED. Full secondary-market matching deferred to
v0.4.
**Prior art / ecosystem references:**
- **Growth Bonds** — "growing bonds" / step-up bonds (coupon increases over
time), inflation-linked bonds (TIPS). OY's GrowthBond is a bond whose coupon
grows with Root-Pool Bloom (real-production-driven). Closest: TIPS (coupon
adjusts to an index) but OY's index is the protocol's real return, not CPI.
- **Secondary markets** — Uniswap v3 (concentrated liquidity AMM), order-book
DEXs (dYdX, 0x Mesh), fixed-income secondary markets (Centrifuge Tinlake
secondary). OY's secondary market is an order-book (buy/sell orders on issued
bonds); the matching engine is v0.4. v0.3 types the order shape.
- **Coupon caps** — the 8% cap (D-028) applies to GrowthBonds too: the growth
coupon is still clamped to [0, 800] bps at any point (the cap is mission-
locked; a growth bond cannot exceed it even as the protocol grows). The
GrowthBond reuses x/bond.Clamp (same package — no G-003 concern).
**Recommendation for skeleton:** Extend `x/bond/types/types.go`:
- `GrowthBond` struct embedding the v0.2 `Bond` + a `GrowthRateBps` field (the
per-period growth rate of the coupon, clamped so that current-coupon +
growth never exceeds CouponCapBps — add a `ClampGrowth(currentBps, growthBps)
uint32` helper that returns min(CouponCapBps - currentBps, growthBps) so the
post-growth coupon is ≤ cap). The growth-bond issuer-stand-id references
x/stand by ID-string (unchanged from v0.2 Bond).
- `SecondaryOrder` struct (order-id, bond-id (by-ID-string ref to the Bond),
side (OrderSide enum: Buy/Sell), price-bps (price as a fraction of principal,
in bps), quantity-grain, holder-reach-id, status, created-at).
- `OrderSide` enum (Buy, Sell) — exactly 2, locked-const `OrderSideCount = 2`.
- `OrderStatus` enum (Open, Filled, Cancelled) — exactly 3, locked-const
`OrderStatusCount = 3`.
- `Keeper` stub: AddOrder / GetOrder / ListByBond / CancelOrder (no matching).
- Extend `GenesisState` with a `GrowthBonds []GrowthBond` and `Orders
[]SecondaryOrder` field; `ValidateGenesis` checks order-id + growth-bond-id
uniqueness (A-212).
- Tests: GrowthBond clamp-growth invariant (post-growth coupon ≤ 800, never
below 0), OrderSideCount=2, OrderStatusCount=3, order round-trip, the 8%/0%
consts STILL = 800/0 (regression: v0.3 must not change D-028), lexicon
assertion (HIGH-RISK: "interest"/"yield"/"deposit"/"savings" banned — use
"coupon"/"growth"/"secondary"/"order").
**Pattern followed:** v0.2 x/bond (locked-const + Clamp + struct + genesis). The
ClampGrowth helper mirrors the v0.2 Clamp shape (min/max with the cap).
**Cross-component dependency:** None new. x/bond references x/stand (issuer-
stand-id, by ID-string, v0.2 baseline). The GrowthBond and SecondaryOrder are
in-package with Bond (same `x/bond/types`), so no G-003 concern for the Clamp
reuse.
**Risk:** Growth Bond is lexicon-hostile ("growth" is safe, but "yield growth"
is the natural phrasing — use "coupon growth" / "real-return-linked coupon",
never "yield"). The secondary-market "order" terminology is lexicon-safe
("buy"/"sell"/"order"/"filled"/"cancelled" are not banned). The regression test
that 8%/0% are unchanged is the D-028 firewall.
---
## v0.3 §2. Documentation Site + Firewall Extension Design
### v0.3 §2.1 MkDocs Material setup
**Decision (D-042):** MkDocs Material (`mkdocs.yml` at repo root + `docs/` tree).
Build-only Python dep (`mkdocs` + `mkdocs-material`); `go.mod` stays zero-dep
(G-006 — the docs toolchain is NOT a Go dependency; it lives in a separate
Python toolchain, documented in README, not in go.mod).
**Minimal `mkdocs.yml`:**
```yaml
site_name: OpenYield
theme:
name: material
features:
- navigation.sections
- navigation.expand
- toc.integrate
markdown_extensions:
- admonition
- toc:
permalink: true
- pymdownx.superfences
nav:
- Home: index.md
- Nomads:
- nomads/index.md
- nomads/reach.md
- nomads/stash.md
- nomads/bearers.md
- nomads/maps-pay.md
- nomads/pacts.md
- nomads/standing-basics.md
- Freeholders:
- freeholders/index.md
- freeholders/four-signals.md
- freeholders/bayesian-standing.md
- freeholders/stands-guilds.md
- freeholders/councils-voice.md
- freeholders/bonds.md
- freeholders/partner-spectrum.md
- Shared:
- shared/index.md
- shared/six-principles.md
- shared/bread-scale.md
- shared/storage-pools.md
- shared/watchers-mirror.md
- shared/lexicon-glossary.md
- shared/vision-overview.md
- Reference:
- reference/architecture-index.md
- reference/component-map.md
```
**Audience organization (D-042, D-045):** nomads (Reach/Stash/bearers/Maps-Pay/
Pacts/standing-basics — 7 pages), freeholders (4-signals/Bayesian-Standing/
Stands-Guilds/Councils-Voice/Bonds/Partner-spectrum — 7 pages), shared (Six-
Principles/Bread-Scale/Storage-pools/Watchers-Mirror/Lexicon-glossary/Vision-
overview — 6 pages), reference (architecture-index/component-map — 2 pages).
Total ~22 pages (within the D-045 20-25 budget).
**No publishing CI in v0.3 (D-046):** `mkdocs.yml` is buildable locally
(`mkdocs serve` / `mkdocs build`); the README documents the build invocation.
Publishing to GitHub/Gitea Pages deferred to v0.4 (needs deployment secrets +
hosting target). v0.3 ships the source.
---
### v0.3 §2.2 Lexicon-clean docs by construction
The 10 banned terms (bank, deposit, interest, yield, currency, dollar, euro,
account, savings, depositor) must not appear in `docs/**/*.md` or `README.md`.
The highest-risk term in docs is **"yield"**: PROJECT.md uses "real yield" but
docs must say "real production" / "real return" (the word-boundary regex in
`lexicon.FindBannedTerm` bans standalone "yield" while allowing "OpenYield" —
verified by `TestLexiconMetaNoFalsePositiveOnOpenYield`).
**Safe phrasings for docs (the docs-writer constraint):**
- "real yield" → "real production" / "real return"
- "account" → "Holder" / "Reach"
- "bank" / "deposit" / "savings" / "depositor" → "Stash" / "Vault" / "Root-Pool"
- "interest" → "coupon" (for bonds)
- "currency" / "dollar" / "euro" → "Bread" / "asset" / opaque chain names
**Firewall-first ordering (D-044):** the docs firewall (`lexicon_meta_docs_test.go`)
lands in P1 BEFORE the content (P2 nomads, P3 freeholders). This ensures docs
are lexicon-clean by construction, not by retrofit — a banned term slipped into
a P2 nomads page fails the P2 build, not the P6 review.
---
### v0.3 §2.3 Firewall extension design (`lexicon_meta_docs_test.go`)
**Decision (D-043):** NEW sibling test `lexicon_meta_docs_test.go` (package
`lexicon_meta_docs`) at the repo root (next to `lexicon_meta_test.go`), NOT a
modification of the existing `lexicon_meta_test.go` (package `lexicon_meta`).
**Rationale for the sibling (not extension) approach:**
1. Preserves v0.2 coverage — the existing `lexicon_meta_test.go` scans `x/**/*.go`
and is unchanged; v0.2's green firewall is not re-risked.
2. Clearer separation — the docs firewall scans a different file set
(`README.md` + `docs/**/*.md`) with different walk logic (repo-root walk, not
`x/` walk); a separate test file keeps each firewall's walk logic self-
contained and readable.
3. Package isolation — `lexicon_meta_docs` is a distinct Go package so the two
meta-tests compile independently and cannot share state by accident.
**The new test mirrors `lexicon_meta_test.go` exactly in detection logic:**
- Uses the SAME `lexicon.FindBannedTerm` (word-boundary, case-insensitive) — no
reimplementation of detection.
- Same self-test table (G-009): one synthetic string per banned term, asserted
to trigger detection, assembled from fragments so the test file's own source
does not contain a banned-term literal.
- Same self-exclusion: the meta-test file excludes ITSELF from its own scan
(via `runtime.Caller(0)` to get its own path, then skipping it in the walk).
- Same `TestLexiconMetaDocsBannedTermsCount` (exactly 10 terms).
- Same `TestLexiconMetaDocsNoFalsePositiveOnOpenYield` (word-boundary does not
match "openyield"/"european").
**File walk logic (the only difference from `lexicon_meta_test.go`):**
- Walk the REPO ROOT (not `x/`): start at `filepath.Dir(thisFile)` (the repo
root, since the test lives at the repo root).
- Target files: `README.md` (repo root) + every `*.md` under `docs/` (recursive).
- Exclude `.ciagent/` (firewall meta-files — PROJECT.md/RESEARCH.md/this file
discuss banned terms by name for governance; they are NOT user-facing docs).
- Exclude `.git/` (VCS metadata).
- Exclude the meta-test file itself (`lexicon_meta_docs_test.go`).
- Exclude `docs/` non-`.md` files (images, etc.) — only `.md` is scanned.
- For each target `.md` file, read its source and run `lexicon.FindBannedTerm`;
collect hits and fail with a list.
**Pseudocode of the walk:**
```go
func TestLexiconMetaDocsNoBannedTermsInDocs(t *testing.T) {
repoRoot := filepath.Dir(thisFile(t)) // repo root (test is at repo root)
thisFile := thisFile(t)
hits := []string{}
filepath.Walk(repoRoot, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
base := filepath.Base(path)
if base == ".ciagent" || base == ".git" { return filepath.SkipDir }
return nil
}
if path == thisFile { return nil } // self-exclusion
if !strings.HasSuffix(path, ".md") { return nil }
// only README.md (repo root) + docs/**/*.md
rel, _ := filepath.Rel(repoRoot, path)
if rel != "README.md" && !strings.HasPrefix(rel, "docs/") { return nil }
bz, _ := os.ReadFile(path)
if found, ok := lexicon.FindBannedTerm(string(bz)); ok {
hits = append(hits, rel+" contains banned term "+found)
}
return nil
})
if len(hits) > 0 { t.Errorf("REQ-012 docs lexicon violations:\n %s", ...) }
}
```
**Per-package lexicon assertions (in the new x/* modules):** each new/extended
v0.3 module's `types_test.go` includes a `TestLexiconNoBannedTermsIn<Module>Package`
scanning the module's production `.go` files (the v0.2 pattern from
`x/partner/types/types_test.go`). These are OWNED by backend-engineer (not the
docs firewall, which is frontend-engineer's). The project-wide `x/**/*.go` scan
stays in `lexicon_meta_test.go` (v0.2, unchanged) and automatically covers the
new v0.3 x/* modules.
---
## v0.3 §3. Cross-Component Dependencies Affecting Phase Ordering
The v0.3 cross-component dependencies (all by-ID-string per G-003, no struct
imports) that constrain the D-044 phase ordering:
1. **`x/exit``x/bridge` (intra-P4):** `x/exit`'s ExitRoute has a `bridge-route-
id` field referencing a `x/bridge` BridgeRoute by ID-string. `x/bridge` types
must exist before `x/exit` tests reference a bridge-route-id. Both land in P4;
`x/bridge` authored first within P4.
2. **`x/partner` (Anchor) → `x/hub` (P4 → P5):** `x/hub`'s HubService has an
`operator-partner-id` field referencing an Anchor Partner by ID-string.
`x/partner` Anchor extension (P4) must precede `x/hub` (P5). The Anchor's
`custody-provider-id` field references a hub custody service (by ID-string)
but is EMPTY in the v0.3 skeleton (hub not live until P5/v0.4), so the
reverse edge is typed-but-deferred. This is the dependency that forces P4
before P5.
3. **`x/services``x/window` (P5 → v0.2 baseline):** `x/services`'s ServiceInfo
has a `window-id` field referencing a `x/window` Window by ID-string. x/window
is a v0.2 baseline module (already shipped); no phase-ordering concern.
4. **`x/bond` (GrowthBond) → `x/stand` (P5 → v0.2 baseline):** GrowthBond's
issuer-stand-id references x/stand by ID-string (unchanged from v0.2 Bond).
x/stand is v0.2 baseline; no concern.
5. **`x/bridge``x/satellite`, `x/watcher` (P4 → v0.2/v0.1 baseline):**
BridgeRoute references a satellite L2Chain and a watcher-quorum-id by ID-
string. Both are baseline; no concern.
**Net phase-ordering conclusion:** D-044's P4→P5 split is confirmed and cannot
be reversed: P4 = exit/bridge/bearers/partner-Anchor; P5 = hub/services/bond.
The only intra-phase ordering within P4 is `x/bridge` before `x/exit`. P5 has no
intra-phase ordering constraint (hub, services, bond are independent of each
other). The docs phases (P1-P3) are firewall-first (P1) then content (P2-P3),
independent of the Bearers phases.
---
## v0.3 §4. Assumptions (logged with confidence scores)
| ID | Assumption | Confidence | Rationale |
|----|-----------|------------|-----------|
| A-301 | v0.3 skeleton stays dependency-free (only stdlib), matching v0.1/v0.2 (A-201). Docs build-deps (mkdocs) are Python, not Go; go.mod unchanged. | 0.95 | D-035/A-201/G-006 confirm; mkdocs is D-042. |
| A-302 | `x/exit` and `x/bridge` are SEPARATE packages (not one x/exit module), per D-036. | 0.90 | D-036 explicitly names both; separation matches v0.2 one-package-per-module (A-202). |
| A-303 | `x/hub` is a NEW module (Pact #6 promoted from x/pact enum value to its own module), per D-039. | 0.85 | D-039 names x/hub; the x/pact HubAPI enum value stays as a cross-ref. |
| A-304 | `x/hub` `LendingCouponCapBps = 800` is a LOCAL const cross-documented to D-028 (not an import of x/bond.Clamp), to preserve G-003 (no struct import). | 0.82 | Mirrors v0.2 guild's cross-doc of feecovenant WaiverHandPassGuild (RESEARCH §1.5). |
| A-305 | `x/partner` Anchor adds an `AnchorCredential` struct + accessor, NOT a new PartnerTier (the 4-tier enum is locked since v0.2). | 0.90 | D-038 says "extend with Anchor credential fields"; the tier enum is locked. |
| A-306 | `x/bond` GrowthBond embeds the v0.2 Bond + a GrowthRateBps field with a ClampGrowth helper ensuring post-growth coupon ≤ 800 bps. | 0.80 | Vision §17 growth-bond; the 8% cap (D-028) applies to growth bonds too. |
| A-307 | `x/services` ServiceKindCount = 4 (Care/SIM/Vault/Mail); Yield Token + Travel + 11 more are Phase 4 (out of v0.3 per D-040). | 0.85 | D-040 + ROADMAP Phase 4 confirm the 4-service v0.3 scope. |
| A-308 | `x/exit` DEXSwap "venue" is an opaque string (not a locked enum) — venues are operational, locking now risks churn. | 0.75 | Venues change (uniswap-v3/v4, oy-dex); a locked enum would be a false firewall. |
| A-309 | The docs firewall sibling test (lexicon_meta_docs_test.go) lives at the repo root (same dir as lexicon_meta_test.go), package lexicon_meta_docs. | 0.90 | D-043 chose the sibling; repo-root placement matches the v0.2 meta-test. |
| A-310 | `.ciagent/` is excluded from the docs firewall scan (meta-files discuss banned terms by name for governance; not user-facing docs). | 0.88 | D-043 rationale; mirrors meta-test self-exclusion. |
| A-311 | OY-SAT `surveillance-resistant` is LOCKED true (matching OY-LR from v0.2); OY-QR is one-shot (consumed flips to true). | 0.80 | Vision §14 marks OY-LR/OY-SAT as surveillance-resistant; QR is physical/one-shot. |
| A-312 | `x/hub` HubServiceCount = 3 (Custody/LendingPrimitive/Compliance) per vision §13; full B2B suite (more services) deferred to v0.4. | 0.85 | D-039 + vision §13 name the three; D-039 defers the full suite. |
| A-313 | `x/bond` OrderSideCount = 2 (Buy/Sell), OrderStatusCount = 3 (Open/Filled/Cancelled). | 0.80 | Standard order-book shape; minimal locked set for v0.3. |
| A-314 | docs-writer is a SEPARATE custom persona (not folded into frontend-engineer) to keep content-vs-toolchain review boundaries explicit. | 0.75 | The ~20-25 page content load (D-045) justifies a split; lower confidence than the structural decisions. |
| A-315 | v0.2 custom personas (cosmos-engineer, security-engineer) are NOT reactivated for v0.3 — lower Cosmos-convention and invariant density. | 0.80 | v0.3 modules are bespoke (no new x/gov/x/group/x/authc maps); invariant density is lower (enum counts, not Mission Lock). |
---
## v0.3 Cross-Reference Summary
| REQ | Component | Module | Phase (D-044) | Depth (D-03x) |
|-----|-----------|--------|---------------|---------------|
| REQ-010 | Exit layer (DEX) | `x/exit/` | P4 | Skeleton (ExitRoute, DEXSwap) — D-036 |
| REQ-010 | Exit layer (bridge) | `x/bridge/` | P4 | Skeleton (BridgeRoute, BridgeStatus) — D-036 |
| REQ-022 | Bearers OY-SAT/OY-QR | `x/bearers/` (ext) | P4 | Stubs (no HW) — D-037 |
| REQ-023 | Anchors | `x/partner/` (ext) | P4 | Skeleton (AnchorCredential) — D-038 |
| REQ-024 | Hub API | `x/hub/` | P5 | Skeleton (3 services) — D-039 |
| REQ-025 | Services | `x/services/` | P5 | Skeleton (4 kinds) — D-040 |
| REQ-026 | Bond market depth | `x/bond/` (ext) | P5 | Skeleton (GrowthBond + secondary) — D-041 |
| REQ-027 | Docs site | `docs/`, `mkdocs.yml`, `README.md` | P1-P3 | ~22 pages, 4 audiences — D-042/D-045 |
| REQ-028 | Docs firewall | `lexicon_meta_docs_test.go` | P1 | Sibling meta-test — D-043 |
**New modules: 4 (exit, bridge, hub, services). Extended modules: 3 (bearers,
partner, bond). Docs surface: new (docs/, mkdocs.yml, README.md). Firewall: 1
new sibling test. Total v0.3: 4 new + 3 extended + docs + 1 firewall test.**
+50 -41
View File
@@ -14,57 +14,66 @@
- Status: COMPLETE (local-only ship, no remote configured)
- MVP release (v0.1.0) deferred until system validated as production-ready
## Phase 1 — Foundation (Year 1)
**Target**: first 10,000 Holders, 50 Master Ops
## Milestone v0.2 — The Mesh (COMPLETE)
- [x] P0: Pre-Execution → v0.1.0
- [x] P1: Orgs + Window Foundation → v0.1.1
- [x] P2: Pacts + Partners → v0.1.2
- [x] P3: Councils + Forex → v0.1.3
- [x] P4: Bonds + Bearers + L2 → v0.1.4
- [x] P5: Final Review + Ship → v0.1.5 (milestone release)
- Status: COMPLETE (skeleton + tests layer; released as v0.1.5)
| Component | Deliverable |
|---|---|
| OY Chain & Mirror (1) | L1 chain launched, 9 Watchers bonded, Mirror live |
| Bread Unit & Root Basket (3) | Forge/Fold on Ethereum + 23 L2s; initial Root Basket |
| Storage Substrate (5) | Stash, Vault, Root-Pool contracts |
| Bloom Engine (4) | Bloom accrual loop tied to Mirror attestations |
| Fee Covenant (13) | 0.1% ceiling live, processor share 50%, internal minimum 1 Grain |
| Identity, Standing & Citizenship (6) | Reach v1, Standing v1, Nomad/Freeholder system |
| Bearers & Processing Mesh (12) | Processing v1, OY-BLE, OY-WiFi-Direct |
| Mesh Experience (9) | Maps, Pay v1 |
## Milestone v0.3 — Bearers & Documentation (ACTIVE; feature type; tags v0.2.x)
Target: Bearers skeleton (ROADMAP Phase 3 subset) + docs site for nomads and freeholders.
## Phase 2 — The Mesh (Year 2) — v0.2 SKELETON COMPLETE
**Target**: $1B annual volume, 4 service categories
> v0.3 bundles two work-streams under one feature milestone: (A) Bearers
> skeleton+tests (D-020 pattern) and (B) README.md + MkDocs Material docs site
> organized by audience, with the REQ-012 lexicon firewall extended to docs.
> **v0.2 (The Mesh) milestone status**: COMPLETE — skeleton + tests layer shipped.
> Phase mapping: P0 (spec/research/plan/grill) -> P1 (Orgs+Window) -> P2 (Pacts+Partners)
> -> P3 (Councils+Forex) -> P4 (Bonds+Bearers+L2) -> P5 (review/audit/ship).
| Component | Deliverable | v0.2 Skeleton Module | Phase |
| Phase | Type | Scope | Patch |
|---|---|---|---|
| Organizational Primitives (10) | 9 Stand types, Guilds (Hand-Passes free) | x/stand, x/guild | v0.2/P1 |
| Partner Spectrum & Forex (11) | First Piers, Forex Engine v1 | x/partner, x/forex | v0.2/P2,P3 |
| Window Primitive (7) | Holder-authorized data channels | x/window | v0.2/P1 |
| Pacts Suite (8) | Pause, Ground, Stance, Cover, Stand Registry | x/pact (6-type enum, one module) | v0.2/P2 |
| Governance (14) | Mesh Council activated | x/council (3-kind + Mission Lock const) | v0.2/P3 |
| Bearers expansion | OY-LR + Beacon v1 | x/bearers (extended) | v0.2/P4 |
| Bonds | First Mesh Bonds | x/bond (8% cap / 0% floor) | v0.2/P4 |
| L2 Satellites | Wrapped Bread via IBC | x/satellite (Polygon rep + 4 stubs) | v0.2/P4 |
| P0 | docs | Pre-Execution (spec/clarify/research/ideate/plan/grill) | v0.2.0 |
| P1 | feat/test+docs | Docs foundation + REQ-012 firewall extension to docs/ + README.md + shared docs | v0.2.1 |
| P2 | docs | Nomads docs (docs/nomads/) | v0.2.2 |
| P3 | docs | Freeholders docs (docs/freeholders/) + docs/reference/ | v0.2.3 |
| P4 | feat | Bearers skeleton I: x/exit, x/bridge, x/bearers (OY-SAT, OY-QR), x/partner (Anchor) | v0.2.4 |
| P5 | feat | Bearers skeleton II: x/hub, x/services, x/bond (Growth Bonds + secondary market) | v0.2.5 |
| P6 | final | REVIEW + AUDIT + milestone SHIP | v0.2.6 (milestone release) |
> **Tag-line reconciliation (G-010)**: v0.1 pre-MVP shipped on the `v0.0.x` patch line
> (ROADMAP lines 4-13: v0.0.0..v0.0.9). v0.2 (The Mesh) ships on the `v0.1.x` patch line
> (config.json `tag_base: v0.1.x`): P0 -> `v0.1.0`, P1..P4 -> `v0.1.1..v0.1.4`, P5 -> `v0.1.5`
> (= the v0.2 milestone release, per D-008/D-020 — final phase patch IS the milestone
> release; no separate minor tag). The `v0.1.5` milestone release is NOT the deferred
> `v0.1.0` "MVP" tag referenced on line 15 — they are different lines (v0.0.x pre-MVP
> vs v0.1.x Mesh). No tag collision.
### v0.3 Component mapping
## Phase 3 — The Bearers (Year 3)
| Component | Deliverable | v0.3 Skeleton Module | Phase |
|---|---|---|---|
| Cross-Chain & Exit (2) | L2/L1 bridge types, DEX swap types | x/exit, x/bridge | v0.3/P4 |
| Bearers expansion | OY-SAT, OY-QR bearer transport types | x/bearers (extended) | v0.3/P4 |
| Anchors | First institutional Partner tier | x/partner (extended: Anchor) | v0.3/P4 |
| Hub API | B2B backbone: custody, lending primitive, compliance types | x/hub | v0.3/P5 |
| Services | Care / SIM / Vault / Mail service types | x/services | v0.3/P5 |
| Bond market | Growth Bonds, secondary-market types | x/bond (extended) | v0.3/P5 |
| Documentation | README.md + MkDocs Material docs site | docs/, mkdocs.yml, README.md | v0.3/P1-P3 |
| Lexicon firewall | Extend REQ-012 to docs/ + README.md | lexicon_meta_docs_test.go | v0.3/P1 |
> **Tag-line note (G-010 continuation)**: v0.1 pre-MVP shipped on the `v0.0.x`
> patch line; v0.2 (The Mesh) shipped on the `v0.1.x` patch line; v0.3 (Bearers
> & Documentation) ships on the `v0.2.x` patch line (config.json `tag_base:
> v0.2.x`): P0 -> `v0.2.0`, P1..P5 -> `v0.2.1..v0.2.5`, P6 -> `v0.2.6`
> (= the v0.3 milestone release, per D-008 — final phase patch IS the
> milestone release; no separate minor tag).
## Phase 3 — The Bearers (Year 3) — v0.3 PARTIAL SKELETON
**Target**: $10B annual volume → fee auto-declines to 0.07%
> v0.3 ships a skeleton+tests subset of Phase 3 (Cross-Chain/Exit, OY-SAT/OY-QR,
> Anchors, Hub API, Services, Bond market depth). Full runtime deferred to v0.4+.
| Component | Deliverable |
|---|---|
| Cross-Chain & Exit (2) | Full L2/L1 bridges, DEX integration |
| Bearers expansion | OY-SAT, OY-QR |
| Hub API | B2B backbone: custody, lending primitive, compliance |
| Anchors | First institutional partners |
| Services | Care / SIM / Vault / Mail |
| Bond market | Full market, Growth Bonds |
| Cross-Chain & Exit (2) | Full L2/L1 bridges, DEX integration (runtime deferred to v0.4) |
| Bearers expansion | OY-SAT, OY-QR (skeleton types in v0.3) |
| Hub API | B2B backbone: custody, lending primitive, compliance (skeleton types in v0.3) |
| Anchors | First institutional partners (skeleton types in v0.3) |
| Services | Care / SIM / Vault / Mail (skeleton types in v0.3) |
| Bond market | Full market, Growth Bonds (skeleton types in v0.3) |
## Phase 4 — Maturity (Years 45+)
**Target**: $50100B volume → fees auto-decline to 0.03%