π 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
- Clone
Gentleman-Programming/engram at main and check out unmodified.
- Start the local server:
engram serve (default port 7437).
- Run:
node --test plugin/opencode/engram.test.mts
- 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.
π Bug Description
plugin/opencode/engram.test.mtsno longer exercises the plugin it was written for. All five#1131tests fail against a pristine, unmodifiedmaincheckout β no local edits, no environment differences, no V2 involved. The suite has been effectively dead since 2026-09-17, when commit22454851cmoved 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
#1131guards the session-lifecycle path, and a real acknowledgement-validation defect reachedmainwhile the suite was already inert.π Steps to Reproduce
Gentleman-Programming/engramatmainand check out unmodified.engram serve(default port 7437).node --test plugin/opencode/engram.test.mts#1131tests failing on an emptyregisteredIDs.β Expected Behavior
All 8 tests in
engram.test.mtsshould pass, with the#1131session-lifecycle assertions exercised against a stubbed process layer.β Actual Behavior
The five
#1131tests fail. The threeshouldNudgeForObservationstests pass because they import a pure exported helper and never touch the process layer.The suite stubs the process layer like this:
but the plugin no longer reads
Bun.*. The stub never intercepts anything, solocalInstanceID()andisEngramRunning()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
Neither runner works as written:
π‘ 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.mtswas not updated in that commit and has not been touched since:from "node:child_process"Bun.spawn*a2199d92e22454851ceddd557d370b4a0cffI checked
mainandfix/opencode-v2-plugin-export: the.mtsis byte-identical (8,942 bytes) on both, so this is not addressed on any branch.The sibling suite needs the opposite runner.
engram.test.mjspatchesglobalThis.Bun,childProcess.spawnSyncandfs.existsSync. Under Bun it fails 46/50 withAttempted to assign to readonly propertyand must be run withnode --test. So the two suites in one directory have contradictory runtime requirements, and the.mtsone 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/sessionsregistration acknowledgement check: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 onmainfrom at least 2026-09-14 to 2026-09-28 β the entire window in which this suite was inert.Suggested fix. Update
engram.test.mtsto stub the layer the plugin actually uses, mirroring whatengram.test.mjsalready does β patchnode:child_processandnode:fsinstead ofglobalThis.Bun, restore them int.after(), and callsyncBuiltinESMExports(). AglobalThis.Bunstub 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.