Status: Archived Owner: Maintainers Source of truth: historical snapshot; current guidance lives in linked active docs Parent: CueLoop Documentation
Date: 2026-03-31
Scope: Full codebase (crates/cueloop/src, crates/cueloop/tests, scripts/, Makefile)
Auditor: AI Agent (comprehensive-codebase-audit skill)
| # | Severity | Category | Issue |
|---|---|---|---|
| 1 | 🟠 High | File Size Limits | 12 non-test source files exceed the 500 LOC hard limit; 34 exceed the 400 LOC soft limit |
| 2 | 🟠 High | Missing SAFETY Docs |
5 unsafe blocks in production code lack SAFETY comments |
| 3 | 🟠 High | Missing set -euo pipefail |
8 sourced library shell scripts omit strict mode |
| 4 | 🟡 Medium | File Size Limits | runner/error.rs (530 LOC) — the largest non-test production file, holds 12 error variants + match arms |
| 5 | 🟡 Medium | Test Coverage | 528 of 826 source files (64%) have zero inline test coverage; 263 files >100 LOC lack tests |
| 6 | 🟡 Medium | Clone Overuse | 820 .clone() calls in non-test source; audit for hot-path cloning warranted |
| 7 | 🟡 Medium | unreachable!() in Production |
1 unreachable!() in notification/display.rs for a legitimate enum branch |
| 8 | 🔵 Low | Test unwrap() Density |
~300+ unwrap() calls in test helper code that could use ? with -> Result test signatures |
| 9 | 🔵 Low | Logging Distribution | 528 log calls but heavily skewed toward warn (151) and info (197); debug (136) under-represents hot paths |
| 10 | 🔵 Low | Dead Code Candidates | Multiple unreachable!() / todo!() patterns absent, but some Ok(_) => {} silent success branches in atomic/undo paths |
Architecture: Well-decomposed. The facade pattern is rigorously applied across 30+ module directories. Module documentation (//!) covers 100% of source files (826/826). The codebase demonstrates disciplined separation of concerns.
Security: Strong. Shell injection is blocked via argv-only CI gate validation, symlink/escape path traversal detection in plugin resolution, comprehensive redaction across env keys, bearer tokens, AWS keys, SSH keys, and hex strings. No eval in shell scripts. No raw Command::output() — all subprocesses flow through managed execution with timeouts.
Error Handling: Two-tier anyhow/thiserror approach is consistently applied. Production code uses ? operator almost universally. unwrap() is confined to test code and LazyLock<Regex> static initialization (acceptable).
| Metric | Count |
|---|---|
Source files (src/) |
826 |
Test files (tests/) |
176 |
| Total source LOC | 139,286 |
| Test LOC (inline) | ~31,675 |
| Integration test LOC | ~28,073 |
| Files >500 LOC (non-test) | 12 |
| Files >400 LOC (non-test) | 34 |
Files with //! docs |
826 (100%) |
Production unwrap() (non-test, non-LazyLock) |
~0 |
Production unsafe blocks |
15 |
unsafe blocks with SAFETY comment |
10 |
unsafe blocks missing SAFETY comment |
5 |
.clone() calls (non-test) |
820 |
| Logging calls | 528 |
| Shell scripts | 21 |
Shell scripts with set -euo pipefail |
13 / 21 |
| Shell scripts missing strict mode | 8 (library scripts) |
eval in shell scripts |
0 |
todo!() macros |
0 |
unreachable!() in production |
1 |
🟠 [God Module / Size Limit] Multiple files exceed 500 LOC hard limit
- Files (12):
queue/operations/tests/batch.rs(753) — test file, but should still decomposerunner/execution/tests/plugin_trait_tests.rs(736)runner/execution/tests/stream.rs(708)queue/operations/tests/mutation.rs(691)config/tests.rs(598)runutil/execution/orchestration/tests.rs(574)session/tests.rs(536)runner/error.rs(530) ← productionqueue/operations/mutation.rs(522) ← productionqueue/operations/batch/mod.rs(512) ← productionqueue/operations/tests/status.rs(507)runner/execution/tests/process.rs(506)
- Problem: Violates AGENTS.md hard limit of 1,000 LOC and target of <500 LOC
- Impact: Maintenance burden, difficult to navigate large test suites
- Blast Radius: Queue operations, runner error classification, batch mutation
- Fix: Split test suites into focused subdirectories following the
runtime_tests/,ci_tests/,worker_tests/patterns already established. Forrunner/error.rs, consider extracting match-arm formatting into arunner/error/formatting.rs.
🟡 [Large Module] 34 non-test files exceed 400 LOC soft limit
- Notable files:
cli/machine/queue_docs.rs(494),commands/init/writers.rs(485),sanity/unknown_keys.rs(484),cli/scan.rs(478),contracts/runner.rs(463),runner/execution/plugin_executor.rs(460) - Problem: Files approaching the hard limit; proactively splitting reduces future risk
- Impact: Review fatigue, merge conflict density
- Fix: Extract sub-concerns following the established facade pattern
✅ [Facade Pattern] Consistently applied across 30+ module directories. Root modules contain only //! docs and re-exports. Implementation lives in companion files. This is exemplary.
✅ [Module Documentation] 100% coverage — all 826 source files have //! purpose/responsibilities/scope/usage/invariants headers.
✅ [Injection Prevention] CI gate argv validation in config/validation/ci_gate.rs rejects sh -c, cmd /C, pwsh -Command, powershell -Command. Shell launcher detection is comprehensive.
✅ [Path Traversal Prevention] Plugin executable resolution in plugins/registry.rs uses canonicalize to detect symlinks escaping plugin directory boundaries. Absolute paths are rejected.
✅ [Secrets Redaction] redaction/patterns.rs implements layered redaction: key-value pairs → bearer tokens → AWS keys → SSH blocks → hex tokens → env values. Well-structured and thorough.
✅ [Subprocess Safety] No raw Command::output() in production code. All subprocess execution flows through runutil::shell::execute_managed_command with timeout classes, bounded capture, and SIGINT-before-SIGKILL escalation.
✅ [No eval] Zero eval usage across all shell scripts.
🟠 [Unsafe Safety Comments] 5 unsafe blocks missing SAFETY documentation
- Files:
lock/pid.rs:47—CreateToolhelp32Snapshot(Windows) — no SAFETY commentlock/pid.rs:90—libc::kill(pid, 0)— no SAFETY commentlock/pid.rs:108—OpenProcess(Windows) — no SAFETY commentcommands/run/parallel/worker_command.rs:33—pre_execforsetpgid— no SAFETY commentrunutil/shell/execute.rs:75—pre_execforsetpgid— no SAFETY comment
- Problem: Rust convention requires every
unsafeblock to have a// SAFETY:comment explaining why the operation is sound - Impact: Review difficulty, certification/audit friction
- Fix: Add
// SAFETY:comments to all 5 remaining blocks following the pattern already used in sibling code
🟡 [Daemon setsid] commands/daemon/start.rs:120
- Violation:
unsafe { command.pre_exec(|| { libc::setsid(); Ok(()) }); } - Problem: Return value of
setsid()is silently ignored; failure could leave daemon in unexpected session state - Impact: Silent failure in daemon session isolation
- Fix: Check
setsid()return value and log on failure:if libc::setsid() == -1 { log::warn!("setsid failed: {}", std::io::Error::last_os_error()); }
🟡 [Large Enum Match] runner/error.rs
- Violation:
RunnerErrorhas 10 variants; theDisplayimpl andclassify()method each have large match blocks spanning ~200 lines - Problem: Adding a new error variant requires touching 4+ match arms in the same file
- Impact: Regression risk on error handling changes
- Fix: Consider a macro-driven approach or separate the
Displayimpl intorunner/error/display.rs
✅ [unwrap() in Production] Virtually zero unwrap() calls in non-test production code. The few that exist are in LazyLock<Regex> static initializers (which would panic at startup if the regex is invalid — a compile-time invariant). This is acceptable.
✅ [Constants Centralization] constants.rs (431 LOC) provides well-organized compile-time constants organized by domain (buffers, limits, timeouts, UI, etc.). Prevents magic number drift.
✅ [todo!() Absence] Zero todo!() macros in the entire codebase — all code paths are implemented.
🟡 [Clone Audit Warranted] 820 .clone() calls in non-test source
- Problem: Not all are problematic, but the volume suggests some hot-path cloning may exist
- Impact: Unnecessary heap allocations in runner streaming paths, queue loading
- Fix: Audit runner/execution/stream_reader.rs and queue loading paths for
Arcor borrowing alternatives where clones copy largeStringorVec
🟡 [unreachable!() in Production] notification/display.rs:59
- Violation:
unreachable!("loop notifications use loop path")inshow_task_notificationmatch arm - Problem: If a future caller passes
LoopCompletethrough this path, it panics at runtime - Impact: Potential runtime crash if the invariant is violated
- Fix: Return an error or no-op instead of panicking:
Ok(())with alog::warn!
✅ [Two-Tier Strategy] anyhow for propagation, thiserror for domain errors (RunnerError). Consistently applied.
✅ [Redacted Errors] RunnerError stores RedactedString for stdout/stderr, ensuring runner output is sanitized before display.
✅ [Context Propagation] Extensive use of .context() and .with_context() throughout the codebase.
🟡 [Silent Success Branches] Several Ok(_) => {} patterns in production:
fsutil/atomic.rs:39— persist success (intentional, but could log)undo/storage.rs:75— backup removal success (intentional)queue/backup.rs:41— backup success (intentional)- Problem: These are intentional no-ops but lack comments explaining why the success case is silently discarded
- Impact: Future readers may wonder if the branch was forgotten
- Fix: Add
// Intentional: success requires no actioncomments
✅ [Process Cleanup] ProcessCleanupGuard ensures streaming threads are joined even on early returns. SIGINT-before-SIGKILL escalation with configurable grace period.
✅ [Bounded Capture] All managed subprocesses use BoundedCapture with configurable byte limits (MANAGED_SUBPROCESS_CAPTURE_MAX_BYTES: 256KB, CI: 4MB).
✅ [Atomic Writes] write_atomic uses NamedTempFile with flush+sync before persist. Explicit temp file drop on persist failure prevents leaks.
✅ [Temp Cleanup] Startup runs cleanup_default_temp_dirs with configurable retention.
🟡 [Regex Initialization] 6 LazyLock<Regex> statics in prompts_internal/util.rs and queue/json_repair.rs
- Problem: These compile at first use and never deallocate; the patterns are compile-time known
- Impact: Minimal —
LazyLockis the correct pattern for this use case - Fix: No action needed; this is documented for awareness
🟡 [Sensitive Env Cache] redaction/env.rs caches all sensitive env values in a RwLock<Option<HashSet<String>>>
- Problem: If environment is large, this caches all values matching secret patterns. Cache is never invalidated.
- Impact: Stale secrets won't be redacted if they change during process lifetime; memory grows with env size
- Fix: Acceptable for a CLI tool — process lifetime is bounded. No action needed.
🟠 [Coverage Gaps] 528 of 826 source files (64%) have zero inline test coverage
- Problem: 263 files over 100 LOC lack even basic
#[cfg(test)]blocks - Impact: Regression risk in untested modules, especially:
cli/machine/queue_docs.rs(494 LOC, 0 tests)commands/task/decompose/support.rs(450 LOC, 0 tests)commands/scan.rs(454 LOC, 0 tests)commands/watch/processor.rs(438 LOC, 0 tests)commands/init/readme.rs(438 LOC, 0 tests)cli/scan.rs(478 LOC, 0 tests)cli/webhook.rs(377 LOC, 0 tests)prompts.rs(365 LOC, 0 tests)
- Fix: Prioritize test coverage for queue mutation, CLI output formatting, and prompt composition modules. These are high-value test targets because they transform user-visible data.
✅ [Integration Test Suite] 176 integration test files with ~28K LOC provide substantial end-to-end coverage.
✅ [Structured Logging] 528 log calls across debug (136), info (197), warn (151), error (56). Distribution is healthy.
✅ [Redacted Logger] RedactedLogger wraps the env_logger output to ensure secrets are never logged.
🟡 [Debug Logging in Hot Paths] Runner streaming and subprocess management paths could benefit from more debug logging for production diagnostics
- Impact: Difficult to diagnose streaming issues without RUST_LOG=debug
- Fix: Add debug logging for session ID extraction, stream buffer growth, and timeout checkpoint transitions
✅ [Precedence Chain] CLI flags → .cueloop/config.jsonc → ~/.config/cueloop/config.jsonc → schema defaults. Well-documented.
✅ [Validation] Config validation includes unknown key detection, CI gate argv validation, and schema enforcement.
✅ [JSONC Support] Both JSON and JSONC config files supported with comments.
🟠 [Missing Strict Mode] 8 of 21 shell scripts lack set -euo pipefail
- Files:
scripts/lib/cueloop-shell.shscripts/lib/release_changelog.shscripts/lib/release_pipeline.shscripts/lib/release_policy.shscripts/lib/release_publish_pipeline.shscripts/lib/release_state.shscripts/lib/release_verify_pipeline.shscripts/lib/release_verify_state.shscripts/lib/xcodebuild-lock.sh
- Problem: Library scripts sourced by entrypoint scripts. If sourced after
set -euo pipefailin the caller, strict mode propagates. But if sourced independently, errors are silently ignored. - Impact: Undefined variable usage or failed commands could go undetected in library functions
- Fix: Add
set -euo pipefailto all library scripts, or add a guard:[[ $- == *e* ]] || set -eto inherit the caller's strict mode only if available. Given these are sourced libraries, addingset -euo pipefailat the top is safest and most explicit.
-
Add SAFETY comments to 5 unsafe blocks — 15 minutes
lock/pid.rs(3 blocks)commands/run/parallel/worker_command.rs(1 block)runutil/shell/execute.rs(1 block)
-
Add
set -euo pipefailto 8 library shell scripts — 10 minutesscripts/lib/*.sh— prepend strict mode header
-
Replace
unreachable!()innotification/display.rs— 5 minutes- Use
log::warn!+ early return instead
- Use
-
Add comments to silent
Ok(_) => {}branches — 10 minutesfsutil/atomic.rs,undo/storage.rs,queue/backup.rs
-
Check
setsid()return value in daemon — 5 minutescommands/daemon/start.rs:120
-
Split 3 largest production files below 500 LOC
runner/error.rs(530) → extractDisplayimpl torunner/error/display.rsqueue/operations/mutation.rs(522) → extract bulk helpers toqueue/operations/mutation/helpers.rsqueue/operations/batch/mod.rs(512) → extract validation tobatch/validation.rs
-
Split top 3 test suites below 600 LOC
queue/operations/tests/batch.rs(753) → split intobatch_basic.rs,batch_edge_cases.rsrunner/execution/tests/plugin_trait_tests.rs(736) → split by trait methodrunner/execution/tests/stream.rs(708) → split by stream type
-
Add test coverage for highest-value untested modules
cli/machine/queue_docs.rs(494 LOC) — machine document generationcommands/scan.rs(454 LOC) — scan workflow orchestrationcommands/watch/processor.rs(438 LOC) — watch event processing
-
Clone audit for runner/queue hot paths — identify and eliminate unnecessary String/Vec clones in streaming and queue loading paths. Consider
Cow<str>or&strborrowing where possible. -
Proactive file decomposition — split remaining 31 files in the 400-500 LOC range before they breach the hard limit. Prioritize
cli/scan.rs,cli/machine/task.rs,commands/init/writers.rs.
| LOC | File |
|---|---|
| 530 | runner/error.rs |
| 522 | queue/operations/mutation.rs |
| 512 | queue/operations/batch/mod.rs |
| 499 | commands/run/parallel/status.rs |
| 499 | commands/run/parallel/state.rs |
| 494 | cli/machine/queue_docs.rs |
| 485 | commands/init/writers.rs |
| 484 | sanity/unknown_keys.rs |
| 478 | cli/scan.rs |
| 463 | contracts/runner.rs |
| 460 | runner/execution/plugin_executor.rs |
| 456 | git/status.rs |
| 454 | commands/scan.rs |
| 451 | commands/run/supervision/ci.rs |
| 451 | commands/run/parallel/cleanup_guard.rs |
| 450 | commands/task/decompose/support.rs |
| 438 | commands/watch/processor.rs |
| 438 | commands/init/readme.rs |
| 436 | commands/task/mod.rs |
| 436 | cli/machine/task.rs |