Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/publish-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ jobs:
crates/bashkit-js/scripted.d.ts
crates/bashkit-js/internal.js
crates/bashkit-js/internal.d.ts
crates/bashkit-js/runtime-functions.js
crates/bashkit-js/runtime-functions.d.ts
crates/bashkit-js/langchain.js
crates/bashkit-js/langchain.d.ts
crates/bashkit-js/anthropic.js
Expand Down
1 change: 1 addition & 0 deletions crates/bashkit-js/tsconfig.check.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"wrapper.ts",
"scripted.ts",
"internal.ts",
"runtime-functions.ts",
"langchain.ts",
"anthropic.ts",
"openai.ts",
Expand Down
1 change: 1 addition & 0 deletions crates/bashkit-js/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"wrapper.ts",
"scripted.ts",
"internal.ts",
"runtime-functions.ts",
"langchain.ts",
"anthropic.ts",
"openai.ts",
Expand Down
4 changes: 4 additions & 0 deletions knowledge/log.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Bashkit Knowledge Update Log

## 2026-10-25

* **npm publish gap**: `tsconfig.json`'s `include` must name every `.ts` source in the native package, including one reached only through an import. tsc compiles a reachable import regardless, so omitting `runtime-functions.ts` broke no build but narrowed what `scripts/tests/test_js_publish_files.py` treats as a tsc output, disabling that guard for the one file it omitted. The `js-stubs` artifact then shipped without `runtime-functions.js` and all fifteen v0.20.0 `Publish JS` test jobs failed on `ERR_MODULE_NOT_FOUND`, leaving both npm packages on 0.19.0 while crates.io and PyPI published. `include` completeness is now guarded; see [Release Process](operations/release-process.md).

## 2026-10-24

* **0.20.0 release preparation**: Synchronize workspace, native/browser package versions, internal release dependencies and standalone lockfiles; refresh self-hosted Python/TypeScript API references. The minor release documents the Rust analysis enum migration from `CommandContext` to `CommandPlacement`, live command I/O, runtime callbacks, and the security fixes since 0.19.0. Keep the opt-in SSH RSA Marvin and unmaintained atomic-polyfill caveats explicit. Exact multi-crate packaging validation and registry/platform verification follow the [Release Process](operations/release-process.md).
Expand Down
11 changes: 11 additions & 0 deletions knowledge/operations/release-process.md
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,17 @@ carries. That artifact must list every `tsc` output (`.js` + `.d.ts` for each
without `langchain.js`/`ai.js`/`anthropic.js`/`openai.js` while `package.json`
exported them. Guarded by `scripts/tests/test_js_publish_files.py`.

`tsconfig.json`'s `include` must name every `.ts` source in the package, even
one reached only through an import. tsc compiles a reachable import whether or
not it is listed, so an omission breaks no build: it narrows what the guard
above treats as a `tsc` output, disabling the guard for exactly the file it
left out. `runtime-functions.ts` landed that way in #2740, so v0.20.0 reached
the registry on crates.io and PyPI while all fifteen `Publish JS` test jobs
died on `ERR_MODULE_NOT_FOUND` for `runtime-functions.js`, leaving both npm
packages on 0.19.0. `include` completeness is now itself guarded by that same
test file -- treat `include`, the `js-stubs` list and `package.json` `files` as
one invariant, since each is a hand-maintained copy of the same set.

### publish-wasm.yml

Dispatched by `release.yml` from the verified release tag. Builds the
Expand Down
30 changes: 30 additions & 0 deletions scripts/tests/test_js_publish_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@
artifact, so `@everruns/bashkit@0.18.2` shipped without langchain.js, ai.js,
anthropic.js and openai.js even though package.json exports them. The publish
job never runs tsc itself; whatever the artifact omits is missing on npm.

Second regression, v0.20.0: `runtime-functions.ts` arrived in #2740 without
being added to tsconfig's `include`. tsc still emitted it, because `wrapper.ts`
imports it and TypeScript compiles a reachable import either way, so every
local build and `js.yml` stayed green. But the omission also made the file
invisible to the two checks above, which read their notion of "tsc output"
straight out of `include` -- so the guard written for the 0.18.2 failure could
not see the next instance of it. All fifteen `Publish JS` test jobs then died
on `ERR_MODULE_NOT_FOUND` for runtime-functions.js and npm stalled at 0.19.0.

`include` is therefore checked against the sources on disk, so no entry point
can be absent from it and silently narrow the two checks that depend on it.
"""

from __future__ import annotations
Expand All @@ -25,6 +37,24 @@ def stub_paths() -> set[str]:


class JsPublishFilesTests(unittest.TestCase):
def test_tsconfig_includes_every_ts_source(self) -> None:
"""`include` is the root both checks below trust; it must be complete.

A source missing here is not a build failure -- tsc follows imports --
so nothing else reveals it. It just quietly shrinks `tsc_outputs`.
`tsconfig.check.json` overrides `include` rather than extending it, so
it needs the same entries to type-check each source in its own right.
"""
sources = {p.name for p in JS.glob("*.ts") if not p.name.endswith(".d.ts")}
for config in ("tsconfig.json", "tsconfig.check.json"):
included = set(json.loads((JS / config).read_text())["include"])
for source in sorted(sources):
self.assertIn(
source,
included,
f"{source} is a package source but is not in {config} include",
)

def test_every_ts_entry_output_is_uploaded(self) -> None:
tsconfig = json.loads((JS / "tsconfig.json").read_text())
uploaded = stub_paths()
Expand Down
Loading