Skip to content

Commit b48e99f

Browse files
authored
Merge pull request #272 from Fr-e-d/contrib/sync-1777568872
sync: update 2 file(s) in core/
2 parents ff1b28b + 4e7a2b6 commit b48e99f

2 files changed

Lines changed: 49 additions & 0 deletions

File tree

.gaai/core/scripts/daemon-monitor-tail.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,54 @@ parse_log() {
136136
last_text=$(printf '%s' "$last_event" | awk -F'\t' '{print $2}')
137137
last_model=$(printf '%s' "$last_event" | awk -F'\t' '{print $3}')
138138

139+
# ── Daemon-log fallback for nested-spawn events ──
140+
# When the orchestrator passed `--log-file <daemon log>` to nested-claude-spawn
141+
# (observed empirically — orchestrator substitutes $GAAI_DELIVERY_LOG_FILE for
142+
# daemon log path), the GLM/secondary subprocess writes its stream-json events
143+
# to the daemon log instead of the per-story log. The per-story panel here
144+
# would display stale orchestrator model unless we also peek at the daemon log.
145+
# Rule per founder 2026-04-30 19:08 BEL : sub-agent / spawned model always wins
146+
# over orchestrator in the display.
147+
local daemon_log="$PROJECT_DIR/.gaai/project/contexts/backlog/.delivery-daemon.log"
148+
if [[ -f "$daemon_log" ]]; then
149+
local daemon_event
150+
daemon_event=$(tail -400 "$daemon_log" 2>/dev/null \
151+
| grep '^{"type":"assistant"' 2>/dev/null \
152+
| jq -r '
153+
def clean: tostring | gsub("\n"; " ") | gsub(" +"; " ");
154+
def arg:
155+
if .name == "Bash" then (.input.command // "" | clean)
156+
elif .name == "Grep" then (.input.pattern // "" | clean)
157+
elif (.name == "Read" or .name == "Edit" or .name == "Write") then ((.input.file_path // "" | clean) | split("/") | .[-1] // "")
158+
elif .name == "Task" then (.input.description // "" | clean)
159+
elif .name == "TodoWrite" then "(todos updated)"
160+
else ((.input.description // .input.file_path // .input.command // "") | clean) end;
161+
. as $m |
162+
(($m.message.model // "") | tostring) as $model |
163+
$m.message.content[]? | select(.type=="tool_use") | "SUB" + "\t" + .name + " " + arg + "\t" + $model
164+
' 2>/dev/null | tail -1 || true)
165+
local daemon_model
166+
daemon_model=$(printf '%s' "$daemon_event" | awk -F'\t' '{print $3}')
167+
# Override main display when daemon log's most recent event is from a
168+
# different (non-orchestrator) model AND the daemon log was touched more
169+
# recently than the per-story log. Sub-agent / spawned model wins.
170+
if [[ -n "$daemon_model" ]] && [[ "$daemon_model" != "$last_model" ]]; then
171+
local daemon_mtime story_mtime
172+
if [[ "$(uname)" == "Darwin" ]]; then
173+
daemon_mtime=$(stat -f %m "$daemon_log" 2>/dev/null || echo 0)
174+
story_mtime=$(stat -f %m "$log_file" 2>/dev/null || echo 0)
175+
else
176+
daemon_mtime=$(stat -c %Y "$daemon_log" 2>/dev/null || echo 0)
177+
story_mtime=$(stat -c %Y "$log_file" 2>/dev/null || echo 0)
178+
fi
179+
if [[ "$daemon_mtime" -ge "$story_mtime" ]]; then
180+
last_origin="SUB"
181+
last_text=$(printf '%s' "$daemon_event" | awk -F'\t' '{print $2}')
182+
last_model="$daemon_model"
183+
fi
184+
fi
185+
fi
186+
139187
# ── Phase detection ──
140188
# Walk recent events, classify each Bash command / Write target into a phase tag,
141189
# keep the LAST non-empty classification — that's the current phase.

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
## [Unreleased]
1111

1212
### Changed
13+
- fix(monitor): sub-agent / spawned model wins in display
1314
- fix(workflow): remove --log-file flag from nested-claude-spawn invocation
1415

1516
## [2.22.0] - 2026-04-30

0 commit comments

Comments
 (0)