Skip to content

refactor(checks): migrate repository check suite to .mts - #6940

Closed
laitingsheng wants to merge 12 commits into
mainfrom
refactor/6921-checks-mts
Closed

refactor(checks): migrate repository check suite to .mts#6940
laitingsheng wants to merge 12 commits into
mainfrom
refactor/6921-checks-mts

Conversation

@laitingsheng

@laitingsheng laitingsheng commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Migrate the repository check suite from .ts to .mts. The runner and every check entrypoint move together, and all consumers that named the old extension are updated. The check set, ordering, arguments, Windows command construction, and exit behavior are unchanged.

Related Issue

Resolves #6921

Changes

  • Rename the 14 scripts/checks/*.ts entrypoints and run.ts to .mts.
  • Update the checks, test:imports:check, test:projects:check, and test:titles:check package scripts.
  • Update the pr.yaml and main.yaml workflows and the ci-cli-coverage-shard composite action that invoke e2e-mock-parity.
  • Update tests, runner fixtures, the workflow-contract assertion, the direct-credential-env usage string, two source comments, and one skill doc that named the old extension; add the explicit .mts extension to test imports of the migrated checks.
  • Switch the three checks that import first-party CommonJS source (direct-credential-env, hermes-light-skin-boundary, local-credential-helper-pin) to dynamic import(). Under tsx an ESM .mts entrypoint cannot statically resolve named exports from a first-party .ts CommonJS module, so the static named imports throw at runtime; dynamic import() resolves the named exports and keeps full types. npm run checks and the per-check tests protect this.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: no user-facing behavior change; internal check-suite extension migration only
  • Sensitive paths changed (security, policy, credentials, preflight, onboarding, inference, runner, sandbox, or messaging)
  • Sensitive-path review completed or maintainer-approved waiver recorded — reviewer/approval link/justification: mechanical .ts.mts rename plus dynamic-import adaptation of the credential and policy checks; no security behavior change and npm run checks passes unchanged — pending maintainer review
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result: npm run typecheck:cli pass; npm run checks all 12 checks pass on node 22.22.2; npx vitest run on the runner, workflow-contract, and 11 per-check tests — 13 files / 173 tests pass; biome lint and biome format clean
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result:
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Signed-off-by: Tinson Lai tinsonl@nvidia.com

Summary by CodeRabbit

  • New Features
    • Added/expanded CI guard checks for dependency pin consistency, layer import boundary violations, OpenShell policy mutation reads, live E2E unit-block detection, createRequire “path budget” enforcement, and Vitest project overlap validation.
  • Bug Fixes
    • Improved validation around Hermes light-skin boundary and credential-helper pin consistency; hardened live E2E mock parity validation behavior.
  • Chores
    • Standardized repository validation/check execution to TypeScript module (.mts) variants across scripts, CI workflow steps, and related tests.

Checks importing first-party CJS source use dynamic import so the ESM
entrypoints resolve named exports at runtime under tsx.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a6930239-dbf9-4829-956d-6ab9aa648fe4

📥 Commits

Reviewing files that changed from the base of the PR and between 5601b15 and 40c2e95.

📒 Files selected for processing (2)
  • scripts/checks/e2e-mock-parity.mts
  • scripts/checks/e2e-mock-parity.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • scripts/checks/e2e-mock-parity.ts
  • scripts/checks/e2e-mock-parity.mts

📝 Walkthrough

Walkthrough

The repository check suite migrates check entrypoints and references to .mts, adds dependency and static audit implementations, preserves the E2E parity compatibility wrapper, and updates package scripts, CI workflows, documentation references, and tests.

Changes

Repository check migration

Layer / File(s) Summary
Dependency pin and credential integrity checks
scripts/checks/dependency-pins.mts, scripts/checks/local-credential-helper-pin.mts, scripts/checks/direct-credential-env.mts, scripts/checks/hermes-light-skin-boundary.mts
Adds dependency pin, credential parity, and ESM-compatible validation logic.
Live E2E mock parity validation
scripts/checks/e2e-mock-parity.mts, scripts/checks/e2e-mock-parity.ts
Validates mock-parity manifests and Git-reference changes in .mts, while .ts forwards execution to the new entrypoint.
Static repository audit checks
scripts/checks/*.mts
Adds AST, filesystem, policy, test, import, coverage, and Vitest contract audits with CLI failure reporting.
Check execution and references
package.json, scripts/checks/run.mts, .github/..., test/*, .agents/..., src/lib/...
Updates registered commands, npm scripts, CI invocations, focused tests, comments, and documentation to use .mts paths.

Estimated code review effort: 4 (Complex) | ~45 minutes

Suggested labels: refactor, area: ci

Suggested reviewers: ericksoa

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning [#6921] Most checks moved to .mts, but scripts/checks/e2e-mock-parity.ts still exists as a runnable shim, so the no-live-.ts-entrypoint criterion is unmet. Remove the remaining runnable .ts shim or convert it to a non-entrypoint alias so no live scripts/checks/*.ts files remain.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: migrating the checks suite to .mts.
Out of Scope Changes check ✅ Passed The changes stay within the migration scope: scripts, workflows, tests, comments, and check entrypoints were updated to .mts.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/6921-checks-mts

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

@github-code-quality

github-code-quality Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the main branch.

TypeScript / code-coverage/cli

The overall coverage in the refactor/6921-checks... branch remains at 80%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main c1bda80 refactor/6921-checks... 40c2e95 +/-
src/lib/state/gateway.ts 93% 91% -2%
src/lib/securit...ntial-filter.ts 98% 99% +1%

Updated July 16, 2026 07:49 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@laitingsheng laitingsheng added the chore Build, CI, dependency, or tooling maintenance label Jul 15, 2026
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Blocking findings reported

Advisor assessment: Blockers require maintainer review
Next action: Review the blockers below.
Findings: 1 blocker · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 1 blocker · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported 1 fewer blocker, the same number of warnings, the same number of suggestions.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: cloud-onboard, credential-sanitization, security-posture

Blockers

PRA-1 Blocker — Complete the check-entrypoint migration without a live TypeScript shim

  • Location: scripts/checks/e2e-mock-parity.ts:8
  • Category: acceptance
  • Problem: The migrated file remains an executable `.ts` entrypoint because it imports the `.mts` implementation and calls `main()`. This leaves a live `scripts/checks/*.ts` entrypoint in the final tree, despite the linked task's explicit migration criterion.
  • Impact: The requested end state is not achieved, and the temporary compatibility boundary can persist indefinitely, leaving callers on two executable entrypoint extensions rather than the single `.mts` check suite.
  • Fix: Sequence the trusted base-action change so the compatibility consumer is no longer needed, then delete `scripts/checks/e2e-mock-parity.ts`; do not retain an executable `.ts` forwarding entrypoint in the final migration state.
  • Verification: Read `scripts/checks/e2e-mock-parity.ts` and enumerate `scripts/checks/*.ts`; confirm no executable TypeScript entrypoint remains after the migration.
  • Test coverage: Add or retain an automated repository check that fails when `scripts/checks/*.ts` contains a live executable entrypoint, while allowing only the migrated `.mts` inventory.
  • Evidence: `scripts/checks/e2e-mock-parity.ts:8` invokes `main()` from `./e2e-mock-parity.mts`, so it is executable rather than a deleted or inert legacy path. Linked issue Migrate the repository check suite to .mts #6921 acceptance criteria state: "No live `scripts/checks/*.ts` entrypoint remains after the migration." The patch already changes the current composite action and bootstrap workflow invocations to `e2e-mock-parity.mts`, leaving the shim solely as a temporary old-base compatibility boundary.

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🤖 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 `@scripts/checks/dependency-pins.mts`:
- Around line 217-219: Update the version-validation logic near the existing
openshell max-version check to also validate pins.openshell.minVersion with
NUMERIC_VERSION_RE when present. Add a failure for malformed
min_openshell_version using the same X.Y.Z invariant and preserve the existing
maximum-version validation.

In `@scripts/checks/e2e-mock-parity.mts`:
- Line 185: Update the usage error message in the CLI argument validation around
the base option to reference the current e2e-mock-parity.mts entrypoint instead
of the removed .ts filename, while preserving the existing command syntax and
validation behavior.

In `@scripts/checks/layer-import-boundaries.mts`:
- Around line 324-337: Update isCommandBase and the surrounding visit logic to
resolve TypeScript import bindings and identify the registered oclif command
base by symbol, not expression text; accept direct and aliased Command imports
plus namespace-qualified oclif.Command, while rejecting unrelated local classes.
Ensure commandClassCount only counts classes extending exactly that resolved
base, and add focused detection and false-positive tests covering these cases.
- Around line 43-49: Update the walkers in
scripts/checks/layer-import-boundaries.mts lines 43-49 and
scripts/checks/no-test-dist-imports.mts lines 72-77 to inspect directory entries
or use lstatSync(), skip symbolic links before recursion or file processing, and
add a regression test covering a symlink loop in
scripts/checks/no-test-dist-imports.mts. Ensure both checks cannot traverse
PR-controlled symlink cycles.
- Around line 31-32: Update isProductionTsFile to recognize all supported
TypeScript module extensions (.ts, .mts, .cts, and .tsx), while continuing to
exclude test and spec files for each extension. Ensure the layer-boundary scan
uses this predicate so protected-layer audits cannot be bypassed by alternate
TypeScript extensions, preserving the ratchet’s monotonic behavior.

In `@scripts/checks/no-coverage-ignore.mts`:
- Around line 17-19: Update SOURCE_EXTENSIONS to include ".mts" so
no-coverage-ignore scans migrated TypeScript module files. Add focused tests
covering detection of a forbidden directive in an .mts candidate and confirming
non-matching files or content remain false positives.

In `@scripts/checks/no-test-dist-imports.mts`:
- Around line 57-60: Update isFastProjectTestPath to derive fast-project test
entries from the canonical Vitest configuration instead of maintaining a
separate path pattern. Include root test/**/*.test.ts files classified as fast
tests, ensure every candidate belongs to exactly one configured project, and
preserve the existing exclusions such as .claude paths.

In `@scripts/checks/no-unit-blocks-in-live-e2e.mts`:
- Around line 67-82: Update findLiveUnitBlocks to track whether each line is
inside a multi-line /* ... */ block comment, skipping comment contents and
correctly handling comment start and end markers on the same or different lines.
Preserve the existing import, //, and * comment exclusions, and only apply
IT_PRIMITIVE_PATTERN to code outside block comments.

In `@scripts/checks/test-create-require-budget.mts`:
- Around line 19-58: The createRequire allowlists must not be expanded by the
checked PR. Update the validation logic in this test to compare
CLI_CREATE_REQUIRE_FILES and TEST_SUPPORT_CREATE_REQUIRE_FILES against their
merge-base versions, reject any newly added paths, and continue permitting
removals while preserving existing checks.
🪄 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: Enterprise

Run ID: 1e7aa52c-05ac-40a2-915a-61f1372a2bab

📥 Commits

Reviewing files that changed from the base of the PR and between 55fdc3f and 907a7bc.

📒 Files selected for processing (33)
  • .agents/skills/nemoclaw-contributor-update-dependencies/SKILL.md
  • .github/actions/ci-cli-coverage-shard/action.yaml
  • .github/workflows/pr.yaml
  • package.json
  • scripts/checks/dependency-pins.mts
  • scripts/checks/direct-credential-env.mts
  • scripts/checks/e2e-mock-parity.mts
  • scripts/checks/hermes-light-skin-boundary.mts
  • scripts/checks/layer-import-boundaries.mts
  • scripts/checks/local-credential-helper-pin.mts
  • scripts/checks/no-coverage-ignore.mts
  • scripts/checks/no-test-dist-imports.mts
  • scripts/checks/no-unit-blocks-in-live-e2e.mts
  • scripts/checks/openshell-policy-mutation-read.mts
  • scripts/checks/run.mts
  • scripts/checks/test-create-require-budget.mts
  • scripts/checks/test-title-style.mts
  • scripts/checks/vitest-project-overlap.mts
  • src/lib/messaging/manifest/types.test.ts
  • src/lib/security/credential-env.ts
  • test/checks-runner.test.ts
  • test/dependency-pins-check.test.ts
  • test/e2e-mock-parity.test.ts
  • test/layer-import-boundaries.test.ts
  • test/local-credential-helper-pin.test.ts
  • test/no-coverage-ignore.test.ts
  • test/no-direct-credential-env.test.ts
  • test/no-unit-blocks-in-live-e2e.test.ts
  • test/policy-mutation-read-discovery.test.ts
  • test/pr-workflow-contract.test.ts
  • test/test-boundary-guards.test.ts
  • test/test-create-require-budget.test.ts
  • test/test-title-style.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 9

