diff --git a/scripts/test/test-T001-workflow-spec.sh b/scripts/test/test-T001-workflow-spec.sh new file mode 100644 index 0000000..f04f671 --- /dev/null +++ b/scripts/test/test-T001-workflow-spec.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Test: spec and workflow YAML exist for 005-add-workflows-to-hookrunner +set -euo pipefail +cd "$(dirname "$0")/../.." + +errors=0 + +# Spec exists +if [ -f "specs/005-add-workflows-to-hookrunner/spec.md" ]; then + echo "[OK] spec.md exists" +else + echo "[FAIL] specs/005-add-workflows-to-hookrunner/spec.md missing" + errors=$((errors + 1)) +fi + +# Spec has required sections +for section in "Problem" "Solution" "Architecture"; do + if grep -qi "$section" specs/005-add-workflows-to-hookrunner/spec.md 2>/dev/null; then + echo "[OK] spec has $section section" + else + echo "[FAIL] spec missing $section section" + errors=$((errors + 1)) + fi +done + +# Workflow YAML exists +if [ -f "workflows/005-add-workflows-to-hookrunner.yml" ]; then + echo "[OK] workflow YAML exists" +else + echo "[FAIL] workflows/005-add-workflows-to-hookrunner.yml missing" + errors=$((errors + 1)) +fi + +exit $errors diff --git a/specs/005-add-workflows-to-hookrunner/spec.md b/specs/005-add-workflows-to-hookrunner/spec.md new file mode 100644 index 0000000..9e9d3c7 --- /dev/null +++ b/specs/005-add-workflows-to-hookrunner/spec.md @@ -0,0 +1,74 @@ +# 005: Add Workflows to Hook-Runner + +## Problem + +Spec-hook has a workflow engine (YAML step pipelines with gate enforcement) that only works within SHTD flow. The engine should be a hook-runner feature so any project can define workflows without depending on spec-hook. Currently: + +- Workflow engine lives in `spec-hook/lib/workflow.js` — wrong home +- Workflow gate is an SHTD module — should be a hook-runner module +- No CLI integration in hook-runner (`--workflow` commands) +- No way to enforce "always use workflows" without manual discipline +- Cross-project context reset behavior needs workflow enforcement + +## Solution + +Move the workflow engine to hook-runner as a first-class feature: + +1. **workflow.js** → hook-runner lib (zero-dep YAML parser + state machine) +2. **workflow-gate module** → hook-runner PreToolUse catalog +3. **CLI commands** → `node setup.js --workflow list|start|status|complete|reset` +4. **Global workflows** → `~/.claude/hooks/workflows/` (shared across projects) +5. **Project workflows** → `workflows/` in project root (project-specific) +6. **Meta-workflow** → `enforce-shtd.yml` that enforces SHTD pipeline using itself + +## Architecture + +``` +hook-runner/ + workflow.js # Engine: YAML parser, state machine, gate checker + modules/PreToolUse/ + workflow-gate.js # Gate: blocks out-of-order edits per active workflow + workflows/ # Built-in workflow templates + enforce-shtd.yml # Meta: enforce spec→test→branch→PR pipeline + cross-project-reset.yml # Context reset when switching projects +``` + +### Workflow Discovery (priority order) +1. Project: `$CLAUDE_PROJECT_DIR/workflows/*.yml` +2. Global: `~/.claude/hooks/workflows/*.yml` +3. Built-in: hook-runner `workflows/` directory + +### State +- Per-project: `$CLAUDE_PROJECT_DIR/.workflow-state.json` +- Tracks: active workflow name, step statuses, timestamps + +### Gate Logic +- On Write/Edit: check if active workflow exists → validate current step's gate +- Gates: `require_step` (previous step completed), `require_files` (files exist) +- Allowed paths bypass gates (TODO.md, CLAUDE.md, specs/, tests/, etc.) + +## Cross-Project Context Reset Workflow + +When TODO.md is complete and a new project is requested: +1. Save state to current project's TODO.md +2. Commit and push current project +3. Create TODO.md in new project (if needed) +4. Context reset into new project directory +5. Variables control behavior: + - `PRESERVE_TAB=true` — keep old project tab open + - `CONTINUE_BOTH=true` — work in both projects (no stop) + - Default: stop old, start new + +## Enforce-SHTD Meta-Workflow + +A workflow that enforces "always use workflows when making behavioral rules": +1. Any new behavioral rule must start with a workflow YAML +2. The workflow defines enforcement steps +3. Only after workflow is active can gates/modules be created +4. Self-referential: this workflow enforces its own creation pattern + +## Scope + +- hook-runner gets: workflow.js, workflow-gate module, CLI commands, built-in templates +- spec-hook gets: updated to delegate to hook-runner's engine (thin wrapper) +- Both projects get PRs diff --git a/specs/005-add-workflows-to-hookrunner/tasks.md b/specs/005-add-workflows-to-hookrunner/tasks.md new file mode 100644 index 0000000..9b7a752 --- /dev/null +++ b/specs/005-add-workflows-to-hookrunner/tasks.md @@ -0,0 +1,25 @@ +# Tasks: 005 — Add Workflows to Hook-Runner + +## Phase 1: Spec & Plan (spec-hook) +- [x] T001 Write spec, workflow YAML, and tasks for this feature + **Checkpoint**: `bash scripts/test/test-T001-workflow-spec.sh` + +## Phase 2: Build in hook-runner +- [ ] T002 Port workflow.js to hook-runner (extract from spec-hook, zero deps) + **Checkpoint**: `bash scripts/test/test-T002-hookrunner-engine.sh` +- [ ] T003 Add workflow-gate PreToolUse module to hook-runner catalog + **Checkpoint**: `bash scripts/test/test-T003-hookrunner-gate.sh` +- [ ] T004 Add --workflow CLI commands to setup.js (list, start, status, complete, reset) + **Checkpoint**: `bash scripts/test/test-T004-hookrunner-cli.sh` +- [ ] T005 Add built-in workflow templates (enforce-shtd.yml, cross-project-reset.yml) + **Checkpoint**: `bash scripts/test/test-T005-workflow-templates.sh` +- [ ] T006 Tests for workflow engine + gate + CLI + **Checkpoint**: `bash scripts/test/test-T006-hookrunner-e2e.sh` + +## Phase 3: Meta-workflow & SHTD update +- [ ] T007 Create enforce-shtd.yml meta-workflow (enforces using SHTD to create rules) + **Checkpoint**: `bash scripts/test/test-T007-enforce-shtd.sh` +- [ ] T008 Update spec-hook to delegate to hook-runner's workflow engine + **Checkpoint**: `bash scripts/test/test-T008-shtd-delegation.sh` +- [ ] T009 PR for hook-runner, PR for spec-hook, update docs + **Checkpoint**: `bash scripts/test/test-T009-final-verify.sh` diff --git a/workflows/005-add-workflows-to-hookrunner.yml b/workflows/005-add-workflows-to-hookrunner.yml new file mode 100644 index 0000000..822062a --- /dev/null +++ b/workflows/005-add-workflows-to-hookrunner.yml @@ -0,0 +1,58 @@ +name: add-workflows-to-hookrunner +description: Move workflow engine from spec-hook to hook-runner as a first-class feature +version: 1 +steps: + - id: spec + name: Write spec for hook-runner workflow feature + gate: + require_files: [] + completion: + require_files: ["specs/005-add-workflows-to-hookrunner/spec.md"] + - id: tasks + name: Break spec into tasks + gate: + require_step: spec + completion: + require_files: ["specs/005-add-workflows-to-hookrunner/tasks.md"] + - id: engine + name: Port workflow engine to hook-runner + gate: + require_step: tasks + completion: + require_files: [] + - id: gate-module + name: Add workflow-gate PreToolUse module to hook-runner + gate: + require_step: engine + completion: + require_files: [] + - id: cli + name: Add workflow CLI commands to hook-runner setup.js + gate: + require_step: gate-module + completion: + require_files: [] + - id: templates + name: Add built-in workflow templates + gate: + require_step: cli + completion: + require_files: [] + - id: test + name: Test workflow engine end-to-end + gate: + require_step: templates + completion: + require_files: [] + - id: meta-workflow + name: Create enforce-shtd meta-workflow + gate: + require_step: test + completion: + require_files: [] + - id: update-shtd + name: Update spec-hook to delegate to hook-runner engine + gate: + require_step: meta-workflow + completion: + require_files: []