cc-os/openspec/specs/adr-plugin-packaging/spec.md

3.6 KiB
Raw Permalink Blame History

Spec: ADR Plugin Packaging

Purpose

Defines how the os-adr plugin is packaged, named, installed, and structured: cc-os naming conventions, git-tracked source with a symlinked install, full three-place marketplace registration, plugin-relative hook wiring, and an object-oriented Ruby core with model-free deterministic tests.

Requirements

Requirement: Plugin naming and skill naming conventions

The plugin SHALL be named os-adr (kebab-case, os- prefix) and its skills SHALL use verb-first kebab-case names invoked as /os-adr:<verb> (create, init, migrate, find), with no commands/ dispatcher directory — matching the cc-os plugin/skill naming convention.

Scenario: Skills register under verb-first names

  • WHEN the plugin is installed and claude plugin details os-adr@local-plugins is run
  • THEN the listed skills are create, init, migrate, and find, and no commands/ directory exists in the plugin

Requirement: Source of truth in cc-os with symlinked install

The plugin source SHALL live git-tracked at cc-os/plugins/os-adr/ and be installed via a symlink ~/.claude/plugins/os-adr pointing at it, matching the os-vault/os-doc-hygiene/ os-orchestration pattern.

Scenario: Symlinked install

  • WHEN installation is complete
  • THEN ~/.claude/plugins/os-adr is a symlink resolving to the git-tracked plugin directory

Requirement: Full three-place marketplace registration

Installation SHALL update all three registration surfaces — the plugin directory/symlink, the local-plugins marketplace manifest (~/.claude/plugins/.claude-plugin/marketplace.json), and settings.json enabledPlugins — then refresh plugin-manager state via claude plugin marketplace update and claude plugin install, and verify skill registration with claude plugin list and claude plugin details.

Scenario: Skills resolve after install

  • WHEN the registration procedure completes
  • THEN claude plugin list shows os-adr@local-plugins enabled and its skills are invocable as slash commands in a fresh session

Requirement: Hooks wired through plugin hooks.json

Plugin hooks SHALL be declared in hooks/hooks.json using ${CLAUDE_PLUGIN_ROOT}-relative commands (the os-doc-hygiene pattern), not by absolute paths in settings.json, so hook registration cannot silently outlive or diverge from plugin registration.

Scenario: Hook path is plugin-relative

  • WHEN the plugin's hook configuration is inspected
  • THEN the SessionStart command references ${CLAUDE_PLUGIN_ROOT} and no os-adr hook entry exists in settings.json

Requirement: OO core with tested deterministic behavior

The plugin's core logic SHALL be implemented as an object-oriented Ruby library (small single-responsibility classes, dependency-injected paths/IO, no globals) exposed through thin CLI entry points, with a thin Python script only for the SessionStart hook. All deterministic behaviors (ID assignment, index regeneration, shape detection, existence check, retrieval layers 12) SHALL have automated tests runnable without any LLM, including golden-example fixtures.

Scenario: Deterministic tests run model-free

  • WHEN the plugin's test suite runs on a machine with no model access
  • THEN all tests for ID assignment, index regeneration, detection, existence check, and frontmatter retrieval pass

Scenario: Skills delegate to CLI entry points

  • WHEN a skill performs a mechanical operation (numbering, indexing, detection, filtering)
  • THEN it does so by invoking a bin/ CLI rather than re-implementing the logic in prompt instructions