Skip to content

feat(learning): add human review surface for learned signals#250

Merged
xinhuagu merged 3 commits into
mainfrom
codex/issue-233-human-review-surface
Mar 14, 2026
Merged

feat(learning): add human review surface for learned signals#250
xinhuagu merged 3 commits into
mainfrom
codex/issue-233-human-review-surface

Conversation

@xinhuagu

@xinhuagu xinhuagu commented Mar 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a project-local review store and daemon RPCs for listing, applying, and surfacing human reviews over learned signals
  • extend learning summary and CLI /learning commands with reviewable signals, recent reviews, and review actions
  • record human review outcomes into learning explanations and validations so they feed the phase-2 learning trail

Testing

  • ./gradlew :aceclaw-daemon:test --tests dev.aceclaw.daemon.LearningSignalReviewStoreTest :aceclaw-cli:test --tests dev.aceclaw.cli.TerminalReplTest --no-daemon
  • ./gradlew :aceclaw-daemon:test :aceclaw-cli:test --no-daemon

Summary by CodeRabbit

  • New Features

    • New /learning subcommands: signals, reviews, and review [note]; apply and list human reviews via daemon.
    • Persistent human-review storage and recording; recent reviews and per-target latest reviews are surfaced and counted.
  • Improvements

    • Learning UI shows review counts, recent reviews and signals.
    • Context window display uses live input token counts when available.
  • Tests

    • Added tests for learning subcommands, review rendering, and review storage behavior.

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds human-review features: CLI /learning subcommands (signals, reviews, review) with RPC endpoints, persistent JSONL review store, LearningSignalReview model, recorder integrations for explanations/validations, and daemon wiring to surface and apply reviews.

Changes

Cohort / File(s) Summary
CLI Learning Command & Tests
aceclaw-cli/src/main/java/dev/aceclaw/cli/TerminalRepl.java, aceclaw-cli/src/test/java/dev/aceclaw/cli/TerminalReplTest.java
/learning now accepts an argument (handleLearningCommand(PrintWriter out, String arg)), adds subcommands signals, reviews, and review <action> <type> <id> [note]; prefers live input tokens for context display; tests updated/added for help text, not-connected behavior, and signal rendering.
Daemon: Review Model
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReview.java
New LearningSignalReview record with timestamp, targetType/targetId, Action enum (SUPPRESS, PIN, LOW_VALUE, INCORRECT, USEFUL, UNSUPPRESS, UNPIN), summary, note, reviewer, sessionId, tags, and targetKey() helper.
Daemon: Persistent Store & Tests
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java, aceclaw-daemon/src/test/java/dev/aceclaw/daemon/LearningSignalReviewStoreTest.java
New JSONL-backed LearningSignalReviewStore (append, recent, latestByTarget with scan limit) with defensive parsing; tests verify ordering, per-target latest selection, and resilience to malformed rows.
Daemon: Recorder APIs
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningExplanationRecorder.java, aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningValidationRecorder.java
Added recordHumanReview(...) to both recorders. Validation recorder maps review actions to validation verdicts (SUPPRESS/LOW_VALUE/INCORRECT → REJECT; PIN/USEFUL → PASS; UNSUPPRESS/UNPIN → HOLD).
Daemon: RPC & Wiring
aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java
Added LearningSignalReviewStore field and initialization; new constants (HUMAN_REVIEW_APPLIED_ACTION, REVIEW_COUNT_WINDOW); applyReviewMetadata(...); RPC handlers: learning.review.list, learning.reviewable.list, learning.review.apply; aggregated latestReviews, reviewCounts, recentReviews and recognized human_review_applied as operator-facing.

Sequence Diagram

