feat: v0.8.0 — Claude Code subagent capture, own Joplin notebook, git-root repo tags, multi-root scanning

- Subagents: fold Task-tool transcripts (subagents/*.jsonl) inline as
  collapsible <details> blocks at the spawn point; their own tool traffic
  collapses under the same policy; nesting handled via toolUseId matching
- Joplin: Claude Code gets its own top-level AI-ClaudeCode notebook;
  update_note sets parent_id so notes self-heal/relocate on re-sync
- Repo [tags] in titles via git-root detection (nearest .git ancestor),
  home-wide and cross-workspace; CLAUDE_CODE_REPO_TAG_IGNORE escape hatch
- Multi-root scanning: CLAUDE_CODE_DIR as os.pathsep list + CLAUDE_CONFIG_DIR;
  merged by launch-folder, newer-mtime wins on UUID collision
- 298 tests passing

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
JesseMarkowitz
2026-07-06 05:04:41 -04:00
co-authored by Claude Opus 4.8
parent bbcb29c856
commit 1f5a445ada
12 changed files with 779 additions and 71 deletions
+25
View File
@@ -17,6 +17,7 @@ from src.blocks import (
make_file_placeholder,
make_hidden_context_marker,
make_image_placeholder,
make_subagent_block,
make_text_block,
make_thinking_block,
make_tool_result_block,
@@ -119,6 +120,30 @@ class TestMarkdownFrontmatter:
assert "```python" in content
assert "print('hello')" in content
def test_subagent_block_renders_as_details(self, tmp_path):
sub = make_subagent_block(
agent_type="Explore",
description="find the thing",
messages=[
{"role": "user", "blocks": [make_text_block("Go find it")]},
{"role": "assistant", "blocks": [make_text_block("Found it here.")]},
],
)
conv = {
**SAMPLE_CONV,
"provider": "claude-code",
"messages": [
{"role": "assistant", "content_type": "text", "timestamp": None,
"blocks": [make_text_block("Delegating."), sub]},
],
}
content = MarkdownExporter(tmp_path).export(conv).read_text()
assert "<details>" in content
assert "<summary>🤖 Subagent: Explore — find the thing</summary>" in content
assert "Go find it" in content
assert "Found it here." in content
assert "</details>" in content
class TestMarkdownFilenameGeneration:
def test_filename_format(self, tmp_path):