Skip to content

deriveBundleDataDir is broken for path bundles (only replaces first slash) #224

@mgoldsborough

Description

@mgoldsborough

Problem

src/bundles/paths.ts:92deriveBundleDataDir only replaces the first /:

```ts
export function deriveBundleDataDir(name: string): string {
return name.replace("@", "").replace("/", "-");
}
```

`.replace("/", "-")` is a single-replacement string call, not a regex. Fine for npm-scoped names (@scope/name has exactly one /). Completely broken for path bundles:

  • Input: /Users/mgolds02/Code/hq/synapse-apps/synapse-crm
  • After .replace("@", ""): /Users/mgolds02/Code/hq/synapse-apps/synapse-crm
  • After .replace("/", "-"): -Users/mgolds02/Code/hq/synapse-apps/synapse-crm ← only the leading / got swapped; the others stayed /
  • join(wsPath, "data", that) happily nests it into workspaces/<ws>/data/-Users/mgolds02/Code/hq/synapse-apps/synapse-crm/...

Impact

Every place a path: bundle is installed produces a junk multi-segment directory under the workspace's data tree. The bundle process is told to write to one location while consumers (briefing, etc.) look in another. Symptoms include:

  • Briefing collector reads facet data from the broken path → finds nothing → LLM faithfully writes "no data yet" briefings for tenants with full workspaces (this was the user-facing trigger for PR fix(briefing): resilient cross-provider home briefing #219; that PR sidesteps the bug via manifest-name re-derivation but doesn't fix the underlying function)
  • Any other caller relying on dataDir from a path-installed bundle has the same divergence

Suggested fix

Use the same shape slugifyServerName (lines 50–58 of the same file) already implements:

```ts
export function deriveBundleDataDir(name: string): string {
return name
.replace(/^@/, "")
.replace(/[/.]/g, "-")
.replace(/[^a-z0-9-]/gi, "-")
.replace(/-+/g, "-")
.replace(/^-+|-+$/g, "");
}
```

Two callers to audit before / after the change:

  1. workspace-ops.ts:47 — the install path that tells the bundle process where to write data
  2. lifecycle.ts:1479seedInstance which derives entityDataRoot (already mitigated in PR fix(briefing): resilient cross-provider home briefing #219 via manifest-name fallback)

Test inputs to cover: @scope/name, /abs/path/with/slashes, reverse-DNS forms, names with ., names with capitals.

Context

Surfaced during local testing of PR #219. See briefing-resilience PR commit 6e31dcf for the briefing-side mitigation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions