Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/plugin/src/hooks/magic-context/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ export interface MagicContextDeps {
min_chars: number;
};
transform_mode?: ResolvedTransformMode;
/** Path to the subc daemon's connection file. Threaded to the module
* transport so a host that publishes it outside the default data-dir
* location (e.g. a systemd RuntimeDirectory) is actually reachable. */
subc?: { connection_file: string };
/** Compaction-off mode gate (issue #266). Resolved ONCE here at the
* session-hook construction boundary via isCompactionEnabled; the
* resolved boolean is threaded to the transform phases. */
Expand Down Expand Up @@ -774,7 +778,7 @@ export function createMagicContextHook(deps: MagicContextDeps) {
const authorityRecoveryModuleClient =
deps.rustModeModuleClient ??
(() => {
const transport = new SubcModuleTransport();
const transport = new SubcModuleTransport(deps.config.subc?.connection_file);
const client: RustModeModuleClient = {
call: (args) => transport.call(args),
stateSyncCapabilities: (args) => transport.stateSyncCapabilities(args),
Expand Down
4 changes: 3 additions & 1 deletion packages/plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ const server: Plugin = async (ctx) => {

const liveSessionState = createLiveSessionState();
const rustModeModuleClient: RustModeModuleClient | undefined =
pluginConfig.transform_mode === "rust" ? new SubcModuleTransport() : undefined;
pluginConfig.transform_mode === "rust"
? new SubcModuleTransport(pluginConfig.subc?.connection_file)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Wake-plane path remains inconsistent

With a non-default subc.connection_file, the changed transform transports reach the configured daemon while wakePlaneStatus still probes the default path, so the daemon's wake-plane ownership is not recognized and smart-note checks continue running locally.

Knowledge Base Used: OpenCode plugin runtime

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified from source — this is real, and it's a third site I missed. wake-plane.ts:27-29:

function connectionFile(): string {
    return join(getDataDir(), "cortexkit", "run", "subc-connection.json");
}

Same hardcoded default the transport had, and unlike the transport it takes no override parameter at all. So with a non-default subc.connection_file the probe hits a path that doesn't exist, probeWakePlaneCatalog fails, and wakePlaneStatus() returns unknown → fail-open → standalone smart-note evaluation keeps running even when the fleet's wake plane owns it. Exactly as described.

I have not folded it into this PR, and the reason is a design call that belongs to you rather than scope-avoidance: wakePlaneStatus() takes no arguments and has three callers — tools/ctx-note/tools.ts:295, smart-notes/runner.ts:54, dreamer/evaluate-smart-notes.ts:100 — none of which carry plugin config today. Options:

  1. Module-level injection — an exported setter called once at plugin init where pluginConfig is in scope, mirroring the existing swappable catalogProbe/now seams in __wakePlaneTest. ~6 lines, fits the module's shape, adds mutable module state.
  2. Thread config to all three callers — no new module state, wider diff, touches one tool and two dreamer paths.
  3. Shared resolver — one resolveSubcConnectionFile(config) consumed by both the transport and the wake plane.

I'd lean (3) as the durable fix: the root problem is that the default path is spelled out in two places and the config value has no single resolution point, which is exactly how this recurs a fourth time. But that's a wider blast radius than a fix PR should decide on its own.

Happy to do any of them — say which and I'll push it here, or open a separate PR if you'd rather keep this one narrow.

Severity note for triage: this one is fail-open (smart notes keep evaluating locally — duplicated work, not lost work), whereas the transform-lane bug this PR fixes was effectively fail-shut: zero materializations, empty sidebar. Same defect class, different urgency.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for verifying the third site. I agree this is real, but it should be a separate PR to keep this fix focused. For that PR, use option 3: introduce a shared resolveSubcConnectionFile(config) (or equivalent) and make both the transport and wake-plane paths consume it. Thread the resolved value through the three wake-plane callers rather than adding module-level mutable state. This removes the duplicated default-path logic while keeping the current transform fix narrowly scoped.

: undefined;

const hooks = await createSessionHooksAsync({
ctx,
Expand Down