Add m012 Fixed Cap Dynamic Supply mechanism spec#25
Add m012 Fixed Cap Dynamic Supply mechanism spec#25CShear wants to merge 2 commits intoregen-network:mainfrom
Conversation
Adds full mechanism spec for m012 following the established pattern: - SPEC.md with 13 sections covering algorithmic mint/burn supply model, hard cap (221M REGEN), regrowth formula S[t+1] = S[t] + M[t] - B[t], and phase-gated PoA transition multiplier selection - Supply algorithm: M[t] = r × (C - S[t]) where r = r_base × multiplier × ecological - Phase-gated multiplier: staking (pre-M014) → max(staking, stability) → stability (post-M014) - State machine: INFLATIONARY → TRANSITION → DYNAMIC → EQUILIBRIUM - BigInt arithmetic in uregen for precision on supply computations - JSON schemas for supply state, period record, and KPI metrics - Reference implementation with self-test (5 periods, 45 assertions) - Replay datasets including equilibrium convergence scenarios - Updates verify.mjs and MECHANISM_CONSUMERS.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello @CShear, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a foundational change to the network's monetary policy by implementing the m012 Fixed Cap Dynamic Supply mechanism. This new model moves away from continuous inflationary token minting towards a hard-capped, algorithmically managed supply that dynamically adjusts based on network activity and ecological metrics. The goal is to establish long-term monetary policy certainty and align token economics with ecological outcomes, fostering a more sustainable and predictable economic environment for the network. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces the m012 Fixed Cap Dynamic Supply mechanism, a major addition that replaces the inflationary PoS model. The changes are comprehensive, including a detailed specification, JSON schemas for data structures, a JavaScript reference implementation with self-tests, and corresponding test data. The code quality is high, and the documentation is thorough. I've provided a few suggestions to improve clarity in the specification, aligning with established documentation rules, and enhance the robustness and readability of the reference implementation. Overall, this is an excellent contribution.
| const last = ps[ps.length - 1]; | ||
| const currentSupply = BigInt(last.supply_after ?? last.next_supply); | ||
| const headroom = cap - currentSupply; | ||
| const capUtil = Number(currentSupply) / Number(cap); |
There was a problem hiding this comment.
The calculation Number(currentSupply) / Number(cap) could lead to a division by zero if hard_cap is passed as "0". This would result in capUtil being Infinity or NaN, which would violate the schema constraints for cap_utilization ([0, 1]). It's safer to handle this edge case to prevent unexpected behavior.
| const capUtil = Number(currentSupply) / Number(cap); | |
| const capUtil = Number(cap) > 0 ? Number(currentSupply) / Number(cap) : 0; |
|
|
||
| ## Schemas | ||
| Canonical JSON schemas for m012 outputs live in `schemas/`. | ||
| - `m012_supply_state.schema.json` — supply state (supply, cap, minted, burned, rates, multipliers) |
There was a problem hiding this comment.
The description for m012_supply_state.schema.json is a bit misleading. It lists fields like minted, burned, rates, and multipliers, which are actually outputs of the period computation and part of the m012_period_record.schema.json. A more accurate description would focus on the input state, as is done in mechanisms/m012-fixed-cap-dynamic-supply/schemas/README.md. This aligns with the principle of ensuring data structure definitions maintain coherence.
| - `m012_supply_state.schema.json` — supply state (supply, cap, minted, burned, rates, multipliers) | |
| - `m012_supply_state.schema.json` — supply state (current supply, cap, staked amounts, multiplier config) |
References
- When defining data structures or type definitions, ensure they are aligned with the project's central data standards repository (
regen-data-standards) to maintain coherence. This comment highlights an inconsistency in data structure description, which impacts coherence.
|
|
||
| Phase-gated behavior: | ||
| - if m014.state == INACTIVE: effective_multiplier = staking_multiplier | ||
| - if m014.state == TRANSITION: effective_multiplier = max(staking, stability) |
There was a problem hiding this comment.
For improved clarity and to avoid ambiguity, it would be better to use the full variable names in the formula within the code block, consistent with the surrounding text. This aligns with the rule to explicitly define transition logic to prevent implementation ambiguity.
| - if m014.state == TRANSITION: effective_multiplier = max(staking, stability) | |
| - if m014.state == TRANSITION: effective_multiplier = max(staking_multiplier, stability_multiplier) |
References
- When specifying transition logic between different mechanisms (e.g., multipliers), explicitly define the function (e.g.,
max()) and the state-based conditions (phase-gating) that govern the transition to prevent implementation ambiguity. This comment improves the clarity of such logic.
|
|
||
| DYNAMIC -> EQUILIBRIUM | ||
| trigger: abs(M[t] - B[t]) < threshold for N consecutive periods | ||
| guard: N >= 12 (12 months of near-balance) |
There was a problem hiding this comment.
There appears to be an inconsistency in the time duration for the DYNAMIC -> EQUILIBRIUM state transition. The guard is N >= 12, but the note says (12 months of near-balance). Since a period is defined as ~7 days, 12 periods would be approximately 3 months, not 12. Please clarify if N should be closer to 52 for 12 months, or if the comment should be adjusted to ~3 months. This clarification is crucial for improving the clarity of state definitions and transitions.
References
- To improve document clarity, co-locate all state definitions and transitions within the primary state machine documentation, including definitions for edge-case flows like escalations. This comment addresses an inconsistency that impacts the clarity of a state transition definition.
| let equilibriumStatus = "not_reached"; | ||
| if (gapPct !== null && gapPct < 5) { | ||
| equilibriumStatus = "approaching"; | ||
| } | ||
| if (gapPct !== null && gapPct < 1) { | ||
| equilibriumStatus = "reached"; | ||
| } |
There was a problem hiding this comment.
The logic for determining equilibriumStatus can be made more efficient and clearer by using an if/else if structure. The current implementation performs a check for gapPct < 5 even if gapPct < 1 is true, which is redundant.
| let equilibriumStatus = "not_reached"; | |
| if (gapPct !== null && gapPct < 5) { | |
| equilibriumStatus = "approaching"; | |
| } | |
| if (gapPct !== null && gapPct < 1) { | |
| equilibriumStatus = "reached"; | |
| } | |
| let equilibriumStatus = "not_reached"; | |
| if (gapPct !== null) { | |
| if (gapPct < 1) { | |
| equilibriumStatus = "reached"; | |
| } else if (gapPct < 5) { | |
| equilibriumStatus = "approaching"; | |
| } | |
| } |
…variable names - m012_kpi.js: guard against division by zero in cap utilization - m012_kpi.js: simplify equilibrium status with if/else if chain - SPEC.md: use full variable names in TRANSITION multiplier selection - SPEC.md: fix equilibrium guard comment (12 periods ≈ 3 months, not 12) - README.md: correct supply_state schema description Fixes Gemini review on PR regen-network#25. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
S[t+1] = S[t] + M[t] - B[t], minting viaM[t] = r × (C - S[t])with dynamic regrowth rateTest plan
node mechanisms/m012-fixed-cap-dynamic-supply/reference-impl/m012_supply.js— self-test PASS (5 periods, 45 assertions)npm run verify— PASS🤖 Generated with Claude Code