|
| 1 | +# NBS Handle-Namespace Collision (cross-project sidecar dedup) |
| 2 | + |
| 3 | +**Authored:** 2026-05-12 by generalist (per supervisor 16:05:15Z dispatch, codification commit |
| 4 | +#3 in post-c4 batch). Anchors librarian 06:16Z + pythia #350 + repeated |
| 5 | +fixup workaround precedent (07:12Z, 08:10Z, 09:11Z, 10:12Z, 11:13Z, 12:50:32Z). |
| 6 | + |
| 7 | +**Class:** silent cross-project work cleanup risk. Operationally workaroundable today; |
| 8 | +proposed one-line fix below. |
| 9 | + |
| 10 | +--- |
| 11 | + |
| 12 | +## Problem |
| 13 | + |
| 14 | +`nbs-sidecar-restart` deduplicates running sidecars by **handle alone**. Multiple |
| 15 | +Phoenix-style team projects on the same workstation (today: `phoenix`, `vib-jit`, |
| 16 | +`nbsterm`) each run a `scribe` sidecar, a `medic` sidecar, and so on. Without scoping, |
| 17 | +the dedup pass collapses `scribe-phoenix` + `scribe-vib-jit` + `scribe-nbsterm` into a |
| 18 | +single `scribe` group and may kill the "duplicates" — i.e., other projects' live |
| 19 | +sidecars. |
| 20 | + |
| 21 | +The handle-strip at `nbs-sidecar-restart` line 153 (`HANDLE="${HANDLE%%-*}"`) is the |
| 22 | +proximate driver: it intentionally collapses compound handles like `supervisor-vib` → |
| 23 | +`supervisor` to handle a per-team-tag artefact, but the same collapse erases cross-project |
| 24 | +distinctness when the project name follows the role. |
| 25 | + |
| 26 | +## Trigger conditions |
| 27 | + |
| 28 | +- Two or more Phoenix-style teams running concurrently on the same OS user. |
| 29 | +- The fixup hook calls `nbs-sidecar-restart` (per scribe/medic mandatory-restart cycle). |
| 30 | +- `--root=PATH` filter omitted from the call. |
| 31 | + |
| 32 | +The default fixup invocation today omits `--root` and would silently affect cross-project |
| 33 | +sidecars if not for the per-cycle workaround documented below. |
| 34 | + |
| 35 | +## Current workaround |
| 36 | + |
| 37 | +Pass `--root=<project-path>` on every invocation of `nbs-sidecar-restart` from a per-team |
| 38 | +context: |
| 39 | + |
| 40 | +```bash |
| 41 | +nbs-sidecar-restart --respawn --root=/data/users/$USER/phoenix |
| 42 | +``` |
| 43 | + |
| 44 | +Applied at every fixup cycle in this session (07:12Z, 08:10Z, 09:11Z, 10:12Z, 11:13Z, |
| 45 | +12:50:32Z, 13:52:13Z, 14:53:48Z). Effective; not a structural fix. |
| 46 | + |
| 47 | +The `--root=PATH` filter at `nbs-sidecar-restart` lines 43, 95, 154–164 is already |
| 48 | +implemented and does the right thing when supplied — see `filter_root` in |
| 49 | +`kill_sidecar_loops` (line 75) and the second filter at line 161 in the dedup pass. |
| 50 | + |
| 51 | +## Proposed one-line fix |
| 52 | + |
| 53 | +Make project root part of the dedup key by default (no flag required, no behavior |
| 54 | +change for single-project setups). At `nbs-sidecar-restart` line 167: |
| 55 | + |
| 56 | +```diff |
| 57 | +- echo "$pid" >> "${DEDUP_DIR}/${HANDLE}.pids" |
| 58 | ++ echo "$pid" >> "${DEDUP_DIR}/${SC_ROOT//\//_}-${HANDLE}.pids" |
| 59 | +``` |
| 60 | + |
| 61 | +Companion change at the args-save block immediately below (line 169 area): |
| 62 | + |
| 63 | +```diff |
| 64 | +- if [[ ! -f "${DEDUP_DIR}/${HANDLE}.args" ]]; then |
| 65 | ++ if [[ ! -f "${DEDUP_DIR}/${SC_ROOT//\//_}-${HANDLE}.args" ]]; then |
| 66 | +``` |
| 67 | + |
| 68 | +(slash-to-underscore replacement keeps the file name path-safe.) Result: cross-project |
| 69 | +sidecars stay in separate dedup groups; `--root=PATH` becomes an additional filter, not |
| 70 | +the only protection. |
| 71 | + |
| 72 | +**Tradeoffs:** |
| 73 | + |
| 74 | +- Backward compatibility: any sidecar that omits `--root` from its own argv lands under |
| 75 | + an empty-string root group, which still dedupes correctly within itself but won't |
| 76 | + collide with project-rooted sidecars. Acceptable. |
| 77 | +- Single-project setups (only `phoenix`): no observable change. |
| 78 | +- Fixup hook simplicity: callers may stop passing `--root` once this fix lands; the |
| 79 | + behavior is correct without it. Optional follow-up: drop `--root` from project-team |
| 80 | + fixup hooks once the fix is in place. |
| 81 | + |
| 82 | +This change is local to `nbs-sidecar-restart` and does not require coordination with |
| 83 | +`nbs-sidecar` itself. |
| 84 | + |
| 85 | +## Out of scope |
| 86 | + |
| 87 | +- Cross-host handle collision (different OS users): out of scope; nbs-sidecar already |
| 88 | + refuses to operate across users. |
| 89 | +- Handle-strip semantics for legitimate compound handles (`supervisor-vib`): preserved |
| 90 | + as-is. The strip is correct for tag-suffix handles; the bug is only in the dedup-key |
| 91 | + composition. |
| 92 | +- Authoring of a parallel test for the fix: deferred to whoever ships the |
| 93 | + `nbs-sidecar-restart` change; this doc captures the operational rationale. |
| 94 | + |
| 95 | +## Anchors |
| 96 | + |
| 97 | +- librarian 06:16Z 2026-05-12: handle-namespace recurring per-cycle observation |
| 98 | +- pythia #350: cross-project handle collision codification queue item |
| 99 | +- pythia #351: per-cycle prediction confirmed by repeated fixup workarounds |
| 100 | +- supervisor 14:31:23Z + 16:05:15Z: post-c4 codification batch dispatches |
| 101 | +- shepard 14:48:49Z (cross-project anchor): D-1776818725 + WT-DIRTY rule |
| 102 | + (orthogonal class — both are cross-coordination defects but different mechanisms) |
0 commit comments