🤖 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 `@scripts/checks/dependency-pins.mts`:
- Around line 217-219: Update the version-validation logic near the existing
openshell max-version check to also validate pins.openshell.minVersion with
NUMERIC_VERSION_RE when present. Add a failure for malformed
min_openshell_version using the same X.Y.Z invariant and preserve the existing
maximum-version validation.

In `@scripts/checks/e2e-mock-parity.mts`:
- Line 185: Update the usage error message in the CLI argument validation around
the base option to reference the current e2e-mock-parity.mts entrypoint instead
of the removed .ts filename, while preserving the existing command syntax and
validation behavior.

In `@scripts/checks/layer-import-boundaries.mts`:
- Around line 324-337: Update isCommandBase and the surrounding visit logic to
resolve TypeScript import bindings and identify the registered oclif command
base by symbol, not expression text; accept direct and aliased Command imports
plus namespace-qualified oclif.Command, while rejecting unrelated local classes.
Ensure commandClassCount only counts classes extending exactly that resolved
base, and add focused detection and false-positive tests covering these cases.
- Around line 43-49: Update the walkers in
scripts/checks/layer-import-boundaries.mts lines 43-49 and
scripts/checks/no-test-dist-imports.mts lines 72-77 to inspect directory entries
or use lstatSync(), skip symbolic links before recursion or file processing, and
add a regression test covering a symlink loop in
scripts/checks/no-test-dist-imports.mts. Ensure both checks cannot traverse
PR-controlled symlink cycles.
- Around line 31-32: Update isProductionTsFile to recognize all supported
TypeScript module extensions (.ts, .mts, .cts, and .tsx), while continuing to
exclude test and spec files for each extension. Ensure the layer-boundary scan
uses this predicate so protected-layer audits cannot be bypassed by alternate
TypeScript extensions, preserving the ratchet’s monotonic behavior.

In `@scripts/checks/no-coverage-ignore.mts`:
- Around line 17-19: Update SOURCE_EXTENSIONS to include ".mts" so
no-coverage-ignore scans migrated TypeScript module files. Add focused tests
covering detection of a forbidden directive in an .mts candidate and confirming
non-matching files or content remain false positives.

In `@scripts/checks/no-test-dist-imports.mts`:
- Around line 57-60: Update isFastProjectTestPath to derive fast-project test
entries from the canonical Vitest configuration instead of maintaining a
separate path pattern. Include root test/**/*.test.ts files classified as fast
tests, ensure every candidate belongs to exactly one configured project, and
preserve the existing exclusions such as .claude paths.

In `@scripts/checks/no-unit-blocks-in-live-e2e.mts`:
- Around line 67-82: Update findLiveUnitBlocks to track whether each line is
inside a multi-line /* ... */ block comment, skipping comment contents and
correctly handling comment start and end markers on the same or different lines.
Preserve the existing import, //, and * comment exclusions, and only apply
IT_PRIMITIVE_PATTERN to code outside block comments.

In `@scripts/checks/test-create-require-budget.mts`:
- Around line 19-58: The createRequire allowlists must not be expanded by the
checked PR. Update the validation logic in this test to compare
CLI_CREATE_REQUIRE_FILES and TEST_SUPPORT_CREATE_REQUIRE_FILES against their
merge-base versions, reject any newly added paths, and continue permitting
removals while preserving existing checks.
🪄 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: Enterprise

Run ID: 1e7aa52c-05ac-40a2-915a-61f1372a2bab

📥 Commits

Reviewing files that changed from the base of the PR and between 55fdc3f and 907a7bc.

📒 Files selected for processing (33)
  • .agents/skills/nemoclaw-contributor-update-dependencies/SKILL.md
  • .github/actions/ci-cli-coverage-shard/action.yaml
  • .github/workflows/pr.yaml
  • package.json
  • scripts/checks/dependency-pins.mts
  • scripts/checks/direct-credential-env.mts
  • scripts/checks/e2e-mock-parity.mts
  • scripts/checks/hermes-light-skin-boundary.mts
  • scripts/checks/layer-import-boundaries.mts
  • scripts/checks/local-credential-helper-pin.mts
  • scripts/checks/no-coverage-ignore.mts
  • scripts/checks/no-test-dist-imports.mts
  • scripts/checks/no-unit-blocks-in-live-e2e.mts
  • scripts/checks/openshell-policy-mutation-read.mts
  • scripts/checks/run.mts
  • scripts/checks/test-create-require-budget.mts
  • scripts/checks/test-title-style.mts
  • scripts/checks/vitest-project-overlap.mts
  • src/lib/messaging/manifest/types.test.ts
  • src/lib/security/credential-env.ts
  • test/checks-runner.test.ts
  • test/dependency-pins-check.test.ts
  • test/e2e-mock-parity.test.ts
  • test/layer-import-boundaries.test.ts
  • test/local-credential-helper-pin.test.ts
  • test/no-coverage-ignore.test.ts
  • test/no-direct-credential-env.test.ts
  • test/no-unit-blocks-in-live-e2e.test.ts
  • test/policy-mutation-read-discovery.test.ts
  • test/pr-workflow-contract.test.ts
  • test/test-boundary-guards.test.ts
  • test/test-create-require-budget.test.ts
  • test/test-title-style.test.ts
🛑 Comments failed to post (9)
scripts/checks/dependency-pins.mts (1)

217-219: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Validate min_openshell_version as well.

Only the maximum is checked against X.Y.Z. A malformed minimum can pass when its consumers contain the same value, allowing an invalid installer constraint through this guardrail.

