Skip to content

fix(kanban): run npm ci in linked worktrees of npm-workspaces repos - #135840

Draft
Byrd-IT wants to merge 1 commit into
NousResearch:mainfrom
Byrd-IT:fix/kanban-worktree-npm-workspace-deps
Draft

Byrd-IT wants to merge 1 commit into
NousResearch:mainfrom
Byrd-IT:fix/kanban-worktree-npm-workspace-deps

Conversation

@Byrd-IT

@Byrd-IT Byrd-IT commented Oct 9, 2026

Copy link
Copy Markdown

What does this PR do?

A dispatcher worktree (workspace_kind=worktree) holds tracked files only. In an npm-workspaces repo that means Node resolution from <repo>/.worktrees/<id> walks up into the main checkout's node_modules, whose workspace links (node_modules/@scope/pkg -> ../../packages/pkg) point at the main checkout's packages. The worker then builds, typechecks and tests code that is not on its branch, and nothing reports it. When the worktree is pinned outside the repo (worktree:<path>), resolution fails outright.

This change makes _ensure_git_worktree, and the same-branch reuse path in _resolve_worktree_workspace, run npm ci once when the worktree root has a package.json with workspaces, a package-lock.json, and no node_modules yet.

  • It uses Hermes' managed npm (find_node_executable("npm") + with_hermes_node_path()) and never falls back to PATH, per hermes_platform/AGENTS.md and tests/test_managed_runtime_resolution.py.
  • Network concurrency is bounded (--maxsockets 3), runtime is capped at 300 s, and it runs with --no-audit --no-fund.
  • Best effort. If managed npm is missing or the install fails, it logs a warning, removes any partial node_modules so the next dispatch retries, and still dispatches the task. Today's behaviour is the worst case.
  • Non-workspace projects are untouched. Walking up to the main checkout's node_modules is usually harmless there, and running an install for every JS repo would be a much larger behaviour change.

Alternatives considered

  • feat(kanban): fire kanban_worktree_created hook after git worktree add #104226 (open, kanban_worktree_created hook): if that lands, an operator could do this with a config hook and no core change. It targets a different gap (gitignored secrets) and has no maintainer review yet. If maintainers prefer the hook route for dependency provisioning, I'm happy to close this in its favour.
  • .worktreeinclude (CLI -w worktrees): it symlinks node_modules back to the main checkout, which reproduces exactly the wrong-package resolution described above for workspace packages. It also isn't wired into kanban worktrees.

Known tradeoff

The install runs inline in the dispatch path, just like git worktree add (60 s timeout) does today, so the first dispatch of a worktree can take up to 300 s longer. Subsequent dispatches skip it because node_modules now exists. I can move it off the tick if you'd prefer that shape.

Related Issue

None found. I searched open and closed PRs and issues for npm ci / node_modules / worktree provisioning; #104226 is the closest.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • hermes_cli/kanban_db_workspace.py: new _provision_npm_workspace_dependencies(worktree). It is called after git worktree add, on the existing-worktree early return in _ensure_git_worktree, and on the same-branch reuse path in _resolve_worktree_workspace.
  • tests/hermes_cli/test_kanban_worktree_npm_workspace.py (new) builds a real two-package npm-workspaces repo, offline, with an installed main checkout, and covers three cases:
    • a fresh worktree resolves @fixture/a inside the worktree;
    • a reused same-branch worktree is provisioned;
    • a failing npm (POSIX fake) does not block dispatch, leaves no partial node_modules, and logs the npm error.
  • website/docs/user-guide/features/kanban.md: one sentence on the new worktree behaviour.

How to Test

  1. scripts/run_tests.sh tests/hermes_cli/test_kanban_worktree_npm_workspace.py gives 3 passed.
  2. Red on base: with the base kanban_db_workspace.py (plus only the two imported seam names so the monkeypatch targets exist), the two resolution tests fail. require.resolve('@fixture/a') from the worktree returns the main checkout's packages/a. The failure-path test passes on base by construction, because base never runs npm. It pins the best-effort contract.
  3. Related suites: scripts/run_tests.sh on the new file, test_kanban_worktree_{isolation,teardown,unicode_path}.py, tests/test_managed_runtime_resolution.py, test_kanban_core_functionality.py, test_kanban_db.py, test_kanban_notify.py, tests/security/test_gitspawn_config_injection.py and tests/tools/test_kanban_tools.py gives 10 files, 217 passed, 0 failed, 3 skipped (the skips are pre-existing and outside the new file).
  4. python scripts/check --base upstream/main gives 11 checks ok.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass (only the touched/related files were run via scripts/run_tests.sh; see above)
  • python scripts/check passes
  • I've added tests for my changes
  • I've tested on my platform: Ubuntu 24.04 (Linux x86_64)

Documentation & Housekeeping

  • I've updated relevant documentation: website/docs/user-guide/features/kanban.md
  • I've updated cli-config.yaml.example if I added/changed config keys: N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows: N/A
  • I've considered cross-platform impact: npm goes through find_node_executable (handles the .cmd shim) with windows_hide_flags(), package.json is read as utf-8-sig, and the fake-npm failure test is platforms("posix")
  • I've updated tool descriptions/schemas if I changed tool behavior: N/A

A dispatcher worktree holds tracked files only. In an npm-workspaces repo,
Node resolution from <repo>/.worktrees/<id> walks up into the main
checkout's node_modules, whose workspace links point at the MAIN
checkout's packages, so the worker builds and tests code that is not on
its branch (or fails to resolve anything when the worktree lives outside
the repo).

_ensure_git_worktree and the same-branch reuse path in
_resolve_worktree_workspace now run `npm ci` once when the worktree root
has package.json with "workspaces" plus package-lock.json and no
node_modules yet. It uses Hermes' managed npm, bounds network concurrency
(--maxsockets 3) and runtime (300s), and is best effort: a missing npm or
a failed install is logged, a partial node_modules is removed so the next
dispatch retries, and the task still dispatches.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels Oct 9, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants