fix(skillify): route push/pull through .hivemind, not the global workspace#317
fix(skillify): route push/pull through .hivemind, not the global workspace#317khustup2 wants to merge 1 commit into
Conversation
…space
`hivemind skillify push` read `loadConfig()` raw and passed the global
`workspaceId` straight to the API, so a skill saved from a directory
routed by `.hivemind` landed in the GLOBAL workspace — the exact symptom
DevOps reported ("saved a local skill, it showed up in the default
workspace"). Session capture already routes via resolveDirConfig; skillify
was a straggler that never got threaded.
Resolve the nearest `.hivemind` at both the push and pull sites so skills
write to, and read from, the directory's routed workspace — symmetric with
where that tree's traces are captured. org/workspace are identity and apply
to reads and writes alike; `collect:false` gates capture only, so a
routed+opted-out directory still pushes/pulls to its workspace.
unpull is untouched: it is a local-filesystem operation that never queries a
workspace (it only reads userName for --not-mine).
The DeeplakeApi ctor puts the workspace in the URL path
(/workspaces/{workspaceId}/tables/query), so that arg is where the write
lands; the new test asserts on it with resolveDirConfig running for real.
Verified to fail against the pre-fix code.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthrough
ChangesSkillify workspace routing
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant Skillify
participant resolveDirConfig
participant DeeplakeApi
User->>Skillify: run pull or push
Skillify->>resolveDirConfig: resolve config for current directory
resolveDirConfig-->>Skillify: routed or global workspace
Skillify->>DeeplakeApi: read or write skills
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Coverage ReportScope: files changed in this PR. Enforced threshold: 90% per metric (per file via
File Coverage — 1 file changed
Generated for commit 3d0059f. |
|
Superseded by #318, which folds this skillify fix into a single-source-of-truth refactor (one loadRoutedConfig entry point + a guard that prevents the whole class of unrouted-writer bugs). |
`.hivemind` routing was wired writer-by-writer, so every new path that built
a DeeplakeApi from a raw loadConfig() silently used the GLOBAL workspace
instead of the directory's routed one. Skillify was the latest to bite
(DevOps: "saved a skill, it landed in the default workspace"); goals, rules,
and the Codex/Cursor/Hermes memory hooks had the identical latent bug.
Introduce ONE entry point — loadRoutedConfig(cwd) in dir-config.ts — that
folds the nearest .hivemind (and the HIVEMIND_* env locks, via
resolveDirConfig) in one place, and migrate every workspace-touching site to
it:
- CLI writers/readers: goal, rules, context, skillify (push/pull),
flush-memory
- other-agent memory hooks: codex/cursor/hermes pre-tool-use
- session-start-setup, skillify auto-pull + skillopt-worker
- mcp/server, graph deeplake-pull (symmetric with the already-routed push)
A guard test (dir-config-single-source.test.ts) enumerates every
`new DeeplakeApi(` site and fails the build unless it routes or is
allow-listed with a reason — so an unrouted writer can no longer be added
silently. Five sites are allow-listed (session-prune, docs, cowork-ingest,
and the creds-based banner/resume-brief reads) each with a documented reason.
This supersedes and folds in PR activeloopai#317 (skillify-only fix).
Deliberately NOT routed, tracked as follow-up: the notification reads
(resume-brief, open-goals) build from creds.workspaceId and need a resolved
workspace threaded in — a different change from a loadConfig swap; and docs,
which use a separate per-(org,repo) consent model.
Verified: loadRoutedConfig routes end-to-end (skillify push/pull behavioral
test, fails against unrouted code); the guard catches a reverted file;
typecheck clean; no new suite failures; touched files clear their coverage
gates.
What DevOps hit
Artyom set up a directory with a
.hivemindconfig, but saving a skill from it wrote to the global workspace, not the routed one. His words in #devops:That test happens to exercise the one writer that never got routed.
Root cause
src/commands/skillify.tsreadloadConfig()raw at the push and pull sites and passed the globalworkspaceIdstraight toDeeplakeApi— noresolveDirConfig. Session capture, session-end summaries, and graph push all route through.hivemindalready; skillify was a straggler nobody threaded. TheDeeplakeApiconstructor puts the workspace in the URL path (/workspaces/{workspaceId}/tables/query), so that argument decides where the row lands — and it was always the global one.To be clear about scope: regular session capture routes correctly (traced end-to-end:
resolveCaptureConfig→workspaceId→ URL path → write). Artyom's complaint was phrased about sessions but the only thing he tested was skillify, which is the single broken path. This PR fixes that path.The fix
Resolve the nearest
.hivemindat both the push and pull sites, so skills write to — and read from — the directory's routed workspace, symmetric with where that tree's traces are captured.orgId/workspaceIdare identity → apply to reads and writes.collect:falsegates capture only, so a routed + opted-out directory still pushes/pulls to its workspace.userNamefor--not-mine).Test
tests/claude-code/skillify-dir-routing.test.tsrunsresolveDirConfigfor real against the process cwd and asserts which workspaceDeeplakeApiwas constructed against — the URL path that decides where the write goes. Covers push + pull, ancestor inheritance,collect:falsestill routing, and the no-.hivemindglobal fallback. Verified to fail against the pre-fix code (the 4 routing assertions fail; the 2 global-fallback cases pass in both, as they should).Verification
tree-sitter-python-missing graph suites + theflush-memorynetwork timeout, all unrelated).skillify.ts; coverage run clean.Still open (not in this PR)
The rules/goals CLI writers use the same
loadConfig()-raw pattern and will behave identically — nobody's tested them yet, but they're the next straggler. Happy to fold them into a follow-up.🤖 Generated with Claude Code
https://claude.ai/code/session_017SDmiDuUn7Wqhi7qdn1p1f
Summary by CodeRabbit
skillify pushandskillify pullnow honor the nearest.hivemindworkspace configuration.collect:falsewhile preserving the selected workspace.