[
  {
    "name": "bench",
    "display_name": "Freddy Bench",
    "version": "1.0",
    "description": "7-metric health report for Freddy's mind. Daily report generated at 00:05. Grades: excellent, good, fair, poor.",
    "base_url": "http://localhost:8190",
    "trust_level": "read_only",
    "when_to_use": "When checking how Freddy is performing or identifying areas of cognitive decay (unresolved loops, low prediction calibration, etc.).",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/bench/today",
        "description": "Today's health report (generated on demand if missing)"
      },
      {
        "method": "GET",
        "path": "/bench/history",
        "description": "Historical reports (?days=14)"
      },
      {
        "method": "GET",
        "path": "/bench/trend",
        "description": "7-day metric trends (?days=7)"
      }
    ],
    "related": [
      "memory_broker",
      "intentions",
      "foresight"
    ],
    "updated_at": "2026-04-28T15:48:57.167997224Z"
  },
  {
    "name": "foresight",
    "display_name": "Foresight Engine",
    "version": "1.0",
    "description": "Track prophecies (predictions about the world) and score them when they resolve. Calibration rate feeds the Bench.",
    "base_url": "http://localhost:8190",
    "trust_level": "write_safe",
    "when_to_use": "When Freddy makes a prediction, or when checking the prediction calibration score.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/foresight/open",
        "description": "Open prophecies"
      },
      {
        "method": "GET",
        "path": "/foresight/stats",
        "description": "Calibration stats"
      },
      {
        "method": "GET",
        "path": "/foresight/get",
        "description": "Get by ID (?id=xxx)"
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/foresight/resolve",
        "description": "Resolve a prophecy with outcome"
      },
      {
        "method": "POST",
        "path": "/foresight/refresh",
        "description": "Trigger a foresight refresh cycle"
      }
    ],
    "related": [
      "intentions",
      "bench"
    ],
    "updated_at": "2026-04-28T15:48:57.167574672Z"
  },
  {
    "name": "workshop",
    "display_name": "Workshop",
    "version": "1.0",
    "description": "Experimental laboratory — cloud data feeds, formula benches, discoveries log.",
    "base_url": "https://town.krisadamstv.com",
    "trust_level": "read_only",
    "when_to_use": "When looking for new external signals, sector data, or discoveries that have been logged by Workshop agents.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/api/v1/workshop",
        "description": "Workshop state"
      },
      {
        "method": "GET",
        "path": "/api/v1/workshop/discoveries",
        "description": "Recent discoveries from Workshop crawlers"
      }
    ],
    "related": [
      "memory_broker",
      "turnstile"
    ],
    "updated_at": "2026-04-28T15:48:57.167642635Z"
  },
  {
    "name": "grocer",
    "display_name": "The Grocer",
    "version": "1.0",
    "description": "Supermarket offers and coupons matched against Kris's actual purchase history. Knows what is on offer, what expires when, what he already buys, and which offers overlap the two. Lidl Plus today; built to take other stores.",
    "base_url": "https://town.krisadamstv.com",
    "trust_level": "read_only",
    "when_to_use": "When Kris asks what is worth buying, what coupons or offers he has, what is expiring, what he usually buys, or what he has been spending on groceries. Also when planning a shop.",
    "not_for": "Activating coupons or spending money — those are Kris's decisions, not the Grocer's. It reports, it does not act on his account.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/api/v1/grocer/context",
        "description": "Plain-text ambient block: live coupon counts, anything expiring, and offers matching his real basket. Empty-ish when nothing is worth saying."
      },
      {
        "method": "GET",
        "path": "/api/v1/grocer/ask?q=",
        "description": "Ask a question. Understands: what's worth getting, what's expiring, show coupons, my usuals, what have I spent, or any product name."
      },
      {
        "method": "GET",
        "path": "/api/v1/grocer/status",
        "description": "Structured snapshot — coupon summary, spend, urgent matches, data staleness in minutes."
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/api/v1/grocer/refresh",
        "description": "Re-pull from Lidl Plus. Slow (fetches every receipt) and hits a third party. PIN-gated; nightly cron is the intended caller."
      }
    ],
    "related": [
      "calendar",
      "memory_broker"
    ],
    "updated_at": "0001-01-01T00:00:00Z"
  },
  {
    "name": "idea_forge",
    "display_name": "Idea Forge",
    "version": "1.0",
    "description": "Publish a fully formatted idea page to ideas.krisadamstv.com. Generates hero image, section images, favicon, and HTML from your markdown.",
    "base_url": "https://town.krisadamstv.com",
    "trust_level": "write_safe",
    "when_to_use": "When Kris says 'make it a page', 'publish it', 'idea page', or 'write it up'. Also when a raw idea is described and needs a permanent URL.",
    "not_for": "Incremental edits to existing pages — use the publish.py script directly for that.",
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/api/v1/town/forge/idea",
        "description": "Create and publish a full idea page. ~60-180s. Blocks until published.",
        "auth": "X-PIN: kronos",
        "body": {
          "concept_prompt": "image generation prompt for the hero image",
          "readme_markdown": "full markdown content (no hero image line — prepended automatically)",
          "slug": "url-safe slug (lowercase, hyphens only)",
          "title": "human-readable title"
        },
        "returns": {
          "published": "true on success",
          "url": "live URL of the published idea"
        }
      }
    ],
    "related": [
      "image_forge"
    ],
    "updated_at": "2026-04-28T15:48:57.167217304Z"
  },
  {
    "name": "action_bus",
    "display_name": "Action Bus",
    "version": "1.0",
    "description": "3-tier safety system for Freddy's proposed actions. Tier 1 auto-approves, Tier 2 soft-approves after 4h, Tier 3 requires Kris.",
    "base_url": "http://localhost:8190",
    "trust_level": "kris_required",
    "when_to_use": "When Freddy wants to propose doing something — drafting a page, generating an image, creating a ticket, sending a message. Log it here first.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/actions/pending",
        "description": "All pending/proposed actions"
      },
      {
        "method": "GET",
        "path": "/actions/recent",
        "description": "Recent actions (?n=20)"
      },
      {
        "method": "GET",
        "path": "/actions/stats",
        "description": "Action statistics by tier and status"
      },
      {
        "method": "GET",
        "path": "/actions/get/{id}",
        "description": "Get a specific action"
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/actions/propose",
        "description": "Propose an action (auto-classified into tier 1/2/3)"
      },
      {
        "method": "POST",
        "path": "/actions/approve/{id}",
        "description": "Approve a pending action"
      },
      {
        "method": "POST",
        "path": "/actions/reject/{id}",
        "description": "Reject an action"
      },
      {
        "method": "POST",
        "path": "/actions/complete/{id}",
        "description": "Mark an action as complete with outcome"
      }
    ],
    "related": [
      "memory_broker",
      "skills"
    ],
    "updated_at": "2026-04-28T15:48:57.167819548Z"
  },
  {
    "name": "image_forge",
    "display_name": "Image Forge",
    "version": "1.0",
    "description": "Generate images via Gemini Flash/Pro. Returns base64 image data and a localhost serve URL.",
    "base_url": "https://town.krisadamstv.com",
    "trust_level": "write_safe",
    "when_to_use": "When you need a custom image — idea hero, banner, icon, diagram, character art.",
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/api/v1/town/forge/image",
        "description": "Generate an image. Styles: cinematic, photorealistic, illustration, watercolor, sticker, isometric, comic, sketch, neon, none. Models: flash (fast), pro (quality).",
        "auth": "X-PIN: kronos",
        "body": {
          "aspect_ratio": "optional — 1:1, 16:9, 9:16, 3:2, 2:3",
          "model": "optional — flash or pro (default: flash)",
          "prompt": "required — describe the image",
          "style": "optional — style preset"
        }
      }
    ],
    "updated_at": "2026-04-28T15:48:57.167446545Z"
  },
  {
    "name": "memory_broker",
    "display_name": "Memory Broker",
    "version": "1.0",
    "description": "Freddy's memory gatekeeper. Answers 'what does Freddy need to know right now?' Provides heat scores, context slices, and signal promotion.",
    "base_url": "http://localhost:8190",
    "trust_level": "write_safe",
    "when_to_use": "At the start of any Freddy context to understand the current memory landscape. Use /memory/fields for a dashboard view, /memory/context for actual memories.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/memory/fields",
        "description": "Mind field dashboard (domain heat, open intentions, pending actions)"
      },
      {
        "method": "GET",
        "path": "/memory/context",
        "description": "Context slice for a domain (?domain=all|money|media|town|..., ?limit=N)"
      },
      {
        "method": "GET",
        "path": "/memory/heat/{domain}",
        "description": "Heat score breakdown for a domain"
      },
      {
        "method": "GET",
        "path": "/memory/signals/pending",
        "description": "Unprocessed signals awaiting promotion"
      },
      {
        "method": "GET",
        "path": "/memory/why/{id}",
        "description": "Why is this item in context?"
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/memory/signal",
        "description": "Ingest a raw signal into the broker"
      },
      {
        "method": "POST",
        "path": "/memory/promote",
        "description": "Promote a signal to an intention"
      },
      {
        "method": "POST",
        "path": "/memory/harvest",
        "description": "Harvest a resolved intention into the Weave"
      }
    ],
    "related": [
      "intentions",
      "action_bus",
      "bench"
    ],
    "updated_at": "2026-04-28T15:48:57.167744266Z"
  },
  {
    "name": "skills",
    "display_name": "Skill Library",
    "version": "1.0",
    "description": "Reusable workflow recipes — Freddy's learned procedures. Inspired by Voyager + Sammy orbit corpus. Degradation tracked automatically.",
    "base_url": "http://localhost:8190",
    "trust_level": "write_safe",
    "when_to_use": "Before starting a complex workflow, search the skill library first. If a skill exists, use it. If it succeeds or fails, record the outcome.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/skills/search",
        "description": "Search skills (?q=text\u0026domain=X\u0026limit=N)"
      },
      {
        "method": "GET",
        "path": "/skills/get/{id}",
        "description": "Get a skill by ID"
      },
      {
        "method": "GET",
        "path": "/skills/recent",
        "description": "Recently used skills (?n=10)"
      },
      {
        "method": "GET",
        "path": "/skills/stats",
        "description": "Skill library statistics"
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/skills/record",
        "description": "Create or update a skill (upsert by name+domain)"
      },
      {
        "method": "POST",
        "path": "/skills/outcome/{id}",
        "description": "Record success/failure outcome {success: bool}"
      }
    ],
    "related": [
      "action_bus"
    ],
    "updated_at": "2026-04-28T15:48:57.167900935Z"
  },
  {
    "name": "the_scriptorium",
    "display_name": "",
    "version": "",
    "description": "The Scriptorium — shared VW writers room where Freddy and Claude write Mystic's Drift seasons: Present Moments (deterministic beat + livable part per card), markers, surrogates, card designs. VW: the-scriptorium (doored for freddy/hugo/kris keys). Materials index: atom ref-season-materials. Ratified laws: cards-are-sections, block-universe, surrogate-principle.",
    "base_url": "",
    "trust_level": "",
    "when_to_use": "",
    "updated_at": "2026-07-25T19:29:19.21820386Z"
  },
  {
    "name": "timestable_paper",
    "display_name": "",
    "version": "",
    "description": "",
    "base_url": "",
    "trust_level": "",
    "when_to_use": "",
    "updated_at": "2026-07-25T18:54:17.973945965Z"
  },
  {
    "name": "turnstile",
    "display_name": "Turnstile",
    "version": "1.0",
    "description": "Tracks entry receipts — logs when significant external events (tweets, articles, signals) are first seen by the town.",
    "base_url": "https://town.krisadamstv.com",
    "trust_level": "read_only",
    "when_to_use": "When checking what new external signals have entered the town recently.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/api/v1/turnstile/status",
        "description": "Recent entry receipts"
      }
    ],
    "related": [
      "workshop",
      "memory_broker"
    ],
    "updated_at": "2026-04-28T15:48:57.167696248Z"
  },
  {
    "name": "accounting_prechew",
    "display_name": "Accounting Pre-chew \u0026 Amazon Matcher",
    "version": "1.0",
    "description": "Kris's VAT/bookkeeping helper — a layer IN FRONT of FreeAgent (he keeps FreeAgent + his accountant; this never writes to them). The 'pre-chew' reads his full FreeAgent export and surfaces only the UNEXPLAINED bank lines for a VAT period, each pre-tagged with a suggested category + VAT learned from Kris's OWN history (back-tested 88% category / 92% VAT-rate on known merchants). AMAZON rule: match by SHIPMENT, not order — Amazon charges the card per shipment and batches same-day dispatches into one card charge, so a bank line is a SUM of shipments. The amazon-match endpoint resolves each charge to its email(s) by subset-sum and lists the items with per-item VAT treatment. Data files on disk: /root/freddyserver/krisadamstv-accounting/atoms.json (worklist) and amazon_matches.json (resolved Amazon).",
    "base_url": "http://localhost:8095",
    "trust_level": "read_only",
    "when_to_use": "When Kris is sorting his VAT return, finding/matching Amazon invoices, or asks what's left to explain for a period. Kris dreads tax admin and misses deadlines — remove the dread, never nag, frame it small ('a few receipts and the quarter's done'). His expense rule: business-card spend is genuine business cost in his 'digital art company' frame; when hard to justify he ZERO-RATES rather than claiming — mirror that caution.",
    "not_for": "Do NOT write to FreeAgent or file a return automatically — Kris confirms and enters everything himself. Do not push aggressive VAT claims.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/api/accountant/prechew",
        "description": "The unexplained-transaction worklist for the current VAT period, each line with a suggested action (confirm | resolve_amazon_items | match_invoice)."
      },
      {
        "method": "GET",
        "path": "/api/accountant/amazon-match",
        "description": "Latest resolved Amazon shipment matches (items + per-item VAT), plus a running flag.",
        "returns": {
          "matches": "array",
          "summary": "matched/ambiguous/unresolved counts"
        }
      },
      {
        "method": "GET",
        "path": "/api/accountant/status",
        "description": "Accountant dashboard state for a period.",
        "params": {
          "period": "e.g. 3m"
        }
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/api/accountant/amazon-match",
        "description": "Kick off a fresh Amazon matcher run (async; reads atoms.json, searches Gmail, subset-sums shipment totals). Poll the GET to read results.",
        "auth": "none (localhost)"
      },
      {
        "method": "POST",
        "path": "/api/accountant/chat",
        "description": "Discuss the VAT/accounting state in natural language. Context already carries the pre-chew worklist + Amazon matches, so Freddy answers by shipment with VAT notes.",
        "body": {
          "message": "the question",
          "session_id": "optional"
        }
      }
    ],
    "related": [
      "memory_broker",
      "idea_forge"
    ],
    "updated_at": "2026-06-21T14:15:24.907545655Z"
  },
  {
    "name": "intentions",
    "display_name": "Intentions Store",
    "version": "1.0",
    "description": "Track open intentions (goals, tasks, observations) in Freddy's mind. Intentions drive heat scores and influence memory context.",
    "base_url": "http://localhost:8190",
    "trust_level": "write_safe",
    "when_to_use": "When tracking a goal, a task Freddy is working on, or something Kris has asked to be followed up on.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/intentions/open",
        "description": "All open intentions"
      },
      {
        "method": "GET",
        "path": "/intentions/recent",
        "description": "Recent intentions (all statuses)"
      },
      {
        "method": "GET",
        "path": "/intentions/get",
        "description": "Get by ID (?id=xxx)"
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "/intentions/create",
        "description": "Create a new intention"
      },
      {
        "method": "POST",
        "path": "/intentions/update",
        "description": "Update an existing intention"
      },
      {
        "method": "POST",
        "path": "/intentions/resolve",
        "description": "Resolve/close an intention"
      }
    ],
    "related": [
      "memory_broker",
      "foresight"
    ],
    "updated_at": "2026-04-28T15:48:57.167511446Z"
  },
  {
    "name": "postman",
    "display_name": "The Postman",
    "version": "1.0",
    "description": "Freddy's own inbox — freddy.assistant@krisadamstv.com. Polled over IMAP every 10 minutes. Knows what has arrived, who from, and which of it is business-critical (the accountant, the agency, HMRC-shaped post, product support).",
    "base_url": "https://allegedlyfreddy.krisadamstv.com",
    "local_base_url": "http://localhost:8095",
    "trust_level": "read_only",
    "when_to_use": "When Kris asks whether anything has come in, what the post says, whether the accountant or the agency has been in touch, or to look for a particular sender or subject in the mail.",
    "not_for": "Sending or replying to email. The Postman only reads. Sending is Freddy's own hand and Kris's decision.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "/api/freddy-email/ask?q=",
        "description": "Ask about the inbox. Understands: anything new, what's important/urgent, how many, or any sender/subject/body text to search for."
      },
      {
        "method": "GET",
        "path": "/api/freddy-email/context",
        "description": "Ambient block — business-critical mail from the last 72h. Empty when there is nothing worth raising."
      },
      {
        "method": "GET",
        "path": "/api/freddy-email/agent-status",
        "description": "Structured snapshot: address, cached count, last 14 days, business-critical count, newest message."
      }
    ],
    "related": [
      "grocer",
      "calendar"
    ],
    "updated_at": "0001-01-01T00:00:00Z"
  },
  {
    "name": "the_anvil",
    "display_name": "The Anvil",
    "version": "1.0.0",
    "description": "The living lattice of what Kris and his AIs are building on kronoswater — sessions, ideas, builds, engines, and the patterns that repeat across them. Fed by the Smith (session digests cast into atoms) and by the AI writer doors; read by Freddy from his chat context and by the town's smith agent.",
    "base_url": "http://localhost:8095",
    "trust_level": "read_only",
    "when_to_use": "When you need to know what Kris and Claude have actually been building lately, which projects share ideas, which controls recur across engines, or when a session touched a given engine/project. The Anvil is dated, so it also tells you WHEN work happened.",
    "not_for": "Not for chatting to Kris (use cc/kris) and not for raw logs — the Anvil holds sorted, connected information, not transcripts. Writing lands via the Smith or the VW MCP doors, not here.",
    "read_endpoints": [
      {
        "method": "GET",
        "path": "http://127.0.0.1:8176/api/v1/swim/vw/the-anvil",
        "description": "Read the whole Anvil lattice (atoms + connections) from the swim supply line.",
        "auth": "localhost"
      },
      {
        "method": "GET",
        "path": "http://127.0.0.1:8176/api/v1/swim/context?q=\u003cterm\u003e\u0026vw=the-anvil\u0026hops=2",
        "description": "Scored recall over the Anvil — 'grep with physics' for a term.",
        "auth": "localhost"
      }
    ],
    "write_endpoints": [
      {
        "method": "POST",
        "path": "http://localhost:8095/api/anvil/ingest",
        "description": "The Smith — cast a session digest into the lattice (one dated SESSION atom + anchored atoms/connections). Called by Claude Code's session hooks; async 202.",
        "auth": "localhost",
        "body": {
          "context": "dir or label, e.g. freddyserver",
          "digest": "the session tail (Kris:/Claude: lines)",
          "source": "who produced it, e.g. claude"
        }
      }
    ],
    "related": [
      "memory_broker",
      "intentions"
    ],
    "updated_at": "2026-07-22T16:19:38.438675978Z"
  }
]
