feat(cli): add type-safety hotspot report#2082
Conversation
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds a TypeScript "type-safety hotspots" analysis CLI and tests; strengthens runtime parsing/validation across agent manifests, config/migration state, onboarding sessions, platform detection, and tiers; updates troubleshooting docs to warn that Changes
Sequence Diagram(s)sequenceDiagram
participant User as User (CLI)
participant Script as type-safety-hotspots.ts
participant TS as TypeScript Compiler API
participant FS as File System
participant Reporter as Report Renderer
User->>Script: run CLI (args)
Script->>FS: read tsconfig + source files
Script->>TS: parse & type-check files
TS-->>Script: ASTs + type info
Script->>Script: analyze weak-typing, build graph, score hotspots
Script->>Reporter: format text/JSON report
Reporter-->>User: output report
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
nemoclaw/src/commands/migration-state.ts (1)
262-276:⚠️ Potential issue | 🟡 MinorPass
envthrough external-root path resolution
detectHostOpenClawaccepts anenvparameter, but on Line 430collectExternalRoots(config, stateDir)still resolves paths with implicitprocess.env(viadefaultWorkspacePath()andresolveUserPath()inregisterRoot). This can produce inconsistent roots vs.workspaceDirwhen callers pass a non-default env.💡 Proposed fix
-function collectExternalRoots( - config: OpenClawConfigDocument | null, - stateDir: string, -): { roots: MigrationExternalRoot[]; warnings: string[]; errors: string[] } { +function collectExternalRoots( + config: OpenClawConfigDocument | null, + stateDir: string, + env: NodeJS.ProcessEnv = process.env, +): { roots: MigrationExternalRoot[]; warnings: string[]; errors: string[] } { @@ - const defaultsWorkspace = readTrimmedString(agentDefaults?.workspace); - const defaultWorkspace = defaultsWorkspace ?? defaultWorkspacePath(); + const defaultsWorkspace = readTrimmedString(agentDefaults?.workspace); + const defaultWorkspace = defaultsWorkspace + ? resolveUserPath(defaultsWorkspace, env) + : defaultWorkspacePath(env); @@ - pathValue: workspace, + pathValue: resolveUserPath(workspace, env), @@ - pathValue: agentDir, + pathValue: resolveUserPath(agentDir, env), @@ - pathValue: extraDir, + pathValue: resolveUserPath(extraDir, env), @@ - const rootInfo = collectExternalRoots(config, stateDir); + const rootInfo = collectExternalRoots(config, stateDir, env);Also applies to: 296-310, 328-329, 430-430
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nemoclaw/src/commands/migration-state.ts` around lines 262 - 276, collectExternalRoots must accept and forward the environment object so path resolution uses the same env as detectHostOpenClaw: add an env parameter to collectExternalRoots and use it when calling defaultWorkspacePath (e.g., defaultWorkspacePath(env)) and when resolving user paths inside registerRoot (replace resolveUserPath(...) with resolveUserPath(..., env) or otherwise pass env through to that helper); update callers (including detectHostOpenClaw) to pass their env through so workspace/default paths and any resolveUserPath uses are consistent across the call chain (refer to functions collectExternalRoots, registerRoot, defaultWorkspacePath, resolveUserPath, and detectHostOpenClaw).src/lib/onboard-session.ts (1)
706-729:⚠️ Potential issue | 🟠 MajorRe-sanitize
failurebefore returning debug summaries.
endpointUrlis redacted on the way out, butfailureis passed through verbatim. BecausecreateSession()still acceptsoverrides.failureunchanged,summarizeForDebug()can leak raw bearer/API tokens when it is called with an in-memory session object instead of one that already went throughnormalizeSession().🔐 Proposed fix
- failure: session.failure, + failure: sanitizeFailure(session.failure),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/onboard-session.ts` around lines 706 - 729, summarizeForDebug currently redacts endpointUrl but returns session.failure verbatim, which can leak tokens when called with an in-memory session; update summarizeForDebug to re-sanitize the failure before returning (e.g., call the existing normalizeSession or a dedicated redactFailure helper to strip/replace bearer/API tokens and other secrets from session.failure) and return the sanitized failure field instead of the raw session.failure; reference summarizeForDebug, normalizeSession, redactUrl, and createSession to locate where to apply the sanitization.src/lib/platform.ts (1)
90-103:⚠️ Potential issue | 🟡 MinorReturn empty candidates on unsupported platforms.
Line 102 currently returns Linux Podman socket paths for any non-
darwinplatform (includingwin32). SincegetPodmanSocketCandidatesis exported, direct callers can get invalid paths outside Linux/macOS.Suggested fix
function getPodmanSocketCandidates(opts: PlatformLookupOptions = {}): string[] { const home = opts.home ?? process.env.HOME ?? "/tmp"; const platform = opts.platform ?? process.platform; const uid = opts.uid ?? process.getuid?.() ?? 1000; if (platform === "darwin") { return [ path.join(home, ".local/share/containers/podman/machine/podman.sock"), "/var/run/docker.sock", ]; } - return [`/run/user/${String(uid)}/podman/podman.sock`, "/run/podman/podman.sock"]; + if (platform === "linux") { + return [`/run/user/${String(uid)}/podman/podman.sock`, "/run/podman/podman.sock"]; + } + + return []; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/platform.ts` around lines 90 - 103, getPodmanSocketCandidates currently returns Linux socket paths for any non-"darwin" platform, which yields invalid candidates on unsupported platforms like "win32"; update getPodmanSocketCandidates to explicitly handle platforms: return macOS paths when opts.platform/process.platform === "darwin", return Linux paths when platform === "linux" (using uid from opts.uid/process.getuid()), and return an empty array for all other platforms so callers don't receive invalid socket paths. Ensure references to opts.platform, process.platform, opts.uid, process.getuid, and the uid variable remain correct when implementing the branching.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.agents/skills/nemoclaw-user-reference/references/troubleshooting.md:
- Around line 359-364: Update step 3 in troubleshooting.md to recommend using
the existing automated command by replacing the manual backup/recreate
instruction with guidance to run the documented "nemoclaw <name> rebuild"
command (which performs backup, destroys the old sandbox, recreates it with the
current image, and restores state); ensure the text references the exact command
syntax "nemoclaw <name> rebuild" and optionally points readers to the earlier
section that documents that command (lines describing the rebuild behavior) for
consistency and safety.
In `@scripts/type-safety-hotspots.ts`:
- Around line 14-15: The current tsDirectiveCount uses countMatches(text,
COMMENT_DIRECTIVE_RE) which scans the whole file and picks up directives inside
strings; instead extract only comment text and run the regex against that: use
the TypeScript compiler API (e.g., ts.getLeadingCommentRanges and
ts.getTrailingCommentRanges on the SourceFile.getFullText()) or iterate over all
comment ranges via ts.forEachChild and collect comment ranges, concatenate their
substrings and call countMatches(commentsText, COMMENT_DIRECTIVE_RE) to compute
tsDirectiveCount; update any other uses (e.g., where `@ts-nocheck` was already
handled) to use the same comment-only extraction logic.
- Around line 392-504: The containsWeakType function is too large and should be
split into smaller per-node-kind helpers (e.g., handleParenthesizedType,
handleArrayType, handleTupleType, handleUnionIntersection, handleTypeLiteral,
handleTypeReference, handleFunctionOrConstructorType, handleConditionalType,
etc.) and a small dispatch table to call the correct handler for each
ts.TypeNode kind; each helper should accept (typeNode, aliases, seen) and return
boolean, preserve existing logic (including new Set(seen) where currently used),
and ensure containsWeakType becomes a thin dispatcher that delegates to these
helpers (or the map) to reduce cyclomatic complexity.
In `@src/lib/agent-defs.ts`:
- Around line 113-118: The code currently accepts any finite number for port
fields; update validation so ports are whole TCP port integers in the valid
range. In readNumberArray (and the equivalent single-number reader used for
health_probe.port) only accept entries where Number.isInteger(entry) is true and
entry >= 1 && entry <= 65535, filter out others and return undefined if no valid
ports remain; add the same integer+range check where health_probe.port is parsed
(referencing readNumberArray and the health probe parsing logic) so manifest
load fails fast on invalid ports.
---
Outside diff comments:
In `@nemoclaw/src/commands/migration-state.ts`:
- Around line 262-276: collectExternalRoots must accept and forward the
environment object so path resolution uses the same env as detectHostOpenClaw:
add an env parameter to collectExternalRoots and use it when calling
defaultWorkspacePath (e.g., defaultWorkspacePath(env)) and when resolving user
paths inside registerRoot (replace resolveUserPath(...) with
resolveUserPath(..., env) or otherwise pass env through to that helper); update
callers (including detectHostOpenClaw) to pass their env through so
workspace/default paths and any resolveUserPath uses are consistent across the
call chain (refer to functions collectExternalRoots, registerRoot,
defaultWorkspacePath, resolveUserPath, and detectHostOpenClaw).
In `@src/lib/onboard-session.ts`:
- Around line 706-729: summarizeForDebug currently redacts endpointUrl but
returns session.failure verbatim, which can leak tokens when called with an
in-memory session; update summarizeForDebug to re-sanitize the failure before
returning (e.g., call the existing normalizeSession or a dedicated redactFailure
helper to strip/replace bearer/API tokens and other secrets from
session.failure) and return the sanitized failure field instead of the raw
session.failure; reference summarizeForDebug, normalizeSession, redactUrl, and
createSession to locate where to apply the sanitization.
In `@src/lib/platform.ts`:
- Around line 90-103: getPodmanSocketCandidates currently returns Linux socket
paths for any non-"darwin" platform, which yields invalid candidates on
unsupported platforms like "win32"; update getPodmanSocketCandidates to
explicitly handle platforms: return macOS paths when
opts.platform/process.platform === "darwin", return Linux paths when platform
=== "linux" (using uid from opts.uid/process.getuid()), and return an empty
array for all other platforms so callers don't receive invalid socket paths.
Ensure references to opts.platform, process.platform, opts.uid, process.getuid,
and the uid variable remain correct when implementing the branching.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: ff43f1e1-7646-470c-b522-6feb0b8ca6d7
📒 Files selected for processing (11)
.agents/skills/nemoclaw-user-reference/references/troubleshooting.mdnemoclaw/src/commands/migration-state.tspackage.jsonscripts/type-safety-hotspots.tssrc/lib/agent-defs.test.tssrc/lib/agent-defs.tssrc/lib/onboard-session.tssrc/lib/platform.tssrc/lib/tiers.tstest/policy-tiers.test.tstest/type-safety-hotspots.test.ts
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
There was a problem hiding this comment.
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 `@scripts/type-safety-hotspots.ts`:
- Around line 883-884: The current scan only updates the file-level metric via
addPattern(fileMetrics, "tsDirectiveCount", countDirectiveComments(text)) and
never increments RawFunctionData.tsDirectiveCount, so inline TS suppressions
inside functions are missed by computeFunctionRawUnsafety() and
buildFunctionReasons(); modify the scanner that calls countDirectiveComments to
preserve each directive's position and, for each directive whose location falls
within the source range of the active functionStack entry, increment that
functionStack entry's RawFunctionData.tsDirectiveCount (and still increment the
fileMetrics counter), ensuring directive positions are captured and attributed
to the correct function.
- Around line 634-639: The matcher currently recognizes JSON.parse/JSON5.parse
and yaml.load (lowercase) plus YAML.parse (uppercase), but misses YAML.load
(uppercase); update the conditional that returns the parse boundary to also
match (owner.text === "YAML" && member === "load") and ideally consolidate the
YAML checks so both owner.text values ("YAML" and "yaml") accept both member
values ("parse" and "load")—modify the expression around the existing owner.text
=== "YAML"/"yaml" and member checks (the returned boolean expression) to include
these additional conditions or replace with a small set/array membership test to
cover both namespaces and both methods.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: ebb76ddb-46ed-4c9e-875b-f17dc598cb3e
📒 Files selected for processing (12)
.agents/skills/nemoclaw-user-reference/references/troubleshooting.mddocs/reference/troubleshooting.mdnemoclaw/src/commands/migration-state.test.tsnemoclaw/src/commands/migration-state.tsscripts/type-safety-hotspots.tssrc/lib/agent-defs.test.tssrc/lib/agent-defs.tssrc/lib/onboard-session.test.tssrc/lib/onboard-session.tssrc/lib/platform.tstest/platform.test.tstest/type-safety-hotspots.test.ts
✅ Files skipped from review due to trivial changes (4)
- test/platform.test.ts
- .agents/skills/nemoclaw-user-reference/references/troubleshooting.md
- docs/reference/troubleshooting.md
- src/lib/onboard-session.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- src/lib/agent-defs.ts
- nemoclaw/src/commands/migration-state.ts
- src/lib/agent-defs.test.ts
- src/lib/platform.ts
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
ericksoa
left a comment
There was a problem hiding this comment.
Code reviewed: type-safety refactoring is clean, new hotspot tool has good test coverage, all CI green. LGTM.
Summary
Add a
type-safety:hotspotsdeveloper command that ranks files and functions by type-safety ROI, then use it to refactor the first wave of high-value hotspots it surfaced. This gives contributors a repeatable way to prioritize typing work and knocks down the initial top five hotspots the new tool identified.Changes
scripts/type-safety-hotspots.tsandnpm run type-safety:hotspots, plus tests covering hotspot scoring and@ts-nocheckdetectionsrc/lib/onboard-session.ts,src/lib/tiers.ts,src/lib/platform.ts,nemoclaw/src/commands/migration-state.ts, andsrc/lib/agent-defs.ts@ts-nocheckfromtiers.tsandplatform.ts, and addsrc/lib/agent-defs.test.tstest/policy-tiers.test.tsfor the stricter nullablegetTier()surface exposed by the new typing work180/117/111/107/102to61/11/0/36/13foronboard-session,tiers,platform,migration-state, andagent-defsType of Change
Verification
npx prek run --all-filespassesnpm testpassesmake docsbuilds without warnings (doc changes only)AI Disclosure
Signed-off-by: Carlos Villela cvillela@nvidia.com
Summary by CodeRabbit
openclaw update, documenting cause and recommending rebuild/upgrade remediation that preserves workspace state.