Skip to content

rust mode: subc.connection_file gates activation but is never passed to the transform transport #375

Description

@iceteaSA

Summary

subc.connection_file is parsed and schema-validated, and it decides whether transform_mode: "rust" may activate — but its value is never threaded to the transform-lane transport. SubcModuleTransport always falls back to its hardcoded default, so on any host where the daemon publishes its connection file somewhere other than <data-dir>/cortexkit/run/, rust mode cannot connect and the setting that would fix it is inert.

The code path

SubcModuleTransport accepts the path (packages/plugin/src/hooks/magic-context/module-transport.ts:248-258):

constructor(
    connectionFile?: string,
    moduleId = DEFAULT_MODULE_ID,
    ...
) {
    this.connectionFile = connectionFile ?? getDefaultConnectionFile();

Both transform-lane construction sites pass nothing:

packages/plugin/src/index.ts:208
    pluginConfig.transform_mode === "rust" ? new SubcModuleTransport() : undefined;

packages/plugin/src/hooks/magic-context/hook.ts:796
    const transport = new SubcModuleTransport();

So the default always wins (module-transport.ts:55-57):

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

Meanwhile the configured value is read exactly once, and only as a boolean gate (packages/plugin/src/config/index.ts:470-476):

function hasUserTierSubcConfig(config: Record<string, unknown> | undefined): boolean {
    const subc = config?.subc;
    if (typeof subc !== "object" || subc === null || Array.isArray(subc)) return false;
    const connectionFile = (subc as Record<string, unknown>).connection_file;
    return typeof connectionFile === "string" && connectionFile.trim().length > 0;
}

resolveTransformMode then requires userTierHasSubc to be true before returning "rust" (config/transform-mode.ts:26-31). Net effect: setting the key unlocks rust mode, then the path you set is discarded.

The embedding lane threads the same key correctly, which makes the asymmetry clear — packages/plugin/src/plugin/embedding-routing.ts:87:

connectionFile: subc.connection_file,

So with one config value, Synapse embeddings connect to the configured socket while the transform lane looks somewhere else.

Observed failure

Host: subc daemon 0.10.0 publishing to /run/user/1000/subc-connection.json (systemd RuntimeDirectory convention). Module registered and healthy.

Config:

{
    "transform_mode": "rust",
    "subc": { "connection_file": "/run/user/1000/subc-connection.json" }
}

Result — the configured path is never consulted:

[rpc] Rust session.status unavailable for ses_…:
      ENOENT: no such file or directory, statx '~/.local/share/cortexkit/run/subc-connection.json'
rust transform failed; attempting LKG replay: ENOENT …
lkg_miss
rust pass: decision=error reason=none served_from=raw in=299 out=299 applied=false
           row_version=0 elapsed=96.5 ms module=0.0 ms

(The ~ is the logger's own sanitizeDiagnosticText home-dir redaction, not an unexpanded tilde.)

Path check on the host:

MISSING  /home/icetea/.local/share/cortexkit/run/subc-connection.json   ← what it used
EXISTS   /run/user/1000/subc-connection.json                            ← what was configured

module=0.0 ms confirms the module is never invoked. From the daemon side it looks perfectly healthy the whole time (health ok, consecutive_error_count: 0, in_flight=0) because nothing ever arrives — which makes this painful to diagnose from the module end.

Downstream, over ~40 passes:

defer 36 · error 4 · parked 2 · execute 1     materialized = 0 on every row

Zero materializations means m[0]/m[1] are never built, so the TUI sidebar renders empty and the session shows "reconnecting". The failure is soft — LKG parking works as designed — but on a session with no prior LKG slot every attempt is lkg_miss and there is nothing to serve.

Suggested fix

Thread the configured value at both construction sites, defaulting as today when unset:

// index.ts
pluginConfig.transform_mode === "rust"
    ? new SubcModuleTransport(pluginConfig.subc?.connection_file)
    : undefined;

and the same for hook.ts:796. Happy to send a PR — I have this fixed locally and verified end to end.

Two smaller things spotted alongside, mentioned only so they can be considered together:

  1. hasUserTierSubcConfig proving a usable path exists while the transport uses a different path means the activation gate does not actually gate on the thing it validates. Threading the value fixes this for free.
  2. When the connection file is missing, the ENOENT arrives per-pass and each one re-enters backoff. A single startup-time existence check with a clear message (configured subc.connection_file not found at <path>) would turn a repeating soft failure into one actionable line — this took a while to trace precisely because the symptom presents as an empty sidebar rather than as a config error.

Environment

  • magic-context fork on upstream master (fork-lane migrations ≥10000; both fork features are TypeScript-only, crates/ byte-identical to upstream)
  • subc daemon 0.10.0, module magic-context registered, healthy, restarts 0/3
  • module built from the same tree; cargo test --workspace 1150 passed / 0 failed / 4 ignored
  • Reverting to transform_mode: "ts" restores normal operation immediately (defer, no errors, no parks)

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