feat: core engine (store, prompts, daemon) - #1
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 19 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughChangesAgentLoop daemon
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Daemon
participant Store
participant Codex
Client->>Daemon: POST /api/dispatch with task prompt
Daemon->>Store: enqueueTask
Daemon->>Store: moveTask pending to running
Daemon->>Codex: spawn worker
Codex-->>Daemon: stream activity and final output
Daemon->>Store: write result and completion state
Client->>Daemon: GET /api/state
Daemon-->>Client: running, pending, and recent tasks
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 52ad495bce
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/daemon.js`:
- Around line 218-230: Secure task submission and execution across spawnWorker
and the request handlers around the referenced ranges: require a valid
authentication token, accept only JSON requests from trusted origins, and reject
any cwd that resolves outside the approved workspace. Remove
--dangerously-bypass-approvals-and-sandbox and ensure Codex runs with its normal
approval and sandbox protections.
- Around line 128-149: Update worker creation and terminateWorker so Unix
workers run in a dedicated process group and termination signals the entire
group, not just child.pid; preserve the existing Windows taskkill tree behavior.
Ensure the timeout/close completion path has a bounded fallback after
termination is attempted, so a failed or missing close event cannot leave the
task pending indefinitely.
- Around line 302-346: Add persistent worker ownership or lease metadata to the
startTask lifecycle, and reconcile running tasks during daemon startup before
fillSlots executes. First ensure any surviving workers cannot continue, then
identify running tasks without valid ownership and either safely requeue or mark
them failed, clearing stale activity/state. Update fillSlots to operate only
after this reconciliation so orphaned tasks do not consume concurrency slots.
- Around line 180-199: Update status handling in completeTask so a task is
marked done only when a valid parsed LOOP_RESULT explicitly reports done and the
worker exit code is zero. Treat missing or invalid parseLoopResult output as
failed, and ensure a nonzero exit code remains failed even if the parsed result
says done; preserve forced-failure and timeout behavior.
In `@src/prompts.js`:
- Around line 56-88: Update parseLoopResult to inspect only the final non-empty
line, requiring that line to contain an anchored LOOP_RESULT marker followed
exclusively by the JSON object with no trailing content. After parsing, accept
the result only when its status is allowed and summary is a string; otherwise
return null.
In `@src/store.js`:
- Around line 70-93: The writeJsonAtomic flow currently permits task-file
identifier collisions to overwrite existing queued tasks. Replace the 32-bit
random suffix used for temporary or task identifiers with crypto.randomUUID(),
and create the initial pending file using exclusive creation semantics, retrying
generation and creation when EEXIST occurs. Preserve the existing atomic rename
and EXDEV fallback behavior once a unique file has been created.
- Around line 192-235: Replace the stale-heartbeat deletion takeover in
acquireHeartbeat with a separate immutable ownership lock containing a unique
token, while keeping heartbeat data managed independently by writeHeartbeat.
Ensure acquisition only succeeds when the lock is atomically created and stale
ownership is safely replaced, and update each scheduler tick to validate its
ownership token before performing work so an old daemon cannot overwrite or act
after losing ownership.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: f07a5901-d657-48fd-9ded-e57e184a8f96
📒 Files selected for processing (3)
src/daemon.jssrc/prompts.jssrc/store.js
📜 Review details
🧰 Additional context used
🪛 ast-grep (0.44.1)
src/store.js
[warning] 30-30: 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(paths.config, 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[warning] 77-77: 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.writeFileSync(tempPath, ${JSON.stringify(value, null, 2)}\n, { encoding: 'utf8', flag: 'wx' })
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[warning] 130-130: 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(taskPath(id, stage), 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[warning] 147-147: 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(stageDir(stage), entry.name), 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[warning] 183-183: 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.writeFileSync(fd, ${JSON.stringify(value, null, 2)}\n, 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[warning] 239-239: 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(paths.daemon, 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[error] 147-147: An archive entry path (e.g. entry.path / entry.fileName / header.name) is joined to an output directory without validating that the resolved path stays inside that directory. A malicious archive can use "../" sequences to escape the extraction directory and overwrite arbitrary files (Zip Slip). Resolve the path and verify it starts with the normalized output directory, or strip traversal with path.basename, before writing the entry.
Context: path.join(stageDir(stage), entry.name)
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(zip-slip-archive-extraction-javascript)
src/daemon.js
[warning] 508-512: Use https protocol over http
Context: http.createServer((req, res) => {
handleRequest(req, res).catch((error) => {
sendJson(res, 500, { error: error.message });
});
})
Note: [CWE-319] Cleartext Transmission of Sensitive Information. Security best practice.
(https-protocol-missing)
[warning] 4-4: Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: require('node:child_process')
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
(detect-child-process)
[warning] 152-152: 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(outputPath, 'utf8')
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[warning] 416-416: 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(dashboardPath)
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').
(detect-non-literal-fs-filename)
[error] 287-291: React's useState should not be directly called
Context: setTimeout(() => {
timedOut = true;
lastTextLine = Worker timed out after ${timeoutMinutes} minutes.;
terminateWorker(child);
}, timeoutMinutes * 60 * 1000)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.
(usestate-direct-usage)
[error] 522-522: React's useState should not be directly called
Context: setInterval(tick, pollMs)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.
(usestate-direct-usage)
[warning] 522-522: Avoid using the initial state variable in setState
Context: setInterval(tick, pollMs)
Note: [CWE-710] Improper Adherence to Coding Standards. Security best practice.
(setstate-same-var)
🔇 Additional comments (3)
src/store.js (1)
1-69: LGTM!Also applies to: 96-108, 125-177, 238-281
src/prompts.js (1)
1-54: LGTM!Also applies to: 90-94
src/daemon.js (1)
1-117: LGTM!Also applies to: 151-179, 349-423, 457-485, 529-536
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c651c632ae
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 91ef217080
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
This PR introduces the core AgentLoop “engine” primitives: a filesystem-backed task queue/state store, a worker prompt/result protocol, and a daemon that schedules tasks and exposes a small local HTTP API for dispatching tasks and querying state.
Changes:
- Added
src/store.jsto manage config, task lifecycle (pending/running/done), results, events, and daemon heartbeat/lock on disk. - Added
src/prompts.jsto define the worker prompt protocol and parse theLOOP_RESULTmarker. - Added
src/daemon.jsto schedule tasks, spawn fresh Codex worker processes, and serve/api/state+/api/dispatch.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/store.js | Filesystem-backed config/state store, task queue operations, and daemon heartbeat acquisition. |
| src/prompts.js | Worker protocol prompt and LOOP_RESULT parser for extracting status/summary. |
| src/daemon.js | Local daemon scheduler, Codex worker runner, and HTTP endpoints for dispatch + state snapshots. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d5b6badc2b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a07b0ed792
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Tasks move through a filesystem JSON queue, and each one runs in a fresh Codex worker process.
The daemon serves /api/state for state snapshots and /api/dispatch for new tasks.
Review fixes applied: