fix: feat: SessionStart compact hook re-injects phase protocol after context compaction (#274)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5c960f1b6e
commit
e3895ad3ac
7 changed files with 86 additions and 8 deletions
|
|
@ -218,6 +218,39 @@ create_agent_session() {
|
|||
fi
|
||||
rm -f "$exit_marker"
|
||||
|
||||
# Install SessionStart hook for context re-injection after compaction:
|
||||
# when Claude Code compacts context during long sessions, the phase protocol
|
||||
# instructions are lost. This hook fires after each compaction and outputs
|
||||
# the content of a context file so Claude retains critical instructions.
|
||||
# The context file is written by callers via write_compact_context().
|
||||
if [ -n "$phase_file" ]; then
|
||||
local compact_hook_script="${FACTORY_ROOT}/lib/hooks/on-compact-reinject.sh"
|
||||
if [ -x "$compact_hook_script" ]; then
|
||||
local context_file="${phase_file%.phase}.context"
|
||||
local compact_hook_cmd="${compact_hook_script} ${context_file}"
|
||||
if [ -f "$settings" ]; then
|
||||
jq --arg cmd "$compact_hook_cmd" '
|
||||
if (.hooks.SessionStart // [] | any(.[]; .hooks[]?.command == $cmd))
|
||||
then .
|
||||
else .hooks.SessionStart = (.hooks.SessionStart // []) + [{
|
||||
matcher: "compact",
|
||||
hooks: [{type: "command", command: $cmd}]
|
||||
}]
|
||||
end
|
||||
' "$settings" > "${settings}.tmp" && mv "${settings}.tmp" "$settings"
|
||||
else
|
||||
jq -n --arg cmd "$compact_hook_cmd" '{
|
||||
hooks: {
|
||||
SessionStart: [{
|
||||
matcher: "compact",
|
||||
hooks: [{type: "command", command: $cmd}]
|
||||
}]
|
||||
}
|
||||
}' > "$settings"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Install Stop hook for Matrix streaming: when MATRIX_THREAD_ID is set,
|
||||
# each Claude response is posted to the Matrix thread so humans can follow.
|
||||
local matrix_hook_script="${FACTORY_ROOT}/lib/hooks/on-stop-matrix.sh"
|
||||
|
|
@ -392,6 +425,16 @@ monitor_phase_loop() {
|
|||
done
|
||||
}
|
||||
|
||||
# Write context to a file for re-injection after context compaction.
|
||||
# The SessionStart compact hook reads this file and outputs it to stdout.
|
||||
# Args: phase_file content
|
||||
write_compact_context() {
|
||||
local phase_file="$1"
|
||||
local content="$2"
|
||||
local context_file="${phase_file%.phase}.context"
|
||||
printf '%s\n' "$content" > "$context_file"
|
||||
}
|
||||
|
||||
# Kill a tmux session gracefully (no-op if not found).
|
||||
agent_kill_session() {
|
||||
local session="${1:-}"
|
||||
|
|
|
|||
|
|
@ -202,6 +202,11 @@ run_formula_and_monitor() {
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Write phase protocol to context file for compaction survival
|
||||
if [ -n "${PROMPT_FOOTER:-}" ]; then
|
||||
write_compact_context "$PHASE_FILE" "$PROMPT_FOOTER"
|
||||
fi
|
||||
|
||||
agent_inject_into_session "$SESSION_NAME" "$PROMPT"
|
||||
log "Prompt sent to tmux session"
|
||||
matrix_send "$agent_name" "${agent_name^} session started for ${CODEBERG_REPO}" 2>/dev/null || true
|
||||
|
|
|
|||
15
lib/hooks/on-compact-reinject.sh
Executable file
15
lib/hooks/on-compact-reinject.sh
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
#!/bin/bash
|
||||
# on-compact-reinject.sh — SessionStart (compact) hook for dark-factory agent sessions.
|
||||
#
|
||||
# Called by Claude Code after context compaction. Reads a context file and
|
||||
# outputs its content to stdout, which Claude Code injects as system context.
|
||||
# No-op if the context file doesn't exist.
|
||||
#
|
||||
# Usage (in .claude/settings.json):
|
||||
# {"type": "command", "command": "this-script /tmp/dev-session-PROJECT-ISSUE.context"}
|
||||
#
|
||||
# Args: $1 = context file path
|
||||
|
||||
cat > /dev/null # consume hook JSON from stdin
|
||||
[ -n "${1:-}" ] && [ -f "$1" ] && cat "$1"
|
||||
exit 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue