Skip to content

#1095 Move compilation out of the install lifecycle into a bootstrap step - #1102

Merged
williamthorsen merged 7 commits into
mainfrom
1095
Jul 28, 2026
Merged

#1095 Move compilation out of the install lifecycle into a bootstrap step#1102
williamthorsen merged 7 commits into
mainfrom
1095

Conversation

@williamthorsen

@williamthorsen williamthorsen commented Jul 28, 2026

Copy link
Copy Markdown
Owner

What

Fixes an issue where installation of dependencies failed intermittently. Reaching a usable tree afterward now takes one command, pnpm run bootstrap, and every workflow that needs a built tree runs it. A command-line tool invoked before bootstrapping now points to a command that exists.

Why

The dependency-installation step failed intermittently on the default branch — five runs since 2026-07-19 — while branch runs of the same commits passed, so a red pipeline carried no signal about the code under test. Separately, codeassembly-mcp would not start from its build output, leaving the run-management tools it exposes unavailable to any client that launched it.

Details

🐛 Bug fixes

  • codeassembly-mcp failed to start with ERR_MODULE_NOT_FOUND. The MCP SDK routes unlisted subpaths through a "./*" export that appends no extension, so server/stdio, server/mcp, client/stdio, and inMemory each need an explicit .js. client keeps its extensionless form, which the SDK exports explicitly. Vite resolves the extensionless form and Node does not, so the test suite exercised these imports without observing the failure.

⚙️ Tooling

  • Workspace packages no longer compile during dependency installation. The removed hooks ran concurrently with the package manager's own executable linking and intermittently invoked a shim before it was executable.
  • A root bootstrap script builds every package, giving a fresh clone or worktree one command to reach a usable state.
  • Worktree creation, the CI job, and the documented clone sequence all reach a built tree through that one command. The build runs in CI's own bootstrap step rather than inside the check command, so a build break turns that step red instead of surfacing as a check failure.

📚 Documentation

  • The four command-line wrappers named pnpm run build for a missing build, which the repository root does not define; they now name the command that exists.
  • The quick start's check step runs on a fresh clone. It named a binary that resolves only after direnv is configured.
  • The bin-wrapper section carries only what a new bin entry must honor and the pointer to the template.

Test plan

  • Confirm a fresh clone reaches a usable tree: pnpm install emits no compile lines, then pnpm run bootstrap populates dist/ for kb, lifecycle, mcp, run-core, and agents.
  • Confirm each built wrapper starts under Node: codeassembly-mcp answers an initialize request, and codeassembly-agents, kb, and codeassembly-runs respond to --help.
  • Confirm CI's bootstrap step performs the build and the check step runs checks alone.

Closes #1095

`pnpm install` no longer compiles workspace packages; building is reached through `nmr build` alone.

The removed `prepare` hooks ran concurrently with pnpm's own bin linking and intermittently invoked a `.bin` shim before it was executable, failing the install with `sh: 1: nmr: Permission denied`.
`pnpm run bootstrap` builds every package, giving a fresh clone or worktree one command to reach a usable state after `pnpm install`.

The root `postinstall` hook is gone. Its `pnpm.overrides` warning is moving into nmr's default check composites (williamthorsen/node-monorepo-tools#511), where it reaches every repo rather than this one.
Worktree creation, the CI job, and the documented clone sequence all reach a built tree through `pnpm run bootstrap`.

The build now runs in CI's own `Bootstrap` step rather than inside the check command, so a build break turns that step red instead of surfacing as a check failure.

Worktrunk gates changed hook commands behind approval, so the first worktree created after this lands prompts once for `pnpm run bootstrap`.
A bin invoked before the build now names a command that exists. `codeassembly-agents`, `codeassembly-mcp`, `codeassembly-runs`, and `kb` told the reader to run `pnpm run build`, which the repository root does not define, so following the advice failed.

`.agents/PROJECT.md` and the run-core README document `pnpm run bootstrap` as the step between install and a usable tree.
`codeassembly-mcp` starts again. It failed with `ERR_MODULE_NOT_FOUND` on `@modelcontextprotocol/sdk/server/stdio`, leaving the server unavailable to any client launching it.

The SDK maps unlisted subpaths through a `"./*"` export that appends no extension, so `server/stdio`, `server/mcp`, `client/stdio`, and `inMemory` need explicit `.js`. Vite resolves the extensionless form and Node does not, so the test suite exercised these imports without observing the failure.
The quick start's check step now runs on a fresh clone. It named the bare `nmr` binary, which resolves only after direnv is configured, so a reader running the three commands in order hit `command not found` on the third.
The bin-wrapper section now carries only what a new `bin` entry must honor and the pointer to the template. How the wrapper behaves when the build output is missing is documented on the wrapper itself, which every new bin copies.
@williamthorsen williamthorsen added the tooling Development tools label Jul 28, 2026
@github-actions

Copy link
Copy Markdown

Dependency audit

Production dependency audit passed.

@williamthorsen williamthorsen self-assigned this Jul 28, 2026
@williamthorsen
williamthorsen marked this pull request as ready for review July 28, 2026 19:34
@williamthorsen
williamthorsen merged commit 7c195d2 into main Jul 28, 2026
3 checks passed
@williamthorsen
williamthorsen deleted the 1095 branch July 28, 2026 19:38
williamthorsen added a commit that referenced this pull request Aug 4, 2026
…e-v0.2.2 codeassembly-v0.4.0 factory-v0.2.2 codeassembly-mcp-v0.2.2

codeassembly-v0.4.0
- #1153 feat: Make codeassembly and kb CLI tools publishable (#1164)
- #1091 fix: Anchor a project-deployed link where its target deploys (#1159)
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- refactor: Refine typescript-preferences
- #1150 fix: State doc-description form and make comment mood opt-in (#1151)
- deps: Upgrade first-party linting deps to latest version
- #1137 feat: Establish personal rulebooks for code layout and TypeScript preferences (#1144)
- #1126 feat: Check a package's own guidance content before it ships (#1138)
- refactor: Fix lint
- tooling: Remove redundant lint rules
- #1133 fix: Reject an anchor link that names no heading (#1135)
- #1122 feat: Capture lede decisions as an accumulating corpus (#1132)
- #1125 feat: Honor invocation tokens in rulebook bodies (#1129)
- #1107 feat: Render rulebook links and path tokens per harness (#1124)
- #1115 feat: Sync guidance at build and install so an upgrade cannot leave it stale (#1123)
- #1114 feat: Adopt a dependency's guidance by naming the package (#1121)
- #1088 feat: Deliver project ambient rulebooks per harness (#1113)
- #1087 refactor: Rename the authoring rulebook and mark its enforced rules (#1092)
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- #1094 refactor: Remove the ambient ripgrep dependency from the test suite (#1097)
- deps: Upgrade all deps to latest version
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint
- #1077 feat: Show the proposed edit above post-review menu options (#1078)
- #1068 feat: Deliver ambient rulebooks mechanically, retiring GLOBAL.md (#1075)
- #1069 feat: Add a no-second-person rule to the lede-voice doctrine (#1070)
- #1050 feat: Add a redundancy rule to the lede-voice doctrine (#1058)
- #1035 internal: Add lifecycle workspace with the canonical envelope, vocabulary & lane fold (#1049)
- #1006 internal: Extend lifecycle-event instrumentation to five high-traffic skills (#1034)
- #1028 feat: Rule out absence-of-removed-code tests (#1032)
- #114 feat: Let reviewers emit gated insights into review artifacts (#1031)
- #1027 internal: Retire input.received and redundant skill.progress emits (#1030)
- #1026 fix: Name the side effects an approval ask authorizes (#1029)
- #1022 fix: Normalize action and question label identifiers across asks blocks (#1025)

factory-v0.2.2
- #1156 refactor: Rename packages to publishable names (#1157)
- deps: Upgrade all deps to latest version
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- tooling: Remove redundant lint rules
- deps: Upgrade deps to latest version
- deps: Upgrade all deps to latest version
- deps: Upgrade all deps to latest version
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint
- deps: Upgrade all deps to latest version

kb-v0.3.0
- #1153 feat: Make codeassembly and kb CLI tools publishable (#1164)
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- tooling: Remove redundant lint rules
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint

codeassembly-lifecycle-v0.2.0
- #1153 feat: Make codeassembly and kb CLI tools publishable (#1164)
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- tooling: Remove redundant lint rules
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- #1038 feat: Add the read-only git adapter for worktree and base-branch ground truth (#1059)
- #1051 feat: Bound fold memory and rescan cost with a retention window (#1057)
- #1035 internal: Add lifecycle workspace with the canonical envelope, vocabulary & lane fold (#1049)

codeassembly-mcp-v0.2.2
- deps: Upgrade all deps to latest version
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint

codeassembly-run-core-v0.2.2
- #1156 refactor: Rename packages to publishable names (#1157)
- #1152 tooling: Run every test in the default gate, classified by what it reaches (#1155)
- #1110 tooling: Migrate Vitest to nmr's centralized model (#1154)
- #1095 tooling: Move compilation out of the install lifecycle into a bootstrap step (#1102)
- tooling: Upgrade all deps to latest version & modernize configs
- refactor: Fix lint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pnpm install fails intermittently when workspace prepare scripts race pnpm's bin linking

1 participant