Skip to content

feat(synapse): SYN Wave 2 — Hook Entry Point + Registration [Story SYN-7]#127

Merged
Pedrovaleriolopez merged 1 commit intomainfrom
feat/syn-7-hook-entry
Feb 11, 2026
Merged

feat(synapse): SYN Wave 2 — Hook Entry Point + Registration [Story SYN-7]#127
Pedrovaleriolopez merged 1 commit intomainfrom
feat/syn-7-hook-entry

Conversation

@Pedrovaleriolopez
Copy link
Contributor

@Pedrovaleriolopez Pedrovaleriolopez commented Feb 11, 2026

Summary

  • Implement Claude Code UserPromptSubmit hook (.claude/hooks/synapse-engine.js) that integrates SynapseEngine for per-prompt context injection via stdin/stdout JSON protocol
  • 75-line thin wrapper: reads JSON from stdin, delegates to SynapseEngine.process(), writes <synapse-rules> context to stdout
  • Safety timeout (HOOK_TIMEOUT_MS=5000) with timer.unref() as defense-in-depth alongside Claude Code's external timeout
  • .gitignore updated with SYNAPSE runtime entries (.synapse/sessions/, .synapse/cache/) and !.claude/hooks/synapse-engine.js exception

Key Design Decisions

  • CommonJS (not ESM) — consistent with all SYNAPSE modules
  • Zero external deps — Node.js stdlib only (path, fs)
  • Graceful degradation — silent exit (code 0) on any error, never blocks user prompt
  • require.main === module guard — enables both direct script execution and Jest import for coverage tracking
  • Dynamic requires — deferred past .synapse/ existence check for fast-exit path

Test Plan

  • 36/36 tests passing (spawn integration + direct Jest coverage)
  • 425/425 full synapse regression passing
  • Coverage: Stmts 93.93%, Branch 75%, Funcs 87.5%, Lines 100%
  • QA Gate: PASS 98/100 — all 3 issues resolved (coverage, timeout, thresholds)
  • Verify hook executes correctly with real SynapseEngine after SYN-6 merge (already on main)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added Synapse Engine hook integration with prompt processing and result handling capabilities.
  • Tests

    • Added comprehensive test suite for Synapse Engine hook covering input/output protocol, error handling, and edge cases.
  • Chores

    • Updated tracking configuration to include new Synapse runtime directories and documentation guides.

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Warning

Rate limit exceeded

@Pedrovaleriolopez has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 27 minutes and 3 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

A new Node.js hook script (synapse-engine.js) has been added under .claude/hooks that serves as an entry point for Synapse Engine prompt processing. The implementation reads JSON from stdin, manages sessions, delegates to the engine, and writes structured output to stdout with a 5-second safety timeout. Supporting .gitignore rules and comprehensive test coverage are included.

Changes

Cohort / File(s) Summary
Synapse Hook Entry Point
.claude/hooks/synapse-engine.js
New hook script that handles stdin/stdout JSON protocol, session management, SynapseEngine delegation, 5-second timeout enforcement, and error handling with [synapse-hook] prefix logging.
Configuration & Gitignore
.gitignore
Adds ignore rules for .synapse/sessions/ and .synapse/cache/ directories; unignores hook file and new documentation paths (docs/guides/aios-workflows/, docs/guides/glue-script-guide.md).
Test Suite
tests/synapse/hook-entry.test.js
Comprehensive unit tests covering JSON protocol handling, .synapse directory detection, error scenarios, output format validation, engine delegation, timeout behavior, hook registration, and both direct module exports and in-process execution paths.

Sequence Diagram(s)

sequenceDiagram
    participant stdin as Stdin/Caller
    participant hook as synapse-engine.js
    participant reader as readStdin()
    participant engine as SynapseEngine
    participant session as Session Manager
    participant stdout as Stdout

    stdin->>hook: Process invoked with JSON payload
    hook->>reader: Call readStdin()
    reader->>stdin: Read JSON from stream
    stdin-->>reader: JSON data
    reader-->>hook: Parsed payload object
    
    hook->>hook: Validate .synapse directory exists
    
    alt .synapse missing
        hook->>stdout: Exit silently (code 0)
    else Directory exists
        hook->>session: loadSession(cwd)
        session-->>hook: Session object (or null)
        
        hook->>engine: Instantiate SynapseEngine
        hook->>engine: process(prompt, session)
        engine-->>hook: Result with optional xml
        
        hook->>hook: Extract additionalContext from result.xml
        hook->>stdout: Write { hookSpecificOutput: { additionalContext } }
    end
    
    hook->>hook: Enforce 5s timeout, then exit
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: adding a Synapse hook entry point with registration for SYN Wave 2, matching the core PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/syn-7-hook-entry

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 and usage tips.

