{
  "schema": "snappy-card/1",
  "skill": "snappy-specwatch",
  "tier": "public",
  "origin_tier": "base",
  "purpose": "Half of every hand's contract belongs to somebody else. This hand reads the",
  "verbs": [
    {
      "name": "check",
      "args": [
        "skill?"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-specwatch/api.ts check"
    },
    {
      "name": "drift",
      "args": [
        "skill?"
      ],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-specwatch/api.ts drift"
    },
    {
      "name": "fix",
      "args": [
        "skill"
      ],
      "effect": "write-reversible",
      "firstCall": "npx tsx ~/.claude/skills/snappy-specwatch/api.ts fix <skill>"
    },
    {
      "name": "schedule",
      "args": [],
      "effect": "read",
      "firstCall": "npx tsx ~/.claude/skills/snappy-specwatch/api.ts schedule"
    }
  ],
  "faces": [],
  "agents": [],
  "uses": [],
  "used_by": [
    "snappy-runner"
  ],
  "checks": {
    "pass": 30,
    "fail": 5,
    "defer": 26,
    "line": "30 of 35 checks pass",
    "failing": [
      {
        "id": 4,
        "rule": "Near-neighbour descriptions cross-reference each other",
        "says": "near neighbours not named: snappy-ai-models, snappy-artifact-loop, snappy-blog, snappy-calendar, snappy-content"
      },
      {
        "id": 33,
        "rule": "Refusal codes form one tested closed table",
        "says": "4 refusal code(s); uncovered tests=[unknown_verb, missing_argument, missing_credential, upstream_error]"
      },
      {
        "id": 40,
        "rule": "Metadata, skill body, and resources follow three-level budgets",
        "says": "metadata ~183 tokens; body ~1172 tokens"
      },
      {
        "id": 55,
        "rule": "Eval scenarios are multi-call with ground truth",
        "says": "eval manifest missing"
      },
      {
        "id": 57,
        "rule": "Eval manifest contains a disjoint holdout",
        "says": "0 disjoint holdout scenario(s)"
      }
    ]
  },
  "coverage": null,
  "spec": null,
  "evals": null,
  "files": [
    "AGENTS.md",
    "SKILL.md",
    "api.ts"
  ],
  "total_size": 24808,
  "checksum": "sha256:e73709a6d4a11361cb51fb9b3fdb327091ce7b26191526c02b95b2261d561ca5",
  "built_at": "2026-09-09T22:11:03.472Z",
  "openapi": {
    "openapi": "3.1.0",
    "info": {
      "title": "snappy-specwatch",
      "version": "0.0.0",
      "description": "Watches the vendor documents the hands sit on -- OpenAPI, Swagger and Google Discovery -- reads each pinned spec once a day with no credential, writes what it found into the collection's spec corpus, and for a hand that has fallen behind a capability the vendor now publishes starts a fix run through the same road Make it better takes. Use when a vendor ships something a skill does not offer yet, when a verb's vendor operation may have been removed, or to see which hands pin a spec at all. NOT the grader itself (see snappy-tool-design, which owns rule 61). NOT the scaffolder (see snappy-skill). Triggers on: snappy-specwatch, spec drift, vendor spec, openapi drift, the vendor added, check the specs, gpt image, api changed."
    },
    "x-snappy-transport": "cli",
    "servers": [
      {
        "url": "npx tsx ~/.claude/skills/snappy-specwatch/api.ts",
        "description": "The hand itself. Every path is a verb word, every query or body key an argument."
      }
    ],
    "paths": {
      "/check": {
        "post": {
          "operationId": "snappy_specwatch_check",
          "summary": "snappy-specwatch check",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": true,
            "openWorldHint": true
          },
          "requestBody": {
            "required": false,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "skill": {
                      "type": "string",
                      "description": "One snappy-* hand to re-read; omit for every hand that pins a spec",
                      "x-snappy-position": 0
                    },
                    "fix": {
                      "x-snappy-flag": "--fix"
                    },
                    "json": {
                      "x-snappy-flag": "--json"
                    },
                    "token-file": {
                      "x-snappy-flag": "--token-file"
                    }
                  }
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/drift": {
        "get": {
          "operationId": "snappy_specwatch_drift",
          "summary": "snappy-specwatch drift",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": false
          },
          "parameters": [
            {
              "name": "skill",
              "in": "query",
              "required": false,
              "schema": {
                "type": "string",
                "description": "One snappy-* hand whose last reading is reported; omit for every hand in the corpus",
                "x-snappy-position": 0
              }
            },
            {
              "name": "json",
              "in": "query",
              "required": false,
              "schema": {
                "x-snappy-flag": "--json"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/fix": {
        "post": {
          "operationId": "snappy_specwatch_fix",
          "summary": "snappy-specwatch fix",
          "x-snappy-effect": "write-reversible",
          "x-snappy-annotations": {
            "readOnlyHint": false,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": true
          },
          "requestBody": {
            "required": true,
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "skill": {
                      "type": "string",
                      "description": "The hand whose measured drift becomes the ask of a fix run",
                      "x-snappy-position": 0
                    },
                    "token-file": {
                      "x-snappy-flag": "--token-file"
                    }
                  },
                  "required": [
                    "skill"
                  ]
                }
              }
            }
          },
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      },
      "/schedule": {
        "get": {
          "operationId": "snappy_specwatch_schedule",
          "summary": "snappy-specwatch schedule",
          "x-snappy-effect": "read",
          "x-snappy-annotations": {
            "readOnlyHint": true,
            "destructiveHint": false,
            "idempotentHint": false,
            "openWorldHint": false
          },
          "parameters": [
            {
              "name": "hour",
              "in": "query",
              "required": false,
              "schema": {
                "type": "integer",
                "description": "Local hour the daily read would run",
                "default": 7,
                "maximum": 23,
                "x-snappy-flag": "--hour"
              }
            }
          ],
          "responses": {
            "200": {
              "description": "The verb's own answer, as printed by `--json`."
            }
          }
        }
      }
    },
    "components": {
      "schemas": {
        "SnappyRefusal": {
          "type": "object",
          "required": [
            "outcome",
            "code",
            "message"
          ],
          "properties": {
            "outcome": {
              "type": "string",
              "const": "refused"
            },
            "code": {
              "type": "string",
              "description": "A row of the closed refusal table."
            },
            "message": {
              "type": "string"
            },
            "fix": {
              "type": "string"
            }
          }
        }
      }
    },
    "x-snappy-vendor-spec": {
      "kind": "none",
      "reason": "This hand calls no vendor API; its only network calls are the public spec documents other hands pin, and the local runner (whose address the registry holds)."
    }
  }
}