feat: RFC 0041 compaction-resilient context injection
- Add hooks/pre-compact: injects survival context before compaction - Add hooks/context-restore: targeted restoration after compaction - Update install.sh to write hooks to settings.json (not hooks.json) - Add migration logic for existing hooks.json - Use symlinks for skills installation (fixes re-install errors) Three-layer injection model: - SessionStart: full knowledge (~800 tokens) - PreCompact: survival context (~200 tokens, enters summary) - SessionStart:compact: targeted restore (~150 tokens) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6ff8ba706c
commit
9170c20c15
4 changed files with 534 additions and 30 deletions
|
|
@ -0,0 +1,425 @@
|
|||
# RFC 0041: Compaction-Resilient Context Injection
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Status** | Draft |
|
||||
| **Date** | 2026-01-30 |
|
||||
| **Related** | RFC 0016 (Context Injection Architecture), RFC 0038 (SDLC Workflow Discipline) |
|
||||
| **Problem** | SDLC discipline drift after conversation compaction |
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
Establish a compaction-resilient context injection architecture by: (1) consolidating dual-source hook configuration into `~/.claude/settings.json`, (2) using `PreCompact` hooks to inject survival context before compaction so it enters the summary, and (3) using `SessionStart` with `compact` matcher to re-run targeted injection scripts (not CLAUDE.md files).
|
||||
|
||||
## Problem
|
||||
|
||||
After conversation compaction, Claude exhibits "SDLC drift"—forgetting workflow discipline, knowledge injection, and project-specific behavior patterns. Investigation reveals three root causes:
|
||||
|
||||
### 1. Dual-Source Hook Configuration Conflict
|
||||
|
||||
| File | Written By | Contents | Status |
|
||||
|------|------------|----------|--------|
|
||||
| `~/.claude/hooks.json` | `install.sh` | Blue's `hooks/session-start` | **Ignored** |
|
||||
| `~/.claude/settings.json` | Manual | Compact-matcher SessionStart | **Active** |
|
||||
|
||||
The `install.sh` script writes hooks to `hooks.json`, but Claude Code reads from `settings.json`. Blue's session-start hook never fires.
|
||||
|
||||
### 2. No PostCompact Hook Exists
|
||||
|
||||
Claude Code provides:
|
||||
- `PreCompact` — fires BEFORE compaction
|
||||
- `SessionStart` with `matcher: "compact"` — fires when session RESUMES after compaction
|
||||
|
||||
But there is no `PostCompact` hook. When compaction occurs mid-session, the context injected at SessionStart is lost and only restored if the session is paused and resumed.
|
||||
|
||||
### 3. Knowledge Files Not Injected
|
||||
|
||||
Blue has five knowledge files that should shape Claude's behavior:
|
||||
- `knowledge/alignment-measure.md` — ALIGNMENT scoring framework
|
||||
- `knowledge/blue-adrs.md` — Architecture decision records digest
|
||||
- `knowledge/expert-pools.md` — Expert persona definitions
|
||||
- `knowledge/task-sync.md` — Claude Code task integration
|
||||
- `knowledge/workflow-creation.md` — Workflow file guidance
|
||||
|
||||
Due to the hook conflict, these files never reach Claude's context.
|
||||
|
||||
### Observable Symptoms
|
||||
|
||||
- Claude forgets to use `blue_*` MCP tools mid-conversation
|
||||
- SDLC discipline (worktree enforcement, RFC-driven development) degrades
|
||||
- Task sync patterns stop working
|
||||
- ADR adherence drops
|
||||
|
||||
## Goals
|
||||
|
||||
1. Single authoritative source for hook configuration
|
||||
2. Critical context survives conversation compaction
|
||||
3. Knowledge files reliably reach Claude's context
|
||||
4. Graceful degradation when hooks fail
|
||||
5. Audit trail for context injection events
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Changing Claude Code's hook architecture
|
||||
- Eliminating compaction (it's necessary for long conversations)
|
||||
- Real-time context refresh during conversation (MCP Resources handle this)
|
||||
|
||||
## Design
|
||||
|
||||
### Architecture Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ ~/.claude/settings.json │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐│
|
||||
│ │ SessionStart (always) → hooks/session-start (full) ││
|
||||
│ │ SessionStart (compact) → hooks/context-restore (targeted)││
|
||||
│ │ PreCompact → hooks/pre-compact (survival) ││
|
||||
│ │ PreToolUse (blue_*) → blue session-heartbeat ││
|
||||
│ │ SessionEnd → blue session-end ││
|
||||
│ └─────────────────────────────────────────────────────────────┘│
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ knowledge/*.md (source of truth) │
|
||||
│ ┌─────────────────────────────────────────────────────────────┐│
|
||||
│ │ alignment-measure.md → ALIGNMENT scoring framework ││
|
||||
│ │ blue-adrs.md → Architecture decision digest ││
|
||||
│ │ expert-pools.md → Expert persona definitions ││
|
||||
│ │ task-sync.md → Claude Code task integration ││
|
||||
│ │ workflow-creation.md → Workflow file guidance ││
|
||||
│ └─────────────────────────────────────────────────────────────┘│
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Hook Configuration (Consolidated)
|
||||
|
||||
All hooks consolidated into `~/.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "/path/to/blue/hooks/session-start"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": "compact",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "/path/to/blue/hooks/context-restore"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PreCompact": [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "/path/to/blue/hooks/pre-compact"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "blue_*",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "blue session-heartbeat"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"SessionEnd": [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "blue session-end"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: Paths are written as absolute paths during `install.sh` execution.
|
||||
|
||||
### PreCompact Hook Strategy
|
||||
|
||||
The `PreCompact` hook fires BEFORE compaction, injecting context that becomes part of the compacted summary:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# hooks/pre-compact
|
||||
# Inject survival context before compaction
|
||||
|
||||
cat << 'EOF'
|
||||
<compaction-survival-context>
|
||||
## Critical Context for Post-Compaction
|
||||
|
||||
This project uses Blue MCP tools. After compaction, remember:
|
||||
|
||||
1. **MCP Tools Available**: blue_status, blue_next, blue_rfc_*, blue_worktree_*, blue_pr_*
|
||||
2. **SDLC Discipline**: Use worktrees for code changes, RFCs for planning
|
||||
3. **Task Sync**: Tasks with blue_rfc metadata sync to .plan.md files
|
||||
4. **Active State**: Run `blue_status` to see current RFC/worktree
|
||||
|
||||
If you notice workflow drift, run `blue_status` to restore context.
|
||||
</compaction-survival-context>
|
||||
EOF
|
||||
```
|
||||
|
||||
This context becomes part of the compaction summary, ensuring Claude retains awareness of Blue's existence.
|
||||
|
||||
### Context-Restore Hook (Post-Compaction)
|
||||
|
||||
A targeted script that re-injects critical context after compaction. Lighter than full session-start:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# hooks/context-restore
|
||||
# Targeted context restoration after compaction
|
||||
# Lighter than session-start - only critical awareness
|
||||
|
||||
BLUE_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
cat << 'EOF'
|
||||
<blue-context-restore>
|
||||
## Blue MCP Tools Available
|
||||
|
||||
This project uses Blue for SDLC workflow management. Key tools:
|
||||
- `blue_status` - Current RFC, worktree, and session state
|
||||
- `blue_next` - Recommended next action
|
||||
- `blue_rfc_*` - RFC lifecycle management
|
||||
- `blue_worktree_*` - Isolated development environments
|
||||
|
||||
## Workflow Discipline
|
||||
|
||||
1. Code changes require active worktrees (RFC 0038)
|
||||
2. RFCs drive planning; worktrees isolate implementation
|
||||
3. Tasks with `blue_rfc` metadata sync to .plan.md files
|
||||
|
||||
Run `blue_status` to see current project state.
|
||||
</blue-context-restore>
|
||||
EOF
|
||||
|
||||
# Optionally inject project-specific workflow if it exists
|
||||
if [ -f ".blue/workflow.md" ]; then
|
||||
echo "<blue-project-workflow>"
|
||||
cat ".blue/workflow.md"
|
||||
echo "</blue-project-workflow>"
|
||||
fi
|
||||
```
|
||||
|
||||
This hook is deliberately minimal (~150 tokens) to avoid bloating post-compaction context while ensuring Claude remembers Blue exists.
|
||||
|
||||
### Three-Layer Injection Model
|
||||
|
||||
| Layer | Hook | Matcher | Script | Tokens | Survives Compaction? |
|
||||
|-------|------|---------|--------|--------|---------------------|
|
||||
| **Bootstrap** | SessionStart | (none) | `session-start` | ~800 | No (restored on resume) |
|
||||
| **Restoration** | SessionStart | compact | `context-restore` | ~150 | Yes (re-injected) |
|
||||
| **Survival** | PreCompact | (none) | `pre-compact` | ~200 | Yes (enters summary) |
|
||||
|
||||
**Why three layers?**
|
||||
|
||||
- **Bootstrap**: Full knowledge injection when session starts fresh. Expensive but comprehensive.
|
||||
- **Survival**: Injected BEFORE compaction so critical awareness enters the compacted summary. Claude "remembers" Blue exists.
|
||||
- **Restoration**: Targeted re-injection when session resumes after compaction. Lighter than bootstrap.
|
||||
|
||||
### Installation Script Updates
|
||||
|
||||
Update `install.sh` to configure hooks in `settings.json` (not `hooks.json`):
|
||||
|
||||
```bash
|
||||
# install.sh changes
|
||||
|
||||
SETTINGS_FILE="$HOME/.claude/settings.json"
|
||||
BLUE_ROOT="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
# Ensure settings.json exists with hooks structure
|
||||
if [ ! -f "$SETTINGS_FILE" ]; then
|
||||
echo '{"hooks":{}}' > "$SETTINGS_FILE"
|
||||
fi
|
||||
|
||||
# Merge blue hooks into settings.json
|
||||
if command -v jq &> /dev/null; then
|
||||
jq --arg blue_root "$BLUE_ROOT" '
|
||||
.hooks.SessionStart = [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [{"type": "command", "command": ($blue_root + "/hooks/session-start")}]
|
||||
},
|
||||
{
|
||||
"matcher": "compact",
|
||||
"hooks": [{"type": "command", "command": ($blue_root + "/hooks/context-restore")}]
|
||||
}
|
||||
] |
|
||||
.hooks.PreCompact = [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [{"type": "command", "command": ($blue_root + "/hooks/pre-compact")}]
|
||||
}
|
||||
] |
|
||||
.hooks.PreToolUse = (.hooks.PreToolUse // []) + [
|
||||
{
|
||||
"matcher": "blue_*",
|
||||
"hooks": [{"type": "command", "command": "blue session-heartbeat"}]
|
||||
}
|
||||
] |
|
||||
.hooks.SessionEnd = [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [{"type": "command", "command": "blue session-end"}]
|
||||
}
|
||||
]
|
||||
' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp" && mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
|
||||
fi
|
||||
```
|
||||
|
||||
### Migration from hooks.json
|
||||
|
||||
For users with existing `~/.claude/hooks.json`:
|
||||
|
||||
```bash
|
||||
# Detect and migrate hooks.json → settings.json
|
||||
if [ -f "$HOME/.claude/hooks.json" ] && [ -f "$HOME/.claude/settings.json" ]; then
|
||||
echo "Migrating hooks.json to settings.json..."
|
||||
jq -s '.[0] * .[1]' "$HOME/.claude/settings.json" "$HOME/.claude/hooks.json" > "$HOME/.claude/settings.json.tmp"
|
||||
mv "$HOME/.claude/settings.json.tmp" "$HOME/.claude/settings.json"
|
||||
mv "$HOME/.claude/hooks.json" "$HOME/.claude/hooks.json.migrated"
|
||||
echo "Migration complete. Old file preserved as hooks.json.migrated"
|
||||
fi
|
||||
```
|
||||
|
||||
### Audit Trail
|
||||
|
||||
Add injection logging to `blue.db`:
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS context_injections (
|
||||
id INTEGER PRIMARY KEY,
|
||||
session_id TEXT NOT NULL,
|
||||
timestamp TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
hook_type TEXT NOT NULL, -- SessionStart, PreCompact, etc.
|
||||
matcher TEXT, -- compact, blue_*, etc.
|
||||
content_hash TEXT, -- SHA-256 of injected content
|
||||
token_estimate INTEGER, -- Approximate token count
|
||||
FOREIGN KEY (session_id) REFERENCES sessions(id)
|
||||
);
|
||||
```
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Hook Scripts & Configuration
|
||||
1. Create `hooks/pre-compact` script with survival context
|
||||
2. Create `hooks/context-restore` script for post-compaction restoration
|
||||
3. Update `install.sh` to write to `settings.json` instead of `hooks.json`
|
||||
4. Add migration logic: detect `hooks.json` and merge into `settings.json`
|
||||
5. Test hook firing with `blue context test` command
|
||||
|
||||
### Phase 2: Audit & Observability
|
||||
6. Add `context_injections` table to schema
|
||||
7. Update all hooks to log injections via `blue context log`
|
||||
8. Add `blue context audit` command to view injection history
|
||||
9. Add `blue context test` command to verify hooks fire correctly
|
||||
|
||||
### Phase 3: Documentation & Refinement
|
||||
10. Document hook customization for per-project needs
|
||||
11. Add `.blue/context-restore.md` override support (optional per-project restoration)
|
||||
12. Tune token budgets based on production usage
|
||||
|
||||
## Test Plan
|
||||
|
||||
### Hook Configuration
|
||||
- [ ] `install.sh` writes to `settings.json`, not `hooks.json`
|
||||
- [ ] Existing `settings.json` hooks preserved during install
|
||||
- [ ] `hooks.json` contents migrated to `settings.json`
|
||||
- [ ] SessionStart hook fires on new session
|
||||
- [ ] SessionStart (compact) hook fires after compaction
|
||||
- [ ] PreCompact hook fires before compaction
|
||||
- [ ] PreToolUse hook fires only for blue_* tools
|
||||
|
||||
### Context Injection
|
||||
- [ ] Knowledge files injected at SessionStart via `session-start` hook
|
||||
- [ ] `context-restore` hook fires after compaction with targeted content
|
||||
- [ ] `pre-compact` survival context appears in compaction summary
|
||||
- [ ] Claude retains Blue awareness after compaction (manual verification)
|
||||
|
||||
### Audit Trail
|
||||
- [ ] Injections logged to context_injections table
|
||||
- [ ] `blue context audit` shows injection history
|
||||
- [ ] `blue context test` verifies hook configuration
|
||||
|
||||
### Per-Project Override
|
||||
- [ ] `.blue/context-restore.md` content appended if present
|
||||
- [ ] Missing override file handled gracefully
|
||||
|
||||
## Alternatives Considered
|
||||
|
||||
### A. Request PostCompact Hook from Anthropic
|
||||
|
||||
**Deferred**: Would be ideal but requires upstream changes. PreCompact + SessionStart(compact) provides equivalent functionality today.
|
||||
|
||||
### B. MCP Resource for Context Refresh
|
||||
|
||||
**Complementary**: RFC 0016's MCP Resources (`blue://context/*`) provide on-demand refresh. This RFC addresses the gap where Claude forgets MCP tools exist.
|
||||
|
||||
### C. Periodic Context Re-injection via UserPromptSubmit
|
||||
|
||||
**Rejected**: Would inject on every user message, wasting tokens. PreCompact is more efficient—fires only when needed.
|
||||
|
||||
### D. Use CLAUDE.md Files
|
||||
|
||||
**Rejected**: Adds file management overhead. Direct hook scripts are simpler—no generated artifacts to maintain, no sync issues between knowledge files and CLAUDE.md.
|
||||
|
||||
### E. Re-run Full session-start on Compact
|
||||
|
||||
**Rejected**: Too heavy (~800 tokens). The `context-restore` hook is deliberately minimal (~150 tokens) to avoid bloating post-compaction context.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
- SDLC discipline survives conversation compaction
|
||||
- Single authoritative hook configuration in `settings.json`
|
||||
- Audit trail for debugging injection issues
|
||||
- No generated files to maintain (no CLAUDE.md sync issues)
|
||||
- Targeted restoration (~150 tokens) vs full re-injection (~800 tokens)
|
||||
|
||||
### Negative
|
||||
- Requires manual migration for existing users
|
||||
- PreCompact adds ~200 tokens before each compaction
|
||||
- Three hooks to maintain instead of one
|
||||
|
||||
### Neutral
|
||||
- Shifts from hooks.json to settings.json (Claude Code's actual config)
|
||||
- Knowledge files remain source of truth; hooks read them directly
|
||||
|
||||
## References
|
||||
|
||||
- [RFC 0016: Context Injection Architecture](0016-context-injection-architecture.draft.md) — Three-tier model
|
||||
- [RFC 0038: SDLC Workflow Discipline](0038-sdlc-workflow-discipline.draft.md) — What needs to survive
|
||||
- [Claude Code Hooks Documentation](https://docs.anthropic.com/en/docs/claude-code/hooks) — Available hook events
|
||||
|
||||
---
|
||||
|
||||
*"Context flows through explicit boundaries; survival requires deliberate architecture."*
|
||||
|
||||
— Blue
|
||||
31
hooks/context-restore
Executable file
31
hooks/context-restore
Executable file
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/bash
|
||||
# Blue Context-Restore Hook
|
||||
# Targeted context restoration after compaction
|
||||
# Lighter than session-start (~150 tokens vs ~800 tokens)
|
||||
|
||||
cat << 'EOF'
|
||||
<blue-context-restore>
|
||||
## Blue MCP Tools Available
|
||||
|
||||
This project uses Blue for SDLC workflow management. Key tools:
|
||||
- `blue_status` - Current RFC, worktree, and session state
|
||||
- `blue_next` - Recommended next action
|
||||
- `blue_rfc_*` - RFC lifecycle management
|
||||
- `blue_worktree_*` - Isolated development environments
|
||||
|
||||
## Workflow Discipline
|
||||
|
||||
1. Code changes require active worktrees (RFC 0038)
|
||||
2. RFCs drive planning; worktrees isolate implementation
|
||||
3. Tasks with `blue_rfc` metadata sync to .plan.md files
|
||||
|
||||
Run `blue_status` to see current project state.
|
||||
</blue-context-restore>
|
||||
EOF
|
||||
|
||||
# Optionally inject project-specific workflow if it exists
|
||||
if [ -f ".blue/workflow.md" ]; then
|
||||
echo "<blue-project-workflow>"
|
||||
cat ".blue/workflow.md"
|
||||
echo "</blue-project-workflow>"
|
||||
fi
|
||||
19
hooks/pre-compact
Executable file
19
hooks/pre-compact
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
#!/bin/bash
|
||||
# Blue PreCompact Hook
|
||||
# Injects survival context BEFORE compaction so it enters the summary
|
||||
# This ensures Claude retains awareness of Blue after compaction
|
||||
|
||||
cat << 'EOF'
|
||||
<compaction-survival-context>
|
||||
## Critical Context for Post-Compaction
|
||||
|
||||
This project uses Blue MCP tools. After compaction, remember:
|
||||
|
||||
1. **MCP Tools Available**: blue_status, blue_next, blue_rfc_*, blue_worktree_*, blue_pr_*
|
||||
2. **SDLC Discipline**: Use worktrees for code changes, RFCs for planning
|
||||
3. **Task Sync**: Tasks with blue_rfc metadata sync to .plan.md files
|
||||
4. **Active State**: Run `blue_status` to see current RFC/worktree
|
||||
|
||||
If you notice workflow drift, run `blue_status` to restore context.
|
||||
</compaction-survival-context>
|
||||
EOF
|
||||
89
install.sh
89
install.sh
|
|
@ -58,9 +58,9 @@ if [ -f "$MCP_CONFIG" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Install Blue skills to Claude Code
|
||||
# Install Blue skills to Claude Code (symlink, not copy)
|
||||
SKILLS_DIR="$HOME/.claude/skills"
|
||||
BLUE_SKILLS_DIR="$(dirname "$0")/skills"
|
||||
BLUE_SKILLS_DIR="$(cd "$(dirname "$0")" && pwd)/skills"
|
||||
|
||||
if [ -d "$BLUE_SKILLS_DIR" ] && [ -d "$HOME/.claude" ]; then
|
||||
echo ""
|
||||
|
|
@ -70,15 +70,19 @@ if [ -d "$BLUE_SKILLS_DIR" ] && [ -d "$HOME/.claude" ]; then
|
|||
for skill in "$BLUE_SKILLS_DIR"/*; do
|
||||
if [ -d "$skill" ]; then
|
||||
skill_name=$(basename "$skill")
|
||||
cp -r "$skill" "$SKILLS_DIR/"
|
||||
echo " Installed skill: $skill_name"
|
||||
target="$SKILLS_DIR/$skill_name"
|
||||
# Remove existing symlink, file, or directory
|
||||
rm -rf "$target" 2>/dev/null
|
||||
ln -s "$skill" "$target"
|
||||
echo " Linked skill: $skill_name -> $skill"
|
||||
fi
|
||||
done
|
||||
|
||||
echo -e "${GREEN}Skills installed to $SKILLS_DIR${NC}"
|
||||
echo -e "${GREEN}Skills linked to $SKILLS_DIR${NC}"
|
||||
fi
|
||||
|
||||
# Install Blue hooks to Claude Code
|
||||
# Install Blue hooks to Claude Code (RFC 0041: write to settings.json, not hooks.json)
|
||||
SETTINGS_FILE="$HOME/.claude/settings.json"
|
||||
HOOKS_FILE="$HOME/.claude/hooks.json"
|
||||
BLUE_ROOT="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
|
|
@ -86,34 +90,59 @@ if [ -d "$HOME/.claude" ]; then
|
|||
echo ""
|
||||
echo "Configuring Blue hooks..."
|
||||
|
||||
# Create hooks.json if it doesn't exist
|
||||
if [ ! -f "$HOOKS_FILE" ]; then
|
||||
echo '{"hooks":{}}' > "$HOOKS_FILE"
|
||||
# Migrate hooks.json to settings.json if both exist (RFC 0041)
|
||||
if [ -f "$HOOKS_FILE" ] && [ -f "$SETTINGS_FILE" ]; then
|
||||
echo " Migrating hooks.json to settings.json..."
|
||||
if command -v jq &> /dev/null; then
|
||||
jq -s '.[0] * .[1]' "$SETTINGS_FILE" "$HOOKS_FILE" > "$SETTINGS_FILE.tmp" && mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
|
||||
mv "$HOOKS_FILE" "$HOOKS_FILE.migrated"
|
||||
echo -e " ${GREEN}Migration complete (old file: hooks.json.migrated)${NC}"
|
||||
else
|
||||
echo -e " ${RED}Install jq to migrate hooks.json${NC}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Update hooks using jq if available, otherwise create fresh
|
||||
# Ensure settings.json exists with hooks structure
|
||||
if [ ! -f "$SETTINGS_FILE" ]; then
|
||||
echo '{"hooks":{}}' > "$SETTINGS_FILE"
|
||||
fi
|
||||
|
||||
# Update hooks in settings.json using jq if available
|
||||
if command -v jq &> /dev/null; then
|
||||
jq --arg blue_root "$BLUE_ROOT" '.hooks.SessionStart.command = ($blue_root + "/hooks/session-start") | .hooks.SessionEnd.command = ($blue_root + "/target/release/blue session-end") | .hooks.PreToolUse.command = ($blue_root + "/target/release/blue session-heartbeat") | .hooks.PreToolUse.match = "blue_*"' "$HOOKS_FILE" > "$HOOKS_FILE.tmp" && mv "$HOOKS_FILE.tmp" "$HOOKS_FILE"
|
||||
echo -e "${GREEN}Hooks configured${NC}"
|
||||
jq --arg blue_root "$BLUE_ROOT" '
|
||||
.hooks.SessionStart = [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [{"type": "command", "command": ($blue_root + "/hooks/session-start")}]
|
||||
},
|
||||
{
|
||||
"matcher": "compact",
|
||||
"hooks": [{"type": "command", "command": ($blue_root + "/hooks/context-restore")}]
|
||||
}
|
||||
] |
|
||||
.hooks.PreCompact = [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [{"type": "command", "command": ($blue_root + "/hooks/pre-compact")}]
|
||||
}
|
||||
] |
|
||||
.hooks.PreToolUse = [
|
||||
{
|
||||
"matcher": "blue_*",
|
||||
"hooks": [{"type": "command", "command": "blue session-heartbeat"}]
|
||||
}
|
||||
] |
|
||||
.hooks.SessionEnd = [
|
||||
{
|
||||
"matcher": "",
|
||||
"hooks": [{"type": "command", "command": "blue session-end"}]
|
||||
}
|
||||
]
|
||||
' "$SETTINGS_FILE" > "$SETTINGS_FILE.tmp" && mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"
|
||||
echo -e "${GREEN}Hooks configured in settings.json${NC}"
|
||||
else
|
||||
# Fallback: write hooks directly
|
||||
cat > "$HOOKS_FILE" << EOF
|
||||
{
|
||||
"hooks": {
|
||||
"SessionStart": {
|
||||
"command": "$BLUE_ROOT/hooks/session-start"
|
||||
},
|
||||
"SessionEnd": {
|
||||
"command": "$BLUE_ROOT/target/release/blue session-end"
|
||||
},
|
||||
"PreToolUse": {
|
||||
"command": "$BLUE_ROOT/target/release/blue session-heartbeat",
|
||||
"match": "blue_*"
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
echo -e "${GREEN}Hooks configured (install jq for safer merging)${NC}"
|
||||
echo -e "${RED}jq is required for hook configuration${NC}"
|
||||
echo "Install jq: brew install jq (macOS) or apt install jq (Linux)"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue