Skip to content

The typecheck skips the two packages that run a Bot's computer, and six lockfiles are never enforced #112

Description

@Hotragn

ci.yml's static job is format:check, lint, typecheck. Two packages ship a typecheck script
that the third of those never reaches, and one of them is the process a Bot's input reaches a child
process in.

The comment above the image job (ci.yml:123-125) is the same thought pointed at a different gap:

The image is the artefact people deploy, and almost nothing about whether it works is visible to
the checks above. A dangling symlink, a supervised service that exits, a missing binary: all of
them typecheck, lint and test perfectly.

This is the version of that inside the repository rather than inside the image. Two things, both
measured, both with a fix that costs nothing today.

1. agent-computer and supervisor ship a typecheck script CI never runs

Root package.json defines the only entry point:

"typecheck": "bun run --filter '*' typecheck"

--filter '*' enumerates workspaces, and workspaces is ["app", "server", "worker"]. ci.yml:37
runs bun run typecheck, and nothing else in the file typechecks anything.

Package typecheck script In workspaces Runs in CI
app yes yes yes
server yes yes yes
worker yes yes yes
agent-computer yes — agent-computer/package.json:9 no no
supervisor yes — supervisor/package.json:9 no no

Confirmed by running bun run typecheck: it names app, server and worker and no other package.

Both pass today. Measured, in each directory after its own bun install:

agent-computer $ bunx tsc --noEmit     # clean, no output
supervisor     $ bunx tsc --noEmit     # clean, no output

So there is no backlog to clear. The scripts are correct, somebody wrote them deliberately, and
wiring them in changes nothing about main — which is also why nobody noticed they were idle.

It matters because neither package is small or peripheral any more. agent-computer is at 158 tests
across 8 files, it holds the only spawn in the deployment, and #68 changed shell.ts without a type
check ever seeing it. supervisor is the only thing holding a Docker socket
(supervisor/Dockerfile:1).

agent-bot, agent-langgraph and the two examples/ packages have no typecheck script at all, so
they are a separate question and I have left them alone.

2. Six of the seven committed lockfiles are never enforced

Lockfile Installed by --frozen-lockfile
bun.lock ci.yml:34, :68, :87, :106, Dockerfile:46, :59 yes
agent-computer/bun.lock Dockerfile:49, agent-computer/Dockerfile:15 no
supervisor/bun.lock supervisor/Dockerfile:14 no
agent-bot/bun.lock agent-bot/Dockerfile:9 no
agent-langgraph/bun.lock agent-langgraph/Dockerfile:9 no
examples/langgraph-bot/bun.lock no
examples/mastra-bot/bun.lock no

Dockerfile:49 is RUN cd agent-computer && bun install. Plain bun install resolves afresh and may
write a tree the committed lockfile does not describe.

The file makes this argument itself, twenty-three lines above that line, about Bun's own version
(Dockerfile:24-25):

Bun is pinned. The installer takes whatever is newest otherwise, so the runtime drifts from the
one the lockfile was resolved against and an image built next month is not the image built today.

Applied to the toolchain, and not to the install below it. A committed lockfile that nothing passes
--frozen-lockfile to is not pinning anything; it is a file that looks like it is.

The flag works today, so this is one word per site rather than a lockfile refresh:

agent-computer $ bun install --frozen-lockfile   # 63 packages installed
supervisor     $ bun install --frozen-lockfile   # 73 packages installed

There is a release-shaped consequence too, since #64 is recent. That change signs a build provenance
attestation for the image digest. Provenance over a dependency tree resolved at build time rather
than pinned attests to less than it appears to: the digest is exact, and part of what went into it
was not decided by anything in this repository.

What I propose

  1. Typecheck agent-computer and supervisor. Not by adding them to workspaces — they are
    separate deployables with their own lockfiles, Dockerfile:48-49 depends on that, and
    tests/workspace.test.ts:21 pins the current shape on purpose. A job that installs each and runs
    its own script reports separately, which is how ci.yml is already organised, and keeps root
    typecheck fast for local work. It also folds into the existing verify gate without anybody
    updating a list, which is what Cut releases from a reviewed PR, and make CI run the thing it ships #64 built that gate for.
  2. --frozen-lockfile wherever a committed lockfile is installed.

One PR, because it is the same sentence about the same two packages. Lint exiting successfully on its
own warnings is the third face of this and is filed separately as #75, since fixing that changes what
fails for other contributors and this does not.

Happy to be told a different shape — particularly on whether the second install belongs in CI at all,
versus only tightening the Dockerfiles. A branch is coming either way; I am not filing this and
leaving it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions