Skip to content

bug(test): engram.test.mts (#1131 suite) is inert since #1228 β€” it stubs globalThis.Bun while the plugin uses node:child_processΒ #1541

Description

@Lostovayne

πŸ“ Bug Description

plugin/opencode/engram.test.mts no longer exercises the plugin it was written for. All five #1131 tests fail against a pristine, unmodified main checkout β€” no local edits, no environment differences, no V2 involved. The suite has been effectively dead since 2026-09-17, when commit 22454851c moved the plugin off the Bun API without updating the test's stubbing mechanism.

This is a coverage gap rather than a plugin defect. It matters because #1131 guards the session-lifecycle path, and a real acknowledgement-validation defect reached main while the suite was already inert.

πŸ”„ Steps to Reproduce

  1. Clone Gentleman-Programming/engram at main and check out unmodified.
  2. Start the local server: engram serve (default port 7437).
  3. Run: node --test plugin/opencode/engram.test.mts
  4. Observe 3 passing and 5 failing, with the five #1131 tests failing on an empty registeredIDs.

βœ… Expected Behavior

All 8 tests in engram.test.mts should pass, with the #1131 session-lifecycle assertions exercised against a stubbed process layer.

❌ Actual Behavior

The five #1131 tests fail. The three shouldNudgeForObservations tests pass because they import a pure exported helper and never touch the process layer.

The suite stubs the process layer like this:

const bun = globalThis as any
bun.Bun = {
  spawnSync(args: string[]) { ... },
  spawn() {},
  file() { ... },
}

but the plugin no longer reads Bun.*. The stub never intercepts anything, so localInstanceID() and isEngramRunning() run against the real environment, readiness resolution fails, and no session is ever registered. The assertions then fail on an empty array.

Operating System

Windows

Engram Version

2.2.1

Agent / Client

OpenCode

πŸ“‹ Relevant Logs

$ node --test plugin/opencode/engram.test.mts
βœ” allows the first-save nudge only after the 15-minute session threshold (1.1ms)
βœ” fails closed for observations without a valid created_at (0.4ms)
βœ” preserves UTC parsing and the 15-minute observation age threshold (1.3ms)
βœ– #1131 ends a root registration in Engram when a later event reveals a parentID
βœ– #1131 retries a failed child deletion during disposal
βœ– #1131 disposal ends every known session including misregistered children
βœ– #1131 keeps deleted-root semantics: exactly one end across deletion and disposal
βœ– #1131 never ends sessions that were never registered
β„Ή pass 3
β„Ή fail 5

  AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal:
    + actual - expected
      actual: []
      expected: [ 'sess-root' ]

Neither runner works as written:

$ bun test plugin/opencode/engram.test.mts
TypeError: Attempted to assign to readonly property.
    at createRuntime (plugin/opencode/engram.test.mts:77:3)
  3 pass
  5 fail

$ node --test plugin/opencode/engram.test.mts
ReferenceError: bun is not defined

πŸ’‘ Additional Context

The break. 22454851c β€” fix(opencode): support Node runtime without Bun (#1228) (issue #1218, PR #1227) β€” replaced the plugin's process layer. engram.test.mts was not updated in that commit and has not been touched since:

Commit Date from "node:child_process" Bun.spawn*
a2199d92e 2026-09-14 0 4
22454851c 2026-09-17 1 0
eddd557d3 2026-09-24 1 0
70b4a0cff 2026-09-28 1 0

I checked main and fix/opencode-v2-plugin-export: the .mts is byte-identical (8,942 bytes) on both, so this is not addressed on any branch.

The sibling suite needs the opposite runner. engram.test.mjs patches globalThis.Bun, childProcess.spawnSync and fs.existsSync. Under Bun it fails 46/50 with Attempted to assign to readonly property and must be run with node --test. So the two suites in one directory have contradictory runtime requirements, and the .mts one needs neither as written.

Corroborating evidence that the gap had real consequences. Commit 70b4a0cff β€” fix(opencode): confirm registered host identity before binding writes (#1479), 2026-09-28 β€” tightened the /sessions registration acknowledgement check:

// before
if (acknowledgement === null) return false
// after
if (acknowledgement?.id !== sessionId || acknowledgement?.status !== "created") return false

Until that commit, the plugin accepted any non-null response as a successful registration, including { status: "rejected" } or a response carrying a different session id. That behaviour was live on main from at least 2026-09-14 to 2026-09-28 β€” the entire window in which this suite was inert.

Suggested fix. Update engram.test.mts to stub the layer the plugin actually uses, mirroring what engram.test.mjs already does β€” patch node:child_process and node:fs instead of globalThis.Bun, restore them in t.after(), and call syncBuiltinESMExports(). A globalThis.Bun stub is a no-op for a plugin that never reads it.

It may also be worth adding a CI guard so this class of drift fails loudly: assert that the target a test stubs is actually referenced by the module under test.

Scope. OpenCode V2 support is tracked separately and is not what this report is about: #1526, #1240, #1220. This concerns only behaviour that was already broken on the V1 plugin path.

Verification environment: Windows 11, Bun 1.4.2, Node v26.5.0, Go 1.27.1.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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