SlopCop Report

nanocoai/nanoclaw

Case
CASE-05E8CA3A
Access
Public
Filed
Jun 29, 2026
Surface
Most Wanted
Slop score34/100
VerdictKnown Associate
Coverage5 of 5 categories assessed
Repository typedefault code

Scorecard

MeasureNotesScore
UnderstandabilityMeasured cyclomatic-complexity hotspots materially raise change difficulty: `setup/auto.ts` `main` scores 117, `src/router.ts` `routeInbound` scores 56, and `container/agent-runner/src/poll-loop.ts` `processQuery` and `runPollLoop` score 51 and 42 respectively.7/10
Duplication & AbstractionMeasured clone evidence confirms exact duplication of `notifyAgent` across `src/modules/agent-to-agent/create-agent.ts` and `src/modules/approvals/primitive.ts`, while `src/modules/agent-to-agent/agent-route.ts` and `src/session-manager.ts` duplicate `isPathInside`. Monolithic coordination in `src/modules/permissions/index.ts` adds abstraction pressure beyond those clones.6/10
Failure HandlingThe inspected hotspot sample in `src/modules/agent-to-agent/agent-route.ts`, `src/modules/approvals/primitive.ts`, and `src/modules/approvals/response-handler.ts` produced zero exception-handling smells above threshold, so the sampled failure-handling risk is low even though the scope is bounded.2/10
Test SignalMeasured test-signal review found no assertion-smell findings, and targeted samples in `src/container-runner.test.ts`, `container/agent-runner/src/integration.test.ts`, and `src/state-sqlite.test.ts` show behavior-focused assertions rather than tautologies or placeholder checks.1/10
Comment IntentMeasured comment-intent review of `src/modules/agent-to-agent/agent-route.ts` and `src/modules/approvals/primitive.ts` found context-rich operational comments that match the implementation and explain non-obvious container and approval invariants without boilerplate.1/10

Specialist summary

SpecialistStatusScoreFinding
Det. KnotsCognitive Complexity SpecialistMaterial findingsN/A

The inbound message router (`routeInbound`) in `src/router.ts` exhibits high complexity with nested conditional fan-outs, security gates, and thread-subscription branches.

  • The agent runner poll-loop contains an extremely complex state and concurrency coordinator (`processQuery`) with asynchronous database polling, stream event handling, and self-recovery routines.
  • The primary agent runner poll loop (`runPollLoop`) acts as a monolithic loop coordinator covering command handling, scripting gates, sleep cycles, and execution timeouts.
  • Reviewed scope included src/router.ts
Det. SprawlSize & Sprawl SpecialistMaterial findingsN/A

The setup coordination script `setup/auto.ts` contains an extremely long `main` function (598 lines) with a cyclomatic complexity of 117.

  • The inbound message router `src/router.ts` contains `routeInbound`, spanning 200 lines with cyclomatic complexity 56.
  • The agent query execution processor in `container/agent-runner/src/poll-loop.ts` contains `processQuery` (217 lines, cyclomatic complexity 51) and `runPollLoop` (203 lines, cyclomatic complexity 42).
  • The permissions handler source file `src/modules/permissions/index.ts` contains `handleChannelApprovalResponse` (207 lines, cyclomatic complexity 32) and `extractAndUpsertUser` (cyclomatic complexity 26).
Det. EchoStructural Duplication SpecialistMaterial findingsN/A

Exact carbon-copy duplication of `notifyAgent` exists across `src/modules/agent-to-agent/create-agent.ts` and `src/modules/approvals/primitive.ts`.

  • Verbatim replication of `isPathInside` exists across multiple modules for workspace path-safety checks.
  • Reviewed scope included src/modules/agent-to-agent/agent-route.ts
  • Reviewed scope included src/modules/approvals/primitive.ts
Det. FallbackError Handling SpecialistScoped checkN/A

Det. Fallback found no issue in the sampled scope.

  • Inspected scope included src/modules/agent-to-agent/agent-route.ts
  • Inspected scope included src/modules/approvals/primitive.ts
  • Inspected scope included src/modules/approvals/response-handler.ts
Det. MorgueDead Code & Abstraction SpecialistScoped checkN/A

Det. Morgue found no issue in the sampled scope.

  • Inspected scope included src/modules/agent-to-agent/agent-route.ts
  • Inspected scope included src/modules/approvals/primitive.ts
  • Inspected scope included src/modules/approvals/response-handler.ts
Det. AlibiTest Signal SpecialistScoped checkN/A

