mirror of
https://github.com/thedotmack/claude-mem.git
synced 2026-09-20 04:23:02 +08:00
fix: rebuild plugin bundles to match manifest 13.24.0 (#3857)
* fix: rebuild plugin bundles so committed artifacts match manifest 13.24.0 The 13.24.0 release commit (85ccd626) bumped the manifests and CHANGELOG but never re-ran the build, so plugin/scripts/*.cjs kept the 13.23.1 bytes last produced by89ca057a. The Claude Code marketplace installs straight from this repo (.claude-plugin/marketplace.json -> "source": "./plugin"), so every marketplace user on 13.24.0 has been executing 13.23.1 code. ensureWorkerRunning() compares the resolved plugin version (13.24.0, taken from the plugin cache directory name) against the worker's baked-in __DEFAULT_PACKAGE_VERSION__ (13.23.1, reported by /api/health). The mismatch SIGKILLs the worker and respawns the same stale file on every hook event, with no state that survives the hook process to bound it -- an unbounded kill/respawn loop that takes the in-flight observer generator down with it, so no observations get written. This is a genuine `npm run build`, not a version-string patch. The bundles were stale in code, not merely in the constant: src/ moved 704 insertions across 12 files since 13.23.1, including the observer's <skip_summary reason="noise" /> protocol change, the new manual-session module, and the platform_source plumbing in SessionStore and MemoryRoutes. No version bump: the manifests were already correct at 13.24.0. It is the artifacts that were wrong. Fixes #3857 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Bshprs1vjut2XmaGTRESqX * fix(tests): restore module mocks so worker-spawner stubs stop leaking bun runs the whole suite in one process and mock.module is process-global and sticky, so stubs installed by one test file stay installed for every file loaded after it. tests/services/worker-spawner.test.ts mocked src/services/infrastructure/{ProcessManager,HealthMonitor}.js and never restored them. tests/infrastructure/{health-monitor,process-manager}.test.ts import the same symbols through the src/services/infrastructure/index.js barrel, so they silently exercised those stubs instead of the real code: isPortInUse returned false without touching net.createServer, waitForHealth returned false without fetching, getPlatformTimeout skipped the Windows doubling, cleanStalePidFile always reported 'dead', and spawnDaemon never returned undefined. waitForPortFree stayed real but resolved through the stubbed isPortInUse binding, inverting its timeout case. This is order-dependent, not new: bun walks test files in filesystem order, and a fresh CI checkout loads worker-spawner (59) well before health-monitor (169) and process-manager (172), while many local checkouts load tests/infrastructure first and pass. That ordering is what surfaced 19 failures in Actions run 33939805959. Snapshot the real namespaces eagerly, before the mock.module calls, and reinstall them in afterAll. The snapshot must be eager: `import * as x` yields a live namespace object that bun re-points when the module is mocked, so spreading it inside afterAll copies the stubs back in. That is exactly the latent bug in tests/cli/handlers/context-session-start.test.ts, whose restore was re-installing its own hook-settings, oauth-token, project-name and worker-utils stubs; fixed here the same way. Tests only. No source, plugin bundle, or version changes — the committed artifacts still match manifest 13.24.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LcjsK6QqeBcYXbJ8gqBsea --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
+127
-127
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+375
-372
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,6 +5,17 @@ import * as realOauthToken from '../../../src/shared/oauth-token.js';
|
||||
import * as realProjectName from '../../../src/utils/project-name.js';
|
||||
import * as realWorkerUtils from '../../../src/shared/worker-utils.js';
|
||||
|
||||
/**
|
||||
* Snapshot the real namespaces EAGERLY, before the mock.module calls below.
|
||||
* `import * as x` yields a live namespace object that bun re-points when the
|
||||
* module is mocked, so spreading it later (inside afterAll) would copy the
|
||||
* stubs back in and leak them into every test file that runs after this one.
|
||||
*/
|
||||
const realHookSettingsSnapshot = { ...realHookSettings };
|
||||
const realOauthTokenSnapshot = { ...realOauthToken };
|
||||
const realProjectNameSnapshot = { ...realProjectName };
|
||||
const realWorkerUtilsSnapshot = { ...realWorkerUtils };
|
||||
|
||||
const calls: unknown[][] = [];
|
||||
|
||||
mock.module('../../../src/shared/hook-settings.js', () => ({
|
||||
@@ -32,10 +43,10 @@ mock.module('../../../src/shared/worker-utils.js', () => ({
|
||||
}));
|
||||
|
||||
afterAll(() => {
|
||||
mock.module('../../../src/shared/hook-settings.js', () => ({ ...realHookSettings }));
|
||||
mock.module('../../../src/shared/oauth-token.js', () => ({ ...realOauthToken }));
|
||||
mock.module('../../../src/utils/project-name.js', () => ({ ...realProjectName }));
|
||||
mock.module('../../../src/shared/worker-utils.js', () => ({ ...realWorkerUtils }));
|
||||
mock.module('../../../src/shared/hook-settings.js', () => realHookSettingsSnapshot);
|
||||
mock.module('../../../src/shared/oauth-token.js', () => realOauthTokenSnapshot);
|
||||
mock.module('../../../src/utils/project-name.js', () => realProjectNameSnapshot);
|
||||
mock.module('../../../src/shared/worker-utils.js', () => realWorkerUtilsSnapshot);
|
||||
});
|
||||
|
||||
describe('contextHandler SessionStart path', () => {
|
||||
|
||||
@@ -1,6 +1,22 @@
|
||||
|
||||
import { describe, it, expect, mock } from 'bun:test';
|
||||
import { describe, it, expect, mock, afterAll } from 'bun:test';
|
||||
import { HOOK_TIMEOUTS } from '../../src/shared/hook-constants.js';
|
||||
import * as realProcessManager from '../../src/services/infrastructure/ProcessManager.js';
|
||||
import * as realHealthMonitor from '../../src/services/infrastructure/HealthMonitor.js';
|
||||
import * as realWorkerSpawnGate from '../../src/shared/worker-spawn-gate.js';
|
||||
|
||||
/**
|
||||
* The whole suite runs in one bun process and `mock.module` mutates the shared
|
||||
* module registry, so the stubs below leak into every test file that loads
|
||||
* after this one (tests/infrastructure/{health-monitor,process-manager}.test.ts
|
||||
* import the same modules via src/services/infrastructure/index.js and would
|
||||
* silently exercise these fakes). Snapshot the real namespaces before the mocks
|
||||
* are installed and put them back in afterAll — same pattern as
|
||||
* tests/shared/worker-utils-version-recycle.test.ts.
|
||||
*/
|
||||
const realProcessManagerSnapshot = { ...realProcessManager };
|
||||
const realHealthMonitorSnapshot = { ...realHealthMonitor };
|
||||
const realWorkerSpawnGateSnapshot = { ...realWorkerSpawnGate };
|
||||
|
||||
const processManager = {
|
||||
cleanStalePidFile: mock(() => 'dead' as 'alive' | 'dead'),
|
||||
@@ -24,6 +40,12 @@ mock.module('../../src/services/infrastructure/ProcessManager.js', () => process
|
||||
mock.module('../../src/services/infrastructure/HealthMonitor.js', () => healthMonitor);
|
||||
mock.module('../../src/shared/worker-spawn-gate.js', () => spawnGate);
|
||||
|
||||
afterAll(() => {
|
||||
mock.module('../../src/services/infrastructure/ProcessManager.js', () => realProcessManagerSnapshot);
|
||||
mock.module('../../src/services/infrastructure/HealthMonitor.js', () => realHealthMonitorSnapshot);
|
||||
mock.module('../../src/shared/worker-spawn-gate.js', () => realWorkerSpawnGateSnapshot);
|
||||
});
|
||||
|
||||
const { ensureWorkerStarted } = await import('../../src/services/worker-spawner.js');
|
||||
|
||||
type TimedProbe = (port: number, timeout: number) => Promise<boolean>;
|
||||
|
||||
Reference in New Issue
Block a user