Session plan — 2026-09-22¶
Spec produced by a grilling session after the workspace reorg. Every decision below was confirmed by Nathan; anything not confirmed is listed under Open questions in its item rather than filled in.
Order: 0 → 2 → 4 → 5 → 1 → 6 → 7 → 3. Security first, the open-ended pilot last.
0. Land the backlog MR — done (merged)¶
MR !6: code-library, voice, dashboard, workspace layout, vendored
laya-integration skill. make check green.
- The Laya SKILL.md has no stated license (model is Apache-2.0); recorded in
shared/skills/laya-integration/PROVENANCE.md.
1. Case-only renames in workspace_layout.py apply¶
On macOS (case-insensitive FS) OSS → oss is treated as already done and
silently skipped.
applydetects source/target that differ only by case and renames via a temporary name (OSS → OSS.tmp-<pid> → oss).planshows the two-step rename.
Done when: a new test fails on current code and passes after; make check green.
2. Keep agents out of the Sensitive Anytype space¶
Verified: a scoped key works. The new key (Agent-Key-Scoped-RW) is granted
3 spaces, not Sensitive; /v2/spaces returns has_not_granted_spaces: true.
Scoped keys are v2-only (/v1 → 403 v1_not_available_for_scoped_keys);
@anyproto/anytype-mcp 2.0.1 loads /v2/docs/openapi.json first, so the MCP is
unaffected after a restart.
Remaining:
- 2b. Add
anytype_id(compact id, e.g.5smqsi) to each entry inknowledge/anytype-integration/schemas/spaces.json; match on id, not name. Fix the name drift while there.tenancy.py --checkvalidates the field. - 2c.
make anytype-scope-check: reads the key from the shell env, calls/v2/spaces, fails if any space withagent_read: falseis visible. Not inmake check/ pre-commit (Anytype isn't always running, never in CI); surfaced as a health item on the dashboard. - 2d. Restart Claude Code; confirm
mcp__anytype__API-list-spacesshows 3 spaces.
Done when: the check fails against a key that can see Sensitive (fixture / stubbed response) and passes against the live scoped key.
3. code_library pilot — blocked on item 7¶
Paused 2026-09-22: a dry scan showed the tool-only model doesn't fit
(see item 7). Categories are enabled on feat/code-library-pilot; processing
waits until repos have kinds, so accepted entries aren't redone.
- Enable all categories:
ai,infosec,finance,ml,utility. - Process through the dashboard:
everything-claude-code,langgraph,strix,agentshield,nautilus_trader. - Write down friction as follow-up items (append to this file).
Done when: search_tools returns relevant hits from ≥3 of those repos, and a
friction list exists.
4. make mcp-smoke — lesson from the code_library serve crash¶
- For each
[mcp.*]intool-chest.toml: launch over stdio with a timeout,initialize,list_tools, assert ≥1 tool. - Separate target, not pre-commit (uv/npx cold starts are slow; anytype needs the app). CI runs it with anytype skipped.
- Record in the lesson ledger (
/lesson).
Done when: it fails against the pre-fix code_library (calibrated on the known failure) and passes on all current servers.
5. Dashboard write-endpoint hardening¶
Found 2026-09-22: scripts/dashboard.py POST routes do no Origin/Host
checks, so any web page open in the browser can reach 127.0.0.1:8787
(CSRF, DNS rebinding). Item 6's connect would widen this to writing agent
config. Must land before 6e.
- Reject requests whose
Hostisn't127.0.0.1:<port>/localhost:<port>. - Reject POSTs whose
Originisn't the dashboard's own origin. - Per-launch random token embedded in the served page, required on every POST.
Done when: tests cover foreign Origin, foreign Host and missing/wrong token (each rejected) and the real UI still works.
6. Capability ring — dashboard home¶
A visual home view: one central workspace object ringed by capability areas. Each area can be configured, activated, and connected to agent clients, and clicks through to its list/detail view.
Decisions¶
| Topic | Decision |
|---|---|
| Ring nodes | Capability areas (not one per MCP) |
| Registry | [capability.<id>] in tool-chest.toml is the source of truth |
| States | Configure (settings) → Activate (prereqs met, health probe passes) → Connect (exposed to clients) |
| Connect | Toggles generated MCP config; UI shows "restart client to apply" |
| Granularity | Per area × client; clients = [...] replaces [mcp.*].scope |
| Clients (v1) | Extensible: a [client.<id>] registry (label, config path, format); built-in writers per common JSON shape, a small adapter only for a genuinely new shape (e.g. CLI-driven). Planned beyond v1: OpenCode, Cline, Cody… v1 set: claude-project (.mcp.json), claude-user (via claude mcp add/remove -s user, never editing ~/.claude.json directly), cursor (.cursor/mcp.json). Local agent dropped: local-agent has no model/MCP layer |
| Placement | Ring replaces Home; existing sections are the drill-downs |
| Rendering | Vanilla SVG, no build step; stacks to a list on narrow screens. Style: C · Constellation (cards on an ellipse). Cards show name, status line, health bar — no client chips; connections appear only in the side panel |
| Center | Overall health (make check, layout, anytype scope), client status and pending restarts, workspace bucket counts, global actions (regenerate configs, run checks, open docs) |
| v1 scope | Ring + side panel + connect + health; areas lacking a view get a count-only placeholder |
Areas¶
| Area | Backed by | Drill-down |
|---|---|---|
| Code library | mcp code_library |
Code library section |
| Reference library | mcp library |
placeholder (book count) |
| Research | mcp research |
placeholder (article count) |
| Patterns | mcp patterns |
Search |
| PKM (Anytype) | mcp anytype, skills pkm-* |
Inbox / Tasks / People |
| Voice | cli voice |
Voice |
| Model routing | service OmniRoute | OmniRoute |
| Sandbox & labs | cli sandbox, labs |
Labs / Sandbox plan |
Skills, MCP list, Harnesses and Workspaces are cross-cutting, reached from the center.
Slices¶
- 6a Registry.
[capability.*]schema (label, mcp, cli, skills, drill-down section, health probe). Drift check inmake check: every[mcp.*]belongs to exactly one area.GET /api/capabilities. - 6b Generator. A
[client.<id>]registry plus built-in format writers;clients(ids from the registry) replacesscopeingen_mcp_config.py; migration test proves today's generated.mcp.json/.cursor/mcp.jsonare unchanged;claude-usergoes throughclaude mcp add/remove -s user(also fixesmake mcp-install-user). - 6c Ring (read-only). Constellation-style SVG ring replaces Home; node badges for the three states; click → side panel → drill-down link.
- 6d Health. Per-area probe from the registry, shown on nodes and the center.
- 6e Connect. One toggle per registered client in the side panel; writes
tool-chest.toml, regenerates, shows pending-restart. Blocked on 5. - 6f Configure / activate. Side-panel settings and setup actions.
Open questions¶
- 6f: which settings are editable per area, and may the dashboard run setup
targets (e.g.
make voice-setup)? If yes, from a fixed allowlist? - Pending restart: how to clear it (a timestamp compare against client start, or a manual "I restarted" dismiss)?
- Cursor user scope (
~/.cursor/mcp.json): out of v1?
Answers:¶
- 6f: for each area, v1 should only expose the settings necessary to correctly configure that area. Exposing additional, optional config surfaces can come later, if the core thesis of this approach bears out.
- Pending restart: Unclear what the best solution is here. Users can be unreliable, and may dismiss the warning even if they have not restarted yet. What is the simplest, safest solution here?
- Cursor usage scope: include in v1
Resolutions (2026-09-22)¶
- Pending restart: derived, no dismiss button. A client is "restart pending" while any of its running processes started before its config last changed; it clears itself. May over-warn, never under-warn.
- 6f settings (v1, required only): Code library
source_root,enabled_categories; Reference librarycalibre_library; Researcharchive_dir(archive lives outside the repo); Patterns none (in-repo corpus); PKMapi_base_url+ key status only; Voicemodel; Model routingenabled,base_url; Sandbox & labs none. Secrets are never editable. - 6f setup runs: fixed allowlist, at most one setup target per capability, declared in the registry, behind item 5's token.
- Cursor user scope: in v1 as client
cursor-user(~/.cursor/mcp.json).
7. Code library: repo kinds¶
Found in the pilot dry scan (205 proposals over 5 repos, almost all noise):
README backtick mentions became "tools" (sk-ant-, StateGraph); build and
maintenance targets swamped real entry points; libraries yielded nothing.
Decisions¶
| Topic | Decision |
|---|---|
| Kinds | collection (many discrete units, e.g. everything-claude-code), library (one unit, used as a detailed reference though imported normally, e.g. langgraph), tool (one runnable app, e.g. strix, agentshield) |
| Assigning a kind | Scanner suggests on Process; Nathan confirms or changes before anything is indexed; stored in library.toml |
| Collection units | Known shapes: skill (dir with SKILL.md), agent, command, hook, MCP server, CLI entry point. Each proposed separately; new shapes are added to the detector as met |
| Tool entry | Its CLI recipe (bin / pyproject script) |
| Library reference | Docs + examples, public API surface (static: modules, classes, signatures, docstrings, never imported or run), source passages as a last resort |
| Version match | Clone version/tag vs pins found in lockfiles under ~/Documents/workspace/projects/* (uv.lock, package-lock.json, pyproject, Cargo.lock); a mismatch is flagged on the library entry |
Slices¶
- 7a Drop README-mention proposals (bug).
- 7b Repo kind: suggest + confirm + persist. Existing proposals flow under tool; the kind drives which extractor runs.
- 7c Tool kind proposes entry points only, not build/lint/test targets.
- 7d Collection units: detect the known shapes, accept per unit.
- 7e Library reference: index docs + examples + source passages, searchable per library.
- 7f Library API surface: static extraction of the public API.
- 7g Version match against projects' lockfiles.
Pilot (item 3) is blocked by 7a–7e.
Open question¶
- 7c: is "entry points only" right for tools, or should the review still list other targets hidden by default? Resolved (Nathan, 2026-09-23): entry points only. Build, lint, test and install targets are not proposed, not even hidden.