Reference implementation for the Phoenix Architecture. Work in progress. aicoding.leaflet.pub/
ai coding crazy
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add settle-up example — expense splitter for demos

Splitwise-like expense splitting app across 4 specs:
- groups.md: group lifecycle, membership, balance-sum-to-zero invariant
- expenses.md: expense creation, 3 split strategies, remainder handling, balance math
- settlements.md: debt simplification (min payments), settlement recording
- api.md: REST endpoints, error codes, response envelope, pagination

Why this example:
- Everyone understands splitting a dinner bill
- Real invariants (balances sum to zero, shares sum to expense)
- Graph algorithm (minimum settlement payments)
- Mixed risk tiers (balance math = critical, API formatting = low)
- Conservation layer (API shape is public contract)
- Subtle edge cases (remainder cents, cycle reduction)

Bootstrap produces: 66 canon nodes, 12 IUs, 4 services, LLM-generated code
with split strategies, debt simplification, and full REST API.

+175
+63
examples/settle-up/README.md
··· 1 + # Settle Up — Phoenix Example 2 + 3 + An expense-splitting app (like Splitwise) specified across four specs: 4 + groups, expenses, settlements, and REST API. 5 + 6 + **Why this example?** It's simple enough that anyone understands it instantly — 7 + you split a dinner bill with friends. But it has real architectural complexity: 8 + money math with invariants (balances must sum to zero), a graph optimization 9 + problem (minimum settlements), multiple risk tiers (balance calculation is 10 + critical, API formatting is low), and conservation layers (the API shape 11 + is a public contract that can't change freely). 12 + 13 + ## Walkthrough 14 + 15 + ```bash 16 + # From the phoenix repo root (one-time) 17 + cd /path/to/phoenix 18 + npm run build && npm link 19 + 20 + # Enter this example 21 + cd examples/settle-up 22 + 23 + # Step 1: Initialize Phoenix 24 + phoenix init 25 + 26 + # Step 2: Bootstrap — ingest specs, canonicalize, plan, generate 27 + phoenix bootstrap 28 + 29 + # Step 3: Explore what was produced 30 + phoenix status # Trust dashboard 31 + phoenix canon # Canonical requirement graph 32 + phoenix plan # Implementation Units 33 + phoenix drift # Drift detection 34 + phoenix evaluate # Evidence against policy 35 + phoenix audit # Replacement readiness per IU 36 + 37 + # Step 4: Make a change — edit a spec, see what cascades 38 + # e.g. add "expenses must support tags" to spec/expenses.md 39 + phoenix diff # See what changed 40 + phoenix bootstrap # Re-run pipeline 41 + 42 + # Step 5: Install and test 43 + npm install 44 + npm test 45 + npm start # API server on :3000 46 + ``` 47 + 48 + ## Specs 49 + 50 + | Spec | Covers | 51 + |------|--------| 52 + | `spec/groups.md` | Group lifecycle, membership, balances summing to zero | 53 + | `spec/expenses.md` | Expense creation, split strategies, remainder handling, balance math | 54 + | `spec/settlements.md` | Debt simplification algorithm, settlement recording, settled-up status | 55 + | `spec/api.md` | REST endpoints, error codes, response envelope, pagination | 56 + 57 + ## Interesting Things to Notice 58 + 59 + 1. **Risk tiers vary**: Balance calculation is `critical` (money math). API formatting is `low`. Phoenix assigns different evidence requirements. 60 + 2. **Invariants are real**: "Net balances must sum to zero" is a system invariant that evaluation coverage will flag if untested. 61 + 3. **The settlement algorithm is a graph problem**: Minimum payments to settle all debts is a max-flow / net-flow optimization. Canonical extraction should identify this as a distinct requirement. 62 + 4. **The API is a conservation layer**: External clients depend on the response format. `phoenix audit` should flag it as needing conservation-layer protection. 63 + 5. **Remainder handling is subtle**: $10 split 3 ways can't be $3.33 × 3. The spec says the payer absorbs the extra cent. This is the kind of constraint that negative knowledge captures when a generation attempt gets it wrong.
+30
examples/settle-up/spec/api.md
··· 1 + # REST API 2 + 3 + ## Endpoints 4 + 5 + - POST /groups — create a new group (body: name, currency, creator member) 6 + - GET /groups/:id — get group details including member list and summary 7 + - POST /groups/:id/members — add a member to a group 8 + - DELETE /groups/:id/members/:memberId — remove a member from a group 9 + 10 + - POST /groups/:id/expenses — add an expense (body: description, amount, payer, participants, split strategy) 11 + - GET /groups/:id/expenses — list expenses with optional filters (payer, participant, date range) 12 + - DELETE /groups/:id/expenses/:expenseId — delete an expense 13 + 14 + - GET /groups/:id/balances — get all member balances for a group 15 + - GET /groups/:id/settlements — compute the minimum settlement plan 16 + - POST /groups/:id/settlements — record a settlement payment 17 + 18 + ## Error Handling 19 + 20 + - All endpoints must return structured JSON errors with a code and human-readable message 21 + - Invalid group ID must return 404 22 + - Invalid member (not in group) must return 403 23 + - Invalid expense data (negative amount, missing participants) must return 400 24 + - Attempting to remove a member with non-zero balance must return 409 (Conflict) 25 + 26 + ## Response Format 27 + 28 + - All responses must use JSON with consistent envelope: { ok: boolean, data?: T, error?: { code: string, message: string } } 29 + - List endpoints must support pagination with `limit` and `offset` query parameters 30 + - Monetary amounts in responses must be represented as integer cents to avoid floating-point errors
+35
examples/settle-up/spec/expenses.md
··· 1 + # Expenses 2 + 3 + ## Creating an Expense 4 + 5 + - An expense must have a unique expense ID, a description, an amount, and a date 6 + - An expense must reference exactly one payer (who paid) by member ID 7 + - An expense must reference one or more participants (who benefited) by member ID 8 + - The payer must be a member of the group 9 + - All participants must be members of the group 10 + - The expense amount must be a positive number with at most two decimal places 11 + - An expense cannot be created in a group that does not exist 12 + 13 + ## Split Strategies 14 + 15 + - An expense can be split equally among all participants 16 + - An expense can be split by exact amounts specified per participant 17 + - An expense can be split by percentages that must sum to 100 18 + - When splitting equally, remainders (e.g. $10 / 3) must be assigned to the payer — no rounding loss 19 + - The sum of all individual shares must always equal the total expense amount — this is a system invariant 20 + 21 + ## Expense History 22 + 23 + - All expenses in a group must be queryable in reverse chronological order 24 + - Expenses must be filterable by payer, by participant, and by date range 25 + - Each expense must record who created it and when 26 + - An expense can be deleted by the member who created it 27 + - Deleting an expense must reverse its effect on all member balances immediately 28 + 29 + 30 + ## Balance Calculation 31 + 32 + - Each member's balance must be computed from the full expense history 33 + - A member's balance is: (total they paid for others) minus (total others paid for them) 34 + - Balance calculation must be deterministic — same expenses always produce same balances 35 + - Balances must be recalculated whenever an expense is added or deleted
+23
examples/settle-up/spec/groups.md
··· 1 + # Groups 2 + 3 + ## Group Management 4 + 5 + - A group must have a unique group ID, a name, and a currency code (e.g. "USD", "EUR") 6 + - A group must have at least one member 7 + - A group must track its creation date 8 + - Only group members can add expenses to the group 9 + - A member can belong to multiple groups 10 + - Each member must have a unique member ID, a display name, and an email address 11 + 12 + ## Member Operations 13 + 14 + - A member can be added to a group by any existing member 15 + - A member can leave a group only if their net balance is zero 16 + - When a member leaves, their past expenses remain in the group history 17 + - A member cannot be removed from a group if they owe or are owed money 18 + 19 + ## Group Summary 20 + 21 + - The group summary must show each member's net balance (positive = owed, negative = owes) 22 + - The group summary must show the total number of expenses and total amount spent 23 + - Net balances across all members must always sum to zero — this is a system invariant
+24
examples/settle-up/spec/settlements.md
··· 1 + # Settlements 2 + 3 + ## Debt Simplification 4 + 5 + - The system must compute the minimum number of payments to settle all debts in a group 6 + - A settlement plan must list each required payment: who pays whom, and how much 7 + - A simplified settlement must produce the same net effect as paying each debt individually 8 + - If only two members have a balance, the settlement is a single payment from debtor to creditor 9 + - The algorithm must handle cycles (A owes B, B owes C, C owes A) by reducing to net flows 10 + - A group where all balances are zero must produce an empty settlement plan 11 + 12 + ## Recording Settlements 13 + 14 + - A member can record a settlement payment (I paid X to Y for Z amount) 15 + - Recording a settlement must update both members' balances 16 + - A settlement must be rejected if the amount exceeds what the payer owes the recipient 17 + - Settlements must be tracked separately from expenses in the history 18 + - A settlement has: settlement ID, payer, recipient, amount, date, and optional note 19 + 20 + ## Settlement Status 21 + 22 + - The system must report whether a group is "settled up" (all balances zero) or has outstanding debts 23 + - Each member must be able to see: who they owe, who owes them, and the amounts 24 + - The total of all outstanding debts must be visible at the group level