create-merlin-brain 3.4.8 → 3.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install.cjs +8 -6
- package/files/hooks/agent-sync.sh +6 -3
- package/files/hooks/post-edit-logger.sh +3 -1
- package/files/hooks/pre-edit-sights-check.sh +3 -1
- package/files/hooks/pre-edit-sights-enforce.md +9 -22
- package/files/hooks/session-end.sh +3 -1
- package/files/hooks/session-start-context.sh +23 -0
- package/files/hooks/session-start.sh +3 -1
- package/files/hooks/stop-check.md +10 -33
- package/files/hooks/subagent-context.sh +15 -3
- package/files/hooks/task-completed-verify.md +10 -11
- package/files/hooks/task-completed-verify.sh +3 -1
- package/files/hooks/teammate-idle-verify.sh +3 -1
- package/package.json +1 -1
package/bin/install.cjs
CHANGED
|
@@ -1005,19 +1005,21 @@ async function install() {
|
|
|
1005
1005
|
settings.hooks.TaskCompleted = settings.hooks.TaskCompleted || [];
|
|
1006
1006
|
settings.hooks.TaskCompleted = removeMerlinPromptHooks(settings.hooks.TaskCompleted);
|
|
1007
1007
|
|
|
1008
|
-
// Now add fresh prompt hooks in new format
|
|
1009
|
-
//
|
|
1010
|
-
|
|
1011
|
-
|
|
1008
|
+
// Now add fresh prompt/command hooks in new format
|
|
1009
|
+
// NOTE: SessionStart does NOT support prompt hooks (only command hooks).
|
|
1010
|
+
// The Merlin boot sequence is handled via CLAUDE.md instructions instead.
|
|
1011
|
+
// We use a command hook to inject additionalContext at session start.
|
|
1012
|
+
addHookIfMissing(settings.hooks.SessionStart, {
|
|
1013
|
+
hooks: [{ type: 'command', command: 'bash ~/.claude/hooks/session-start-context.sh' }]
|
|
1012
1014
|
});
|
|
1013
1015
|
|
|
1014
|
-
// Prompt-based PreToolUse hook:
|
|
1016
|
+
// Prompt-based PreToolUse hook: evaluate Sights check before edits
|
|
1015
1017
|
settings.hooks.PreToolUse.push({
|
|
1016
1018
|
matcher: 'Edit|Write',
|
|
1017
1019
|
hooks: [{ type: 'prompt', prompt: fs.readFileSync(path.join(HOOKS_DIR, 'pre-edit-sights-enforce.md'), 'utf8') }]
|
|
1018
1020
|
});
|
|
1019
1021
|
|
|
1020
|
-
// Prompt-based Stop hook:
|
|
1022
|
+
// Prompt-based Stop hook: evaluate whether stopping is appropriate
|
|
1021
1023
|
settings.hooks.Stop.push({
|
|
1022
1024
|
hooks: [{ type: 'prompt', prompt: fs.readFileSync(path.join(HOOKS_DIR, 'stop-check.md'), 'utf8') }]
|
|
1023
1025
|
});
|
|
@@ -2,19 +2,19 @@
|
|
|
2
2
|
# Merlin Hook: Agent Sync (SessionStart, background)
|
|
3
3
|
# Checks installed agents freshness and updates from cloud. Max once/hour.
|
|
4
4
|
set -euo pipefail
|
|
5
|
-
trap 'exit 0' ERR
|
|
5
|
+
trap 'echo "{}"; exit 0' ERR
|
|
6
6
|
|
|
7
7
|
AGENTS_DIR="${HOME}/.claude/agents"
|
|
8
8
|
MERLIN_DIR="${HOME}/.claude/merlin"
|
|
9
9
|
LAST_SYNC="${MERLIN_DIR}/.last-agent-sync"
|
|
10
10
|
API_URL="${MERLIN_API_URL:-https://api.merlin.build}"
|
|
11
11
|
|
|
12
|
-
[ -d "${AGENTS_DIR}" ] || exit 0
|
|
12
|
+
[ -d "${AGENTS_DIR}" ] || { echo '{}'; exit 0; }
|
|
13
13
|
|
|
14
14
|
# Skip if synced within the last hour
|
|
15
15
|
if [ -f "${LAST_SYNC}" ]; then
|
|
16
16
|
last=$(cat "${LAST_SYNC}" 2>/dev/null || echo "0")
|
|
17
|
-
[ $(($(date +%s) - last)) -lt 3600 ] && exit 0
|
|
17
|
+
[ $(($(date +%s) - last)) -lt 3600 ] && { echo '{}'; exit 0; }
|
|
18
18
|
fi
|
|
19
19
|
|
|
20
20
|
sync_agents() {
|
|
@@ -41,4 +41,7 @@ sync_agents() {
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
sync_agents &
|
|
44
|
+
|
|
45
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
46
|
+
echo '{}'
|
|
44
47
|
exit 0
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Always exits 0 — never blocks Claude Code.
|
|
6
6
|
#
|
|
7
7
|
set -euo pipefail
|
|
8
|
-
trap 'exit 0' ERR
|
|
8
|
+
trap 'echo "{}"; exit 0' ERR
|
|
9
9
|
|
|
10
10
|
HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
@@ -30,4 +30,6 @@ fi
|
|
|
30
30
|
# Log file change event
|
|
31
31
|
log_event "file_changed" "$(printf '{"file":"%s","tool":"%s"}' "${file_path:-unknown}" "${tool_name:-unknown}")"
|
|
32
32
|
|
|
33
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
34
|
+
echo '{}'
|
|
33
35
|
exit 0
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Advisory only — always exits 0, never blocks edits.
|
|
6
6
|
#
|
|
7
7
|
set -euo pipefail
|
|
8
|
-
trap 'exit 0' ERR
|
|
8
|
+
trap 'echo "{}"; exit 0' ERR
|
|
9
9
|
|
|
10
10
|
HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
@@ -35,4 +35,6 @@ fi
|
|
|
35
35
|
# Log the pre-edit event
|
|
36
36
|
log_event "pre_edit" "$(printf '{"file":"%s"}' "${file_path:-unknown}")"
|
|
37
37
|
|
|
38
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
39
|
+
echo '{}'
|
|
38
40
|
exit 0
|
|
@@ -1,25 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
You are evaluating whether a file edit should proceed. Context: $ARGUMENTS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Check: Has the assistant recently called merlin_get_context, merlin_find_files, or merlin_search for this file's area in the current conversation? Look at recent tool calls in the transcript.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
If
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
3. Check if similar code already exists (don't duplicate)
|
|
10
|
-
4. THEN proceed with the edit
|
|
5
|
+
Rules:
|
|
6
|
+
- If Sights was consulted recently (within the last few messages) for this area: allow the edit
|
|
7
|
+
- If this is a minor/trivial edit (formatting, typo fix, small change): allow the edit
|
|
8
|
+
- If this is a significant edit and Sights was NOT consulted: suggest checking first
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
- Naming conventions — match existing patterns
|
|
16
|
-
- Testing requirements — note if tests are needed
|
|
17
|
-
|
|
18
|
-
## Required: Show Your Work
|
|
19
|
-
After the Sights check, show a brief line so the user sees Merlin is involved:
|
|
20
|
-
```
|
|
21
|
-
Merlin | Checked [area] | [what you found or "clear to edit"]
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
## Never Skip This
|
|
25
|
-
Every edit should be informed by codebase knowledge. This is what makes Merlin sessions better than raw Claude sessions. The user chose Merlin for a reason — deliver on it.
|
|
10
|
+
Respond with ONLY valid JSON, no other text:
|
|
11
|
+
- Allow the edit: {"ok": true}
|
|
12
|
+
- Suggest Sights check first: {"ok": false, "reason": "Call merlin_get_context before editing this file to check for existing patterns and conventions"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Always exits 0 — never blocks Claude Code shutdown.
|
|
6
6
|
#
|
|
7
7
|
set -euo pipefail
|
|
8
|
-
trap 'exit 0' ERR
|
|
8
|
+
trap 'echo "{}"; exit 0' ERR
|
|
9
9
|
|
|
10
10
|
HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
@@ -24,4 +24,6 @@ if command -v merlin >/dev/null 2>&1; then
|
|
|
24
24
|
merlin save-checkpoint "Session ended" >/dev/null 2>&1 &
|
|
25
25
|
fi
|
|
26
26
|
|
|
27
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
28
|
+
echo '{}'
|
|
27
29
|
exit 0
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
#
|
|
3
|
+
# Merlin Hook: SessionStart (context injection)
|
|
4
|
+
# Injects Merlin identity context into the session via additionalContext.
|
|
5
|
+
# Uses the SessionStart command hook JSON output format.
|
|
6
|
+
# Always exits 0 — never blocks Claude Code startup.
|
|
7
|
+
#
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
trap 'echo "{}"; exit 0' ERR
|
|
10
|
+
|
|
11
|
+
# Output additionalContext JSON for Claude to see at session start.
|
|
12
|
+
# This reminds Claude it's a Merlin-powered session.
|
|
13
|
+
# Full boot instructions are in CLAUDE.md — this is a lightweight nudge.
|
|
14
|
+
cat <<'CONTEXT_JSON'
|
|
15
|
+
{
|
|
16
|
+
"hookSpecificOutput": {
|
|
17
|
+
"hookEventName": "SessionStart",
|
|
18
|
+
"additionalContext": "You are a Merlin-powered session. Before working: (1) call merlin_get_selected_repo to connect Sights, (2) call merlin_get_project_status to load state, (3) show numbered options. Check Sights before every edit. Route complex tasks to specialists via /merlin:route. Save checkpoints before stopping."
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
CONTEXT_JSON
|
|
22
|
+
|
|
23
|
+
exit 0
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Always exits 0 — never blocks Claude Code startup.
|
|
6
6
|
#
|
|
7
7
|
set -euo pipefail
|
|
8
|
-
trap 'exit 0' ERR
|
|
8
|
+
trap 'echo "{}"; exit 0' ERR
|
|
9
9
|
|
|
10
10
|
HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
@@ -28,4 +28,6 @@ if command -v merlin >/dev/null 2>&1; then
|
|
|
28
28
|
record_sights_call
|
|
29
29
|
fi
|
|
30
30
|
|
|
31
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
32
|
+
echo '{}'
|
|
31
33
|
exit 0
|
|
@@ -1,36 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
You are evaluating whether Claude should stop working. Analyze the conversation context: $ARGUMENTS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Check these criteria:
|
|
4
|
+
1. Did the user's most recent request get fully addressed?
|
|
5
|
+
2. Are there any obvious errors or broken code that should be fixed before stopping?
|
|
6
|
+
3. Did Claude mention follow-up tasks it intended to complete but hasn't done yet?
|
|
4
7
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
- Stage and commit with a clear message
|
|
8
|
-
- Run `merlin_run_verification` before committing
|
|
8
|
+
IMPORTANT: This is NOT about saving checkpoints or showing summaries — those are handled elsewhere.
|
|
9
|
+
Only evaluate whether the core work is done.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
- What's left to do
|
|
14
|
-
- Any blockers or decisions made
|
|
15
|
-
This lets the next session (or another agent) pick up exactly where you left off.
|
|
16
|
-
|
|
17
|
-
## 3. Session Summary
|
|
18
|
-
Show the user a brief summary:
|
|
19
|
-
```
|
|
20
|
-
Merlin | Session Complete
|
|
21
|
-
- [X] files changed
|
|
22
|
-
- [Y] Sights queries made
|
|
23
|
-
- [Z] tasks completed
|
|
24
|
-
- Checkpoint saved: [yes/no]
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## 4. Next Steps
|
|
28
|
-
Always end with what should happen next:
|
|
29
|
-
```
|
|
30
|
-
Next session:
|
|
31
|
-
[1] Continue with [next task]
|
|
32
|
-
[2] Review what was built
|
|
33
|
-
[3] [other relevant option]
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
Do NOT stop without saving checkpoint. The user trusts Merlin to maintain continuity across sessions.
|
|
11
|
+
Respond with ONLY valid JSON, no other text:
|
|
12
|
+
- If stopping is appropriate: {"ok": true}
|
|
13
|
+
- If Claude should continue: {"ok": false, "reason": "brief explanation of what's unfinished"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Advisory only — always exits 0, never blocks subagent startup.
|
|
6
6
|
#
|
|
7
7
|
set -euo pipefail
|
|
8
|
-
trap 'exit 0' ERR
|
|
8
|
+
trap 'echo "{}"; exit 0' ERR
|
|
9
9
|
|
|
10
10
|
HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
@@ -28,9 +28,21 @@ fi
|
|
|
28
28
|
# Log subagent start event
|
|
29
29
|
log_event "subagent_start" "$(printf '{"task":"%s"}' "${task_desc:-unknown}")"
|
|
30
30
|
|
|
31
|
-
# If Merlin CLI available, fetch
|
|
31
|
+
# If Merlin CLI available, fetch context for the task and output as JSON
|
|
32
32
|
if [ -n "$task_desc" ] && command -v merlin >/dev/null 2>&1; then
|
|
33
|
-
merlin context "$task_desc" 2>/dev/null || true
|
|
33
|
+
context_text=$(merlin context "$task_desc" 2>/dev/null || true)
|
|
34
|
+
if [ -n "$context_text" ]; then
|
|
35
|
+
# Output as proper JSON additionalContext for the subagent
|
|
36
|
+
# Use jq if available, otherwise output empty JSON (context is best-effort)
|
|
37
|
+
if command -v jq >/dev/null 2>&1; then
|
|
38
|
+
jq -n --arg ctx "$context_text" '{hookSpecificOutput:{hookEventName:"SubagentStart",additionalContext:$ctx}}'
|
|
39
|
+
else
|
|
40
|
+
echo '{}'
|
|
41
|
+
fi
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
34
44
|
fi
|
|
35
45
|
|
|
46
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
47
|
+
echo '{}'
|
|
36
48
|
exit 0
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
You are evaluating whether a task should be marked as completed. Context: $ARGUMENTS
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Check these criteria:
|
|
4
|
+
1. Was the task's stated objective accomplished based on the conversation?
|
|
5
|
+
2. Were there any errors or test failures mentioned that haven't been resolved?
|
|
6
|
+
3. Is the implementation reasonably complete (not a half-finished skeleton)?
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
Be lenient — don't block completion for minor issues like missing docs or style nits.
|
|
9
|
+
Only block if the core objective clearly wasn't met or there are unresolved errors.
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
4. **Documentation**: If the task added new APIs or features, are they documented?
|
|
12
|
-
|
|
13
|
-
If all verifications pass, allow task completion.
|
|
14
|
-
If issues are found, list them and suggest fixes before completing.
|
|
11
|
+
Respond with ONLY valid JSON, no other text:
|
|
12
|
+
- Task is complete: {"ok": true}
|
|
13
|
+
- Task is not complete: {"ok": false, "reason": "brief explanation of what's unfinished"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Informational only — always exits 0 for v1.
|
|
6
6
|
#
|
|
7
7
|
set -euo pipefail
|
|
8
|
-
trap 'exit 0' ERR
|
|
8
|
+
trap 'echo "{}"; exit 0' ERR
|
|
9
9
|
|
|
10
10
|
HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
@@ -43,4 +43,6 @@ if [ -f "tsconfig.json" ] && command -v npx >/dev/null 2>&1; then
|
|
|
43
43
|
fi
|
|
44
44
|
fi
|
|
45
45
|
|
|
46
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
47
|
+
echo '{}'
|
|
46
48
|
exit 0
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# Advisory only — always exits 0, never blocks teammates.
|
|
6
6
|
#
|
|
7
7
|
set -euo pipefail
|
|
8
|
-
trap 'exit 0' ERR
|
|
8
|
+
trap 'echo "{}"; exit 0' ERR
|
|
9
9
|
|
|
10
10
|
HOOKS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
@@ -38,4 +38,6 @@ if command -v npm >/dev/null 2>&1; then
|
|
|
38
38
|
npm run build --if-present >/dev/null 2>&1 || true
|
|
39
39
|
fi
|
|
40
40
|
|
|
41
|
+
# Claude Code command hooks must output valid JSON to stdout
|
|
42
|
+
echo '{}'
|
|
41
43
|
exit 0
|
package/package.json
CHANGED