wogiflow 2.22.2 → 2.22.4

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/lib/wogi-claude CHANGED
@@ -17,13 +17,63 @@
17
17
  # Opt-out: pass --no-wogi-restart to run claude once without the restart loop
18
18
  #
19
19
  # Environment:
20
- # WOGI_RESTART_FLAG — path to restart-flag file (default: <cwd>/.workflow/state/restart-requested)
21
- # WOGI_MAX_RESTARTS — safety cap, default 50 (prevents runaway restart storms)
22
- # WOGI_WRAPPER_PID — exported to child; hook checks this to confirm wrapper is present
23
- # WOGI_CLAUDE_BIN — override path to claude binary (default: found via PATH)
20
+ # WOGI_RESTART_FLAG — path to restart-flag file (default: <cwd>/.workflow/state/restart-requested)
21
+ # WOGI_MAX_RESTARTS — safety cap, default 50 (prevents runaway restart storms)
22
+ # WOGI_WRAPPER_PID — exported to child; hook checks this to confirm wrapper is present
23
+ # WOGI_CLAUDE_BIN — override path to claude binary (default: found via PATH)
24
+ # WOGI_USE_EXPECT — (EXPERIMENTAL, v2.22.4+) set to 1 to opt IN to the
25
+ # expect-based auto-dismiss of the "Loading development
26
+ # channels" dialog. OFF BY DEFAULT because Ink's
27
+ # ANSI-rich output can cause expect's text match to
28
+ # miss, which deadlocks the dialog (user keystrokes
29
+ # get held by expect, not forwarded to claude). If
30
+ # you can confirm it works for your terminal, opt in
31
+ # and enjoy zero-click restarts.
32
+ # WOGI_NO_EXPECT — legacy opt-out from 2.22.3. Still honored (forces
33
+ # expect off regardless of WOGI_USE_EXPECT).
34
+ # WOGI_EXPECT_TIMEOUT — override the expect timeout (default 30s) for watching
35
+ # the dialog. After timeout we hand off to the user
36
+ # unconditionally.
24
37
 
25
38
  set -u
26
39
 
40
+ # --- Resolve helper paths (for expect-based dialog auto-dismiss) ---
41
+ WOGI_CLAUDE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
42
+ WOGI_EXPECT_SCRIPT="$WOGI_CLAUDE_DIR/wogi-claude-expect.exp"
43
+
44
+ # Detect whether to use the expect wrapper (v2.22.4: OPT-IN only).
45
+ # Four conditions must all hold:
46
+ # 1. WOGI_USE_EXPECT=1 is explicitly set (opt-in)
47
+ # 2. WOGI_NO_EXPECT is NOT set (legacy escape hatch still honored)
48
+ # 3. `expect` is on PATH and the wogi-claude-expect.exp script exists
49
+ # 4. The args include --dangerously-load-development-channels (the only
50
+ # flag that triggers the dialog we want to auto-dismiss)
51
+ #
52
+ # 2.22.3 tried opt-out by default; in practice, expect's text match can miss
53
+ # Ink's ANSI-fragmented output, which deadlocks the dialog (user keystrokes
54
+ # get held in expect's buffer instead of reaching claude). 2.22.4 flips to
55
+ # opt-in so the default UX is predictable.
56
+ __wogi_use_expect=0
57
+ if [ "${WOGI_USE_EXPECT:-}" = "1" ] && [ -z "${WOGI_NO_EXPECT:-}" ] && \
58
+ command -v expect >/dev/null 2>&1 && [ -x "$WOGI_EXPECT_SCRIPT" ]; then
59
+ for arg in "$@"; do
60
+ if [ "$arg" = "--dangerously-load-development-channels" ]; then
61
+ __wogi_use_expect=1
62
+ break
63
+ fi
64
+ done
65
+ fi
66
+
67
+ # run_claude — invoke claude, routing through expect when we can auto-dismiss
68
+ # the dev-channels dialog. Preserves stdin/stdout/stderr exactly.
69
+ run_claude() {
70
+ if [ "$__wogi_use_expect" -eq 1 ]; then
71
+ expect "$WOGI_EXPECT_SCRIPT" "$CLAUDE_BIN" "$@"
72
+ else
73
+ "$CLAUDE_BIN" "$@"
74
+ fi
75
+ }
76
+
27
77
  # --- Opt-out path: no restart loop, just exec claude once ---
28
78
  for arg in "$@"; do
29
79
  if [ "$arg" = "--no-wogi-restart" ]; then
@@ -31,7 +81,11 @@ for arg in "$@"; do
31
81
  filtered=()
32
82
  for a in "$@"; do [ "$a" = "--no-wogi-restart" ] || filtered+=("$a"); done
33
83
  CLAUDE_BIN="${WOGI_CLAUDE_BIN:-claude}"
34
- exec "$CLAUDE_BIN" "${filtered[@]}"
84
+ if [ "$__wogi_use_expect" -eq 1 ]; then
85
+ exec expect "$WOGI_EXPECT_SCRIPT" "$CLAUDE_BIN" "${filtered[@]}"
86
+ else
87
+ exec "$CLAUDE_BIN" "${filtered[@]}"
88
+ fi
35
89
  fi
36
90
  done
37
91
 
@@ -66,7 +120,7 @@ while true; do
66
120
  rm -f "$FLAG_FILE"
67
121
  fi
68
122
 
69
- "$CLAUDE_BIN" "$@"
123
+ run_claude "$@"
70
124
  inner_exit=$?
71
125
 
72
126
  # If the user hit Ctrl+C (INT/TERM reached us), don't restart
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env expect
2
+ #
3
+ # wogi-claude-expect.exp — Auto-dismiss Claude Code's "Loading development
4
+ # channels" dialog so workspace worker restarts are truly seamless.
5
+ #
6
+ # Claude Code fires an interactive Ink dialog EVERY session when:
7
+ # - User is OAuth-authenticated to claude.ai
8
+ # - The CLI is launched with --dangerously-load-development-channels
9
+ #
10
+ # There's no Claude Code setting that persists an "accepted" state
11
+ # (verified via decompiled source 2026-04-17). So we intercept the dialog
12
+ # at the wrapper level: spawn claude in an expect-managed PTY, watch for
13
+ # the dialog title text, send Enter to accept the already-highlighted
14
+ # "I am using this for local development" option, then hand off control
15
+ # to the user via `interact`.
16
+ #
17
+ # Usage (invoked from lib/wogi-claude):
18
+ # expect wogi-claude-expect.exp /absolute/path/to/claude [args...]
19
+ #
20
+ # Disable at runtime: set WOGI_NO_EXPECT=1. The wrapper then execs claude
21
+ # directly and the user sees the dialog as before (manual single-click).
22
+
23
+ set timeout 30
24
+
25
+ # Allow WOGI_EXPECT_TIMEOUT override (rarely needed)
26
+ if {[info exists env(WOGI_EXPECT_TIMEOUT)]} {
27
+ set timeout $env(WOGI_EXPECT_TIMEOUT)
28
+ }
29
+
30
+ # Mirror claude's output to the user's terminal during dialog watch
31
+ log_user 1
32
+
33
+ # argv[0] is the claude binary path; rest are claude's args
34
+ if {[llength $argv] < 1} {
35
+ puts stderr "wogi-claude-expect.exp: missing claude binary path"
36
+ exit 2
37
+ }
38
+
39
+ set claude_bin [lindex $argv 0]
40
+ set claude_args [lrange $argv 1 end]
41
+
42
+ # Spawn claude in a pseudo-TTY so its Ink UI renders normally.
43
+ # eval is needed because claude_args is a list and spawn expects a
44
+ # flattened command line.
45
+ eval spawn $claude_bin $claude_args
46
+
47
+ # Watch for the DevChannels dialog title, then press Enter to accept
48
+ # the default-highlighted "I am using this for local development" option.
49
+ #
50
+ # On timeout or EOF: fall through to `interact`. If the dialog appears
51
+ # AFTER our timeout window, the user can still answer it manually —
52
+ # same failure mode as running claude directly.
53
+ expect {
54
+ -re "Loading development channels" {
55
+ # Let Ink finish rendering the dialog before sending Enter.
56
+ # Without this, the select-input component may not have bound
57
+ # its keyboard listener yet and the keystroke is dropped.
58
+ after 250
59
+ send "\r"
60
+ }
61
+ timeout { }
62
+ eof { exit }
63
+ }
64
+
65
+ # Hand off: user's keystrokes flow to claude, claude's output flows
66
+ # to the user's terminal. interact blocks until claude exits.
67
+ interact
68
+
69
+ # After claude exits, let the bash wrapper decide whether to restart.
70
+ # Pass through claude's exit status (expect sets it in $expect_out(-code)
71
+ # after `interact`, but a plain exit is sufficient since the wrapper
72
+ # only cares about the restart flag file, not exit code).
73
+ exit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wogiflow",
3
- "version": "2.22.2",
3
+ "version": "2.22.4",
4
4
  "description": "AI-powered development workflow management system with multi-model support",
5
5
  "main": "lib/index.js",
