λ Reputation — Algorithm Extraction
Language-agnostic pseudocode extracted from Phoenix Python source.
Source files: pure_core.py (579L), tokens.py (149L).
1. Five Reputation Domains
| Domain | Measures | Decay Rate (bps/epoch) | Access Grants |
|---|---|---|---|
| Execution | Task completion quality | 500 (5%) | Parallel task slots, reduced cooldowns |
| Commissioning | Task creation & scoping | 300 (3%) | Stake-setting authority, high-rep executor access |
| Arbitration | Dispute fairness | 1000 (10%) | Arbiter pool membership, dispute vote weight |
| Governance | Rule participation | 200 (2%) | Proposal rights, governance vote weight |
| Social | Relationships & vouching | 100 (1%) | Recovery guardian eligibility, gossip priority |
Domains are independent: no cross-domain transfer. Each computed separately.
enum ReputationDomain:
EXECUTION
COMMISSIONING
ARBITRATION
SOCIAL
GOVERNANCE
// decay_rates_bps: source-verified from pure_core.py
decay_rates_bps = {
EXECUTION: 500,
COMMISSIONING: 300,
ARBITRATION: 1000,
GOVERNANCE: 200,
SOCIAL: 100,
}
2. apply_decay() Pseudocode with Quadratic Entropy
function apply_decay(rep: Map<Domain, int64>, inactive_epochs: Map<Domain, int64>) -> Map<Domain, int64>:
result = copy(rep)
for domain in ReputationDomain:
if inactive_epochs[domain] == 0:
continue // active this epoch; no decay
base_rate = decay_rates_bps[domain]
// Quadratic entropy multiplier: higher rep decays proportionally faster
// entropy = ilog2(1 + rep[domain]/1000) + 1
entropy = max(1, ilog2(1 + result[domain] / 1000) + 1)
effective_rate = min(base_rate * entropy, 5000) // cap at 50% per epoch
decay_amount = (result[domain] * effective_rate) / 10000
result[domain] = max(0, result[domain] - decay_amount)
return result
// Properties:
// - Exponential: higher scores decay faster (quadratic multiplier)
// - Floor: score never goes below 0
// - Cap: max decay is 50% per epoch (5000 bps)
// - Activity resets: if inactive_epochs == 0 for domain, no decay that epoch
Entropy Multiplier Examples
| Rep Score | entropy = ilog2(1 + score/1000) + 1 | effective_rate (EXECUTION, base=500) |
|---|---|---|
| 0 | 1 | 500 bps (5%) |
| 1000 | ilog2(2)+1 = 2 | 1000 bps (10%) |
| 7000 | ilog2(8)+1 = 4 | 2000 bps (20%) |
| 10000 | ilog2(11)+1 = 4 | 2000 bps (20%) |
3. 14-Action Reputation Delta Table
Full table from pure_core.py action_table:
| Action | Delta (bps) | Domain | Notes |
|---|---|---|---|
| CreateProposal | +1000 | Commissioning | Initiating new work contracts |
| CreateContract | +1000 | Commissioning | Creating governance proposals |
| AcceptCommitment | +500 | Execution | Accepting a task commitment |
| SettleContract | +500 | Execution | Completing a contract successfully |
| OpenDispute | +2000 | Arbitration | Initiating dispute resolution |
| ResolveDispute | +2000 | Arbitration | Resolving a dispute as arbiter |
| Schism | -1000 | Social | Creating a network split |
| InvitePeer | +500 | Social | Inviting a new participant |
| Vouch | +500 | Social | Vouching for another node’s identity |
| SecureIdentity | +1500 | Social | Setting up identity recovery (SSS) |
| RecoverIdentity | +2000 | Social | Recovering lost identity via guardians |
| VoteCast | +200 | Arbitration | Casting any governance vote |
| GovernancePropose | +2500 | Governance | Submitting a governance proposal |
| GovernanceVote | +2500 | Governance | Voting on a governance proposal |
function calculate_reputation_delta(action: string, actor: Node) -> (int64, Domain):
(base_delta, domain) = action_table[action]
adjusted = apply_gain_ceiling(base_delta, actor.reputation[domain])
adjusted = apply_anti_bias(adjusted, action, actor)
adjusted = apply_sentinel_dampening(adjusted, actor.sentinel_status)
return (adjusted, domain)
4. Tiered Gain Ceiling Formula
Diminishing returns on reputation gain based on current score:
// gain_ceiling_tiers: (score_threshold, max_gain_bps)
gain_ceiling_tiers = [
(10000, 5000), // score < 10000: gain capped at 5000 bps
(100000, 3000), // score < 100000: gain capped at 3000 bps
(∞, 1000), // score >= 100000: gain capped at 1000 bps
]
function apply_gain_ceiling(base_delta: int64, current_score: int64) -> int64:
if base_delta <= 0: return base_delta // penalties not subject to ceiling
for (threshold, cap_bps) in gain_ceiling_tiers:
if current_score < threshold:
return min(base_delta, cap_bps)
return min(base_delta, 1000) // floor tier
5. Offense Penalties
Severity Table
| Severity | Penalty (bps) | Scar Applied | Ban Duration |
|---|---|---|---|
| Minor | 1500 (15%) | No | None |
| Moderate | 3000 (30%) | No | None |
| Severe | 5000 (50%) | Yes — reduces max_score | None |
| Critical | 8000 (80%) | Yes — reduces max_score | N epochs (configurable) |
| Fraud | 10000 (100%) | Yes — permanent scar | Permanent |
function calculate_damage(severity: Severity, current_score: int64) -> DamageResult:
penalty_bps = severity_to_bps[severity]
damage = (current_score * penalty_bps) / 10000
scar = severity in [SEVERE, CRITICAL, FRAUD]
permanent = severity == FRAUD
ban_epochs = get_ban_duration(severity) // 0 for Minor/Moderate
return DamageResult {
damage: damage,
scar: scar,
permanent: permanent,
ban: ban_epochs,
}
// Double jeopardy protection: same event cannot trigger same penalty twice
function apply_penalty(node: Node, event_id: bytes32, severity: Severity):
if event_id in node.penalized_events[severity]:
return // already penalized for this event at this severity
node.penalized_events[severity].add(event_id)
result = calculate_damage(severity, node.reputation[domain])
node.reputation[domain] = max(0, node.reputation[domain] - result.damage)
if result.scar:
apply_scar(node, result)
Scar Rules
function apply_scar(node: Node, damage: DamageResult):
// Scar = permanent reduction in max_score ceiling
node.max_score[domain] = max(0, node.max_score[domain] - damage.damage)
// Score may not exceed max_score (enforced on every update)
node.reputation[domain] = min(node.reputation[domain], node.max_score[domain])
if damage.permanent:
// Fraud scar: max_score permanently locked at current level
node.fraud_locked = true
// Reputation can never increase above current max_score for this domain
6. Anti-Bias: 90% Correlation Dampening
Prevents reputation farming by repeatedly using the same counterparty or action pattern.
ANTI_BIAS_THRESHOLD = 0.90 // 90% correlation triggers dampening
ANTI_BIAS_REDUCTION = 0.50 // reduce gain by 50%
function apply_anti_bias(delta: int64, action: string, actor: Node) -> int64:
if delta <= 0: return delta // penalties not dampened by anti-bias
// Check: is arbitration reputation > 90% from interactions with same counterparty?
if action in ARBITRATION_ACTIONS:
correlation = compute_counterparty_correlation(actor, domain=ARBITRATION)
if correlation >= ANTI_BIAS_THRESHOLD:
return (delta * 5000) / 10000 // 50% reduction
return delta
function compute_counterparty_correlation(actor: Node, domain: Domain) -> float:
// Returns fraction of domain rep earned from most frequent single counterparty
rep_by_counterparty = aggregate_rep_by_source(actor, domain)
if total_rep == 0: return 0.0
max_single = max(rep_by_counterparty.values())
return max_single / total_rep
7. Sentinel Dampening
When the integrity monitor flags a node, reputation gains are suppressed.
enum SentinelStatus: NORMAL, WARN, CRITICAL
function apply_sentinel_dampening(delta: int64, status: SentinelStatus) -> int64:
if delta <= 0: return delta // penalties not dampened
match status:
NORMAL: return delta
WARN: return (delta * 5000) / 10000 // WARN → 50% of gain
CRITICAL: return 0 // CRITICAL → 0% (no gain)
8. Experience Token Levels
enum TokenLevel: L0=0, L1=1, L1_5=15, L2=2, L3=3
enum TokenKind: EPISTEMIC_MASTERY, MORAL_STANDING, SYSTEMIC_INTEGRITY
enum L2SubLevel: L2A_CORRELATION, L2B_CAUSAL
enum IrreversibilityType: EPISTEMIC, MORAL, SYSTEMIC
Token Level Hierarchy
| Level | Name | Minting Condition |
|---|---|---|
| L0 | Raw Token | Auto-minted on first event completion |
| L1 | Episode | Full commit → deliver → confirm cycle completed |
| L1.5 (Witness) | WitnessToken | 3 or more disputes witnessed as observer |
| L2a | Correlation | 5+ same-pattern repetitions across events |
| L2b | Proto-Causal | L2a + context_diversity >= 2 + 3 counterparties |
| L3 | Mastery / Scar / Systemic | Promotion from L2b only (not L2a) |
All tokens are non-transferable — bound permanently to issuing node identity.
9. L3 Permanence Rules
// L3 decay behavior depends on IrreversibilityType:
function apply_l3_decay(token: TokenRecord, epochs_elapsed: int64) -> TokenRecord:
match token.irreversibility_type:
EPISTEMIC:
// Linear decay over 100 epochs
decay_per_epoch = token.initial_weight / 100
token.weight = max(0, token.initial_weight - decay_per_epoch * epochs_elapsed)
MORAL:
// No decay — permanent moral scar
// token.weight unchanged forever
pass
SYSTEMIC:
// No decay + quarantine flag set
// Node placed in reduced-trust mode
token.quarantine = true
// token.weight unchanged
return token
10. WitnessToken Rules
WITNESS_MAX_WEIGHT = 0.30 // Max 30% of reputation weight per WitnessToken
WITNESS_PORTFOLIO_CAP = 0.40 // Max 40% of total portfolio may be WitnessTokens (INV-ET-06)
// WitnessToken minting:
function mint_witness_token(node: Node, dispute_id: bytes32) -> WitnessToken | null:
witnessed = count_witnessed_disputes(node)
if witnessed < 3: return null // minimum threshold
return WitnessToken {
node_id: node.id,
level: L1_5,
weight: min(compute_witness_weight(node), WITNESS_MAX_WEIGHT),
dispute_id: dispute_id,
minted_epoch: current_epoch,
}
function enforce_portfolio_cap(node: Node):
witness_weight = sum(t.weight for t in node.tokens if t.level == L1_5)
total_weight = sum(t.weight for t in node.tokens)
if total_weight > 0 and witness_weight / total_weight > WITNESS_PORTFOLIO_CAP:
// Scale down witness token weights proportionally
scale = (WITNESS_PORTFOLIO_CAP * total_weight) / witness_weight
for t in node.tokens:
if t.level == L1_5: t.weight *= scale
11. Token Promotion Conditions
function can_promote_to_l2b(node: Node, l2a_token: Token) -> bool:
// L2b requires: L2a exists + context diversity >= 2 + 3 distinct counterparties
return (
l2a_token.level == L2A_CORRELATION
AND compute_context_diversity(node) >= 2
AND count_distinct_counterparties(node) >= 3
)
function can_promote_to_l3(node: Node, l2_token: Token) -> bool:
// L3 can only be promoted from L2b (not L2a)
return l2_token.level == L2B_CAUSAL
function promote_token(node: Node, token: Token, new_level: TokenLevel) -> Token:
if new_level == L3:
irr_type = determine_irreversibility(token) // EPISTEMIC / MORAL / SYSTEMIC
return Token {
...token,
level: new_level,
irreversibility_type: irr_type,
promoted_epoch: current_epoch,
}
12. Derived Limits from Reputation
function max_parallel_tasks(rep: Map<Domain, int64>) -> int:
return min(isqrt(max(rep[EXECUTION], 1)), 20)
function rate_limit_bonus(rep: Map<Domain, int64>, base_rate: int64) -> int64:
return base_rate * max(1, ilog2(max(rep[EXECUTION], 1)))
function stake_requirement(required: int64, rep: Map<Domain, int64>) -> int64:
return (required * 10000) / max(rep[EXECUTION], 1000)
function can_arbitrate(rep: Map<Domain, int64>) -> bool:
return rep[ARBITRATION] >= 5000 AND rep[EXECUTION] >= 3000
function can_govern(rep: Map<Domain, int64>) -> bool:
return rep[GOVERNANCE] >= 4000
function cooldown(base: int64, rep: Map<Domain, int64>) -> int64:
return base - min(ilog2(max(rep[EXECUTION], 1)), base / 2)
13. Recovery: Shamir’s Secret Sharing
SSS_SHARES = 5 // total guardian shares
SSS_THRESHOLD = 3 // required shares to recover
function setup_recovery(node: Node) -> Share[]:
shares = shamir_split(node.secret_key, SSS_SHARES, SSS_THRESHOLD)
// Distribute one share to each chosen guardian
return shares
function recover_identity(shares: Share[]) -> Node:
assert len(shares) >= SSS_THRESHOLD
secret_key = shamir_reconstruct(shares, SSS_THRESHOLD)
node = load_identity(secret_key)
// Recovery penalty: 50% reputation discount on recovery
for domain in node.reputation:
node.reputation[domain] = (node.reputation[domain] * 5000) / 10000
return node
14. Data Structures
struct ReputationRecord:
node_id: NodeId
domain: ReputationDomain
score: int64 // 0 to max_score (bps-scale, 10000 = full)
max_score: int64 // reduced by scars
scars: bitmask // bitmask of applied scar types
ban_until_epoch: int64 // 0 if not banned
last_activity_epoch: int64
created_at: int64
struct ReputationEvent:
node_id: NodeId
domain: ReputationDomain
epoch: int64
delta: int64
reason: string
event_id: bytes32
consequence_hash: bytes32 // hash of triggering event
struct TokenRecord:
node_id: NodeId
kind: TokenKind // EPISTEMIC / MORAL / SYSTEMIC
level: TokenLevel // L0, L1, L1_5, L2A, L2B, L3
discriminator: string // unique label for this token's evidence
minted_epoch: int64
work_proof: bytes32 // SHA-256 of evidence
irreversibility_type: IrreversibilityType? // set for L3 only
weight: int64 // bps-scaled contribution weight
quarantine: bool // set for SYSTEMIC L3
15. Dependencies
| Module | Interaction |
|---|---|
| κ Rule Engine | Computes reputation deltas from rule effects |
| θ Consensus | Validates reputation changes have quorum |
| ι State Fork | Fork carries reputation snapshot; merge applies 50% discount |
| η Proof Store | All rep changes produce Merkle proofs |
| μ Integrity | Sentinel status dampens gains (advisory) |
Links
| [[concepts/λ-reputation | λ Reputation]] · [[spec/S04-reputation | S04 Reputation Spec]] · [[spec/S05-experience-tokens | S05 Experience Tokens]] · [[reference/extractions/kappa-rule-engine-extraction | κ Extraction]] · [[reference/extractions/theta-consensus-extraction | θ Extraction]] |