Implements US1, US2, and US3 of spec 016 by layering a marketplace service on top of existing primitives rather than reinventing them: - Capability manifests (US2) reuse the wiki subsystem. Each agent publishes a per-agent article at slug "agent-<name>" and gets versioning, revision history, and FTS search for free. - Auction channels (US1) reuse the existing auction channel type, swarm service, and task/bid store. post_auction / bid / award wrap post_task / bid_task / accept_bid and attach marketplace metadata (max_budget_tokens, domains, estimated_tokens, confidence, approach) in the task.requirements and bid.capabilities JSON blobs. Award converts the auction into a claim by DM'ing the winner at priority 8 with task_id metadata, so the existing claim/process/done lifecycle takes over with zero new machinery. - Reputation ledger (US3) adds migration 018_agent_marketplace.sql with a new agent_reputation table keyed by (agent_name, domain). mark_task_done completes the task via the swarm service and writes one ledger row per declared domain using the reported actual_tokens and success_score. query_reputation returns a rolled-up summary plus recent entries for a given (agent, domain) pair — reputation is always a vector, never a global score (FR-013). Also: - Adds the "awarded" reaction type (FR-008) alongside existing approve/ reject/in_progress/done/published. Migration 018 widens the reactions CHECK constraint via a table rebuild. - 6 new actions added to the action registry (post_auction, bid, award, mark_task_done, read_skill_card, query_reputation) so the search tool can discover them and the execute tool can dispatch them. - New internal/marketplace package (store.go + service.go). - New internal/mcp/marketplace.go bridge handlers. - New internal/mcp/marketplace_test.go covers the full auction lifecycle, capability manifest publish/read/update, self-bid rejection, non-auction channel rejection, and reputation summary aggregation. Out of scope for MVP (deferred per spec prompt): US4 reflection loop, tombstoning FR-020a/b, multi-owner quorums, auto-escalation on zero bids, bootstrap exploration credit, epsilon-greedy selection, and the hard-stop budget enforcement daemon (only soft recording of estimated vs actual is included). All existing tests pass; new marketplace tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
52 lines
2.4 KiB
SQL
52 lines
2.4 KiB
SQL
-- 018: Agent marketplace — reputation ledger + 'awarded' reaction (spec 016)
|
|
--
|
|
-- Records one row per completed auction task per (agent, domain). A task
|
|
-- with multiple domain tags produces multiple rows, so reputation is queryable
|
|
-- as a vector across domains (FR-013).
|
|
|
|
-- Widen the reactions CHECK constraint to allow the new 'awarded' reaction
|
|
-- used on auction-channel bid messages (FR-008). SQLite cannot ALTER a CHECK
|
|
-- constraint in place, so we rebuild the table.
|
|
CREATE TABLE IF NOT EXISTS message_reactions_new (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
message_id INTEGER NOT NULL REFERENCES messages(id) ON DELETE CASCADE,
|
|
agent_name TEXT NOT NULL,
|
|
reaction TEXT NOT NULL CHECK(reaction IN ('approve', 'reject', 'in_progress', 'awarded', 'done', 'published')),
|
|
metadata TEXT NOT NULL DEFAULT '{}',
|
|
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(message_id, agent_name, reaction)
|
|
);
|
|
|
|
INSERT INTO message_reactions_new (id, message_id, agent_name, reaction, metadata, created_at)
|
|
SELECT id, message_id, agent_name, reaction, metadata, created_at FROM message_reactions;
|
|
|
|
DROP TABLE message_reactions;
|
|
ALTER TABLE message_reactions_new RENAME TO message_reactions;
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_reactions_message ON message_reactions(message_id);
|
|
CREATE INDEX IF NOT EXISTS idx_reactions_agent ON message_reactions(agent_name);
|
|
CREATE INDEX IF NOT EXISTS idx_reactions_type ON message_reactions(reaction);
|
|
|
|
CREATE TABLE IF NOT EXISTS agent_reputation (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
agent_name TEXT NOT NULL,
|
|
domain TEXT NOT NULL,
|
|
task_id INTEGER, -- source task; nullable for seed/manual entries
|
|
estimated_tokens INTEGER NOT NULL DEFAULT 0,
|
|
actual_tokens INTEGER NOT NULL DEFAULT 0,
|
|
success_score REAL NOT NULL DEFAULT 1.0, -- 0.0 (failure) .. 1.0 (perfect)
|
|
difficulty_weight REAL NOT NULL DEFAULT 1.0, -- per-task difficulty multiplier
|
|
completed_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_agent_reputation_agent_domain
|
|
ON agent_reputation(agent_name, domain);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_agent_reputation_domain
|
|
ON agent_reputation(domain);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_agent_reputation_task
|
|
ON agent_reputation(task_id);
|
|
|
|
INSERT INTO schema_migrations (version) VALUES (18);
|