Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(observer): repair daemon boot (stale resolver name) and close analysis stdin (#2452)#2464

Open
mc856 wants to merge 1 commit into
affaan-m:mainfrom
mc856:fix/observer-homunculus-resolver
Open

fix(observer): repair daemon boot (stale resolver name) and close analysis stdin (#2452)#2464
mc856 wants to merge 1 commit into
affaan-m:mainfrom
mc856:fix/observer-homunculus-resolver

Conversation

@mc856

@mc856 mc856 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • fix the all-platform observer boot regression: start-observer.sh:40 still called _ecc_resolve_homunculus_dir, but the shared lib was renamed to _clv2_resolve_homunculus_dir (observe.sh, detect-project.sh, and migrate-homunculus.sh were updated; start-observer.sh was missed) — under set -e every launch dies with exit 127, so this breaks daemon boot everywhere, not only on Windows
  • close stdin (< /dev/null) on the backgrounded analysis claude call in observer-loop.sh: on Git Bash/MSYS2 the child inherits an open stdin, waits on it, warns "no stdin data received", and exits 1 before reading the analysis file; this is the only backgrounded claude call site in the repo
  • keep the -p prompt flag rather than reverting to a stdin redirect, preserving the Windows-compat decision from [Windows] Observer Haiku agent cannot read temp files and never writes instinct files #842 (the fix suggested in continuous-learning-v2 observer broken on Windows/Git Bash: daemon boot + analysis both fail (two regressions) #2452 would undo it)
  • add two source invariant guards to tests/hooks/hooks.test.js: every *_resolve_homunculus_dir call site must match a function the shared lib defines, and the backgrounded claude call must close stdin

Verification

  • pre-fix repro on macOS: start-observer.sh status dies with line 40: _ecc_resolve_homunculus_dir: command not found, exit 127
  • post-fix: full start → status → stop cycle completes in a sandboxed CLV2_HOMUNCULUS_DIR
  • node tests/run-all.js on node 22: 2973 passed, 0 failed
  • shellcheck on both scripts: only two pre-existing info-level findings on untouched lines
  • note: no Windows machine available — bug 1 is verified end-to-end on macOS (it is platform-independent); bug 2's fix is the standard stdin-close idiom and is behavior-neutral on macOS/Linux, but has not been exercised on Git Bash

Fixes #2452

…lysis stdin (affaan-m#2452)

Two continuous-learning-v2 observer regressions reported in affaan-m#2452:

- start-observer.sh still called _ecc_resolve_homunculus_dir, but the
  shared lib was renamed to _clv2_resolve_homunculus_dir (with observe.sh
  and detect-project.sh updated, start-observer.sh missed). Under set -e
  every launch dies with exit 127 at line 40 - daemon boot is broken on
  all platforms, not just Windows.
- observer-loop.sh backgrounds the analysis claude call with stdin left
  open; on Git Bash/MSYS2 the child inherits it, waits, warns 'no stdin
  data received', and exits 1 before reading the analysis file. Close
  stdin with </dev/null while keeping the -p prompt flag, preserving the
  Windows-compat decision from affaan-m#842 instead of reverting to a stdin
  redirect.

Adds two source invariant guards to tests/hooks/hooks.test.js: every
*_resolve_homunculus_dir call site must match a function the shared lib
defines, and the backgrounded claude call must close stdin.

Fixes affaan-m#2452
@mc856 mc856 requested a review from affaan-m as a code owner July 6, 2026 17:50
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7ea51654-65cc-46cb-8a57-0abbe7f1921f

📥 Commits

Reviewing files that changed from the base of the PR and between 4130457 and f8fbe40.

📒 Files selected for processing (3)
  • skills/continuous-learning-v2/agents/observer-loop.sh
  • skills/continuous-learning-v2/agents/start-observer.sh
  • tests/hooks/hooks.test.js
📜 Recent review details
⏰ Context from checks skipped due to timeout. (28)
  • GitHub Check: Greptile Review
  • GitHub Check: Test (ubuntu-latest, Node 20.x, yarn)
  • GitHub Check: Test (macos-latest, Node 22.x, bun)
  • GitHub Check: Test (ubuntu-latest, Node 20.x, bun)
  • GitHub Check: Test (macos-latest, Node 22.x, npm)
  • GitHub Check: Test (macos-latest, Node 20.x, yarn)
  • GitHub Check: Test (ubuntu-latest, Node 20.x, pnpm)
  • GitHub Check: Test (windows-latest, Node 18.x, yarn)
  • GitHub Check: Test (windows-latest, Node 20.x, yarn)
  • GitHub Check: Test (ubuntu-latest, Node 18.x, yarn)
  • GitHub Check: Test (macos-latest, Node 18.x, npm)
  • GitHub Check: Test (macos-latest, Node 18.x, pnpm)
  • GitHub Check: Test (windows-latest, Node 20.x, pnpm)
  • GitHub Check: Test (windows-latest, Node 22.x, yarn)
  • GitHub Check: Test (windows-latest, Node 22.x, npm)
  • GitHub Check: Test (windows-latest, Node 22.x, pnpm)
  • GitHub Check: Test (ubuntu-latest, Node 22.x, pnpm)
  • GitHub Check: Test (windows-latest, Node 18.x, npm)
  • GitHub Check: Test (windows-latest, Node 20.x, npm)
  • GitHub Check: Test (windows-latest, Node 18.x, pnpm)
  • GitHub Check: Test (ubuntu-latest, Node 18.x, pnpm)
  • GitHub Check: Test (ubuntu-latest, Node 22.x, npm)
  • GitHub Check: Test (ubuntu-latest, Node 22.x, yarn)
  • GitHub Check: Test (ubuntu-latest, Node 18.x, bun)
  • GitHub Check: Test (ubuntu-latest, Node 18.x, npm)
  • GitHub Check: Test (ubuntu-latest, Node 22.x, bun)
  • GitHub Check: Test (ubuntu-latest, Node 20.x, npm)
  • GitHub Check: Coverage
🧰 Additional context used
📓 Path-based instructions (16)
**/*.sh

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Before running shell commands, explain destructive or networked actions and prefer read-only inspection first

Files:

  • skills/continuous-learning-v2/agents/start-observer.sh
  • skills/continuous-learning-v2/agents/observer-loop.sh
skills/**

📄 CodeRabbit inference engine (AGENTS.md)

skills/ is the canonical workflow surface, so new workflow contributions should be added there first.

Files:

  • skills/continuous-learning-v2/agents/start-observer.sh
  • skills/continuous-learning-v2/agents/observer-loop.sh
{skills,commands,agents,rules}/**

⚙️ CodeRabbit configuration file

{skills,commands,agents,rules}/**: Focus on prompt-injection resilience, tool-permission scope, destructive action guards, and secret exfiltration risks.

Files:

  • skills/continuous-learning-v2/agents/start-observer.sh
  • skills/continuous-learning-v2/agents/observer-loop.sh
**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}

📄 CodeRabbit inference engine (.cursor/rules/common-coding-style.md)

**/*.{js,ts,jsx,tsx,py,java,cs,go,rb,php,scala,kt}: Always create new objects, never mutate existing ones. Use immutable patterns to prevent hidden side effects and enable safe concurrency
Organize code into many small files (200-400 lines typical, 800 lines max) organized by feature/domain rather than by type
Always handle errors explicitly at every level and never silently swallow errors
Always validate all user input before processing at system boundaries
Use schema-based validation where available
Fail fast with clear error messages when validation fails
Never trust external data (API responses, user input, file content)
Ensure code is readable and well-named
Keep functions small (less than 50 lines)
Keep files focused (less than 800 lines)
Avoid deep nesting (more than 4 levels)
Do not use hardcoded values; use constants or configuration instead

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

No hardcoded secrets (API keys, passwords, tokens) - validate before any commit

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php}: All user inputs must be validated
Enable CSRF protection on all state-changing endpoints
Verify authentication and authorization for all protected endpoints
Implement rate limiting on all endpoints to prevent abuse
Ensure error messages do not leak sensitive data in responses

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,sql}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

Use parameterized queries to prevent SQL injection

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,jsx,tsx,html,php,java,cs,rb,go}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

