# ADR 0016: JavaScript Tool Verification

## Status

Accepted

## Date

2026-06-10

## Context

The repository contains `tools/trapos-server`, a TypeScript Node.js tool that sits next to the ComputerCraft Lua code. It has a different build and test lifecycle than TrapOS packages, but it still participates in the same local developer workflow and Git hooks described by [ADR-0011](adr-0011-repo-conventions.md). (This convention was first established for `tools/mcp-bridge`, which has since been removed; `trapos-server` is now the JS tool it governs.)

The tool also needs end-to-end coverage that spans both runtimes: a host Node process and a headless CraftOS-PC computer. That is broader and slower than normal unit tests, and it needs the same kind of timeout discipline as the Lua harness in [ADR-0007](adr-0007-test-framework.md).

## Decision

Keep the Node package scripts simple and one-purpose:

- `npm run build` emits TypeScript into `dist/` and acts as the type-check gate.
- `npm run test` runs the Node unit tests directly from TypeScript with `tsx --test test/*.test.ts`. No prior build is required.
- `npm run check` runs ESLint. TypeScript compilation is covered by `npm run build` and `npm run test:ci` to avoid duplicate compiler runs in repository CI.
- `npm run test:ci` runs `npm run check && npm run build && npm run test`, so type errors and lint failures both surface even though `test` itself no longer compiles.
- `npm run test:integration` runs the host-to-CraftOS integration suite with `tsx --test --test-concurrency=1 test-integration/*.test.ts`. Each case boots the gateway in-process on an ephemeral loopback port, spawns a CraftOS-PC headless computer that connects back over the gateway WebSocket, drives MCP tool calls through the Fastify app (`inject`, no separate listener), and tears everything down.
- These integration-test ports are loopback-only and unrelated to the public production ports documented in [`../public-ports.md`](../public-ports.md).

Expose matching repository recipes for the Node lifecycle:

- `just build` delegates to `npm run build` for the trapos-server tool.
- `just test` depends on `just build`, runs `npm run test`, then runs the existing CraftOS-PC test suite.
- `just check` includes `npm run check` alongside Lua and Markdown checks.
- `just ci` uses `npm run test:ci`, then runs CraftOS-PC tests and the broader integration/harness target.
- `just test-integration` runs the placeholder Node integration target and the Lua timeout harness checks.

## Consequences

- `npm run test` no longer needs `dist/`. Both unit and integration tests load TypeScript directly through `tsx`, so test iteration is faster and `dist/` is only required for `npm start`.
- TypeScript errors are no longer caught by `npm run test`; they are caught by `npm run build`, which stays wired into `npm run test:ci`, `just build`, `just test`, and `just ci`.
- `just ci` avoids duplicating Node unit tests by calling `npm run test:ci` directly and then invoking only the CraftOS-side test body.
- ESLint failures are part of `just check`, so they are covered by the same pre-commit and pre-push hooks as Lua and Markdown checks.
- Integration tests live in `tools/trapos-server/test-integration/`, with Lua client fixtures under `test-integration/lua/`. Slow end-to-end behavior stays out of the fast unit-test path.

## Future Work

- Extend the integration harness with disconnect and reconnect scenarios (computer drops mid-probe; bridge restarts while a computer is connected) once those failure modes need regression coverage.
