Repository navigation
[bug] DeepSeek Harness never loads teamai's hooks unless the member runs dsh --patch #1219
Description
Problem
teamai writes its dsh hooks to ~/.teamai/dsh/hooks.json and a patch overlay to ~/.teamai/dsh/cordis.patch.yml, then asks the member to start dsh with --patch "<path>" (src/dsh-hooks.ts:108). A member who runs plain dsh, which is the default and the only option in a launcher that takes no flags, gets no teamai hook: no project rules, no session-start sync, no env hint, no usage. doctor still reports ✔ Project rules reach dsh through its session-start hook, because it compares the patch and hooks.json bytes.
dsh already applies a patch from its home on every boot. readProfilePatches composes the bundle layers, <DSH_HOME>/profiles/<name>/cordis.patch.yml, then $DSH_HOME/cordis.patch.yml, then any --patch overlays (packages/boot/app-boot/src/profile-context.ts). The home layer is in the published app-boot 0.1.7-rc.2 and 0.2.0-rc.2.
flowchart TB
subgraph boot ["dsh boot: readProfilePatches, applied in order"]
b["bundle layers"] --> p["$DSH_HOME/profiles/<name>/cordis.patch.yml"] --> h["$DSH_HOME/cordis.patch.yml"] --> o["--patch overlays"]
end
t["~/.teamai/dsh/cordis.patch.yml<br/>mounts teamai's hooks.json"]:::teamai
t -. "today: only when the member runs dsh --patch" .-> o
row["teamai's row, merged in<br/>(member's rows kept)"]:::added -- "proposed: every boot" --> h
classDef teamai fill:#2f5f8f,stroke:#1f4569,color:#fff;
classDef added fill:#2f8f4f,stroke:#1f6b39,color:#fff;
Evidence
- dsh source at
687f282e(dsh-v0.2.1-rc.2):readProfilePatchesandcomposeProfile(apps/cli/src/profile-boot.ts).~/.teamai/dsh/cordis.patch.ymlis in none of the layers. - dsh's own hook parser (
parseClaudeCodeConfig,selectHookGroups) parses all six entries of teamai's hooks.json, so the file is right. Only the mount is missing. - An isolated-HOME
pullwrites the bridge, anddoctorpasses its check. dsh's boot source shows that plaindshdoes not load that bridge.
Two more problems on the same path
- Hook writes are sandboxed. With
--patch, hook commands run indsh-bash-sandbox(ordsh-pwsh-sandbox) underworkspace-write, rooted at the boot cwd. Under the default permission policy, writes to~/.teamaifail silently unless dsh started in$HOME, so session-start sync and usage stay off even when the hook runs. Read-only handlers (project rules, env hint) work. - A stale note. The doctor text in
src/resources/rules.ts:1672says the hook "runs detached, so the first request can miss the rules". Sincedsh-hooks-claude-code0.1.7-rc.1 the SessionStart run is awaited before the agent starts.
Fix
Mount the hooks plugin from $DSH_HOME/cordis.patch.yml. That file belongs to the member, so the writer inserts or updates only teamai's row and keeps the other rows. Removal deletes only that row. Drop the --patch instruction and the stale note. The sandbox needs its own decision: the hooks that write could move their writes out of the hook process, or teamai could document that sync needs dsh started in $HOME.
Done when
- Plain
dshloads teamai's hooks. - A member's own rows in
$DSH_HOME/cordis.patch.ymlsurvive pull and uninstall. -
doctorchecks the mount in$DSH_HOME/cordis.patch.yml, not the bytes of a file dsh never reads. - Under the default sandbox, sync and usage either work or
doctorsays they cannot write teamai's state. Mounting the hooks alone does not close this.
Activity
fix(dsh): preserve empty member-owned patches during removal (Tencent…
fix(dsh): retain commented patch file on removal of last mount (Tence…
fix(dsh): preserve inline comments on empty member patches (Tencent#1219
fix(dsh): mount hooks from the default home patch (#1223)
fix(rules,recall): migrate the legacy rules block; share recall outpu…
fix(rules,recall): migrate the legacy rules block; share recall outpu…
fix(rules,recall): migrate the legacy rules block; share recall outpu…