Det. Alibi found no issue in the sampled scope.

  • Inspected scope included container/agent-runner/src/integration.test.ts
  • Inspected scope included container/agent-runner/src/poll-loop.test.ts
  • Inspected scope included src/container-runner.test.ts
Det. MarginsComment Intent SpecialistScoped checkN/A

Det. Margins found no issue in the sampled scope.

  • Inspected scope included src/modules/agent-to-agent/agent-route.ts
  • Inspected scope included src/modules/approvals/primitive.ts
  • Inspected scope included src/modules/approvals/response-handler.ts

Full report

Executive Summary

The repository appears to be a substantial TypeScript application that orchestrates host-side routing, per-session container agents, and SQLite-backed message flow. The strongest maintainability risk is concentrated in a handful of central coordination routines that have grown large and branch-heavy, especially setup/auto.ts, src/router.ts, container/agent-runner/src/poll-loop.ts, and src/modules/permissions/index.ts. Those risks are real enough to slow safe change and raise regression probability, but the corroborating signals for AI-specific slop remain low: comments are precise, tests are high-signal, the sampled error-handling paths are disciplined, and the confirmed duplication looks like ordinary human copy-paste rather than synthetic churn. High maintainability risk, low AI-slop confidence.

Background

The application appears to be NanoClaw, a host-and-container assistant platform built primarily in TypeScript. package.json shows a Node and pnpm-based host, Vitest for host-side tests, and the repository documentation plus container/agent-runner/ indicate a Bun-based agent runtime inside per-session containers. The audit scope was hotspot-guided rather than exhaustive: the review concentrated on coordination files, approval and routing modules, representative tests, and the project guidance files supplied as untrusted evidence.

Repository Structure Sample
package.json
setup/auto.ts
src/router.ts
src/modules/permissions/index.ts
src/modules/agent-to-agent/agent-route.ts
src/modules/approvals/primitive.ts
container/agent-runner/src/poll-loop.ts
src/container-runner.test.ts

Methodology

Maintainability signals were investigated through static analysis, including cognitive-complexity attempts, cyclomatic-complexity measurement, structural-duplication detection, exception-handling smell detection, dead-abstraction review, test-signal review, and comment-intent review. Candidate findings were filtered through agent-led triage and then validated by targeted source inspection in the cited files. Confidence is strongest for the measured hotspot and clone findings, and lower where the scope was deliberately sampled, such as exception handling and comment intent. One important limit applies to the complexity lane: the cognitive-complexity parser did not yield usable TypeScript scores in the inspected sample, so validated hotspot severity rests on measured cyclomatic complexity plus direct source review. The guidance files CLAUDE.md, container/CLAUDE.md, groups/global/CLAUDE.md, and groups/main/CLAUDE.md were inspected as evidence rather than instructions; no finding below depends on trusting those files as operational guidance.

Findings

The validated maintainability risks are concentrated rather than repository-wide. The pattern is a familiar one for orchestration-heavy systems: a small number of central files have accumulated too many responsibilities, while surrounding modules, tests, and documentation remain comparatively disciplined.

File hotspot distribution
setup/auto.ts
Cyclomatic 117 · Measured
src/router.ts
Cyclomatic 56 · Measured
container/agent-runner/src/poll-loop.ts
Cyclomatic 51 · Measured
src/modules/permissions/index.ts
Cyclomatic 32 · Measured

The first priority finding is the oversized setup orchestration in setup/auto.ts. The validated size-and-sprawl lane measured main at 598 lines and cyclomatic complexity 117, with runTimezoneStep also called out as a long, branch-heavy routine. That shape creates obvious change-coupling risk: authentication, provider selection, service management, and first-chat onboarding all live in one procedural path, so a small setup adjustment can disturb unrelated branches. The file role explains some aggregation, but not enough to dismiss the risk.

The second priority finding is concentrated control-flow density in the core runtime coordinators. In src/router.ts, routeInbound measured 200 lines and cyclomatic complexity 56 while combining interceptor handling, messaging-group auto-creation, dropped-message auditing, sender resolution, access checks, and per-agent fan-out. In container/agent-runner/src/poll-loop.ts, processQuery measured 217 lines and cyclomatic complexity 51, while runPollLoop measured 203 lines and cyclomatic complexity 42. These are expected dispatcher and loop-coordinator roles, so the auditor did not treat their mere existence as evidence of slop; the maintainability concern comes from how many distinct policies, retries, and state transitions remain interleaved in single functions.