6
6
  "bin": {
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "scripts": {
12
12
  "flow": "./scripts/flow",
13
- "test": "NODE_ENV=test node --test tests/auto-compact-prompt.test.js tests/flow-paths.test.js tests/flow-io.test.js tests/flow-config-loader.test.js tests/flow-damage-control.test.js tests/flow-output.test.js tests/flow-constants.test.js tests/flow-session-state.test.js tests/flow-hooks-integration.test.js tests/flow-utils.test.js tests/flow-security.test.js tests/flow-memory-db.test.js tests/flow-durable-session.test.js tests/flow-skill-matcher.test.js tests/flow-bridge.test.js tests/flow-proactive-compact.test.js tests/flow-cascade-completion.test.js tests/flow-capture-gate.test.js tests/flow-correction-detector-hybrid.test.js tests/flow-promote.test.js tests/flow-archive-runs.test.js tests/flow-memory.test.js tests/flow-hooks-pre-tool-helpers.test.js tests/flow-hooks-bugfix-scope-gate.test.js tests/flow-hooks-routing-gate.test.js tests/flow-hooks-phase-read-gate.test.js tests/flow-hooks-commit-log-gate.test.js tests/flow-hooks-deploy-gate.test.js tests/flow-hooks-todowrite-gate.test.js tests/flow-hooks-git-safety-gate.test.js tests/flow-hooks-scope-mutation-gate.test.js tests/flow-hooks-strike-gate.test.js tests/flow-hooks-component-check.test.js tests/flow-hooks-scope-gate.test.js tests/flow-hooks-implementation-gate.test.js tests/flow-hooks-research-gate.test.js tests/flow-hooks-loop-check.test.js tests/flow-hooks-manager-boundary-gate.test.js tests/flow-hooks-phase-gate.test.js tests/flow-hooks-pre-tool-orchestrator.test.js tests/flow-hooks-observation-capture.test.js tests/flow-hooks-task-gate.test.js tests/flow-durable-session-suspension.test.js tests/flow-health-mcp-scopes.test.js tests/flow-lean-config.test.js tests/flow-workspace-autopickup.test.js tests/flow-worker-boundary-gate.test.js tests/flow-worker-question-classifier.test.js tests/flow-completion-truth-gate-contradictions.test.js tests/flow-structure-sensor.test.js tests/flow-workspace-dispatch-tracking.test.js tests/flow-story-gates.test.js tests/flow-workspace-restart-handoff.test.js && NODE_ENV=test node tests/run-quality-gates.test.js",
13
+ "test": "NODE_ENV=test node --test tests/auto-compact-prompt.test.js tests/flow-paths.test.js tests/flow-io.test.js tests/flow-config-loader.test.js tests/flow-damage-control.test.js tests/flow-output.test.js tests/flow-constants.test.js tests/flow-session-state.test.js tests/flow-hooks-integration.test.js tests/flow-utils.test.js tests/flow-security.test.js tests/flow-memory-db.test.js tests/flow-durable-session.test.js tests/flow-skill-matcher.test.js tests/flow-bridge.test.js tests/flow-proactive-compact.test.js tests/flow-cascade-completion.test.js tests/flow-capture-gate.test.js tests/flow-correction-detector-hybrid.test.js tests/flow-promote.test.js tests/flow-archive-runs.test.js tests/flow-memory.test.js tests/flow-hooks-pre-tool-helpers.test.js tests/flow-hooks-bugfix-scope-gate.test.js tests/flow-hooks-routing-gate.test.js tests/flow-hooks-phase-read-gate.test.js tests/flow-hooks-commit-log-gate.test.js tests/flow-hooks-deploy-gate.test.js tests/flow-hooks-todowrite-gate.test.js tests/flow-hooks-git-safety-gate.test.js tests/flow-hooks-scope-mutation-gate.test.js tests/flow-hooks-strike-gate.test.js tests/flow-hooks-component-check.test.js tests/flow-hooks-scope-gate.test.js tests/flow-hooks-implementation-gate.test.js tests/flow-hooks-research-gate.test.js tests/flow-hooks-loop-check.test.js tests/flow-hooks-manager-boundary-gate.test.js tests/flow-hooks-phase-gate.test.js tests/flow-hooks-pre-tool-orchestrator.test.js tests/flow-hooks-observation-capture.test.js tests/flow-hooks-task-gate.test.js tests/flow-durable-session-suspension.test.js tests/flow-health-mcp-scopes.test.js tests/flow-lean-config.test.js tests/flow-workspace-autopickup.test.js tests/flow-worker-boundary-gate.test.js tests/flow-worker-question-classifier.test.js tests/flow-completion-truth-gate-contradictions.test.js tests/flow-structure-sensor.test.js tests/flow-workspace-dispatch-tracking.test.js tests/flow-story-gates.test.js tests/flow-workspace-restart-handoff.test.js tests/flow-wogi-claude-wrapper.test.js && NODE_ENV=test node tests/run-quality-gates.test.js",
14
14
  "test:syntax": "find scripts/ lib/ -name '*.js' -not -path '*/node_modules/*' -exec node --check {} +",
15
15
  "lint": "eslint scripts/ lib/ tests/",
16
16
  "lint:ci": "eslint scripts/ lib/ tests/ --max-warnings 0",