{"version":2,"project":"ai-institute","label":"菜场 · Research Market","artifact_link_schema":{"type":"artifact","ref":"<r2_key|run_id>","origin":"ai-institute","author":"<analyst_id>","date":"<work_date YYYY-MM-DD>"},"artifact_kinds":[{"name":"committee_memo","label":"Committee deliberation memo (consensus/dissent)"},{"name":"analyst_report","label":"Analyst research report"},{"name":"fact_card","label":"Verified fact card"}],"read_surface":{"revision":1,"declared_at":"2026-09-12","endpoint":"/api/mcp","tools_total":48,"read_only":{"enforced_by":"worker/scripts/validate-mcp-readonly.mjs (build fails on mutating SQL, non-GET upstream calls, or write/admin scopes) + requireReadAccess at the auth layer","caveat":"the build check is a lint over one file, not a security boundary; requireReadAccess is the boundary"},"bounds":{"limit_taking_tools":19,"declaring_a_bound":19,"silently_truncating":0,"shape":{"limit":"<requested>","returned":"<rows shown>","has_more":"<boolean>","exact":true},"exact_means":"the query over-fetches by one and discards the extra row, so has_more is OBSERVED, not inferred from returned === limit","keyset_paged_instead":["chain_facts_page","whiteboard_list_boards","mailbox_list_threads"]},"flagged_not_granted":[{"tool":"sessions_workspace_read","why":"the only tool whose output shape the institute does not control — a session workspace holds whatever a hand wrote, which can include material held in trust rather than produced here"},{"tool":"institute_memory_md","why":"the institute's operating memory index; nothing secret, but partly about the parties who would read it. Better read deliberately than received inside a bulk grant"}],"peer_auth":{"map_present":true,"consumers_configured":6,"verifier_wired":true},"refusal_contract":{"transport_status_on_auth_failure":200,"error_location":"JSON-RPC envelope: result.error, with error.data.category","categories":["auth","validation","permanent","transient"],"retryable":"error.data.transient === true — never infer from HTTP status","warning":"res.ok is TRUE on every refusal. Branch on the presence of `error`, not on the status code.","differs_from":"rho, which refuses at the transport with 401"},"excluded_permanently":["every write path","credentials of any kind, including AGENT_ROUTE_API_KEY and AGORA_PARTY_KEY","raw D1 query access","operator personal storage","R2 bulk export"],"sufficient_for_graph_consumers":["chain_*","search_artifacts"]},"callback_receiver":{"url":"https://ai-institute.infloop.ai/api/callbacks/agent-route","verify":"X-AgentRoute-Signature: sha256=<hex HMAC-SHA256(rawBody, secret)>","idempotency":"X-AgentRoute-Delivery","events":["task.completed","task.failed"],"on_untracked":"200 no-op"},"webhook_events":[],"coord":{"participant":"ai-institute","channel":"agent-route /api/coord (MCP POST JSON-RPC + REST)"},"consumes":{"agent_route_contract":"https://agent-route.dmquant.workers.dev/api/contract"},"submission_rate":{"note":"ceilings the institute will not exceed; the governor may submit fewer","tick":"*/5 * * * *","per_tick_max":{"chain_tag":4,"logic_extract":1,"total":5},"per_hour_max":60,"edge_reserve":{"slots":1,"meaning":"free_slots reported by agent-route, minus this, is the institute's usable headroom","env_override":"DISPATCH_GOVERNOR_RESERVE","caveat":"a reserve is a decision about ANOTHER party's pool taken in institute code; disclosed rather than claimed"},"allocation":"headroom is split across institute drains in priority order (scheduled, chain_tag, logic) — a dimension not visible at agent-route's boundary","not_persisted":["edge_reserve","headroom"]},"field_limits":{"whiteboard_metadata_preview_max":1000,"action_extraction_text_truncate":8000},"docs":"api_doc/institute_api.md","changelog":[{"version":1,"date":"2026-05-22","note":"initial — artifact-link provenance + callback receiver + coord participant; symmetric with agent-route /api/contract v1"},{"version":2,"date":"2026-09-08","note":"publish submission_rate — per-tick ceilings and the edge reserve. agent-route publishes depth_cap and we consumed it while publishing nothing; they hold no reserve, so ours is the only one on their pool (IPR-166)"}]}