feat: add opt-in tldraw skill and local snapshot store#11
feat: add opt-in tldraw skill and local snapshot store#11codejunkie99 merged 3 commits intomasterfrom
Conversation
…er as well, to be worked with tl draw only at localhost 3000
codejunkie99
left a comment
There was a problem hiding this comment.
Required changes before merge:
1. Rebase onto current master. This branch predates v0.8.0 and PR #9. CHANGELOG.md, test_claude_code_hook.py, verify_codex_fixes.py, adapters/claude-code/CLAUDE.md (+119), and the hook_patterns.json tip in onboard.py are drift, not tldraw work.
2. Drop the "5th memory layer" framing. .agent/memory/visual/ has no lifecycle, no clustering, no dream-cycle integration, no retrieval. auto_dream.py never touches it. Move to .agent/skills/tldraw/store.py or .agent/memory/working/canvases/. Update README + CHANGELOG accordingly.
3. Fix concurrency bugs in visual_memory.py:
:99-101_append_jsonl— no lock; concurrent snapshots corrupt the JSONL.:195-204archive_snapshot— read-modify-rewrite race loses records appended between read and rewrite.:94-95_read_jsonl— silently swallowsjson.JSONDecodeError. Log to stderr.
Use the flock pattern from .agent/memory/render_lessons.py.
4. Validate sid in load_snapshot / archive_snapshot (:177-184). os.path.join(SNAPSHOTS_DIR, f"{sid}.json") accepts ../ traversal. Constrain sid to [A-Za-z0-9_-]+ before joining.
5. Bound the id-resample loop at :142-144 to ~8 attempts and raise. Currently unbounded.
6. Delete duplicate files:
adapters/antigravity/.mcp.jsonadapters/claude-code/.mcp.jsonadapters/cursor/.cursor/mcp.json
They are byte-identical to adapters/_shared/tldraw-mcp.json. Have install.sh / install.ps1 copy the shared file per adapter instead.
7. Delete .agent/skills/tldraw/KNOWLEDGE.md. 4-line empty placeholder. SKILL.md can instruct create-on-first-use.
8. Stop committing generated .agent/memory/visual/INDEX.md. Add it to .gitignore; let _render_index create it on first snapshot.
9. Delete adapters/claude-code/.claude/commands/tldraw.md. Redundant with SKILL.md triggers.
10. Remove status CLI subcommand + _cmd_status from visual_memory.py. list covers it.
11. Tests:
- Delete structural tests (
test_tldraw_visual_memory.py:57-111— file-existence and manifest-key assertions). - Add a concurrency test: two threads appending snapshots concurrently, assert no JSONL corruption.
- Add a malformed-JSONL-line recovery test.
- Add a path-traversal test for
sid.
…y, drop duplicates
Relocate
Move persistence out of .agent/memory/visual/ into the skill itself at
.agent/skills/tldraw/store.py. The previous layout implied a fifth
memory layer, but there is no lifecycle, clustering, dream-cycle, or
recall integration — it's skill-local storage, not memory. Naming now
matches behavior.
Concurrency
* JSONL mutations acquire an advisory exclusive flock on Unix and a
process-local threading.RLock on Windows (fcntl unavailable).
* Archive does read-modify-rewrite inside a single lock scope.
* Atomic-write tmp names include 6 bytes of entropy so two threads
writing the same target in the same millisecond can't race on the
tmp file.
* Snapshot id retries are bounded (_MAX_RESAMPLE = 8) so a degenerate
RNG can't spin forever.
Security
load_snapshot / archive_snapshot validate the sid against
^[A-Za-z0-9_-]+$ before any os.path.join. Blocks traversal inputs
like "../etc/passwd" at the API boundary.
Robustness
Malformed JSONL lines are logged to stderr and skipped rather than
silently swallowed — the store exists to surface corruption, not hide
it.
Duplicates removed
* adapters/{antigravity,claude-code}/.mcp.json and
adapters/cursor/.cursor/mcp.json were byte-identical to
adapters/_shared/tldraw-mcp.json. install.sh and install.ps1 now
copy the shared file into the target per adapter.
* Deleted .agent/skills/tldraw/KNOWLEDGE.md (placeholder) and
adapters/claude-code/.claude/commands/tldraw.md (redundant with the
skill).
Gitignore
INDEX.md, snapshots/, and snapshots.jsonl under the skill are runtime
output — gitignored so installs start clean. The PR-local validation
harness (test_tldraw_visual_memory.py) is also gitignored
Tests (local)
66/66 passing. New coverage: 16-thread concurrent snapshot writes with
post-hoc jsonl parse + count check, malformed-line recovery.
Adds an opt-in, harness-agnostic tldraw skill plus a skill-local snapshot store.
Skill
.agent/skills/tldraw/SKILL.mdwith triggers, tool guidance, constraints, and a self-rewrite hook._index.mdand_manifest.jsonlbehindfeature_flag: tldraw.skill_loader.pyso flagged skills load only when.agent/memory/.features.jsonexplicitly enables them.Local snapshot store
.agent/skills/tldraw/store.pywithsnapshot,list,load, andarchiveCLI/API support.snapshots.jsonl,snapshots/, andINDEX.md.Opt-in MCP setup
adapters/_shared/tldraw-mcp.jsonas the canonical config users can manually merge after enabling the feature.Onboarding and docs
tldraw [BETA]onboarding feature flag, default off.Review fixes
.agent/skills/tldraw/store.pyinstead of removed.agent/memory/visual/visual_memory.py.INDEX.mdwhile holding the JSONL lock to avoid stale concurrent renders.Verification
python3 test_tldraw_visual_memory.pypasses: 52/52.verify_codex_fixes.pypasses.test_claude_code_hook.pypasses: 54/54.py_compile,jq, SVG parse, andgit diff --checkpass.