deepflow 0.1.64 → 0.1.66

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.
Files changed (2) hide show
  1. package/bin/deepflow-auto.sh +113 -65
  2. package/package.json +1 -1
@@ -168,32 +168,28 @@ discover_specs() {
168
168
  # Context-monitored claude -p wrapper
169
169
  # ---------------------------------------------------------------------------
170
170
 
171
- # run_claude_monitored <working_dir> <prompt_text> [session_id]
171
+ # run_claude_monitored <working_dir> <prompt_text>
172
172
  #
173
173
  # Runs `claude -p --output-format stream-json` and monitors token usage in
174
174
  # real time. If usage reaches CONTEXT_THRESHOLD_PCT% of the context window the
175
- # process is killed and automatically restarted with `--resume <session_id>` so
176
- # it gets a fresh context window.
175
+ # process is killed and restarted with a fresh context (same prompt, clean
176
+ # session). Prior work persists in the worktree via committed files.
177
177
  #
178
178
  # The final result text is written to stdout. A side-effect context.json is
179
179
  # written to <working_dir>/.deepflow/context.json for statusline consumption.
180
180
  run_claude_monitored() {
181
181
  local working_dir="$1"
182
182
  local prompt_text="$2"
183
- local session_id="${3:-}"
184
183
 
185
184
  local result_tmp
186
185
  result_tmp="$(mktemp)"
187
186
  local error_log
188
187
  error_log="$(mktemp)"
189
188
 
190
- # Outer loop: may restart with --resume when threshold is hit
189
+ # Outer loop: restart with fresh context when threshold is hit
191
190
  while true; do
192
191
  # Build command arguments
193
192
  local -a cmd_args=(claude -p --output-format stream-json --dangerously-skip-permissions)
194
- if [[ -n "$session_id" ]]; then
195
- cmd_args+=(--resume --session-id "$session_id")
196
- fi
197
193
 
198
194
  # Accumulated token count and context window size across events
199
195
  local total_tokens=0
@@ -207,13 +203,8 @@ run_claude_monitored() {
207
203
  fifo_path="$(mktemp -u)"
208
204
  mkfifo "$fifo_path"
209
205
 
210
- if [[ -n "$session_id" ]]; then
211
- "${cmd_args[@]}" < /dev/null > "$fifo_path" 2>>"$error_log" &
212
- claude_pid=$!
213
- else
214
- echo "$prompt_text" | "${cmd_args[@]}" > "$fifo_path" 2>>"$error_log" &
215
- claude_pid=$!
216
- fi
206
+ echo "$prompt_text" | "${cmd_args[@]}" > "$fifo_path" 2>>"$error_log" &
207
+ claude_pid=$!
217
208
 
218
209
  # Read the FIFO line-by-line (set +e to tolerate EINTR from signals)
219
210
  local capturing_result=false
@@ -304,12 +295,10 @@ run_claude_monitored() {
304
295
  : > "$error_log"
305
296
  fi
306
297
 
307
- if [[ "$threshold_hit" == "true" && -n "$current_session_id" ]]; then
308
- # Restart with --resume and the captured session_id
309
- session_id="$current_session_id"
310
- total_tokens=0
311
- context_window=0
312
- auto_log "Restarting claude -p with --resume session_id=${session_id}"
298
+ if [[ "$threshold_hit" == "true" ]]; then
299
+ # Restart with fresh context the prompt is re-sent but prior work
300
+ # persists in the worktree (committed files, etc.)
301
+ auto_log "Restarting claude -p with fresh context (prior work is in worktree)"
313
302
  continue
314
303
  fi
315
304
 
@@ -1149,70 +1138,129 @@ generate_report() {
1149
1138
  # Build report
1150
1139
  # -----------------------------------------------------------------
1151
1140
  {
1152
- # Section 1: Resultado
1153
- echo "## Resultado"
1141
+ # Header
1142
+ echo "# deepflow auto report"
1154
1143
  echo ""
1155
- echo "Status: ${overall_status}"
1144
+ echo "**Status:** ${overall_status} "
1145
+ echo "**Date:** $(date -u '+%Y-%m-%d %H:%M UTC')"
1156
1146
  echo ""
1157
1147
 
1158
- # Winner info (if converged)
1159
- if [[ "$overall_status" == "converged" ]]; then
1160
- for sname in "${all_spec_names[@]}"; do
1161
- local w="$(_spec_get WINNER "$sname")"
1162
- if [[ -n "$w" ]]; then
1163
- local summary=""
1164
- local winner_file="${PROJECT_ROOT}/.deepflow/selection/${sname}-winner.json"
1165
- if [[ -f "$winner_file" ]]; then
1166
- summary="$(grep -o '"winner"[[:space:]]*:[[:space:]]*"[^"]*"' "$winner_file" | sed 's/.*"\([^"]*\)".*/\1/')" || summary=""
1148
+ # Per-spec details
1149
+ for sname in "${all_spec_names[@]}"; do
1150
+ local s="$(_spec_get STATUS "$sname" "unknown")"
1151
+ local w="$(_spec_get WINNER "$sname")"
1152
+
1153
+ echo "---"
1154
+ echo ""
1155
+ echo "## ${sname}"
1156
+ echo ""
1157
+ echo "**Status:** ${s}"
1158
+ if [[ -n "$w" ]]; then
1159
+ echo "**Winner:** ${w}"
1160
+ fi
1161
+ echo ""
1162
+
1163
+ # Hypotheses
1164
+ local hyp_file="${PROJECT_ROOT}/.deepflow/hypotheses/${sname}-cycle-0.json"
1165
+ if [[ -f "$hyp_file" ]]; then
1166
+ echo "### Hypotheses"
1167
+ echo ""
1168
+ # Parse each hypothesis slug + description
1169
+ local slug_list hyp_list
1170
+ slug_list="$(grep -o '"slug"[[:space:]]*:[[:space:]]*"[^"]*"' "$hyp_file" | sed 's/.*"\([^"]*\)".*/\1/')" || slug_list=""
1171
+ hyp_list="$(grep -o '"hypothesis"[[:space:]]*:[[:space:]]*"[^"]*"' "$hyp_file" | sed 's/.*"hypothesis"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/')" || hyp_list=""
1172
+
1173
+ paste <(echo "$slug_list") <(echo "$hyp_list") | while IFS=$'\t' read -r hslug hhyp; do
1174
+ [[ -z "$hslug" ]] && continue
1175
+ echo "- **${hslug}:** ${hhyp}"
1176
+ done
1177
+ echo ""
1178
+ fi
1179
+
1180
+ # Spike results
1181
+ local has_spikes=false
1182
+ for wt_dir in "${PROJECT_ROOT}/.deepflow/worktrees/${sname}-"*; do
1183
+ [[ -d "$wt_dir" ]] || continue
1184
+ local wt_slug
1185
+ wt_slug="$(basename "$wt_dir")"
1186
+ wt_slug="${wt_slug#${sname}-}"
1187
+
1188
+ local spike_yaml="${wt_dir}/.deepflow/results/spike-${wt_slug}.yaml"
1189
+ if [[ -f "$spike_yaml" ]]; then
1190
+ if [[ "$has_spikes" == "false" ]]; then
1191
+ echo "### Spike Results"
1192
+ echo ""
1193
+ has_spikes=true
1167
1194
  fi
1168
- echo "Winner: ${w} (spec: ${sname})"
1195
+ local spike_status spike_summary
1196
+ spike_status="$(grep -m1 '^status:' "$spike_yaml" | sed 's/^status:[[:space:]]*//')" || spike_status="unknown"
1197
+ spike_summary="$(grep -m1 '^summary:' "$spike_yaml" | sed 's/^summary:[[:space:]]*//')" || spike_summary=""
1198
+ local status_icon="✅"
1199
+ [[ "$spike_status" =~ fail ]] && status_icon="❌"
1200
+ echo "- ${status_icon} **${wt_slug}** — ${spike_summary}"
1169
1201
  fi
1170
1202
  done
1171
- echo ""
1172
- fi
1203
+ if [[ "$has_spikes" == "true" ]]; then
1204
+ echo ""
1205
+ fi
1173
1206
 
1174
- # Per-spec status table
1175
- echo "| Spec | Status | Winner |"
1176
- echo "|------|--------|--------|"
1177
- for sname in "${all_spec_names[@]}"; do
1178
- local s="$(_spec_get STATUS "$sname" "unknown")"
1179
- local w="$(_spec_get WINNER "$sname" "-")"
1180
- echo "| ${sname} | ${s} | ${w} |"
1181
- done
1182
- echo ""
1207
+ # Selection rationale
1208
+ local winner_file="${PROJECT_ROOT}/.deepflow/selection/${sname}-winner.json"
1209
+ if [[ -f "$winner_file" ]]; then
1210
+ echo "### Selection Rationale"
1211
+ echo ""
1183
1212
 
1184
- # Section 2: Mudancas
1185
- echo "## Mudancas"
1186
- echo ""
1213
+ # Parse rankings from winner file
1214
+ local rankings
1215
+ rankings="$(node -e "
1216
+ try {
1217
+ const d = JSON.parse(require('fs').readFileSync('${winner_file}','utf8'));
1218
+ if (d.selection_output && d.selection_output.rankings) {
1219
+ d.selection_output.rankings.forEach(r => {
1220
+ const icon = r.rank === 1 ? '🏆' : ' ';
1221
+ console.log(icon + ' **#' + r.rank + ' ' + r.slug + ':** ' + r.rationale);
1222
+ });
1223
+ }
1224
+ } catch(e) {}
1225
+ " 2>/dev/null)" || rankings=""
1226
+
1227
+ if [[ -n "$rankings" ]]; then
1228
+ echo "$rankings"
1229
+ fi
1230
+ echo ""
1231
+ fi
1187
1232
 
1188
- local has_changes=false
1189
- for sname in "${all_spec_names[@]}"; do
1190
- local w="$(_spec_get WINNER "$sname")"
1233
+ # Changes (git diff stat)
1191
1234
  if [[ -n "$w" ]]; then
1192
- has_changes=true
1193
1235
  local branch_name="df/${sname}-${w}"
1194
- echo "### ${sname} (winner: ${w})"
1236
+ echo "### Changes"
1195
1237
  echo ""
1196
1238
  echo '```'
1197
- git diff --stat "main...${branch_name}" 2>/dev/null || echo "(branch ${branch_name} not found)"
1239
+ git -C "$PROJECT_ROOT" diff --stat "main...${branch_name}" 2>/dev/null || echo "(branch ${branch_name} not found)"
1198
1240
  echo '```'
1199
1241
  echo ""
1200
1242
  fi
1201
1243
  done
1202
- if [[ "$has_changes" == "false" ]]; then
1203
- echo "No changes selected"
1204
- echo ""
1205
- fi
1206
1244
 
1207
- # Section 3: Decisoes
1208
- echo "## Decisoes"
1245
+ # Next steps
1246
+ echo "---"
1209
1247
  echo ""
1210
-
1211
- local decisions_log="${PROJECT_ROOT}/.deepflow/auto-decisions.log"
1212
- if [[ -f "$decisions_log" ]]; then
1213
- cat "$decisions_log"
1248
+ echo "## Next Steps"
1249
+ echo ""
1250
+ if [[ "$overall_status" == "converged" ]]; then
1251
+ for sname in "${all_spec_names[@]}"; do
1252
+ local w="$(_spec_get WINNER "$sname")"
1253
+ if [[ -n "$w" ]]; then
1254
+ echo "To merge the winner:"
1255
+ echo '```bash'
1256
+ echo "git merge df/${sname}-${w}"
1257
+ echo '```'
1258
+ fi
1259
+ done
1260
+ elif [[ "$overall_status" == "in-progress" ]]; then
1261
+ echo "Run \`deepflow auto --continue\` to resume."
1214
1262
  else
1215
- echo "No decisions logged"
1263
+ echo "Review the spec and run \`deepflow auto\` again."
1216
1264
  fi
1217
1265
  echo ""
1218
1266
  } > "$report_file"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepflow",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "description": "Stay in flow state - lightweight spec-driven task orchestration for Claude Code",
5
5
  "keywords": [
6
6
  "claude",