sequenceDiagram
    actor User
    participant CLI as TerminalRepl
    participant Daemon as AceClawDaemon
    participant Store as ReviewStore
    participant ExplRec as ExplanationRecorder
    participant ValRec as ValidationRecorder

    User->>CLI: /learning review SUPPRESS trend abc [note]
    CLI->>Daemon: RPC learning.review.apply(action,type,id,note)
    Daemon->>Store: append(projectRoot, LearningSignalReview)
    Store-->>Daemon: persisted
    Daemon->>ExplRec: recordHumanReview(...)
    ExplRec-->>Daemon: recorded
    Daemon->>ValRec: recordHumanReview(...)
    ValRec-->>Daemon: recorded
    Daemon-->>CLI: success response
    CLI-->>User: review applied
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Block Major Correctness And Security Risks ❌ Error Pull request introduces critical race conditions in LearningSignalReviewStore, missing error handling in Action.valueOf(), and lacks unit test coverage for RPC handlers. Implement ReadWriteLock for synchronized reads, add try-catch for Action.valueOf() with user-friendly errors, and add comprehensive unit tests for RPC handlers.
Docstring Coverage ⚠️ Warning Docstring coverage is 7.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding human review functionality for learned signals, which is evident across the new store, RPC endpoints, CLI commands, and recording mechanisms.
✨ 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 codex/issue-233-human-review-surface
📝 Coding Plan
  • Generate coding plan for human review comments

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.

@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: 6