@github-actions github-actions bot added type: docs Documentation improvements core area: agents Agent system related area: workflows Workflow system related squad squad: etl squad: creator mcp docker-mcp type: test Test coverage and quality labels Feb 11, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 11, 2026

📊 Coverage Report

Coverage report not available

📈 Full coverage report available in Codecov


Generated by PR Automation (Story 6.1)

@Pedrovaleriolopez
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Pedrovaleriolopez
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@Pedrovaleriolopez
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.claude/hooks/synapse-engine.js:
- Around line 41-45: The main function reads input and destructures sessionId,
cwd, and prompt but does not validate cwd before using it to build synapsePath;
add a guard at the top of main to verify cwd is a non-empty string (and
optionally that sessionId/prompt exist if required) and return early (or log a
clear error) when cwd is missing/invalid so path.join is never called with
undefined; update the validation near the readStdin() call and before computing
synapsePath in function main to use the cwd check.
🧹 Nitpick comments (5)
.claude/hooks/synapse-engine.js (1)

28-38: Missing error event handler on process.stdin could leave the promise hanging.

If stdin emits an error event (e.g., broken pipe), the promise is never settled. While run()'s 5-second timeout provides a backstop, explicitly handling the error event is more robust.

Proposed fix
 function readStdin() {
   return new Promise((resolve, reject) => {
     let data = '';
     process.stdin.setEncoding('utf8');
+    process.stdin.on('error', (e) => reject(e));
     process.stdin.on('data', (chunk) => { data += chunk; });
     process.stdin.on('end', () => {
       try { resolve(JSON.parse(data)); }
       catch (e) { reject(e); }
     });
   });
 }
tests/synapse/hook-entry.test.js (4)

469-501: Monkey-patched process.stdin is not restored if the test throws.

In multiple tests (here and in the main() in-process tests below), process.stdin and process.stdout.write are replaced via Object.defineProperty but only restored in the happy path. If an assertion or the promise rejects unexpectedly, the originals are never restored, which could cascade failures to subsequent tests.

Wrapping in try/finally is the standard safeguard:

Example pattern
     const originalStdin = process.stdin;
+    try {
       const mockStdin = new Readable({ read() {} });
       Object.defineProperty(process, 'stdin', { value: mockStdin, writable: true });

       const promise = hookModule.readStdin();
       mockStdin.push('not json');
       mockStdin.push(null);

       await expect(promise).rejects.toThrow();
+    } finally {
       Object.defineProperty(process, 'stdin', { value: originalStdin, writable: true });
+    }

This applies to all tests in sections 8 and 9 that patch process.stdin / process.stdout.write / process.exit (lines 469–620).


503-525: Same restoration concern for process.stdout.write.

The originalWrite is only restored after the assertions. If JSON.parse(captured) or any expect throws, process.stdout.write stays patched. Apply the same try/finally pattern here and in the other main() in-process tests (lines 527–587).


597-620: process.exit spy not guarded by try/finally.

If the expect on line 612 or 613 fails, exitSpy.mockRestore() and errorSpy.mockRestore() on lines 617-618 are skipped. A leaked process.exit mock is particularly dangerous — it silently swallows exits for all remaining tests.

Safer pattern
     const exitSpy = jest.spyOn(process, 'exit').mockImplementation(() => {});
     const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
+    try {
       // ... test body ...
       expect(exitSpy).toHaveBeenCalledWith(0);
       expect(errorSpy).toHaveBeenCalledWith(
         expect.stringContaining('[synapse-hook]')
       );
+    } finally {
       exitSpy.mockRestore();
       errorSpy.mockRestore();
       Object.defineProperty(process, 'stdin', { value: originalStdin, writable: true });
+    }

385-408: Timing-based assertions can be flaky in resource-constrained CI environments.

The 2000ms and 1500ms thresholds are generous, but under heavy load (shared CI runners, Windows containers), spawn overhead alone can spike. Consider bumping the thresholds slightly or marking these with a retry/flaky annotation if you start seeing intermittent failures.

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 11, 2026
- Add stdin error event handler in readStdin() to prevent unhandled rejections
- Add cwd validation guard before path.join() to handle missing input gracefully
- Wrap process.stdin/stdout/exit mocks in try/finally blocks for reliable test cleanup

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Pedrovaleriolopez Pedrovaleriolopez merged commit f73bde5 into main Feb 11, 2026
7 checks passed
@Pedrovaleriolopez Pedrovaleriolopez deleted the feat/syn-7-hook-entry branch February 11, 2026 17:49
@github-actions
Copy link
Contributor

🎉 This PR is included in version 4.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Labels

area: agents Agent system related area: workflows Workflow system related docker-mcp mcp released squad: creator squad: etl squad type: docs Documentation improvements type: test Test coverage and quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant