-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Lifecycle hooks #549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
harikrishnan83
wants to merge
2
commits into
Fission-AI:main
Choose a base branch
from
intent-driven-dev:lifecycle-hooks
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+448
−0
Open
Lifecycle hooks #549
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,203 @@ | ||
| ## Context | ||
|
|
||
| OpenSpec generates markdown instructions for AI agents at three lifecycle phases: proposal (planning), apply (implementation), and archive (completion). The current implementation hard-codes these instructions in `slash-command-templates.ts`. Users wanting to integrate external tools (issue trackers, CI systems, notification services) must fork OpenSpec and modify these templates directly. | ||
|
|
||
| The Linear MCP integration demonstrated in the `intent-driven-dev` fork shows a common pattern: injecting additional instructions into each phase to call MCP tools for issue status updates. This should be generalizable to any integration. | ||
|
|
||
| **Constraints:** | ||
| - Hooks must be markdown instructions (not shell scripts) - they're guidance for AI agents, not executable code | ||
| - Must not break existing workflows - hooks are optional | ||
| - Must work with all schemas (spec-driven, tdd, custom) | ||
| - Should allow project-level configuration without global state | ||
|
|
||
| ## Goals / Non-Goals | ||
|
|
||
| **Goals:** | ||
| - Enable custom instructions to be injected before/after each lifecycle phase | ||
| - Support all three phases: proposal, apply, archive (and any custom phases) | ||
| - Discover hooks by convention from `openspec/hooks/` directory | ||
| - Support multiple integrations through namespace folders | ||
| - Keep hook execution simple - concatenate into phase instructions | ||
|
|
||
| **Non-Goals:** | ||
| - Shell script execution (hooks are markdown instructions, not code) | ||
| - Global hooks (per-project only) | ||
| - Conditional hook execution based on change properties | ||
| - Hook dependency ordering (keep it simple) | ||
|
|
||
| ## Decisions | ||
|
|
||
| ### Decision 1: Hooks as Markdown Instructions | ||
|
|
||
| **Choice:** Hooks are markdown files that get concatenated into phase instructions. | ||
|
|
||
| **Rationale:** OpenSpec generates instructions for AI agents - the agents interpret markdown, not shell scripts. This matches the existing architecture and the pattern demonstrated in the Linear MCP integration. | ||
|
|
||
| **Alternatives considered:** | ||
| - Shell scripts: Would require a separate execution model and wouldn't integrate with agent instructions | ||
| - MCP tool configuration: Too specific to one integration type; markdown is more flexible | ||
| - Schema-level hooks: Would require duplicating hooks across schemas; project-level is simpler | ||
|
|
||
| ### Decision 2: Convention-Based Hook Discovery | ||
|
|
||
| **Choice:** Hooks are discovered by convention from `openspec/hooks/` directory using predictable file names. | ||
|
|
||
| **Directory structure:** | ||
| ``` | ||
| openspec/ | ||
| ├── hooks/ | ||
| │ ├── linear/ # Integration namespace | ||
| │ │ ├── before-proposal.md # Select Linear story | ||
| │ │ ├── after-proposal.md # Move to Todo | ||
| │ │ ├── before-apply.md # Update description | ||
| │ │ ├── after-apply.md # Move to In Progress | ||
| │ │ └── after-archive.md # Move to Done | ||
| │ ├── slack/ # Another integration | ||
| │ │ └── after-archive.md # Notify channel | ||
| │ └── custom/ # Project-specific hooks | ||
| │ └── before-apply.md # Custom setup | ||
| ``` | ||
|
|
||
| **Naming convention:** | ||
| - Folder: integration/namespace name (e.g., `linear`, `slack`, `custom`) | ||
| - File: `{before|after}-{phase}.md` | ||
|
|
||
| **Composition rules:** | ||
| - All hooks for the same phase across ALL folders are concatenated | ||
| - Order: alphabetical by folder name, then by file | ||
| - Duplicate files within same folder = misconfiguration (warning logged) | ||
|
|
||
| **Rationale:** | ||
| - Zero configuration required - just drop files in folders | ||
| - Each integration is namespaced - easy to add/remove by folder | ||
| - Automatically works with custom schema phases (e.g., `before-review.md`) | ||
| - Future-proof: no code changes needed when new phases are added | ||
| - Clear ownership: know which integration owns each hook | ||
| - Simple to distribute: copy the integration folder | ||
|
|
||
| **Alternatives considered:** | ||
| - Flat structure (`hooks/before-proposal.md`): No namespace, conflicts between integrations | ||
| - Config-based (`hooks:` in config.yaml): Requires updating config for each hook | ||
| - Numbered ordering (`01-before-proposal.md`): More complex, less readable | ||
|
|
||
| ### Decision 3: Hook Injection Points | ||
|
|
||
| **Choice:** Inject hooks at these points in the phase instructions: | ||
|
|
||
| | Phase | Before Point | After Point | | ||
| |-------|--------------|-------------| | ||
| | proposal | After guardrails, before steps | After references | | ||
| | apply | After guardrails, before steps | After references | | ||
| | archive | After guardrails, before steps | After references | | ||
|
|
||
| **Rationale:** | ||
| - "Before" hooks set up context/prerequisites before the main workflow steps | ||
| - "After" hooks handle cleanup/follow-up after the workflow completes | ||
| - Placing hooks relative to existing sections maintains readability | ||
|
|
||
| ### Decision 4: Hook File Resolution | ||
|
|
||
| **Choice:** Hook files are read from `openspec/hooks/{integration}/{timing}-{phase}.md` paths within the project. | ||
|
|
||
| **Path resolution:** | ||
| ``` | ||
| openspec/hooks/linear/before-proposal.md # Reads from project's openspec/hooks/ directory | ||
| ``` | ||
|
|
||
| **Rationale:** All hooks are centralized in the `openspec/hooks/` directory, keeping integration files organized and separate from other project files. | ||
|
|
||
| **Error handling:** | ||
| - Missing `openspec/hooks/` directory: no hooks loaded (not an error) | ||
| - Empty integration folder: skipped without warning | ||
| - Invalid filenames (e.g., `setup.md`): ignored with debug log | ||
| - File read errors: warning logged, hook skipped | ||
|
|
||
| ### Decision 5: Integration Distribution Model | ||
|
|
||
| **Choice:** Integrations are distributed as standalone packages containing hook files and optional configuration templates. | ||
|
|
||
| **Integration package structure:** | ||
| ``` | ||
| openspec-linear/ # npm package or git repo | ||
| ├── README.md # Setup instructions | ||
| ├── linear/ # Folder name = integration namespace | ||
| │ ├── before-proposal.md # Linear story selection | ||
| │ ├── after-proposal.md # Move story to Todo | ||
| │ ├── before-apply.md # Update story description | ||
| │ ├── after-apply.md # Move story to In Progress | ||
| │ └── after-archive.md # Move story to Done | ||
| ├── config/ | ||
| │ └── linear.yml.example # Template for openspec/linear.yml | ||
| └── install.sh # Optional: copies folder to project | ||
| ``` | ||
|
|
||
| **Installation methods (user choice):** | ||
|
|
||
| 1. **Manual copy** (simplest): | ||
| ```bash | ||
| # Clone/download the integration | ||
| git clone https://github.com/user/openspec-linear | ||
| # Copy the integration folder to your project's hooks | ||
| cp -r openspec-linear/linear your-project/openspec/hooks/ | ||
| ``` | ||
|
|
||
| 2. **CLI command** (future enhancement): | ||
| ```bash | ||
| openspec integration add linear | ||
| # Copies integration folder from registry or git URL | ||
| ``` | ||
|
|
||
| 3. **npm package with postinstall**: | ||
| ```bash | ||
| npm install openspec-linear --save-dev | ||
| # postinstall script copies linear/ folder to openspec/hooks/ | ||
| ``` | ||
|
|
||
| **Composing multiple integrations:** | ||
|
|
||
| Automatic! Each integration lives in its own folder: | ||
| ``` | ||
| openspec/hooks/ | ||
| ├── linear/ # From openspec-linear package | ||
| ├── slack/ # From openspec-slack package | ||
| └── jira/ # From openspec-jira package | ||
| ``` | ||
|
|
||
| All `before-proposal.md` files from all folders are concatenated into the proposal phase instructions. | ||
|
|
||
| **Rationale:** | ||
| - Hooks are just markdown files - trivial to distribute | ||
| - No plugin API or runtime to maintain | ||
| - Works with any package manager or none at all | ||
| - Users can inspect and modify hooks freely | ||
|
|
||
| ## Risks / Trade-offs | ||
|
|
||
| | Risk | Mitigation | | ||
| |------|------------| | ||
| | Large hook files bloating instructions | Add max size check (50KB limit per file) | | ||
| | Hook content breaking instruction parsing | Hooks are plain markdown - no special parsing required | | ||
| | Users expecting executable hooks | Clear documentation that hooks are agent instructions, not scripts | | ||
| | Accidental inclusion of unwanted hooks | Each integration is namespaced - remove folder to remove all its hooks | | ||
| | Hook ordering conflicts between integrations | Alphabetical by folder name provides deterministic ordering | | ||
| | Discovery overhead scanning directories | Hooks directory is small; scan is fast and cached per command | | ||
|
|
||
| ## Migration Plan | ||
|
|
||
| 1. **No migration required** - hooks are additive and optional | ||
| 2. Existing projects continue working unchanged | ||
| 3. New projects can opt-in by creating `openspec/hooks/{integration}/` directories | ||
|
|
||
| ## Open Questions | ||
|
|
||
| 1. **Should hooks support schema-level defaults?** (e.g., hooks defined in schema package) | ||
| - Current decision: No - start simple with project-level hooks only | ||
| - Can add schema-level hooks later if there's demand | ||
|
|
||
| 2. **Should there be a way to disable specific integrations without removing the folder?** | ||
| - Current decision: No - removing/renaming the folder is simple enough | ||
| - Could add `.disabled` marker file or config override later if needed | ||
|
|
||
| 3. **Should the CLI provide commands for managing integrations?** | ||
| - Current decision: Defer to future enhancement | ||
| - Manual copy works for MVP; can add `openspec integration add/remove` later |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # Change: Add Lifecycle Hooks for Proposal, Apply, and Archive Phases | ||
|
|
||
| ## Why | ||
|
|
||
| OpenSpec's lifecycle phases (proposal, apply, archive) generate instructions for AI agents, but there's no way to inject custom behavior at phase boundaries without modifying OpenSpec's source code. Users integrating external tools (Linear, Jira, GitHub Issues, custom CI pipelines) must fork and modify slash command templates directly. A hooks system would allow users to define custom markdown instructions that get injected before/after each phase, enabling integrations like automatic issue tracking without touching OpenSpec internals. | ||
|
|
||
| ## What Changes | ||
|
|
||
| - **New capability**: `lifecycle-hooks` - defines how hooks are discovered and injected | ||
| - Discover hooks by convention from `openspec/hooks/{integration}/` directories | ||
| - Hook files named `{before|after}-{phase}.md` (e.g., `before-proposal.md`, `after-apply.md`) | ||
| - Extend slash command template generation to inject hook instructions at phase boundaries | ||
| - Support before/after hooks for any phase (proposal, apply, archive, or custom phases) | ||
| - Multiple integrations compose automatically - all hooks for same phase are concatenated | ||
| - Hooks are markdown instruction files that get concatenated into the phase instructions | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### New Capabilities | ||
| - `lifecycle-hooks` - Configuration and injection of custom instructions at lifecycle phase boundaries | ||
|
|
||
| ### Modified Capabilities | ||
| - `slash-commands` - Extend template generation to discover and inject hooks | ||
|
|
||
| ## Impact | ||
|
|
||
| - **Affected code**: | ||
| - `src/core/hooks.ts` (new) - Hook discovery and loading from `openspec/hooks/` directory | ||
| - `src/core/templates/slash-command-templates.ts` - Inject hook content into phase instructions | ||
| - `src/commands/artifact-workflow.ts` - Pass project root to template generation | ||
| - **Affected files**: `openspec/hooks/` directory structure for hook files | ||
| - **Users**: Can define custom integrations (Linear MCP, Jira, etc.) by adding hook files to `openspec/hooks/{integration}/` without forking OpenSpec | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Missing delta spec for
slash-commandscapability modification - proposal claims to modifyslash-commandscapability but no delta spec exists atchanges/add-lifecycle-hooks/specs/slash-commands/spec.mdPer AGENTS.md line 196: "If multiple capabilities are affected, create multiple delta files under
changes/[change-id]/specs/<capability>/spec.md—one per capability."Options:
specs/slash-commands/spec.mdwith MODIFIED requirementsslash-commandsisn't an existing capability, remove this line or clarify that template generation changes don't require a separate capability specPrompt To Fix With AI