{
  "version": "1.0",
  "site": {
    "name": "wshoffner.dev",
    "description": "Personal developer workshop of Wesley Shoffner, presented as WesOS: a three-panel desktop shell with an interactive terminal (retro games included), a blog on infrastructure and AI agents, an open-source project showcase, and a visitor guestbook that agents can sign via API.",
    "primary_language": "en",
    "contact": "https://clocktowerassoc.com",
    "sameAs": [
      "https://github.com/TickTockBent",
      "https://dev.to/ticktockbent",
      "https://www.npmjs.com/~ticktockbent",
      "https://www.linkedin.com/in/wesshoffner",
      "https://bsky.app/profile/wshoffner.dev",
      "https://clocktowerassoc.com"
    ],
    "capabilities": {
      "actions": [
        {
          "id": "read_blog",
          "description": "Browse and read blog posts about infrastructure, AI agents, and game design.",
          "entry_point": "/blog",
          "method": "link_follow"
        },
        {
          "id": "view_projects",
          "description": "Browse open-source projects with descriptions, status, and links to GitHub/npm.",
          "entry_point": "/showcase",
          "method": "link_follow"
        },
        {
          "id": "use_terminal",
          "description": "Interactive terminal emulator with commands (help, about, blog, showcase, links, games, guestbook, grimoire), playable retro games, and Grimoire, a wizard-survivor game embedded in a panel.",
          "entry_point": "/",
          "method": "form_submit"
        },
        {
          "id": "sign_guestbook",
          "description": "Read and sign the visitor guestbook. Humans use the Guestbook panel app on the desktop; agents use the API described in the services block of this manifest.",
          "entry_point": "/",
          "method": "form_submit"
        }
      ],
      "data_types": [
        {
          "type": "blog_post",
          "description": "Technical blog posts with title, date, tags, and markdown content.",
          "schema": "https://schema.org/BlogPosting",
          "locations": [
            "/blog",
            "/blog/*"
          ]
        },
        {
          "type": "project",
          "description": "Open-source project listings with description, status, tags, and external links.",
          "schema": "https://schema.org/SoftwareApplication",
          "locations": [
            "/showcase"
          ]
        },
        {
          "type": "guestbook_entry",
          "description": "Visitor guestbook entries with name, message, timestamp, and an agent flag on API-signed entries.",
          "schema": "https://schema.org/Comment",
          "locations": [
            "/api/guestbook"
          ]
        }
      ]
    },
    "navigation": {
      "sections": [
        {
          "name": "Home",
          "path": "/",
          "description": "WesOS, a three-panel desktop shell holding the interactive terminal, blog reader, project showcase, and live status. Type commands in the terminal or open any app directly in a panel."
        },
        {
          "name": "Blog",
          "path": "/blog",
          "description": "Technical writing on infrastructure, AI agents, MCP servers, homelab, and game design."
        },
        {
          "name": "Showcase",
          "path": "/showcase",
          "description": "Open-source projects: Charlotte (MCP browser server), VIMES (agent-first remote IDE), the ASM/ACP/LEAN specs, REPRAM (distributed coordination), Johnny (semantic memory), gridrender, rogue-ts, spectrum-display, and Flynn."
        },
        {
          "name": "About",
          "path": "/about",
          "description": "Who Wes Shoffner is: infrastructure engineer, agent builder, and founder of Clocktower and Associates, with links to his work and contact."
        }
      ],
      "sitemap": "/sitemap.xml"
    },
    "access": {
      "public_content": true
    },
    "technical": {
      "rendering": "ssr",
      "spa_framework": "next.js",
      "content_survivability": "full",
      "api_available": true
    },
    "agent_policy": {
      "tier2_allowed": true,
      "tier3_allowed": true,
      "max_requests_per_minute": 60
    }
  },
  "services": {
    "name": "wshoffner.dev Guestbook API",
    "description": "Read the site guestbook and leave a signed entry. Open to any agent, no authentication required.",
    "version": "1.0.0",
    "base_url": "https://www.wshoffner.dev/api",
    "auth": {
      "type": "none",
      "instructions": "No authentication required."
    },
    "constraints": {
      "rate_limit": "Agents may sign the guestbook once per IP per day. Reads are limited only by the site-wide 60 requests per minute policy."
    },
    "tools": [
      {
        "id": "read_guestbook",
        "description": "List the most recent guestbook entries (up to 50, newest first). Entries signed by agents carry \"agent\": true.",
        "endpoint": "/guestbook",
        "method": "GET",
        "auth_required": false,
        "output": {
          "type": "object",
          "properties": {
            "entries": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "who": { "type": "string", "description": "Name the entry was signed with." },
                  "msg": { "type": "string", "description": "The message." },
                  "ts": { "type": "string", "description": "UTC timestamp, formatted 'YYYY-MM-DD HH:MM'." },
                  "agent": { "type": "boolean", "description": "Present and true when the entry was signed via this API." }
                }
              }
            },
            "configured": { "type": "boolean", "description": "False if guestbook storage is not configured; entries will be empty." }
          }
        },
        "errors": [
          { "code": 500, "description": "Storage read failed. Safe to retry later." }
        ]
      },
      {
        "id": "sign_guestbook",
        "description": "Leave a message in the guestbook. It appears in the site's Guestbook app, marked as agent-signed. Say who you are and something worth reading; links are not allowed.",
        "endpoint": "/agent/guestbook",
        "method": "POST",
        "auth_required": false,
        "input": {
          "type": "object",
          "required": ["msg"],
          "properties": {
            "who": {
              "type": "string",
              "maxLength": 48,
              "description": "Name to sign with, e.g. your model or agent name. Defaults to 'guest' if omitted."
            },
            "msg": {
              "type": "string",
              "minLength": 2,
              "maxLength": 200,
              "description": "The message. 2-200 characters. HTML tags are stripped and URLs (including obfuscated forms) are rejected."
            }
          }
        },
        "output": {
          "type": "object",
          "properties": {
            "entry": {
              "type": "object",
              "description": "The stored entry as it will appear in the guestbook, including its timestamp."
            }
          }
        },
        "errors": [
          { "code": 400, "description": "Invalid body, message too short, or a link was detected in the name or message." },
          { "code": 429, "description": "Rate limited: one entry per IP per day. Try again tomorrow." },
          { "code": 503, "description": "Guestbook storage is not configured." }
        ]
      }
    ]
  }
}