Proposed fix
+  if (pins.openshell.minVersion && !NUMERIC_VERSION_RE.test(pins.openshell.minVersion)) {
+    failures.push("nemoclaw-blueprint/blueprint.yaml min_openshell_version must match X.Y.Z");
+  }
   if (pins.openshell.maxVersion && !NUMERIC_VERSION_RE.test(pins.openshell.maxVersion)) {

As per path instructions, “Enforce objective invariants with deterministic code.”

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  if (pins.openshell.minVersion && !NUMERIC_VERSION_RE.test(pins.openshell.minVersion)) {
    failures.push("nemoclaw-blueprint/blueprint.yaml min_openshell_version must match X.Y.Z");
  }
  if (pins.openshell.maxVersion && !NUMERIC_VERSION_RE.test(pins.openshell.maxVersion)) {
    failures.push("nemoclaw-blueprint/blueprint.yaml max_openshell_version must match X.Y.Z");
  }
🤖 Prompt for 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.

In `@scripts/checks/dependency-pins.mts` around lines 217 - 219, Update the
version-validation logic near the existing openshell max-version check to also
validate pins.openshell.minVersion with NUMERIC_VERSION_RE when present. Add a
failure for malformed min_openshell_version using the same X.Y.Z invariant and
preserve the existing maximum-version validation.

Source: Path instructions

scripts/checks/e2e-mock-parity.mts (1)

185-185: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the CLI usage to reference the .mts entrypoint.

The reported command still targets the removed .ts file, so copying it will fail.

Proposed fix
-  if (!base) throw new Error("usage: e2e-mock-parity.ts --base <git-ref> [--head <git-ref>]");
+  if (!base) throw new Error("usage: e2e-mock-parity.mts --base <git-ref> [--head <git-ref>]");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

  if (!base) throw new Error("usage: e2e-mock-parity.mts --base <git-ref> [--head <git-ref>]");
🤖 Prompt for 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.

In `@scripts/checks/e2e-mock-parity.mts` at line 185, Update the usage error
message in the CLI argument validation around the base option to reference the
current e2e-mock-parity.mts entrypoint instead of the removed .ts filename,
while preserving the existing command syntax and validation behavior.
scripts/checks/layer-import-boundaries.mts (3)

31-32: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scan every supported TypeScript module extension.

Restricting the audit to .ts lets .mts, .cts, or .tsx files under protected layers bypass every rule.

Proposed fix
 function isProductionTsFile(absPath: string): boolean {
-  return absPath.endsWith(".ts") && !absPath.endsWith(".test.ts") && !absPath.endsWith(".spec.ts");
+  return (
+    /\.(?:ts|tsx|mts|cts)$/u.test(absPath) &&
+    !/\.(?:test|spec)\.(?:ts|tsx|mts|cts)$/u.test(absPath)
+  );
 }

 function sourceFileFor(absPath: string): ts.SourceFile {
   return ts.createSourceFile(
     absPath,
     readFileSync(absPath, "utf8"),
     ts.ScriptTarget.Latest,
     true,
-    ts.ScriptKind.TS,
+    absPath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
   );
 }

As per path instructions, “A ratchet must be monotonic and must not be weakenable by the PR it checks.”

Also applies to: 55-62

🤖 Prompt for 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.

In `@scripts/checks/layer-import-boundaries.mts` around lines 31 - 32, Update
isProductionTsFile to recognize all supported TypeScript module extensions (.ts,
.mts, .cts, and .tsx), while continuing to exclude test and spec files for each
extension. Ensure the layer-boundary scan uses this predicate so protected-layer
audits cannot be bypassed by alternate TypeScript extensions, preserving the
ratchet’s monotonic behavior.

Source: Path instructions


43-49: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Prevent symlink traversal across repository guardrails.

Both walkers dereference symbolic links, allowing a PR-controlled loop to prevent the checks from completing.

  • scripts/checks/layer-import-boundaries.mts#L43-L49: use directory entries or lstatSync() and skip symbolic links.
  • scripts/checks/no-test-dist-imports.mts#L72-L77: apply the same non-following traversal and add a symlink-loop regression test.

As per path instructions, “A ratchet must be monotonic and must not be weakenable by the PR it checks.”

📍 Affects 2 files
  • scripts/checks/layer-import-boundaries.mts#L43-L49 (this comment)
  • scripts/checks/no-test-dist-imports.mts#L72-L77
🤖 Prompt for 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.

In `@scripts/checks/layer-import-boundaries.mts` around lines 43 - 49, Update the
walkers in scripts/checks/layer-import-boundaries.mts lines 43-49 and
scripts/checks/no-test-dist-imports.mts lines 72-77 to inspect directory entries
or use lstatSync(), skip symbolic links before recursion or file processing, and
add a regression test covering a symlink loop in
scripts/checks/no-test-dist-imports.mts. Ensure both checks cannot traverse
PR-controlled symlink cycles.

Source: Path instructions


324-337: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Resolve the actual oclif command base instead of matching source text.

A local unrelated Command class is accepted, while aliases such as Command as OclifCommand or oclif.Command are rejected. Resolve import bindings so the rule proves that exactly one class extends the registered command base.

As per path instructions, guardrails must enforce objective invariants and include focused detection and false-positive tests.

🤖 Prompt for 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.

In `@scripts/checks/layer-import-boundaries.mts` around lines 324 - 337, Update
isCommandBase and the surrounding visit logic to resolve TypeScript import
bindings and identify the registered oclif command base by symbol, not
expression text; accept direct and aliased Command imports plus
namespace-qualified oclif.Command, while rejecting unrelated local classes.
Ensure commandClassCount only counts classes extending exactly that resolved
base, and add focused detection and false-positive tests covering these cases.

Source: Path instructions

scripts/checks/no-coverage-ignore.mts (1)

17-19: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include .mts files in the coverage-directive scan.

The migration makes .mts a live source extension, but this inventory omits it. Consequently, all migrated check entrypoints can contain forbidden coverage directives without detection.

Proposed fix
-const SOURCE_EXTENSIONS = new Set([".cjs", ".cts", ".js", ".mjs", ".ts", ".tsx"]);
+const SOURCE_EXTENSIONS = new Set([".cjs", ".cts", ".js", ".mjs", ".mts", ".ts", ".tsx"]);

Add a focused discovery test proving an .mts candidate is scanned. As per path instructions, guardrails require focused detection and false-positive tests.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

const SCAN_ROOTS = ["bin", "src", "scripts", "test", "nemoclaw/src"];
const SOURCE_EXTENSIONS = new Set([".cjs", ".cts", ".js", ".mjs", ".mts", ".ts", ".tsx"]);
const SKIP_DIRS = new Set([".git", "coverage", "dist", "node_modules"]);
🤖 Prompt for 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.

In `@scripts/checks/no-coverage-ignore.mts` around lines 17 - 19, Update
SOURCE_EXTENSIONS to include ".mts" so no-coverage-ignore scans migrated
TypeScript module files. Add focused tests covering detection of a forbidden
directive in an .mts candidate and confirming non-matching files or content
remain false positives.

Source: Path instructions

scripts/checks/no-test-dist-imports.mts (1)

57-60: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Derive fast-project entries from the canonical Vitest configuration.

This inventory omits root test/**/*.test.ts files, although scripts/checks/e2e-mock-parity.mts Lines 26-30 classifies them as fast PR tests. Their dependencies are therefore not traversed, allowing a source module that imports compiled internals to evade the transitive audit.

As per coding guidelines, every test candidate must belong to exactly one configured project. As per path instructions, derive inventories from a canonical source rather than duplicating lists.

🤖 Prompt for 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.

In `@scripts/checks/no-test-dist-imports.mts` around lines 57 - 60, Update
isFastProjectTestPath to derive fast-project test entries from the canonical
Vitest configuration instead of maintaining a separate path pattern. Include
root test/**/*.test.ts files classified as fast tests, ensure every candidate
belongs to exactly one configured project, and preserve the existing exclusions
such as .claude paths.

Sources: Coding guidelines, Path instructions

scripts/checks/no-unit-blocks-in-live-e2e.mts (1)

67-82: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Multi-line block comments aren't skipped, risking false positives.

findLiveUnitBlocks only skips // line comments and JSDoc-style *-prefixed continuation lines. A plain /* ... */ block spanning multiple lines, where the body line doesn't start with *, would still have its it(...) line flagged — a false positive that fails CI for legitimately commented-out code.

🐛 Proposed fix to track block-comment state
 export function findLiveUnitBlocks(source: string, file: string): LiveUnitBlockViolation[] {
   const violations: LiveUnitBlockViolation[] = [];
   const lines = source.split(/\r\n|\r|\n/);
+  let inBlockComment = false;
   for (let i = 0; i < lines.length; i += 1) {
     const text = lines[i] ?? "";
     const trimmed = text.trimStart();
+    if (inBlockComment) {
+      if (trimmed.includes("*/")) inBlockComment = false;
+      continue;
+    }
+    if (trimmed.startsWith("/*") && !trimmed.includes("*/")) {
+      inBlockComment = true;
+      continue;
+    }
     // Skip import lines (`import { it, test } from "vitest"`) and comments.
     if (trimmed.startsWith("import ") || trimmed.startsWith("//") || trimmed.startsWith("*")) {
       continue;
     }
     if (IT_PRIMITIVE_PATTERN.test(text)) {
       violations.push({ file, line: i + 1, text: trimmed });
     }
   }
   return violations;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

export function findLiveUnitBlocks(source: string, file: string): LiveUnitBlockViolation[] {
  const violations: LiveUnitBlockViolation[] = [];
  const lines = source.split(/\r\n|\r|\n/);
  let inBlockComment = false;
  for (let i = 0; i < lines.length; i += 1) {
    const text = lines[i] ?? "";
    const trimmed = text.trimStart();
    if (inBlockComment) {
      if (trimmed.includes("*/")) inBlockComment = false;
      continue;
    }
    if (trimmed.startsWith("/*") && !trimmed.includes("*/")) {
      inBlockComment = true;
      continue;
    }
    // Skip import lines (`import { it, test } from "vitest"`) and comments.
    if (trimmed.startsWith("import ") || trimmed.startsWith("//") || trimmed.startsWith("*")) {
      continue;
    }
    if (IT_PRIMITIVE_PATTERN.test(text)) {
      violations.push({ file, line: i + 1, text: trimmed });
    }
  }
  return violations;
}
🤖 Prompt for 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.

In `@scripts/checks/no-unit-blocks-in-live-e2e.mts` around lines 67 - 82, Update
findLiveUnitBlocks to track whether each line is inside a multi-line /* ... */
block comment, skipping comment contents and correctly handling comment start
and end markers on the same or different lines. Preserve the existing import,
//, and * comment exclusions, and only apply IT_PRIMITIVE_PATTERN to code
outside block comments.
scripts/checks/test-create-require-budget.mts (1)

19-58: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Make the createRequire ratchet immutable against the checked PR.

A PR can introduce a new seam and add its path to these allowlists, making this check pass. Compare the allowlists with the merge-base and reject additions while permitting removals.

As per path instructions, “A ratchet must be monotonic and must not be weakenable by the PR it checks.”

Also applies to: 159-195

🤖 Prompt for 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.

In `@scripts/checks/test-create-require-budget.mts` around lines 19 - 58, The
createRequire allowlists must not be expanded by the checked PR. Update the
validation logic in this test to compare CLI_CREATE_REQUIRE_FILES and
TEST_SUPPORT_CREATE_REQUIRE_FILES against their merge-base versions, reject any
newly added paths, and continue permitting removals while preserving existing
checks.

Source: Path instructions

The base-pinned ci-cli-coverage-shard action still invokes the
pre-migration `.ts` path until it lands on main.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/checks/e2e-mock-parity.ts (2)

1-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No focused test for the shim's forwarding behavior.

As per path instructions for scripts/checks/**, checks-related scripts should "require focused tests for both detection and false-positive behavior." This shim has no test asserting it spawns node --import tsx against the .mts path with the correct forwarded args/cwd, unlike the other check modules in this cohort. A small unit test mocking spawnSync would catch regressions before the shim is removed.

🤖 Prompt for 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.

In `@scripts/checks/e2e-mock-parity.ts` around lines 1 - 27, add a focused unit
test for the compatibility shim’s forwarding behavior, mocking spawnSync to
verify it invokes the current Node executable with --import tsx, the
e2e-mock-parity.mts target, forwarded command-line arguments, and REPO_ROOT as
cwd. Also assert the shim propagates the spawned process status, while keeping
the test isolated from actually launching the script.

Source: Path instructions


9-9: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Spawn failure is swallowed silently.

If spawnSync fails to launch the child (e.g., tsx not resolvable), result.error is set and result.status is null, so process.exit(result.status ?? 1) exits with 1 but never surfaces the underlying reason. During the migration window this shim is meant to bridge, a silent unexplained failure makes CI triage harder.

The ast-grep command-injection hint on the child_process import doesn't apply: spawnSync is called with an argv array (not a shell string) and the shell option is not enabled, so process.argv.slice(2) is passed as discrete arguments rather than being shell-interpolated.

🩹 Proposed fix to surface spawn errors
 const result = spawnSync(
   process.execPath,
   [
     "--import",
     "tsx",
     path.join(REPO_ROOT, "scripts/checks/e2e-mock-parity.mts"),
     ...process.argv.slice(2),
   ],
   { cwd: REPO_ROOT, stdio: "inherit" },
 );
 
+if (result.error) {
+  console.error(result.error);
+}
+
 process.exit(result.status ?? 1);

Also applies to: 15-26

🤖 Prompt for 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.

In `@scripts/checks/e2e-mock-parity.ts` at line 9, Update the spawnSync execution
flow in this script to check result.error before exiting, and report the
underlying launch failure through the script’s existing error-output mechanism.
Preserve the current status-based exit behavior for successfully spawned
commands, including nonzero child exit statuses.
🤖 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.

Nitpick comments:
In `@scripts/checks/e2e-mock-parity.ts`:
- Around line 1-27: add a focused unit test for the compatibility shim’s
forwarding behavior, mocking spawnSync to verify it invokes the current Node
executable with --import tsx, the e2e-mock-parity.mts target, forwarded
command-line arguments, and REPO_ROOT as cwd. Also assert the shim propagates
the spawned process status, while keeping the test isolated from actually
launching the script.
- Line 9: Update the spawnSync execution flow in this script to check
result.error before exiting, and report the underlying launch failure through
the script’s existing error-output mechanism. Preserve the current status-based
exit behavior for successfully spawned commands, including nonzero child exit
statuses.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 62b38d74-0d05-45c4-be30-a09b75717458

📥 Commits

Reviewing files that changed from the base of the PR and between 907a7bc and b428260.

📒 Files selected for processing (1)
  • scripts/checks/e2e-mock-parity.ts

Issue #6921 requires no live scripts/checks/*.ts entrypoint after
migration. The trusted, base-pinned ci-cli-coverage-shard action will
stay red against the old path until a prerequisite change updates it
on main.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
# Conflicts:
#	package.json
#	scripts/checks/local-credential-helper-pin.mts

@cv cv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This migration is not mergeable yet at commit 889dca0:

  1. The trusted coverage-shard action on current main still invokes scripts/checks/e2e-mock-parity.ts, which this PR deletes. CI fails with ERR_MODULE_NOT_FOUND. Land a small compatibility prerequisite that selects the available .mts or .ts entrypoint, then rebase this PR.
  2. scripts/checks/no-coverage-ignore.mts omits .mts from SOURCE_EXTENSIONS, excluding all migrated checks from coverage-directive enforcement. Add .mts plus positive and false-positive regression tests.
  3. scripts/checks/e2e-mock-parity.mts still advertises the removed .ts command; update the diagnostic.
  4. Add the focused negative test required by #6921 for an unreviewed Hermes boundary version.

Local focused tests and the registered checks pass, but these enforcement and trusted-action gaps must be closed before merge.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@scripts/checks/e2e-mock-parity.ts`:
- Around line 4-10: Delete the stale e2e-mock-parity.ts wrapper, including its
forwarding import and main() invocation; retain the implementation in
e2e-mock-parity.mts unchanged.
🪄 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: Enterprise

Run ID: a2d3029d-fa92-40a0-976d-109f88588280

📥 Commits

Reviewing files that changed from the base of the PR and between 5601b15 and 40c2e95.

📒 Files selected for processing (2)
  • scripts/checks/e2e-mock-parity.mts
  • scripts/checks/e2e-mock-parity.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/checks/e2e-mock-parity.mts

Comment thread scripts/checks/e2e-mock-parity.ts
@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Superseded by #7047, a clean current-main replacement. Tinson Lai retains authorship and sign-off on the four original commits, and the follow-up guardrail hardening credits Tinson as co-author. The replacement removes the live .ts shim and addresses the review findings without rewriting the original branch.

@laitingsheng
laitingsheng deleted the refactor/6921-checks-mts branch July 17, 2026 01:52
cv added a commit that referenced this pull request Jul 18, 2026
## Summary

Migrates the repository check suite from `.ts` entrypoints to `.mts` and
removes the final live `.ts` shim. This clean current-`main` replacement
for #6940 preserves Tinson Lai as the author of the original four
commits and credits him as co-author of the follow-up hardening.

## Related Issue

Closes #6921

## Changes

- Rename the coordinated `scripts/checks` suite to `.mts` and update
package scripts, workflows, actions, tests, diagnostics, and
contributor-skill references.
- Preserve the trusted coverage action's current `.mts`-first
compatibility selection while leaving no live `scripts/checks/*.ts`
entrypoint in the tree.
- Close review gaps in version validation, `.mts` coverage scanning,
canonical Vitest project discovery, live-E2E AST detection, oclif
command binding detection, and merge-base createRequire allowlist
enforcement.
- Make repository walkers and transitive import resolution symlink-safe
and canonical, including loop and protected-layer alias regressions.
- Move the compiled credentials shim assertion into the dedicated
package-contract test lane.

## Type of Change

- [x] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: internal repository checks
and CI entrypoint extensions change; contributor-facing npm commands and
product behavior remain unchanged. Independent docs audit found no stale
public references.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: independent maintainer
security audit completed for the static enforcement and CI changes; no
runtime permission or credential handling behavior changes.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — repository-check focused tests passed;
final layer/import-boundary suite: 62/62; package-contract credentials
suite: 4/4
- [ ] Applicable broad gate passed — `npm run checks` passed. `npm run
check` was attempted, but its CLI coverage lane failed across 265
unrelated tests under the concurrent local environment: spawned Python
fixtures reported missing `tomllib`/PyYAML and Node 26 deprecation
warnings polluted expected-empty stderr. Focused suites, `npm run
check:diff`, typecheck, and repository checks pass; hosted CI remains
required.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added automated validation for Hermes compatibility versions and
trusted `createRequire` allowlists.
* Expanded static checks to cover modern TypeScript file types, symlink
handling, module resolution, Vitest project assignments, and policy-read
discovery.
* Added stricter validation for OpenShell version pins and credential
artifact URLs.

* **Bug Fixes**
* Improved detection of invalid test structures, import-boundary
violations, coverage directives, and live E2E unit blocks.

* **Tests**
* Expanded coverage for new validation rules, aliases, alternate file
extensions, symlinks, and workflow requirements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: Tinson Lai <tinsonl@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

chore Build, CI, dependency, or tooling maintenance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate the repository check suite to .mts

5 participants