🤖 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-cli/src/main/java/dev/aceclaw/cli/TerminalRepl.java`:
- Around line 2848-2863: The left-hand identifier (constructed as left =
targetType:targetId) is being truncated by fitWidth(..., 32) in
renderLearningSignals which makes the exact key uncopyable; replace the
width-limited rendering for that identifier in renderLearningSignals so the full
sanitized identifier (sanitizeTerminalText(left)) is printed verbatim
(optionally pad to 32 chars when shorter) instead of being trimmed by fitWidth,
leaving the summary still width-limited; update the printf call in
TerminalRepl.renderLearningSignals to use the full sanitized left value (and
padding logic if desired) so users can copy targetType:targetId exactly for
/learning review.
- Around line 2676-2688: The current parsing in TerminalRepl accepts only exact
"signals", "reviews", or "review <id>", but silently treats other non-empty
inputs as successful; update the logic around trimmedArg (in TerminalRepl) so
that: if trimmedArg equalsIgnoreCase "review" (no argument) return a clear
usage/error message, if trimmedArg starts with "review " call
handleLearningReviewApplyCommand(trimmedArg.substring(...)) as it does, and if
trimmedArg is non-blank and does not match "signals" or "reviews" or the
"review" patterns then reject it by returning a usage/error (use the same output
stream variable 'out' to print the message). Reference
handleLearningSignalsCommand, handleLearningReviewsCommand,
handleLearningReviewApplyCommand and trimmedArg when adding these explicit
checks before falling through to the default summary.

In `@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java`:
- Line 1329: The code currently limits latest-by-target results by passing 200
into learningSignalReviewStore.latestByTarget(projectPath), causing older
targets to lose reviewAction/reviewSummary; update the call in AceClawDaemon
(the latestReviews assignment using learningSignalReviewStore.latestByTarget) to
load the full latest-by-target map (i.e., remove the hard cap argument) or, if
performance concerns exist, add/use a store API that accepts only the target
keys needed by the endpoint; apply the same change at the other occurrence noted
(around the second call at ~1469) so both endpoints no longer truncate to 200.
- Around line 1471-1488: The loop that builds signals from
learningExplanationStore.recent(...) is accidentally selecting synthetic review
rows (created by recordHumanReview()) because it dedupes by target key and keeps
the first sight; fix it by skipping explanations whose actionType equals
"human_review_applied" (or whatever constant represents the synthetic review
event) before creating the key/adding to seen so the original explanation
remains the reviewable signal; update the block handling
explanation.actionType() in AceClawDaemon (the loop using
learningExplanationStore.recent, the seen set, and applyReviewMetadata) to
filter out those synthetic review events.
- Around line 1371-1383: The current loop increments reviewCounts while
iterating only over learningSignalReviewStore.recent(projectPath, limit), so
reviewCounts reflects just the returned page (default limit=10); change the
logic to compute reviewCounts from a broader/bounded window separate from the
recentReviews page—e.g., call a dedicated method or an additional iterator like
learningSignalReviewStore.recent(projectPath, countWindow) (use a configurable
countWindow) to aggregate counts into reviewCounts, and keep the existing
learningSignalReviewStore.recent(projectPath, limit) loop solely to populate
recentReviews; update any callers or configuration for countWindow and ensure
you still lowercase action names (key) when incrementing reviewCounts.

In
`@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java`:
- Around line 28-40: The append method in LearningSignalReviewStore can throw
OverlappingFileLockException when concurrent append() calls run in the same JVM;
add a process-local ReentrantLock field (e.g., private final ReentrantLock
writeLock = new ReentrantLock()) to the LearningSignalReviewStore class and use
writeLock.lock()/writeLock.unlock() to serialize the entire append write path
(acquire the ReentrantLock before creating/opening the FileChannel and releasing
it in a finally block after the channel lock and write complete); also add the
necessary import for java.util.concurrent.locks.ReentrantLock.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b66e144a-331a-49ec-afea-036645be9e54

📥 Commits

Reviewing files that changed from the base of the PR and between e1023f3 and 808f146.

📒 Files selected for processing (8)
  • aceclaw-cli/src/main/java/dev/aceclaw/cli/TerminalRepl.java
  • aceclaw-cli/src/test/java/dev/aceclaw/cli/TerminalReplTest.java
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningExplanationRecorder.java
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReview.java
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningValidationRecorder.java
  • aceclaw-daemon/src/test/java/dev/aceclaw/daemon/LearningSignalReviewStoreTest.java

Comment thread aceclaw-cli/src/main/java/dev/aceclaw/cli/TerminalRepl.java
Comment thread aceclaw-cli/src/main/java/dev/aceclaw/cli/TerminalRepl.java
Comment thread aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java Outdated
Comment thread aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java Outdated
Comment thread aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java
@xinhuagu

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 14, 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

Copy link
Copy Markdown
Owner Author

@coderabbitai review latest changes

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown

@xinhuagu Sure, triggering a review of the latest changes now!

✅ 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.

@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: 1

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

1373-1388: Consider collapsing the two review-store reads into one materialized window.

learning.summary currently scans reviews once for counts and again for recentReviews. Reusing a single fetched list would reduce disk I/O and keep summary latency steadier.

🤖 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/AceClawDaemon.java` around
lines 1373 - 1388, The code currently calls
learningSignalReviewStore.recent(projectPath, REVIEW_COUNT_WINDOW) and
learningSignalReviewStore.recent(projectPath, limit) separately causing
duplicate reads; consolidate by materializing a single List (e.g., var reviews =
learningSignalReviewStore.recent(projectPath, Math.max(REVIEW_COUNT_WINDOW,
limit))) and iterate that list twice (first to populate reviewCounts by using
review.action().name() and REVIEW_COUNT_WINDOW semantics, then to build
recentReviews via objectMapper.createObjectNode using review.timestamp(),
targetType/Id, action, summary, note, reviewer); ensure you still respect the
intended windows (trim or filter the materialized list if needed) and replace
references to direct learningSignalReviewStore.recent calls with the new local
variable.
🤖 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/AceClawDaemon.java`:
- Around line 1525-1537: The current flow appends LearningSignalReview via
learningSignalReviewStore.append before calling
learningExplanationRecorder.recordHumanReview and
learningValidationRecorder.recordHumanReview, which can leave a durable append
if either follow-up fails; change the flow to either (A) perform
recordHumanReview calls first and only call learningSignalReviewStore.append
after both succeed, or (B) wrap the three operations in a transactional/atomic
boundary if supported, or if transactions aren't available perform the append
last and on any failure of explanation/validation do not append (or if append is
unavoidable, implement a compensating delete via learningSignalReviewStore to
roll back the append when recordHumanReview fails); update the code around
learningSignalReviewStore.append, learningExplanationRecorder.recordHumanReview,
and learningValidationRecorder.recordHumanReview accordingly to ensure no
durable partial-write remains on RPC error.

---

Nitpick comments:
In `@aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java`:
- Around line 1373-1388: The code currently calls
learningSignalReviewStore.recent(projectPath, REVIEW_COUNT_WINDOW) and
learningSignalReviewStore.recent(projectPath, limit) separately causing
duplicate reads; consolidate by materializing a single List (e.g., var reviews =
learningSignalReviewStore.recent(projectPath, Math.max(REVIEW_COUNT_WINDOW,
limit))) and iterate that list twice (first to populate reviewCounts by using
review.action().name() and REVIEW_COUNT_WINDOW semantics, then to build
recentReviews via objectMapper.createObjectNode using review.timestamp(),
targetType/Id, action, summary, note, reviewer); ensure you still respect the
intended windows (trim or filter the materialized list if needed) and replace
references to direct learningSignalReviewStore.recent calls with the new local
variable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7786748c-24f6-414a-b034-a761112c182c

📥 Commits

Reviewing files that changed from the base of the PR and between 808f146 and 83be021.

📒 Files selected for processing (4)
  • aceclaw-cli/src/main/java/dev/aceclaw/cli/TerminalRepl.java
  • aceclaw-cli/src/test/java/dev/aceclaw/cli/TerminalReplTest.java
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java

Comment thread aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java
@xinhuagu

Copy link
Copy Markdown
Owner Author

@coderabbitai review latest changes

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown

@xinhuagu Sure, triggering a review of the latest changes now!

✅ 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.

@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/AceClawDaemon.java`:
- Around line 1519-1524: The code currently calls
LearningSignalReview.Action.valueOf(actionText.toUpperCase(Locale.ROOT)) which
will throw a generic IllegalArgumentException for invalid actionText; catch that
exception (or pre-validate actionText against
LearningSignalReview.Action.values()) and rethrow a new IllegalArgumentException
with a user-friendly message that includes the invalid value and the list of
valid actions, keeping the existing checks for targetType/targetId/actionText
and preserving the subsequent construction of the summary variable; reference
the LearningSignalReview.Action enum and the local variables actionText,
targetType, and targetId when implementing the change.
- Line 1474: LearningSignalReviewStore currently writes under writeLock in
append() but reads in recent() and latestByTarget() use Files.readAllLines()
unsynchronized, causing races; fix by adding a
java.util.concurrent.locks.ReadWriteLock field to LearningSignalReviewStore,
keep append() holding the existing writeLock (and file lock) and acquire the
read lock around the body of recent() and latestByTarget() (and any other reader
helpers) so readers cannot see partially-written lines—use try/finally to
release the read lock and ensure all call sites (methods referenced: recent(),
latestByTarget(), append()) are updated to use the new lock consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 28395c8c-5f3b-466a-8ad1-6b366245da21

📥 Commits

Reviewing files that changed from the base of the PR and between 83be021 and 3137cc0.

📒 Files selected for processing (1)
  • aceclaw-daemon/src/main/java/dev/aceclaw/daemon/AceClawDaemon.java


var result = objectMapper.createObjectNode();
var signals = objectMapper.createArrayNode();
var latestReviews = learningSignalReviewStore.latestByTarget(projectPath);

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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the LearningSignalReviewStore synchronization pattern
ast-grep --pattern $'class LearningSignalReviewStore {
  $$$
  public $_ recent($$$) {
    $$$
  }
  $$$
}'

# Check if there's any locking in the recent method
rg -nA 20 'public.*recent\(Path projectRoot' aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java

Repository: xinhuagu/AceClaw

Length of output: 1072


🏁 Script executed:

#!/bin/bash
# Check the append() method implementation
rg -nA 15 'public void append\(' aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java

Repository: xinhuagu/AceClaw

Length of output: 894


🏁 Script executed:

#!/bin/bash
# Check the latestByTarget() method implementation
rg -nA 20 'public.*latestByTarget' aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java

Repository: xinhuagu/AceClaw

Length of output: 708


🏁 Script executed:

#!/bin/bash
# Get the full class structure to understand synchronization
head -100 aceclaw-daemon/src/main/java/dev/aceclaw/daemon/LearningSignalReviewStore.java

