{"_id":"@adhd/sox-manifest","_rev":"4-5141e55b7e4c1c89f019712622928160","name":"@adhd/sox-manifest","dist-tags":{"latest":"1.0.0"},"versions":{"0.2.0":{"name":"@adhd/sox-manifest","version":"0.2.0","license":"MIT","_id":"@adhd/sox-manifest@0.2.0","maintainers":[{"name":"pseudosky","email":"skywinston.sk@gmail.com"}],"dist":{"shasum":"238c9a67057635f7523494916d28bf5b5140a20c","tarball":"https://registry.npmjs.org/@adhd/sox-manifest/-/sox-manifest-0.2.0.tgz","fileCount":6,"integrity":"sha512-SWPNcm4EtNxXlzhRvRxv7S6XCMPy+QhbeDFfASjURaAqi8Z3cbXrJY6FEdUUOyYlTaGjcnNyZUed7lslonUHMQ==","signatures":[{"sig":"MEQCIFINAbfeJ6sHLWq48uGyjKTa/YASbr0fxIMnN5h5lbgKAiADR1azKcNIBWklSC6Ckcs0pZZ+LzBH2invnqddkrYCQg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74237},"main":"./dist/index.js","_from":"file:adhd-sox-manifest-0.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"_npmUser":{"name":"pseudosky","email":"skywinston.sk@gmail.com"},"_resolved":"/private/var/folders/yg/cfczgtx54bzfh74lx2_mv0z80000gp/T/7fb7a59a43903027304cb4b3c118326c/adhd-sox-manifest-0.2.0.tgz","_integrity":"sha512-SWPNcm4EtNxXlzhRvRxv7S6XCMPy+QhbeDFfASjURaAqi8Z3cbXrJY6FEdUUOyYlTaGjcnNyZUed7lslonUHMQ==","_npmVersion":"11.6.2","description":"Extension manifest schema and validate() — single source of truth","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sox-manifest_0.2.0_1782451185049_0.3835285263081565","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@adhd/sox-manifest","version":"0.3.0","license":"MIT","_id":"@adhd/sox-manifest@0.3.0","maintainers":[{"name":"pseudosky","email":"skywinston.sk@gmail.com"}],"dist":{"shasum":"246259e4d6d9f1f3df7dbac0b6c4e7b31b9e3c0c","tarball":"https://registry.npmjs.org/@adhd/sox-manifest/-/sox-manifest-0.3.0.tgz","fileCount":6,"integrity":"sha512-B1GsOtmFg6hHV5QihDxPDvKnXjJAMLn5+a8AJTkTr2aqCQkErHJaNrVnnQwK1pOzyw46sXEcTIyShi1p5HC1MA==","signatures":[{"sig":"MEQCIB9YuMNa5DNFWkoYtk7CDUEYgoPXIK6eok0CaVMjf6eSAiBvEqwu74GwEs/jOUKudlFBMBXUa3jfhZUsJ1x1Pk56OQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":75820},"main":"./dist/index.js","_from":"file:adhd-sox-manifest-0.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"_npmUser":{"name":"pseudosky","email":"skywinston.sk@gmail.com"},"_resolved":"/private/var/folders/yg/cfczgtx54bzfh74lx2_mv0z80000gp/T/163b0cd909b55fe480bf1e7e95702f84/adhd-sox-manifest-0.3.0.tgz","_integrity":"sha512-B1GsOtmFg6hHV5QihDxPDvKnXjJAMLn5+a8AJTkTr2aqCQkErHJaNrVnnQwK1pOzyw46sXEcTIyShi1p5HC1MA==","_npmVersion":"11.6.2","description":"Extension manifest schema and validate() — single source of truth","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sox-manifest_0.3.0_1786144737627_0.8931331561898301","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@adhd/sox-manifest","version":"0.4.0","keywords":["manifest","schema","validation","typescript"],"license":"MIT","_id":"@adhd/sox-manifest@0.4.0","maintainers":[{"name":"pseudosky","email":"skywinston.sk@gmail.com"}],"homepage":"https://github.com/PseudoSky/adhd","bugs":{"url":"https://github.com/PseudoSky/adhd/issues"},"dist":{"shasum":"411694ce095acd8d8e1548684328d0131af5e02e","tarball":"https://registry.npmjs.org/@adhd/sox-manifest/-/sox-manifest-0.4.0.tgz","fileCount":8,"integrity":"sha512-M2ovKoYUgVZD/9Wst3Of/f4ws1vw8EkXkZUNMam7X9ra3cstSWukqTDaw6AtFcLIIa1JfLRGZBZhlxwtdFutHg==","signatures":[{"sig":"MEUCIAwY4HglnS6A13VNoBJZz9b0APjZUjEj/y5+IZTnuZD8AiEAxIPNZB/6lnB+jA/m7HfeOff18bSltE5YyvbOCO/YJ3w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIFch/TDdpqq+AqNy/+FsYgtDEA00ihRC/7hqUNZMj9vtAiA8EJYb/DbfO7Eo37tFBII1rTfTb7oheqURlA+oLhlz8w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98836},"main":"./dist/index.js","_from":"file:adhd-sox-manifest-0.4.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"_npmUser":{"name":"pseudosky","email":"skywinston.sk@gmail.com"},"_resolved":"/private/var/folders/yg/cfczgtx54bzfh74lx2_mv0z80000gp/T/492c2b34dca01cc1c934f2619f6a5cf4/adhd-sox-manifest-0.4.0.tgz","_integrity":"sha512-M2ovKoYUgVZD/9Wst3Of/f4ws1vw8EkXkZUNMam7X9ra3cstSWukqTDaw6AtFcLIIa1JfLRGZBZhlxwtdFutHg==","repository":{"url":"git+https://github.com/PseudoSky/adhd.git","type":"git"},"_npmVersion":"11.6.2","description":"Extension manifest schema and validate() — single source of truth","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sox-manifest_0.4.0_1788566561442_0.5473357662687903","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"_id":"@adhd/sox-manifest@1.0.0","bugs":{"url":"https://github.com/PseudoSky/adhd/issues"},"dist":{"shasum":"b630b9cd08f9446c6151f225932b544156d619b8","tarball":"https://registry.npmjs.org/@adhd/sox-manifest/-/sox-manifest-1.0.0.tgz","fileCount":8,"integrity":"sha512-Cpjd6ZCa83F4AbFM55wftTm5kwTBnsUHhtWN24OgoY83ScBkTFrte+oyiPXfVpX1OxKxP5q5XE1hCbMB+G6tGQ==","signatures":[{"sig":"MEQCIHSPnBYRO1QkmY4tAQx1UINv1RUG7nVwjAunmUT50i0zAiAB+FZtTRqX2zVNcy+76zsr54hqFIyiUYNT58rap/HOuQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHYdrFKNVTQzT9kCC/odAY5VDgN++mEiRqCuOQJEgUqxAiAT9YoFM4b6zp4oteVXyScuwArbeRlwrodryIgXHoeJ/Q=="}],"unpackedSize":101629},"main":"./dist/index.js","name":"@adhd/sox-manifest","_from":"file:adhd-sox-manifest-1.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.js"}},"license":"MIT","version":"1.0.0","_npmUser":{"name":"pseudosky","email":"skywinston.sk@gmail.com"},"homepage":"https://github.com/PseudoSky/adhd","keywords":["manifest","schema","validation","typescript"],"_resolved":"/private/var/folders/yg/cfczgtx54bzfh74lx2_mv0z80000gp/T/028730dcf91fb5f6b2820490e9426610/adhd-sox-manifest-1.0.0.tgz","_integrity":"sha512-Cpjd6ZCa83F4AbFM55wftTm5kwTBnsUHhtWN24OgoY83ScBkTFrte+oyiPXfVpX1OxKxP5q5XE1hCbMB+G6tGQ==","repository":{"url":"git+https://github.com/PseudoSky/adhd.git","type":"git"},"_npmVersion":"11.6.2","description":"Extension manifest schema and validate() — single source of truth","directories":{},"maintainers":[{"name":"pseudosky","email":"skywinston.sk@gmail.com"}],"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sox-manifest_1.0.0_1790650270060_0.42401811184178717"}}},"time":{"created":"2026-06-26T05:19:44.920Z","modified":"2026-09-29T02:51:10.295Z","0.2.0":"2026-06-26T05:19:45.191Z","0.3.0":"2026-08-07T23:18:57.785Z","0.4.0":"2026-09-05T00:02:41.522Z","1.0.0":"2026-09-29T02:51:10.141Z"},"bugs":{"url":"https://github.com/PseudoSky/adhd/issues"},"license":"MIT","homepage":"https://github.com/PseudoSky/adhd","keywords":["manifest","schema","validation","typescript"],"repository":{"url":"git+https://github.com/PseudoSky/adhd.git","type":"git"},"description":"Extension manifest schema and validate() — single source of truth","maintainers":[{"name":"pseudosky","email":"skywinston.sk@gmail.com"}],"readme":"# @adhd/sox-manifest\n\nThe single source of truth for the `extension.json` manifest shape used across\nthe sox ecosystem: a `Manifest` TypeScript interface, a runtime `validate()`\nfunction, a type predicate (`isManifest`), and the raw JSON Schema those two\nare generated from. Every extension type — agent, skill, mcp-server, prompt,\nhook, command, bundle, service — is described by the same `Manifest` shape;\n`validate()` is what every installer, registry builder, and CLI in this\necosystem calls to check one before trusting it.\n\n```bash\npnpm add @adhd/sox-manifest\n```\n\n## Quick start\n\n```typescript\nimport { validate, isManifest, type Manifest } from '@adhd/sox-manifest';\n\nconst manifest: Manifest = {\n  id: 'note-taker',\n  type: 'skill',\n  title: 'Note Taker',\n  description: 'Does one thing well',\n  compatibility: { host: '>=1.0.0 <2.0.0' },\n  license: 'MIT',\n  entrypoint: 'dist/index.js',\n};\n\nconst result = validate(manifest);\nconsole.log(result.ok);       // true\nconsole.log(result.errors);   // []\nconsole.log(result.warnings); // []\n\nconsole.log(isManifest(manifest)); // true — isManifest is validate() as a type predicate\n\nconst bad = { id: 'Bad_ID', type: 'skill', title: '', description: 'x' };\nconsole.log(validate(bad).errors);\n// [\n//   'missing required field: \"compatibility\"',\n//   'missing required field: \"license\"',\n//   'id \"Bad_ID\" must match ^[a-z][a-z0-9-]*$',\n//   'title must be a non-empty string',\n// ]\n```\n\n## API reference\n\n### `validate()` — the runtime conformance check\n\n```typescript\nfunction validate(raw: Record<string, unknown>): ValidateResult;\n\ninterface ValidateResult {\n  ok: boolean;\n  errors: string[];\n  /** Non-fatal advisory notices. `ok` may still be `true` when warnings are present. */\n  warnings: string[];\n}\n```\n\nChecks a plain object (not a file path — read and `JSON.parse` the file\nyourself first) against every structural and semantic rule in the manifest\ncontract: required fields, the `id` slug pattern (`^[a-z][a-z0-9-]*$`), `type`\nagainst the known extension types, `runtime` against the known runtimes,\n`install.hosts` against known hosts, the `profiles ⊆ serves ∪ transports`\ninvariant, and the managed/forbidden-key guards described below. Returns every\nviolation found — not just the first — in `errors`.\n\n### `isManifest()` — type predicate\n\n```typescript\nfunction isManifest(value: unknown): value is Manifest;\n```\n\nA thin wrapper over `validate()` that narrows `value` to `Manifest` when it\nreturns `true`. Use `validate()` directly when you need to report *why*\nsomething failed.\n\n### The `Manifest` interface\n\n```typescript\ninterface Manifest {\n  $schema?: string;\n  id: string;\n  /** Deprecated display label — never an identity input; identity is id + checksum. */\n  version?: string;\n  type: 'agent' | 'skill' | 'mcp-server' | 'prompt' | 'hook' | 'command' | 'bundle' | 'service';\n  title: string;\n  description: string;\n  compatibility: Record<string, string>;\n  license: string;\n  /** Optional — absent for bundle, prompt, declarative types. */\n  entrypoint?: string;\n  /** Defaults to 'node' when absent. */\n  runtime?: ManifestRuntime;\n  /** Host-placement path for declarative extensions. */\n  'install-target'?: string;\n  author?: string | { name: string; email?: string; url?: string };\n  homepage?: string;\n  repository?: string;\n  keywords?: string[];\n  tags?: string[];\n  license_url?: string;\n  private?: boolean;\n  checksum?: string;\n  order?: number;\n  requires?: ManifestRequires;\n  dependencies?: Array<ManifestDependency | string>;\n  capabilities?: string[];\n  members?: ManifestMember[];\n  lifecycle?: ManifestLifecycle;\n  events?: string[];\n  invocation?: ManifestInvocation;\n  tools?: ManifestTool[];\n  parameters?: ManifestParameter[];\n  template_engine?: 'handlebars' | 'jinja2' | 'mustache' | 'simple' | 'none';\n  run_interface?: ManifestRunInterface;\n  config_schema?: Record<string, unknown>;\n  permissions?: ManifestPermissions;\n  /** Hybrid install descriptor — replaces the older single-string install-target. */\n  install?: ManifestInstall;\n  /** Runtime/environment config carried on the built extension. */\n  config?: Record<string, unknown>;\n  /** Top-level provenance path (alias; prefer install.source). */\n  source?: string;\n  [key: string]: unknown;\n}\n\ntype ManifestRuntime = 'node' | 'shell' | 'python' | 'declarative' | 'stdio-any';\n```\n\n### Supporting block types\n\n```typescript\ninterface ManifestRequires {\n  tool_calling?: boolean;\n  structured_output?: boolean;\n  min_context_tokens?: number;\n}\n\ninterface ManifestDependency {\n  id: string;\n  version: string;\n}\n\ninterface ManifestMember {\n  id: string; // bundle members are referenced by id only — identity is id + checksum\n}\n\ninterface ManifestLifecycle {\n  background?: boolean;\n  singleton?: boolean;\n  stop_timeout_ms?: number;\n  health?: ManifestLifecycleHealth;\n}\n\ninterface ManifestLifecycleHealth {\n  type?: 'stdio-ping' | 'http-get' | 'socket' | 'command';\n  endpoint?: string;\n  interval_ms?: number;\n  timeout_ms?: number;\n}\n\ninterface ManifestInvocation {\n  protocol?: 'function-export' | 'stdio' | 'ipc' | 'http';\n  handler?: string;\n  input_schema?: Record<string, unknown>;\n  output_schema?: Record<string, unknown>;\n}\n\ninterface ManifestTool {\n  name: string;\n  description: string;\n  inputSchema?: Record<string, unknown>;\n}\n\ninterface ManifestParameter {\n  name: string;\n  type?: 'string' | 'number' | 'boolean' | 'array' | 'object';\n  required?: boolean;\n  description?: string;\n}\n\ninterface ManifestRunInterface {\n  input_schema?: Record<string, unknown>;\n  output_schema?: Record<string, unknown>;\n}\n\ninterface ManifestPermissions {\n  fs?: ManifestFsPermissions;\n  network?: ManifestNetworkPermissions;\n  socket?: ManifestSocketPermissions;\n}\ninterface ManifestFsPermissions { read?: string[]; write?: string[]; }\ninterface ManifestNetworkPermissions { outbound?: string[]; }\ninterface ManifestSocketPermissions { paths?: string[]; }\n\ninterface ManifestInstall {\n  type?: 'agent' | 'skill' | 'mcp-server' | 'prompt' | 'hook' | 'command' | 'bundle' | 'service';\n  hosts?: Array<'claude' | 'codex' | 'opencode'>;\n  /** Presets keyed by transport name — each key must also appear in `serves`/`transports`. */\n  profiles?: Record<string, unknown>;\n  /** Transports the mcp extension implements. `profiles ⊆ serves ∪ transports` is enforced by validate(). */\n  serves?: Array<'stdio' | 'sse' | 'http'>;\n  /** Transports declared by a service extension (superset of `serves`). */\n  transports?: Array<'stdio' | 'http' | 'sse' | 'socket'>;\n  /** Origin path when --content @path / --from @dir was used at init. */\n  source?: string;\n  /** Per-host key overrides — validate() expects host keys at the top level,\n   * e.g. `{ claude: {...}, codex: {...} }`; managed (claude) and\n   * project-forbidden (codex) keys nested under those are refused. */\n  overrides?: Record<string, unknown>;\n}\n```\n\n### Constants\n\n```typescript\nconst VALID_TYPES: Set<string>;       // agent, skill, mcp-server, prompt, hook, command, bundle, service\nconst VALID_RUNTIMES: Set<string>;    // node, shell, python, declarative, stdio-any\nconst VALID_HOOK_EVENTS: Set<string>; // PreToolUse, PostToolUse, SessionEnd, ScopePromotionProposed, Stop\nconst KNOWN_HOSTS: Set<string>;       // claude, codex, opencode\n```\n\n```typescript\nimport { VALID_TYPES } from '@adhd/sox-manifest';\n\nif (!VALID_TYPES.has(manifest.type)) throw new Error(`unknown extension type: ${manifest.type}`);\n```\n\n### `ManifestSchema` — the raw JSON Schema\n\n```typescript\nconst ManifestSchema: Record<string, unknown>;\n```\n\nThe same contract as `Manifest`/`validate()`, expressed as a draft-07-flavored\nJSON Schema — inlined directly into the built module (not a sibling\n`schema.json` asset) so it is available under both `require()` and dynamic\n`import()` with nothing extra to load. Use it wherever you need the schema as\ndata rather than as a TypeScript type — e.g. handing it to a generic\nJSON-Schema validator, or embedding it in a published registry index.\n\n```typescript\nimport { ManifestSchema } from '@adhd/sox-manifest';\n\nconsole.log(ManifestSchema['required']); // ['id', 'type', 'title', 'description', 'compatibility', 'license']\n```\n\n## Invariants / gotchas\n\n- **`entrypoint` is optional, not required.** A `bundle`, `prompt`, or\n  `declarative`-runtime extension legitimately has none; `validate()` never\n  flags its absence.\n- **`version` is deprecated and never validated as identity.** Identity is\n  `id` + content `checksum`. If `version` is present it must still\n  be a syntactically valid semver string, but a manifest with no `version` at\n  all is fully valid.\n- **`id` must match `^[a-z][a-z0-9-]*$`.** Uppercase, underscores, and a\n  leading digit are all rejected.\n- **`id` must not end with (or equal) its own `type` name.** A `type: 'skill'`\n  manifest with `id: 'note-skill'` (or `id: 'skill'`) fails validation — every\n  type except `bundle` enforces this. Pick a name that describes what the\n  extension does, not what kind of extension it is.\n- **`profiles ⊆ serves ∪ transports`.** Every *key* of `install.profiles` must\n  itself be one of the values declared in `install.serves` or\n  `install.transports` (e.g. `install: { serves: ['stdio'], profiles: { stdio: {...} } }`)\n  — `validate()` rejects a profile key that names an undeclared transport.\n- **`type: 'service'` requires at least one transport — but only when an\n  `install` block is present.** `install: { transports: [...] }` (or\n  `serves`) must be non-empty for a service; a manifest that omits `install`\n  entirely is not checked against this rule.\n- **Managed/forbidden override keys are rejected, not silently dropped —\n  when nested under the right host key.** `install.overrides.claude` can\n  never contain `managed`, and `install.overrides.codex` can never contain\n  `model_providers`, `notify`, `profile`, or `otel` — `validate()` reports\n  these as errors so a manifest author finds out at authoring time, not at\n  install time. The check only inspects `overrides.claude`/`overrides.codex`;\n  a flat `overrides.managed` (not nested under `claude`) is not caught.\n- **`compatibility` accepts any string-keyed shape.** It is intentionally\n  unconstrained beyond \"an object of strings\" so both host-keyed and\n  soxe-keyed compatibility blocks validate.\n- **`Manifest` has an index signature (`[key: string]: unknown`).** Extra,\n  forward-compatible fields on a manifest object are never a TypeScript error;\n  `validate()` only checks the fields it knows about.\n","readmeFilename":"README.md"}