From 400b0ddd3bf8c816e8a7734d876379f9e02e9566 Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sat, 4 Jul 2026 01:12:56 -0700 Subject: [PATCH 1/5] ci(hooks): streamline local PR verification Signed-off-by: Carlos Villela --- .../nemoclaw-contributor-create-pr/SKILL.md | 46 +++-- .../SKILL.md | 23 ++- .github/PULL_REQUEST_TEMPLATE.md | 10 +- .github/actions/ci-static-checks/action.yaml | 2 - .pre-commit-config.yaml | 21 +- AGENTS.md | 18 +- CONTRIBUTING.md | 44 ++-- docs/AGENTS.md | 6 +- docs/CONTRIBUTING.md | 9 +- fern/AGENTS.md | 4 +- package.json | 5 +- test/pr-workflow-contract.test.ts | 188 +++++++++++++++++- test/skills-frontmatter.test.ts | 3 + 13 files changed, 292 insertions(+), 87 deletions(-) diff --git a/.agents/skills/nemoclaw-contributor-create-pr/SKILL.md b/.agents/skills/nemoclaw-contributor-create-pr/SKILL.md index 7a503d8e324..eb83ba8cd18 100644 --- a/.agents/skills/nemoclaw-contributor-create-pr/SKILL.md +++ b/.agents/skills/nemoclaw-contributor-create-pr/SKILL.md @@ -22,19 +22,25 @@ Follow the shared [Git and GitHub Access Hard Stop](../_shared/git-github-hard-s Before creating a PR, verify the branch. -1. **Not on main.** Never create PRs from main. +1. **Refresh the trusted base ref.** + + ```bash + git fetch --prune origin main + ``` + +2. **Not on main.** Never create PRs from main. ```bash git branch --show-current ``` -2. **Branch has commits ahead of main.** +3. **Branch has commits ahead of `origin/main`.** ```bash - git log main..HEAD --oneline + git log origin/main..HEAD --oneline ``` -3. **Working tree is clean.** Stage or stash any uncommitted changes first. +4. **Working tree is clean.** Stage or stash any uncommitted changes first. ```bash git status @@ -49,21 +55,22 @@ Use the checks that match the diff and the verification you already have. If the commits were created normally and the branch was pushed normally, count the installed hooks as verification: -- `pre-commit` runs file fixers, formatters, linters, skill frontmatter validation, and changed-surface Vitest hooks. +- `pre-commit` runs cheap structural and file-local checks, including fixers, formatters, linters, and skill frontmatter validation. - `commit-msg` runs commitlint. -- `pre-push` runs TypeScript build and type-check gates. +- `pre-push` runs path-scoped incremental type checks for affected CLI and plugin surfaces plus checked-JavaScript checks. -If hooks were skipped with `--no-verify`, were not installed, failed, or you cannot tell whether they ran, run a manual diff-scoped fallback before creating the PR: +If hooks were skipped with `--no-verify`, were not installed, failed, or you cannot tell whether they ran, use the single diff-scoped fallback that reproduces `pre-commit`, `commit-msg`, and `pre-push` checks: ```bash -npx prek run --from-ref main --to-ref HEAD +npm run check:diff ``` -Use `npx prek run --all-files` only when you need a whole-repository baseline, such as changing hook configuration, formatter configuration, generated-check scripts, or other repo-wide validation behavior. +The fallback compares with the refreshed `origin/main` ref from Step 1. +Reserve `npm run check` for the whole-repository pre-commit and full CLI/plugin coverage baseline, such as when changing hook configuration, formatter configuration, generated-check scripts, or other repo-wide validation behavior. ### Targeted Tests -Run the smallest meaningful tests for changed behavior: +Run the smallest meaningful tests for changed behavior once per relevant change set, and record the command and result for the PR body: - CLI or root `src/`, `bin/`, `scripts/`, or `test/` changes: `npx vitest run --project cli` or the directly affected test file. - Plugin changes under `nemoclaw/src/`: `npx vitest run --project plugin` or the directly affected plugin test file. @@ -71,7 +78,9 @@ Run the smallest meaningful tests for changed behavior: - E2E workflow, artifact upload, trace timing, or fixture environment-boundary changes: run the directly affected `test/e2e/support/*workflow*.test.ts`, `test/e2e/support/upload-e2e-artifacts-workflow-boundary.test.ts`, `test/e2e/support/sanitize-trace-timing.test.ts`, and fixture boundary tests instead of relying on unrelated live target runs. - Installer behavior changes: run the relevant installer integration project only when the local environment supports it. -Reserve full `npm test` for broad runtime changes, test harness changes, or cases where targeted coverage is hard to justify. +Do not rerun targeted tests solely because the normal hooks passed; rerun them after later edits or hook autofixes that can affect the tested behavior. +Reserve `npm test` for broad runtime changes, test harness changes, or cases where targeted coverage is hard to justify. +Reserve `npm run check` for repo-wide hook, formatter, generated-check, or coverage-baseline changes. Do not run the full test suite for doc-only changes unless the docs change code samples or generated behavior in a way that needs runtime validation. For doc-only changes, run the docs build before opening the PR: @@ -95,7 +104,7 @@ If the push fails because of SSH, authentication, remote access, authorization, ## Step 4: Prepare DCO Declaration and Verify GitHub Commits -Before creating the PR, prepare the DCO declaration for the PR body and verify every commit in `main..HEAD`. +Before creating the PR, prepare the DCO declaration for the PR body and verify every commit in `origin/main..HEAD`. This is a hard contributor self-serve gate. Do not run `gh pr create` until the PR body will include the DCO declaration and every commit passes GitHub verification. @@ -108,10 +117,10 @@ Do not run `gh pr create` until the PR body will include the DCO declaration and ``` 2. **GitHub verification.** Each pushed commit must appear as verified in GitHub. - Check the commit SHAs from `main..HEAD` with the GitHub API before opening the PR. + Check the commit SHAs from `origin/main..HEAD` with the GitHub API before opening the PR. ```bash - for sha in $(git rev-list main..HEAD); do + for sha in $(git rev-list origin/main..HEAD); do gh api "/repos/NVIDIA/NemoClaw/commits/$sha" --jq '.sha + " verified=" + (.commit.verification.verified | tostring) + " reason=" + .commit.verification.reason' done ``` @@ -193,8 +202,8 @@ Follow these rules when filling in the template: - **Related Issue:** Include `Fixes #NNN` or `Closes #NNN` if an issue exists. Remove the section entirely if there is no related issue. - **Changes:** Bullet list of key changes. Be specific — reference file names, commands, or behaviors that changed. - **Type of Change:** Check exactly one box. Use `[x]` for checked, `[ ]` for unchecked. -- **Quality Gates:** Check every line that applies to the diff. If tests/docs are not needed or existing coverage is sufficient, include the justification. If sensitive paths changed or a non-success CI check is accepted, record the authorized reviewer, maintainer-approved waiver, approval link, or follow-up issue. -- **Verification:** Check only the boxes for steps you actually ran and confirmed passing, or for Git hooks that passed during normal commit and push. Do not check boxes for steps you skipped or did not verify. The DCO declaration and GitHub verification checkbox is mandatory before PR creation because Step 4 must pass first. For doc-only changes, `npm test` is not required; leave it unchecked unless you ran it. +- **Quality Gates:** Check exactly one tests line and one docs line, then check every other line that applies to the diff. If tests/docs are not needed or existing coverage is sufficient, include the justification. If sensitive paths changed or a non-success CI check is accepted, record the authorized reviewer, maintainer-approved waiver, approval link, or follow-up issue. +- **Verification:** Check only the boxes backed by the requested command/result, justification, normal hook evidence, or fallback evidence. Do not check boxes for steps you skipped or did not verify. The DCO declaration and GitHub verification checkbox is mandatory before PR creation because Step 4 must pass first. For focused changes, leave the broad-gate line unchecked unless you actually ran the applicable command. - **DCO Sign-Off:** Replace `{name}` and `{email}` with values from `git config user.name` and `git config user.email`. ## Step 7: Create the PR @@ -245,8 +254,9 @@ Automated review: no actionable findings / addressed findings / waiting on user - **Do not invent your own PR body format.** Use `.github/PULL_REQUEST_TEMPLATE.md` exactly. - **Do not omit sections.** Even if a section is not applicable, keep it with the "Skip if..." comment. - **Do not check boxes for steps you did not run.** If you did not run `npm run docs`, leave that box unchecked. -- **Do not rerun hook-covered checks by default.** Normal commit and push hooks are valid verification. Use `npx prek run --from-ref main --to-ref HEAD` as the fallback when hooks were skipped, missing, or uncertain. -- **Do not run the full test suite for doc-only changes by default.** Run the docs build instead, and leave `npm test` unchecked unless you actually ran it. +- **Do not rerun hook-covered checks by default.** Normal `pre-commit`, `commit-msg`, and `pre-push` hooks are valid verification. Use `npm run check:diff` once as the fallback when hooks were skipped, missing, or uncertain. +- **Do not run targeted tests more than once per unchanged relevant change set.** Record the passing command and result; rerun when subsequent edits or hook autofixes can affect that behavior. +- **Do not run broad gates for doc-only changes by default.** Run the docs build instead, and leave the broad-gate verification item unchecked unless you actually ran the applicable command. - **Do not forget the DCO sign-off declaration in the PR body.** CI will reject the PR without it. - **Do not create PRs with unverified commits.** GitHub must report every PR commit as `Verified` before the PR is opened. - **Do not rely on maintainers to repair contributor signature history.** If force-push is not allowed and the branch contains an unverified commit, use a fresh branch and fresh PR. diff --git a/.agents/skills/nemoclaw-contributor-onboard-messaging-channel/SKILL.md b/.agents/skills/nemoclaw-contributor-onboard-messaging-channel/SKILL.md index 63ae3a48878..30c2a688500 100644 --- a/.agents/skills/nemoclaw-contributor-onboard-messaging-channel/SKILL.md +++ b/.agents/skills/nemoclaw-contributor-onboard-messaging-channel/SKILL.md @@ -88,15 +88,24 @@ Start with the manifest. Add core code only when the manifest vocabulary cannot ## Verification -Use the narrowest tests that cover the changed behavior: +Build one targeted Vitest invocation from only the files that cover the changed behavior. +Omit unaffected paths from this example, then run the resulting command once per relevant change set: ```bash -npm run build:cli -npm run typecheck:cli -npx vitest run src/lib/messaging/channels/manifests.test.ts src/lib/messaging/channels/metadata.test.ts src/lib/messaging/compiler/manifest-compiler.test.ts -npx vitest run src/lib/messaging/channels//hooks -npx vitest run test/messaging-build-applier.test.ts +npx vitest run \ + src/lib/messaging/channels/ \ + src/lib/messaging/channels/manifests.test.ts \ + src/lib/messaging/channels/metadata.test.ts \ + src/lib/messaging/compiler/manifest-compiler.test.ts \ + test/messaging-build-applier.test.ts ``` Add channel-specific config render, hook, policy, and channel add/remove tests when those surfaces change. -Run `npm run docs` for documentation changes and `npx prek run --files ` before handoff. If broad hooks expose unrelated failures, report the failure with the targeted passing evidence. +Rerun the targeted command after later edits or hook autofixes that can affect the tested behavior. +Run `npm run docs` for documentation changes. +Commit and push normally so pre-commit handles cheap structural and file-local checks and pre-push runs the path-scoped type checks. +Treat successful hooks as verification and do not rerun their checks manually. +If `pre-commit`, `commit-msg`, or `pre-push` hooks were skipped or unavailable, run `npm run check:diff` once to reproduce those checks. +Refresh `origin/main` first. +Reserve `npm test` for broad runtime or test-harness changes. +Reserve `npm run check` for repo-wide validation or coverage-baseline changes. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index adddd93405a..e21982ef79f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,7 +16,7 @@ - [ ] 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: @@ -27,11 +27,11 @@ - [ ] Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue: ## Verification - + - [ ] PR description includes the DCO sign-off declaration and every commit appears as `Verified` in GitHub -- [ ] Git hooks passed during commit and push, or `npx prek run --from-ref main --to-ref HEAD` passes -- [ ] Targeted tests pass for changed behavior -- [ ] Full `npm test` passes (broad runtime changes only) +- [ ] 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 or justification: +- [ ] 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) diff --git a/.github/actions/ci-static-checks/action.yaml b/.github/actions/ci-static-checks/action.yaml index e5d2aa5cea6..043466e958f 100644 --- a/.github/actions/ci-static-checks/action.yaml +++ b/.github/actions/ci-static-checks/action.yaml @@ -42,8 +42,6 @@ runs: shell: bash run: | npx prek run --all-files --stage pre-commit \ - --skip test-cli \ - --skip test-plugin \ --skip source-shape-test-budget \ --skip test-file-size-budget \ --skip test-skills-yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1349c651f49..9b6a4b0d05e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,9 +12,10 @@ # Usage: # npx prek install # npx prek run --all-files +# npx prek run --all-files --stage manual # full CLI/plugin coverage # -# CI / diff-only runs: -# npx prek run --from-ref --to-ref HEAD +# Diff-only fallback for automatic commit, commit-message, and push checks: +# npm run check:diff # # Priority groups (prek runs same-priority hooks in parallel): # 0 — General file fixers (whitespace, EOF, line endings) @@ -240,17 +241,16 @@ repos: entry: bash -c 'npm run build:cli && npx tsc -p jsconfig.json' language: system pass_filenames: false - files: ^(bin|test|scripts)/.*\.js$ + files: ^(bin|test|scripts)/.*\.js$|^(jsconfig\.json|package(-lock)?\.json)$ stages: [pre-push] priority: 10 - id: tsc-cli name: TypeScript (CLI) - entry: npx tsc -p tsconfig.cli.json + entry: npm run typecheck:cli -- --incremental language: system pass_filenames: false - files: ^(bin|scripts|src|test|nemoclaw-blueprint/scripts)/.*\.(ts|tsx)$|^tsconfig\.cli\.json$ - always_run: true + files: ^(\.agents|agents/hermes|bin|scripts|src|test|tools|nemoclaw/src|nemoclaw-blueprint/scripts)/.*\.(ts|tsx|mts|cts|json)$|^(package(-lock)?\.json|tsconfig\.cli\.json|vitest\.config\.ts)$ stages: [pre-push] priority: 10 @@ -279,25 +279,26 @@ repos: stages: [post-merge, post-checkout] priority: 10 - # ── Priority 20: project-level checks (coverage + ratchet) ───────────────── + # ── Priority 20: project-level checks (full coverage is manual) ──────────── - repo: local hooks: - id: test-cli name: Test (CLI) - entry: >- - bash -c 'node -e "require(\"node:fs\").rmSync(\"dist\", { recursive: true, force: true })" && npm run build:cli && npx tsx scripts/check-dist-sourcemaps.ts dist && npx vitest run --project cli --project integration --coverage --coverage.reporter=text-summary --coverage.reporter=json-summary --coverage.reportsDirectory=coverage/cli --coverage.include="bin/**/*.js" --coverage.include="src/**/*.ts" --coverage.exclude="test/**/*.js" --coverage.exclude="test/**/*.ts" && npx tsx scripts/check-coverage-ratchet.ts coverage/cli/coverage-summary.json ci/coverage-threshold-cli.json "CLI coverage"' + entry: npm run test:coverage:cli language: system pass_filenames: false files: ^(bin/|src/.*\.(ts|tsx|js|mjs|cjs)$|test/.*\.(ts|tsx|js|mjs|cjs)$) require_serial: true + stages: [manual] priority: 20 - id: test-plugin name: Test (plugin) - entry: bash -c 'npx vitest run --project plugin --coverage --coverage.reporter=text-summary --coverage.reporter=json-summary --coverage.reportsDirectory=coverage/plugin --coverage.include="nemoclaw/src/**/*.ts" --coverage.exclude="**/*.test.ts" && npx tsx scripts/check-coverage-ratchet.ts coverage/plugin/coverage-summary.json ci/coverage-threshold-plugin.json "Plugin coverage"' + entry: npm run test:coverage:plugin language: system pass_filenames: false files: ^nemoclaw/ + stages: [manual] priority: 20 - id: source-shape-test-budget diff --git a/AGENTS.md b/AGENTS.md index 57ed7e226ae..4d99c7037a2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,15 +47,15 @@ Package-specific guides: | Launch pinned coding agent | `npm run agent` | | Build plugin | `cd nemoclaw && npm run build` | | Watch mode | `cd nemoclaw && npm run dev` | -| Run all tests | `npm test` | +| Run all tests for broad changes | `npm test` | | Render behavior-oriented test tree | `npm run test:spec` | | Run fast source tests | `npm run test:fast` | | Run integration tests | `npm run test:integration` | | Run package contracts | `npm run test:package` | | Run live E2E targets | `npm run test:live-e2e` | | Run plugin tests | `cd nemoclaw && npm test` | -| Run all repository checks | `npm run check` | -| Run all hooks manually | `npx prek run --all-files` | +| Run repo-wide pre-commit and coverage checks | `npm run check` | +| Reproduce `pre-commit`, `commit-msg`, and `pre-push` checks for the current diff | `npm run check:diff` | | Type-check CLI | `npm run typecheck:cli` | | Auto-format | `npm run format` | | Build docs | `npm run docs` | @@ -159,9 +159,9 @@ All hooks managed by [prek](https://prek.j178.dev/) (installed via `npm install` | Hook | What runs | |------|-----------| -| **pre-commit** | File fixers, formatters, linters, Vitest (plugin) | +| **pre-commit** | Cheap structural and file-local checks, including fixers, formatters, and linters | | **commit-msg** | commitlint (Conventional Commits) | -| **pre-push** | TypeScript type check (tsc --noEmit for plugin, JS, CLI) | +| **pre-push** | Path-scoped incremental CLI/plugin TypeScript checks and checked-JavaScript checks | ## Working with This Repo @@ -171,7 +171,7 @@ All hooks managed by [prek](https://prek.j178.dev/) (installed via `npm install` 2. For a first-time checkout, use `.agents/skills/nemoclaw-contributor-onboard/SKILL.md` or run `npm run dev:setup` 3. Run `npm run dev:doctor` to verify the contributor environment without changing it 4. Use `./scripts/dev-setup.sh --expose-cli` only with explicit approval for host-visible CLI exposure -5. Run tests targeted to the area you plan to change; reserve the full suite for broad changes +5. Run the tests targeted to the behavior you change once per relevant change set; rerun them after later edits or hook autofixes that can affect that behavior ### Git and GitHub Access Failures @@ -228,13 +228,13 @@ Follow `.agents/skills/_shared/pr-follow-up.md`: after opening or pushing to a P ## PR Requirements - Create feature branch from `main` -- Let normal commit and push hooks provide hook verification before submitting +- Let normal `pre-commit`, `commit-msg`, and `pre-push` hooks provide hook verification before submitting - Contributor-owned PRs must self-serve the DCO declaration and GitHub commit verification before opening a PR - Every contributor-owned PR description must include a valid `Signed-off-by:` declaration for the contributor, and every commit in the PR must appear as `Verified` in GitHub - Contributor agents must stop before `gh pr create` if the PR body will not include the DCO declaration or any commit is missing GitHub verification; tell the contributor to fix the issue before opening a PR - If force-push is not allowed and an already-published branch contains an unverified commit, require a fresh branch and fresh PR with a clean compliant history -- Run targeted tests for changed behavior, and run `npm run docs` for doc changes -- Use `npx prek run --from-ref main --to-ref HEAD` if hooks were skipped or unavailable +- Run targeted tests once per relevant change set, rerunning after later behavior-affecting edits or hook autofixes, and run `npm run docs` for doc changes +- Count successful normal hooks as verification; if hooks were skipped or unavailable, refresh `origin/main` and use `npm run check:diff` - Follow PR template (`.github/PULL_REQUEST_TEMPLATE.md`) - No secrets, API keys, or credentials committed - Limit open PRs to fewer than 10 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ed34c6ae3fc..e109340c8eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -168,10 +168,11 @@ These are the primary npm scripts for day-to-day development: | `npm run dev:setup` | Install or repair repository-local contributor tooling | | `npm run dev:doctor` | Run read-only contributor environment readiness checks | | `npm run agent` | Launch the repository-pinned Pi coding agent | -| `npm run check` | Run all repository checks | +| `npm run check` | Run repo-wide pre-commit and full CLI/plugin coverage checks | +| `npm run check:diff` | Reproduce `pre-commit`, `commit-msg`, and `pre-push` checks for the diff from `origin/main` | | `npm run format` | Auto-format Biome-supported source files | -| `npm run typecheck:cli` | Type-check CLI TypeScript using `tsconfig.cli.json` (`bin/`, `scripts/`, `src/`, `test/`, `nemoclaw-blueprint/scripts/`) | -| `npm test` | Build package artifacts and run every non-live Vitest project | +| `npm run typecheck:cli` | Type-check the root TypeScript project using `tsconfig.cli.json` | +| `npm test` | Build package artifacts and run every non-live Vitest project for broad changes | | `npm run test:spec` | Run every non-live test with hierarchical behavior-oriented output | | `npm run test:fast` | Clean `dist/` and run source CLI, plugin, and E2E-support tests | | `npm run test:integration` | Clean-build the CLI and run root integration and installer tests | @@ -182,7 +183,6 @@ These are the primary npm scripts for day-to-day development: | `npm run docs:live` | Serve Fern docs locally with auto-rebuild | | `npm run docs:preview:watch` | Publish branch-based Fern previews when docs files change | | `npm run docs:deps` | Print the pinned Fern CLI version used by docs commands | -| `npx prek run --all-files` | Run all hooks from `.pre-commit-config.yaml` — see below | ### Test Titles as Behavioral Documentation @@ -202,24 +202,22 @@ All git hooks are managed by [prek](https://prek.j178.dev/), a fast, single-bina | Hook | What runs | |------|-----------| -| **pre-commit** | File fixers, formatters, linters, skill frontmatter validation, Vitest (plugin) | +| **pre-commit** | Cheap structural and file-local checks, including fixers, formatters, linters, and skill frontmatter validation | | **commit-msg** | commitlint (Conventional Commits) | -| **pre-push** | TypeScript type check (`tsc --noEmit` for plugin, JS, and CLI) | +| **pre-push** | Path-scoped incremental CLI/plugin TypeScript checks and checked-JavaScript checks | -For PR preparation, normal commit and push hooks are valid verification when they ran without `--no-verify`. -If hooks were skipped, missing, failed, or uncertain, use a scoped fallback: `npx prek run --from-ref --to-ref HEAD`. -Reserve `npx prek run --all-files` for whole-repository baselines, such as hook, formatter, generated-check, or repo-wide validation changes. +For PR preparation, normal `pre-commit`, `commit-msg`, and `pre-push` hooks are valid verification when they pass and were not bypassed with `--no-verify`. +If hooks were skipped, missing, failed, or uncertain, run `npm run check:diff` once to reproduce those checks for the diff from `origin/main`. +Refresh that remote-tracking base with `git fetch origin main` before relying on the fallback. -For TypeScript changes under `src/`, `test/`, `scripts/`, `bin/`, or -`nemoclaw-blueprint/scripts/` (and for `tsconfig.cli.json` updates), the pre-push -hook runs `npm run typecheck:cli` before the branch is pushed. -CI runs this unconditionally. -If the pre-push hook was skipped or unavailable, run `npm run typecheck:cli` -manually before opening a PR. +Pre-push selects the root TypeScript, checked-JavaScript, and plugin type checks from the paths changed relative to the push base, and uses incremental compilation for the TypeScript projects. +The `check:diff` fallback applies the same path selection, so do not rerun type checks separately solely to prepare a PR. +CI runs the complete type-check gates independently; local path selection is a fast-feedback optimization, not the authoritative trust boundary. If you still have `core.hooksPath` set from an old Husky setup, Git will ignore `.git/hooks`. Run `git config --unset core.hooksPath` in this repo, then `npm install` so `prek install` (via `prepare`) can register the hooks. -`npm run check` is the primary command for running repository checks. +`npm run check` is the whole-repository pre-commit and full CLI/plugin coverage baseline for broad changes to hooks, formatters, generated checks, or shared validation behavior. +It is not part of routine PR preparation for a focused change. For doc-only changes, you do not need to run the full test suite by default. Commit and push normally so the hooks run, then run the docs build: @@ -228,10 +226,12 @@ Commit and push normally so the hooks run, then run the docs build: npm run docs ``` -Leave `npm test` unchecked in the PR verification checklist unless you actually ran it. -If hooks were skipped or unavailable, run `npx prek run --from-ref main --to-ref HEAD` before opening the PR. -For code changes, run targeted tests for the changed behavior. -Reserve full `npm test` for broad runtime changes, test harness changes, or cases where targeted coverage is hard to justify. +Leave the broad-gate verification item unchecked unless you actually ran the applicable command. +If hooks were skipped or unavailable, run `npm run check:diff` before opening the PR. +For code changes, run the targeted tests for changed behavior once per relevant change set and record that command as evidence. +Do not rerun them solely because hooks passed, but do rerun after later edits or hook autofixes that can affect the tested behavior. +Reserve `npm test` for broad runtime changes, test harness changes, or cases where targeted coverage is hard to justify. +Reserve `npm run check` for repo-wide hook, formatter, generated-check, or coverage-baseline changes. ## Project Structure @@ -331,8 +331,8 @@ Follow these steps to submit a pull request. 1. Create a feature branch from `main`. 2. Make your changes with tests. 3. Run the relevant checks. - Let normal commit and push hooks provide hook verification, run targeted tests for changed behavior, and run `npm run docs` for doc changes. - If hooks were skipped or unavailable, run `npx prek run --from-ref main --to-ref HEAD`. + Run targeted tests once per relevant change set, let normal hooks provide verification, and run `npm run docs` for doc changes. + Rerun targeted tests after later behavior-affecting edits or hook autofixes. If hooks were skipped or unavailable, run `npm run check:diff` once instead of reproducing the checks separately. 4. Confirm the PR description includes the DCO declaration and every commit appears as `Verified` in GitHub. 5. Open a PR. diff --git a/docs/AGENTS.md b/docs/AGENTS.md index 52d5b015ae4..a3112bf0de8 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -43,6 +43,6 @@ Treat `docs/` as the source of truth for published content and AI-agent Markdown - Run `npm run docs:sync-agent-variants` after editing shared variant source pages or navigation. - Run `npm run docs` before opening a PR for docs or Fern changes. -- For doc-only PRs, rely on normal commit and push hooks when they ran. - If hooks were skipped or unavailable, run `npx prek run --from-ref main --to-ref HEAD`. -- Leave `npm test` unchecked in the PR verification checklist unless you actually ran it. +- For doc-only PRs, rely on normal `pre-commit`, `commit-msg`, and `pre-push` hooks when they pass. + If hooks were skipped or unavailable, refresh `origin/main` and run `npm run check:diff` once to reproduce those checks. +- Leave the broad-gate verification item unchecked unless you actually ran the applicable command. diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 650203bc328..2b60c404af6 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -117,9 +117,12 @@ Commit and push normally so the Git hooks run, then run: npm run docs ``` -Leave `npm test` unchecked in the PR verification checklist unless you actually ran it. -If hooks were skipped or unavailable, run `npx prek run --from-ref main --to-ref HEAD` before opening the PR. -Run targeted tests only when the change also touches code, generated behavior, or runtime behavior. +Leave the broad-gate verification item unchecked unless you actually ran the applicable command. +If normal `pre-commit`, `commit-msg`, or `pre-push` hooks were skipped or unavailable, run `npm run check:diff` once to reproduce those checks before opening the PR. +The command uses `origin/main`, so refresh it with `git fetch origin main` first. +Run targeted tests once per relevant change set only when the change also touches code, generated behavior, or runtime behavior; rerun after later edits or hook autofixes that can affect it. +Reserve `npm test` for broad runtime or test-harness changes. +Reserve `npm run check` for repo-wide validation or coverage-baseline changes. ## Writing Conventions diff --git a/fern/AGENTS.md b/fern/AGENTS.md index e07665add19..24a51bc22d5 100644 --- a/fern/AGENTS.md +++ b/fern/AGENTS.md @@ -34,4 +34,6 @@ Use this guide when editing files under `fern/`. - Run `npm run docs` after Fern configuration changes. - Run `npm run docs:live` when layout, component, CSS, or asset changes need visual review. - Run `npm run docs:preview:watch` only when you need to verify branch preview publication behavior. -- For doc-only or Fern-only PRs, run `npx prek run --all-files` unless the user asks for a narrower draft. +- For doc-only or Fern-only PRs, rely on normal `pre-commit`, `commit-msg`, and `pre-push` hooks when they pass. +- If hooks were skipped or unavailable, refresh `origin/main` and run `npm run check:diff` once to reproduce those checks. +- Do not run `npm run check` or an all-files hook baseline routinely for focused docs changes. diff --git a/package.json b/package.json index 0ef3318d653..1665e6131e6 100644 --- a/package.json +++ b/package.json @@ -28,12 +28,15 @@ "test:fast": "npm run clean:cli && vitest run --project cli --project plugin --project e2e-support", "test:integration": "npm run clean:cli && npm run build:cli && vitest run --project integration --project installer-integration", "test:package": "npm run clean:cli && npm --prefix nemoclaw run clean && npm run build:cli && npm --prefix nemoclaw run build && vitest run --project package-contract", + "test:coverage:cli": "npm run clean:cli && npm run build:cli && tsx scripts/check-dist-sourcemaps.ts dist && vitest run --project cli --project integration --coverage --coverage.reporter=text-summary --coverage.reporter=json-summary --coverage.reportsDirectory=coverage/cli --coverage.include=\"bin/**/*.js\" --coverage.include=\"src/**/*.ts\" --coverage.exclude=\"test/**/*.js\" --coverage.exclude=\"test/**/*.ts\" && tsx scripts/check-coverage-ratchet.ts coverage/cli/coverage-summary.json ci/coverage-threshold-cli.json \"CLI coverage\"", + "test:coverage:plugin": "vitest run --project plugin --coverage --coverage.reporter=text-summary --coverage.reporter=json-summary --coverage.reportsDirectory=coverage/plugin --coverage.include=\"nemoclaw/src/**/*.ts\" --coverage.include=\"nemoclaw/src/**/*.cts\" --coverage.exclude=\"**/*.test.ts\" && tsx scripts/check-coverage-ratchet.ts coverage/plugin/coverage-summary.json ci/coverage-threshold-plugin.json \"Plugin coverage\"", "test:live-e2e": "NEMOCLAW_RUN_LIVE_E2E=1 vitest run --project e2e-live", "test:imports:check": "tsx scripts/checks/no-test-dist-imports.ts", "test:projects:check": "tsx scripts/checks/vitest-project-overlap.ts", "test:titles:check": "tsx scripts/checks/test-title-style.ts", "bench": "tsx scripts/bench/run.ts", - "check": "npx prek run --all-files", + "check": "npx prek run --all-files --stage pre-commit && npx prek run --all-files --stage manual", + "check:diff": "npx prek run --from-ref origin/main --to-ref HEAD --stage pre-commit && npx commitlint --from origin/main --to HEAD && npx prek run --from-ref origin/main --to-ref HEAD --stage pre-push", "checks": "tsx scripts/checks/run.ts", "lint": "npx @biomejs/biome lint . && npm run checks", "lint:fix": "npx @biomejs/biome lint --write . && npm run checks", diff --git a/test/pr-workflow-contract.test.ts b/test/pr-workflow-contract.test.ts index 1c156b2c5e6..b4b7fc30b56 100644 --- a/test/pr-workflow-contract.test.ts +++ b/test/pr-workflow-contract.test.ts @@ -31,10 +31,24 @@ type CodebaseGrowthGuardrailsWorkflow = { type PrekConfig = { default_stages?: string[]; repos: Array<{ - hooks?: Array<{ id: string; stages?: string[] }>; + hooks?: Array<{ + id: string; + always_run?: boolean; + entry?: string; + files?: string; + stages?: string[]; + }>; }>; }; +type PackageJson = { + scripts: Record; +}; + +type TypeScriptConfig = { + include: string[]; +}; + const sharedActionPaths = { staticChecks: "./.github/actions/ci-static-checks", buildTypecheck: "./.github/actions/ci-build-typecheck", @@ -165,6 +179,46 @@ function runWorkflowShellStep( }; } +function runLoggedPackageScript(script: string): string[][] { + const temp = mkdtempSync(join(tmpdir(), "nemoclaw-package-script-")); + const fakeBin = join(temp, "bin"); + const commandLog = join(temp, "commands.jsonl"); + mkdirSync(fakeBin); + + for (const command of ["npm", "npx", "tsx", "vitest"]) { + writeFileSync( + join(fakeBin, command), + [ + "#!/usr/bin/env node", + 'const fs = require("node:fs");', + `fs.appendFileSync(process.env.COMMAND_LOG, JSON.stringify(["${command}", ...process.argv.slice(2)]) + "\\n");`, + ].join("\n"), + { mode: 0o755 }, + ); + } + + try { + const result = spawnSync("sh", ["-c", script], { + encoding: "utf8", + env: { + ...process.env, + COMMAND_LOG: commandLog, + PATH: `${fakeBin}:${process.env.PATH ?? ""}`, + }, + }); + if (result.status !== 0) { + throw new Error(`Package script failed: ${result.stderr}`); + } + return readFileSync(commandLog, "utf8") + .trim() + .split("\n") + .filter(Boolean) + .map((line) => JSON.parse(line) as string[]); + } finally { + rmSync(temp, { force: true, recursive: true }); + } +} + function codeFilterMatchesChangedPaths(workflow: CiWorkflow, paths: string[]): boolean { const filterStep = workflow.jobs.changes.steps?.find((step) => step.id === "filter"); const quantifier = filterStep?.with?.["predicate-quantifier"]; @@ -207,6 +261,10 @@ describe("pull request and main workflow contracts", () => { ".github/actions/ci-installer-hash-check/action.yaml", ); const prekConfig = readYaml(".pre-commit-config.yaml"); + const packageJson = JSON.parse(readFileSync("package.json", "utf8")) as PackageJson; + const cliTypeScriptConfig = JSON.parse( + readFileSync("tsconfig.cli.json", "utf8"), + ) as TypeScriptConfig; const sharedActions = { staticChecks: readYaml(".github/actions/ci-static-checks/action.yaml"), buildTypecheck: readYaml(".github/actions/ci-build-typecheck/action.yaml"), @@ -500,13 +558,15 @@ describe("pull request and main workflow contracts", () => { ).toBe(true); }); - it("keeps ordinary hooks in pre-commit and heavyweight push hooks explicit", () => { + it("keeps ordinary hooks automatic and full coverage explicit", () => { const hooks = prekConfig.repos.flatMap((repo) => repo.hooks ?? []); const hook = (id: string) => hooks.find((candidate) => candidate.id === id); expect(prekConfig.default_stages).toEqual(["pre-commit"]); - expect(hook("test-cli")?.stages).toBeUndefined(); - expect(hook("test-plugin")?.stages).toBeUndefined(); + expect(hook("test-cli")?.stages).toEqual(["manual"]); + expect(hook("test-cli")?.entry).toBe("npm run test:coverage:cli"); + expect(hook("test-plugin")?.stages).toEqual(["manual"]); + expect(hook("test-plugin")?.entry).toBe("npm run test:coverage:plugin"); for (const id of [ "trailing-whitespace", "end-of-file-fixer", @@ -522,6 +582,122 @@ describe("pull request and main workflow contracts", () => { } }); + it("scopes pre-push typechecks to project and transitive inputs", () => { + const hooks = prekConfig.repos.flatMap((repo) => repo.hooks ?? []); + const cliTypecheck = hooks.find((candidate) => candidate.id === "tsc-cli"); + const jsTypecheck = hooks.find((candidate) => candidate.id === "tsc-js"); + const files = new RegExp(cliTypecheck?.files ?? "(?!)", "u"); + const jsFiles = new RegExp(jsTypecheck?.files ?? "(?!)", "u"); + + expect(cliTypecheck?.entry).toBe("npm run typecheck:cli -- --incremental"); + expect(cliTypecheck?.always_run).toBeUndefined(); + for (const include of cliTypeScriptConfig.include) { + const representativeInput = include.replace("**/*", "nested/input"); + expect(files.test(representativeInput), include).toBe(true); + } + for (const path of [ + ".agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts", + "agents/hermes/generate-config.ts", + "bin/nemoclaw.ts", + "scripts/check.ts", + "scripts/check.mts", + "src/lib/runner.ts", + "test/runner.test.ts", + "tools/e2e/workflow-boundary.mts", + "nemoclaw/src/lib/subprocess-env.ts", + "nemoclaw/src/blueprint/private-networks.ts", + "nemoclaw-blueprint/scripts/render.ts", + "src/lib/actions/sandbox/credentials.json", + "package.json", + "package-lock.json", + "tsconfig.cli.json", + "vitest.config.ts", + ]) { + expect(files.test(path), path).toBe(true); + } + for (const path of [ + "agents/hermes/start.sh", + "docs/get-started/quickstart.mdx", + "scripts/check.js", + ]) { + expect(files.test(path), path).toBe(false); + } + for (const path of ["bin/nemoclaw.js", "jsconfig.json", "package.json", "package-lock.json"]) { + expect(jsFiles.test(path), path).toBe(true); + } + expect(jsFiles.test("docs/_ext/nemoclaw.js")).toBe(false); + }); + + it("executes repo-wide coverage and diff-scoped automatic hook commands", () => { + const scripts = packageJson.scripts; + const cliCoverageCalls = runLoggedPackageScript(scripts["test:coverage:cli"]); + const pluginCoverageCalls = runLoggedPackageScript(scripts["test:coverage:plugin"]); + const repoCheckCalls = runLoggedPackageScript(scripts.check); + const diffCheckCalls = runLoggedPackageScript(scripts["check:diff"]); + + expect(cliCoverageCalls.map(([command]) => command)).toEqual([ + "npm", + "npm", + "tsx", + "vitest", + "tsx", + ]); + expect(cliCoverageCalls[3]).toEqual( + expect.arrayContaining(["--project", "cli", "integration", "--coverage"]), + ); + expect(cliCoverageCalls[4]).toEqual([ + "tsx", + "scripts/check-coverage-ratchet.ts", + "coverage/cli/coverage-summary.json", + "ci/coverage-threshold-cli.json", + "CLI coverage", + ]); + expect(pluginCoverageCalls[0]).toEqual( + expect.arrayContaining([ + "--project", + "plugin", + "--coverage.include=nemoclaw/src/**/*.ts", + "--coverage.include=nemoclaw/src/**/*.cts", + ]), + ); + expect(pluginCoverageCalls[1]).toEqual([ + "tsx", + "scripts/check-coverage-ratchet.ts", + "coverage/plugin/coverage-summary.json", + "ci/coverage-threshold-plugin.json", + "Plugin coverage", + ]); + expect(repoCheckCalls).toEqual([ + ["npx", "prek", "run", "--all-files", "--stage", "pre-commit"], + ["npx", "prek", "run", "--all-files", "--stage", "manual"], + ]); + expect(diffCheckCalls).toEqual([ + [ + "npx", + "prek", + "run", + "--from-ref", + "origin/main", + "--to-ref", + "HEAD", + "--stage", + "pre-commit", + ], + ["npx", "commitlint", "--from", "origin/main", "--to", "HEAD"], + [ + "npx", + "prek", + "run", + "--from-ref", + "origin/main", + "--to-ref", + "HEAD", + "--stage", + "pre-push", + ], + ]); + }); + it("reuses the same shared CI actions in PR and main workflows", () => { for (const [jobName, stepName, trustedActionPath, mainActionPath] of [ [ @@ -722,14 +898,14 @@ describe("pull request and main workflow contracts", () => { expect(staticRuns).toContain("npm run typecheck:scorecard"); expect(staticPrekRun).toContain("npx prek run --all-files --stage pre-commit"); for (const skippedHook of [ - "test-cli", - "test-plugin", "source-shape-test-budget", "test-file-size-budget", "test-skills-yaml", ]) { expect(staticPrekRun).toContain(`--skip ${skippedHook}`); } + expect(staticPrekRun).not.toContain("--skip test-cli"); + expect(staticPrekRun).not.toContain("--skip test-plugin"); expect(staticRuns).toContain("npm run source-shape:check"); expect(staticRuns).toContain("npm run test-size:check"); expect(staticRuns).toContain("npx vitest run test/skills-frontmatter.test.ts"); diff --git a/test/skills-frontmatter.test.ts b/test/skills-frontmatter.test.ts index 7a0ad1e9519..4639ef1bbef 100644 --- a/test/skills-frontmatter.test.ts +++ b/test/skills-frontmatter.test.ts @@ -107,7 +107,10 @@ describe("repo skill markdown files", () => { expect(skill).toContain("trusted base branch"); expect(skill).toContain("origin/main:.github/PULL_REQUEST_TEMPLATE.md"); + expect(skill).toContain("git log origin/main..HEAD"); expect(skill).toContain("git diff origin/main...HEAD"); + expect(skill).toContain("git rev-list origin/main..HEAD"); + expect(skill).not.toMatch(/(? Date: Sat, 4 Jul 2026 01:17:10 -0700 Subject: [PATCH 2/5] test(ci): keep workflow contract linear Signed-off-by: Carlos Villela --- test/pr-workflow-contract.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/pr-workflow-contract.test.ts b/test/pr-workflow-contract.test.ts index b4b7fc30b56..e5554f71457 100644 --- a/test/pr-workflow-contract.test.ts +++ b/test/pr-workflow-contract.test.ts @@ -206,9 +206,7 @@ function runLoggedPackageScript(script: string): string[][] { PATH: `${fakeBin}:${process.env.PATH ?? ""}`, }, }); - if (result.status !== 0) { - throw new Error(`Package script failed: ${result.stderr}`); - } + expect(result.status, `Package script failed: ${result.stderr}`).toBe(0); return readFileSync(commandLog, "utf8") .trim() .split("\n") From 7b514c62bc49d7db632ee45134aa2434e44a090f Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sat, 4 Jul 2026 01:23:03 -0700 Subject: [PATCH 3/5] fix(hooks): align typecheck path scopes Signed-off-by: Carlos Villela --- .pre-commit-config.yaml | 2 +- test/pr-workflow-contract.test.ts | 15 ++++++++++++--- tsconfig.cli.json | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9b6a4b0d05e..695fb9bb91c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -250,7 +250,7 @@ repos: entry: npm run typecheck:cli -- --incremental language: system pass_filenames: false - files: ^(\.agents|agents/hermes|bin|scripts|src|test|tools|nemoclaw/src|nemoclaw-blueprint/scripts)/.*\.(ts|tsx|mts|cts|json)$|^(package(-lock)?\.json|tsconfig\.cli\.json|vitest\.config\.ts)$ + files: ^(agents/hermes|bin|scripts|src|test|tools|nemoclaw-blueprint/scripts)/.*\.(ts|tsx|mts|cts|json)$|^\.agents/skills/nemoclaw-maintainer-day/scripts/pra-gate\.ts$|^(package(-lock)?\.json|tsconfig\.cli\.json|vitest\.config\.ts)$ stages: [pre-push] priority: 10 diff --git a/test/pr-workflow-contract.test.ts b/test/pr-workflow-contract.test.ts index e5554f71457..7b8d00c2704 100644 --- a/test/pr-workflow-contract.test.ts +++ b/test/pr-workflow-contract.test.ts @@ -582,8 +582,10 @@ describe("pull request and main workflow contracts", () => { it("scopes pre-push typechecks to project and transitive inputs", () => { const hooks = prekConfig.repos.flatMap((repo) => repo.hooks ?? []); + const pluginTypecheck = hooks.find((candidate) => candidate.id === "tsc-plugin"); const cliTypecheck = hooks.find((candidate) => candidate.id === "tsc-cli"); const jsTypecheck = hooks.find((candidate) => candidate.id === "tsc-js"); + const pluginFiles = new RegExp(pluginTypecheck?.files ?? "(?!)", "u"); const files = new RegExp(cliTypecheck?.files ?? "(?!)", "u"); const jsFiles = new RegExp(jsTypecheck?.files ?? "(?!)", "u"); @@ -594,7 +596,6 @@ describe("pull request and main workflow contracts", () => { expect(files.test(representativeInput), include).toBe(true); } for (const path of [ - ".agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts", "agents/hermes/generate-config.ts", "bin/nemoclaw.ts", "scripts/check.ts", @@ -602,8 +603,6 @@ describe("pull request and main workflow contracts", () => { "src/lib/runner.ts", "test/runner.test.ts", "tools/e2e/workflow-boundary.mts", - "nemoclaw/src/lib/subprocess-env.ts", - "nemoclaw/src/blueprint/private-networks.ts", "nemoclaw-blueprint/scripts/render.ts", "src/lib/actions/sandbox/credentials.json", "package.json", @@ -614,12 +613,22 @@ describe("pull request and main workflow contracts", () => { expect(files.test(path), path).toBe(true); } for (const path of [ + ".agents/skills/example/scripts/unchecked.ts", "agents/hermes/start.sh", "docs/get-started/quickstart.mdx", + "nemoclaw/src/lib/subprocess-env.ts", + "nemoclaw/src/blueprint/private-networks.ts", "scripts/check.js", ]) { expect(files.test(path), path).toBe(false); } + for (const path of [ + "nemoclaw/src/lib/subprocess-env.ts", + "nemoclaw/src/blueprint/private-networks.ts", + ]) { + expect(pluginFiles.test(path), path).toBe(true); + } + expect(pluginFiles.test(".agents/skills/example/scripts/unchecked.ts")).toBe(false); for (const path of ["bin/nemoclaw.js", "jsconfig.json", "package.json", "package-lock.json"]) { expect(jsFiles.test(path), path).toBe(true); } diff --git a/tsconfig.cli.json b/tsconfig.cli.json index 94c4ddfc817..31c7927079e 100644 --- a/tsconfig.cli.json +++ b/tsconfig.cli.json @@ -16,6 +16,6 @@ "moduleDetection": "force", "types": ["node"] }, - "include": ["agents/hermes/**/*.ts", "bin/**/*.ts", "scripts/**/*.ts", "scripts/**/*.mts", "src/**/*.ts", "test/**/*.ts", "tools/**/*.ts", "tools/**/*.mts", "nemoclaw-blueprint/scripts/**/*.ts"], + "include": [".agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts", "agents/hermes/**/*.ts", "bin/**/*.ts", "scripts/**/*.ts", "scripts/**/*.mts", "src/**/*.ts", "test/**/*.ts", "tools/**/*.ts", "tools/**/*.mts", "nemoclaw-blueprint/scripts/**/*.ts"], "exclude": ["node_modules", "nemoclaw"] } From fe0fdf5caa6df61bb309b351ffdaa20aebf17bd5 Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sat, 4 Jul 2026 01:25:32 -0700 Subject: [PATCH 4/5] fix(hooks): cover cross-project inputs Signed-off-by: Carlos Villela --- .pre-commit-config.yaml | 2 +- test/pr-workflow-contract.test.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 695fb9bb91c..dfa9c0a15c6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -250,7 +250,7 @@ repos: entry: npm run typecheck:cli -- --incremental language: system pass_filenames: false - files: ^(agents/hermes|bin|scripts|src|test|tools|nemoclaw-blueprint/scripts)/.*\.(ts|tsx|mts|cts|json)$|^\.agents/skills/nemoclaw-maintainer-day/scripts/pra-gate\.ts$|^(package(-lock)?\.json|tsconfig\.cli\.json|vitest\.config\.ts)$ + files: ^(agents/hermes|bin|scripts|src|test|tools|nemoclaw-blueprint/scripts)/.*\.(ts|tsx|mts|cts|json)$|^\.agents/skills/nemoclaw-maintainer-day/scripts/pra-gate\.ts$|^nemoclaw/src/(lib/subprocess-env|blueprint/private-networks)\.ts$|^(package(-lock)?\.json|tsconfig\.cli\.json|vitest\.config\.ts)$ stages: [pre-push] priority: 10 diff --git a/test/pr-workflow-contract.test.ts b/test/pr-workflow-contract.test.ts index 7b8d00c2704..5f8ee333c6b 100644 --- a/test/pr-workflow-contract.test.ts +++ b/test/pr-workflow-contract.test.ts @@ -603,6 +603,8 @@ describe("pull request and main workflow contracts", () => { "src/lib/runner.ts", "test/runner.test.ts", "tools/e2e/workflow-boundary.mts", + "nemoclaw/src/lib/subprocess-env.ts", + "nemoclaw/src/blueprint/private-networks.ts", "nemoclaw-blueprint/scripts/render.ts", "src/lib/actions/sandbox/credentials.json", "package.json", @@ -616,8 +618,7 @@ describe("pull request and main workflow contracts", () => { ".agents/skills/example/scripts/unchecked.ts", "agents/hermes/start.sh", "docs/get-started/quickstart.mdx", - "nemoclaw/src/lib/subprocess-env.ts", - "nemoclaw/src/blueprint/private-networks.ts", + "nemoclaw/src/commands/status.ts", "scripts/check.js", ]) { expect(files.test(path), path).toBe(false); @@ -625,6 +626,7 @@ describe("pull request and main workflow contracts", () => { for (const path of [ "nemoclaw/src/lib/subprocess-env.ts", "nemoclaw/src/blueprint/private-networks.ts", + "nemoclaw/src/commands/status.ts", ]) { expect(pluginFiles.test(path), path).toBe(true); } From 3a1dcae9c3720e85dc83e21c685af38467850884 Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Sat, 4 Jul 2026 01:40:29 -0700 Subject: [PATCH 5/5] fix(hooks): typecheck maintainer gate entrypoint Signed-off-by: Carlos Villela --- .pre-commit-config.yaml | 2 +- test/pr-workflow-contract.test.ts | 3 +++ tsconfig.cli.json | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dfa9c0a15c6..ebc96c2326a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -250,7 +250,7 @@ repos: entry: npm run typecheck:cli -- --incremental language: system pass_filenames: false - files: ^(agents/hermes|bin|scripts|src|test|tools|nemoclaw-blueprint/scripts)/.*\.(ts|tsx|mts|cts|json)$|^\.agents/skills/nemoclaw-maintainer-day/scripts/pra-gate\.ts$|^nemoclaw/src/(lib/subprocess-env|blueprint/private-networks)\.ts$|^(package(-lock)?\.json|tsconfig\.cli\.json|vitest\.config\.ts)$ + files: ^(agents/hermes|bin|scripts|src|test|tools|nemoclaw-blueprint/scripts)/.*\.(ts|tsx|mts|cts|json)$|^\.agents/skills/nemoclaw-maintainer-day/scripts/(check-gates|pra-gate|shared)\.ts$|^nemoclaw/src/(lib/subprocess-env|blueprint/private-networks)\.ts$|^(package(-lock)?\.json|tsconfig\.cli\.json|vitest\.config\.ts)$ stages: [pre-push] priority: 10 diff --git a/test/pr-workflow-contract.test.ts b/test/pr-workflow-contract.test.ts index 5f8ee333c6b..e403ed3c1cc 100644 --- a/test/pr-workflow-contract.test.ts +++ b/test/pr-workflow-contract.test.ts @@ -596,6 +596,9 @@ describe("pull request and main workflow contracts", () => { expect(files.test(representativeInput), include).toBe(true); } for (const path of [ + ".agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts", + ".agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts", + ".agents/skills/nemoclaw-maintainer-day/scripts/shared.ts", "agents/hermes/generate-config.ts", "bin/nemoclaw.ts", "scripts/check.ts", diff --git a/tsconfig.cli.json b/tsconfig.cli.json index 31c7927079e..a4bfb3e13e7 100644 --- a/tsconfig.cli.json +++ b/tsconfig.cli.json @@ -16,6 +16,6 @@ "moduleDetection": "force", "types": ["node"] }, - "include": [".agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts", "agents/hermes/**/*.ts", "bin/**/*.ts", "scripts/**/*.ts", "scripts/**/*.mts", "src/**/*.ts", "test/**/*.ts", "tools/**/*.ts", "tools/**/*.mts", "nemoclaw-blueprint/scripts/**/*.ts"], + "include": [".agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts", ".agents/skills/nemoclaw-maintainer-day/scripts/pra-gate.ts", ".agents/skills/nemoclaw-maintainer-day/scripts/shared.ts", "agents/hermes/**/*.ts", "bin/**/*.ts", "scripts/**/*.ts", "scripts/**/*.mts", "src/**/*.ts", "test/**/*.ts", "tools/**/*.ts", "tools/**/*.mts", "nemoclaw-blueprint/scripts/**/*.ts"], "exclude": ["node_modules", "nemoclaw"] }