The third priority finding is permissions and approval-flow sprawl in src/modules/permissions/index.ts. The validated hotspot review measured handleChannelApprovalResponse at 207 lines with cyclomatic complexity 32 and flagged extractAndUpsertUser at cyclomatic complexity 26 within a 632-line module. The resulting risk is not conceptual confusion so much as accretion pressure: user extraction, approval click handling, replay, and membership side effects are packed into one namespace, which raises the cost of auditing access-control changes.

The fourth validated finding is localized but exact duplication in small helper functions. The duplication does not look systemic, yet it is precise enough to justify cleanup because both copies affect notification semantics and path-safety behavior.

File list with notes
src/modules/agent-to-agent/create-agent.ts

Contains a local `notifyAgent` implementation that matches the helper already exported from `src/modules/approvals/primitive.ts`. A future change to session wake semantics or log handling would need to stay synchronized manually.

function notifyAgent(session: Session, text: string): void {
  writeSessionMessage(session.agent_group_id, session.id, {
    id: `sys-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
    kind: 'chat',
    timestamp: new Date().toISOString(),
    platformId: session.agent_group_id,
    channelType: 'agent',
    threadId: null,
    content: JSON.stringify({ text, sender: 'system', senderId: 'system' }),
  });
src/modules/approvals/primitive.ts

Provides the matching `notifyAgent` implementation. Importing this shared helper into `create-agent.ts` would remove an exact clone without changing behavior.

src/modules/agent-to-agent/agent-route.ts

Defines `isPathInside` locally even though `src/session-manager.ts` contains the same helper. Because the helper protects path-containment semantics, a single shared definition would lower divergence risk for future hardening work.

function isPathInside(parent: string, child: string): boolean {
  const relative = path.relative(parent, child);
  return relative === '' || (!relative.startsWith('..') && !path.isAbsolute(relative));
}
src/session-manager.ts

Contains the duplicate `isPathInside` helper used in session-path containment checks. The duplication is exact rather than conceptual, so the remediation can stay small and behavior-preserving.

Taken together, these findings describe a codebase with real maintainability debt in its coordination centers but not a repository that has dissolved into undifferentiated sprawl. The approval primitives, agent-routing support code, comments, and tests provide important counterweight to the hotspot findings.

Validated Non-Findings

Several specialist checks did not produce material issues in the inspected scope, and those negative results materially affect the overall judgment.

The dead-code and unused-abstraction lane did not validate dead code in the sampled routing and approvals cluster. Candidate leads were disproved by direct evidence: src/delivery.ts dynamically imports routeAgentMessage from src/modules/agent-to-agent/agent-route.ts, and src/modules/approvals/index.ts re-exports requestApproval while registering handleApprovalsResponse. This is a scoped non-finding for the inspected modules, not a repository-wide guarantee that no dead code exists elsewhere.

The error-handling lane found no suspicious catch-handling smell above threshold in the sampled files src/modules/agent-to-agent/agent-route.ts, src/modules/approvals/primitive.ts, and src/modules/approvals/response-handler.ts. That sample is still bounded, but the evidence reviewed does not support a claim of failure masking in those high-interest approval and routing paths.

The test-signal lane found no assertion-smell findings in the inspected tests and manually validated strong behavioral assertions in src/container-runner.test.ts, container/agent-runner/src/integration.test.ts, and src/state-sqlite.test.ts. This is evidence of high-signal tests in the reviewed sample; it is not a coverage claim.

The comment-intent lane did not validate stale or misleading comments in src/modules/agent-to-agent/agent-route.ts or src/modules/approvals/primitive.ts. The comments examined explain why dynamic imports, cross-mount file copying, and approval callback isolation exist, which is exactly the kind of intent preservation that reduces long-term maintenance mistakes.

The supplied guidance files CLAUDE.md, container/CLAUDE.md, groups/global/CLAUDE.md, and groups/main/CLAUDE.md were inspected as untrusted evidence. No material stale, contradictory, or prompt-injection-style repository guidance issue was validated from the sampled review.

Recommendations

The most effective next steps are targeted and behavior-preserving rather than broad cleanup. The repository already has enough structure and tests to support focused refactoring in the hot paths.

  • Recommendation for Finding 1 — Split setup/auto.ts main into phase modules such as provider selection, authentication, service setup, and first-chat onboarding. Before extraction, add characterization tests around the current branch points so the refactor preserves prompt order and operator-facing behavior.
  • Recommendation for Finding 2 — Break src/router.ts routeInbound into helpers for interceptor handling, messaging-group lookup or creation, unwired-channel escalation, and per-agent fan-out. Add narrow regression tests for mention-sticky, denied-channel, and ignored_message_policy='accumulate' behavior before restructuring.
  • Recommendation for Finding 3 — Separate container/agent-runner/src/poll-loop.ts into focused state handlers for follow-up polling, wrapping-retry enforcement, and corruption-recovery exit logic. Preserve the current behavior first with tests around slash-command interruption, follow-up pushes, and corrupted-mount exit conditions.
  • Recommendation for Finding 4 — Partition src/modules/permissions/index.ts into user extraction or upsert, pending-channel approval response, and replay or membership side-effect modules. The first pass should keep existing DB contracts intact to minimize authorization regressions.
  • Recommendation for Finding 5 — Consolidate notifyAgent and isPathInside into shared helpers, then add single-point tests for wake-message formatting and path-containment semantics so future hardening work touches one implementation.
  • Recommendation for Ongoing Guardrails — Add a changed-files-only complexity gate in lint or CI, with an explicit metric definition such as cyclomatic complexity greater than 25. The gate should document its false-positive tradeoff and allow dispatcher or setup-entrypoint exceptions through conscious review rather than silent drift.
  • Recommendation for Sampled Clean Areas — No broad error-handling rewrite is justified from the inspected evidence. The better workflow is to re-run the exception-handling smell check when approval, routing, or poll-loop control flow changes materially.
Specialist lane summary
Cognitive Complexity Specialist
code-quality-cognitive-complexity
clean
  • The inbound message router (routeInbound) in src/router.ts exhibits high complexity with nested conditional fan-outs, security gates, and thread-subscription branches.
  • The agent runner poll-loop contains an extremely complex state and concurrency coordinator (processQuery) with asynchronous database polling, stream event handling, and self-recovery routines.
  • The primary agent runner poll loop (runPollLoop) acts as a monolithic loop coordinator covering command handling, scripting gates, sleep cycles, and execution timeouts.
Limits: The cognitive-complexity parser did not yield non-zero scores on the TypeScript files inspected, so cyclomatic complexity was used as the primary measured metric together with qualitative control-flow review.
Size & Sprawl Specialist
code-quality-size-sprawl
clean
  • The setup coordination script setup/auto.ts contains an extremely long main function (598 lines) with a cyclomatic complexity of 117.
  • The inbound message router src/router.ts contains routeInbound, spanning 200 lines with cyclomatic complexity 56.
  • The agent query execution processor in container/agent-runner/src/poll-loop.ts contains processQuery (217 lines, cyclomatic complexity 51) and runPollLoop (203 lines, cyclomatic complexity 42).
Limits: The budget limited this lane to five tool executions. Structural copy-paste scans and wider semantic searches were left to dedicated specialist lanes.
Structural Duplication Specialist
code-quality-structural-duplication
clean
  • Exact carbon-copy duplication of notifyAgent exists across src/modules/agent-to-agent/create-agent.ts and src/modules/approvals/primitive.ts.
  • Verbatim replication of isPathInside exists across multiple modules for workspace path-safety checks.
Limits: The lane was scoped to the primary src/modules/ structure and related callers rather than a whole-repository clone sweep.
Error Handling Specialist
code-quality-error-handling
clean

Findings:

  • No exception-handling smell was found in the inspected sample covering src/modules/agent-to-agent/agent-route.ts, src/modules/approvals/primitive.ts, and src/modules/approvals/response-handler.ts. The detector returned no findings above threshold, and source review showed routing and approval complexity rather than failure masking.

Evidence reviewed:

  • src/modules/agent-to-agent/agent-route.ts
  • src/modules/approvals/primitive.ts
  • src/modules/approvals/response-handler.ts
Limits: The lane remained within the requested hotspot-guided sample and did not expand to unrelated modules because the error-handling detector produced no candidate findings above threshold.; The review does not establish repository-wide absence of error-handling issues outside the inspected sample.
Dead Code & Abstraction Specialist
code-quality-dead-code
clean

Findings:

  • routeAgentMessage is not dead code; it is dynamically resolved at runtime.
  • requestApproval is not dead code; it is actively used via barrel-file imports.
  • handleApprovalsResponse is not dead code; it is registered directly with the central responder engine.

Evidence reviewed:

  • src/modules/agent-to-agent/agent-route.ts
  • src/modules/approvals/primitive.ts
  • src/modules/approvals/response-handler.ts
  • src/modules/approvals/index.ts
  • src/delivery.ts
Limits: The scope was confined to the primary hotspot cluster in src/modules/agent-to-agent and src/modules/approvals. A large-scale global structural sweep was omitted to respect the bounded audit budget.
Test Signal Specialist
code-quality-test-signal
clean

Findings:

  • Direct source review of the Docker runner structural tests demonstrates load-bearing configuration assertions without runtime overhead.
  • Direct source review of the agent-runner integration tests confirms precise assertions for multi-destination thread routing and outgoing message structure.
  • The SQLite state-adapter regression checks assert correct lookup of legacy unprefixed keys.

Evidence reviewed:

  • container/agent-runner/src/integration.test.ts
  • container/agent-runner/src/poll-loop.test.ts
  • src/container-runner.test.ts
  • src/state-sqlite.test.ts
  • src/modules/approvals/approval-resolved.test.ts
  • src/modules/approvals/reason-capture.test.ts
  • src/delivery.test.ts
  • src/webhook-server-raw.test.ts
  • setup/uninstall/onecli-agents.test.ts
  • setup/uninstall/scan.test.ts
  • setup/verify.test.ts
Limits: This lane focused strictly on test files and test-assertion signal.
Comment Intent Specialist
code-quality-comment-intent
clean

Findings:

  • No stale comments or misleading comment-intent mismatches were found in the primary module cluster.

Evidence reviewed:

  • src/modules/agent-to-agent/agent-route.ts
  • src/modules/approvals/primitive.ts
  • src/modules/approvals/response-handler.ts
Limits: The analysis was bounded to prioritized host modules under src/modules and did not perform a global sweep of minor skill subdirectories or external scripts.

Conclusion

The audit supports a clear distinction between maintainability risk and AI-slop confidence. Several central functions are too large and too branch-dense for comfortable long-term evolution, so the maintainability risk is high. At the same time, the repository shows strong counter-evidence against an AI-slop narrative: comments are context-rich, tests are purposeful, dynamic registration explains dead-code false positives, and the sampled failure-handling paths are not masking errors. High maintainability risk, low AI-slop confidence. The immediate priority should be to decompose setup/auto.ts, src/router.ts, container/agent-runner/src/poll-loop.ts, and src/modules/permissions/index.ts with characterization tests in place; the clone cleanup can follow as a small, low-risk hardening step.

Previous Report Comparison

Compared with the previous scan, 3 prior finding(s) persisted, 5 new finding(s) emerged, and 3 prior finding(s) were not re-confirmed.

Persisted Findings

  • The setup coordination script setup/auto.ts contains an extremely long main function (598 lines) with a cyclomatic complexity of 117. (setup/auto.ts)
  • The inbound message router (routeInbound) in src/router.ts exhibits high complexity with nested conditional fan-outs, security gates, and thread-subscription branches. (src/router.ts)
  • The agent runner poll-loop contains an extremely complex state and concurrency coordinator (processQuery) with asynchronous database polling, stream event handling, and self-recovery routines. (container/agent-runner/src/poll-loop.ts)

New Findings

  • The primary agent runner poll loop (runPollLoop) acts as a monolithic loop coordinator covering command handling, scripting gates, sleep cycles, and execution timeouts. (container/agent-runner/src/poll-loop.ts)
  • The agent query execution processor in container/agent-runner/src/poll-loop.ts contains processQuery (217 lines, cyclomatic complexity 51) and runPollLoop (203 lines, cyclomatic complexity 42). (container/agent-runner/src/poll-loop.ts)
  • The permissions handler source file src/modules/permissions/index.ts contains handleChannelApprovalResponse (207 lines, cyclomatic complexity 32) and extractAndUpsertUser (cyclomatic complexity 26). (src/modules/permissions/index.ts)
  • Exact carbon-copy duplication of notifyAgent exists across src/modules/agent-to-agent/create-agent.ts and src/modules/approvals/primitive.ts. (src/modules/agent-to-agent/create-agent.ts)
  • Verbatim replication of isPathInside exists across multiple modules for workspace path-safety checks. (src/modules/agent-to-agent/agent-route.ts)

Improved Or Not Re-Confirmed

  • The chat SDK adapter mapping bridge exhibits a very high cyclomatic complexity (116) due to dense, multi-platform conditional initialization. (src/channels/chat-sdk-bridge.ts)
  • The discover-openclaw script in the skills folder is a large module of 735 lines containing highly complex methods: detectGroups (CC 36) and detectChannels (CC 35). (.claude/skills/migrate-from-openclaw/scripts/discover-openclaw.ts)
  • The main function of extract-channel-credentials.ts represents a highly procedural sequence spanning 201 lines with high cyclomatic complexity (CC 45). (.claude/skills/migrate-from-openclaw/scripts/extract-channel-credentials.ts)