Repository: xinhuagu/AceClaw

Length of output: 3537


Data race in LearningSignalReviewStore reads requires synchronization.

The append() method holds writeLock during writes (with additional file-level locking), but recent() and latestByTarget() perform unsynchronized reads via Files.readAllLines(). This creates a race condition where concurrent RPC handlers calling latestByTarget() (lines 1474, 1444, 1377) can read partially-written lines while another thread appends. Although recent() catches and skips parse exceptions from malformed lines, this masks data corruption.

Add a ReadWriteLock to LearningSignalReviewStore: hold the read lock during recent() and wrap latestByTarget() calls appropriately. This ensures readers cannot race with writers.

Also applies to: 1444-1444, 1377-1377

🤖 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/AceClawDaemon.java` at line
1474, LearningSignalReviewStore currently writes under writeLock in append() but
reads in recent() and latestByTarget() use Files.readAllLines() unsynchronized,
causing races; fix by adding a java.util.concurrent.locks.ReadWriteLock field to
LearningSignalReviewStore, keep append() holding the existing writeLock (and
file lock) and acquire the read lock around the body of recent() and
latestByTarget() (and any other reader helpers) so readers cannot see
partially-written lines—use try/finally to release the read lock and ensure all
call sites (methods referenced: recent(), latestByTarget(), append()) are
updated to use the new lock consistently.

Comment on lines +1519 to +1524
if (targetType.isBlank() || targetId.isBlank() || actionText.isBlank()) {
throw new IllegalArgumentException("targetType, targetId, and action are required");
}
var action = LearningSignalReview.Action.valueOf(actionText.toUpperCase(Locale.ROOT));
String summary = "Human review marked " + targetType + " '" + targetId + "' as "
+ action.name().toLowerCase(Locale.ROOT).replace('_', '-') + ".";

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

Provide a user-friendly error for invalid action values.

Action.valueOf() throws IllegalArgumentException with an unhelpful message if actionText is not a valid enum constant. Per coding guidelines, wrap this into a more descriptive error.

🛠️ Suggested fix
             if (targetType.isBlank() || targetId.isBlank() || actionText.isBlank()) {
                 throw new IllegalArgumentException("targetType, targetId, and action are required");
             }
-            var action = LearningSignalReview.Action.valueOf(actionText.toUpperCase(Locale.ROOT));
+            LearningSignalReview.Action action;
+            try {
+                action = LearningSignalReview.Action.valueOf(actionText.toUpperCase(Locale.ROOT));
+            } catch (IllegalArgumentException e) {
+                throw new IllegalArgumentException("Invalid action: " + actionText
+                        + ". Valid values: " + java.util.Arrays.toString(LearningSignalReview.Action.values()));
+            }
             String summary = "Human review marked " + targetType + " '" + targetId + "' as "
🤖 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/AceClawDaemon.java` around
lines 1519 - 1524, The code currently calls
LearningSignalReview.Action.valueOf(actionText.toUpperCase(Locale.ROOT)) which
will throw a generic IllegalArgumentException for invalid actionText; catch that
exception (or pre-validate actionText against
LearningSignalReview.Action.values()) and rethrow a new IllegalArgumentException
with a user-friendly message that includes the invalid value and the list of
valid actions, keeping the existing checks for targetType/targetId/actionText
and preserving the subsequent construction of the summary variable; reference
the LearningSignalReview.Action enum and the local variables actionText,
targetType, and targetId when implementing the change.

@xinhuagu xinhuagu merged commit 3137cc0 into main Mar 14, 2026
4 checks passed
@xinhuagu

Copy link
Copy Markdown
Owner Author

@coderabbitai review latest changes

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown

@xinhuagu Sure, triggering a review of the latest changes now!

✅ 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.

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.

1 participant