Implement XSS prevention by sanitizing HTML output

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,jsx,tsx,py,java,cs,rb,go,php,swift,kt,rs,c,cpp,h,hpp,properties,yml,yaml,json,env,config}

📄 CodeRabbit inference engine (.cursor/rules/common-security.md)

NEVER hardcode secrets in source code - ALWAYS use environment variables or a secret manager

Files:

  • tests/hooks/hooks.test.js
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/typescript-coding-style.md)

**/*.{ts,tsx,js,jsx}: Use spread operator for immutable updates in TypeScript/JavaScript instead of direct mutation
Use async/await with try-catch for error handling in TypeScript/JavaScript
Use Zod for schema-based input validation in TypeScript/JavaScript
No console.log statements in production code; use proper logging libraries instead

**/*.{ts,tsx,js,jsx}: Auto-format JavaScript/TypeScript files using Prettier after edit
Warn about console.log statements in edited files
Check all modified files for console.log statements before session ends

**/*.{ts,tsx,js,jsx}: Use the ApiResponse interface pattern with generic type parameter: interface ApiResponse<T> { success: boolean; data?: T; error?: string; meta?: { total: number; page: number; limit: number; } }
Implement custom React hooks following the pattern: export a named function with use prefix, generic type parameters, and proper useEffect cleanup for side effects

**/*.{ts,tsx,js,jsx}: Never hardcode secrets; always use environment variables for sensitive credentials like API keys
Throw an error when required environment variables are not configured to fail fast and ensure security prerequisites are met

