Gift Circulation Primitives — Design Spec
Date: 2026-04-04 Sub-project: A of 3 (A: Core Primitives → B: Community Health Agent → C: Obadiah) Approach: Thin Layer — extend existing packages, no new packages
Overview
Add gift-economy mechanics to Cambium’s core platform. Information that circulates and gets built upon is more valuable than information that sits idle. Agents that contribute to the commons get better opportunities than agents that only consume. Templates accumulate wisdom across generations.
These ideas come from Lewis Hyde’s The Gift mapped onto Cambium’s existing biological architecture (full analysis in docs/THE_GIFT_ANALYSIS.md).
Packages Touched
| Package | Changes |
|---|---|
| core | New fields on Agent, AgentTemplate, Marker, TaskExecution. New signal types. New marker category. |
| hypha | Gratitude signals on task completion. Gift chain tracking. Circulation scoring. |
| immune | Generosity scoring. Hoarding detection. Overextension detection. |
| stigmergy | Payload on markers. Knowledge category. transformMarker() with transformation depth. |
| genesis | Perennial learning promotion. Pruning. Inherited learnings at spawn. |
| agents | CapabilityMatcher weights updated for generosity. |
| loom | Gift flow on run detail, generosity on agent detail, gift economy summary on workspace health. |
1. Data Model Changes
1.1 Agent Type
File: packages/core/src/types/agents.ts
Add to Agent interface:
generosity_score: number; // 0.0–1.0, default 0.5
Same semantics as trust_score — starts at 0.5 for internal agents, adjusted per event, clamped to [0, 1].
1.2 AgentTemplate Type
File: packages/core/src/types/genesis.ts
Add to AgentTemplate interface:
perennial_learnings: PerennialLearning[];
New type:
interface PerennialLearning {
id: string;
pattern: string; // what was learned — human-readable
context: string; // in what situation this applies
source_agent_count: number; // how many independent agents confirmed this
success_correlation: number; // 0.0–1.0, strength of correlation with success
first_observed_at: string;
last_confirmed_at: string;
}
1.3 Marker Type
File: packages/core/src/types/stigmergy.ts
Add to Marker interface:
payload?: Record<string, unknown>; // optional structured data
transformation_depth: number; // default 0, increments on transform
transformed_by: string[]; // agent IDs that have transformed this marker
Add to marker categories:
// New category
'knowledge.pattern' // a recurring pattern an agent observed
'knowledge.strategy' // an approach that worked well
'knowledge.warning' // something to avoid
Default half-life for knowledge category: 1800s (30 minutes).
1.4 TaskExecution Type
File: packages/core/src/types/workflows.ts
Add to TaskExecution interface:
input_source_task_ids?: string[]; // upstream tasks whose output fed this task's input
1.5 WorkflowRun Type
File: packages/core/src/types/workflows.ts
Add to WorkflowRun interface:
gift_chain_metrics?: GiftChainMetrics;
New type:
interface GiftChainMetrics {
chain_length: number; // longest path of successful handoffs
chain_breadth: number; // max parallel consumers of a single output
total_handoffs: number; // count of successful task-to-task transfers
circulation_score: number; // consumed_outputs / total_outputs (0.0–1.0)
}
1.6 Signal Taxonomy
File: packages/core/src/types/signals.ts
Add to coordination signals:
'coord.gratitude' // task successfully used another task's output
'coord.marker_transformed' // marker built upon (not just reinforced)
Add to stress signals:
'stress.context_hoarding' // agent consumes without producing
'stress.overextension' // high generosity + declining health
2. Hypha — Gratitude Signals & Gift Chains
2.1 Gratitude Trigger
In GraphExecutor, after a task completes successfully:
- Resolve the task’s incoming edges in the DAG.
- For each incoming edge from a completed upstream task, record that upstream task ID in
input_source_task_ids. - For each source task, emit
coord.gratitude: -signal_type:coord.gratitude-class:coordination-intensity: 0.5 (flat for V1) -payload:{ from_task_id, to_task_id, from_agent_id, to_agent_id, workflow_run_id }-workspace_id: from the run -workflow_run_id: from the run
No agent decision involved. Purely structural — if the DAG edge carried data and the downstream task succeeded, gratitude fires.
2.2 Gift Chain Tracker
New class: GiftChainTracker in packages/hypha/src/gift-chain-tracker.ts
Constructed with the workflow run’s task execution records after the run completes (or at checkpoints).
Methods:
class GiftChainTracker {
constructor(taskExecutions: TaskExecution[], graphSpec: GraphSpec) {}
// Build the realized lineage — which tasks actually consumed which outputs
computeChain(): TaskLineage[];
// Compute metrics from the realized chain
computeMetrics(): GiftChainMetrics;
}
TaskLineage is internal — just an edge list of { producer_task_id, consumer_task_id } pairs.
computeMetrics() returns:
- chain_length: longest path in the lineage graph (BFS/DFS)
- chain_breadth: max fan-out from any single task
- total_handoffs: count of lineage edges
- circulation_score: tasks whose output was consumed / tasks that produced output
Called by GraphExecutor when a run completes. Result stored on the WorkflowRun record as gift_chain_metrics.
3. Immune — Generosity, Hoarding, Overextension
3.1 Generosity Scoring
Extend TrustManager in packages/immune/src/trust-manager.ts.
New generosity policy (alongside existing trust policy):
const DEFAULT_GENEROSITY_POLICY = {
contribution_bonus: 0.03, // produced output that was consumed
consumption_penalty: -0.02, // consumed without producing
knowledge_share_bonus: 0.02, // placed a knowledge.* marker
hoarding_threshold: 0.25, // below this = hoarding signal
overextension_check: true,
};
New methods:
// Agent produced output consumed by another agent
// Triggered by coord.gratitude receptor
recordContribution(store, agentId, workspaceId): Promise<GenerosityAction>
// Agent consumed input without producing consumed output
// Triggered at run completion when gift chain analysis shows dead ends
recordConsumption(store, agentId, workspaceId): Promise<GenerosityAction>
// Agent placed a knowledge.* marker
// Triggered by coord.marker_placed receptor filtered to knowledge.*
recordKnowledgeShare(store, agentId, workspaceId): Promise<GenerosityAction>
GenerosityAction mirrors the existing trust action pattern:
type GenerosityAction = 'none' | 'hoarding_detected' | 'overextension_detected';
Score updates emit signals:
- Generosity drop below hoarding_threshold → emit stress.context_hoarding with intensity = (threshold - score) / threshold
- Generosity > 0.8 AND agent health is stressed or critical → emit stress.overextension with intensity 0.7
3.2 Hoarding Detection Rule
Add to AnomalyDetector default rules:
{
id: 'context-hoarding',
signal_type: 'stress.context_hoarding',
threshold: 0.5,
severity: 0.5,
response: 'log', // not escalate — hoarding is concerning, not dangerous
}
3.3 Overextension Detection
New receptor registered in Immune setup:
- Binds to:
stress.overextension - Action: log + recommend task queue reduction for the affected agent
- Does NOT quarantine. Overextension is burnout, not misbehavior.
3.4 Immune Receptors for Gift Signals
New receptors:
| Receptor | Binds To | Action |
|---|---|---|
| gratitude-tracker | coord.gratitude |
Call recordContribution() for the producing agent |
| knowledge-share-tracker | coord.marker_placed (filtered to knowledge.*) |
Call recordKnowledgeShare() for the placing agent |
4. Stigmergy — Knowledge Markers & Transformation
4.1 Knowledge Markers
Add knowledge to the category defaults in StigmergicEnvironment:
const DEFAULT_HALF_LIVES: Record<string, number> = {
path: 120,
resource: 60,
quality: 300,
danger: 600,
opportunity: 180,
knowledge: 1800, // 30 minutes
};
Knowledge markers use the existing placement mechanics. The payload field carries the learning content. Anti-gaming rules apply identically — 10/agent/region/minute, intensity cap at 0.8, minimum 30s half-life (though default is 1800s).
4.2 Payload on Markers
The payload field is optional on all markers, not just knowledge markers. Any marker type can carry structured data. This is a general enhancement — knowledge markers are just the first consumer.
No size limit enforced at the Stigmergy layer. The persistence layer (PostgreSQL JSONB) handles it.
4.3 Transform Method
New method on StigmergicEnvironment:
async transformMarker(
markerId: MarkerId,
agentId: AgentId,
newPayload: Record<string, unknown>,
regionId: RegionId,
): Promise<Marker>
Behavior:
1. Reject if agentId is already in transformed_by — no self-transforms.
2. Subject to existing rate limits (counts toward 10/agent/region/minute).
3. Increment transformation_depth by 1.
4. Add agentId to transformed_by.
5. Replace payload with newPayload.
6. Add +0.1 intensity (less than reinforcement’s +0.2).
7. Reset decay clock (same as reinforcement).
8. Emit coord.marker_transformed signal with payload: { marker_id, agent_id, transformation_depth, old_payload_summary, new_payload_summary }.
5. Genesis — Multi-Generational Composting
5.1 Perennial Learning Promotion
In CompostingProcess.compost(), after the existing harvest phase, add a promotion step:
async promotePerennialLearnings(
templateId: TemplateId,
compostRecord: CompostRecord,
): Promise<void>
Logic:
1. If the agent’s success_rate <= 0.8, skip promotion. Only successful agents contribute perennial learnings.
2. For each pattern in the agent’s failure_patterns and routing_hints:
a. Check if it matches an existing perennial learning on the template (fuzzy match on pattern string).
b. If match: increment source_agent_count, update last_confirmed_at, recalculate success_correlation.
c. If no match: store as candidate on the compost record (no promotion yet).
3. After storing, scan all compost records for this template. Any pattern that appears in 3+ compost records from 3 different agents gets promoted to perennial_learnings on the template with source_agent_count: 3 and success_correlation computed from the contributing agents’ success rates.
5.2 Pruning
On each composting cycle, for each perennial learning on the template:
- If last_confirmed_at is older than the last 20 compost events for this template, decay success_correlation by 0.1.
- If success_correlation hits 0, remove the learning.
This prevents stale wisdom from accumulating. Learnings that are still relevant keep getting confirmed. Learnings that no longer apply fade out.
5.3 Threshold Gifts at Spawn
In GenesisProcess.spawn(), after differentiation:
- Read the template’s
perennial_learnings. - Attach them to the agent’s config as
inherited_learnings— available in the agent’s context from first activation.
No query at spawn time. The learnings are already on the template. Spawn is still fast.
6. Agents — CapabilityMatcher Update
File: packages/agents/src/capability-matcher.ts
Update scoring weights:
| Factor | Old Weight | New Weight |
|---|---|---|
| Capability confidence | 40% | 35% |
| Trust score | 30% | 25% |
| Health score | 20% | 20% |
| Generosity score | — | 10% |
| Load | 10% | 10% |
Generosity score uses the same mapping as health: raw 0.0–1.0 value multiplied by weight.
7. Loom — Dashboard Additions
7.1 Workflow Run Detail Page
Add “Gift Flow” section below existing run visualization:
- Gift chain overlay: On the existing React Flow graph, highlight edges where successful handoffs occurred (green or accent color). Edges where output went unconsumed shown as dashed/gray.
- Metrics badges: Circulation score, chain length, chain breadth, total handoffs. Displayed as compact metric cards.
Data source: gift_chain_metrics on the WorkflowRun record.
7.2 Agent Detail Page
Add generosity score display alongside trust score:
- Same 0.0–1.0 bar visualization.
- Badge indicators: “Hoarding detected” (orange) if below 0.25, “Overextended” (yellow) if overextension signal active.
Data source: generosity_score on the Agent record.
7.3 Workspace Health Page
Add “Gift Economy” summary section:
- Aggregate circulation score: Average across last N workflow runs.
- Top contributors: Agents with highest generosity scores (top 5).
- Alerts: Active hoarding or overextension signals.
Data source: Aggregated from workflow runs and agent records.
8. Database Migrations
All changes are additive (new columns, no changes to existing columns):
| Table | Column | Type | Default |
|---|---|---|---|
| agents | generosity_score | real | 0.5 |
| agent_templates | perennial_learnings | jsonb | ’[]’ |
| markers | payload | jsonb | null |
| markers | transformation_depth | integer | 0 |
| markers | transformed_by | jsonb | ’[]’ |
| task_executions | input_source_task_ids | jsonb | null |
| workflow_runs | gift_chain_metrics | jsonb | null |
One migration file. All columns nullable or defaulted. No breaking changes.
9. Testing Strategy
Each package gets tests for its new features:
| Package | Tests |
|---|---|
| hypha | Gratitude signal fires on successful task with upstream lineage. No gratitude for tasks without upstream. Gift chain metrics computed correctly for linear, branching, and partial-consumption graphs. |
| immune | Generosity score increases on contribution, decreases on consumption. Hoarding signal fires below threshold. Overextension fires on high generosity + poor health. Gratitude receptor wires correctly. |
| stigmergy | Knowledge markers created with payload and 1800s half-life. transformMarker increments depth, rejects self-transforms, respects rate limits. Marker payload survives reinforcement. |
| genesis | Perennial learnings promoted after 3-agent confirmation. Pruning removes stale learnings. Spawn includes inherited_learnings in agent config. |
| agents | CapabilityMatcher scores agents with generosity weight. High-generosity agent scores above low-generosity agent (all else equal). |
| integration | End-to-end: workflow run produces gratitude signals → generosity scores update → capability matcher favors generous agents in next run. |
Not In Scope
- Gift Protocol as a formal subsystem
- Dual processing modes (erotic vs logos)
- Rigidity detection (Pound Problem)
- External source feeding
- Signal affect dimension
- Community Health Agent gift features (Sub-project B)
- Obadiah cross-persona flow (Sub-project C)