Skip to content

feat: implement BOOT.md execution at daemon startup (#33)#43

Merged
xinhuagu merged 2 commits into
mainfrom
feat/issue-33-boot-md
Feb 20, 2026
Merged

feat: implement BOOT.md execution at daemon startup (#33)#43
xinhuagu merged 2 commits into
mainfrom
feat/issue-33-boot-md

Conversation

@xinhuagu

@xinhuagu xinhuagu commented Feb 20, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add BootExecutor that discovers and runs BOOT.md files at daemon startup for workspace initialization
  • BOOT.md supports project-level (.aceclaw/BOOT.md) and global (~/.aceclaw/BOOT.md) — both execute in order
  • Read-only permission policy during boot: read_file, glob, grep, list_directory auto-approved; all write/execute tools denied
  • Config options: bootEnabled (default true), bootTimeoutSeconds (default 120)
  • Integration in AceClawDaemon.start() between health monitor start and UDS listener start (runs before accepting connections)

Test plan

  • 11 integration tests in BootExecutorTest
  • No BOOT.md — returns not executed
  • Project BOOT.md — discovered and executed
  • Global BOOT.md — discovered and executed
  • Both exist — both execute (project first, then global)
  • Write tool denied — boot continues gracefully
  • LLM failure — caught, daemon continues normally
  • Empty BOOT.md — skipped without LLM call
  • Permission checker — read tools allowed, write tools denied
  • Full build passes (./gradlew clean build -x :aceclaw-core:test — core test failures are pre-existing)

Closes #33

Summary by CodeRabbit

  • New Features

    • Added boot configuration options to enable/disable the startup boot sequence and set boot timeout.
    • Automatic discovery and prioritized execution of BOOT.md at startup from project and global locations.
    • Boot runs in a restricted environment allowing only read-only operations; write actions are blocked.
    • Boot execution is best-effort; failures do not prevent daemon startup.
  • Tests

    • Added comprehensive unit tests covering BOOT.md discovery, execution, permission checks, and failure cases.

Add BootExecutor that discovers and runs BOOT.md files during daemon
startup for workspace initialization. BOOT.md contains natural-language
instructions executed autonomously before the daemon accepts connections.

- BootExecutor: discovers project (.aceclaw/BOOT.md) and global
  (~/.aceclaw/BOOT.md) files, executes both in order with timeout
- BootPermissionChecker: read-only tools auto-approved (read_file, glob,
  grep, list_directory), all write/execute tools denied during boot
- AceClawConfig: bootEnabled (default true), bootTimeoutSeconds (default 120)
- Integration in AceClawDaemon.start() between health monitor and UDS listener
- 11 integration tests covering discovery, execution, permissions, failures
@coderabbitai

coderabbitai Bot commented Feb 20, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds configurable boot-time BOOT.md execution: new boot config options, daemon startup integration to run boot sequences, a BootExecutor that discovers and executes project/global BOOT.md files with read-only tool restrictions and timeout guards, and tests covering discovery and execution scenarios.

Changes

Cohort / File(s) Summary
Configuration
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawConfig.java
Adds bootEnabled (boolean) and bootTimeoutSeconds (int) fields with getters and default values; extends config file format and merge logic to propagate boot settings.
Daemon Integration
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java
Stores LLM client, tool registry, model, and system prompt at wiring time and invokes BootExecutor.execute during start() when bootEnabled; boot failures are logged and non-fatal.
Boot Execution Engine
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java
New class implementing discovery (project .aceclaw/BOOT.md then global BOOT.md) and execution of BOOT.md files with per-file and overall timeout handling, read-only tool enforcement via BootPermissionChecker, and aggregated BootResult reporting.
Tests
aceclaw-daemon/src/test/java/dev/aceclaw/daemon/BootExecutorTest.java
New comprehensive unit tests validating discovery order, execution flow, permission enforcement, timeout and error handling, empty-file behavior, and LLM prompts using MockLlmClient and temp directories.

Sequence Diagram

sequenceDiagram
    participant Daemon as AceClawDaemon
    participant BE as BootExecutor
    participant FS as FileSystem
    participant LLM as LLM Client
    participant AR as AgentLoop
    participant TR as ToolRegistry
    participant PC as BootPermissionChecker

    Daemon->>BE: execute(homeDir, workingDir, llmClient, toolRegistry, model, systemPrompt, ...)
    BE->>FS: discover BOOT.md files (project -> global)
    FS-->>BE: list of boot files

    loop for each boot file
        BE->>FS: read boot file
        FS-->>BE: content
        alt content empty
            BE->>BE: mark found, skip execution
        else content present
            BE->>AR: create StreamingAgentLoop with SilentStreamHandler
            AR->>LLM: send boot prompt (includes [BOOT] context)
            LLM-->>AR: response
            loop agent iterations
                AR->>TR: request tool use
                TR->>PC: check(toolName, input)
                PC-->>TR: allow (read-only) or deny (with message)
                alt allowed
                    AR->>LLM: continue interaction
                else denied
                    AR->>AR: record denial, continue best-effort
                end
            end
            AR-->>BE: execution result
        end
        BE->>BE: append per-file outcome to summary
    end

    BE-->>Daemon: return BootResult(executed, filesFound, summary, elapsed)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PR #5: Adds ToolPermissionChecker/ToolPermissionResult interfaces that BootPermissionChecker implements; strongly related to boot permission enforcement.
  • PR #4: Modifies config and daemon wiring for new boot settings, overlapping changes in AceClawConfig and startup integration.
  • PR #40: Adjusts daemon startup wiring and LLM client handling; related to how boot captures and uses LLM/tool context.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: implementing BOOT.md execution at daemon startup, which is the core objective of the PR.
Linked Issues check ✅ Passed The PR implementation fully addresses all coding requirements from issue #33: discovers BOOT.md files (project and global), executes them at startup with logging, enforces read-only permission policy, adds config options, integrates into daemon startup, and includes comprehensive integration tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #33 objectives: configuration additions for boot settings, BootExecutor implementation for discovery/execution, daemon integration, and comprehensive test coverage. No extraneous changes detected.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/issue-33-boot-md

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

@greptile-apps

greptile-apps Bot commented Feb 20, 2026

Copy link
Copy Markdown

Greptile Summary

Implements BootExecutor to run BOOT.md files at daemon startup for workspace initialization. The implementation discovers project-level (.aceclaw/BOOT.md) and global (~/.aceclaw/BOOT.md) files, executes them in order with read-only permissions, and integrates gracefully into the daemon boot sequence.

Major changes:

  • Added BootExecutor with discovery logic for project and global BOOT.md files
  • Read-only permission policy: read_file, glob, grep, list_directory auto-approved; all write/execute tools denied
  • Config options: bootEnabled (default true), bootTimeoutSeconds (default 120)
  • Integration point: runs after health monitor start, before UDS listener accepts connections
  • Comprehensive test suite with 11 integration tests covering discovery, execution, permissions, and error handling
  • Executor resource leak in BootExecutor.executeBootFile() - ExecutorService created but never shut down

Confidence Score: 4/5

  • Safe to merge after fixing executor resource leak
  • Well-tested feature with comprehensive test coverage and proper error handling. The executor resource leak is a clear issue that will cause thread leaks on repeated boot executions, but it's contained to the boot phase and doesn't affect core daemon functionality. All other aspects are solid: permission model is restrictive (read-only), timeout handling is correct, and integration is non-blocking.
  • Pay attention to BootExecutor.java - fix the executor resource leak before merging

Important Files Changed

Filename Overview
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java Implements BOOT.md execution with read-only permissions, timeout handling, and graceful error recovery; executor resource leak potential
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java Integrates BOOT.md execution between health monitor start and UDS listener start with proper exception handling
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawConfig.java Adds bootEnabled (default true) and bootTimeoutSeconds (default 120) config options with proper defaults
aceclaw-daemon/src/test/java/dev/aceclaw/daemon/BootExecutorTest.java Comprehensive test coverage with 11 tests covering discovery, execution, permissions, error handling, and edge cases

Sequence Diagram

sequenceDiagram
    participant D as AceClawDaemon
    participant BE as BootExecutor
    participant AL as StreamingAgentLoop
    participant PC as BootPermissionChecker
    participant LLM as LlmClient
    participant FS as FileSystem

    D->>D: start()
    D->>D: Start health monitor
    
    alt bootEnabled == true
        D->>BE: execute(homeDir, workingDir, llmClient, ...)
        BE->>FS: discoverBootFiles(homeDir, workingDir)
        FS-->>BE: List of BOOT.md files (project first, then global)
        
        alt No BOOT.md found
            BE-->>D: BootResult(executed=false)
        else BOOT.md files found
            BE->>BE: Create BootPermissionChecker
            BE->>AL: new StreamingAgentLoop(with bootPermChecker)
            
            loop For each BOOT.md file
                BE->>FS: Files.readString(bootFile)
                FS-->>BE: BOOT.md content
                
                alt Content is blank
                    BE->>BE: Skip (no LLM call)
                else Content not blank
                    BE->>AL: runTurn("[BOOT] ..." + content)
                    AL->>LLM: streamMessage(bootPrompt)
                    
                    loop Agent ReAct loop (max 10 iterations)
                        LLM-->>AL: Tool use request
                        AL->>PC: check(toolName, inputJson)
                        
                        alt Read-only tool (read_file, glob, grep, list_directory)
                            PC-->>AL: ALLOWED
                            AL->>AL: Execute tool
                        else Write/execute tool
                            PC-->>AL: DENIED
                            AL->>AL: Return error to LLM
                        end
                    end
                    
                    LLM-->>AL: Final response
                    AL-->>BE: TurnResult
                end
            end
            
            BE-->>D: BootResult(executed=true, summary)
        end
    else bootEnabled == false
        D->>D: Skip boot (log debug message)
    end
    
    D->>D: Start UDS listener
    D->>D: Daemon ready
Loading

Last reviewed commit: 1aab65e

@greptile-apps greptile-apps Bot 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.

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +186 to +204
var executor = Executors.newVirtualThreadPerTaskExecutor();
var future = CompletableFuture.supplyAsync(() -> {
try {
var turn = agentLoop.runTurn(bootPrompt, new ArrayList<>(),
new SilentStreamHandler());
return turn.text();
} catch (LlmException e) {
throw new CompletionException(e);
}
}, executor);

try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
future.cancel(true);
throw e;
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ExecutorService created but never shut down - resource leak

Suggested change
var executor = Executors.newVirtualThreadPerTaskExecutor();
var future = CompletableFuture.supplyAsync(() -> {
try {
var turn = agentLoop.runTurn(bootPrompt, new ArrayList<>(),
new SilentStreamHandler());
return turn.text();
} catch (LlmException e) {
throw new CompletionException(e);
}
}, executor);
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
future.cancel(true);
throw e;
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}
// Run in a virtual thread with timeout
var executor = Executors.newVirtualThreadPerTaskExecutor();
try {
var future = CompletableFuture.supplyAsync(() -> {
try {
var turn = agentLoop.runTurn(bootPrompt, new ArrayList<>(),
new SilentStreamHandler());
return turn.text();
} catch (LlmException e) {
throw new CompletionException(e);
}
}, executor);
try {
return future.get(timeoutMs, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
future.cancel(true);
throw e;
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}
} finally {
executor.close();
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java
Line: 186-204

Comment:
`ExecutorService` created but never shut down - resource leak

```suggestion
        // Run in a virtual thread with timeout
        var executor = Executors.newVirtualThreadPerTaskExecutor();
        try {
            var future = CompletableFuture.supplyAsync(() -> {
                try {
                    var turn = agentLoop.runTurn(bootPrompt, new ArrayList<>(),
                            new SilentStreamHandler());
                    return turn.text();
                } catch (LlmException e) {
                    throw new CompletionException(e);
                }
            }, executor);

            try {
                return future.get(timeoutMs, TimeUnit.MILLISECONDS);
            } catch (TimeoutException e) {
                future.cancel(true);
                throw e;
            } catch (ExecutionException e) {
                throw (Exception) e.getCause();
            }
        } finally {
            executor.close();
        }
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 21405e8 — wrapped executor in try-finally with executor.close(). @greptileai please re-review.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Looks good! The executor.close() in the finally block at BootExecutor.java:202 properly handles cleanup for all exit paths (success, timeout, and exceptions). Resource leak is resolved.

Wrap the virtual thread executor in try-finally to ensure it is closed
after boot file execution completes, times out, or fails.
@xinhuagu

xinhuagu commented Feb 20, 2026

Copy link
Copy Markdown
Owner Author

@greptile review

@xinhuagu

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java (1)

49-55: Consider enforcing the documented max‑iterations guardrail.

The class‑level guardrail mentions a max‑iteration limit, but it isn’t wired into the boot agent loop. Either apply it (if supported by AgentLoopConfig) or drop the guardrail constant/docs to avoid drift.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java` around
lines 49 - 55, BootExecutor declares BOOT_MAX_ITERATIONS but never enforces it;
either wire it into the boot agent loop by applying the constant to the agent
loop configuration (e.g., set BOOT_MAX_ITERATIONS on the AgentLoopConfig
instance used to create/start the boot agent) or enforce it directly inside the
BootExecutor boot loop (increment a local counter in the method that runs the
loop and break/throw when counter > BOOT_MAX_ITERATIONS). Update uses of
AgentLoopConfig (or the method that starts the loop) to accept the
max-iterations value, or add the explicit counter guard in the method that
performs the boot agent iterations, and keep the BOOT_MAX_ITERATIONS constant
(or remove it if you choose not to enforce).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java`:
- Around line 49-55: BootExecutor declares BOOT_MAX_ITERATIONS but never
enforces it; either wire it into the boot agent loop by applying the constant to
the agent loop configuration (e.g., set BOOT_MAX_ITERATIONS on the
AgentLoopConfig instance used to create/start the boot agent) or enforce it
directly inside the BootExecutor boot loop (increment a local counter in the
method that runs the loop and break/throw when counter > BOOT_MAX_ITERATIONS).
Update uses of AgentLoopConfig (or the method that starts the loop) to accept
the max-iterations value, or add the explicit counter guard in the method that
performs the boot agent iterations, and keep the BOOT_MAX_ITERATIONS constant
(or remove it if you choose not to enforce).

@coderabbitai

coderabbitai Bot commented Feb 20, 2026

Copy link
Copy Markdown
✅ 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.

@xinhuagu xinhuagu merged commit e6f7167 into main Feb 20, 2026
2 checks passed

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java`:
- Around line 203-205: In the ExecutionException catch block in BootExecutor
(the code catching ExecutionException e), avoid the unsafe cast of e.getCause()
to Exception; instead retrieve Throwable cause = e.getCause() and rethrow it
appropriately: if cause is an Error, throw (Error) cause; else if cause is a
RuntimeException, throw (RuntimeException) cause; else if cause is an Exception,
throw (Exception) cause; otherwise wrap the Throwable in a new Exception (e.g.,
throw new Exception(cause)). This preserves Error types and avoids
ClassCastException while keeping the original cause.
- Around line 100-108: BOOT_MAX_ITERATIONS is defined but never used; add an
enforcement path by extending AgentLoopConfig to carry a maxIterations field
(and builder method) and set it from BOOT_MAX_ITERATIONS in BootExecutor when
constructing bootConfig, then update StreamingAgentLoop to read
config.maxIterations and stop the loop after that many iterations (or throw a
controlled exception/exit). Specifically: add a maxIterations:int (or Integer)
to the AgentLoopConfig record and builder, set
.maxIterations(BOOT_MAX_ITERATIONS) in BootExecutor where bootConfig is built,
and make StreamingAgentLoop's main run/iterate method check
AgentLoopConfig.maxIterations each iteration to enforce the guardrail.

Comment on lines +100 to +108
// Create a boot-restricted agent loop with read-only permission checker
var bootPermChecker = new BootPermissionChecker();
var bootConfig = AgentLoopConfig.builder()
.sessionId("boot")
.permissionChecker(bootPermChecker)
.build();
var agentLoop = new StreamingAgentLoop(
llmClient, toolRegistry, model, systemPrompt,
maxTokens, thinkingBudget, null, bootConfig);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find the BootExecutor file and check its content
find . -type f -name "BootExecutor.java" | head -5

Repository: xinhuagu/AceClaw

Length of output: 127


🏁 Script executed:

# Search for BOOT_MAX_ITERATIONS definition and usage
rg -n "BOOT_MAX_ITERATIONS" --type java

Repository: xinhuagu/AceClaw

Length of output: 183


🏁 Script executed:

# Check AgentLoopConfig for maxIterations method
rg -n "maxIterations" --type java

Repository: xinhuagu/AceClaw

Length of output: 42


🏁 Script executed:

# Also check the AgentLoopConfig builder pattern
rg -n "class AgentLoopConfig" --type java -A 30

Repository: xinhuagu/AceClaw

Length of output: 42


🏁 Script executed:

# Search for AgentLoopConfig definition more broadly
rg -n "AgentLoopConfig" --type java | head -20

Repository: xinhuagu/AceClaw

Length of output: 2976


🏁 Script executed:

# Read the BootExecutor.java file to understand the context
cat -n aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java | head -110

Repository: xinhuagu/AceClaw

Length of output: 5291


🏁 Script executed:

# Read the AgentLoopConfig class definition
cat -n aceclaw-core/src/main/java/dev/aceclaw/core/agent/AgentLoopConfig.java

Repository: xinhuagu/AceClaw

Length of output: 2959


🏁 Script executed:

# Check if StreamingAgentLoop or AgentLoop has any iteration limiting logic
rg -n "maxIterations\|iterations\|BOOT_MAX" --type java aceclaw-core/src/main/java/dev/aceclaw/core/agent/StreamingAgentLoop.java aceclaw-core/src/main/java/dev/aceclaw/core/agent/AgentLoop.java

Repository: xinhuagu/AceClaw

Length of output: 42


BOOT_MAX_ITERATIONS is defined but never enforced.

The constant BOOT_MAX_ITERATIONS = 10 is defined at line 50 and documented as a guardrail (line 40), but it is never used. AgentLoopConfig does not support iteration limiting—the record and builder contain only sessionId, eventBus, permissionChecker, memoryHandler, and metricsCollector. This means the max iterations guardrail documented in the Javadoc is not actually enforced during boot execution, leaving the agent loop vulnerable to runaway iterations.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java` around
lines 100 - 108, BOOT_MAX_ITERATIONS is defined but never used; add an
enforcement path by extending AgentLoopConfig to carry a maxIterations field
(and builder method) and set it from BOOT_MAX_ITERATIONS in BootExecutor when
constructing bootConfig, then update StreamingAgentLoop to read
config.maxIterations and stop the loop after that many iterations (or throw a
controlled exception/exit). Specifically: add a maxIterations:int (or Integer)
to the AgentLoopConfig record and builder, set
.maxIterations(BOOT_MAX_ITERATIONS) in BootExecutor where bootConfig is built,
and make StreamingAgentLoop's main run/iterate method check
AgentLoopConfig.maxIterations each iteration to enforce the guardrail.

Comment on lines +203 to +205
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Unsafe cast from Throwable to Exception can mask Error types.

If the underlying task throws an Error (e.g., OutOfMemoryError, StackOverflowError), e.getCause() returns a Throwable that is not an Exception. The cast would throw ClassCastException, masking the original error.

Proposed fix to handle all Throwable types
             } catch (ExecutionException e) {
-                throw (Exception) e.getCause();
+                Throwable cause = e.getCause();
+                if (cause instanceof Exception ex) {
+                    throw ex;
+                } else if (cause instanceof Error err) {
+                    throw err;
+                } else {
+                    throw new RuntimeException(cause);
+                }
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (ExecutionException e) {
throw (Exception) e.getCause();
}
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof Exception ex) {
throw ex;
} else if (cause instanceof Error err) {
throw err;
} else {
throw new RuntimeException(cause);
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/BootExecutor.java` around
lines 203 - 205, In the ExecutionException catch block in BootExecutor (the code
catching ExecutionException e), avoid the unsafe cast of e.getCause() to
Exception; instead retrieve Throwable cause = e.getCause() and rethrow it
appropriately: if cause is an Error, throw (Error) cause; else if cause is a
RuntimeException, throw (RuntimeException) cause; else if cause is an Exception,
throw (Exception) cause; otherwise wrap the Throwable in a new Exception (e.g.,
throw new Exception(cause)). This preserves Error types and avoids
ClassCastException while keeping the original cause.

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.

[P1] Implement BOOT.md execution at daemon startup

1 participant