MCP server for tangled

document PR architectural incompatibility

- move design-pulls.md to sandbox/ (exploratory, not production-ready)
- add critical warning: PRs can't work via atproto records
- appview doesn't subscribe to sh.tangled.repo.pull in jetstream
- no firehose ingester for pulls (only issues have ingestIssue)
- web UI creates DB entries directly, atproto record is decorative
- improve release.md wording (current repo vs current release)
- add tree reminder to CLAUDE.md

PR support would require tangled-core changes (adding firehose consumer).
The design is architecturally sound but incompatible with current implementation.

Changed files
+61 -1
.claude
commands
sandbox
+1 -1
.claude/commands/release.md
··· 2 2 3 3 read @docs/publishing.md and use it to help me cut a new release of tangled-mcp. 4 4 5 - use gh to view the website for the current release, it should point to the latest published version, verify after release that this refers to the new version you just released. 5 + use gh to view the website for the current repo, it should point to the latest published version of the MCP in the official registry, verify after release this points to the new version you just released. 6 6 7 7 also curl pypi to verify that the new version is available. 8 8
+1
CLAUDE.md
··· 22 22 - justfile: `setup`, `test`, `check`, `push` 23 23 - versioning: uv-dynamic-versioning (git tags) 24 24 - type checking: ty + ruff (I, UP) 25 + - remember that `tree` is your friend, better than `ls` and a dream 25 26 - **use `jq` for JSON parsing** (not python pipes) 26 27 - example: `curl -s https://pypi.org/pypi/tangled-mcp/json | jq -r '.info.version'` 27 28 - **never use `sleep`** - poll/check with actual tools instead
+59
docs/design-pulls.md sandbox/design-pulls.md
··· 1 1 # pull requests: design exploration 2 2 3 + **⚠️ CRITICAL: THIS DESIGN CANNOT BE IMPLEMENTED ⚠️** 4 + 5 + **Date discovered**: 2025-10-11 6 + **Reason**: Pull requests in tangled use a fundamentally different architecture than issues. 7 + 8 + ## Why PR support via atproto records doesn't work 9 + 10 + After implementing this design and testing, we discovered that **tangled's appview does not ingest pull records from the firehose**. Here's the architectural difference: 11 + 12 + ### Issues (✅ Works): 13 + 1. **Jetstream subscription**: `appview/state/state.go:109` subscribes to `sh.tangled.repo.issue` 14 + 2. **Firehose ingester**: `appview/ingester.go:79-80` has `ingestIssue()` function 15 + 3. **Pattern**: atproto record is source of truth → firehose keeps database synchronized 16 + 4. **Result**: MCP tools work! Create issue via atproto → appears on tangled.org 17 + 18 + ### Pulls (❌ Broken): 19 + 1. **No jetstream subscription**: `tangled.RepoPullNSID` is **missing** from subscription list 20 + 2. **No firehose ingester**: No `ingestPull()` function exists in `appview/ingester.go` 21 + 3. **Pattern**: Database is source of truth → atproto record is decorative 22 + 4. **Web UI flow** (`appview/pulls/pulls.go:1196`): 23 + - Creates DB entry FIRST via `db.NewPull()` 24 + - THEN creates atproto record as "announcement" 25 + 5. **Result**: MCP-created PRs are **orphan records** that exist on PDS but never appear on tangled.org 26 + 27 + ### Why this design exists 28 + 29 + Looking at the code (`appview/pulls/pulls.go`), pulls have: 30 + - **Submissions array**: Multiple rounds of patches (DB-only concept) 31 + - **Size concerns**: Patches can be megabytes (expensive in atproto) 32 + - **Complexity**: Appview manages pull state in its database with features not in atproto schema 33 + - **Pragmatism**: They wanted to ship pulls quickly, made DB the source of truth 34 + 35 + ### Evidence 36 + 37 + ```bash 38 + # Issues are subscribed in jetstream 39 + grep -n "RepoIssueNSID" sandbox/tangled-core/appview/state/state.go 40 + # 109: tangled.RepoIssueNSID, 41 + 42 + # Pulls are NOT subscribed 43 + grep -n "RepoPullNSID" sandbox/tangled-core/appview/state/state.go 44 + # (no results) 45 + 46 + # Issues have an ingester 47 + grep -A 2 "RepoIssueNSID:" sandbox/tangled-core/appview/ingester.go 48 + # case tangled.RepoIssueNSID: 49 + # err = i.ingestIssue(ctx, e) 50 + 51 + # Pulls do NOT have an ingester 52 + grep "RepoPullNSID:" sandbox/tangled-core/appview/ingester.go 53 + # (no results) 54 + ``` 55 + 56 + ### Conclusion 57 + 58 + **Pull request support cannot be added to tangled-mcp** without changes to tangled-core (adding firehose consumer). The design below is architecturally sound but incompatible with tangled's current implementation. 59 + 60 + --- 61 + 3 62 ## design principle: gh CLI parity 4 63 5 64 **goal**: tangled-mcp pull request tools should be a subset of `gh pr` commands with matching semantics