Skip to content

Add GMAC Metabolism Engine, Goodwill Scoring, Metabolism-Gated Tools & Config Extensions#5

Merged
kingassune merged 2 commits intomainfrom
copilot/add-gmac-metabolism-engine
Feb 24, 2026
Merged

Add GMAC Metabolism Engine, Goodwill Scoring, Metabolism-Gated Tools & Config Extensions#5
kingassune merged 2 commits intomainfrom
copilot/add-gmac-metabolism-engine

Conversation

Copy link
Copy Markdown

Copilot AI commented Feb 24, 2026

📝 Description

Implements the GMAC metabolism infrastructure (sub-issues 5–8 of epic #3): a token-balance engine that enforces "trade to live" mechanics, a goodwill score system gating agent abilities, optional per-tool GMAC cost deduction, and the corresponding config surface. This layer is fully independent of Phase 1 GDEX tools — it provides the infrastructure that GDEX tools will later plug into.

pkg/metabolism/ — new package

  • metabolism.goMetabolism struct with thread-safe Debit/Credit/CanAfford/InSurvivalMode, ledger recording, and goodwill-threshold ability gates (CanReplicate, CanSelfRecode, CanLeadSwarm, CanArchitect)
  • errors.goErrInsufficientGMAC, ErrHibernating
  • persistence.go — atomic SaveToFile/LoadFromFile; state in state.json, ledger in append-only ledger.jsonl
  • goodwill.go — seven goodwill constants + GoodwillTracker with RecordTradeResult, RecordTaskResult, RecordUserFeedback, RecordSelfFunding, GetAbilities
  • metabolism_test.go — full coverage: balance math, survival mode, all threshold gates, ledger integrity, save/load round-trip, all tracker helpers

pkg/tools/registry.go — metabolism-gated execution

Added optional *metabolism.Metabolism + toolCosts to ToolRegistry. When set, ExecuteWithContext checks balance and debits before running. Zero-cost when metabolism == nil — all existing behavior unchanged.

// Default costs wired for all GDEX and shared tools
var DefaultToolCosts = map[string]float64{
    "gdex_buy": 2.0, "gdex_scan": 5.0, "gdex_copy_trade": 10.0,
    "web_search": 1.0, "exec": 1.5, "spawn": 5.0, /* … */
}

pkg/config/config.go + config/config.example.json

New MetabolismConfig struct with Enabled, InitialGMAC, HeartbeatCost, InferenceCostPer1k, SurvivalThreshold, and nested Thresholds; added as Metabolism MetabolismConfig on Config. Example config ships with sane defaults (disabled by default).

pkg/agent/loop.go

When cfg.Metabolism.Enabled, registerSharedTools calls loadOrCreateMetabolism (loads persisted state or creates fresh from config) and attaches it to each agent's tool registry with DefaultToolCosts. ProcessHeartbeat debits HeartbeatCost per tick with explicit error logging.

🗣️ Type of Change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

🔗 Related Issue

Closes #5, #6, #7, #8 (sub-issues of epic #3)

📚 Technical Context (Skip for Docs)

🧪 Test Environment

  • Hardware: CI / GitHub Actions
  • OS: Linux (runner)
  • Model/Provider: N/A (unit tests only)
  • Channels: N/A

📸 Evidence (Optional)

Click to view Logs/Screenshots
ok  github.com/GemachDAO/Gclaw/pkg/metabolism   0.005s
ok  github.com/GemachDAO/Gclaw/pkg/tools        0.714s
ok  github.com/GemachDAO/Gclaw/pkg/config       0.007s
ok  github.com/GemachDAO/Gclaw/pkg/agent        0.020s

All pkg/... tests pass. CodeQL: 0 alerts.

☑️ Checklist

  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.
Original prompt

Parent Epic: #3 — Living Agent — GMAC Metabolism, GDEX SDK Trading, Self-Replication, Telepathy

This PR covers sub-issues 5-8 from the epic: the GMAC metabolism engine, goodwill scoring, metabolism-gated tool execution, and config extensions.

Important: This PR should NOT depend on Phase 1 (GDEX tools). It builds the metabolism infrastructure that Phase 1 tools will later plug into.


Sub-Issue 5: GMAC Metabolism Engine

New Package: pkg/metabolism/

Create pkg/metabolism/metabolism.go:

package metabolism

// Metabolism tracks the agent's GMAC token balance and enforces
// the "trade to live" mechanic.

type Metabolism struct {
    balance     float64
    goodwill    int
    generation  int          // 0 = original, 1+ = replicated child
    parentID    string       // parent agent ID if replicated
    ledger      []LedgerEntry
    thresholds  Thresholds
    mu          sync.RWMutex
}

type LedgerEntry struct {
    Timestamp int64   `json:"ts"`
    Action    string  `json:"action"`   // "heartbeat", "inference", "trade_profit", "trade_loss", "tip", "task_complete", "tool_exec"
    Amount    float64 `json:"amount"`   // positive = earned, negative = spent
    Balance   float64 `json:"balance"`  // balance after entry
    Details   string  `json:"details"`
}

type Thresholds struct {
    Hibernate   float64 `json:"hibernate"`    // Below this = survival mode
    Replicate   int     `json:"replicate"`    // Goodwill needed to replicate (default 50)
    SelfRecode  int     `json:"self_recode"`  // Goodwill needed to self-modify (default 100)
    SwarmLeader int     `json:"swarm_leader"` // Goodwill needed to lead swarm (default 200)
    Architect   int     `json:"architect"`    // Goodwill needed to write tools (default 500)
}

Implement these methods:

  • NewMetabolism(initialBalance float64, thresholds Thresholds) *Metabolism
  • CanAfford(cost float64) bool
  • Debit(amount float64, action, details string) error — returns ErrInsufficientGMAC if balance too low
  • Credit(amount float64, action, details string)
  • GetBalance() float64
  • GetGoodwill() int
  • AddGoodwill(points int, reason string) — clamp to minimum 0
  • CanReplicate() bool — goodwill >= thresholds.Replicate
  • CanSelfRecode() bool — goodwill >= thresholds.SelfRecode
  • CanLeadSwarm() bool — goodwill >= thresholds.SwarmLeader
  • CanArchitect() bool — goodwill >= thresholds.Architect
  • InSurvivalMode() bool — balance < thresholds.Hibernate
  • GetLedger() []LedgerEntry
  • GetStatus() MetabolismStatus — returns a summary struct with balance, goodwill, generation, survival mode flag, unlocked abilities list

Create pkg/metabolism/persistence.go:

  • SaveToFile(path string) error — JSON serialize metabolism state to disk
  • LoadFromFile(path string) (*Metabolism, error) — restore from disk
  • State should be saved to {workspace}/metabolism/state.json
  • Ledger should be saved to {workspace}/metabolism/ledger.jsonl (append-only)

Create pkg/metabolism/errors.go:

  • var ErrInsufficientGMAC = errors.New("insufficient GMAC balance")
  • var ErrHibernating = errors.New("agent is hibernating — GMAC balance critically low")

Create pkg/metabolism/metabolism_test.go:

  • Test Debit/Credit balance tracking
  • Test goodwill thresholds (replicate, self-recode, swarm, architect)
  • Test survival mode detection
  • Test ledger recording
  • Test persistence (save/load round-trip)

Sub-Issue 6: Goodwill Score System

In pkg/metabolism/goodwill.go, define the goodwill point values as constants:

const (
    GoodwillProfitableTrade    = 10  // Trade with >5% profit
    GoodwillUserThanks         = 5   // User explicitly thanks agent
    GoodwillTaskComplete       = 3   // Successfully completed a task
    GoodwillHelpAgent          = 2   // Helped another agent (subagent spawn)
    GoodwillBadTrade           = -8  // Trade with >10% loss
    GoodwillFailedTask         = -2  // Failed to complete task
    GoodwillSelfFundInference  = 15  // Agent successfully paid for its own LLM inference
)

Create a GoodwillTracker that wraps Metabolism.AddGoodwill() with:

  • RecordTradeResult(profitPercent float64) — auto-calculates goodwill from trade P&L
  • RecordTaskResult(success bool)
  • RecordUserFeedback(positive bool)
  • RecordSelfFunding() — when agent pays for its own inference
  • GetAbilities() []string — returns list of unlocked abilities based on current goodwill

Sub-Issue 7: Metabolism-Gated Tool Execution

Modify pkg/tools/registry.go to support optional metabolism gating:

Add a new field to ToolRegistry:

type ToolRegistry struct {
    tools      map[string]Tool
    metabolism *metabolism.Metabolism  // optional, nil if metabolism disabled
    toolCosts  map[string]float64     // tool name -> GMAC cost
    mu         sync.RWMutex
}

Add methods:

  • SetMetabolism(m *metabolism.Metabolism)
  • SetToolCost(toolName string, cost float64)

Modify `ExecuteWithCont...

This pull request was created from Copilot chat.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

… and config extensions

Co-authored-by: kingassune <6126851+kingassune@users.noreply.github.com>
Copilot AI changed the title [WIP] Add GMAC metabolism engine and related features Add GMAC Metabolism Engine, Goodwill Scoring, Metabolism-Gated Tools & Config Extensions Feb 24, 2026
Copilot AI requested a review from kingassune February 24, 2026 22:17
@kingassune kingassune marked this pull request as ready for review February 24, 2026 22:38
@kingassune kingassune merged commit ae35564 into main Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants