Skip to content

#1264 Consolidate error-message extraction on toolbelt.errors' describeError - #1284

Merged
williamthorsen merged 9 commits into
mainfrom
1264
Aug 11, 2026
Merged

#1264 Consolidate error-message extraction on toolbelt.errors' describeError#1284
williamthorsen merged 9 commits into
mainfrom
1264

Conversation

@williamthorsen

@williamthorsen williamthorsen commented Aug 11, 2026

Copy link
Copy Markdown
Owner

What

Consolidates error-message extraction across the workspace on @williamthorsen/toolbelt.errors, replacing the local copies each package had defined under its own name. The repository's exact-version dependency rule now accepts shared pins (via catalog:) as an alternative and enforces sharing over duplication. The packages that stated no Node requirement now declare the workspace's Node 24 minimum.

Why

The expression error instanceof Error ? error.message : String(error) had been rewritten nine times across four packages, five of those as module-private helpers under three different names. A reader had to learn three names for one behavior, and each copy was free to drift from the others. The behavior also has edge cases worth getting right once — an Error carrying an empty message, and a value String() cannot render — which no local copy handled.

Details

🐛 Bug fixes

  • mcp and run-core were the only packages in the workspace declaring no engines floor, while every sibling and the root manifest declare Node 24. Both now declare it. run-core is bound for publication and its dependencies require Node 24, so a consumer on an older runtime previously had nothing to warn them at install time.

♻️ Refactoring

  • describeError replaces all nine occurrences of the ternary in factory, fleet, mcp, and run-core, called directly at each site with no local alias or wrapper. The five helper definitions it displaces are deleted: errorMessage (run-core, twice), getErrorMessage (factory), and readMessage (fleet, twice).
  • Two sites are supersets of the pattern and keep their extra branches, delegating only their terminal fallback: fleet's readErrorText, which prefers accumulated stderr, and run-core's pick-demo-runs.ts, which prefers a parse error's category.
  • Three factory sites that test instanceof Error but fall back to a domain string or to an Error object are a different construct and are unchanged. Routing them through describeError would degrade user-visible messages.
  • The three bin launcher scripts keep their inline copy. A top-level import resolves before their build-first gate runs, so importing the helper would replace their diagnostic with ERR_MODULE_NOT_FOUND whenever the install is incomplete.

📦 Dependencies

  • @williamthorsen/toolbelt.errors reaches six consumers — agents, factory, fleet, kb, mcp, and run-core — more than any other external dependency here, so it becomes the workspace's first catalog: entry. It is pinned once at 0.2.0 in pnpm-workspace.yaml and every consumer declares catalog:; agents and kb move off the literal pins they already carried. The other sixteen shared dependencies stay literal.

📚 Documentation

  • AGENTS.md's exact-version rule now records the catalog as the sanctioned alternative to a literal pin, and instructs that a package taking on a cataloged dependency declares catalog: rather than re-pinning the literal.
  • kb's bin launcher gains the comment its two siblings already carry, stating that the file's imports must stay builtins-only and what breaks otherwise.

Closes #1264

factory, fleet, mcp, and run-core now depend on `@williamthorsen/toolbelt.errors`, joining agents and kb.

The version is pinned once in `pnpm-workspace.yaml`'s catalog, and all six consumers reference it as `catalog:`.
Error text now comes from the shared `@williamthorsen/toolbelt.errors` helper, which falls back safely for an `Error` carrying an empty message and for a value that cannot be stringified.
Error text now comes from the shared `@williamthorsen/toolbelt.errors` helper, which falls back safely for an `Error` carrying an empty message and for a value that cannot be stringified.
Error text now comes from the shared `@williamthorsen/toolbelt.errors` helper, which falls back safely for an `Error` carrying an empty message and for a value that cannot be stringified.

The launcher script keeps its own copy, since a top-level import of the helper would replace its build-first message with a module-resolution error whenever the install is incomplete.
Error text now comes from the shared `@williamthorsen/toolbelt.errors` helper, which falls back safely for an `Error` carrying an empty message and for a value that cannot be stringified.
The launcher script's node-builtins-only import list now carries the reason it stays that way: a top-level import of a dependency would replace the build-first message with a module-resolution error whenever the install is incomplete.
The dependency-version guidance now covers the `catalog:` specifier: a shared dependency may be pinned once in `pnpm-workspace.yaml`, and a package taking one on declares `catalog:` rather than a literal version.
`codeassembly-mcp` and `codeassembly-run-core` declare `engines.node` as `>=24`, matching every other package in the workspace. run-core takes that floor on transitively through `@williamthorsen/toolbelt.errors`, so an install on an older Node warns at install time rather than failing at runtime.
The catalog guidance carries the mechanism alone, so it stays accurate however many dependencies adopt it.
@williamthorsen williamthorsen added the refactoring Improvement to code without change in functionality label Aug 11, 2026
@github-actions

Copy link
Copy Markdown

Dependency audit

Production dependency audit passed.

@williamthorsen williamthorsen self-assigned this Aug 11, 2026
@williamthorsen
williamthorsen marked this pull request as ready for review August 11, 2026 04:16
@williamthorsen
williamthorsen merged commit 89280bf into main Aug 11, 2026
3 checks passed
@williamthorsen
williamthorsen deleted the 1264 branch August 11, 2026 04:17
williamthorsen added a commit that referenced this pull request Aug 13, 2026
…e-v0.3.0 codeassembly-v0.9.0 factory-v0.2.6 codeassembly-mcp-v0.2.5

codeassembly-v0.9.0
- #1288 feat: State mutability and name the lede reader at the artifact type lists (#1303)
- #1285 fix: Require plain bullets for checklists on both update-jira-ticket paths (#1302)
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1294 feat: Specify artifact mutability and its sanctioned exceptions (#1297)
- #1293 fix: Present and classify discretionary findings as actionable (#1295)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1280 feat: Add a refresh path that edits an existing AGENTS.md instead of redrafting it (#1287)
- #1055 feat: Replace the lede doctrine with corpus-derived guidance and retire the changelog-writer (#1286)
- deps: Upgrade all deps to latest version
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)
- #1263 refactor: Retire the deferred-lint mechanism and adopt toolbelt.errors in agents (#1279)
- #1262 refactor: Hoist unreadable for-of expressions and promote the lint rule to an error (#1276)
- #1267 fix: Extend the no-hard-wrapping instruction to every GitHub composer (#1275)
- #1177 fix: Rewrite links, tokens, and template variables in a Markdown file support entry (#1273)
- #1176 feat: Add a ticketing-preferences hook to the skills that split and create tickets (#1268)
- #1252 fix: Keep a skill's own sections out of injected guidance (#1266)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)
- #1247 feat: Add a personal tooling-preferences rulebook (#1257)
- #1251 feat: Let a rulebook declare that a guidance hook is how it is reached (#1259)
- #1246 feat: Guard home-domain writes and record their provenance (#1254)
- #1175 feat: Link new tickets to their blockers and parents (#1249)

factory-v0.2.6
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- deps: Upgrade all deps to latest version
- deps: Upgrade all deps to latest version
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)

kb-v0.6.0
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)
- #1261 feat: Attach causes to kb's loader errors and retire its lint deferral (#1272)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)

codeassembly-lifecycle-v0.4.0
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1261 feat: Attach causes to kb's loader errors and retire its lint deferral (#1272)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)

codeassembly-mcp-v0.2.5
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)

codeassembly-run-core-v0.3.0
- deps: Upgrade all deps to latest version
- #1290 tooling: Upgrade eslint-config-typescript to 10 and complete manifest metadata (#1301)
- #1289 tooling: Remove shelled nmr calls from package manifests (#1291)
- #1264 refactor: Consolidate error-message extraction on toolbelt.errors' describeError (#1284)
- #1261 feat: Attach causes to kb's loader errors and retire its lint deferral (#1272)
- #1260 refactor: Fix lint and retire rule deferrals (#1265)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactoring Improvement to code without change in functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adopt toolbelt.errors' describeError in factory, fleet, mcp, and run-core

1 participant