Use Playwright as the E2E testing framework for critical user flows in TypeScript/JavaScript

Files:

  • tests/hooks/hooks.test.js
**/*.{test,spec}.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{test,spec}.{js,ts,jsx,tsx}: Write tests before implementation (test-driven development); target 80%+ coverage
Achieve minimum 80% test coverage across all three layers: Unit, Integration, and E2E
Use AAA structure (Arrange / Act / Assert) in tests with descriptive test names that explain behavior under test

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,ts,jsx,tsx}: Always create new objects and never mutate in place; return new copies instead
Keep files between 200–400 lines typical, with a maximum of 800 lines
Extract helpers when a file exceeds 200 lines
Handle errors explicitly at every level; never swallow errors silently
Validate all user input before processing; use schema-based validation where available
Never trust external data (API responses, file content, query params); always validate
All user inputs must be validated and sanitized
Error messages must be scrubbed of sensitive internals
Use readable, well-named identifiers in all code
Keep functions under 50 lines
Keep files under 800 lines
Avoid nesting deeper than 4 levels
Implement comprehensive error handling in all code
Do not hardcode values; use constants or environment configuration instead
Do not use in-place mutation; always return new objects or state

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,jsx,tsx,json,env*}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Do not hardcode secrets, API keys, passwords, or tokens

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{js,ts}: Use parameterized queries for all database writes (no string interpolation)
Auth/authz must be checked server-side for every sensitive path
Rate limiting must be applied to all public endpoints

Files:

  • tests/hooks/hooks.test.js
**/*.{jsx,tsx,js,ts}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

HTML output must be sanitized where applicable

Files:

  • tests/hooks/hooks.test.js
