{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$ref": "#/definitions/HookManifest",
  "definitions": {
    "ExtensionVisibility": {
      "type": "string",
      "enum": ["public", "private"],
      "title": "Extension Visibility",
      "description": "Intended whole-Extension Registry visibility. Establishes new Extensions and must match established Extensions."
    },
    "PublishOptions": {
      "type": "object",
      "properties": {
        "visibility": {
          "anyOf": [{ "$ref": "#/definitions/ExtensionVisibility" }, { "type": "null" }]
        },
        "ignore": {
          "anyOf": [
            {
              "type": "array",
              "uniqueItems": true,
              "description": "Registry-only archive exclusions matched against package-relative POSIX paths. Matching files are omitted only from published archives; local, Git, workspace, import, fork, and agent projection behavior is unchanged. `*` is the only wildcard, is case-sensitive, and spans `/`. An explicit empty array records a reviewed publish-all decision.",
              "examples": [[], ["evals/*"]],
              "items": { "type": "string", "minLength": 1 }
            },
            { "type": "null" }
          ]
        }
      },
      "additionalProperties": false,
      "title": "Publish Options",
      "description": "Publication policy and archive options for this extension."
    },
    "Handle": {
      "type": "string",
      "pattern": "^@[a-z0-9_](?:[a-z0-9_-]*[a-z0-9_])?$",
      "title": "Handle",
      "description": "A unique username or organization name starting with @, like @my-org.",
      "examples": ["@my-org", "@username"]
    },
    "Version": {
      "type": "string",
      "pattern": "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$",
      "title": "Version",
      "description": "A semver version like 1.0.0. Ranges are not allowed here.",
      "examples": ["1.0.0", "2.3.1", "0.1.0-beta.1"]
    },
    "Repository": {
      "anyOf": [
        {
          "type": "string",
          "examples": ["https://github.com/acme/code-review", "github:acme/code-review"],
          "format": "uri-reference"
        },
        {
          "type": "object",
          "properties": {
            "type": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "description": "Version control system (e.g., `git`).",
                  "examples": ["git"]
                },
                { "type": "null" }
              ]
            },
            "url": {
              "type": "string",
              "allOf": [
                {
                  "minLength": 1,
                  "description": "Repository URL.",
                  "examples": ["https://github.com/acme/code-review"],
                  "format": "uri"
                }
              ]
            },
            "directory": {
              "anyOf": [
                {
                  "type": "string",
                  "minLength": 1,
                  "description": "Subdirectory within the repository, for monorepo publishers.",
                  "examples": ["packages/code-review"]
                },
                { "type": "null" }
              ]
            }
          },
          "required": ["url"],
          "additionalProperties": false
        }
      ],
      "title": "Repository",
      "description": "Source repository for this extension. Accepts a URL string (or `host:owner/repo` shorthand) or an object with `type`, `url`, and optional `directory`."
    },
    "Bugs": {
      "anyOf": [
        {
          "type": "string",
          "examples": ["https://github.com/acme/code-review/issues"],
          "format": "uri"
        },
        {
          "type": "object",
          "properties": {
            "url": {
              "anyOf": [
                {
                  "type": "string",
                  "allOf": [
                    {
                      "minLength": 1,
                      "description": "Issue tracker URL.",
                      "examples": ["https://github.com/acme/code-review/issues"],
                      "format": "uri"
                    }
                  ]
                },
                { "type": "null" }
              ]
            },
            "email": {
              "anyOf": [
                {
                  "type": "string",
                  "allOf": [
                    {
                      "minLength": 1,
                      "description": "Contact email for bug reports.",
                      "examples": ["bugs@acme.dev"],
                      "format": "email"
                    }
                  ]
                },
                { "type": "null" }
              ]
            }
          },
          "additionalProperties": false
        }
      ],
      "title": "Bugs",
      "description": "Where to report bugs against this extension. Accepts a URL string or an object with optional `url` and `email`."
    },
    "Author": {
      "type": "object",
      "properties": {
        "name": { "type": "string" },
        "email": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
        "url": { "anyOf": [{ "type": "string" }, { "type": "null" }] }
      },
      "required": ["name"],
      "additionalProperties": false,
      "title": "Author",
      "description": "A person credited as a creator or maintainer of this extension."
    },
    "PackageIdentityPurl": {
      "type": "string",
      "minLength": 1,
      "pattern": "^[Pp][Kk][Gg]:[a-zA-Z][a-zA-Z0-9.+-]*\\/.+$",
      "title": "Package Identity Purl",
      "description": "A Package URL (purl) identity for a companion package. Companion package purls are identities, not pins: omit the purl @version segment and put compatibility constraints in versionRange.",
      "examples": ["pkg:npm/react", "pkg:pypi/requests", "pkg:cargo/serde"]
    },
    "VersRangeEncoded": {
      "type": "string",
      "minLength": 1,
      "examples": ["vers:npm/>=18.0.0|<19.0.0", "vers:pypi/>=2.31.0", "vers:cargo/>=1.0.0"]
    },
    "CompanionPackage": {
      "type": "object",
      "properties": {
        "purl": { "$ref": "#/definitions/PackageIdentityPurl" },
        "versionRange": {
          "anyOf": [{ "$ref": "#/definitions/VersRangeEncoded" }, { "type": "null" }]
        }
      },
      "required": ["purl"],
      "additionalProperties": false,
      "title": "Companion Package",
      "description": "A companion package purl identity with an optional VERS compatibility range."
    },
    "PackSpec": {
      "type": "string",
      "minLength": 1,
      "pattern": "^(@[a-z0-9_](?:[a-z0-9_-]*[a-z0-9_])?)\\/packs\\/([a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?)(?:@.+)?$",
      "title": "Pack Spec",
      "description": "Pack reference with an optional version constraint suffix.",
      "examples": ["@acme/packs/typescript", "@acme/packs/typescript@^1.0.0"]
    },
    "ExtensionName": {
      "type": "string",
      "minLength": 1,
      "pattern": "^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$",
      "title": "Extension Name",
      "description": "Short name for this hook within its owner namespace. Combined with owner, forms the FQN @owner/hooks/<name>.",
      "examples": ["my-skill", "code-review", "prettier"]
    },
    "HookRuntime": {
      "type": "string",
      "enum": ["bash", "node", "python"],
      "title": "Hook Runtime",
      "description": "Interpreter family used to execute the materialized hook entrypoint."
    },
    "HookEvent": {
      "type": "string",
      "enum": [
        "session.start",
        "prompt.submit",
        "turn.end",
        "tool.pre",
        "tool.post",
        "subagent.stop",
        "compaction.pre"
      ],
      "title": "Hook Event",
      "description": "Canonical AXM hook event this extension binds to.",
      "examples": ["tool.pre", "tool.post", "prompt.submit"]
    },
    "CanonicalHookToolId": {
      "type": "string",
      "enum": ["file.read", "file.write", "file.edit", "shell.exec", "web.fetch", "mcp.call"],
      "title": "Canonical Hook Tool ID",
      "description": "Vendor-neutral tool identity used by portable hook matchers.",
      "examples": ["file.write", "file.edit", "shell.exec"]
    },
    "HookMatch": {
      "type": "object",
      "properties": {
        "tools": {
          "anyOf": [
            {
              "type": "array",
              "minItems": 1,
              "uniqueItems": true,
              "items": [{ "$ref": "#/definitions/CanonicalHookToolId" }],
              "additionalItems": { "$ref": "#/definitions/CanonicalHookToolId" }
            },
            { "type": "null" }
          ]
        }
      },
      "additionalProperties": false,
      "title": "Hook Match",
      "description": "Portable hook matcher expressed over AXM canonical tool IDs."
    },
    "HookBindingTarget": {
      "type": "object",
      "properties": {
        "matcherRaw": { "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] }
      },
      "additionalProperties": false,
      "title": "Hook Binding Target",
      "description": "Target-agent-specific hook binding escape hatches."
    },
    "HookBlockOutcome": {
      "type": "string",
      "enum": ["allow", "deny", "ask"],
      "title": "Hook Block Outcome",
      "description": "Decision outcome available to blocking hook systems."
    },
    "HookModifyOperation": {
      "type": "string",
      "enum": ["modify-input", "inject-context", "modify-output", "synthesize", "redact"],
      "title": "Hook Modify Operation",
      "description": "Transform operation available to modifying hook systems."
    },
    "HookDecisionRequirement": {
      "anyOf": [
        {
          "type": "object",
          "properties": { "kind": { "type": "string", "enum": ["observe"] } },
          "required": ["kind"],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "kind": { "type": "string", "enum": ["block"] },
            "outcomes": {
              "anyOf": [
                {
                  "type": "array",
                  "minItems": 1,
                  "uniqueItems": true,
                  "items": [{ "$ref": "#/definitions/HookBlockOutcome" }],
                  "additionalItems": { "$ref": "#/definitions/HookBlockOutcome" }
                },
                { "type": "null" }
              ]
            }
          },
          "required": ["kind"],
          "additionalProperties": false
        },
        {
          "type": "object",
          "properties": {
            "kind": { "type": "string", "enum": ["modify"] },
            "operations": {
              "anyOf": [
                {
                  "type": "array",
                  "minItems": 1,
                  "uniqueItems": true,
                  "items": [{ "$ref": "#/definitions/HookModifyOperation" }],
                  "additionalItems": { "$ref": "#/definitions/HookModifyOperation" }
                },
                { "type": "null" }
              ]
            }
          },
          "required": ["kind"],
          "additionalProperties": false
        }
      ],
      "title": "Hook Decision Requirement",
      "description": "Decision capability a hook binding requires from the target agent event."
    },
    "HookBinding": {
      "type": "object",
      "properties": {
        "on": { "$ref": "#/definitions/HookEvent" },
        "match": { "anyOf": [{ "$ref": "#/definitions/HookMatch" }, { "type": "null" }] },
        "matcherRaw": { "anyOf": [{ "type": "string", "minLength": 1 }, { "type": "null" }] },
        "targets": {
          "anyOf": [
            {
              "type": "object",
              "additionalProperties": { "$ref": "#/definitions/HookBindingTarget" }
            },
            { "type": "null" }
          ]
        },
        "requires": {
          "anyOf": [
            {
              "type": "object",
              "properties": { "decision": { "$ref": "#/definitions/HookDecisionRequirement" } },
              "required": ["decision"],
              "additionalProperties": false
            },
            { "type": "null" }
          ]
        }
      },
      "required": ["on"],
      "additionalProperties": false,
      "title": "Hook Binding",
      "description": "Universal hook event binding with portable canonical matching and raw native escape hatches."
    },
    "HookCapabilities": {
      "type": "object",
      "properties": {
        "network": { "anyOf": [{ "type": "boolean" }, { "type": "null" }] },
        "filesystemWrite": { "anyOf": [{ "type": "boolean" }, { "type": "null" }] },
        "exec": {
          "anyOf": [
            { "type": "array", "items": { "type": "string", "minLength": 1 } },
            { "type": "null" }
          ]
        },
        "env": {
          "anyOf": [
            { "type": "array", "items": { "type": "string", "minLength": 1 } },
            { "type": "null" }
          ]
        }
      },
      "additionalProperties": false,
      "title": "Hook Capabilities",
      "description": "Advisory author-declared hook capability surface. v1 does not enforce it."
    },
    "HookManifest": {
      "type": "object",
      "properties": {
        "$schema": { "anyOf": [{ "type": "string" }, { "type": "null" }] },
        "publish": { "anyOf": [{ "$ref": "#/definitions/PublishOptions" }, { "type": "null" }] },
        "metadata": {
          "anyOf": [
            {
              "type": "object",
              "title": "Extension Metadata",
              "description": "Opaque consumer-defined JSON metadata. The compact UTF-8 JSON representation is limited to 65,536 bytes and container depth 16."
            },
            { "type": "null" }
          ]
        },
        "owner": { "$ref": "#/definitions/Handle" },
        "version": { "$ref": "#/definitions/Version" },
        "description": {
          "anyOf": [
            {
              "type": "string",
              "description": "Short, registry-facing summary of this extension shown in listings and search results."
            },
            { "type": "null" }
          ]
        },
        "keywords": {
          "anyOf": [
            {
              "type": "array",
              "examples": [["lint", "typescript", "review"]],
              "items": { "type": "string", "minLength": 1 }
            },
            { "type": "null" }
          ]
        },
        "repository": { "anyOf": [{ "$ref": "#/definitions/Repository" }, { "type": "null" }] },
        "homepage": {
          "anyOf": [
            { "type": "string", "examples": ["https://acme.dev/code-review"], "format": "uri" },
            { "type": "null" }
          ]
        },
        "license": {
          "anyOf": [
            {
              "type": "string",
              "title": "License",
              "description": "SPDX license expression, or `UNLICENSED` for proprietary code.",
              "examples": ["MIT", "Apache-2.0", "MIT OR Apache-2.0", "UNLICENSED"],
              "format": "spdx-expression"
            },
            { "type": "null" }
          ]
        },
        "bugs": { "anyOf": [{ "$ref": "#/definitions/Bugs" }, { "type": "null" }] },
        "authors": {
          "anyOf": [
            { "type": "array", "items": { "$ref": "#/definitions/Author" } },
            { "type": "null" }
          ]
        },
        "packages": {
          "anyOf": [
            {
              "type": "array",
              "description": "External ecosystem packages this extension is designed to work with, declared as identity Package URLs with optional VERS compatibility ranges.",
              "items": { "$ref": "#/definitions/CompanionPackage" }
            },
            { "type": "null" }
          ]
        },
        "enhances": {
          "anyOf": [
            {
              "type": "array",
              "uniqueItems": true,
              "description": "Soft capability enhancements used by the source. These never block installation.",
              "items": {
                "type": "string",
                "minLength": 1,
                "pattern": "^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?::[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)?$"
              }
            },
            { "type": "null" }
          ]
        },
        "requires": {
          "anyOf": [
            {
              "type": "array",
              "uniqueItems": true,
              "description": "Hard capabilities without which the extension cannot operate.",
              "items": {
                "type": "string",
                "minLength": 1,
                "pattern": "^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?::[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)?$"
              }
            },
            { "type": "null" }
          ]
        },
        "fallback": {
          "anyOf": [
            {
              "type": "string",
              "enum": ["auto", "none"],
              "description": "Whether AXM may apply platform-provided capability fallbacks. Defaults to auto.",
              "default": "auto"
            },
            { "type": "null" }
          ]
        },
        "recommendedPacks": {
          "anyOf": [
            {
              "type": "array",
              "description": "Pack recommendations and same-pack composition metadata. Entries do not install or guarantee the pack or its members.",
              "items": { "$ref": "#/definitions/PackSpec" }
            },
            { "type": "null" }
          ]
        },
        "standalone": {
          "anyOf": [
            {
              "type": "boolean",
              "description": "False means the extension requires sibling extensions that are direct members of a pack named in recommendedPacks; it does not create dependencies.",
              "default": true
            },
            { "type": "null" }
          ]
        },
        "type": { "type": "string", "enum": ["hook"] },
        "name": { "$ref": "#/definitions/ExtensionName" },
        "title": {
          "anyOf": [
            {
              "type": "string",
              "minLength": 1,
              "description": "Optional display title for this hook."
            },
            { "type": "null" }
          ]
        },
        "runtime": { "$ref": "#/definitions/HookRuntime" },
        "entrypoint": {
          "type": "string",
          "minLength": 1,
          "description": "Hook body entrypoint path, relative to the hook manifest directory.",
          "examples": ["src/hook.sh", "src/hook.js", "src/hook.py"]
        },
        "bindings": { "type": "array", "items": { "$ref": "#/definitions/HookBinding" } },
        "timeoutMs": {
          "anyOf": [{ "type": "integer", "exclusiveMinimum": 0 }, { "type": "null" }]
        },
        "capabilities": {
          "anyOf": [{ "$ref": "#/definitions/HookCapabilities" }, { "type": "null" }]
        }
      },
      "required": ["owner", "version", "type", "name", "runtime", "entrypoint", "bindings"],
      "additionalProperties": false,
      "title": "Hook Manifest",
      "description": "Hook manifest for managed agent hooks. The executable body lives under src/ and is invoked from native agent settings."
    }
  }
}