**/*.{js,ts,env*}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Required environment variables must be validated at startup

Files:

  • tests/hooks/hooks.test.js
🧠 Learnings (1)
📚 Learning: 2026-06-27T23:49:19.839Z
Learnt from: gaurav0107
Repo: affaan-m/ECC PR: 2373
File: tests/hooks/observe-signal-timeout.test.js:0-0
Timestamp: 2026-06-27T23:49:19.839Z
Learning: In tests under tests/hooks that require a Python runtime to run, the test should fail fast when Python isn’t available (or prerequisites aren’t met). Do not treat a missing Python runtime as test.skip, as an expected/allowed condition, or as a passing state; instead, explicitly fail (e.g., throw/return a rejected promise or use a test runner fail/expect that marks the test as failed) so reviewers can’t accidentally mask environment issues.

Applied to files:

  • tests/hooks/hooks.test.js
🪛 ast-grep (0.44.1)
tests/hooks/hooks.test.js

[warning] 3173-3173: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(path.join(skillRoot, 'scripts', 'lib', 'homunculus-dir.sh'), 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename)


[warning] 3184-3184: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(path.join(skillRoot, ...rel), 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename)


[warning] 3196-3196: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(path.join(__dirname, '..', '..', 'skills', 'continuous-learning-v2', 'agents', 'observer-loop.sh'), 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename)

🔇 Additional comments (4)
tests/hooks/hooks.test.js (2)

3195-3204: 🎯 Functional Correctness

Static-analysis path-traversal warning is a false positive.

The flagged fs.readFileSync(path.join(__dirname, ...)) call uses only hardcoded literal path segments in a test file — no external or user-controlled input reaches the path. Safe to ignore.


3171-3194: LGTM! Good regression coverage for the stale-resolver bug — validates caller names against the actual definitions in homunculus-dir.sh rather than hardcoding an expected function name.

skills/continuous-learning-v2/agents/start-observer.sh (1)

40-40: LGTM!

skills/continuous-learning-v2/agents/observer-loop.sh (1)

251-260: LGTM!


📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • Improved background observer reliability by ensuring non-interactive analysis runs don’t hang or exit early on Git Bash/MSYS2.
    • Updated observer startup to use the current configuration directory resolver, helping prevent mismatched path resolution.
  • Tests

    • Added regression coverage for resolver-name consistency across observer-related scripts.
    • Added a check that confirms analysis calls close inherited stdin as expected.

Walkthrough

Fixes two Windows/Git Bash regressions in the continuous-learning-v2 observer: start-observer.sh now calls the correct _clv2_resolve_homunculus_dir function, and observer-loop.sh closes inherited stdin on its backgrounded claude analysis call. Adds two regression tests.

Changes

Observer daemon and analysis fixes

Layer / File(s) Summary
Resolver function name fix
skills/continuous-learning-v2/agents/start-observer.sh
CONFIG_DIR now derives from _clv2_resolve_homunculus_dir instead of the non-existent _ecc_resolve_homunculus_dir, fixing daemon boot failure.
stdin closure on backgrounded claude call
skills/continuous-learning-v2/agents/observer-loop.sh
The backgrounded claude --print invocation in analyze_observations now redirects stdin from /dev/null, preventing premature exit on Git Bash/MSYS2 due to inherited stdin.
Regression tests for both fixes
tests/hooks/hooks.test.js
New tests verify observer scripts only call resolver function names defined in homunculus-dir.sh, and that observer-loop.sh closes stdin on the backgrounded claude call.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • affaan-m/ECC#2062: Also modifies the claude subprocess invocation in observer-loop.sh's analyze_observations, changing max_turns handling.
  • affaan-m/ECC#2386: Also modifies analyze_observations in observer-loop.sh, changing control flow around archiving observations after claude exit.
  • affaan-m/ECC#2390: Also modifies the claude invocation in analyze_observations, switching the --model argument.

Suggested reviewers: affaan-m, daltino

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main fixes: stale resolver call, stdin closure for the analysis subprocess, and the linked issue reference.
Description check ✅ Passed The description accurately summarizes the resolver fix, stdin closure, tests, and the preserved -p behavior.
Linked Issues check ✅ Passed The PR fixes both regressions, preserves -p, and adds the requested invariant tests, matching #2452.
Out of Scope Changes check ✅ Passed The diff stays within the observer boot, analysis, and regression-test scope; no unrelated changes are shown.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR patches two distinct daemon-boot regressions in the continuous-learning-v2 observer: a stale function name that prevented every launch under set -e, and an open-stdin inheritance problem that caused the backgrounded analysis call to hang on Git Bash. Two invariant tests are added to prevent both classes of regression from recurring silently.

  • start-observer.sh: Renames the stale _ecc_resolve_homunculus_dir call to _clv2_resolve_homunculus_dir, matching the actual export in homunculus-dir.sh and eliminating the exit-127 boot failure on all platforms.
  • observer-loop.sh: Adds < /dev/null to the backgrounded claude invocation so Git Bash/MSYS2 children do not inherit an open stdin and hang; change is behavior-neutral on POSIX systems.
  • tests/hooks/hooks.test.js: Adds two regression guards — one verifying resolver-name consistency across all caller scripts, one asserting stdin is closed on the backgrounded claude call (though the latter uses a brittle literal substring match).

Confidence Score: 4/5

The two shell fixes are minimal, correct, and well-targeted; the only thing to watch is the fragility of the literal-string assertion added to guard the stdin fix.

Both shell changes are straightforward and verified against the shared library source. The stdin-closure test in hooks.test.js checks for an exact positional substring rather than the presence of the redirect anywhere in the backgrounded-claude command block, so harmless reformatting of that line could either trip the guard unnecessarily or — if the redirect moves to a still-effective but differently-positioned location — silently miss a regression.

tests/hooks/hooks.test.js — the stdin-closure assertion is a positional substring check and is brittle to reformatting of the observer-loop command line.

Important Files Changed

Filename Overview
skills/continuous-learning-v2/agents/start-observer.sh Single-line fix: renames stale _ecc_resolve_homunculus_dir call to _clv2_resolve_homunculus_dir, matching the actual function name in homunculus-dir.sh and eliminating the exit-127 boot failure under set -e.
skills/continuous-learning-v2/agents/observer-loop.sh Adds < /dev/null to the backgrounded claude invocation to prevent Git Bash/MSYS2 from leaving the child process waiting on inherited stdin; change is behavior-neutral on POSIX systems.
tests/hooks/hooks.test.js Adds two regression-guard tests: one verifying resolver-name consistency between caller scripts and homunculus-dir.sh, and one checking that observer-loop.sh closes stdin; the stdin test uses a literal substring match that could miss semantically equivalent reformulations.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["start-observer.sh\n(set -e)"] --> B["source homunculus-dir.sh"]
    B --> C["_clv2_resolve_homunculus_dir()\n✅ fixed: was _ecc_resolve_homunculus_dir"]
    C --> D["CONFIG_DIR resolved"]
    D --> E["Spawn observer-loop.sh &"]
    E --> F["analyze_observations()"]
    F --> G["Build prompt_content in-memory"]
    G --> H["claude -p prompt_content\n< /dev/null >> LOG 2>&1 &\n✅ fixed: stdin closed"]
    H --> I["claude_pid captured"]
    I --> J["Watchdog subshell\nsleep timeout_seconds &"]
    J --> K["wait_for_claude_analysis claude_pid"]
    K --> L{"exit_code == 0?"}
    L -->|Yes| M["Archive observations.jsonl"]
    L -->|No| N["Retain for retry"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["start-observer.sh\n(set -e)"] --> B["source homunculus-dir.sh"]
    B --> C["_clv2_resolve_homunculus_dir()\n✅ fixed: was _ecc_resolve_homunculus_dir"]
    C --> D["CONFIG_DIR resolved"]
    D --> E["Spawn observer-loop.sh &"]
    E --> F["analyze_observations()"]
    F --> G["Build prompt_content in-memory"]
    G --> H["claude -p prompt_content\n< /dev/null >> LOG 2>&1 &\n✅ fixed: stdin closed"]
    H --> I["claude_pid captured"]
    I --> J["Watchdog subshell\nsleep timeout_seconds &"]
    J --> K["wait_for_claude_analysis claude_pid"]
    K --> L{"exit_code == 0?"}
    L -->|Yes| M["Archive observations.jsonl"]
    L -->|No| N["Retain for retry"]
Loading

Reviews (1): Last reviewed commit: "fix(observer): repair daemon boot (stale..." | Re-trigger Greptile

Comment thread tests/hooks/hooks.test.js
test('observer-loop closes stdin on the backgrounded claude analysis call (#2452)', () => {
const observerLoopSource = fs.readFileSync(path.join(__dirname, '..', '..', 'skills', 'continuous-learning-v2', 'agents', 'observer-loop.sh'), 'utf8');

assert.ok(observerLoopSource.includes('-p "$prompt_content" < /dev/null'), 'observer-loop should close stdin on the backgrounded claude call so Git Bash children do not hang on inherited stdin and exit 1');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The test guards against removing < /dev/null, but it checks for a very specific token order (-p "$prompt_content" < /dev/null on a single line). A semantically equivalent reformulation — e.g. moving the redirect before the env-var prefix, or splitting the line differently — would cause this test to fail even though the guard is actually in place. Consider anchoring only on the presence of < /dev/null in the same command block rather than on exact positional text.

Suggested change
assert.ok(observerLoopSource.includes('-p "$prompt_content" < /dev/null'), 'observer-loop should close stdin on the backgrounded claude call so Git Bash children do not hang on inherited stdin and exit 1');
// Match the backgrounded claude line and assert it redirects stdin from /dev/null.
// Anchoring on the whole command block rather than a positional substring keeps the
// guard robust to minor reformatting while still catching accidental removal.
const bgClaudeLineMatch = observerLoopSource.match(/-p "\$prompt_content"[^\n]*&/);
assert.ok(bgClaudeLineMatch, 'observer-loop should have the backgrounded claude call with -p flag');
assert.ok(bgClaudeLineMatch[0].includes('< /dev/null'), 'observer-loop should close stdin on the backgrounded claude call so Git Bash children do not hang on inherited stdin and exit 1');

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@daltino daltino left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR resolves critical issues in the observer scripts, including fixing a stale resolver name and properly closing stdin to prevent analysis errors. The changes look minimal yet impactful, adding robustness to daemon boot and maintaining compatibility with shared lib-defined resolvers. Additionally, the comprehensive new test ensures future reliability. Nice work!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

continuous-learning-v2 observer broken on Windows/Git Bash: daemon boot + analysis both fail (two regressions)

2 participants