OpenWiki Init

This commit is contained in:
Kaede Akino committed 2026-09-22 09:11:39 +08:00
1 parent a048a37e6f
commit 4873b8dd66
37 files changed
+5130 -5

No files matched your search

+23 -3
View File
@@ -30,14 +30,34 @@ jobs:
# mermaid + jsdom are optional; they add high-fidelity validation of Mermaid diagrams. Remove if your wiki has none.
run: npm install --global openwiki@0.5.2 mermaid@11.16.0 jsdom@29.1.1
- name: Validate OpenAI-compatible configuration
env:
OPENAI_COMPATIBLE_API_KEY: ${{ secrets.OPENAI_COMPATIBLE_API_KEY }}
OPENAI_COMPATIBLE_BASE_URL: ${{ vars.OPENAI_COMPATIBLE_BASE_URL }}
OPENWIKI_MODEL_ID: ${{ vars.OPENWIKI_MODEL_ID }}
run: |
test -n "$OPENAI_COMPATIBLE_API_KEY" || {
echo "::error::Missing repository secret OPENAI_COMPATIBLE_API_KEY"
exit 1
}
test -n "$OPENAI_COMPATIBLE_BASE_URL" || {
echo "::error::Missing repository variable OPENAI_COMPATIBLE_BASE_URL"
exit 1
}
test -n "$OPENWIKI_MODEL_ID" || {
echo "::error::Missing repository variable OPENWIKI_MODEL_ID"
exit 1
}
- name: Run OpenWiki
id: openwiki
continue-on-error: true
run: openwiki code --update --print
env:
OPENWIKI_PROVIDER: openai
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENWIKI_MODEL_ID: "gpt-5.6-terra"
OPENWIKI_PROVIDER: openai-compatible
OPENAI_COMPATIBLE_API_KEY: ${{ secrets.OPENAI_COMPATIBLE_API_KEY }}
OPENAI_COMPATIBLE_BASE_URL: ${{ vars.OPENAI_COMPATIBLE_BASE_URL }}
OPENWIKI_MODEL_ID: ${{ vars.OPENWIKI_MODEL_ID }}
# Required for the LangSmith connector's code-mode pull to authenticate.
# For extra workspaces, add OPENWIKI_LANGSMITH_API_KEY_2, _3, ... as repo
# secrets and env entries here.
@@ -0,0 +1,234 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:7d2268951977dcbe8bf9e3bfa6b79ec69cb3d55c72a1c242cc8b944a0fb88ec5",
"claims": [
{
"id": "claim_bd9f5ddda6b6466eb79c622b02fd73f2",
"statement": "Termind builds distinct macOS (`TFM`) and iOS/iPadOS (`TFI`) application targets, while shared framework modules do not import the application targets; the application targets own native UI and lifetime behavior.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L8-L21",
"version": "repo-lines-v1:sha256:beb72f34aa32ee1d79a5d3645e1bc9c3bb88759c2cfc1b7326be5dfe5a813303:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjMzZhZjE0ZWI0MTViMjBmZGY2NTMzNGRmYTVkOGFiMjhkOGE3OGJjMTBmOTM4ZWQ3MDAzYmE4MzNjYTBjZDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVkZTI2OTNjNDgwYTVkOWI2NGJlZDk2Y2UwOGQ2NDNhMDgxNDNjMWI1MjZjNzA0MDg2NTk5MDc1M2I2ZTQ0OTciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBkMjllYWFhZmYzYmM1Yzg0YTBjNzQ4MzkzNGYwYmE2NDY5NTYzN2JmYjU5OTNiMmE5NzE3OWYyNjgxNTYwYzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk4YzFlYjFkZGU1NDQzMjdmMzNiYzcwNTdhMDZiYWEwZDU5N2NiZGExNzIwOWE3Y2QwMjVmMzQwMDg2ODk4ODkifQ"
},
{
"resource": "repo://TFI/App/TermindIOSApp.swift#L5-L17",
"version": "repo-lines-v1:sha256:a2a3bd4ff94c140758b6b89a59d0745d4318eccea3e565614aeb71ae86e31ba5:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0MDI1ZTA5ZDBlYTM3ZDMyNTYyMDVjODkwYTg5YjU0NmE0MDcwNTg4MDJmZWUyZDY1N2Q2ZjJmODg5MzllMTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBkMjE5MGFjNWM3N2IzZTA5NDYzN2Q0YzdjYzhhNTY4M2M2MjE3YWY4MGYyMzU1YjY5NzlkNDNiZGI5ODkwM2EifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L13-L20",
"version": "repo-lines-v1:sha256:891f05013590adcc8910c2e5088931000fa575e966a2550c82fb466ad06f1d36:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNWNmYmRiYjUwMTZhYzdkZWVhNTZlODkwYWU5M2FkNzczNjVjYjRkOGEwZDg2OGIyZTZjOWJlM2NjMTFjNDY0ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNWEyZGI2NmY0YTUzMjU3NWRjNTBmYmM5MWNmNGJjYThiMTVkN2U4ZDJiZTlmNWNjMThlMDY2MjY1OWMwYTVmOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYjAzMTkyYWFlOGU2ZGIzZjk3M2MyMjYyODQyNDdjOWI2ODgxYWMxNTEyOGUzOGQ3N2JjNmMyNDQ3Mjg4NWZlZCJ9"
}
]
},
{
"id": "claim_67bc0bd4217544de9b7ddb97de66989f",
"statement": "On macOS, `TermindApp` is the composition root: it creates one SwiftData container, prepares persistence and Keychain-backed services, constructs sync/outbox/repository dependencies, and retains one `AppModel` in SwiftUI state; failure to open the local container terminates startup rather than substituting an empty store.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L17-L20",
"version": "repo-lines-v1:sha256:58dfb9d543fbe26e0e9685791c843a88d19dea527b3e1bfad82837d66b1a12e2:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzY3MDc0OTM5MmVmYmVhMWIzMjMwYTdhZDBhNTM5MDMxNjgyNzZiNWExMDY0OGFjMjFhZTU1YmNiMGJiNzQ0OCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmFhZTQ5YmFlNzNkMzFhMzk2Y2IzNTg5MjU4MjVlMzkxNGFkNTRkNmMwZmI1ZTQzNWYyYTcyODRkZWYyYmUxYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYjAzMTkyYWFlOGU2ZGIzZjk3M2MyMjYyODQyNDdjOWI2ODgxYWMxNTEyOGUzOGQ3N2JjNmMyNDQ3Mjg4NWZlZCJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L30-L138",
"version": "repo-lines-v1:sha256:da735745bc8b4d982752f5614f36d0bef93a6fe352c2695c43b2c93434ebf779:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA5LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIxYzI1OGI3YjRmNWI0YWY4ODYxOGQyODRiZDg4NWNlZmMzYjJkMTlkYTE5OTk5ZjdhMTQyNGJkMTA5YjIzY2YzIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJhY2U2ZTRmM2EzYmY1YjY4ZmQ0OTNlMjkwNGRlNTNiMmNmYTMyNDMxMDYyMDdhODAxYjhmZGU3NDNkZmFiM2U3IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI0YTM2NTM4ODFmODkyM2RhMmFiZjNiYWQzZjJiYWIzYmRiOGEzNjY5NWI2OTJmOWI5ZjZhMTFiNzVkODI5MGYwIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4In0"
}
]
},
{
"id": "claim_3740255f82db44d5960768217e4669c0",
"statement": "`AppModel` is app-wide desktop coordination state, while `WindowModel` owns state that may differ per window—including workspaces, selection, sidebar and search state—and registered windows receive shared services without transferring workspace ownership to the app model.",
"evidence": [
{
"resource": "repo://TFM/App/AppModel.swift#L36-L48",
"version": "repo-lines-v1:sha256:1f1a4c4ed6efe1ff110509ba5d5234e8c6ed2daf61023f3a1742f08e4c539da3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQzYjAwMzIyNmFiNjY2MjhjYzliNDFmOTQ0ZGIwNDUwNTBmNDIyOTA2ZjJjNmM1ZDU4NzEyYjU2YjQxZjQ3MGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVmMzkyNGUxNGRjMTM4NjZlODJlNGQ4ODk2ZGM3MDg4Yjc4MmI4OTIxZTM0OTY4M2U5OTE5NGI5NGRiYzA5ZjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzZGRmZjMwMjE5YjY1ZGI1MTg3NmJkYjJkYjIwMzJhMWU3MWNjMDM0Nzc4YzhhNjRjMGI5NTViMzcyZGM5M2QifQ"
},
{
"resource": "repo://TFM/App/AppModel.swift#L435-L483",
"version": "repo-lines-v1:sha256:66425b677043ad80e7539f1934c7f80b1ec165f96cfc5d7a3445f426cef38715:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiMDNmZDkyNGM2ZDY3NmQ2Y2Y4YzA1MGUxZWFjZDI4ZDMwNTE4NzU3ODIwMTViNWNiMTAxYzY3MTI2MzU1Y2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI1NmZjODJmYjZlYmU4YjJhNzY1ZjU0OTZkMjUzMTIzNDIwMTM2MDBlZjE0MTRiNWMwZDQ2OGYyZDFkYmE1MjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU1YTFlYzk2OGVhY2JmYWU2Y2VjYmU3MGFjOGFhNjYzZjExZWFjZjY5OTE3NTdlZDM4MDk3YWM1ZWU0MTAzOGYifQ"
},
{
"resource": "repo://TFM/App/AppModel.swift#L50-L116",
"version": "repo-lines-v1:sha256:f42357f9bf35b10d60fe8daaef9077c5f6da17ad900b9b0bb661e17cfa5eb1ed:eyJzZWxlY3RlZExpbmVDb3VudCI6NjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA3NDZjZjIyOTJiYzNmYzYwNWU0MDk1ZmYwOTQwMzNhNzE3NTU1NmFlMWQ4YzU4NmNiMzZjNDEzZTM1NDZiZTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4NjY3ZDE1NjU4NGZjZGYxNTY0NjJmMDY3OThmMjYzZDc1NTE2Yzg1ZWVkYTc3MmFhYzZjMjkyMzkwYzAxNDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYyOGM4NTE1Nzc4MjNmMWQ2Y2E4NmEyM2RlNDI2YmQ4ZDIwZjZiM2M2YmVhMDIzMDZlMzNiMDNlZWU4M2ExNTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3YzVkNTgzZDAzNDQ5OGMyMWE2MmNiMjE0MmVhMGNmNzc3YTU3YmI4NjU3NDIwYjc1NTRiZGI0NTcxMWEzY2MifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L188-L203",
"version": "repo-lines-v1:sha256:285d5010d326e778a3894b5a491496643929c899279182a6295339008e89ff44:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiZWEyYWFlNzM1MmYwOWMyZTg5NGE1ODRkNWY5YmMzNzkyOWJmZjIyNjk5MzIxYjMyMGY0MTMwM2E1YmNlY2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAwMDljNzJjMDIzYWFiMWYxZTU0NmQ0OGJjZjM5OTE2MWQzODFhYTQ0NmYyZTBjMDkzYTE4NDVkYzQxODhmOWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJiNTI4MTA3MjY3NzU5YWYzYmQyYzJjNDNkODg5OWQwYTJmNWVkZWU1NjE1NjVjZTQ3NjQzMjZhNTczOWVjODUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBhYmY5NjgwOTZmOGRiMTM1Mjc5MDA1MzAxNWQ2ZmI4MWRmM2EyMzExZjVmNDg0ZWI3M2MzNzAwNDYwZjg4ZWEifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L6-L12",
"version": "repo-lines-v1:sha256:385e37c29ac3360b6d6c13770600b7f05f500dbf4aae2166554bb47959e8cfd9:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjg2OWM0NjBiYjViODM0YzhmNzhjOGMyMTMyMDI1OGJlZmMwZWZkYTMxNmZlMTYzNjQ4NjU3M2FkOTIwYmY1OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjRhNTQ3NGNhNDJkZjJiNTlhZDgzNGVlMTNiMWI1NzNhOWE3OTE5YzU4ODU0NmM5ODgxYjk3NzkxYzBlOWI4MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNTcxZGE3NDM0NTdjMDNhMjQwNDRhMTk3NTQ2MGE2YzQ4OTllODBiNzUyOGUzMDRkMzE0ZDY3ZmU1NWE0MTYwNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjRlNjdhZDA1MjQ5NGIzMjM1OWIxZTVhNWY1NTIyZDk1ZDViYzJmMjY5NDg5ZmYzODY2MzJhZjUwYjI5MGZlZSJ9"
}
]
},
{
"id": "claim_4d8f0cdfed604a539181a840b57357ff",
"statement": "The macOS main `WindowGroup` creates a fresh `WindowModel` per scene but injects the same `AppModel` and SwiftData container; it also declares a separate externally-driven authentication window.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L146-L190",
"version": "repo-lines-v1:sha256:eb20fcc10fa3cc0f5740fa0fbbf0746859c1e4b7b431188ee4e3672fc48bae73:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxMDk3ZDRjZTdkZDAyOWU5OGI2YWFkMjViMDFiYzEzNzhjOTdlMzA5YmRjMDY0YTM0ZTI2NTQ4MTFmMTgxYWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQwMmQ5OGU3M2M3ZmQxZDQ4ZjUzNjdjZmY5NGFlNGYzNDlhZTYzZmIyMWRiYzkwZmYxYjZhNDViYjNmOWQ5MzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjZGEyMmE4ZWYyODNjOGFmOTJjZDlmMmY2ZTA4MzdkODg4MjdjYjBkZGM2OWNlNDFkMTAwZDFiOTdjYWM5MmMifQ"
}
]
},
{
"id": "claim_988820a5d0344307af4a55732527e55a",
"statement": "The desktop native window coordinator registers and unregisters each `WindowModel`, handles workspace transfer/new-window requests, preserves system-restored geometry, and closes the window model when its native `NSWindow` closes.",
"evidence": [
{
"resource": "repo://TFM/Platform/MainWindowCoordinator.swift#L164-L198",
"version": "repo-lines-v1:sha256:39c33819ac6c901dc92d22c529ae1be50ac338f0b31e3549ed59dde26117cedf:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImViNzczMmVjOGVkYzNiMmY0ZDYwNjFlNGEzZGE4YTVkNDVmODE5ZWM0NTJlYTJkZTYzZjUyYmE0YWE2MjAwZDQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU5MDcwMTcyYjVmYzFkNTQ4YjhjNzMwMzk5YWRhYWEyMTRlMjM1NTdjZjQyNmU3OTJmMThmMTE5MjM3NDI5ZjkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQzODlhNTliNGY0MDI4MWFhZDFlM2YxNmIwMmE3YWVjMzVkMjI1YzczOTZiYWE1ZmNhMTM0NzcxNzA1MDcwZWEifQ"
},
{
"resource": "repo://TFM/Platform/MainWindowCoordinator.swift#L216-L245",
"version": "repo-lines-v1:sha256:20497ec4b23f0dbd500bbedb9ece84ed40049b79733a01d7b08aca7aba36ed71:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkyODZhNmM2N2VhNDQ3M2I4YTkyZjk3ZWViMTAwOTNhYjZjYTUwNGRlNTkxMzQwZjY5YTI1NDEyYzJhOTNhZDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ4ODllZDk4Yzg4OWFhOTViNTdiYWEwODk0NjI0YmEyMDBkMDg4NWQ0NDY2ZWQ1ZDE3MmEwOGY4NzM1M2ZkY2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU1NGZlOWE1ZDY4ZmYzY2I3MWYwYjhmYzIxNmYwY2JlM2FjNjM2OThkYzkwOTZlOGI2YTA2NDgxMzJmOTQ0OTIifQ"
}
]
},
{
"id": "claim_5365b20c970945918fcbd2cc865bc5c6",
"statement": "macOS termination asks the user before quitting with pending external edits, then performs idempotent app-wide cleanup that closes windows and cancels/stops runtime services; the AppKit delegate replies when cleanup finishes or after a three-second fallback.",
"evidence": [
{
"resource": "repo://TFM/App/AppModel.swift#L669-L693",
"version": "repo-lines-v1:sha256:3fdd3e3a61b4f0fac27a94144beb60ee81bea2eb973de02975ed94e17607bcf9:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiNmE1OWU3Nzg2NmU1MGRiZDYxZjA5ZmQ1YWM2MjQwN2Q0ZGVlNjdkNGIyNTJhNDExYzRhZTEwZWNmMWQwNmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzODNlN2M2MmI5ZmI0ZGU3YjNjNTc3ZmFkNjNiOTYxMGRlZTcyNmI4NzljYzZjN2M5ZjYzNTljOTU5YWEwODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzNmM5MGE0M2ZiOWQ0NDg2NzI0NmE0MzY5ODk4YWZkOTFiOWUyYjM0OTZmMjU3OTg1YTk0MDFhZjY4ZDI1YWYifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L331-L380",
"version": "repo-lines-v1:sha256:dba035b03cf3758c5dd56a198c82d72e009987583daf5432a41a80018be9c9f2:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg2MmZlMmQ0YmFjM2JhZjAxN2NiYmY5MmFiMTcwZTQ0NWExMWQxNzYyODBkZDEyOTdjZmM2ZDQxZjI2Y2NlMGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdlMjAyMDc0MmMzM2IxYjkxZWIyMjYxNmJmYTg4NWMxNjQ2NThlM2Y5YzAzZDNkODZhYzllMjgwMGRkYmNhMzcifQ"
}
]
},
{
"id": "claim_15f8482e2b68459c99b860197c4a5195",
"statement": "`TermindIOSApp` creates one `MobileAppModel` startup result, selects testing or live dependencies from the XCTest environment, injects the shared model container into its `WindowGroup`, and presents an unavailable-data view when initialization fails.",
"evidence": [
{
"resource": "repo://TFI/App/TermindIOSApp.swift#L5-L33",
"version": "repo-lines-v1:sha256:1574c44f26f386fca5834af375adbea23b9471aaca384b9aa647006e94caec2e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0MDI1ZTA5ZDBlYTM3ZDMyNTYyMDVjODkwYTg5YjU0NmE0MDcwNTg4MDJmZWUyZDY1N2Q2ZjJmODg5MzllMTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwOWRlZDA1YTMwZTBiMDk1ZjI3NWRkNTcwMzRmNzU2NTgzNjBjOWQ4ZWIyNTg3NjNjNGI0MDMwYmM5ZGRjYjEifQ"
}
]
},
{
"id": "claim_b1cae51b3caa4541bddb49f0d857c3b6",
"statement": "`MobileAppDependencies` is the mobile composition seam: live assembly creates one logged `RemoteConnectionCoordinator` shared by workspace connection and metrics services, while testing assembly enables in-memory operation and injectable platform services.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppDependencies.swift#L7-L61",
"version": "repo-lines-v1:sha256:906eb5af1cfd06ac4eebb7a6570af4fda6ab91957ee714f84f703a0491eeeb97:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFlNGI3ZThmYTBlOWU0NjE2ZGYyYzk2MzVhZDY1NjEyYTBkMzYxZTdjMTQxZGYxYjYwOTMwOGM0ZjY2ZGVjN2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_bd6009649be84c4291e149d30476e3a3",
"statement": "`MobileAppModel` owns the mobile app-wide container, libraries, sync, assistant, metrics, transfer, forwarding, workspace registry and descriptor store; production persists `Termind.store` under Application Support while in-memory/test modes use an in-memory container and omit production sync.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppModel.swift#L104-L220",
"version": "repo-lines-v1:sha256:0ce45f41f79ef0529cdaa4bd371d5d6378921ead85d0b6994e50f54e35f2011b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE3LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJhZTFlMGE4ZDBhODljNDRhNDI0MjM4Yjk0ODVjOWJmZGVlMjBkNzNjNTgxYmExMzljMTgzYjExMGM1ODdhY2I0IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJmY2I3MmJhNGQ5NjQwZDkyNjNiZTM3MGViYjcyZTM1ZWQwODBmNmUzNTY1NTIwMThkYWViYjJhZmZiN2FmNzVkIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIzYmI1MzE1NmEzZGIwOTA3ZmNiODQxMDYyYzY3OTY3YjMzMGNiOTU5NWY1YjVhMzNiOGVlZjU2Y2U1ZTM3M2YzIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI0ODdhZTQyM2M0ZDA5N2YwYmQ1OGQ1ZDIzMDAyOTg0YmUzMzA4YTM0MTAxMTI3ODFhZmEwN2FmZGEyMTY5NWRhIn0"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L35-L84",
"version": "repo-lines-v1:sha256:9b7bf812883d719506d6d5770e57352438a10f5b18c25e4096ffe4fedf33a8b6:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJmZjliNTBiNjc3MTVhYTVmNjlmZjNkN2VmZjcxZTU4MjNkOWI2ZmE5ZWE1YzE2OGJlMGJhNDdkODViYTg3YmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI3NjQzMTk0ZmY2ZTJiNTNhMjZmZGI3ZmUxN2VlMWNjM2I1NWY3MjMxOTAzOGE3MWRjMjQ5ZTdlNjNjODJhZDAifQ"
}
]
},
{
"id": "claim_e07596d3b8dc45eb99e771505942be17",
"statement": "Each `MobileRootView` creates a scene-local `MobileSceneModel` for navigation and presentation, reports its phase to the shared app model, and publishes it as a focused scene value; its sidebar-adaptable tabs retain per-feature navigation stacks.",
"evidence": [
{
"resource": "repo://TFI/App/MobileRootView.swift#L4-L39",
"version": "repo-lines-v1:sha256:107885cd61c384831f96818970b307dab47a74153f16743478683c50734e4691:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBmZmQ2NjgyMzJiMzJmMGE2ZTZiMmE3ODI2MzE1ZmY0ODEyZmQxNTVkNzI1ZjM0ZjA0ZGNiOWY4MGU5ZDA1MWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkOTY4MDU1YmE3YjlkNGU0YzBkYmMzMDczNjYzZDM0M2U5MTg2ODliZWRlZjc3MTI0NDRmYTc4YzNjNGJiODMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE3ZmYyYjcxMGUxMzQ2NWEzZmU1MjE2MzA1YjkzODIxZDZkMzNmNTJmZTI5NTBjMzdhYzgwYjJlOGQyZDAwYzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI2MjIzODhlOTUxYjRjY2JlM2I1ZWVmOGMxMTg0MDA0MjFkNzJhNjg5Y2EyZDFiZTUwNDFmNTExNDA1N2YyN2IifQ"
},
{
"resource": "repo://TFI/App/MobileRootView.swift#L49-L72",
"version": "repo-lines-v1:sha256:1f9048541f568bea75db7cff31aa0ed19d9f4c25d5cfa707c4a57b1e8848f550:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwNmIyOTNhY2FiZjI2YWJjZmZmNDhiYzNlZmVkZTIzZmEyMDFiYjA3MDMzMDMxYzcwOWVkZDc2NmQ1YjQ2NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcxZTQxZGU0OGM0NWIxYTkxYmVmZjAzYmNlNmQxMjhkYWIwMDE5MGE3NjI1YWMxODE4NzAzYTA0MmQ2NzViODUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM2MTlhZGM1NjcxMTNjZmI2YWE4YTM2ZmI4N2U5ZWI3N2FhZGFlNjU4MDc3ZDRlODQ0NGNkNGM0NWM1YTFiNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE0M2M5YmQyMmFhOGFjOGQ2ZGU3MTU1YmVjMTljYTgyNzgxOTliMzBkMGQwYWU4MDdlOTY0MzY4OGZmZTdkZGUifQ"
},
{
"resource": "repo://TFI/App/MobileSceneModel.swift#L9-L39",
"version": "repo-lines-v1:sha256:10dd34203f9f3747730e12c9536f7ba843fca90976d0e3dd1adf6be19ebede5f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdlMzBiMWNmYzNlMDdhNWQzNDFjZTY5NjdjZDYzMTI4MWQzYzQwYmYzMWQzNTI1MTM2M2MyNzYxN2NiZmIwMzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkYTMxMmZlMTU1NzA0MzkzMzRiYzkwMGRiNDQyOTUzNjJmMzg5ZjVjNmVkOGU0MTViODIyYzBmN2YwNDJjNDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliNjdkY2Q0ZWY5ZGYwOGQ4MTFkZDQ2ZmJiZmVhZDk5OGVmNzYzOTM0M2NkNTdjMmZhZWFhOTIyYTI2YjIwNTMifQ"
}
]
},
{
"id": "claim_449cc2faba114c37bc4e51a189667299",
"statement": "Mobile live workspaces are app-wide: `openWorkspace` reuses an existing instance or publishes a newly constructed workspace before connecting, allowing multiple scenes to select one live workspace without duplicate initial connections.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppModel.swift#L584-L600",
"version": "repo-lines-v1:sha256:4695fd57bfd1677ccfbaa7ef3e23c87ff6c636ab1d93fe889299f5b87723ace0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA4YjM0MjE2MjYzZjM3NTkzNDUyZGMyNDNlYTQyNTQ3MDJkZTEzYjI0OTliYTQ4ODYxODk2NTI4NGNmNDQzNmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ1NWE2YmQ5MDhjMTBjOGM0MzYyZDBkNDAyZDI0Y2JkMDY2MDgyYjNjMjQ0N2YwZTA0MjZhYjEzY2M4NDc2M2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY4ZDgxNTIzY2NhNWZlYmRiNWVhZDU5MDU2NmU5NjhlMTVkOTViZjRlODNlZjNkYjExNmJhOGM1NThhNDY0ZDQifQ"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L677-L701",
"version": "repo-lines-v1:sha256:25da6d1276fcd4f2d70d3d960f0f81aec17035b0f078a20b775db3579cc06321:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxODI4YWZmNmM2MDJhZDBjNDkzM2FhYjA1ZmQzZTgzOTVmYmI4ZjY3NTI1OGU4NzBiMmE4MGY5MjhjYzhmZWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyNGNmZGM2MjI3YzViMTBhM2MyMmRkNjNmNWFhMDg4N2IwODRjNGUyNTJhN2Y5YzU0M2EzMDEzZTY3NjAyOTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
},
{
"resource": "repo://TFI/App/MobileSceneModel.swift#L141-L173",
"version": "repo-lines-v1:sha256:046edd6f6b167f8f15d96ba41e370795db4c16457cdeea6f78d28f59cf9e7ae5:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjczZjY3MmNkMDk3YWMyMjczZDY2N2Q1OGE0OGRhNTM4ODA0ZjI5NmUzZThhMmU5NmVhMTg3MmMwN2IwZTc1MDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhlNWQ3ODg1MGNkODkxODM4ZjUxYzk1YzllY2FmZDRkZTU0Y2M1NjkzOTNjZDM4MDA1YzQwNzlkMDg0Yzc3ZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNjNjA5ZTE4OTFiNTYxZjIzOWZlODAxNDMzNGFlZDk1NDk1NTczMGY2ODVlZjAxNTEzYmQxNzQwMGNhODI3NTYifQ"
},
{
"resource": "repo://TFITests/MobileAppTests.swift#L1442-L1480",
"version": "repo-lines-v1:sha256:2439296f96421e4c851e8967430d0ff1414fbe1d0cb8c1488c854946e13ace17:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkyNjg1Mjg5MWQ1ZjVjNTVlNjY5YzQyNjRiNzc3NzAyOTVkMDcwYTY0YTVlZDAyZTc4ZmJiYTJhMTk5NGFkNDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYxYzcwNGY0MzY4NDQ0ZDNlNGEzODU3OTA2YmU0NjIwMjA0MDI0M2Q5MGNkZDgwYTYwYzMzYTc4NTY0ZWJlYzkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjczNzhlZjkzMGE2OGVlNWNmZTg4Y2NlMTZlOWYzYjkwMzBhNjExMzYwNzg2OTI0ZDM4ZGU5MzJlZGM3NjI0NDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJiNWNiMmQwMGY5Y2FiODA3MjdkZDE5YjRlNWIwZjVhZGE5YzRiYTkzZTVhZmZhYjc1ZDI5N2NkYzNjYTk3NjIifQ"
}
]
},
{
"id": "claim_f5346484cdd743e09ae538b8754cddd5",
"statement": "Mobile cold launch restores only saved workspace descriptors, not live sessions: it loads valid descriptors, starts with no workspaces, clears live activities, and opens/connects a descriptor only on demand; descriptors exclude runtime command/path state.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppModel.swift#L345-L353",
"version": "repo-lines-v1:sha256:1d57ee858a60500f68e9bdbf3fba3cfb6613a303d9c65a290a7bad433bf7fcef:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNzUxNjg0ZWYwZTk2OGFjMjk5MjA2MGY0MmEwZWM0MjI1ZDZhYjc5MWI4Mjc0OTNkNTliNTkwNjI2OWJhODNjMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYjFhMjgzODcyMjk0ZTkxOGM4MTYwNzVlODNmNGUzY2JiZjBlNDkwMTcyMTU2ZjA2YWNlOTNjYTI2Zjg1NjczNSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZThkYTY5NWUzYTVlMDMxODgzMjMwZWM3NmMxOGY4MzY1ODI2MmZkZDYzZmI3NTlhNGE2YjVjYzAzZWNhNWQyZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWYzYzJiZTljODg4NmMyYzVjMjgyNjM5OTgxMGZlNjIwNjRhZmFlYTI3ZGYxM2Y3NDk4YjgzZDIyZWU4MGM4OSJ9"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L602-L620",
"version": "repo-lines-v1:sha256:d648ce6e91c032555378e00f846e7665eb7c8832d40f2b1a34c64bb082cd1f8e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE4MWU5OGE2NTQ4ZjM3ODk4ZWRhZTdlNTI2MTVhNTVlN2U1MmMzMWRhYzNmODE4N2NhNjBhNGYxZGM0NWU0YTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4NDg1NDZhYzY0MDljOTA2MmY1NmFhOTZjMjljMWMyZmJhMGQ0YmQ4NTZlOTkyOGNhZjgxNTcyNzk3NmRiNzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY1OTRkNzNjNzQ0ZDE4YWVhMDM4MjgzOGE5YWFhYzVmMjJmNjhhNTljNTc4ZjJlMWM1OWIzYTQ0NzA5M2FhY2EifQ"
},
{
"resource": "repo://TFITests/MobileAppTests.swift#L1421-L1439",
"version": "repo-lines-v1:sha256:75e1a0a8bcca7df32e065b7c55332a2b6da3fa6213495d8b124dd90df28b08ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFkNjFlYTM5MmIwYWViMDc5OTViYjhjZjA0ZjQwMjA2YzcwODVkNjU2YzE1N2NjMDIxZTY2OWMxYTBlMWM5YWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyZmRmZmY4YjRkNzFkNzdkODhmZDc2NWQ2MjhkMzI5NmRlYjY3NjljMWM3NjFmNDRiMzgzN2Q5OWVkYWE1MWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyZGZmM2RjZTkwMTYzOGNlMjRkNDc0ODNkYmUyYzE5ODQzMmY2ZWQzYzI5NzU2ODI4YWEzYmExYzgxZjk1YTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc4NTMxZTQ5Yjg5YzNjN2IzMWMzZTAzMmE5Yzk4NWIwMzkzYWEzOWM2Y2UxZWE2NjU1Njk2YmNjMmFkYTNjZTAifQ"
}
]
},
{
"id": "claim_9b627f261e1648d8a6a30ed16515bf1f",
"statement": "Mobile background behavior is aggregated across scenes: only when all tracked scenes are backgrounded does the app suspend sync/monitoring and begin a finite background task; expiry suspends workspace, forwarding, transfer, and assistant runtime work, while an active scene resumes existing workspaces and foreground services.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppModel.swift#L491-L536",
"version": "repo-lines-v1:sha256:f39329e8c7e533ceaef89590620b417dfffec9d46ddbf28a15a29bc868a69396:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ1MGZiNmUwZThhYmY3YmNiNjdkODIzMzJjMmVlOGZlNzY0NzYzZDFlZjA5ODc4NWM3ZmM4Y2Q1Zjk2ZmRkOGUifQ"
},
{
"resource": "repo://TFI/App/MobileRootView.swift#L49-L51",
"version": "repo-lines-v1:sha256:6facd243b08481babb75f6282b56d53f1e0165402144532ee098000deb645e4c:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzA2YjI5M2FjYWJmMjZhYmNmZmY0OGJjM2VmZWRlMjNmYTIwMWJiMDcwMzMwMzFjNzA5ZWRkNzY2ZDViNDY1YyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMmI5N2I4NWVjMDNiMGRhMGM3YWYyNzU2OTkzYTE5OTY2MDg4NGI3MTgyMWEyZDRkZDg3ZjgyMzRlODU1MWZiYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzYxOWFkYzU2NzExM2NmYjZhYThhMzZmYjg3ZTllYjc3YWFkYWU2NTgwNzdkNGU4NDQ0Y2Q0YzQ1YzVhMWI1ZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDVlMmZmMDFmMDRiNTlmYjYzMjQwYWU1ZTQ2OWVhYzMxN2ZkZDhjNTljNmIxMTA0MjBiODQ3YmNlZjJlYjVlYyJ9"
},
{
"resource": "repo://TFITests/MobileAppTests.swift#L318-L365",
"version": "repo-lines-v1:sha256:a931ada6538eda81068f2cb53aa5b6af5e5cffe259a41873160448d469d86c7a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiZDFmNThmMjIzZDQ1NjI2YzYyY2U4NDc3Nzg4MjI0OWNkMDdjMzM4MzQyYTE0MWRhYWRhMzkzMjUwNGY5NTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU5MzgwYmQ2NzA4ZjU3ZTE2Mjk5NmM5OWQ4M2VkZTA1Njg5OTQ2YjRlOTZhYTgxYTAxZmU3YTU2MWI0OTM5MWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzY2QxZDE2MWMyZWJmNTNmZjg1NjNmM2Q5MDdiMmM5MDJiYzVmZWE1MThmMDcyY2UwNmU2MjI2NTQwMGIyMmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI4MjZjODhhNmZiNTA3OGEyZjViYTNmZDdjZDM4ZTZkOWQ4ODQ0ZTM2NTliMDBlNWFhODRiNTc5ZTliMWRhNTcifQ"
},
{
"resource": "repo://TFITests/MobileForwardingLifecycleTests.swift#L62-L91",
"version": "repo-lines-v1:sha256:d25147a779dcda58165ef9df969487f07bd86a6888e99c7dfe3221578e78f969:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxZjdmM2ViZmViN2ViOTI0ZGFjMWUyMzBmN2JlYWQ2MTkzNWFlMDIwMWMzMTVkN2QxZmM3YTkwYjQ2NDFkOTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZjYjUxYWJjMDhjNDdkMzE5YTA2YjI0ZWI2NWUzOThlODA5MTg2ZGQyODAyNjNlMTYyZDE5YmMzODE4OGYyYjEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhmZmQ3ZGYxZjIyNzM4YzcxN2EwNjNjZWExNDJmNTQ3NDczNGM0YzBjZjQzZDdkNzljNzg2MjMyOTJiZDAwOTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEwZjg0ODA1ZWUzNmE1ZTZjNmFiMTRjZjEyOGM2YzY4NTE4ZWM5YzFkYzliYmFmZGZhM2UzMjc4NzU2ZTA4MGMifQ"
}
]
},
{
"id": "claim_f89939b05e164dcea4b8f0869d4ca6cc",
"statement": "Desktop external SSH/SFTP/Telnet URL handling opens temporary unsaved workspace/session state in the target window; Telnet URLs that carry an advisory password require explicit confirmation before opening.",
"evidence": [
{
"resource": "repo://TFM/App/AppModel.swift#L761-L821",
"version": "repo-lines-v1:sha256:1c6df32dff348711da79f105fd6d28d5f4861c458b11f6bdb83e76ce91138697:eyJzZWxlY3RlZExpbmVDb3VudCI6NjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjMjYyYWM1NzdlODU1NGNjMTM1M2E4NjUxMjk1ZGEwYTgzM2EwZWYwNDVmNTVmNDU1NDIzYWQwNWU0MDBkNzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIxZTZhN2E4MjNmMzRhZWJjY2E1M2M0MWFlNjBmNmJkMGFlMzBmNDYwOTFjZTUyNDU0Mjg1YzlhNmI0OTRhZGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdmNTE0NzI0NWM5NzEzNTg0Y2Q3Y2VlNWM0NGNlODk5MjIxNzZjZTY3NGRhNTYxOGQ3YTU1NmU2ZTA1MTBjZDYifQ"
},
{
"resource": "repo://TFMTests/ExternalConnectionURLTests.swift#L9-L45",
"version": "repo-lines-v1:sha256:1f318118564e3c8a1ceac6136bf9c344ae39976ff5793b9dd39658561f5381d0:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ3ZThkZDgzNmY2YmU5M2Q1ZTk4YjZmNGM4ZjZkNTFjMGNmMjBhOTlhZjMyYzQwNTUyYzE3MDRjODQ2M2ZkZjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIyM2QxNzZhYTU5ZjhjMDRhOWVkZjg2YTRiZDA1MDk4Y2FlMWUyODFmMTkzMzBjMWI3NTc4OGFkMDE2YWNmYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,154 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:95ae2f50f3a459aa6c5502c11c301d3783446a4c86117684b7d4092e7e88a15f",
"claims": [
{
"id": "claim_085ce722f39f48eea75366ec3b3f7554",
"statement": "Termind is organized around shared Domain, Application, Infrastructure, Remote Infrastructure, Persistence, and Presentation frameworks, while TFM and TFI own native UI, platform adapters, and lifecycle; shared modules must not depend on an app target.",
"evidence": [
{
"resource": "repo://AGENTS.md#L5-L13",
"version": "repo-lines-v1:sha256:5bf8f722418eac38057a37c2f664f7f78762650fe7e8d0d55318d6aa97bcaba3:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjM4YmQ4MDg4Y2Q5OGMyYTJiZjdjZWUwMjg2NjU0OTRlOTA0MGI0YmIzNTBhYjMwY2VjOThmMmZmNDlkMjUyMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZmQxNDRhYTY2MzdkYjRiY2Q3MWYxZmE2NDc0MGI1YTJmMDk1YzZiYWYyM2JlOWU1NzJhMGE4Y2VkODJkNzIyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmQ1ZDk4ZDMyNTIxNzM5OGEyYzA4Mzg5YzFlMjg1MDQyMTA2MDQ2OGUzYzI5ODdhODRiMDFjNDM0ZWU2ZDcyZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWQwMTdmYTAzMWI3MzUzMDUxZTQ5YWQxNjI0YTFhNjBlMjAzYzhmYTljN2QxYjE0YjY2ZjU3YjlkMTU5Mzg5NSJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L13-L23",
"version": "repo-lines-v1:sha256:a2f25cec3b82d39c9769736e5b4cf3bf18725df93febafa7c4b98611bf00c26e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0Mzg4ZDgwNDRkMmQ0NzQwNmY2YmZkMjkxZDY0NGM0NTllMzNjYmE2YmFmMjhkZTY2YTY2MzNhM2ZjOTM3ZDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1ODI5NDE4N2JlY2IzNDk0ZDY5NDIyYjc1ZjBjY2NjMzlhNjI2NjQ3MjNlNjZiMzk3NDNiYmNhZWY3YTg3NDciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRhZDk1YTk4OGI1ODk1MmE3M2I0YmJiMmZiZTEwMjRiZjYzMTI5NjdkMTg4MDhkN2ExYTViMTEzNjExNTA3MDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE4YmUzYmQ3MjdjOWYxMTNjNWMyODU1ODIyMGUwN2EyZDE0NzEwZWJhZTM3MjE3ZjUzYmQ4MjAwOTQwODcyZjIifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189",
"version": "repo-lines-v1:sha256:0d3b3a4cd81181b5228a2cfa0b6a89f30ffcaa8a77112e9c8ed819cc29a59663:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ3NDI5ODQ5YmU0MTZhMzMzMmY5NTcyYmY1NTM5ZDkzOTZjNDEzMjY1MWE4MzhiZGRhZGIzN2IwNzg1OWViMmUifQ"
}
]
},
{
"id": "claim_07d6c15b703242fa94b68c4f347d23a1",
"statement": "ArchitectureBoundaryTests enforce dependency direction: Domain cannot import platform, UI, storage, security, network, commerce, SSH, or terminal frameworks; Application cannot import UI, persistence, or implementation frameworks or construct selected concrete infrastructure symbols; Presentation cannot import platform UI, persistence, or Remote Infrastructure.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189",
"version": "repo-lines-v1:sha256:0d3b3a4cd81181b5228a2cfa0b6a89f30ffcaa8a77112e9c8ed819cc29a59663:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ3NDI5ODQ5YmU0MTZhMzMzMmY5NTcyYmY1NTM5ZDkzOTZjNDEzMjY1MWE4MzhiZGRhZGIzN2IwNzg1OWViMmUifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L75-L106",
"version": "repo-lines-v1:sha256:11f74fcd104993cd2feab9af4770f39538b63efcdefeeb85a9faf48e46c50f74:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk2ZThiMDFjOTI0YTg1OTFkMDY1YTNiZWE5M2Y5Yjg3MTA1N2MzZmE2NzRiYzk5N2JmMWU1ZGExYjRlNzU2MWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ"
}
]
},
{
"id": "claim_04df7977ba1a43bfba0b2585bc5f185a",
"statement": "Persistence exclusively owns SwiftData models, versioned schemas, migrations, and ModelContainer construction; the test suite rejects @Model declarations outside TermindPersistence.",
"evidence": [
{
"resource": "repo://AGENTS.md#L7-L11",
"version": "repo-lines-v1:sha256:eb1d08366705afdc99b54adcffa378299221d4d7be416d22cc011f6a15dbcfd2:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOWM0OTlkYTUxNTAxNzdiYTFlNzljZjc5YTM0ODFiMzM4NmViYmJlYTU4MGI3Zjc2ZTBjZjUxOTNmYWE5OTFjYiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYjEzMjhkOGFmMzQ1YjI3MzczOTBkZjBlMWYwN2I1ZmZlYmE3Y2IyZWIyNzZmZDBiMDk1NTg5ZmVkZjgwOGE2NiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiODRkOWIzNTZmZmVmMmJmZWFiZmM5MmQwM2EwMDkyMWY3YTk0OTUwMzk5Nzc3YTY1MmFhZTZkNmZhMTcyZTQ0OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMmM0MzRhZjQzYmUwYTA3MjE2NzE5ZjBkMjg5MjdhNjkzMzNhYmJlZDhiY2U0MWZmOTA4ODM2ZDIxNDk3NmFjNyJ9"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L4-L21",
"version": "repo-lines-v1:sha256:75bc34d3cd5e480f2d8ea11fb1e38f4cfdde54db5adfccbc5def8238f426b623:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzMzA4NTlkNjgzODAyNWFiM2Y2NjIxNTU5NWM4N2JiZWI1ZDVlMDlmNTIxMjk3YmY2MzI3NTUwYzgxYzBjYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4OTUxYTVlMDA0MTE2ZjBmM2Y1MzVjODgxOTBiNmUwNmU3NGFmZGZlYjU2MTc0MTA0YTIzYzQyZjJiYTNlZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L191-L206",
"version": "repo-lines-v1:sha256:f8c236519e8486d9e23370a1125780885a560563104317d8b0667fde12b5c048:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM5YjJkYjM3YThjY2FiMDIzMTkyOGUwZGY0MzcxOTc3ZWQzYzQwNzBkYTlkMDUwMjEzMzQyYmMwMmQyOGE0YWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyMzk2YTZjMGFlNGEyMDI0YjE2OWE0NWY3MjdmZjYwNWE4NDI4NjdkODJlYjJjOTNkYmNkNmVlNDg4YmExYWEifQ"
}
]
},
{
"id": "claim_549399d4a1fe49c9a74f0a574a669d2c",
"statement": "Platform composition roots choose persistent versus in-memory storage and retain the ModelContainer, but use TermindPersistence.makeContainer rather than owning the schema; desktop fails startup when the local database cannot open while iOS surfaces an unavailable-data screen.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L4-L21",
"version": "repo-lines-v1:sha256:75bc34d3cd5e480f2d8ea11fb1e38f4cfdde54db5adfccbc5def8238f426b623:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzMzA4NTlkNjgzODAyNWFiM2Y2NjIxNTU5NWM4N2JiZWI1ZDVlMDlmNTIxMjk3YmY2MzI3NTUwYzgxYzBjYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4OTUxYTVlMDA0MTE2ZjBmM2Y1MzVjODgxOTBiNmUwNmU3NGFmZGZlYjU2MTc0MTA0YTIzYzQyZjJiYTNlZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L126-L126",
"version": "repo-lines-v1:sha256:fb0eb95a9489d07f13bfc5dd8a79a4ea9a3c8e5ecb77e91490982cb9490b92ce:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZmIwZWI5NWE5NDg5ZDA3ZjEzYmZjNWRkOGE3OWE0ZWE5YTNjOGU1ZWNiNzdlOTE0OTA5ODJjYjk0OTBiOTJjZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZmIwZWI5NWE5NDg5ZDA3ZjEzYmZjNWRkOGE3OWE0ZWE5YTNjOGU1ZWNiNzdlOTE0OTA5ODJjYjk0OTBiOTJjZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmFiM2M4YmNlOTM0ZTMzMTZjMDVjMGI4YWFhYjJhZTg4ZTI3NDM1Y2NkODU1Mjg0MjVjODBkYzViOGUzMDdhOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDNhOTkxMGRkNDRlMTA2OWExY2VkMDFhZTMzOTk3YzNlMTU0YjcyN2U3YzczMDg0MjMzODdlYTQ1NzlmYmY2ZSJ9"
},
{
"resource": "repo://TFI/App/TermindIOSApp.swift#L11-L30",
"version": "repo-lines-v1:sha256:da8be22039112fa704351fb896f9a2ced4d1600f566c8cd5afde7aeac3066350:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhiY2M2MTFhZjIzYTkxYzNiNzI3ZDBhY2U0ZGUyMjI0MmZjNDkwNmM3MTk0YTYzNDkxOWI2NWQ3MDNkZDAwYjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNmYTc4NDM4ZDRhOWM4YzI5OWQ1NmJlNDRmNDNhN2Y1YWQ5M2FjYjRlMzllNzI1Y2YwMjYwYjY0OWQ4NjA5YWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjllYmU5ZjVkMjdiOGY2ZjAyMTc1ZTAyYWFhYTJlMzI0YjM0NjVkODMxMmM4ZWVjM2I4ZWQyOWRmNTkyY2ExZDgifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L137-L139",
"version": "repo-lines-v1:sha256:7e521f0009c7097b3075811418a0f0975f3a229ce9bb3012a58b7cd360f45681:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTc0MzYyN2VkOThlMDJiNTc4ZjUyNjljNzYwZWU1ODRlZTU0MmMzZTNjOWE0NDA4OTFjZDE1MTYyNWE1OWRmNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYjk1Mzg1OGIwNGQ2ZDU2ZTRkNWMxMzQxNThmNDA4NDRkNWRlZDMzMzliMWYyYWZmZjFkMzcwYzVlODUyN2Y1MyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWE4YzE5YmU1ZDgzZTVhODY3NzY1ZTdiZmJmZDg3YTA2NDBiYjRjOTk4Yjg2MTIxY2U3N2U1ZGIxNzUwNDAxMSJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L30-L39",
"version": "repo-lines-v1:sha256:8adecd981086eaed1cad0903e82917b4d86a8e9d6e35d0314bcbb752f450f95d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjMjU4YjdiNGY1YjRhZjg4NjE4ZDI4NGJkODg1Y2VmYzNiMmQxOWRhMTk5OTlmN2ExNDI0YmQxMDliMjNjZjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZTg1YmI2MTQ1ZGM4ZDE4OWJhMzEyOTRhNDk4Njc0ZjU4M2RlZjE4ODIwM2JiZDJlZWVhYWQyN2Q3OTNjYmEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRhMzY1Mzg4MWY4OTIzZGEyYWJmM2JhZDNmMmJhYjNiZGI4YTM2Njk1YjY5MmY5YjlmNmExMWI3NWQ4MjkwZjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQxMmJjZjU5NmJmOTk3NWM2Y2ZhOTU1NWJhZjAwMjBiZmM4OWFkMjA1N2U2YWNmNzQ3NzJjZTJlNWIxMDQxMTAifQ"
}
]
},
{
"id": "claim_e8a8ed759cf8492e9a8ffd0182466419",
"statement": "AgentKit is a separately versioned remote Swift Package pinned by Package.resolved; Xcode uses that resolved package rather than a sibling working tree, so cross-repository work requires an AgentKit release followed by a Termind dependency and resolution update.",
"evidence": [
{
"resource": "repo://AGENTS.md#L16-L18",
"version": "repo-lines-v1:sha256:79d9222951afd1cde2967f4987b4aa7b4347f1510f1fc4d1141010690b9c8bff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGI2ZWFiNGFjNWIwNmRiMjY5NmQ0ZDUzZTJlN2YwZDE3MzhmMWI3NTAyY2UyZWY1YjcwMzIzZjg3NjdjYTllNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRkZTk1MTMwNGUxYWVlNjRiM2IyYmY3NWZkMzI2YjAyZGM0OTE5YjlhODM4MGZjZTY1YTAyY2VjOTE3MzdjMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWM1NjRmZjMwNzY2N2QwZTgzMGJkYjkxYmY1MDYwY2FlODNhMjc2NzRkNTU5NWNiYTU0ZGMwNmQzNmE2NWMzYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWYxZjNmMTg5YTBiZTIyMGIzYjA0YmIwYzc0MTI2OGE5MzE4OGU1YzY0OTMzZGUyNzU0YzI3ZTZkYzRmZTE0NSJ9"
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj#L2837-L2844",
"version": "repo-lines-v1:sha256:444f908545e708b1d395265e4292e5529193fc19d4f609c8b5e06f6d68e13abe:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDhlMTQzODY5ZWI0MzVjMzZmNTljZTI5N2IxYWYxNzc3NThjMzVhNzFlNzJiMDQ2MTY2ZjkzNTNkODcxM2E3MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzYwYjg4YTA1ZDViNTM4NDc2MDIyOWJlNjA1NzJmZTYyYjFjMjljZGM1N2VkYjVlNjk1MWRhYTRmZDQ2YzgwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzExMTg1YzI4MDExZTZiNWFiYjU1YzRlOTQ5MjMyMTkwMzE1YWFmNGZhYzU4MzhhMDFjMWZmNTQyMjgwZmFiOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2M5YzA1MzMwYWQ3YTFmNDVhMmI2NDU2MTQ4OGZmY2NjZGY5Yjc3YzZmMDA0ZjBkYzRmNTBiOWRhZWFiYjdmNyJ9"
},
{
"resource": "repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved#L5-L11",
"version": "repo-lines-v1:sha256:2893ec786d107632932b507dfecf16a8152af8508dc9ddc629aaf66178d75316:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTFmYmFmZTBlNGFjY2NmMjk3ODM3MWMwNTU1NWVkYTQxNjMwYjgyYzE4OTA2ZjliMDhjZjY3OGUwN2MyZTc5OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOWI2MmY2MGQ4NTkwYTU3OWNmNDZmOGQ2NzM3OGM0YzU3MmI5NjJjZWNjZGI5MGM3YTVmN2I0MmI5NjA3ODJhNCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmE5ZjU0Y2Q3ZTc2NjY2YzhmZjE1NGQ4ZDRhODZmNGMxNGNiYmQyNTM5YmU4OGQ5NWE2YzU0NDZiY2Q2OWFkMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjdlNmMwMmJkYjc5NzI3MjI1ZDU2Y2UwOThlNjgyNWQ4MTFiZWFkOGRlMDcyYTEyOTA4NTllNWE5NmNmODQ0NiJ9"
}
]
},
{
"id": "claim_566be4320136458ca3ca16da0773c5c0",
"statement": "AgentKit owns the host-neutral agent loop, approval gate, provider adapters, MCP client, and built-in tools; Termind must not add Termind-specific SSH, SFTP, UI, or host behavior to it.",
"evidence": [
{
"resource": "repo://AGENTS.md#L16-L18",
"version": "repo-lines-v1:sha256:79d9222951afd1cde2967f4987b4aa7b4347f1510f1fc4d1141010690b9c8bff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGI2ZWFiNGFjNWIwNmRiMjY5NmQ0ZDUzZTJlN2YwZDE3MzhmMWI3NTAyY2UyZWY1YjcwMzIzZjg3NjdjYTllNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRkZTk1MTMwNGUxYWVlNjRiM2IyYmY3NWZkMzI2YjAyZGM0OTE5YjlhODM4MGZjZTY1YTAyY2VjOTE3MzdjMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWM1NjRmZjMwNzY2N2QwZTgzMGJkYjkxYmY1MDYwY2FlODNhMjc2NzRkNTU5NWNiYTU0ZGMwNmQzNmE2NWMzYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWYxZjNmMTg5YTBiZTIyMGIzYjA0YmIwYzc0MTI2OGE5MzE4OGU1YzY0OTMzZGUyNzU0YzI3ZTZkYzRmZTE0NSJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L352-L356",
"version": "repo-lines-v1:sha256:425557967a3c8daba2a7af324081dff7809f5fdfdee4f2ce780c46819e9ba6d0:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTIzZDQxNmU1NjU1M2FiOWFiZjg0MjVkNjExMTI4MTQ4NjMxNDFlZmYzZTVhM2NhNDVlNDQzYzk1ZTAwNzA4MSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYzY1NjVkMWUyNTAzN2VjMzdhZWQ1Y2ViMzYxNDVkM2RhNzJlNzZjZmVmMDI0NDQzNzIyNzM5Mjg2NDYyMThjMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDA0NjZmNDJmZTgxYzZkOGQ0ZGI3YTVjNGUzNmI2OGMyYmQ4MTIwYTgxNTU1NGQ0ZTNlOGVlYTQwNDg1Yjg2YiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMmUyOWFiMjBkMjIzZGE3ZjFhODcyYzIxZWY1MmFjNTVhODMxN2RjOWI5OTQyZDc5NzUwYmU1OWQ0YjJmY2E2ZiJ9"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L137-L160",
"version": "repo-lines-v1:sha256:df1426afee6cba4b9c4a3b901694c27f4855687f2d8a386e8b3264d45b49ef22:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjOWJmNjE2ZGNmNTM5YTBkNTRhMTM2YzY2NGM1M2EyNTllZmFkOWNmNWFmYTY5MDY5ZmEzOGI1MzE5OTQ0YzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0N2NhYjY3NzUxMmRjZWQ0YTIyMGVkZGQ4NjNlZDFlNDM1OTM0NmRiYTk4ZDljYjkwZDBmZjk2MjhjM2IzNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
},
{
"id": "claim_368fa7e429f84aa1aa9e34b296de06d7",
"statement": "Termind registers host-aware agent functionality additively through TermindAgentTools, whose injected environment supplies host, connection, authentication, metrics, background-command, and scratch services; AssistantToolRegistry supplies AgentKit built-ins and then these additional tools.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift#L42-L68",
"version": "repo-lines-v1:sha256:f00dc05b6b14f14e9071bb2c3725c64e133622f8e78ffc3e87a20fba2c5752af:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM4YjBhZGQ3NDg1ZGY0OTA5MTkwNzI5ZGEzYTVkZWY5MjVkZmFkMTQ2YTJkMTA1MDk5YmFjZTJiYmJhM2ViMDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhiZTBhODk2YTNjYjAzNmM0NDZiNDgyMTA3MDA4ZDZkOTZmNTdkNzA2MGRiNDk4ZjQ5YTVhNjhkNDI1ZWI4NGIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRlYzQ4ZTU4YzVlMTBhZWJkMDdkOGQ5OTljOWJhYjg0MDBlNWRlMDA3NzE4YWQwNzA5OTkxOGRjOGMxMDg3ZjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift#L45-L62",
"version": "repo-lines-v1:sha256:74627a2745ff783912181210d9283bca8f0d39f2f9d0611a90b97371d2429d30:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ3N2EwYzQwOTMzNDI2NWIxN2I5N2E2OGM1MmYwNWQwNmNmMGU0ZTAwOTNlZWIzNTE0MmQzYWFiMWJkOTkyOTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYzFmMTg4ZjE0MmVkN2E4MjQ2ODBiMjA3MTcyYzU1MTliYzYxNGE0OGZkYTdjZjE2N2VkYjhkZGY3OTk1NmMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQyYWE5ZTVmMGI2N2UwYjRlYTEyOWI5NDQ2NjhhMjNlNDdlZWJhOThmM2I0Nzk3MGU3NmM5ZWQzNzAzMjZlNTMifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift#L5-L23",
"version": "repo-lines-v1:sha256:a6707f4eac40956e70af3b606852201b6d17b54d295c771bb743f37fbad2797f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2NTgzYWUxYWM2NTU4YTlmNGQ0MTYyYzcxZDJjMTk4OTE3OWI2MDljYWE0MDg0OTMzYjZlY2E5YWEzYWU1ZDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk1OTRjZTkxMWRiMTE2YWVlNzAyNWMyYzAzNzE5NzZmZTVjN2M3Yzc1ZmY2MGQ3MTA4NDgyYzY0NjNmNDM4YTYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM0NmY4Y2RkMDA0NDk4MWZkNzI0N2EwYzg5MzE2ODM0ZDNlZGFjOWU1MTAwNThkNGMwNGNhM2RkODczYzFhYTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkzNjg4OWY0NDhlNDhjMWE0MjM5NjQ5ZDdkZTEyNzBlNDU1NDk0NDgyODY3NjQ4M2ZkYWY1YjhmYjkwZWUzN2EifQ"
}
]
},
{
"id": "claim_29eb9d1db73e4802ad397fa5de81f173",
"statement": "ArchitectureBoundaryTests also guard against local redefinition of AgentKit runtime types, confine ListViewKit to an allowlist, and check forwarding/mobile authentication ownership plus benchmark independence.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L108-L160",
"version": "repo-lines-v1:sha256:84b510fa05a9833e8a137fd3439676c51ffcb2dd45c0dfccc4082850625a0968:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0MzhiMmNjZWI4NWM2ODdkODk0OTcxYmY3ZmZiNDUzNTI0OWYzNDRjZjExNmFlMzg3ZTAwZGM3MjJjNGNlYzYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L6-L44",
"version": "repo-lines-v1:sha256:04c57608a4f36e066a86d45b1927320ec3f1b3912960cf3ead95574b6a0deab2:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI5ZjdjNGNiNzk4NDRmM2QyMTg3YjU1MGRiNjhlZmVlMjU5MDQ4NDZiNTgwZWRmNjIxNTc3MGE4NTAyYTIwMzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5Zjg3ODhhMDEwYWMyNjY0MDQxYThhYzZjNjU3MTdiOGU0Y2RiZTYzMmMyY2JjNTMyMzZhMWMwNWI5MzhjNmUifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,260 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:4737dc09eb90c0420b880bf2fab094f9135192ed24ce438943b5251eea09c18b",
"claims": [
{
"id": "claim_981f16f030e9469588af705aa377161e",
"statement": "AgentKit owns the host-neutral agent loop, provider-facing runtime, approval handling, MCP and generic tool catalog, while Termind assembles host-specific SSH/SFTP tools, policy, persistence, and UI around it.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L201-L328",
"version": "repo-lines-v1:sha256:02c4383ae6885f3dea6168d146dfc1dfc12cfe9af93cd56bead4023f25f8bf25:eyJzZWxlY3RlZExpbmVDb3VudCI6MTI4LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI2NTVlMmVkYTc3Yzc3ODBiNjg2ODJiMmZiYTExNGQ4YWE5YmIwOTBkMDYzN2ZmY2RmMzgwNWViODkzNjZlYWZkIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI1OTA5YTUzYTYxOGQwMjhlMWQzMDAwYzBhN2FiY2VlY2JlNWZiMzdmNGU1MTFlZmU0NjY0M2ZhZDZlNjY4NzJmIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI0YmE4NGEwNzc5OGYyNzk4NjliNDM1ZTdiZGU2MmZkYzg2ZDRhZjkzNzJkYTcyMmY5NWM2MjY5YTJhYjkwM2U3IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIyNGJkNzA2YzdkNTlkMjVmM2MxNTUzNDM5MDAxZmYyOWQ2ZGEzZjVlNjQ1YWIyZTE5ZjM2N2MwZmM3MDQ0MGU0In0"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift#L42-L68",
"version": "repo-lines-v1:sha256:f00dc05b6b14f14e9071bb2c3725c64e133622f8e78ffc3e87a20fba2c5752af:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM4YjBhZGQ3NDg1ZGY0OTA5MTkwNzI5ZGEzYTVkZWY5MjVkZmFkMTQ2YTJkMTA1MDk5YmFjZTJiYmJhM2ViMDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhiZTBhODk2YTNjYjAzNmM0NDZiNDgyMTA3MDA4ZDZkOTZmNTdkNzA2MGRiNDk4ZjQ5YTVhNjhkNDI1ZWI4NGIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRlYzQ4ZTU4YzVlMTBhZWJkMDdkOGQ5OTljOWJhYjg0MDBlNWRlMDA3NzE4YWQwNzA5OTkxOGRjOGMxMDg3ZjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L352-L359",
"version": "repo-lines-v1:sha256:e7282ed7e9f63e4e8f7e4283cdda6022103d7cf4ff661be316ecfc9adf285128:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTIzZDQxNmU1NjU1M2FiOWFiZjg0MjVkNjExMTI4MTQ4NjMxNDFlZmYzZTVhM2NhNDVlNDQzYzk1ZTAwNzA4MSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZmI4MjYxNjM5MWFlOGJhMWRkOTJmMzVmNTRjZmZiMDUzMDU0OWUzZjAwYjI5OTQwY2FiMTBlZGFmZmQ1ZWM5ZiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDA0NjZmNDJmZTgxYzZkOGQ0ZGI3YTVjNGUzNmI2OGMyYmQ4MTIwYTgxNTU1NGQ0ZTNlOGVlYTQwNDg1Yjg2YiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOTI2ZWQ1ZDJhNDlmZDc4YzgwOGUxMmQ0ZGJmMzQzNzE3NDk5YWRhM2VkNTA1NWY5MmM0MGQ1OTc3NzNkODM0MCJ9"
}
]
},
{
"id": "claim_28c4b1e064e94a798fe0220965a3951e",
"statement": "A submitted Termind turn records the user prompt, freezes run context and tool availability, constructs a new AgentRuntime, and starts it through ConversationModel; the runtime persists a running snapshot before requesting the model and persists transcript snapshots around each tool-result round.",
"evidence": [
{
"resource": "repo://.build/verify-zh-hans/ios/SourcePackages/checkouts/AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L161-L241",
"version": "repo-lines-v1:sha256:ca6910405404893e5f20a65facc669d891dab442eb019ea645c30141cb27798a:eyJzZWxlY3RlZExpbmVDb3VudCI6ODEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVkNWE5M2M2ZjljMzg2NWRjZjkwOTliYWE0YWNiZTI3MjI4MmY2ZTFhZDE5OGU3MWQ5NGU5MzRlMjIzNzNiMTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkNGFlYTM3NDhjNzUxOGU3Zjk1MWMzNGM0MTQ5M2FlYjY4OTgxYTg1YzBiY2UwYTk5ZTZmOWY1MTQ2OGQ1NWQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBhZWFjOGZkNTg4ZjE5OWZlNzFmOWJiMGY3Mjk1NDI5NGNiMmVlOWRkNzgyYzQzMDJlYTg4NWE3MTAzMDNjMTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3ZTA4ZDYzNDU5ZjAxMzEzODQ4MDgxMGIwZmI3ZjBiYTJhYWY3MmM5MzhkZGViZDEyYzRhZWZiNTEyZDQxMzYifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L285-L346",
"version": "repo-lines-v1:sha256:00d555bfa02408a1b7619b54dfce3ea70403a2f114b8332941de455674e9c86c:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4YjA1OGQwZDE5MTQ0NzUxZmFhNDYzZmM5OTk3NjQyYjQ0OGNjMDVhZmFjZmMxYzY3YTg5NjhhZTA4MTgzMGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJkNWYxMjI0YzZkNDJlNjVhZWMzNmY2ZGNiMGIxNzZjYWQwYmNiNTQzZTVmMzcwMzM4ZDhmNjNmOTRkYTBlYzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVlYThlMTdlZjdhMzg5MDQ1NjczYTQyYWZkOGFlYWFiMjk5OTg3NGIwYjdmNmEyMGY1YzEyNDc2OTU2ZGI1NzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVlYzAyYjAwYTc2Mjk0MTQ4MDZkMTIyMjc2OWI4MGUwZjZiMWM1MWZmYTQwYzU5YzExMjliMmY0MThjYTNlYzYifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L46-L95",
"version": "repo-lines-v1:sha256:2a4b30082e0de792ca959a899e5cdbe5073c3fed89b37a6767845f2231d7a6b8:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzNTMzM2MzZTA4M2NlNjk4MjRiZTAyZTMyZWFlMzcxNjc0ZDhmOGZhZDMyYzNlOGU1MDViMmJmNTE0M2VmMTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzYWVlMmNjZDYwMjA1YzRmNTY0NWM0NjE3MzZlZTZmYjkyZTU1ZGQzZjE2MmQ2NGQ0Y2UzOGIwY2I1NjExZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZiNWI5MWZmNzRmYmZjZWY0OGZjOTZhMzNmMGFlNzk2NzkzODE3N2U1YTJlN2Q1OWE1YTg0MWJiZDU5OTY0NWMifQ"
}
]
},
{
"id": "claim_27e003cf2fdc46a69d1b04b9b366fd67",
"statement": "ConversationModel keeps a display projection separate from the authoritative transcript because replaying display messages would lose tool calls and results; it owns the active runtime and consumes its ordered event stream.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1855-L1887",
"version": "repo-lines-v1:sha256:fe3484016f99762359b65be4ea1f12a76f0bcd358bb9df3739219263b7201002:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk4MzU3NDc3MTIzNGY2N2ExYzRjOWU1MDEyZjcwMzUxYTUxNWI4ZmVmMTcwYTRkYjQyM2M1YmFhNDQxOTJkNzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAxMWE4MTg2YjMyNGI2MmY1NzZkYjA1MDc5YWJlYzNlYjU3YjU0YmVmYjgxMzc4NTgyZmY1ODg1NGUwZGFiM2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFjYjFmYTljNzA3NDFlNzgzNWY2ZGY3YWY1NmQzYWUyNjUyYmNiMjYzZTFlOTFkZjE5MjYyNmM2ZWU2MWE0ODAifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L785-L803",
"version": "repo-lines-v1:sha256:fbfbc47722c6c98fb8ef1707713ef10376782045b660ce93864fef69a4b22c85:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjljZjIxYjFiNzJjNDQxMzg5ZmYyMzE1NjcxOTNiOTgyNWY3ZjQ0YWY1MTI4YmVjNjlkNjVjNmUzOGI5NWQ0YTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJlZDJhZGU3YmY0OGRkZWUwNGVjOWIxNTIxMjZhODBkNDBlYmRjYjAyNTc3MTE1ZDg1OTY2NDAwMjI1YzBkNWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdhZjhmZjY1NDM5MTMxODVjM2UyNWNhNWQ5M2U3NjhlY2NjZTI4ZmRmNzZmN2Q1NTA2ZjRkMmViNzJiMzYwMDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAyNTczNGI5ZTA2ZjkwMGU3ZWY0NTY2ZWYzMjQzZmM2OWYyYTc1MTY4ZDE4OWFjNDJkNjJlM2Y5NDg4OTM5NmYifQ"
}
]
},
{
"id": "claim_2faba60540ed41f4bfdf9a0f8db0292a",
"statement": "Tool calls are schema-validated before approval and execution; Deny always refuses, Approve needs no further approval, and Ask follows permission mode, while full access does not bypass trust, secret, schema, sandbox, or capability boundaries.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L357-L367",
"version": "repo-lines-v1:sha256:9a3c145d5b25224961ed7684ee17930293e0e6e7ac184ebdebc279a8fea0cbde:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNjNTVmY2M1ODczYTllYzRiYTM0OTZkNjMwNTljYWFjY2ZhZjk5YmI5Mzc3NDRhYzQ0ZmI4M2ZlZTkzZjg1ZjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU4N2IyM2Q3NDhmNjVkZWM5OWUwNzMzMTYyMjRkNzI3MzZhN2NjZDBlMzA0YTlhYzU2ZjVjY2E4MmMxMWE5ZTAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyODIyNzk5ZmMxZmNmNjM1ZjA1YzE0ODQxYjdlMGM3MTkwMDA4Y2IyMDMxMmE5OGJiMDFiZmMyOWRmYTI5YTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVmN2Q4ZDE0YjliNTg5ZTFjZGY3MWExNDE2M2YwODc4MDViZDY4ZWE4YTBhZGFkMzAwNWY5ZTYxNzdmNDFjM2IifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L382-L386",
"version": "repo-lines-v1:sha256:4d2524750797dacd175df785a959408d1ee9933e09b75656742cd40194a5fbfd:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTI2M2YyNTQ0MTI2YmJhYjhmNGM2MTkyZTRiNzBmOTQwYWNkYWVkYWE4MWIwNzI1OGI4MjkzMmE1NmU2YTA4MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDUzMDcxOWQzYWNjMmIxMTY3NGRjZjM0NWE0ZDJhYjhiNDIzNzNiNDQ4MThmMGE1ZDFjNGNmYTIzYjE1MTNkNyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNkNzk0NjE2ZDViMWEzM2JhNTkyNjZhYTgyZjFlMDFmMzY1YzEwNWI2Mzg4NDc5YjM2NjE2Yjk3ZWEzMmJlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDA0MjJjOWRhMTZmZTM3NjVhYWM4YWVkYzcyODEwZDY5YTdmNGQwNThiYWU4ZWZkOGYwMjQ2NGU2MzJjMDFjOCJ9"
},
{
"resource": "repo://TFMTests/AgentRuntimeTests.swift#L484-L526",
"version": "repo-lines-v1:sha256:f6aad3e399f570d7b20c1aa11514a6e10605d81146d31bc693b93629cea68458:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdjNTliMmQ4ZTQzNGRmMzg1OWNlNDViOWYxMmE1Mzc0MTEzYmViNTUxYmU2MzE5YTE1YTBkN2FjMDI5MzY4ODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhjMWI1MTA4ZGIxMmVhZmJiZWVmNjBmYTc5MTZhYzFlMTcwM2I2M2Y2MWFiZGYwOThjZWQ2NjYxNGEwZTRkZTIifQ"
},
{
"resource": "repo://TFMTests/AgentRuntimeTests.swift#L603-L635",
"version": "repo-lines-v1:sha256:0b1ffc4ad64ac8e02ce7ee47e31ca3bfb322270c9e2e179ae8418ec46c77d6a3:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE4NDkxZjYxODRmOTViNzMwNWQxOTY0YTMwOWFkNGRjYjM1NzM3Y2JlODAzMmUwN2UwMmRhMDg1MGZmMTFlODEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ0ZWYyNTM5MGU5MTkzNmE0NzM0MTQ4MjY0ZjMzODI1MDY3NDEzNWZlNDM0OWFhNmM2Mjc4ZDg1ODI2ZGU0YzUifQ"
}
]
},
{
"id": "claim_0a5108380b2e4c28854a87655a6662ee",
"statement": "Guardian review is used only for approve-for-me runs when a configured reviewer credential is available; unavailable, timed-out, malformed, or otherwise failed review denies execution rather than allowing it.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L241-L281",
"version": "repo-lines-v1:sha256:7898f2adaa92869c8bd82511e787865dac90da5721cc4fc9ab2721c4f3b0044b:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI0ZDFmYTZhZWEyMmE1YzExY2JkODNlN2Q5NmZlZTQxZmRiYWFhNGZkMDZkODNhYTMyYTk4N2JmNDFhZmY4NTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRjNGM2YzQwNjcxOGIzOWFjYzE3Zjk5ZGE2NDhjZWJkNmRmODZiZWUwMmFkZjAzNDUxZTQ5YTRkZDExYmIwZjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVlYThlMTdlZjdhMzg5MDQ1NjczYTQyYWZkOGFlYWFiMjk5OTg3NGIwYjdmNmEyMGY1YzEyNDc2OTU2ZGI1NzUifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L364-L367",
"version": "repo-lines-v1:sha256:234c31b4c01f1ea8b45e214c7254b23061d9b1d859a27692a4ac7ed3c7bec5d2:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODlhOTA2ZmNhNmY3ODU0ODExYzVjOGUxNzM0ZTU0OTU2ZDYzZTU1YWU5MTExMTk1MjA0MmNjM2MzODg4YzJiZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTg3YjIzZDc0OGY2NWRlYzk5ZTA3MzMxNjIyNGQ3MjczNmE3Y2NkMGUzMDRhOWFjNTZmNWNjYTgyYzExYTllMCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMDU2ODBkZTZlNjMwNWVmYzY5ODYxYTM1YjA3MmM4ZGQzMGU0MjUwNzRjZWE1ZThlMTY4MjNjZjNlMmM5MTRjMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWY3ZDhkMTRiOWI1ODllMWNkZjcxYTE0MTYzZjA4NzgwNWJkNjhlYThhMGFkYWQzMDA1ZjllNjE3N2Y0MWMzYiJ9"
},
{
"resource": "repo://TFMTests/AgentRuntimeTests.swift#L709-L774",
"version": "repo-lines-v1:sha256:68040a200b403f6850a95c3bf6764761a6ff094e17a221d56c845af637107b43:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk3MjRlYjJkMjAxZjZiYTlhMzY5ZmU0NWZkZDhjMWNhOWU3NTU5MTE5M2QwYmNlMzIwOWQ5YTI1NmUyMWFlZmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE2YTAwMzI5YzNiMzJiOWYyZTJhZjIwYjM2NzBhNzUxZTY4NDVmZTE4MTdlMzI3MTljMjM5NDM2YWQ4ODQyMzEifQ"
}
]
},
{
"id": "claim_41df25079f6c45a7b41a4183d03d0814",
"statement": "Secret handles are single-use and bound to run, tool, host, and purpose; secret values and handles are removed from replay and durable history rather than exposed to the model, review, events, logs, SwiftData, or Hermes memory.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L377-L380",
"version": "repo-lines-v1:sha256:06a1989f108ec2eedbc903780412293b02779e094cce12db2dcf594923c9d46e:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNDMzYmM0MTRhNDQwOWRkMjg0ZDZlNmQ3NmQzNzE1ZTRmOTNmYTcwNTg3ZDAzOGIyZGQwYmU3NDIxNDM2ZDVlOSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMTM0ZmE0MmE0YWYxMTFlNmFlMGMzOGY0MTdlMGVkYjRkMGUwNTliZjg0NzcxMmY3M2U5MTczMjRlY2I5OGU5NCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjk0MDQzNmExMzhiZTg0NTg4OTRhNzk3MTM4ZDEwOWE5NjZlOTE2YzRmZDI4ZTYwZDUwMzdhZmFmYmI2MzkyNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTljOTNmMWNlYzBlNzg4YWE2OGNlZDQ1OTY0ZTEwZDM0ZDIzMDgzNDczZmJiNzY2NmNlNWU4NWE3YmJlMmFjYSJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L404-L407",
"version": "repo-lines-v1:sha256:c7f882f44127f116fb303fa85756715ea626fcb71c4efa063946d06f9d488515:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjI2M2FiMGQ4YjBkZWE3MWM5MGY2NGFkZjRlNTc4NjhjOTAyZTQ0ZjVmNDcwOGNlNjQzNmYzZGVhOTFmYzQ0ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiY2ZiNjUzNWIzZGFkZTViMTJiY2VkOTE0MzkwNzZiNTczOWMyMDFmODJjYTAwNjA3OTM2Y2JhMzU1MjZkZTcyNSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzM2ZGVhOTlkNGQ4ODEzZWY4MGY1NzQ1YWU2ODYxNWQ4NDI5ZDU2NTAwMmNiMzI3NGYzZGM5MTAxYzlkNDhkZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWRhYWUxN2IwZjYyNmQ0OTFmNWVmNmRjYmUwM2ZkMjFkM2FkNjFlNDRjNjZiNDA1ZmI4Mzk3MjEyZjRjMzY5OCJ9"
},
{
"resource": "repo://TFMTests/AgentPersistenceTests.swift#L481-L529",
"version": "repo-lines-v1:sha256:2bd4b0bb8256abe8c53fd2c7fe378dd0fbf43ca06069811eb2d5e823a224c3bf:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM1M2RhOTQ5ZTJkYmNhNTRmZDI0ZGRlYWU3MTc2ZGUwMjUwNDFkZjk2MWY3NjUwOGU3ZjhkZjViZDJiN2ViOTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFlZDU1OTE5YmQ3NmJhOGUzNzVjNjkzYmUxYTAxZWJkZjE4YTE0NGI4MGE4ZTMxMmYxMmM1ZmVlZDQ4N2FkNDgifQ"
},
{
"resource": "repo://TFMTests/AgentRuntimeTests.swift#L940-L961",
"version": "repo-lines-v1:sha256:61466ccfec9e1aa28bc3a4d34374e90f1d3c48f918d371d24ad1b7b45c566718:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZiY2EwYWI5MjU1ZjVlNDA5MGYzNmMzODg1NzJjNDhiNzhkM2JkODFhYTdjMTNkMTc4ODE3Y2Y4MTM4MDA3OWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
}
]
},
{
"id": "claim_10f2f03c85434fd3b22cbe8e51895b0c",
"statement": "Steering messages are queued while a run is active and only become transcript history at the next model boundary; cancellation stops the runtime, cancels its task, discards run secrets, and returns undeliverable steering to the composer.",
"evidence": [
{
"resource": "repo://.build/verify-zh-hans/ios/SourcePackages/checkouts/AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L135-L159",
"version": "repo-lines-v1:sha256:1e7ee3251e0671722c1fa5ceddf8acaf9c387c1214e7d87e25b3061dc64e2dbd:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4N2Q1NGYyZWZiNDBlN2ZjNDdkYmUzNjJmOTgzNzNmYzJkZmI3NDM3Yzc1NTlkMzEzYWFmNzAyMWZjMDkyNGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFhYmQ3YjdjN2RkYTI0MTcyNTJhMDY3ZmY2YjU5NWQyMDllNGI5OTc1ZGRhYmJkODc2M2ZkYzFkOWQyMDQ0ZDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjEyZmQ2NTFmYjQ2OWY4YjVmMTQ0NjRiY2M2ZGMwZDZhYjJkZTM1Njg4MDhhZDcyNzYxYjhiMGNlNTFlNDZjNjgifQ"
},
{
"resource": "repo://.build/verify-zh-hans/ios/SourcePackages/checkouts/AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L217-L252",
"version": "repo-lines-v1:sha256:33f1041e47578bf10577d59d8e680d52acc08b9618c31112ee86070cda232bb9:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM0OTgzZGE0OWNjMWViMzBkM2MzODMzNjMzM2I4NmM0ODc0ZmEwNDA2YWE3OTIxNDI3ZTU5YzgwN2Y3OWI2NDQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImEyNmU0MzY4ZjIxZjg4OTFjZWQyNGNmYWY3Y2EzYmY5OTg1YjNmNDY5ZDRhNjgyNTZlMTYwOWQ2NTZmMWE3OWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRlOWQ2MDRlNmM4MjFhMGNkZDdjNjhjMGQ5MjM2ZGYzNGQzYWY1NjM5ZDI2YzAxNDRiMDQ5MDQzZTgxMjBmZWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3YzhmMzI1N2Q0YmMwNGQ2ZjViYjFjYmRiY2FiN2QwNmQyMTA1MzJjMDhkZTExM2MyNzJmZDdjZjkzYmZlNzQifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1909-L1987",
"version": "repo-lines-v1:sha256:09a1dfd058b41e37f5cc8489c4536b2c966c4c0d75a6d766e18567e4b0934c92:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmZmM0MzNjZDM1OTM3MTAxZjgyZTM2MzI0MGZiMDkzMWJlMjZkYTcwYjg1MjRlMDEwYjVjMzlkNzdkNWYyNjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVkYjZjMmYzYTBiZWM4ZmU1ZTRlYjY3M2NlODAwMmMwODM0YWJiYTU1ZDM2MjhkOTMzNzUxYzA3MmUwYTc4NGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmMThmMGI1OGIyNjAwNzUwYzBkMjdlZDlmMDA2ZGRhNjZiMjBmYWM4NDg1NzFlYTVlODUwOWFlZDQ3NWJmNjkifQ"
},
{
"resource": "repo://TFMTests/AgentRuntimeTests.swift#L428-L457",
"version": "repo-lines-v1:sha256:5d7811288d8d6d02c029b2d582688bcaf07e08796cd196f6f69823d757672b3c:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjYTZkN2QzNTY5ZTQwMDNkM2VkZTM4M2Y1NGZiMzM4ZTM3OTU1NmZmNGFlYTQ5NDNlNDIwMGFmZWJhMjM5MWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRlZTI3YzAxZDY3NDFjMWI2Y2YzNmJhMTM4YTk1NWU1YTA1MjhhZGRhMzQwOTNjNDEwNGRjNDE5MDUxNDFhMmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIxM2RlZDMwMDA2NTNlYzc5ZDMxNGQwOTIwZmE2NTFiY2M3OWY1ZmFiYjcwMTkyN2ZiODBjYjAxZTcyMWVjYzQifQ"
}
]
},
{
"id": "claim_b70a11449d9f407fbc27c8f1e86538ef",
"statement": "Each tool-capable conversation receives a persistent, per-conversation scratch workspace that is isolated from other conversations; scratch paths reject escape and symlink routes, and scratch push rechecks the approved file digest before writing remotely.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentScratchTransferTools.swift#L110-L146",
"version": "repo-lines-v1:sha256:723c9a39e14adf5b96aa808a16247ea51402035210e27a93f9c060dfaacb30b2:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM4OTY1YThjNWYyYTUzODM0MjNkMzFiZTg2MmNjNzQzZDQyMzUyOTFjZjJjNzg1ZGIxM2E1OTUzZGIwNzk3YWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQxYjdiM2E4OGQ2M2EzODFiMTI4Y2ZlMGRiZTVlOTI1YTdlMjc2ZDM5MjViMDQxYzAxMmRmYzA0NjUxNzA4M2UifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift#L21-L30",
"version": "repo-lines-v1:sha256:04842a05cffa9e911592d2e2250c8bf75056f1e25dac5521c3cfeff2896a717e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4ZTYxNjZjMjIxYzk4YzlkMzQzYjNmZGY5MzMyMTJmYjVmNjI0M2MxYjQyNmY0ZWVkNmE4YmUzMjkyODE1NzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU3YTU1ZTg4MmYyNWExMjllYmFkNDM0MzRmZTUyZmI3ZmE0ZjVlZTkzMmIxMmM4NjM4OTY2ZGE2Y2JkMzBmN2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ1NjFlZGZiNWRiZjRkOGYwOWM1MDFiMjBmOWZkNmI0MjU4NTZlZWYxMzNlNjg5MzMzMWMyMTNmNDAxNmVhOWUifQ"
},
{
"resource": "repo://TFMTests/AgentScratchTests.swift#L19-L83",
"version": "repo-lines-v1:sha256:5ee273606eba6db5b7fdcd82998ef11f7bb14260fd6abcb71940819f12913847:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZiOGJmM2I0NTg2NGRlZjJjMzU3N2VkY2QxODlkMTBkMzYzODUzYjFiZjkyMjU3ZmIxZTk4NzQ3ZDdmZDFlZDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhiZmVjYjVlYzlmZWIyNmEyOWE2MWRlODk0YTk3ODZkOTZiMzBiNzQzMDMzZTQ5MTBlMGRmNjBhMDkyYzY2MGQifQ"
}
]
},
{
"id": "claim_08d587b15e9c4cab863934a64d8a1575",
"statement": "SwiftData persistence stores conversation/run history and durable tool lifecycle records, deduplicates replayed messages by message ID, marks nonterminal runs interrupted on repository initialization, and restores recorded tool results to repair otherwise unanswered historical calls.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L11-L14",
"version": "repo-lines-v1:sha256:d63fa5240e197b14ca235275b415affcb5df50fd36b04407f3853864de0eec2f:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiY2JlNzJmMzczMTQyYTJhMDE4M2U5YjUyYzE4OTMxZDkwNTI5ZWFjOGQwZmJhY2FlMmU3Njc1MTZjMTVlZmIzYiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYjZlYzhlMjVhMTk4MGQ0YmVmNDRmYzk1Y2JlYTAzNmRiZjM2ODQ2MWU1YTU3NmRhNjA2MTNhYzFhYmFjODk1MiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOGYzMzJlODFkY2ZiZjQyZmQyMjU3NDk1OWM2YjdjMTAxNzJjOWMwOWUwOTY3MjczMmUxNDM5Mzg1ZmNkZDNmZiJ9"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L47-L75",
"version": "repo-lines-v1:sha256:3e3cf6dd4cb38f70d589568031e9bdf159967aaa4a80c86fe225a88a4414f107:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJlOGZlM2YzMDFmYjI4M2EzNDNmNWNhZWVkYWZkMTAzMGY0OTQ5YWE4NDQ5MjFiNzUxZDI0NWU0MDViOWMwMWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3ZmIwOGJmYjIyNTk4ZmJiOWM0NTgyNjRmM2MxYzZiMDA2MTY4YjY5MTY2MmJjNTBhZTVjYzVlMjg2ZDU2ZmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4OTZhNDc4MzIxYTFmMGQwOTUyMDliMjkyMTBmNmFkZmMyMmQ3YjQ2ZjMxYzMzODhlNGQzMjk5OWRhMTFjNzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkwODY1Mjc5OWI1MWU3OWUxYTg3OTZlZDMzNDM5ZDVmNTEwNTYzYjA5ODY1ZDgyOGJjYTFiZDMwYTY3MThmYmEifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L550-L605",
"version": "repo-lines-v1:sha256:6aa3a9f8b2bd8335e17c386f68b91564551f30ee25e239ae960ae032ef4f90fd:eyJzZWxlY3RlZExpbmVDb3VudCI6NTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzNzE0ODNiZmQ5OGM1MGM5NDg5ODlmOWEwNTJjMzI1MGUzNzMyYTczYTc2MGY1ZDJhN2I2MjFhNTJhNmUzYjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNiYjUzMTU2YTNkYjA5MDdmY2I4NDEwNjJjNjc5NjdiMzMwY2I5NTk1ZjViNWEzM2I4ZWVmNTZjZTVlMzczZjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMyZTEzMDIxNmFiMTA4MGE5ZWZiY2Q1NGIzMDdiNDk0ODU2YTUzMTYxNDc2Y2Y4ZWNjZGM0YTYxYzk3NWVlMTIifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L671-L683",
"version": "repo-lines-v1:sha256:f142043bb1b01de9a0458b3995239712303b9ee5f7cd1bc4531d3ee6da2913f1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ5NGQ4ZDkyN2FkMTU0ZTM2ZmFhZjZiMmI2MjMxZDllN2Q2MzRiY2IzZTliMjI2MzA4ZmJhMGVkOWQ3MDY0NjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_dc0fa388e5284bcabd1c6e9ba00d23aa",
"statement": "Compaction persists a record before the live conversation applies it and replaces only the model-facing projection with a synthetic summary; the original display history remains available after restore.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L473-L482",
"version": "repo-lines-v1:sha256:7c9756ce11f5a802355fdf037aff24ef90f81e71df715249370eef766c0a4ab0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2MTZmMWZiZWQwMTYzZTEyMTU4OGUxOTZkMjA3Zjk1ZWYwNTFmMGZiMDEwN2YyNDI4OTA1MzAyOTEyYTVhNmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVhZjdjMDM3Nzg0ZTJjNDQ1NmE3Y2MwZWUwNTFiZGU2ZjA0YjZjNmU0OGJiYzA1Y2Y1OWQ0Y2Q5NGE0OGI0NjEifQ"
},
{
"resource": "repo://TFMTests/AgentPersistenceTests.swift#L961-L1010",
"version": "repo-lines-v1:sha256:309eb4d5282b146727667728b061d8a1bf59db4633971690ac54823192c7dd34:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg3MzRkODNjMTFmMDlhYWJjODY3YTUxODMyZTI4MmE0ZGVlMjEzMmZhOGY5Mjc4MWMxNWU5ZGM4MzkxMTcyMTYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJhZjRjZmQyZjMzYTRkZmMwMDJmZmE2MWVkMDg2ZWU0YWIzNWU3NjA1YTZhNGFlZmM5YTc5YTFkZTMyYzIwYzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
},
{
"id": "claim_5adad6caaaf1482baf6e5d4afcebc008",
"statement": "Skills are app-managed packages whose catalog is fixed per run; only SKILL.md is procedural instruction, and a skill does not authorize commands, writes, or transfers outside the normal approval policy.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L218-L234",
"version": "repo-lines-v1:sha256:5c7b2d3892cdad34fcb9cb2996fde4ff824188998dc264d7b3600bf156a37ad9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmMDg3ZmZlODE0NTk2NGYwZWIwOTlhM2FiMzQxOTRjMzlkM2E5YTY2YTM2NWJhYTQ3OWQ0OGIyOWJhY2ZiNDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIyZGFjYzM0NjMzZGIxZjRlY2ZjYjYzOGI5OTNjYWY1ZWE1MGU3ZThmZTk5MTFjNjBmODBhZjIxNWM4ODk5ZjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhkZjJlZWYyYmU0YTM1MGU3ZjI3MmVmZjExNDc2MWJlM2I1Y2MyYzMyYmI1NzllZTc3NjIyY2JkN2MxOWIxNDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjEwNjZiMzQxNmZhZmQ5NWY2NjY2OTQ5MzJmMjc5ZmVjNWM4ZTliODY4N2I0NDk2NGM4MTU4Y2UzZDJmYWYxZjcifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Agent/TermindAgentPolicy.swift#L46-L49",
"version": "repo-lines-v1:sha256:81359ab87f7ba9a790818b6e8d31c3a5fbc50e1fb4e4b2cead9f1a7ca42567cb:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTZiY2U2NDRlZDg2MDdlNTRjMWExZjU1Njk3M2VkZGFkY2ZiNWE4NGIxYWE4MTRhNDMyYmYyNGU2ZWZjMGMxMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMTNjODMxYmFjNTNlN2E1NDdiNjZlYTk0YzNlMjJkYjY4ODMwMWYzYjc1NTkzYTBjZDA5ZTNjNmEyNzBhMDg0ZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZjM0MzUyNGVhMWRhYjc3YzE0YjM5MGJmM2I3OTE2MmMwOGZjNTg3Yjc2OGRkMDQ1ZTQxYmY0MjI1NTdjMmEyYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZDQ2MzU1NzZhMjE4ODFiOGFiZjIyYmY2ODJhOGEyNDUyY2NjMmJjZGE5YWFmYTY5ZmFlMDNmZGI4Y2YzY2JmMSJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L390-L396",
"version": "repo-lines-v1:sha256:a6ed42b816901606dd7a4cd12a5257d7337a093df69a89b023c11e7f79409d20:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiN2EwNzY4YTZhZjk3ZjliZDg2NzQ1MDBlZDdiMTBhNDZiODZiODc2MjQ2NTZhMTU0Y2VkYTU1NmE2YzQ5Njc5OCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNzk2Mzk0NWMyZjA3NzdiMjM5ODY4MjgzYjFhOGE4NDM2NWFiZGViMTFhN2U2NjQ5MTE2YjMzZTYxMzU1Yjk4MyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMDA0MjJjOWRhMTZmZTM3NjVhYWM4YWVkYzcyODEwZDY5YTdmNGQwNThiYWU4ZWZkOGYwMjQ2NGU2MzJjMDFjOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjk3ZDI1MDA4MmUyZTE4NTQ0Njk1NGVkODFlNGQ1YmRlOGU0MWNmZWZhNGQzYmQ0MWNlMmUzY2RmMDhhNzg4OCJ9"
}
]
},
{
"id": "claim_3296a53f3da64fa9bfda12f9f8ae35eb",
"statement": "Hermes memory is device-local and disabled by default; the GRDB store opens lazily and separately stores memory state, per-conversation snapshots, review checkpoints, and an FTS5-backed redacted history index, while SwiftData remains the conversation source.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L123-L224",
"version": "repo-lines-v1:sha256:4db4ea2d811f10d0fb1345147f521e5a493179ad7661195ed552ca2d61cc58f0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJiNGNhOWU1NTU5YmY4NzhmYTExNTgzNzMwNDE0Nzg0YzFmMDk1NTY0ZmRmNzA2MDI2MzY3MjliYWQ2YjMwMDA2IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIyYjI5OThkODI0ZTVjZDc3MjNiZWY5MWI5MWE2MDE0YzEwMzMzMWNjMTY5M2Q0NDQyYThmMzFlOGZjOTEzNTYwIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJiZTQ4YWE5NDM3ZTU2OWExZGIwMWFiOGY5ODQ0YjM5MGE0MDQwOTkyMTdiMmQyMThhNTRhNDM0NmRiOTk1NjQwIn0"
},
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L6-L45",
"version": "repo-lines-v1:sha256:8365553c7428472ce048f7d8c2fe2b1bed26640a0e82a3b015acbeb3d131ee0a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2ZTgzNWJiMzkzNjdhODBkMDdiMDkxZDJmZGIwODFhZGM0YThkYTg0NmQ4MjhjYjM1YzUzY2IwYzUyMjc4MDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiNTk0OGZjNGE2MTllOTBjZDM5Yzk1YzdmNjdlZGJhOWU2OTdhZGJlN2YxNmFmMjY5NmM1ZGRlNDMzMTgyODciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNiZWFjYTU1MGI4N2Y4MTM4MGM0NDM2MDc1YTA3MDQ0NGJkMTRhYWQ4MzMwNTZmNjE0MmYyMDdiNzlhNjdkMDUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5ODg4MmQ2NWE4M2YwNjEyNzFiMTQ0MmNjMWRhOTIzNzZlM2E5MDg5NzczZjMyNzg5ODQ2NTFmNGZmZjQzNDQifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L94-L105",
"version": "repo-lines-v1:sha256:7062dea6d750d5f5844cdd575659ace68dc528cbe06fd4c3500d4c6a4bd7db2d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyNDE1ZGFjYWRjY2RiMTk4ZDJkYmQ4OTI0NDA2Zjc2ZjE5NTFmNDBkNTYzNGVmNDRjNDYyMTdhNTQ5MmMwNTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExNGJhMjZkMGQ0OWIyMzAyZjU5YmRhY2U4Y2IzNDE5N2YxZTI1YmZiYTZiMzdkOTVmYjAxMjNjNjU1NDg4NmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFlYmUzM2VkMWNmMmIyN2FiY2ViMTU1MjJiMGE2ZThhM2M1NTZmZTA5NTYxOTY1NWIwNmU2NjJmZDYxOGRlYWEifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L397-L403",
"version": "repo-lines-v1:sha256:57177032693dd6d4998dd53cd596ca2628830d3efd218083d4ff263ba52aff21:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTMxZDZiMDlmZmMzNjA2NWYyZjc3ZTA3MTk2MjdmNjU4MDhkZDYwZDgwOGQxZGMzMTdkMmZhY2UwNDZjNTExNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOGQ1YzNjNjdlMDQxNTIyZTFjMGM0ZWE2MzU4YThlOWU4ZmMwYjljY2QwNDBhYzA3M2E3NGYxMjVmZTc0NzQzOCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDAwNTYzZTNmZjk2NTdlNzgxMjBlZDBmZjZlYzA5NGQ0ZGQ5MTkzNjgxMDI2NGZiMDllODkzN2NkZDZkZmEwNyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYmU2ZDNmZjI3MWU2YzZjZTZmNzRhNjViNmI0YTJjYzgzMTFiNTlhZWZmNTA5NDIzMDA5NTIxZGExNzRiMTU1YiJ9"
}
]
},
{
"id": "claim_a3ad24a30cc74874af7e95eba686afbc",
"statement": "Disabling Hermes memory invalidates contexts and cancels indexing/reviews while retaining storage, whereas destroy persists disabled state, joins work, and removes the owned database directory; stale accesses are rejected by generation checks.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L232-L255",
"version": "repo-lines-v1:sha256:1f1936e4e3cbc44909d06cc25a5f18b6c26588b7ff8596107fe54c2e1c9e1a5c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhlNzEwNmQ4YmYxZmZiMTA5ZGJhZjNlNzU3ZDYyMzA0NGEyYTE4YTZhODg4ZmU1YzllZGFiNjFjMWQ1NjBkMjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjYThiNmYwOTgwNzYzZjgwY2I3Mjk4ODliYzM3MTdlMTQ1MjBiOTkxZGVkODdhZDNhNWZmOGUxY2FmYTJjMzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MjgxMjhkMDk1ODYwMmUyNTRkNmFlNmVhOTBjZjM0NzA0OWYzNjdhMDE3MDEwMjJmNTI4ZGRhNDkzMDU5OTgifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L52-L76",
"version": "repo-lines-v1:sha256:63ceffb701cb214698f1c57e2105b4dc02d7d20d26ec8b71c4eb50058a6e8aed:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYzVkNTIyNmFhZThmY2Y0MzhjMzM0OTQ3MWY0M2JlYWU3ZjkzYjAwMTlmOWY3MTIxOWQyMzhhNTY3MWU0YWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmMjE1Y2QxMWU4MjNlM2M0M2IxYWY0OGI2MDBmNDQ1ZTY5MDA4OTZmNmU1MmFlN2U1ZGI3M2FmYjFkNjMwMmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU5NzJkNjIzZGZjOTFjMGU2YzQ4MDU1YzY3NzhlYThmNWUxZGQxOTYyZGNlYmY3YjY1NDQ4M2NlZGUzZGY0OGEifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L98-L140",
"version": "repo-lines-v1:sha256:63a4e0832eb58af19f1014b010116530bd83aa6cfe5c62c9e3643d154d77383e:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk5MmZkOWM4MzE1NGM3OTBiNGI3MDUyY2ViZTk3ZWI5ZjVjZjYyNjZhOGFkNGY2ZWMyOGY4NjY5MjU4NWNhMmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc3MmY5Njk1Yzc0NjdjNzQ3NzNjOWNlN2ZjNDI5YzVkMGQwZTQ4N2YzYzUxZDE1ZDY2NjhhM2QyNDA3MmJiOTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFiYzgyYTk3NzE1YzQ3N2I3MzM1MWJkN2M4NGVkYWRjNTdmMTlhM2QzOTIyYjE2NjRjZTlmOGZlNTdkNzU3ODIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQyNWZmZTlhNjZiY2Q1Y2QwNWE0NDhhYjFlYmQ1NmVjMTJkNTg1ZjYyN2RhOGM5YmI2ZjYxYTVhNWUzOWU2YzcifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L401-L403",
"version": "repo-lines-v1:sha256:736dea99d4d8813ef80f5745ae68615d8429d565002cb3274f3dc9101c9d48df:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYjZhOGE3ZDg2Y2EyYzljN2VlZDUxZGNhNjY0MTQ4Njg0OTlkZDkzYzVjYTVmMTkyOTgxNmFkNWU0NDk2YWI0NCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOGQ1YzNjNjdlMDQxNTIyZTFjMGM0ZWE2MzU4YThlOWU4ZmMwYjljY2QwNDBhYzA3M2E3NGYxMjVmZTc0NzQzOCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzFiZTc4NWM0YTVhM2UzODcwZmFjODNiMjFkMjNiNTEyZDVmZDA5MWU2Zjk0YzgxNGM5OWUyOTM0YTMyYzM0ZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYmU2ZDNmZjI3MWU2YzZjZTZmNzRhNjViNmI0YTJjYzgzMTFiNTlhZWZmNTA5NDIzMDA5NTIxZGExNzRiMTU1YiJ9"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,242 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:13ee440b075102e79b27dd13511c49632f448d22bca95bd6a15fe2a7573ee4d8",
"claims": [
{
"id": "claim_70c5c3da992944188e719c65adc9b06c",
"statement": "Pro access is owned by the shared main-actor `ProAccessController`, which observes StoreKit transaction updates, refreshes entitlements separately from product metadata, and uses the lifetime and annual product identifiers `com.akinokaede.termind.pro` and `com.akinokaede.termind.pro.annual`.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L120-L150",
"version": "repo-lines-v1:sha256:3a9ea9b1019f6867b8049707e1a32bd789e570d57091ed484df1a71773af59aa:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlNmU4ZTUzOWQ0ZmM1M2ZkMDVjNmNmYWE1ZjI5MzVjYmY2ZmMxYjkyOGMzMWEyNDg2YjAzMWMzZjU5M2QxYWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU2OTFmYTU5YmU2ODkyMzY4ZjIzNzA1ZGVmOTNlNGY2Nzk3M2IwMTRkMTBkMDBhMzI0MTg0NDhlNTZhMDA2ZWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI1MmQ2NWZkNzUzMzA0OTc0OTA1ZjlkNmM3ZWE0N2ZkMWMwNDdjYzg1Y2ViMTg2MmI1NjYzYTA4NDJlOGRjOTYifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L5-L30",
"version": "repo-lines-v1:sha256:31df9012be46b10a6a018a2f46d9345679a49fa7df0368a1a92bf9c18454402f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJjMjU3YTRlMmRjYWViN2Y3NGFkYmRkZmNjMDcwNzFkZTU1ZDMyYTljNTRhMTQ2NDc4NjI2OTU3NzExZjhhNzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY1YzYxZjRkN2RhZWFiYWEyY2QxNDNlMWQzZWMwZmM2NDAwODAyMzUyNTE0MWU1OGY0ZTAwNTQyMTViY2Q3MDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjYjQ4YTEzYTZkOTI3Nzc0YmUwMDRkYzFmYjhkNTMyMDBhZDIwNDIyZTcxOTU2Mjc3NzY0ZmIzZWJkY2I5ZDMifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L67-L91",
"version": "repo-lines-v1:sha256:2e3aee85dfccdb286ebe480d758e14da2a4d6a8dc84c5acb772c775a863a1a88:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVjYjc4YTBhYmU3YWE5YTA1YmY5NDJhYWZhMmQ0Y2Y5NjQ0ZTVlZDc4MjAwYTcyZTYxY2EzMDM1YmU5ZTc2ODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhkMmY3YmFlODViOTYzNjFlYjMwMTlhYzBjZGFiZjc1YTQ5Mjk5ZDk5NzEzZDM4MTVjOTc1NGU2OTI2YjZjZjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAxN2ZmNzExODJhMzNiYzIyMDFiMTY2ZTViMTRlMDc1ZTA5MTZiYzVkNmI2Nzk1MTBlNmRkOGVjMjgxZGQzNDgifQ"
}
]
},
{
"id": "claim_c87b5b82140b4546940c2c8550a82766",
"statement": "The local StoreKit fixture defines a family-shareable lifetime non-consumable and a family-shareable yearly auto-renewable subscription with a two-week free introductory offer, localized for English, Simplified Chinese, and Traditional Chinese.",
"evidence": [
{
"resource": "repo://StoreKit/Termind.storekit#L6-L31",
"version": "repo-lines-v1:sha256:ec0609146feab84d0556dd4b296f81e17f962d95c2808907bcb89021acc7efe8:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzZTRiNjA3YTAwYTVhY2Q0NmQ4M2M1MWY4ZjUyYjlmMzkzYTViYzExZTcyZDMwMzg1YmYwOGMyZTAwZjAwZDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcxMDc4NDE2ZTMzMGNiZmY3YzY4NTAxNzYyM2VkYzZiMzlkM2I2ZDY3NGU4MDc0ZTQ1MjI1YzdmM2NiYWU3ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBmMmZkODRiMGE3MWJhOTE5ZTk4MGQ2ZTI0M2I1MzljYmE3ZWM0ZjNhOTgyNTJmNWY5OTlmNzVkYmU5YzIyODYifQ"
},
{
"resource": "repo://StoreKit/Termind.storekit#L73-L105",
"version": "repo-lines-v1:sha256:9ec6af598ebac1d9539dd633911f934b2ff0bbc874918fb2a5b5b23695b50f96:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQyZTcxMGY1N2NkMWU5ODY2OGY4ZDE5NjI0ZWYxZjI0MjFlZDg5OWU2ODAxMWU4MjE2MTVlMTA2OGNkYjAzMmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU1Y2RiNTkxMWRhMzYzYmRjNmYzZmM4NzZmNWYxMjNmNDJhNDY1OTM2MzgzNWZjMjg0NDIwNjQ0YmQ1MWExMDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc0MmNlMWQ2N2RkNzliNTQ2ZTRlNWNjMDdhMDkxY2YxOWIzOWNhZjBlODBlMzk5MzA1YjU5ZDhlYTM0MjYyYzUifQ"
}
]
},
{
"id": "claim_c3007d2070464a3a8a270214c56b824b",
"statement": "Only verified StoreKit entitlements grant Pro: a non-revoked lifetime product takes precedence, while annual access is granted for introductory trial, subscribed, and grace-period phases but denied in billing retry, expiry, revocation, and verification failure.",
"evidence": [
{
"resource": "repo://Frameworks/TermindDomain/Commerce/ProAccessTypes.swift#L22-L79",
"version": "repo-lines-v1:sha256:73c9e30b10b53977a839d1365696abecec97e9ed4385e738764f170e89d7ec03:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjczMWIzNTVmNTRjYTY5NDMyYTJiZTU2NDZhMjBjOTk5NDJmMjk1M2M2ZTYwNTI0ZGM3MDcwYzI0YWMxN2VmOGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ0NGEwMjE2ZTU3NDAxODJmYjc0ZTdmYTlmMmZhMjZhOGZkMzcyMjc4MDhiNmVkNjVkODdlYWFkN2M3ODY0YmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L279-L341",
"version": "repo-lines-v1:sha256:8aa57d11d11f5f110189dc337ec94cf0c04b6f872b99ec3c1fafb21c136a0126:eyJzZWxlY3RlZExpbmVDb3VudCI6NjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEyYjRiNjRmZWQ3ZmE4NzI0OTlkZWI2ODZhZGQ3ZmI1YTE2NDM4OTAyYzM4MzU2MmFlYTAxMjAzODJjODE0NWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2OTM1M2MyOGE2ZmM3MmVhZDlkZWQ5ZWI5OGUzNDIzZmIyNmU4ZDY0MTQxMTZmY2IwM2NjOGE4YTNjMWU4NGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNjMjZhNmNiNzg0ZDlkNTI5ZmMzNGVlY2QxNGQwZjZjNzE4OTRiOTRiNzY1NDY0ZDk0MTUyZmY4MzcxM2I5ZWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY0NDNlNWFjMmJjMzY3MjY2NTI1NjEyY2EzYTMxZTQ4ZWY2MDNmNzcyOTU2NjU3NWM5ZTcxYzQ3YjkxMTlmNWYifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L344-L405",
"version": "repo-lines-v1:sha256:c1748fec8ca19c8364bdbf33ede90e9da719c0bb138838e59541bd935944feae:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMyNGU4ZjQzZmJjYTk5NzA0MmM5MWE4OGEzZTAyZDNhNTYzZTQ4MzA3MGQ1OTVkOGU3MWY1YzYyMzU3MzdlMTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3ZTY3YmRlNTAwYjBjMTBkZTNhZDc0ZTYxYTc0NjRmMGY4MjdjYzE1ZWYyZDVlMGVkZDBiYTVmY2NiNzliMTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJkZGRmMmYwYzc1OTc4ZTJhMWFlMjIzMWM0MWE3NDk3MGNiMDY0MGFkYmY5OGIxOTM4NGYwOTBlOTAxNWM2ODIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMzOWNkNmUzZWJiNGZiOTdhMjMwMTA0YWZjNDBkMTZiMjVmYjEyYWJkZTU2NWM3NzJjN2NkMzI4YmIzOTFmZTEifQ"
},
{
"resource": "repo://TFMTests/ProAccessTests.swift#L12-L48",
"version": "repo-lines-v1:sha256:7c269e3940165ee673bc73c2404a69f92598f9e14bf50c5a13bdb51ba51b8681:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzNTAxM2IwNWQ1YjBmZWQ5NTY5OGYwMjI2NTZmZWQ4MmY4NjM5NGFjYWYwNTY0N2YyNjQ0ZjcwYmU3MjY4MDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NTJjOTcxMTBhMDM1ZjNkYjQ2MWIzM2VjZmQ1MzAwNzk5ODMxZWJlYjdlMmEzOThkMzJiY2ZmNTJlYjFlNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_d247871a71d1469fa57fa36a1fe48703",
"statement": "The controller serializes purchase operations, handles deferred purchases through transaction updates, finishes verified transactions after refresh, and treats catalog metadata failure independently so existing verified access is retained.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L152-L220",
"version": "repo-lines-v1:sha256:26ce06f94f2906a4476a2034e0ec1a616e332543e01545cc336be77ad17372c5:eyJzZWxlY3RlZExpbmVDb3VudCI6NjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE5NDQ0MTE1YjUxNTFkYmY1YTc3ZDhkODE4N2FiMzFhZjY2MmI3YTk1NTBkMjEyYjVkMWU1ZjEwYzEyYWNjZDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFiMDI0MDAzN2IyMWExMWU2NzJhZjFmMWJiZWFlYmI3MWEzODFlZDBkNzFjMzY5NDY0YTE5YjMxNDBkZTg0MzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEyMGQxNTU3ZjkzYjM3YjIxMDRhZWU0MTU2YmI1YTlhZmM2NzQ1ZTk5MDZkNjA5YmU4NzdkZDY5MjcyMmM1NjAifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L222-L259",
"version": "repo-lines-v1:sha256:d70d5fde3cfb5fc1f3ee4768e381304a95dfd6ee7b5ca07cc435233b6b83b61f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA4Y2NhYTE1NmMzMjg3MmYyM2M3ZmE4MjNhZjQ3MDc1ZWZkNDZmOGQzMTllYWM3NmU5MGQzMTkxMTYxYzYxNWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZhNWY2ZmZhMmU1ZDJhMTM5MGFhNDQ0OTZhZjkyYWIyNzI1MmIwNTc5M2QxZmEwYzIzMzMyOGNlMDc1NWU5ZTQifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L408-L439",
"version": "repo-lines-v1:sha256:7f78457b5cdc3f6d39462cdb1fa4c4872f187d67290d94e76b88f361134ab3d4:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhlMTA1YjI3MWEzZTU0Zjc4Y2MxZWY1MmMzNTY4ZjYwNzViMTY3ZTZjYmI3ZmI5MDhkZDI4ZDUzNTcxNmY2NWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRjOTI3YmRlM2Q4OGIxYWQ1MzcxY2FkMjFiZDc1MjViYWY1MWNhYzNkNjgyYWJhODg0ZTNiMGRiNGI5YzBlYWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA3MWYzYTI5NWQ1NjE5YjQwMGY5MDkwNWJiYTVhMzg3NmIzYTVlZmJjYWNiMzkxNmNjZmYxYmQ0NWIzZmMxZjAifQ"
},
{
"resource": "repo://TFMTests/StoreKitTrialTests.swift#L64-L122",
"version": "repo-lines-v1:sha256:e299315be2ffdb2539d969f5b795fcace4e81a4520c173e4bb12b5e7fccccd20:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI5NDg5M2U3MzMyMjljMGFiYmMxMTAzYzYwMzQ5NGJlNjA3OTQ4YzRiOTk5YjQxN2VjMzBlZDA3ZDIzZTk3NTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk0OGQ3NjU1YWUzZGY0MzgwYTU3MDMzZjkyYmIxNTFmYjJiMGNhOWEyODVkZjA4MTIxOWEyZGE3NmRjNjlkZjcifQ"
}
]
},
{
"id": "claim_3c3775313c2849d79dd89f7e7b5bb5b0",
"statement": "The complete entitlement-derived gate vocabulary is assistant, terminal file upload, remote MCP, built-in MCP server, Vault sync, and unlimited Metrics; `require` blocks the caller and raises the shared paywall state when entitlement is absent.",
"evidence": [
{
"resource": "repo://Frameworks/TermindDomain/Commerce/ProAccessTypes.swift#L3-L10",
"version": "repo-lines-v1:sha256:5fdfef11a66bbf817666613a29e471ab7328b43b35785a7ae598872602518436:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNGRlMWMyNzI0YTk5NDlkNGNmODMxOGZmZDFhNzIyMzNjMzZlN2M5OWE4ZGQwMGFkMzhkODgzY2M1OWJmNjI1ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjIsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTE4YmZjYzA1ZGE1ZWQ5YjU1ZGM1NzI1YTRmY2RhZWM1YzI1NzVmZGY0Y2UyMmExOTkwOWIxYjNmNGRlODFmZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMzMzYzVkNDFmMjAyMWQwOTk1YzcwYmYxZjU1ZDE2ZmY3YjM5OTkxYmY2MDg1OTU2NTQ3NmFhNjU1MDM4ZDRiOCJ9"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L93-L118",
"version": "repo-lines-v1:sha256:6a76d54ef19ad5c6b564234115af5f6d34dd4d600f01435ccb6ed36cebdbdf5f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNkMDE3YjUwYWY0OTFiMzExZTAwMzA0N2UzMGMyYWUxMDFkZDRkZjllMzRkNmE5YmI5OGEyZTIzZjIzNDI4NWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEzMGQ3MDNjMjIxZGFkNmRhMzg4Yzk5MjdjOTQyN2I5YTY5NTBiYmNlZTliMzM0NGY4OGY4YjAxOTZmNGU0OWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk3YWNjMWEyNTVjNDVmNzk5ZTAyYjM4Zjg1MGVmOGIzMDMwOTNiZTE5OTZiMDIwNTE5MjU0YzRkNjYyYTViMzAifQ"
}
]
},
{
"id": "claim_255dda6ad72a45bcb7c3f86fd120f945",
"statement": "Free access retains the ordinary remote-workspace experience and the first three Metrics cards, while protected callers gate assistant execution, terminal drag/drop upload, remote MCP operations, built-in MCP server availability, iCloud synchronization, and Metrics beyond the free limit.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppModel.swift#L525-L545",
"version": "repo-lines-v1:sha256:aad17fae07c748996e66ae9c9cbe627c73d6f20ebf16ca6ed7e0c7a56fd8b2fb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE3Y2E3MWJkZmM2MGVhMzNkYWQ0YWI2NmNkYjBjNmM5MjUzOGY1NDA0NjRkYzY1OGExMTkwYjUyZTc3MGUyMmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3YzFlN2NkMjk4NDdjY2ExY2U2MjE4ZWQ4ZGRlMDJkYzFiMTIzMmFiNWE0OGZlYzVjNGU5NGIxOWYzYThlMzkifQ"
},
{
"resource": "repo://TFI/Features/Settings/MobileMCPSettings.swift#L43-L52",
"version": "repo-lines-v1:sha256:6a4e61aaa27af6fad81a3403faa2d30b6a4709b33cdc3ebf056d086a4d768937:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3N2E2YTA3ODhiODFjMDQxNjFlMjBlYjgyYzdlMGZkOGIyNDVmMjY1YTJjZmJmMzg2ZTM5Y2ZlNThkOTczYjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYzM2M5NjlhOTU1ZTc3Njk5OTFiNjYxMGY4NDY5ZDMyZTY3OGUyM2Q3NGJhZGZmOWQ5NDRhODhhN2VhMDA2NDQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxNDRmOGIxNzcyZWYwYWU4NjA2Y2ExZjU4YzQ1YjkxZTdhZmQ1N2U3YTM2MGVhYTlkYTA3MjhkNTIzZDhlZWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYwOTM0N2Y3MmNhYWI3ZmU4MTVhNzcyMzhkM2UzNWMzODY0NWJhNTRmODZlYzkwNWEzYjczOWY3MzcxNjFjMmQifQ"
},
{
"resource": "repo://TFI/Features/Workspaces/MobileWorkspaceView.swift#L555-L562",
"version": "repo-lines-v1:sha256:20dc4bdedc36e2b39f1165283a7a67ebfe15a542f847f3d50d22db4d8ea43359:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZWFjMDVhNTBmMWZkOGZmMjk3YzNiMzc3MzUzMzVmNTIyMmU0MGRhZmNmOWVkNzVkZTQ1OWExOWY4MzZjOGNiOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZmYwZDc1OTUwZGYwZmY5YTNlZTk2NjM5ZGNjOGZmNWVhZWRiNDBkNjgyYmVhOTI2MjJiNTIwZGQ4ODdkOTNlOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMzdkNGU2ZDRhZGY1YjUzNjlhMDI0MTUzOTcyNTJhYjZiNDY4YjBhYTdiMjVmMDFkYWIzM2Y2NTFhZTI3YjU1OSJ9"
},
{
"resource": "repo://TFM/App/AppModel.swift#L168-L175",
"version": "repo-lines-v1:sha256:f0d53660f430dd84f87f5307a7fc14c2a5ed098451023878a8e6bc11d839b7e1:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNzhlNjlkZTAyNmJhNzY5YmNhODkzZmM0NDRiYTliYWM4NTRlNGZkOGI0NTQzOTUwOGZjOTI3N2UwMTljZTBmMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTUwMzJlOTY0ZDA5MzIzNTFlNWQxODUyNjkyODFiMTcxYTNhMDliMDhiMjg2ZTY2MWVhNDcwMzIzYzgyZWI0ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNkZWYwY2Q0Y2QzYTUzZjgwMWYxMGY1OWIxMzliNGE0NGE4YTM4ZDMyOGQxODY2ZWM2OThkNTk5ZTE5NTdlYyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOTRiNTdmYjk5ODgxZmRmMmRjNjU1NWQ0ZWM5Y2FjNTdlMzY4ZTYzYjdkYjFjYzMxZjFhMjliYzQ0NmVlMzdmMyJ9"
},
{
"resource": "repo://TFM/App/AppModel.swift#L232-L239",
"version": "repo-lines-v1:sha256:5fbeb435765ba0be31a7f6c42307b4a81b0525e439fc511ecfd9168f309a9097:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGEyYWQ1MjgyOWE0NDM4NjVhMDI3NTVjMjQ1ZGFhZGY5OGViNTAzMDc4MTdmMTMyYTBkOTk0MjQ4NjIxMWJhNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTkwOWE1M2E2MThkMDI4ZTFkMzAwMGMwYTdhYmNlZWNiZTVmYjM3ZjRlNTExZWZlNDY2NDNmYWQ2ZTY2ODcyZiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDg4ODAzZDYzMjJmZDM2YjkyMTExMWNlZTUxYjJmNjZmZWRjNjdiYWRiNDk1ZTFlZGNiMDc1ZTc0MzA4NmY2ZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNzBkYTJjY2ZmZmI5YzRlYzg1MjMwZTk0MzNkZWYwMWU0MjFhYjgyMmQ3YjllZDBhMDhjZDMwYjA4ODhhYmQ1MCJ9"
},
{
"resource": "repo://TFM/App/AppModel.swift#L328-L348",
"version": "repo-lines-v1:sha256:7096d285ae42140058f24ec8ba1a2d2d229718f0ae7a3d5bc1f7a8dc85101d80:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3MDMyZjUzOTcxNDA0YjMxMjM2MmZkYmQ5MzlmOGRlNjYzMGRiNGVhNTQ1Mjk5MTUxNDVlMjNmY2RjNTc0MGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdhNmVkNDJiNDliZDBjNGNkMDNiZmMwMzRkNzZiMzI2NjliZmYwOGYwOTE5OTRkMDUyNTIwODllYmEyNTEwNWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY5MWEwM2RhNGM3ZDMxZDk4YjI2YjJlYTcyNzg0YzlkOGExNjEyOTE3Y2RjZmE0NjBkOWEyYTZjMDQxODg1NDUifQ"
}
]
},
{
"id": "claim_91e20cd811814788a1350d91abb6a2ad",
"statement": "Native platform views own paywall presentation: macOS elects a single main-window sheet owner, while iOS presents `MobileProView` and uses the system subscription-management sheet; both views purchase through the shared controller and expose restore.",
"evidence": [
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift#L14-L41",
"version": "repo-lines-v1:sha256:23c7bc4783f04b1326da5618d9d292fe69931e3a41d8da9a3a307f8155d33bd1:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4MjFmMTM3MGVjN2JlMThlNDBlMWI1OGE2NGMxZGEzMDY0ZTk2NTUxZmUwMzdiNTE0OGJjM2JkZWI4MTliZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc1YzZjYTI4OGM3NzFmN2NlMDJmZWFjOTRjNTMwNDJkN2QyMDljZjA0MTk4MjcxMGExN2RhMmNjYjgyMGNlN2YifQ"
},
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift#L97-L155",
"version": "repo-lines-v1:sha256:a41d31b277d4d4152f1ed25e49a8429ce8de6905dbf6d6e4baece1a74304f2a7:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1N2U2YzM3M2E4NmNiYzcyYmVjNTMzYTNlMjUyZDk5MDQyYmU0ZWMzOTc0NzdhMTg2YTkxOTQ1MzVkOWJiYzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkzNTExZGY1YTFmMzExNjNlMmViMzBiNmM2Y2Y3NWMxZGEzNjljYjRjMThlNmYzMTJmYzgxMmJlOTZiMjdlNjAifQ"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L207-L237",
"version": "repo-lines-v1:sha256:46278fe2efd2619743b5627d51fa5f712932b91efff90e0689004a2b011be61e:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3NTYzODYxNjFmN2ZiOWMwZGU0MWVlMWMxZmU1MDM4MmY0YThiMjZlYjFjM2Q2M2Y4MWYzN2ZmOGQ3YjY1NDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L52-L109",
"version": "repo-lines-v1:sha256:40e56387488240ca3eba78f2b0403ee5b5451828f3ac9e6bd8f25d10e0c19a05:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiYTU2MzIzNTNhZmQyYzk1NDZlODZjNGE0ZjRiNzhlMWNjOThkZjJlN2Y0OWY2OTBjNTQ1M2ZlOWE4NzRjNWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYwNThmNmQ1NWJjNWQ5OGMzYWQxMTA3ZTQ4ZmQyMGMwNDdlYTVlZjA1OThjNjYxZWEwZmEzZmE4MDhjMDU5M2QiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEwMmYwZjZmYjFiNzQ5NzAxZWNmYzVmYjljN2M5NTIxM2YzMjhkMDlmNjA5MmJkODUzZjc1YjBlZWNlNmJhMzgifQ"
}
]
},
{
"id": "claim_104af269c6164fa8b46539c6989431bf",
"statement": "`AppReviewController` records review-request attempts rather than ratings or prompt completion, and only arms an invitation after a qualifying active workspace-to-review-page transition; it requires seven elapsed days, three active dates, five foreground workspace minutes, a per-version budget, and a 120-day cooldown.",
"evidence": [
{
"resource": "repo://FrameworkTests/AppReviewControllerTests.swift#L10-L75",
"version": "repo-lines-v1:sha256:127d0f024bd5bbf7d6571312a351f3ca04f4ab1d453f7f8003b72f7094df8aec:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkOGU0NWU5ZjZlYTJmYjYxMTk3MDRjNmY1Mzc0MzkwMGY1MjVjNTA2ZDE0NThhYzQzY2YxZjhlNDEyZjY4YjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM2OTljMzc0NzQwYzk4MDY0NTUzOTY4NjI3MGJlNWJkYWIzYzllYTQ5OTYxYTZjYjIzMjA2NGNmMDM4N2JlOGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU2YTlmMTg5MDM1NjkxMjY4YTg0Mjg0YzIyZDg3NTU0ZmQxMjY3NGRlMDFmNDkxYTY4MmQyMGRjYzQyYjc3MzgifQ"
},
{
"resource": "repo://FrameworkTests/AppReviewControllerTests.swift#L158-L208",
"version": "repo-lines-v1:sha256:76095faaa1c8e4cfe789bb4d9e8aedf5ff9d372b1c5090e419d3505801fddc5e:eyJzZWxlY3RlZExpbmVDb3VudCI6NTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFlMzg0MjQ0MDI5YmRhMDg0NTA3NDQ3OTY5ZDI5NGJlNmFmMGM0ZjNlNDA4YjhkNTdhNTQyN2NlYjI1MjI2YmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIwMTAxMGUzNjc4OWQ2MmFlNTE3ODczNzMzOTQ1MWQ2N2E3MjA0NGVlYjY2NGE3Nzk2ZDViMTZhMjU4MzZkNTYifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/FeatureModels/AppReviewController.swift#L3-L37",
"version": "repo-lines-v1:sha256:d13d8a0e3227a7bc2fbbda7f2d18a0d230d46d6e320a47fe16a9cc1d78c325dd:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg4MzYzZDIyZTA4MTE2MTg3OWFlMmM2Mjg2NDdhOTk2NWVmNWRkNTcwY2FmYzJkZjYyZjk2ODUzOWEzYjUwNmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZlOWYxYjA4NzYzZjM4OGI4ZWI0ZGZkZmVlZmUzMjVmYTk3MmNhNzcwM2IxZWY2YWMxYmU3NjZjMmUxNzRmOGEifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/FeatureModels/AppReviewController.swift#L79-L151",
"version": "repo-lines-v1:sha256:e338ec06bdcd9d02c5a9966c12a49e58b6281c35a9a930f50bd73619661918f6:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjczOGM0MzNiZmUyYmY4NGUxNTVhNGJjODQ5MzJmZjJhZWY3OTUwOWM4Mjg2MjExNTRiZmRiN2VjMGM1ZjUzNGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3YzRmZjVmY2EyMGUzODk0Zjc3ZmY2NDk0Y2FmNmVkZDU2NzFiZjE3N2YyMmVmMDE3NDBlNzNhMTYwMTc3OWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2YTAwMjVlYjUyYTliMDQyNGVmODk1MGNjYWJmNWY5OWJkMDFlNTE5ZWQxNDJkZjUwNThkMGU4YWZhNTQ3MDYifQ"
}
]
},
{
"id": "claim_8cb59d2af4c74383a37b91861cd0ec90",
"statement": "App localization is centralized in `Frameworks/Resources/Localizable.xcstrings`; every changed English string requires finished `zh-Hans` and `zh-Hant` translations, and the localization check rejects invalid catalogs, missing or unfinished translations, and Chinese spacing violations.",
"evidence": [
{
"resource": "repo://AGENTS.md#L46-L52",
"version": "repo-lines-v1:sha256:ee3248e602d379f9dec697411865c83301ec4b03165ce02b62dfae384112d63b:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiN2ViNmVkNjM3YmU2ODNjNzYxMmY2NzdlYTllMWE1NmI5NjU5OWU3NzJmNmQ3NjkwYjQyMzc0MGNkMTRhZmZmNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTAzYWFlMjllMDYzMTZkNmRhNmY4YzJhOTFmNmU0NGE2MTJmYWJkNzkzYWQxZjVhMWZjYTUyMDZiY2VkYTQ3YyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjZhNzFhZDgxY2FlOGI3MGJiZDYwMzkxNzllYTExZmU0OGExODY0YzdmMDcwNzU2MDQwYWJlOTYxNmVhNmMyYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWIxYmM1YmM0YTIzN2Y1NzhlNmFmNGE0MTVkMDY0N2Y5OTEwYjAzYjM2NGUxZTI3YzFmMWRiYWE3NDNkMDNiYSJ9"
},
{
"resource": "repo://Scripts/check-zh-localization.sh#L5-L65",
"version": "repo-lines-v1:sha256:67cab4f2004a6fc46d722a29d6b97cf17726952b1f426ad5215bbc22494a3e9b:eyJzZWxlY3RlZExpbmVDb3VudCI6NjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiM2ZjMjU5YmQyZWU2NDYyYzExYjZkOGUxNjZkMjU4MTVlMjNjNjkzZTA0ODRjOGZiZWQ3OTRmOTJmODI3ZDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzOTljNGUwYTRmNDI2YjhlNDA4MzZiNzc1YmUyYWJjMmU3Njc1YTcyZWQzN2UwOTBhZjA2ZTVhYTc2ZTNhNTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImExOTg0ZjI4NTg4NzhjMzQwMjJjYzU0NDQ0NjVjNGY1NjczYTE0ZGVhNGE1N2E1NmRiZTdmOTA2M2E2ODQwYzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
}
]
},
{
"id": "claim_f68095dd87b44f8da9859b708ede887c",
"statement": "The iOS widget extension contains only a workspace Live Activity; its payload excludes credentials and terminal output, is bounded to six focused-first summaries, and its strict deep links route to the workspace list or a UUID-addressed workspace.",
"evidence": [
{
"resource": "repo://TFI/App/MobileSceneModel.swift#L262-L286",
"version": "repo-lines-v1:sha256:622a6bab1aa4e5bbb0ee0f7a6684b5fccf0cec1a38034165bcaefa7db1396828:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIxMjkyYmFmZTA0M2E3OGJhYmRjMWQ1MDcwYmQ0ODhmY2I4MDM0OGEwZGUwNjdlZTI1MDQxZTM0OGUzMTM5YjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEwOWJiMzVjZWYyZTI0MmZkOWE0ZTEzY2ZiNmNiN2MxNmEzZDNlOGJmZTQ0NTA5ODM1OTY4OTQ4NjA3MDIyMzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMzYWY3YTZkNTQ2MGEzNGI4YWJiZmJiNjg4Nzg0MmJjZjY4NjljMGFlOTA0ODJkYTgxNzVkNWY2MTgzMDVhYTgifQ"
},
{
"resource": "repo://TFI/Platform/MobileLiveActivityController.swift#L32-L70",
"version": "repo-lines-v1:sha256:af164097734deb0c2f56e1a08e4d69f7ac10146df945abfcd2593c32e7f9af50:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRkNDRhNjkxZjVmZWUzMjllYmZkMGYxNGNhMTQyZjI1ZjdiOTRkMDZiYzgxOTE0NWI0MjA2MTBjMjdhMTMzMTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
},
{
"resource": "repo://TFIWidgets/WorkspaceLiveActivity.swift#L6-L87",
"version": "repo-lines-v1:sha256:5487010e8bc6b3af3520cf8c74d0870d88f91c71b609345532ca8bc83a10b5a7:eyJzZWxlY3RlZExpbmVDb3VudCI6ODIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0YWNiYTJjZTI3ZTEyYTI1YWUwZGM1ZDliMzYzZjhjNjllODhmM2I2ODgwMjEwMDgzYWI0YjU2ZTI4NGMxODQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRmODhlNjc1Yzg4M2QwZTJiNWU2ZTkzMmNkNjU1NDVhMGVlOTU3MzJjODk2ZmZjZjBjMGMzYTRhMzIzMDk0Y2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIxYTNkNDQ0NGU0MjU0M2Y5ZGZiNzE4NjEzZmQ4YjAxNDIzMzQzODM2YzM2ODJiYzRhN2JmYzIwNjNjNWRmZTMifQ"
},
{
"resource": "repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift#L4-L63",
"version": "repo-lines-v1:sha256:938424bd16bafc536af8683e97f8d8420425c89eb32056ccc5ede9b45e474338:eyJzZWxlY3RlZExpbmVDb3VudCI6NjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc0MzJiYWQ2MmU2M2RlM2Q2MmI4NmZjMGYwZGI3OTk2ODAwNzdhOTgxMTc1MmUzYTYzNWE1NDZjMjY2NTY3MjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFiZWNmMmM1YzNiMzhlM2IwOThjM2JmYjk2MjhkODdiYmQxMDQ1MGM5M2U4ZWFhMGE5YmUzNGZiZGY3MjUwYmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_f28e3dbb1a43406d9b0e46e1a16b28f6",
"statement": "`ScreenshotDemoConfiguration` is DEBUG-only and binds one validated demo scene to one of English, Simplified Chinese, or Traditional Chinese; the screenshot helper builds TFM and launches it with matching application language and locale overrides.",
"evidence": [
{
"resource": "repo://Scripts/run-screenshot-demo.sh#L5-L61",
"version": "repo-lines-v1:sha256:ee8b8d0951598ec230e3ea8f5ba3d5f04023e4aa4783059025767f99480b0b51:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3ZGJkNWExYTVkZDNiNGJkZTdmNDQzYTI0NjRkOGVlYzZiOGY4ZjI2NWJlNDAxMmY3ZTM0YTg1YzJlYzk0ZGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMzOTgzNTM4YTUxNzUwNGE0NWFkZmI1MDYwZDQ2YzY1NjlhOGY5M2I4ODRhY2UwZjY4MWU5NGI1ZjEyZThjMGMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImExOTg0ZjI4NTg4NzhjMzQwMjJjYzU0NDQ0NjVjNGY1NjczYTE0ZGVhNGE1N2E1NmRiZTdmOTA2M2E2ODQwYzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFM/App/ScreenshotDemo.swift#L3-L85",
"version": "repo-lines-v1:sha256:18e6ba83cb05aa018385523a2b45760d32bc656fda1d1cd5cdd190f8a676057f:eyJzZWxlY3RlZExpbmVDb3VudCI6ODMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAwZTBmZjYzY2I1NTE0NjU3Yzc4ZDY1M2VhZTMzOTgxZjFjYjIyMDczZjIwMjA2ZWM3YWFmY2U1MjEyMThlMTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVmYTg1YjA0NTllOWQxNGNiMzM0MjUxNzU3MWJjY2JmYTZkNWRiMjhhNzBmNmQyOTExMjA0YmFmOWI3MmVmMGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNjNTUzYmU2ZjhmZTYxZmY0ZDg3ODQyYWM0NjEzMjZhMDVhNGQ0ZGFhYWQxM2UwNzMyNWU0ZGU3YmU3MDI1Y2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhjYTcyMjZmYzUzMDI0ZjViNTA4NWU0MDA3MDJiNWE1MzNiYWIyYzljYTQyNWJmMWNjNGI3MzZlODY3MDJjZmIifQ"
}
]
},
{
"id": "claim_d41780eea21b46cba74c60f6d4ae01b5",
"statement": "The Astro marketing site is a separate `LandingPage` app whose build runs `astro check && astro build`, and it imports an explicit allowlist of framed assets rather than serving copied sources from the public directory.",
"evidence": [
{
"resource": "repo://LandingPage/package.json#L1-L21",
"version": "repo-lines-v1:sha256:832181dd1c57382ec69ce1f74d60047f776261ae8136c2185e51f09ebf1dccd3:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2ZmIwOGZkYTFhY2I5NTdiNjExNmJkMzc4MTFhMWZlNDFhMDE2MTFjMDYzMWVkYmY3ODZkNjg4OWEyN2E1NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI3ZTU3ODhkNWQ5ZDczZDI0YTgxZGJjMGE1YTc0YmZhODJjOWMzYjNhZjk5ZTUyYWY3OTZlOTBiNDY4YThhM2QiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjowLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://LandingPage/src/lib/marketingImages.ts#L1-L54",
"version": "repo-lines-v1:sha256:27008acfe7f2255cadb61f5a064788cd26fd86adc66c77b30ed03a4b533bd19c:eyJzZWxlY3RlZExpbmVDb3VudCI6NTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc2N2NjOTRiMmJlNWEzMjBkYzFhY2E5NDBkMmU2NjFiMTY4ZTQ2MjIzYjA0MGIyY2M3NDA5MzJlOTFiYzYyYmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzNjk1OTFkN2ViODY1NWNiNjFhNDc2YmFjZWU5NDI3YWYyMDQyNTMyNDM4ZWFjZDI5YmUxYjA2Y2Y5ZDNiY2YiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjowLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://Memory/MARKETING.md#L18-L19",
"version": "repo-lines-v1:sha256:efbe02aefbbf679c8d191778ebc79cc57dc7b1b64bf7a453ef13e86b5a881f66:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYjFjM2QyN2VkZjNlZWNiY2RjZDJjNGU4OTZiNGRiNmE3YjBjZDMzYmRlZjk2YWJjYmQ1YTk0ZDJkNjgxNGZkMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOTcyZTcyM2JkZjBhODdkMmZlMDU2ODhiNzU2Yzc2Njk0YmQ3MzI0MzJjNjNlYTM2YTViMDRlMjBjMGFkMWJjMCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzAwZjM4OGU4MTYzYjE3YjEyOTUwNTRlMDQyM2EzNDQ5ZTk2OTQyZmMxNTMyNjhmZjdkOWNiZDM3OWNmN2RkZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDdjMDEzOGU4YjRjMjczYjYyMzMyNzQzY2I5NTBlYWIwZGIyMzVjZmI5N2U2YmUyMjMwMDI3ZjYwNDg1YWNiMyJ9"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,254 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:f80158b701ee0dc77c084e3efa79baac40aee8b745e4db59ad684daf439dc8d4",
"claims": [
{
"id": "claim_e50b505da2214c6781fa8eb1a146dacf",
"statement": "`TermindPersistence.makeContainer` is the single SwiftData container factory: it fixes the current V30 schema and migration plan, disables SwiftData CloudKit for its configuration, rejects a simultaneous in-memory request and URL, and returns errors to callers rather than substituting another store.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L4-L21",
"version": "repo-lines-v1:sha256:75bc34d3cd5e480f2d8ea11fb1e38f4cfdde54db5adfccbc5def8238f426b623:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzMzA4NTlkNjgzODAyNWFiM2Y2NjIxNTU5NWM4N2JiZWI1ZDVlMDlmNTIxMjk3YmY2MzI3NTUwYzgxYzBjYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4OTUxYTVlMDA0MTE2ZjBmM2Y1MzVjODgxOTBiNmUwNmU3NGFmZGZlYjU2MTc0MTA0YTIzYzQyZjJiYTNlZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L118-L127",
"version": "repo-lines-v1:sha256:8a5d262e80caed31f8089ea83dc01c1168a7c8d943178df9eb503ba742bf686c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwMDc4NTkwOGZlY2YyODUxNWNhMDMxOGZkYjI4ODhhNjU4ZTQyMjVkZWZjMTAxNWExYWFmNzUxZGQ3OTUwNTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ2YzY1MmUyMjgxMzZlMDc4MGYyYzE2ODBmMGVjZTA5NzlmMTRiYjFlOTM1OGZmNzY3MGJjZWMyMTM2Y2YyM2UiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlmN2M4NjBjOTAzOGM2ODEzOWVjMTYzOGNiZThkNDYzNzYxMDYyOGY0NGU4MTk1OThjYmY2YjA0Y2MzOWIzNWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3MThiYjE3MDU3MDRiYmUxN2JjNWM5ZDRmODc2NDI3NzY4MWUyYjkwNDk5NWExYzJiOWY5MWJlYTdiNzNkZmMifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L30-L39",
"version": "repo-lines-v1:sha256:8adecd981086eaed1cad0903e82917b4d86a8e9d6e35d0314bcbb752f450f95d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjMjU4YjdiNGY1YjRhZjg4NjE4ZDI4NGJkODg1Y2VmYzNiMmQxOWRhMTk5OTlmN2ExNDI0YmQxMDliMjNjZjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZTg1YmI2MTQ1ZGM4ZDE4OWJhMzEyOTRhNDk4Njc0ZjU4M2RlZjE4ODIwM2JiZDJlZWVhYWQyN2Q3OTNjYmEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRhMzY1Mzg4MWY4OTIzZGEyYWJmM2JhZDNmMmJhYjNiZGI4YTM2Njk1YjY5MmY5YjlmNmExMWI3NWQ4MjkwZjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQxMmJjZjU5NmJmOTk3NWM2Y2ZhOTU1NWJhZjAwMjBiZmM4OWFkMjA1N2U2YWNmNzQ3NzJjZTJlNWIxMDQxMTAifQ"
}
]
},
{
"id": "claim_b568795bf1ad46c4b6004396995adb73",
"statement": "The macOS and mobile composition roots retain one process-level `ModelContainer` and inject contexts into persistence-backed services; the mobile root creates Application Support before opening its file store and uses in-memory dependencies for test/injected operation.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L23-L28",
"version": "repo-lines-v1:sha256:0a7cfe442574be25ea10e1fcdaea5023ad21f6f7ec14fa6032c8a3b77698eab4:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzU4Mjk0MTg3YmVjYjM0OTRkNjk0MjJiNzVmMGNjY2MzOWE2MjY2NDcyM2U2NmIzOTc0M2JiY2FlZjdhODc0NyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNGRjY2E1YzFlZTczZjQ2ZDZmN2UyODFjNjk4MjA4NGMyYWRiMTNlNWRjNzg4MTg2NjRiYzU5YWI2OTQ2ZDRkNSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDE4YmE0MTk2OGFlZWUyMDY2NjA3MjgyMzQ4NDBmNWRjNTY1NTExZDE5MmI3ZjEyZWVlODcwNTIwMDNlNzM3OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDkxNDgxZDkzYWI4NzRkY2JkOWEzYjY3MjhjYzg3ODBlMWZmN2FkMTY1YjFhZmMwMzU4ZGIxMGYzYThhOWUyOCJ9"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L118-L180",
"version": "repo-lines-v1:sha256:db92778684ec854d21ad83fb0e5a404e35f1b8c641d70b6e391c4263f5e48330:eyJzZWxlY3RlZExpbmVDb3VudCI6NjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwMDc4NTkwOGZlY2YyODUxNWNhMDMxOGZkYjI4ODhhNjU4ZTQyMjVkZWZjMTAxNWExYWFmNzUxZGQ3OTUwNTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZlZmNhMTIzMDYwZmVkZGE3ODBjZjAzMDMwM2YwNGYxNTM1ZWE5NzQ1ZWQxOTU4MTg1N2M2MTIyYTU3NmRmYTkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlmN2M4NjBjOTAzOGM2ODEzOWVjMTYzOGNiZThkNDYzNzYxMDYyOGY0NGU4MTk1OThjYmY2YjA0Y2MzOWIzNWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3OTYyMzI4MWRlNDNmYTI5YTFhYWUwMjYxMzE0N2U0NmQ3NGQzYTkxYzFmZGMxMDg3MDRmNjIxMzQ0ZTFhMGEifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L15-L18",
"version": "repo-lines-v1:sha256:72f66055489ca0a54a2d7ba2dae85c23c53633772a0410e5cab61e509ede8233:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNGFjZDYzNGUzMzQ5OTk5YzFmMmJkYTYyYzViMTY2OWNmZDRmMzY2ZDNmYWQyZmQzNjZhNDdmMDJmYmFmYmQ3ZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDgzYmJlNTc2ZTk0MTRlYjJjMTQwMTk4YzEyOTU1NDEzNGRhOWZmMjA2OTRmOWJkMzU4ODE1MjVlMjdlMDg5YyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzEwYmYxOWZlNGNjNzhjZDE3MWFjOGMxOWVlYmUzNzUwNzhiNGY4Yjg5NjI5MDAwOTY4NGU5OWEyZWIzNjkyNSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYjAwYTIzMzNkNWNiZTQ1NWZmNGRlM2E3ODFmMjUyNWU5OTUxMjc0NjQ5YTRiYTE0ZDdlYzIzZGQwNTE2NjFhOCJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L38-L77",
"version": "repo-lines-v1:sha256:cd060dc855bcde4d82c78e5a5f417b74beed952a63a8748fdd9eac673f76054f:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjMTgzNWMwYTZhOTg4ZDMzNTU2ZmQxNThmMGVlNDAwNzM2YTU0MTk5MjRlZDY0MWI2ODg5ZmFhMDBmZTIxNDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM4MDAwODJlYmI2ODI4YTdkMzkzYjcwZTY3NjNhNWQ1ZTFkNzdlNmNkNWI3ZDA4ZmNlMWMzZGI0NWJhZDg4MjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQxNmEwNjE2YjQzMDc3MTFiODYyZjA2ODAyYTI3OGU2ZTc2Nzk0MWRlMDM4YmI3NjlkZmNkZmYzYmE0ZDI4MTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlmYmU4MTBiMWQyMjc1MDIyNTEwZjg4MmNiZDlhMmMzY2Y3Mjc5NjhiYTMxOTA1YTQxZTk3NWRiYjUxMDM5NDkifQ"
}
]
},
{
"id": "claim_bb0d52f6f4dc4ad98daa2e4ce054b621",
"statement": "`SwiftDataHostRepository` projects SwiftData rows into revisioned host-library snapshots and commits host changes atomically with a repository revision and Vault mutation recording; it rolls the context back on failure and publishes change streams only after saving.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift#L142-L169",
"version": "repo-lines-v1:sha256:3ad6fec4a3967cb8fe84ed5630ea5994e54020a0c5dec997f3468192223c0c34:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2MmMzNTUxN2M1MjA0YWI3YmI5OWFmOTg5YjQ3NGRjZTk0ZGY2NzY3ZjZlODAwOWEzNzQ0NDI2NTJjMTdmNWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgxNWMzYzc5MTViNzEzOTdhODc2NWZjY2EzZWY2NDk1N2M4ZWU3NjVhNjg3MjE4Y2Q0ZTMzNTg4MDg0MzljN2MiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdhOTBlMmRmMGMwOGVjNjcxZDVhMGZjZjE4ZmQxNzRhMTU0N2RkMjE4N2ZiNjNjMWM3ZWZmYjQ4NmFhMzhhYjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA2Y2VjZWZhMGQ0YTVmMTQyZDJmODdiZjMzMzFlNjI0MDU5N2Y1MTRjYzQ0MTlhMGZkNmMyYmY4OTEwZDkxN2YifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift#L18-L61",
"version": "repo-lines-v1:sha256:a0cb787f4c53266915480f3e1f366df4399e18125c03d6e1cad41482cc9e1099:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkODJmMzBiNDgzNjViYzQzNDRlMzFmNmEzNTBiMWFkNjA5ZGNhODg0YjM1MjI2NWFlZGJmZWMyNzIzNjEyMjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJjZTZiOWI4MGE1MGI4NzAzYmMzMjM1Y2U3OTY5NTNhNGZjYzA0NTAzYThhMGY0MmRhMDUzNDMwNDc5ZmZiNzEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY2MWNhYzQxODkwOWE1ZGMyZTkzMjg4MzVlOTYwZTc5NDIwMzc2NjNiNDMwZWUzYTQxMjQxMzcwZmE1NDY5MGMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliZjVhODk0MDA1MzIzZTc3YTRiM2E1MTI1ZWI5YmQwN2JlNzU3NDRkZjY0M2JkMjRhZmY3ODUzNzY2NDQ3YzYifQ"
}
]
},
{
"id": "claim_5377d205f8674ceab66de9415b34e048",
"statement": "Host deletion is represented as a durable saga: the request transaction writes a pending-deletion marker and outbox jobs, snapshots hide pending hosts, later work clears dependent data, and finalization removes host-owned identities, the host, and marker.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift#L75-L140",
"version": "repo-lines-v1:sha256:1f0b48ed72eb9a6513a75fa973401243ac1c3b74939ffa9300ed407ec6d3d636:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiZjZiOTc3YTk5YjNlYWI1NjczZTA2ZmRhZmEwYWMzOTUwYzMxNzE5ZDhlNzk0MDNmNTU4Y2QwYjcxNWNiMDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3MWYxNzAzMmQ1MDMzNTY0MjE5YWZjN2I4ZjIzMjcyNmRiZGE0N2JlOWFjMzE1ZWFmOTZhYWU1N2M4MDQxZGUifQ"
}
]
},
{
"id": "claim_724958e5129a4a6a847deb92d7f33b5f",
"statement": "Termind retains frozen SwiftData schema types and an adjacent V1-through-V30 migration plan so historical model hashes and semantics remain available; V30 replaces the V29 Known Host model to remove the mismatch field while retaining trust-record fields.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/AIPersistence.swift#L6-L14",
"version": "repo-lines-v1:sha256:f1914d2ea96c7a89b7c606e14c91e627344f1409a27f1a3e9f6e8d6f9ff001de:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOWM4NmYxYWIzZGIwOWViNWJlMDk4ZDc2YzBjZWNkZmYwZWJmMTkwMmE5Yzc1YjU1OTYxOWUzZmVmMzZiMmYwNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZDBmNzdjZGRlNGQ3ZWMyYjQyMjI3ZDRhYjA3NDc2ZTc5MjY2MWVlNzI3OTQyMzZmYmYzYmI1ODMzMWUyNjc0ZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOGNkYjk3N2ZhZTAwYWNjNjBhNTJhZTM2ZmQ0MmI3NGQyMTVlNjI1ZDM4YWE5MTRmN2JlMWU3N2U1OTYzYTA4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDJkZGQzYWM3ODZkOWI1NmNlOWI0NDIyMTk2ODE1ZTI5YmY5MWYxNzA4NWNjOWVmZTZmYTM4OTVkMGQ1MTkwNCJ9"
},
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L775-L867",
"version": "repo-lines-v1:sha256:e01e4e43dafcb3540897e97312d6aac108d292442ecd50b19fda256b5f6fce79:eyJzZWxlY3RlZExpbmVDb3VudCI6OTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjYWE4OTE4YmZiNjliMDEzM2Y4NjMyYjcwM2Y3NDY1YmY0ZDY3OWM0NzllNTNkY2NlNzNlZmU0OTRlOGM4Y2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhYWU4YTBjYTc2Zjk4ZjdiN2RjNzk4NDk1MWQ2M2U1N2RiM2M2NDU1NzljYTUxYmFkNmE1MzlkNjE0ZWRiYmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV30KnownHostModels.swift#L5-L35",
"version": "repo-lines-v1:sha256:4750546fa8333fe6fb3d2bd6b3b800c6c51e25138e64ac311a0da8c6e24158bb:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY1NmVjMWMyYTlkNGE0ZjRiYjNjODhkYjNmN2ExYjQ1YWRhNTdjNWU3NzlmNjdkYzA3YWE3Mjk3NGQyYWI5MDQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjZGI5NzdmYWUwMGFjYzYwYTUyYWUzNmZkNDJiNzRkMjE1ZTYyNWQzOGFhOTE0ZjdiZTFlNzdlNTk2M2EwODgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
}
]
},
{
"id": "claim_e5eace34b0c14e78bff0e37229bf9f6f",
"statement": "Persistence compatibility tests open legacy V1/V14 fixtures, verify reopen and full-schema in-memory behavior, and exercise migrations that preserve prior values while applying new defaults or removing obsolete data.",
"evidence": [
{
"resource": "repo://FrameworkTests/PersistenceCompatibilityTests.swift#L22-L89",
"version": "repo-lines-v1:sha256:86e0ea6e63d5624d21afc6b082e4d62104188200b4b484e2ef92513b8a3fcf68:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwY2NlMjYyMzJlNGRmZGY0MzdkMDRjNDAxN2I1MWQ5ZGY0ZGYyODVjYmFkNTI4YzcxMDY5ZTA5NGRkNjNhMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjljZDY0Y2U3MWNmNThiZmMxOGRjOGNlOTc3N2RlNjVhMGU4MjcyNDc2ZDUzMDUzNDdiZDYyNmI3YjFiZTJjMmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmNjM3YTI0NzMyOGUzMTA0MWU4Y2I4MjE3NzhiYTVkNjE3ZjNlYzIyNzE2ZTgzMTdjMTU2NTU4YTk0Mjg4ZTIifQ"
},
{
"resource": "repo://FrameworkTests/PersistenceCompatibilityTests.swift#L91-L227",
"version": "repo-lines-v1:sha256:1635e37d882f0c41f616f465bab3aac02ed1473bedeb48acb1c48f5f7b57adb8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTM3LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0Y2YwOWViMGM1NzQ0ZmI5NzMzMWI5OGZmM2ZiZjA1YTYwMmJhM2Y3ZjY3ZTVkYTViZTkwOTUwMzNmNjI1ODI1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI2NjJjMzkyZmU4OGM0ZjhkYjc0ZjRlNmY3MjU1ZTQwMzBkYmM4MjMwMzVmZTc2MDkwYmExZTg1NmExN2U4MzVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MSwiZm9sbG93aW5nQ29udGV4dEhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIn0"
}
]
},
{
"id": "claim_2e5250d779cc42099b19c8fe45bf78b5",
"statement": "Durable credentials are represented by non-secret references and storage metadata; `SecretStoring` resolves those references from a concrete secret store and converts them to runtime SSH secret/key credential values, while the app roots use Keychain in live composition and in-memory storage for tests.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/SecretStoring.swift#L12-L56",
"version": "repo-lines-v1:sha256:8b142ee6e4fd012420ddcd01d0279e49db2ed680c87424cb39388c19864875eb:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk0MTJmZDViNTkwODQ5ZGZiYTZlMDQ0Njg0NTgwNGI4OWViOTdhM2I2NzIxYTgwYmRjZGNkNGY2M2U2MmJiMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmYzVkOGVjN2Q1M2E5MTkzMzI1NjYzZGMwZTdjYmZiZDgzZTg3ZGY3N2UxYzk2NmI2NjU3ZmU2NTc4NDBlMGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJhYjI5ZWRhODM2ZDRlMjE0ODhiOTk0ZTA5ZTJjZjU5ZDZmOTJlMTEzMTcxYzhhYzA2MDYzZDc2NTJkOGMwZjUifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L121-L130",
"version": "repo-lines-v1:sha256:355eb5fe58244baf7b920109cb6947317699898f99cbf6bc2bd17e133870c9e8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZmYzVhZWJhNmJiNzliODVjNTZkMDY2ZDc1OGM1ZGFhNTdlNmMwY2YyZTM2YzU5OTcyZDgwMDBmZmJkNGQyNzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE3NmVjOGUzNzljZjQ4ZGVlN2I3MWZiNGU5Yzk3ODUxNTI3NWNlOWZiMzI4ZTVjNDdkYWE2M2MwOWQ2MjAxOWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMxMDU5Nzg0MjQxZTdjMDlmZTcxMzBjYmExMGZiODAzM2U0ODVhMGI2MTdjNGJkOTRmOGMwMzg3N2E1M2YzM2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFlYzk2YjNhODU0MjlkYzFjNzUyYTA5NWQwYjUwNWIyMDIyZGYwZDQ1MDg0ODJhNDc0MzNhMGVmYzM0YTE0NDEifQ"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L136-L153",
"version": "repo-lines-v1:sha256:d27aa15b3f753c6f6b4bdf7aa8d09d4c780a5f1c0a86bb1fa8e543fe1596578d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk0ZTZmZGNjYzBhNzIxZmJlNDcyNjI3NzQ0NmUwMGMyYmI2OTVmNzIzZGNiNDgyZTE0OWRkZDE0YTVmMjBhYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJkZmQwYzE3ZjE4NTM2OWJjOTc2YWUxNjgxY2FmMzU2ZDlhNGYwMWZlMGM1MTRkYjdhNTNmYmFjMDdjNmRlZmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZkZTRmMzcxNjA0NDFkN2Y0MmQ1YjBlN2U5MjIzNzQ4OTI0ZmNkOWRmNTBiYzQ3OTYyYzg1YzQxMWRiYWM5MjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5ZDQ5M2Y0YmQwN2MyZTUyNDMyYjllOWExNWVkYTVmNDc1OWNjMTgwZjQyZDkzZDk2MWJkZGI3YjFmNTllZDAifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L52-L64",
"version": "repo-lines-v1:sha256:adec58d880d89fe0f1f83e2d36f03bcfef3d5ea246c24e1e174f8a30d927bd98:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0N2Y4YTRmZDhlNjlhM2FiY2ZlYzY3NWY2YjI0OThiNzJmNWFhNTEzOTllZjcyOGRhMTNmZTdiNjkxMTM5OWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3YWMxNjU5NmY0MjhmMjk0NGRhY2RmZjc4OTFlMWViZDJiMzczMWM2NDkyMmYxZGNiZGNmYjc0N2ExYzM0ZDQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0NzZiYjU1MWU3MGU0MjhjYmFhZGVlNjAyYTE3NjE2ODk1NzBhMjRlNjMyMWRiZTg1YmJkZjBkYzc1M2E0NzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMzYzVhOTM0MTM1ZjFiNmMwMDE5ZmIwZTY5NzM4YThjOTA3MGVmMWI1ZTE2NTc3MTRjMGI0NTY3N2M4Y2ZmYWQifQ"
}
]
},
{
"id": "claim_09af400547a2456bba57ebfabd11ae39",
"statement": "`AISecretStore` keeps only reference/location/deletion metadata in SwiftData and secret bytes in Keychain; it gates new iCloud placement on authorization and both sync switches, verifies the cloud write before removing the device copy, and keeps deletion markers to prevent a delayed Keychain value from being read again.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/AISecretStore.swift#L4-L10",
"version": "repo-lines-v1:sha256:c0a705603a62978aa00e0909837f6ed504767878bd92251ac64d2a5ba9c5488d:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNzEyMjE3ZjgzOWI1NzJiYTZlYjc4MDdhM2QwNmQ4MGMyYWE1MDQ3NTUwNTFlOWExZDcxOTliMmVmY2I3YWEyZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjg5NTFhNWUwMDQxMTZmMGYzZjUzNWM4ODE5MGI2ZTA2ZTc0YWZkZmViNTYxNzQxMDRhMjNjNDJmMmJhM2VlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjAsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSJ9"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift#L19-L46",
"version": "repo-lines-v1:sha256:8f16a29cb87c0ad0ac70e0491602272ec81393f8b123acee975a3fdf6b27a301:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY0OWEzNWM1Y2M5YTU1MTkwNmY4NTdhYmZiOWQ0ZTE3NzFlOTA2YzAxMWM3MDAwMTFhYjM2MTZkZjEwYzkyYzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY1Njk5ZjYzN2FkMjM5YWIxNjY1ODdiZTI0ZTAyZGVmM2ZjOTA4YTMwNjFiNmZmMmM1ODE3NzNkY2FjOGZlOTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk4ZDhlMmY4ZGZkYzE3MTRlYzA3MzBlOTRkZmIxMWI2ZDU1YzU1M2U3MmNiYjYwYTQ2NWVhZWQzMDBjYzdjZmQifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift#L48-L110",
"version": "repo-lines-v1:sha256:ae0deed867533fef2e0aa7f2fbc4d80a6a6385a83c5a51c400eb0db65cd9781e:eyJzZWxlY3RlZExpbmVDb3VudCI6NjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYzZlZGM3NGRjNGJhNzI4YWYxNWUyOWZlNDgxZjViZTgwOWY1ZWRhYjljZDMzMTQwMWZjZWRlMGIyOWE2OTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQyODdlYmRmMDU5M2M5ODU0NjZmOWQ4ZDgyMjc1MGU3OGU0MWRiMDYzY2FmYTA2Yjk4OTI0MTljM2E5ODkyM2QiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFMTests/SettingsSyncTests.swift#L573-L663",
"version": "repo-lines-v1:sha256:2339bf3c35a60ded5bcf75202d0a370db3247c0e3fbcefe3bf8f58f0698d0c5a:eyJzZWxlY3RlZExpbmVDb3VudCI6OTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBkMDkxM2YwZGJmMWViZTFmMDM5NTMyNGQ4MDBjZTgyYjE0NTZmMzY5MmQxNzA2ZGNmODkwZGI1NmVjNDRhN2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgxZGFlZDZmNTM1YzYwN2VkMDE0MjE5ZjZlMWE3ZWU3OGM5OWU3ZWMzYWYyZTVmMjIwYjgzYjZhNWNlMGJlYjEifQ"
}
]
},
{
"id": "claim_128e92ab767a414fb5b029490deaaa5c",
"statement": "`SSHSecret` is one-shot wipeable runtime storage: it clears the source buffer, shares one owned allocation across copies, consumes it at most once, and overwrites/deallocates it before return; connection configurations can clear credentials, proxy secrets, and jump secrets while retaining non-secret provenance.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/SSHConnectionTypes.swift#L408-L450",
"version": "repo-lines-v1:sha256:835c132dc63fefad928c3f17ab9991cd5af2cd2912121d01b6b8ffc81e0e7149:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY4ZTdlMWRhMGY0OGExZjNlZjYwZmU2YTU2ZDljMDU0YjNjN2ZiMDU3OGY1OThlODVmYzc3Mzg0YzZjZjk3MTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBmYzVkOGVjN2Q1M2E5MTkzMzI1NjYzZGMwZTdjYmZiZDgzZTg3ZGY3N2UxYzk2NmI2NjU3ZmU2NTc4NDBlMGQifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/SSHSecret.swift#L15-L111",
"version": "repo-lines-v1:sha256:6a972ae4bcfb1cbeef73352bed5244033bb3f12d78321d42a3fe9aabbde4047c:eyJzZWxlY3RlZExpbmVDb3VudCI6OTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdhZTYwYjFmZjQ2NzRiMmIwYjNhOGVkYzI2Nzc5NzJiMDU0ZGU2NDZjZjIxM2U5ZTI4NzUxZTI2MDBjZGI4ZGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYyMThiNDJkN2ZjNmZjM2I5OWI4M2RjM2U5ZTkyYTQwMThiMDExOTZkYWFjMWNmMTY5ZDFhYjQzMzA0MTVkYTEifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/SSHSecret.swift#L4-L12",
"version": "repo-lines-v1:sha256:a68dc3ba129b95768c94b47a0e84a38889ba0f06fdba8d7ff6deccf13a4d7d7d:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjg0M2NmNTc1OGIxMTRhMDRhNDg4YWIxZDkzMjQ1OTFiZjM4YzQ0MjE1OWU0MGViZDAyNWY3ZTIwMGEyNTdiMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTQ4NzFhZjk0ODVjODdlOGMwYzRkY2E3YjJhMjcxOGI5ZjlhMmY3ZDEzZGVhYzVjYzJhNjljODI1ZWFjZWJmZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiODE5OGQzZTJlNmVmYTMzYTE2ZWI2NjAzZTU1OTM0MzkzNzEwYzYwNmMwMzk3MGU5MDdmMjViYjU5ODQ5NTM3ZiJ9"
}
]
},
{
"id": "claim_5ddf4c77db3d43e4b1666b08bd09bb94",
"statement": "When interaction is forbidden, SSH connection requests replace passphrase- or user-presence-protected credentials with `interactionRequired` and make host-key or keyboard-interactive prompts fail, preventing silent auxiliary connections from consuming interactive secrets.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/SSHConnectionTypes.swift#L151-L180",
"version": "repo-lines-v1:sha256:b34609490f90971a26be17de676fce55de6c08c8965d1e58b69ff68f8cb378a5:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzYTZkNGMyYTg2Yjg5NzFlZWJmNzljZjcwMDEzNmQxODg5YzkyYjhmZWRjYmE4YzEzMDczMTI1NWRiNWVlNDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA1NmZlNWM5NTVkNTM0ZDMwMjgzODc4NjZmMmMwZmQyNzM0YjAzMjlkMmYzZmNmODJmZjNmODFiMjE1NzlhN2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAyNmRjZTI3YmE2N2MxMGJlY2JkOWU3ZjJkN2FhMmEzMjRkMjIyZDNjZmIzNTZlNjljOTlhZDI4N2VlZGRmMDIifQ"
}
]
},
{
"id": "claim_1133fb4da6384affaf2a52db22af6fd5",
"statement": "Saved credential reads for actual connection preparation, but not availability checks or missing reads, update local identity usage metadata; route preparation batches target, jump, and proxy updates, and a failed persistence write rolls usage state back for retry.",
"evidence": [
{
"resource": "repo://FrameworkTests/IdentityCredentialUsageTests.swift#L10-L86",
"version": "repo-lines-v1:sha256:8554763e9ea350ef276cf0c54893b88a26f83c1b13d47a73cde1bc32c43474b5:eyJzZWxlY3RlZExpbmVDb3VudCI6NzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM5MzUwODRjMDkzYzU3MGM4MzQ4YjNiNTBmOWYyYWMzOGU0YWJjMzNkNWE2NjViMmQ3OThmYzFkYzc3YTkwNzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUxOTExMzI5OTJmMmNhYjQ5MmQ3NGE1ODY5MzYyZmE1NmE4NmI0NzM4MGU4NjBhOWZlYzFlNGNiODAxODE1YzkifQ"
},
{
"resource": "repo://FrameworkTests/IdentityCredentialUsageTests.swift#L207-L231",
"version": "repo-lines-v1:sha256:b99f791f7bc9e162f2ddf2c6b1b36d8be0a94f86c9dca58f36aa2a47674b9cc2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBhYjkzOWE1MThhNjUxMTdmY2IwMTYyNTQ4NWZkMjU4M2ExYzU3Y2VjODYxOGZhMDRkYTg1NTExZmZmMmEwZGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ"
},
{
"resource": "repo://FrameworkTests/IdentityCredentialUsageTests.swift#L88-L179",
"version": "repo-lines-v1:sha256:28b2dc8817dc12cabc929dd0cc36a93ae37fbecfcc2d34362acb945a55dda8e2:eyJzZWxlY3RlZExpbmVDb3VudCI6OTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRhM2Y2YTAzMzc3NjliMTc3ZjczYjUwNDA0YTBmNDY3ZjRhNThjODYyMjMwOWFmOTAyNTRkMjYyOGFmNmNiMWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjYTIzZDE2OTI0YTBkMWE5Yzc0OTJhYjk5NjY3OTZhYzQxY2VhMGRmYmNiZGNmMzgyYjIxYTk5OGE4YWZjOWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L157-L159",
"version": "repo-lines-v1:sha256:f6fcef37018454e8b53190d8155992e912c868660a039faa7f299b15e85a0839:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzJhMmQ3NDIyZmUxMTY4MzU4OGQzMmRmM2IzNzY5YzE5NTkwNjFkNWNlNTg2MGU1OThkZGIwNjNjZmQzNDMxNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZjA4MWY0NzIwYjZiYzkyNGRkYTQyN2ZmOTFiMWM1MWRmYTFlNWQ1MmU3ZTBhYzE0NGQzM2MxMWE1OWM4OTI5YyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZjI4N2ZkOGRkOGUxYjQ2ZDk2M2FiMGEwNzJlMGEyOTExYWM4ZWYxNDE1OWJjZDU1NWM1MTg1NjRjMjJmMmMwNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMjczZTAwMzA4YzBkMmVhNDI0MTdhYTAzN2E3OTVlNDk3OGNmZmVkYzQ3NDUyMTc4OTYyMzQ2MDQ1OTZmZjk3MCJ9"
}
]
},
{
"id": "claim_63a8d5259915468b8626249c21d9a503",
"statement": "`GRDBMemoryStore` is a lazily opened actor-owned SQLite store in its own directory: first access creates the directory, enables WAL, migrates tables/FTS/triggers, and later `close` or `destroy` releases the queue and optionally removes that directory.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L221-L233",
"version": "repo-lines-v1:sha256:30adc0a40ea7f1daf6e6acad6683f81de04dd639bc390689e6af84cb3054932a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkOGJiNmI3OTYyOTk1OTA2ZGIzZmNmYjNmMWJiOTNmZjdjZmM1ZGVmZWY2NTYyMjlmNmNiNDIyNjkzZTE0MTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjllYWQ0NDhiOWFjMDg1ZmU0OGEzNmIwNzM4NmRmYWI3NzYwYjgyZjVkMDE0NzlkZDExMDM2YzE3OWQ1Njk1YzIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L6-L46",
"version": "repo-lines-v1:sha256:83cd37c69b35b75f335188423ef3c57774f7ffce0f1db63844b7047efc5247ef:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2ZTgzNWJiMzkzNjdhODBkMDdiMDkxZDJmZGIwODFhZGM0YThkYTg0NmQ4MjhjYjM1YzUzY2IwYzUyMjc4MDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNiZWFjYTU1MGI4N2Y4MTM4MGM0NDM2MDc1YTA3MDQ0NGJkMTRhYWQ4MzMwNTZmNjE0MmYyMDdiNzlhNjdkMDUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI1YTZiNTI2NjViMzM1YzQwMjMzMjBlNWJmODU4MjMzMGFmZDEyODlkOTMzYjg5YWU2NDQ3Nzc5NTc4YzU0YzIifQ"
}
]
},
{
"id": "claim_27622ad0acaa4b21898cab1516c0fe05",
"statement": "Hermes memory applies review operations only when the supplied expected state matches the current state, and its history replacement stores redacted user/assistant/tool messages, removes absent sessions, and supports FTS-backed or short-query fallback search.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L123-L170",
"version": "repo-lines-v1:sha256:4e602f79b32185971553efebed6d474ec0e4bb06041a7ebe3b10951fe2d1fc56:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI0Y2E5ZTU1NTliZjg3OGZhMTE1ODM3MzA0MTQ3ODRjMWYwOTU1NjRmZGY3MDYwMjYzNjcyOWJhZDZiMzAwMDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJiMjk5OGQ4MjRlNWNkNzcyM2JlZjkxYjkxYTYwMTRjMTAzMzMxY2MxNjkzZDQ0NDJhOGYzMWU4ZmM5MTM1NjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUyMGU0OWU1NGVlNTBkZTBlYmIzMjhmYTc3NTdjOGVkOWMwZTU4MjUwZTJmMzhkNWQ5MGVmNGUyMTliZDgzNGYifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L172-L219",
"version": "repo-lines-v1:sha256:0cc4745f4a717306571dfd02811a87c6d099b9ffe29ae5d474aa63e941221489:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMyMWY2Y2RlZmY2MzBmYWQ0MjkwNjJjNDNlNzU4YjZmZTdiMTQ0OGIwYzNlNTgyZjUzMDY0OGM3ODUxMjA3NTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmM2UzN2Y2NzljZDY2NzAyYjcxZjNmOThkN2IyYjYyZTAwMGEzM2FkYjQ4OTE1NDdjNjZhOTJkNDEyNGIxNzkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY0ZDk3ZDYyMjJiYWQxMTMzOGY1MzllYWNkOGUyOWI1MTI4NTcxYjc5MGU2ODIyNzEyNDJiZGRiNWI2YzIyNGIifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L69-L92",
"version": "repo-lines-v1:sha256:4930c9e1fd92fd74b94bbe8575f51ca291ed366221cf5a89b679c4a0c0e245f5:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk5Yzg3YTM4OWI4ZGZlZDBjMzc0ZGJhYjkwYmYxYTQ4ZDdlMmU0MThiODI2ODk5ZWFmMzZjMDcwYjZjNTc2MmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4Y2M5MTMxNDk2YjMyNjMyODM3NTllYjM4YzQ3OTYwZmRiYjMwNThlYWU0MzIyNDM1MWFiZWU2NmNkZTNhOTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE4YjBhMmIzYWI3MTU3NTVjOWRhYjA0NWUxMWFlOGZiMDgxOGMxNjcxZWU5NmM5ZGNkNGVlNzE5NDE2ZDc2NDUifQ"
}
]
},
{
"id": "claim_96c797e1d62b4565991af39bf957dd37",
"statement": "Agent run persistence writes durable snapshots and sanitized message/tool data, marks unfinished runs interrupted at repository initialization, and reconstructs recorded tool results that were committed before their transcript row after a process interruption.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/AgentPersistence.swift#L59-L109",
"version": "repo-lines-v1:sha256:da292992815fff9efe5274ba635a38f9c4189246f1737ba3ca30ef3208ab7ad7:eyJzZWxlY3RlZExpbmVDb3VudCI6NTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcxMjIxN2Y4MzliNTcyYmE2ZWI3ODA3YTNkMDZkODBjMmFhNTA0NzU1MDUxZTlhMWQ3MTk5YjJlZmNiN2FhMmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVmNjA3ODI4ZDQxZDU5YjhjM2Y0YmZmOWQ0ZWQyZDRkODYyMzRlOGZmOGE4M2U5OTQ4OGYyMjhjNWQzMzMzZWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliZWQ2YWM2NjQyZTQ4OWUxY2Y0NmNiY2EzNjhmYTg0MzM2OWYzYzgxNGYzMDZlM2RjMGRiMjQ0M2VjYjY0MWYifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L550-L605",
"version": "repo-lines-v1:sha256:6aa3a9f8b2bd8335e17c386f68b91564551f30ee25e239ae960ae032ef4f90fd:eyJzZWxlY3RlZExpbmVDb3VudCI6NTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzNzE0ODNiZmQ5OGM1MGM5NDg5ODlmOWEwNTJjMzI1MGUzNzMyYTczYTc2MGY1ZDJhN2I2MjFhNTJhNmUzYjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNiYjUzMTU2YTNkYjA5MDdmY2I4NDEwNjJjNjc5NjdiMzMwY2I5NTk1ZjViNWEzM2I4ZWVmNTZjZTVlMzczZjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMyZTEzMDIxNmFiMTA4MGE5ZWZiY2Q1NGIzMDdiNDk0ODU2YTUzMTYxNDc2Y2Y4ZWNjZGM0YTYxYzk3NWVlMTIifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L6-L75",
"version": "repo-lines-v1:sha256:d6a55a5ac83894bc6f31facb7b9ec18a1aa3d1c286a07c6868034542f73c54f2:eyJzZWxlY3RlZExpbmVDb3VudCI6NzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkzNzE0OTM1NDEzMWZlZDcyNmU1MTA3MDQ0NjQzM2M5YzczMGY2MWQ5MWJlZmY1MDY4OTYzZTI2NjhkZThjYTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3ZmIwOGJmYjIyNTk4ZmJiOWM0NTgyNjRmM2MxYzZiMDA2MTY4YjY5MTY2MmJjNTBhZTVjYzVlMjg2ZDU2ZmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE4NjBhNzU1MzgyZWFiYWMzMmM1MTBkNmYwNjU1ZjIxMWJmYjM4MzA4YzZjMzU5YTdkNzk0YzM1NmRiNmNkYzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkwODY1Mjc5OWI1MWU3OWUxYTg3OTZlZDMzNDM5ZDVmNTEwNTYzYjA5ODY1ZDgyOGJjYTFiZDMwYTY3MThmYmEifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L671-L683",
"version": "repo-lines-v1:sha256:f142043bb1b01de9a0458b3995239712303b9ee5f7cd1bc4531d3ee6da2913f1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ5NGQ4ZDkyN2FkMTU0ZTM2ZmFhZjZiMmI2MjMxZDllN2Q2MzRiY2IzZTliMjI2MzA4ZmJhMGVkOWQ3MDY0NjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,186 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:1ba92bb80b68bc0bcc82b721f3e819856f8ea736469dabc908eca371f6250395",
"claims": [
{
"id": "claim_7c677489fd8b4a4fadd006a4da4e9937",
"statement": "SSH is a shared transport substrate with separate feature-owned lifetimes and interaction policies: forwarding, metrics, terminal, and Agent/SFTP services do not merge their authentication or recovery state, and connection/authentication/forwarding state is memory-only rather than persisted with domain records.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L300-L308",
"version": "repo-lines-v1:sha256:2ea51fe32eccff3a2b866c406e3d3c565e426d537ecc41146bf1cc0c7f3552cf:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODFlODAyMDJiN2Y2YjgxYTUzMDk1NTcwNDM4Yzk1ZDYzM2Y1NjM3MTg0MGI0NWVlZjUwZjQzMjE5YzUzYThhNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjViMmU0YzAyOWIxNzM4NzhkYTFmNWQyMjUxYWIxMTU0NTc5ZDgyYTczNWZiMWQwYmY3NWViOWRiOGU0YWVmYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWJiYmRjMmRmOTJhMzliYzY3NjliNWU3NGU0OTk1OTUwYTVkYjQwNjhlODY1Y2QwZjJhYWI5OTk4OWI2ZDllNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDRkMDcwYzdhODU5MWY0ODUwMDU1NTY2NWY2ZWY5ZTMyZjcxOTczYzI5MTlmMzdhNDQyNTAyNmE3NWNmMzNhYyJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L69-L70",
"version": "repo-lines-v1:sha256:c8e421288cd320600e16fee3f45dd36477de3d83663f7790c1046027b6680a2c:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDQ3YjgzZmI2MjYxZmFhMWZhNDk3NDlmYTRkNDc5OGUxM2I2YjI3M2E2ZDEzODc3ZjljNzZkNDA4NGFiOGE5YSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZWUzMTA5YjlhODE1N2Y3ODgwODZhYzFlOTMwMjk2MDUyZjNhMDdlNTk0NzdkNTg4NDc2OTQxNjA4YzY5NTI0MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMDdjYzIyMWQxMWZkMDkzYTljMDdjNDY5Mzc5ZWQ5MzE5YTY5YTYzOTdhMDNkOTYxYzMwOGE1NDhkMmNjMjFjMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMGFmYjQ3OGEyN2E0MDQ0NjlmOWNhOGIxODNmZDhjY2VkYjc4NWU1MjU3NTgxMTk0NzhiZjQ5NjJjMTlmZmNlNSJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L97-L109",
"version": "repo-lines-v1:sha256:4f6f8dcd9249804009e885e9b820e706a10c848cd4212927cf468b855beca09d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlkNzMyN2M3MDQwMmJhZDI0OTJlZjk5NDI2OGM5OTdhZGYzZThmNGM2NmRkNjU1MDBmYjgwMjIyYzEyMWY4MTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3NGQ3NWEyYWI2MWYyNDgyN2E4NDc5ZWI1MmRiOGE0ZmZiY2ZhZmRjMWU2YTFmMzhlMDkwYWQwYzM2Yjc1ZDEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk3ZmZmZjgzM2E4ZjlmZjYxY2ZjNmYzODRlZTcyMDhlYTJmNTkyMzQ5OTQ5YTQwZmM1ODFhZmJiNzBjMzNiYmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU2YjRkZmNmMGJkOGIwZTEyOTY5YTdhZmIxMzI4MTY4MTE0NzNlMzU1ZmM2ZDYzMTY3YmUyOWU4NzQxYTdlY2QifQ"
}
]
},
{
"id": "claim_8335d311a32c46a5b39fc3d7dc0df067",
"statement": "Port forwarding rules are saved descriptions rather than live listeners: they support local, remote, and dynamic kinds; dynamic rules clear target fields; validity requires a nonblank bind host and port 1 through 65535, plus a target host and port for non-dynamic rules.",
"evidence": [
{
"resource": "repo://Frameworks/TermindDomain/Connections/PortForwardingRule.swift#L3-L34",
"version": "repo-lines-v1:sha256:d514b252038bd538cfde08e0dd642a3aad92f75abb2ff2fe4975d95796d002e6:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYTFlNDM2ZTgyZTY3ZWJmYTk5Njk3NjAzYzYxMmIzODdlNzBhZGI1OTBiZjU5YWNiOGY1ZjVhMzRhODljMmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3ZjVhMmFlNTgxZTUxYzlhZTM1MjZkNDZkMWM1NTAyMGQxNTY3YjU0NzhkNTdkYjA0NmFkMmVlNjNiMmNlNGUifQ"
},
{
"resource": "repo://Frameworks/TermindDomain/Connections/PortForwardingRule.swift#L54-L60",
"version": "repo-lines-v1:sha256:c359e2f664e2c96e55afe3f714839e32831992fb172acd3db7057c63b3497218:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYmM2OTJkMDViZThiNjFlM2E3MTM4MjFmZTBiN2FlMTc1NzM3MzFhNmYyZGVhYjkyN2NjNzJhYWM4YjBhYTEwOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiN2RjYzM3ZWNiOWQyYjQxODE4YWViMDE5YTliNTViYzA5OTc2NTcyZDFjNTdhNjFkMzg2NjE1NmI1OTY3MmEzYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNWI0NGY4Y2QyZmQ3ODlhYjgzMWIyYjRjYmVhMDczY2M3YzY5ZGJlMmNiZjA0NGM3NDYwMTI4NzI5MWY4MmE1NCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTBmZDIzMDI4NDRiMmJlZmI1MTQ5YzY3NTBjODM2ODYyZmZlOWVjNGM4ZjNmYjUzMjZkYzNjN2VmMjUzODBhYyJ9"
}
]
},
{
"id": "claim_73da97fed5404776a7642b71176cd60f",
"statement": "Per physical SSH connection, SSHMaxSessionsPolicy supplies a FIFO channel budget shared by PTY, exec, and SFTP subsystem channels; updates apply to live budgets without closing active channels, while forwarded TCP channels, remote listeners, and jump bridges do not consume this budget.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHMaxSessionsPolicy.swift#L4-L37",
"version": "repo-lines-v1:sha256:15cc14360ba2ad70b5fe46d62378dc22d787dbe5eee9eea962b61a2574666c3c:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMyYjFkN2FjN2EwY2UyMjRjZTFlMTRiYTc3MGM4MGY1NjVhNDc5NjQ2OTg2YjgwNGVkOWM4NmMzMjFiZWE5N2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE1OGQ0YTkxMDc0MDU5ZjBjOGQyMTM2ZjliZjgwODM0NjE0OGZjOGNmYjM1NDNkZGNiYzc1MGU3NTc2ZTcyNjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVmOWI4MWMwNzllNzQ5Y2RhNWIxODE2MmViMjFjNmQyYmJmYjMzMGQyODcxZWVhZDhhM2IxNTcwNjY0Mjc3ZjYifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHMaxSessionsPolicy.swift#L57-L193",
"version": "repo-lines-v1:sha256:796fd0bc152591e748f4399a584fb6c76177e20b1010298b6056cbc269ba7436:eyJzZWxlY3RlZExpbmVDb3VudCI6MTM3LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIzNWJmOTQ1NmIxMjM4NTQyOTg2YzQyNGRiMjBhYTUxZDk5ZjgxYWM1ODUyNTdhNGNmODk4ODczOGJjMjZkMjlhIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJkNDMzNTYwY2U4NjRhOGY5NTMxNjExZjJmZjQ5MTEwZDRjMzI4MGY2NGRlMTYxNjIzN2Q1ZTM2ZWE4ZDI5ZTg4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI1ZjU0YWY3NWQ0ODAxY2E2M2YxNWE0Nzk5YzE2YTBjNDc0M2Q0NmNmYTVjYTg5YWZkNWFmOTE2N2QwY2MwNzQyIn0"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L190-L199",
"version": "repo-lines-v1:sha256:73b8da79389cc8c548546ea6a25734903def9298bae2a8ecc8e99172f5af6f5d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRmMWQ1YmIzZDQ4YzkzYTZhOTRiODhjZmRhMTAwN2ZiNjdiNDNmMjk2MjM5ZjMyZjQyZDg4YTk4OTRkZmYwODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY5ZWNhYjI4NjRlNDZhMjlhMDlkOGM1ZGIyZjNlYzg1ODlkODNmZjdjMWE5ZGU3YThmYjYzYmI0MjllMmJlN2MiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhODk2NzQ0NjkxMzhiZDJmYjcwNTNlZDhkNzEzMDQ3OWU3YzYwM2I4YzVhYTU4YTBiOGUyZjUxMGY3ZDkzMmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ3ZmNiYTA3NDljM2Q3MDBjN2MyZGQ3YmM0OTQ5YzIyODE0ZWM1NzM3ZDk2YzdiMGY1NDk5OGExNzEzNDQ3NzQifQ"
}
]
},
{
"id": "claim_085bfb76938f4f408a9d00116ce1c49f",
"statement": "Interactive SSH PTY setup sends configured environment variables after the PTY request and before shell startup; individual server rejections are nonfatal and reported by variable name, while non-PTY services do not inherit these variables.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L1067-L1153",
"version": "repo-lines-v1:sha256:cf6dadcd49a0a06a996653ba34d2651add8904ab9039c545cd9ea162dcba16f6:eyJzZWxlY3RlZExpbmVDb3VudCI6ODcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyNGZjYWZiZmNlNWM4ZjRkZDhjMTI0YWMzYTViZTBlODhkMmZlMGQ3NjUzMjZkMjdjYWI1ZjM1ODQ4MGU3ZjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyY2Y4MDIwYTk3MWQ4YzliZjFkNTY2Njg4YTZjNTcxMGQ5YTNlYWI0ZGYwZTgzNmYwNzkxZmZlZGVlM2NiMjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA1ZWMyMjIxNGI5M2JhY2MwNmJhNjhlOWY3NTc0MjU4YmJlMjNiOTIwNzYzMjk2MTU4OTBmZjQ1N2QxNDlkNDEifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L216-L219",
"version": "repo-lines-v1:sha256:51c58ec8396dfc2cc1721bcef836bdc329cce37f90304fb0d623de0abd40690a:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTZjZjFkZTBmNzAxNjcwNTExMGRlZjNmMDZkYmZhNDZhMTExY2Y2MWNiNDZkMWEyYzI2OTJlNDI1NmE3Yjc3MSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGU3YjcwZTgwOWVmNjBmOGI0OGEwNzExMDcwYzU3MzQ0NzUxNzMwMzU2NjFiYWM2OWUyZGEzZDdmZGE2ZTIzMSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTQ3NmE2NzNiMzMxM2RmMzI1ZGY4MDVhODdmNjM3Yjc2MTg1MGU0NDZiZTYyYTczZWNmYzU5YzcyNjViYjQwMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDkyMTMzNTQ0MjJlY2I3ZjEzOTkxODQ3YzZlZjk4NTI0YzljY2RkZDRmYTIzMWFmZDE4MWZmNDNkZWE3OTY5YSJ9"
}
]
},
{
"id": "claim_a5f2f85af09a4c62b086c246d4b2ace5",
"statement": "ServerMetricsModel runs one serial worker per selected host. It connects a sampler with its own challenge-capable trust and keyboard-interactive handlers, publishes base samples before optional detail probes, and retries failed cycles with exponential delay capped at 60 seconds.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Metrics/ServerMetricsModel.swift#L48-L86",
"version": "repo-lines-v1:sha256:7dcde3c81d9bc14cf1587f8db730874513ba5b428341b04e93296f38f7323219:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2OWM3MTk3OTEyOTVjNjNkMGM3N2MzY2JmMTE5M2JhNjYzZGY5YjY3ZTE3NzI2Mjc3YmIzYzZmM2QxMTU5OTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA3Y2RjNGEzMWUyZmM5ZWQ5YzlkNDFjNjA5YjJiMTBjZjUyNDhjZmEzYzljZjg5MGFlNmNmMDYwZjMwYjU5MGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3YjcwNGRkOTYyNTc2NTQ5N2FhNzhjYzcxOTNkNTdkYWEyNDRlZWIwOTZkNzk5MTI2ODZlNDZiOTZmMWEyZjQifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Metrics/ServerMetricsModel.swift#L526-L561",
"version": "repo-lines-v1:sha256:a69317daa00d1548b8e8bb4767738e1f4c7fd2e68359a094991398bc733dc441:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ2MDA5YzU0MjE2NTg2NzdjMzYyZTM0MzNmZWJhMzAzMzkzYTM3MTQ5Y2NiOTI1ZjUyYmUxNTVkOGQ5OTE2Y2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY3YmJhN2MzNzIxMjExMjY5NmFmOWEwYWQ2M2U1N2Q1Y2RmODZjNDY2ODBlOTFhMDNkNGQ4MWYyZGJhNWU5OTEifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Metrics/ServerMetricsModel.swift#L574-L693",
"version": "repo-lines-v1:sha256:983bf7747d418fcfa2359c9f8ed1292530674ec02e30daccd736aa1798a4a955:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIwLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIzNTk2MjMwMGQxODM4NzlkZGIwYjliMTgyMGQ2NjFiMzM2YzVhNzExZDA1YTk3MTg4MjgxYjc1ZDJlOTQ5ZTc4IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIwZDc4MDg0YTY5OGJmZGUxMjM0NWM3MDgwNmU2OWYyMGQxZmUzZjUwZWQ5YWY0MDY3M2IwODcyZWE2N2M1MDNjIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI2YzVjNDEzNmNiMTZmNWZiYjgyMjUyY2NmMzE4MWQ3ZDI5NzdhNzRhNGZkNjg3MDI3YzNhYTcyYWJiZWYwNTRkIn0"
}
]
},
{
"id": "claim_80a437a3625941859c6a306d6f09af37",
"statement": "SSHMetricsSampler uses exclusive bounded SSH exec calls and marker framing to isolate structured metrics from remote shell preamble/trailer; malformed, truncated, or oversized output fails, while exit code 42 means unsupported primary metrics and GPU exit codes 42 or 6 mean no GPU.",
"evidence": [
{
"resource": "repo://FrameworkTests/SSHMetricsSamplerTests.swift#L10-L84",
"version": "repo-lines-v1:sha256:8a8a947e1736c86afd145255c47d8b532071a1def168179b3f64c55bc455d490:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJlZjBhMGJhMGQyZGY1N2FiNWFiMDUwOGM4YjA3YjdlYTVkYjQ5NmI1NjI5ZGY1MGI0MWFmMTVkMjYzODEwZDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc4YWI3Y2U0Zjk4MGU2N2QzNmE5NmVhYWJlMzA0NzZkMzcyYmViODc1ZWJjMmY5MGVjMjk0OGQ2NmI1MTU1ZjMifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHMetricsSampler.swift#L150-L182",
"version": "repo-lines-v1:sha256:eb552642c1ee42ce1defecee83d3fc251b05783155f1297231071333761ade5b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVlYjUxZGI3MDhjYTQ3ODJiZGI1MzYzNGYxMGEwNTU1ZTYyYTI4MGNmNmYzZGUwOTFmNDU1NzliNTE2NDBlYTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyODcxNjcyMjExMTkwMzRkNDJkOTI5MTNjMGYxMTEyNmExYzdhZWU0NWNjMjFjNzI2OGJmN2FhNTJlY2U4Y2EiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4Mjc2NzI4OGQzNmVjYmY4YzRkODU5OTUzMWIwZjhmNDM4MzQ5MmYzNzUwMWNmZjg0ZTU2YjVjMjE2MmUxZWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVkMGYxZDcyMGQwMzFmODJkYTc0NmFmNDA2ZDRiM2E3NTM1NTc0OTg4OGYzNDg4OTE1NjgxYTNhOGEyMjY5ZDEifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHMetricsSampler.swift#L43-L117",
"version": "repo-lines-v1:sha256:44e5f2c9be6cbf8b9464f1fdca77fbce414fdd8daf741e759aa9dc4e628c9761:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFhMWFlMTc5YzhkOTk4MmI3MjgwZjE1ZjYxZmYyYjNiNmY0M2NmZDI1NzQ4ZGMyOTVkZjA1YWNhYWEyYjdhNDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY3NjVlNGI5OTlmYmYwYzIxODYxMDY3N2E5ZGQ3Y2RhOWIyOTNjZDFjZjMwYmI0ZWM2YTI1ZDJkNmIyMzE0NTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI1YTVmMGQ3MDFkMGM0Y2UyNzczMzQ3MDM3Mjk2NjZiZDVjZGE2YmVkYmQ3Nzc1ZWEzN2E0Y2M2Y2RjN2I5NGUifQ"
}
]
},
{
"id": "claim_bb61bd5937424b5a88db0c3b856becb3",
"statement": "PortForwardingController starts only valid SSH-enabled rules, shares a host-scoped forwarding context among active rules, snapshots its maximum connection count at context creation, and uses per-rule generations to reject stale callbacks; stopping the final active rule retires the context.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/PortForwardingController.swift#L169-L219",
"version": "repo-lines-v1:sha256:ae88011f51e4d2f2fd7e6db1050ddc7e8f96b54ff29b94def1ba2e89dc7e088c:eyJzZWxlY3RlZExpbmVDb3VudCI6NTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM4OGRmYzU3MDExMzI3YjE3ZjA0YmM2MjlmNWU0Mzc5N2RmMWY3YTFiZGQ2NWFiMDg2MWRiN2VmMWRmMzY0NjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAwMTNjZTg5MzRjZDdjZGQyY2M1MTVlZDllM2YwNmMwMjYxODdjYWRjMjc4YmY1N2NkOWY2NmM4Zjg2NmY3ZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUyOThhNjQyZjM4NmE3YWE1ZTg3YTIyNGVhZWZhN2YyNjkwOWM1NzRmMWYyNTk0NDZjYzNlMDU0MmQxOGJmNWQifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/PortForwardingController.swift#L330-L354",
"version": "repo-lines-v1:sha256:02a6d1bbbd2a413d9d0b7f6e79d5a92015333ca0f007c93e1c117d9e48ca3397:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI2MDg2ZjI0YjIyMDFkY2FmMmEwYWE1ZGMyOTE0NDNiNmQyYTk2YWE0NzdhM2E3NGQwZTEzNGJkZDVmZjhmNDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc4NjI5MTcyNDZiZTY1MzE2ZjE4MmYxNjBmNWU0M2ZiM2M1MDNkNGYzMTBmMmUwYzg5MDBjN2IyNzU4YjA4NDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA5MjRjMTc1NjE4YjViOGVjNzZhNzEyZGQzNThiYzJlNWZhNzAxYzVkODZlYzNiMTAwYWIyNTBhN2M0N2NjOTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkZmQ1Njk2MDY2Mjk2YzNjZmJjMmU4MzZjYzQ4MzQwOTRiMjQ0ZmQzN2QxZjU3ZGNiMzY1Y2QxMDViZmFkNTcifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/PortForwardingController.swift#L63-L95",
"version": "repo-lines-v1:sha256:e71969161770b282030fb13020d96b6251889b42a00087f304a44902ab4bcf28:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4MmRhNjJmYTA3MDhhZDNlNjIyZWQ5NjM5NzA0OThmOWU5MjIwZTM5MDM4OGI2ZmJhYzNjYWRkODY4NjAyYmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRlNmQ1NTk0NTFjZjRlMjBiZTBmNWRhNTg3YjIxOTg1ZDNkMTk3MTU1NGJkY2RhNDQ1ZDQwYTM2OGFhMjE3MWEifQ"
}
]
},
{
"id": "claim_1659f76f8fe245c3bc795b5abc838484",
"statement": "A forwarding pool fans out only local and dynamic rules: it has one pool-level local listener per rule, registers those rules on healthy slots, assigns accepted flows to a least-loaded eligible slot with round-robin tie breaking, and keeps remote rules on the primary connection.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHForwardingConnectionPool.swift#L300-L320",
"version": "repo-lines-v1:sha256:c5ff7b25ed0e5478c01268b524ae756a24681c88b2ece9323fbdfe0e6afa8d47:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4MjM5YTMxMTJiZWYyNjMzYTY4Yjg4Nzk1OWViYWZmNmY1ZjY3ODI3NzJlYTA1YTdmNjU0MzBjNGFjZTllOTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMzMTUwOTViMTU2YWFiYjc0YmI0Y2YwYWU5OWE3MzJmNDc1YWMyNjNlOTViNmIwZDNlNWZiOTJhZGQ0MmJiNTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVjMzU3MTRiNzUwYzc5ODRkNWM5ZWMyYzZiMGI5NDU0OTE5ZTRmZTU1YmJjZjNhN2RiNzgwODMwMjQzODgzNGUifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHForwardingConnectionPool.swift#L7-L8",
"version": "repo-lines-v1:sha256:8e4f205ed9c09fe1250cb2a138270fc71860926197c51765d91fc6137abb0ab4:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNzJkNjAxNzA1MTJmZjA3MjQxYmUyN2FmMGY5N2VmMmY3OTA4YzIzMDE2ZjQ5NWE3MGZhODM5ZTg3Yzg5ZDFmZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYzAyMmM5NzY1MTU2ODVkZGNiNjgwNDQyZmJmNDNmYTIzZmM1ZmQxZTQ4MGE2OWZhMTIxMGUxZmZiN2MzN2MxZiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZWRkYjg1NzgwMGE1ZDcyNDdmZjIzYzVjZDVlNTJjNTQ3YmJmNGJjMzY1YjlhNzQyNjk5ZWUzM2RiYjI4OTJjMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTdjOWI2NDE0NzkwY2IxMTZmODBhMGI1N2RhZTJkOGEwNjk4NGVlOTAxZDA3YzkwZGU1ZGE1MmViYjgxNzFlMyJ9"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHForwardingConnectionPool.swift#L94-L128",
"version": "repo-lines-v1:sha256:fda260ceb3874c81c24929acce6d886bbb96d87494cbe9e4865195bd2def34c4:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhhYzFmODg1ZTdlYjQ0ZjM2NjMyYmE4OTE1MmVlODcxYzVkMmQ5Y2NjNTIzYzVjYzk1N2ZiNjQ5Y2E4NmEwYTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJjOWY5MzQ2MmRjNzQzMjdiOWMwZTQ5MDcxODlhYWE3NzdkOWUwOWM3NTRlM2NlNGRiZTIwM2VhZWQ1YzJlMWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMGUwNTVkMTUzZjhhNjU3MjM5ZjE0ODU5MGExMGMzNmI4MzQwZjhiZTBlZDI3MjdmOWVmMGZhNzU5YWYxYzUifQ"
}
]
},
{
"id": "claim_950d5baadbb74c6da2060fde4a10539f",
"statement": "Forwarding auxiliary connections are filled with no more than four concurrent opens, install existing shared rules before publication, retry transient loss at 1/2/5/10/30-second delays, and do not automatically retry failures requiring interaction, trust, credentials, or cancellation.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHForwardingConnectionPool.swift#L167-L249",
"version": "repo-lines-v1:sha256:c5dd7326f52fabc5c5932978402f481a8f4e495d6677058072cdc77b7d0c89ac:eyJzZWxlY3RlZExpbmVDb3VudCI6ODMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ0NTE3MzFlYzZhYWEyMmQwNDk1MjczYjdlOWIyMmVlNjY4YjFhODgyZjAwZDRmNmY3MDQzZTkxNzNkZDcwM2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM0ZGMzNTE2YjZmYjY4ODUxOGIyZmRiZDVmYWFhODJiNzk2NjE1MDNhYjI5NDAzNjU2NTViMDU0NzUzZTM0NzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFjNjAzMzU2NjQ0NjJlNzliNWZmY2M3NWViMDJlM2YzYjIxMDk0MDlkZTU4YzU3MmQ1MmQ3ZDZlM2QyMjQ4OGMifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHForwardingConnectionPool.swift#L340-L350",
"version": "repo-lines-v1:sha256:f5d72fe1ee78b73df5b04fe4227feb201146437df69aca1e2f89cf41e21664bd:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFkOGUzZThjMzA0YTFkNWQwZWRkYjljODc5OTM1NjYzZDk2YTA1YmU0ZDFiZDI1OGJlM2NhMTNkMzU4MDcwNGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU2ODQwZTVjNGYzYzQ0ZmEzMmFkYTFiNmUzOGViYjZhNjE1Y2Y1MzYyYWZjZmFkZjQ0YzQ2NWZkMzM3ZTE5M2YifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L178-L188",
"version": "repo-lines-v1:sha256:56713e56f469357822b196efb9b6de804322add53c1ad89069e014eb6613a312:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlkNjE0NDllMDA1N2QyYjkwOGNiZjYzMjdkZTU5OGFkY2I2MjQ2MGViMDE0ZjVkMTk5Y2E2YzhmY2IzYTEzYjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2NDRkNWMxNjQzOTAyNzFjMTU5MjM2OTEzMjNhNDUwMjA5YjZjYzFkNWJkZjE0NjE5Zjg2NzZiMzdmZmExZTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgyMGEyZjQzMjBiYTI3ZWZmOGZmYWJmZDlmYjBiYTE5MzA2ZDYwNDcyMzdhNWZhM2M5MzQ2MWIyOGI5NDAyYTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkzOTI4NTI0NDkzZWE4Y2NjODg1OGE5OTA4ZjExYmUyMTVmYzgyZDJiNDYyNzJhY2Y1MDg4MmRhOTUwNDZhMDkifQ"
}
]
},
{
"id": "claim_2c0cb4fc712b4684a10e547171c98f0d",
"statement": "Forwarding recovery and auxiliary opens forbid interaction and retain only reusable identity/route references rather than temporary passwords, passphrases, or once-only trust; existing TCP streams are not migrated or replayed after worker loss.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L142-L148",
"version": "repo-lines-v1:sha256:5d2590b43a7fd351b59ab40fb6dc194997d5c0b21667ba9c910db997c1264aba:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzU5MWZlYzQzZWVmMjAwMjMyMDc0NzliODBkYzVjOGQyMGRjMWQ3MDlhN2MzNTkxOGU2ZDllNWRmYzEwNTJhNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODc2YzA0ZmIwYTE5OTE3ZTdiNGZkYmVhZDk1MGI0MzI4MmFhYzg3N2RlZGRkZWI0ZjBiZTRlNmU4MzkwZjNmZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDM2Mzk5NTYxODlkNDkxNjFjZGIwNWFiZTYwYWY3MjllMDhjYTFhNjc1NGU3NTBiMWNhZThiMzFjZTA0ZDQ0MiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNzAwZjM5OWNmMDRjYTQxMjg5N2QzMTNiMGNiMWYzZDFkZjUyMzEwNDgzOGY0ZWIwNjkyZDNhYWY3NGFiNThiMiJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L181-L184",
"version": "repo-lines-v1:sha256:45c5c23aa7cbf4ef2495db69c312510d42bb74461e50a7fbf58f71adcb83be6b:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTVmZWIyZmE5MWI0YzEyNDJlYmI5ZGUxYzYzM2QwOWNkN2M1NGFmYWUyZWFkOGQ2MWNlYWIxZmIzODI0MDU4YyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTU4MjkxNWQ4MTA2NDE2NzA3MGZkMmY2MTQ3NzAzNjA1NzgxZTdhYTFlMDc4NzlhYjAxYTM5YzY5MzRmZDcwYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNWJhMzM1ODQ2ZWEwMmYwNmRlZDcwZmM4NjVhNTI2N2JlNDdiYmY2MmRkM2ZmYTAxYmVhMDJkNzA3YmQ0MWIxMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjAzODMxZWI0MDQzZTg2Njk5MTQ3NzYyZTQ4Y2M1Njg3NDcwNzQxZmVlNWFjYjA2M2NiMjIzODBlOGFmOWU0MiJ9"
},
{
"resource": "repo://TFMTests/PortForwardingReconnectTests.swift#L172-L202",
"version": "repo-lines-v1:sha256:d8649195a20f827780ac06abf7b9c8ea678f8473920d292f4bffe81e7b8d90ba:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjYzUyYmEyMWEwNzkyNjBmOTAxZWE1MzdjYTEyYWEwMWJmMTNlZjc4ZjdmOWQyZGUxNWE3NWJlMjkzZDNmMWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgxZTljNDEzYzNkNDQ0ZGI2ZWI5Mzc4NjZmYjZmMjZlYjkzZTA0ZWQxZDI0YzgwMGIxMjhjYmVmZTc4OWQ4N2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZiMTJjMTE3NGJjYmVkNDQ1OGNiNDE5NmQyZDJkMmUyZWVkNjI5ZjFlMTE5NjgwMWM2Mjg1NjNmZTI5YzAyOWEifQ"
},
{
"resource": "repo://TFMTests/PortForwardingReconnectTests.swift#L98-L126",
"version": "repo-lines-v1:sha256:126ca2648f3109930cbb465d7a74bfc5658d320d430810327b912dc24d3cfa67:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJjZGFlMzAyOTk2ZDRmOTVmMmEyNjM1MjE1NDI0Njc5YjIyMDgwNGJlOWFlNDI0N2YxOTJhOWY2OTQ2MjY0YjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU0NGJkNjE1ZDNhNTc5OTNkMTE2NWY1MWRhMmQxMjA4YzY2YzI2YTVjZDU1NzI5MjJjOWFkMTE5YTdlYTIxZmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFkZDcyYTdjYjEzOTAyMmM5MWUxNjFkZjlmMmFjMjMwNTRmZWQ5OWU4MTRmMGZkOTcxYWQ2NjkwYzdhYjhkNzUifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,310 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:31386cf38a0d16ee1dd92c94cf5aa7c8d8ca1d97425ea06d79ca64e53609daab",
"claims": [
{
"id": "claim_b47979774aa94e7dae517a6894c508d4",
"statement": "The macOS MCP listener is off by default, Pro-gated, and binds only to 127.0.0.1 and ::1 with local-only network parameters; the mobile app does not start a local MCP listener.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L499-L506",
"version": "repo-lines-v1:sha256:9cc38e58fcb2e4f8ec7a9ff1de20bc915bed5644bba1ce7048f63737ce9f517f:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOWEwMTc2NmMxZjg0MWIxZDU1YTk2NGNmZTRjNDM4ZTJkMmY4NjhmZjRiNzlkY2E3MGUwYTdhZTE2MjBjMzk2ZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYmU4M2ZiMDJlYjkyZjRhZTBkZjcyYjQzMmZjNzkyNDdkN2EyZjViMWE4MmRlOTMyZDc5NWZmZjMwZDJmY2Y2MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDVmYzVkYTRmZTNiY2ExODIxMWVhMDYwMzdmNDI3NWNkODVjNTlkNDI2MGUyODE5NDMyZjVmZmQxMWRmZDJmMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYmNmYzFkMzViZjVhNGJhOTJmZjFjNzYwYTg5OGNlYTk4ZTA3YmRjN2M0ZTdiMjUzMGE0MmJiZTM3ZjJiZGNkYSJ9"
},
{
"resource": "repo://TFM/App/MCPServerController.swift#L68-L89",
"version": "repo-lines-v1:sha256:2b418ed8ee4e50e58cae8abc2517708b7cc9df75f646a77fecbc91788e23f7fe:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1YTgyM2UzZTMyYjI3MjM5YjhjMmE4ZWJkYTRmYmViNWM4ZDZmN2I3MmI2MmM3NjY5MzE2MzJkM2M5OGRiMDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA5OGM5Y2I5ZmFjNDVhN2JjNTY3NGZiNGRhYjhjYWE4YjAwMmE0M2U5ZDUwMGFkNjFiYzI0ZjE3MjcwYmQ4NTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5M2EwMzlmOTVjZWNhZjJlYzIwMjc2ZTY2YThiYWUyN2UwZWZlOTQ1NzQzYjgzYjZlNjRmMjFiZjUyYWQ2NTgifQ"
},
{
"resource": "repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift#L99-L141",
"version": "repo-lines-v1:sha256:72c450807cefd172dec598041b65c8223bb27e73804e3b786cb06fa9779acd32:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2NWVkOTY2ZmY0ZjE5YWQxMWExOWU0MDZmMzNjZDZmNzBjZmU1ZDAzZDRiNTAyZjM4NjJiOTc5OGQ4OGEwOTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY3NWVkMDUwMmI1NWMxMGUwZmFiOTNlZDBjMmI2NWU4NzY0OGMxMGViMjczYWJlMTM5YzkyNThmODgwNzI3NjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRhOWMyOTVjM2JhMjIwNDNhZWM5OWE0YzUyYjYyM2YyNDkxZjY4YzFhNTc4NjUwM2VlYmJkNmU5OGI3ZDYyOTAifQ"
},
{
"resource": "repo://TFMTests/LoopbackHTTPServerTests.swift#L24-L28",
"version": "repo-lines-v1:sha256:d6f3744573638c3ecbc1208feaf69c76d8144774b3c19128eeb01cbc0ca9a391:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNGNmMDllYjBjNTc0NGZiOTczMzFiOThmZjNmYmYwNWE2MDJiYTNmN2Y2N2U1ZGE1YmU5MDk1MDMzZjYyNTgyNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOWVkNjQ1MDk5YWIxNGY0OTYxNmQ2NjRlYWE1NGNhYTRiODFjM2NiNWFkZTE0Y2E4NTQxZGEwM2NmMDMwMmU0OSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2EyZjkzYWJkODYzNTI5MjBmYzFiOWNkOTJiZmU2MGJhZjllNjgzMjI4N2RjNzcxYjc1MTgwZDM3NmNjZmI2YyJ9"
}
]
},
{
"id": "claim_5202470cef454890b998afbbba80c68f",
"statement": "Ordinary MCP requests require a constant-time-compared Bearer server token and, when supplied, a loopback-only Origin; ordinary request bodies are capped at 4 MiB.",
"evidence": [
{
"resource": "repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift#L279-L337",
"version": "repo-lines-v1:sha256:2ab6162481a2ac2651586a442b3da47017f299fb7683e078106c82227d364739:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmYzZmNzA4NjM3ZTNlMjRjZTExZTM0OTkxOWZjYTk4M2QxZTdjOWUzMzI4MjM1MjA0YzQ4ZTRiMDYzZDk2MGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEwYjc0ZDY4MzA0YzdkODYwMzBlZTZlMzFjZDM4NDU3NmI5N2I2YjdlMmJmMjA0M2FjMWUxNWVkY2YxZTc2MjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM5Yzc4ZmI0NTQzMzI0Y2RhZWNiYzVhNWUyMjg4MjYyZjdmMTM0NTljYzM1ZGYyMGEwMTY4ZGJiZTY5MDU2YTYifQ"
},
{
"resource": "repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift#L339-L353",
"version": "repo-lines-v1:sha256:2a80b398f54bd582509fdfbdf058a5b2947d3764187f79a502637cb28a14fd6d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJmOGI1NmVhYmEyNjJhMzBkYTI1ZmQ1NzYxN2FhN2E1ZDU3ODdkNjkxMjM5YTc2OTI4Y2MxYWUxOTkzYTIyOWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhMDA3NzdmZmZkMWU0N2ZkZDYzY2JjZDM0MGFkZWVlODk3MzNiNDM2MDQwNzFiY2RkZmNiYzhiMTBiYjg4NWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFkNjgzNDJhYWM2YzcxMjJmMjY5NjRlYzk5M2Y2ZjRmNDA5YmZjZTcyZjgzYjA2MTMxZjMyYjkxMWM0OGQ0Y2UifQ"
},
{
"resource": "repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift#L86-L88",
"version": "repo-lines-v1:sha256:45e932e939245b8c8caf2cc7443ad3b6e260f32b2331fd53ab42bfe2c7943b84:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjI1YjYyZDY2YzVjZjhhYmNmOTI0ZTNjZDcyODNkYzViNGNiMjE5OGM2NGU4ODE1NTA5MzMzZWIwOWVmOTRhNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTU4NWViMTU1MDI3NDMwNjllMWUwZDE1YzgwYjA0NDU4YmEzZGMzY2ZhOGUwNDc2ZjcyMjA5ZWUzMmFlMjZmNiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzI4MmQwZDJmMWJjMTU3NTM4MmJiMDM3Njc3OTAxYmJiZjMyOTdhOGZmNTZkNWI1MzBlMzljNDg0NzQ0NmI5ZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYjI5MzZiOTU4YTgyZjQ0OTIwMGZhMDY2ZjE1OTllYzQ4MTY0MTExMDU0NWFmZDdjYzk5MWRkNzQyYTQwZmMxMSJ9"
}
]
},
{
"id": "claim_61fbf41b2627422fb4aa95533a2d2ca5",
"statement": "The server token is generated from 32 secure random bytes, stored in this-device Keychain, and migration from a legacy iCloud value verifies the local copy before removing the cloud copy.",
"evidence": [
{
"resource": "repo://TFM/App/MCPServerController.swift#L129-L152",
"version": "repo-lines-v1:sha256:ab4b08773d9d8a61cc5c04655ea8f810639d3bd7ab78278d08394f677647eb32:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiNmIxYzBkZDkwZjExYjQ2ZWVkMDlkMTUwZjA2N2UyZTYzY2RkNmY4N2NjZGVmZTg1MTRlOTRkZGRkOGVlNjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjllNjc4ZmFlYWE5YmQxNTRlYmUxOTU1NjMwMDIyYzM1MGI5Mjc3MWUyYTRiNDdjNzkwMzJlNDk5NzY0ZjRkNWEifQ"
},
{
"resource": "repo://TFM/App/MCPServerController.swift#L233-L242",
"version": "repo-lines-v1:sha256:520a64029cab5c469abb1bde7c8c95300edd2cef0e0a8ddfd43159a7e4a5da9a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ1ZjZjYTcyNzNiYThjNTMwMTZhNTM3ZjcwMzhkOWQ3OGYzOWRmZjQwOGM0NjRlYWVmODhhZmZmMmNiZjQyYTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlODJhY2NlMzljN2VkNmY1NDNlZDc3MTFlY2ViNjM5ZmQyNTBhMWUzYTlmYzJmZTY2MDg2OTM4NGE3NjNiYWYifQ"
},
{
"resource": "repo://TFM/Infrastructure/Security/MCPServerTokenStore.swift#L5-L53",
"version": "repo-lines-v1:sha256:f66f4dcd12dae6f36149c831148c27a30308219521c8d4559dc0fe0ed2d51866:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVhNTVlNThlNTkxODdlOTY4YWJmZGQ3YTA4ZTYzYmExNGQ4MWM3Zjg4ZDNkYzMwMjNlZWE2YWQwMjc1MzAzZDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVkZGI4NTc4MDBhNWQ3MjQ3ZmYyM2M1Y2Q1ZTUyYzU0N2JiZjRiYzM2NWI5YTc0MjY5OWVlMzNkYmIyODkyYzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFMTests/MCPServerTokenStoreTests.swift#L10-L66",
"version": "repo-lines-v1:sha256:9eaa24bc68f6e54b118f88a95b778b036a9796deb0ddae0e3b59ad724a652610:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJlNWQ2MmM2MjE0NTk1MzVlNmE4MGJmOTJjMTA2MDZlNzY4ZDFiYjZlNGZlNjFmZWQxYWJjMjMyYTFiNjVjODEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJlZGFjMjZiMzJhOTI3NjVhOGFhODNhNDk4MTFiY2RlYzNhMWMzYjMyNmJhMjhlNjU2M2Y1MGU0Zjg4YWU5ZDQifQ"
}
]
},
{
"id": "claim_9a64b8332474428cabfddaa0d9239f59",
"statement": "Rotating the server token stops transfers and MCP sessions, replaces the HTTP token, disconnects active HTTP connections, and requires clients to use updated configuration.",
"evidence": [
{
"resource": "repo://TFM/App/MCPServerController.swift#L129-L152",
"version": "repo-lines-v1:sha256:ab4b08773d9d8a61cc5c04655ea8f810639d3bd7ab78278d08394f677647eb32:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiNmIxYzBkZDkwZjExYjQ2ZWVkMDlkMTUwZjA2N2UyZTYzY2RkNmY4N2NjZGVmZTg1MTRlOTRkZGRkOGVlNjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjllNjc4ZmFlYWE5YmQxNTRlYmUxOTU1NjMwMDIyYzM1MGI5Mjc3MWUyYTRiNDdjNzkwMzJlNDk5NzY0ZjRkNWEifQ"
},
{
"resource": "repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift#L148-L152",
"version": "repo-lines-v1:sha256:86543ac0371093fc5a685ec526cd2647bbe8532141e51f837d23557ab6542ab3:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYmM5ZWRjZTdmMDVhNjVmNGMwODA4ZTEyYjBiODJjZWZjMjlmMTQ1MDFmZjZlZDE5ZDJjNmRjZmRkMGYxYWZkYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDdlMWY4ZWE3MTgyZTZmYTMyMGU0YjAzN2MxOGIzYzk0MDk1NzhmNjVjMTYxZjhhOTlmNzA2NjBlOTliNzY0OCJ9"
},
{
"resource": "repo://TFMTests/MCPClientSetupCommandTests.swift#L64-L82",
"version": "repo-lines-v1:sha256:023204a2c6d366443d1203918643935a10d0404b36cef8c7ce1c6521a982a527:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4YzY3YjYwMGU3NzcxMzRhZGFjNDEzNjMwNTZiNzc5ZDczMmE5MjUwN2FhYmM2NDdiOGY2YmMxMzkwMzRhODIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFkZGNmZTI4ZDdlYTUxZmY4NzRiYTM4OTExMjA5NWY3Y2M4ZTg1MDgxZmVlMDkyOTY0MGJhMWUxMTViZWY4NTgifQ"
}
]
},
{
"id": "claim_6dc0461df9964b17808cf1f0c5757a23",
"statement": "Streamable MCP initializes a per-client session and requires its session ID and negotiated protocol-version headers on subsequent requests; the protocol limits sessions to 64 and normally expires idle sessions after 30 minutes unless transfer activity is active.",
"evidence": [
{
"resource": "repo://TFM/Infrastructure/MCP/MCPServerProtocol.swift#L342-L368",
"version": "repo-lines-v1:sha256:2391e1b5b950c55665df4b82fd25bbbb5792fd4554e8cd3164fe53a4e0e1a270:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwNTI5MjRhMzM0MjAwNWNmZjJiOGRmOWI5NmQwZTJjMWZhZTdmYzhlODM3MjgxN2E3YjI5YzA0ODhiYTliOTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJmMmNiMzA3YjRiYTljOTEyODJkMTc3MzUyYTZhMjgwOTIwMDBmYTJjMmY2ZDMxYWQ2NDhiNzYxMjBmZjUyYTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdmYjBjYWE5YWFlYzMxZDNmMDA5ZmFjYTI0NDk0ODM4NWQ5ZmIxMWQ5MGU3MjBiOTVjMTUyYWE1MzI3OTViNTYifQ"
},
{
"resource": "repo://TFM/Infrastructure/MCP/MCPServerProtocol.swift#L4-L10",
"version": "repo-lines-v1:sha256:31ef63bd55ded53401c8edcee3531bc674a34c329f3f376dad91a8f93cb67e6a:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMWYzNDkxMWU2MWY1MmYxMDIzYjI2MDYwNjBmNWViNWY5MTM0ZmU0NzQ0NDc4OGFjZTVkNjcxZWIyYjQ2OGRiYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzQ1YTE4YjY2NWM5NGU3MWM5ZDljZWY5ZDdhNTk2ZmYzNDZmZjRjYWQzYTY4NTZiM2NkY2RkY2JmNjQxMjdjNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjE2OWU5NzAxZTNkZGI5NTUzMzA1MWVlNTdkZWY5ZmIyOGI0ZDE3MjE0NmE1YTQ2YTkyMWVlNmEwYjc5ZWZjZiJ9"
},
{
"resource": "repo://TFM/Infrastructure/MCP/MCPServerProtocol.swift#L67-L105",
"version": "repo-lines-v1:sha256:105ddc47fbd3b3ad60b1fb88cbaab1fa38fc0d8e875963c4be6171c644d7b431:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM0M2VmZTc2N2UxMDRlMGQ0YmYzY2Q2MDBkMjQ5MDQzMTg2ODk3ZGYyM2ZlOTNlNjU4Nzk3ODdmMDVlM2RhZjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZkNDE1MTg0ZWNmODFhZGM5ODA5NWFlMmIyNTVkNjYzNmIxODkyY2UzMmEyNTIxNTI4MjI4ZWY5OGNhMWNhMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ4MmFlZGY1ODNmMzA2MmYwN2Q5YjE2NzViMWQwOGJlZTlmZGEzZTU1YmEwMzliZWZlYmViODliZjRkOThmYjUifQ"
},
{
"resource": "repo://TFMTests/MCPServerSessionTests.swift#L128-L153",
"version": "repo-lines-v1:sha256:05192c4f5dd3f1abd2147e5f42dbdec6663bb477c0fdd4d27391c0f706de5101:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM2Yjc0NzEyNGE2MjkxMTAzMTJlZDBiNTY5NmMzNTIyYzVhZWRhMWQ3NzdjYTA3ZDRmZDAzNDgxM2JlYTdmNTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAwNWRhOTBjMTA3YWIxMmE4NTA3NzM4MGFlMDlmNDczNmFhOGM1YjcyMmJlODQwZDkzZGRlOGQzMmUyM2M0ZjQifQ"
},
{
"resource": "repo://TFMTests/MCPServerSessionTests.swift#L19-L87",
"version": "repo-lines-v1:sha256:2a50af3e6869ca7c6b29b6723b91dfeabd5df7e239ea7ea1268d292fc4c5e99a:eyJzZWxlY3RlZExpbmVDb3VudCI6NjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZiN2YxZTY5NjYxODE1MzVjNTE2NDFkN2EzMjdmODJlZTlkYjI1ZWMyZWMyYjcwZGEwMDY0MzRlMTFjMjM2NWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE3Y2RhYzE1MTZlZDFmOTU4MGNkY2JlNWQ4NGM5YmQwNjk5YTNhNDY3OTYxODM4N2M1ZGE2OTU3OWQzYWFiOTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg5OWY2NWM4MDgxNzYyYTY4MTk0NTYxMzI0ZjYzMGE1ZGRmMjBmYWJjOWYwY2E1NjM5OWVmNzE3ZTQwMGYzMzkifQ"
}
]
},
{
"id": "claim_755f3f0d25bc4b3780a51e04427ac7f7",
"statement": "Ending, deleting, expiring, or stopping an MCP session cancels session-owned copies, transfer capabilities, external authentication requests, and brokered secrets.",
"evidence": [
{
"resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L148-L159",
"version": "repo-lines-v1:sha256:f28ea3cde8289bb585785c9de02c1a523097cd7a7e7518f5f5bc4377134548ae:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzMDI2MmM1NzZiNjU3Yjc3ZDMyM2YwYzhmNjRlMjIwY2UzYmE0MDZlODYwZWU5ODMxYzYyMzk5YjA5NDcxMjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVhOWRlYmQwNzRkNmE4ZWM4ZjU3YTgzZjNiNzUwZWRlMzhkYTc0MWYzNzlmMmViN2U3ZGUwZTc4NDhkNDBmMGYifQ"
},
{
"resource": "repo://TFM/Infrastructure/MCP/MCPServerProtocol.swift#L107-L118",
"version": "repo-lines-v1:sha256:57c101c786e2dd325b6da943a4393d840979a802b4cc1c251faa6d609b9baf79:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY0MjI1YTBjZTNhYzU1OGM4ZjNjNTIyNjllMjc0YmRjYjk2Y2E0ZmFhMDNmNmFmZmQzMmZjYWZkY2FmNjkxYWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk1YzcwOTYyMTdhYzlmZGEwMTJiMGYxZmU1M2ZlZWVhNzUxNmJhYWIzOGNmNDA5MjJhNjAwNWE2MmM4NmViMGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJkYzJjZWZjNzAzNjRjM2EzNTMzNzJlNmI5NGNiMTYzM2RjMjMyM2Q4MDE3MmVmMzE1MjQ0YmNjOGQ1MTdhNGYifQ"
},
{
"resource": "repo://TFM/Infrastructure/MCP/MCPServerProtocol.swift#L55-L65",
"version": "repo-lines-v1:sha256:2b1ab5f017aedd6d3b2672972807e8cb20f7fef3ccfd6b6b8ba59d939df6c906:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE1NWMwMDJlZmM4NzhlMjhjZDI4OGJjN2JmNzg4NGI1NWEyOTJmYjU5NGQ2OTUzOThiYWYxMDZmZDM1MGY3Y2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJmMGZhYWRiNjUyZmJjZWY4OTkwZmQ1ZGJjMTcyOWMzZDZkYTI4MTE5ZDEwODFkODk5ZmYyMzVhZjZjZTRhMjIifQ"
},
{
"resource": "repo://TFMTests/MCPServerSessionTests.swift#L212-L270",
"version": "repo-lines-v1:sha256:456903d9995b1dbcc28b0d002b3087fea275bb4dc857b7abc8e5a796e7a7480b:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFlZmQ1NmM4MWYxYThkMTEyYWIxOGY5NGQ5YzVmOWNjMzYzMGNmODM1YjhjZTYxNDdjOTllYTc4Zjg2YzRiNjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBhNTQ0NWRhZjQ3ZGUwY2VjNzk2NTU1ZTg5NTc2OTcwODY5YTMzMjgxMzI5NDVjYmEwMzA2Y2ZjMTY1MzI0YzYifQ"
}
]
},
{
"id": "claim_37f9c1c787274c10937a3d6e77ddc1e6",
"statement": "The external registry is an allowlist of Termind host tools plus request_user_secret and transfer tools; disabled tools are omitted from discovery and cannot be called, while disabling upload or download revokes that direction's coordinator.",
"evidence": [
{
"resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L183-L211",
"version": "repo-lines-v1:sha256:3c47a9f75666c7e0501e5cfe9367d0bf69ecdb6d889fe10cd823e8c92bfa297f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY5OGU0MzcyYjgwNTM0ZmI5NjNmYzVlNGFmZDlhY2JlZGQ0NTNhZWEzYjU0ODAzMThmMWE2MWZmZTQzNGMyMTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVlYTYxNGM5ZTJkZjc0NWU4Y2ZkZTdiNGIwZThiMmE5OWYxYTNjMTM3YmEzMmE5YjE4YzQ4MzBkMDg1NTY0M2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L7-L13",
"version": "repo-lines-v1:sha256:37e1cc2fd471a7feaba49f4edbfcbc40f04e035bbf4b08b3f68416aa598e3d88:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMGI0NjVkOWExMDQwNDZiYTI3NTgwNTQ3ZjNlZDgwMmEyNWExYWUxZjhjZWYxODYyNjMyZTY0ZGQwYjUwN2U3OCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYWRkMjQ0NTgyYjZmYjAzZDIzYjg0MTVhYmVjZDM0NmIwYzlmNDY2YjZmNzUyYjA2ODE4OWNlN2U5YTJkYzM1MCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmE0ZDY1ODhmOWI3YWQwODA5MzgyODExMDk1NTQ3ZTJjZDE4OGEzYTM0ZDMzM2E0OGQ4YmM5NzgxZDY0NTM5NyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMGY0ZWNlYzhkOWUyZDdhM2I4MjVjMTVlOTc2MjQwMmExZDZlZDIxMGI1YzVhNTQ5NWEwMjBjYmJiZDU1MzA1ZiJ9"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L81-L112",
"version": "repo-lines-v1:sha256:9a47d3738e9223dc103b59b1c730fef89233e69f4ef011e9ff4a31d4646cf9e8:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE4ZWM0MWMzYmVkYjQ5MGE1MzIyZDJkZWRmNGYzZDYyY2U0NjE5YzIwOWNlNmY5ODk2NWM5ZjgzMzRlMDVmYTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQwOWQxYTBlZGQxY2RmNzllMjI1Yzg3ZDFlODMxYmMwMTU0ZGExNzA1NTZhZTFkMzBlMzZkNDg2ZjhkZTg3OTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM2OGE1Yjk5MDRlNmQzOTZhNzllNGY1OWYzMmNjODc2NDA3MmUwZmMxZTJiYzg4MWM2YmIzNWViNGU3MjliM2IifQ"
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift#L99-L144",
"version": "repo-lines-v1:sha256:ac61705a90aec4fc5ad8fe90ba5336d9d529b77717009ddbf93e6f52d1fbfe85:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJkZDA4NDk0MjZmMmNmMDE4MTZiNTkwMzQ0YTBkZTI0NDUzNTVkZjliNDdmNjYyMGY4YjA0ZTI1OWYyMDg0YzgifQ"
}
]
},
{
"id": "claim_7817cc5769014bf59deebb45c183cf44",
"statement": "External SSH authentication, host-key confirmation, and command-secret requests are queued through ExternalAuthCoordinator with client and session identity; MCP shutdown cancels external requests without cancelling Termind-origin authentication.",
"evidence": [
{
"resource": "repo://TFM/App/MCPServerController.swift#L163-L169",
"version": "repo-lines-v1:sha256:07571e46f828a6d8a7fcccf5f2e5c8a7d17abde7c29d7611c4465bf53355aabd:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTU1YzAwMmVmYzg3OGUyOGNkMjg4YmM3YmY3ODg0YjU1YTI5MmZiNTk0ZDY5NTM5OGJhZjEwNmZkMzUwZjdjZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBhOTJjMzljNzhiNmU4ZmUzOGI0ZGQyOTExZTA1ODAzN2ExYWVhMzllNzYxNjllNzBhM2UwYmEwNDc5MzkxNyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNmI2NDY3NmU5OGYwYzUxNTQ2Mzg4ZTc1ZmQ0MmQ5NjBhNTI2YTYzNjZmNTEwNWYzMzI5ZDQ2YmVkZTkxODBhMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTI4ZjcwYjQ3ZWYyODg2OGM3MjIzNWM0MjM2ZDZlYWQ2NjkxMDRkY2UxNmUzYzUzN2JlYmQ2NGEwYjNkNmE3OCJ9"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L122-L130",
"version": "repo-lines-v1:sha256:3c60dee9829d7c3e4e12366ce209e6f75677a778ca73c1a48846adbadc56de6f:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZmU0ZDcwNDA3ZTNkNzRkMGZiNzA0ZTI4NGJkMjBiYjlmMmRmMmUyNDhmNGJlOTc3NjM3MTI2ZWFiNzYwMjRkMSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNWY3NWQ5MjQ1ZWM4MjU5YTA0MWJhZTM1YjUzYTgwYjU0NjdmMWM1MmFmM2E5Mzc3M2IzYjViMWI3ZTM0NTlkNCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTdmZmNmMDQxZDYwZGY4OWI2MWJhNDgwMWZkZTEyYTRkMjQxMGJmMmJmYmJmNGJmNzdhNzE5ZDgxM2FjODg1YiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2JkNzQwNjllNTUxZDNlZjViZWM2ODRmMDY1OWVlNzAxMjczMTJlNDkyMzY4YzgzMTI4NzVjNGQ5ZmQ4ZjdmYSJ9"
},
{
"resource": "repo://TFM/Features/ExternalRequests/ExternalAuthCoordinator.swift#L101-L108",
"version": "repo-lines-v1:sha256:f63dec9591ff289cb478d0e7a3a9ef342c04397df4e73ede634323638c4abdd0:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2E2YTI4NThhZjRhNTE3MDViYTkzOWI4Mzk0ODI0YTdiY2I1NTNhMjdkYTQ0NzRlM2IwYmRhMTEwNzM3YTgzNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZWU2YTdhODEzNzBkNTdiOGQyODMwOTRlZDI4ZGMxMDAzMDliYjhkMGIxNjY0MjJmYzQyNjQ0NzJkNjFkMWQ5MCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMGMwYmQ4NzJiMjQ3OWFmNzQzMDcxZWQxNzQ1NzQyZmNlOWEzYmFmMjdkNTUyZTI0N2UwMjkzYzY0ZmY4ZTUzOCJ9"
},
{
"resource": "repo://TFM/Features/ExternalRequests/ExternalAuthCoordinator.swift#L220-L242",
"version": "repo-lines-v1:sha256:e8221631a58a47118f21fd5070d10334248f32a4409e6c0b6801bacf76e6914f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxZWY4MzFhNmFkNWEyOTAxYjI1ZjY3NjM5OTIyZTkzMzJkOGRhMjY5ZjhlMjgwNGZiMDEzMjlmZTMzMjkyODgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU1NmU0NDBkMWIzMmJkZDNjZWFiMjRmMDdjOTQzYjQ1YmI1ZTA1MTZmODAyMmJlZGJjNmRjNTA3YzExNDE0YzkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYyNzgwZjc5MThiNWIzNzk1NGRhYjMwYmQ0NzRjYmQ0ZWUxMzkyZjUxNmE5NzI5NjE5NzdiYTFlMGE3OWVkNTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3MDRmMDE0MzUzZDY3ZTlkMWIwYTU2OTkxYWMyZGFiMDY5YzAxMTRkY2RlNWZjNGRjMjRjNjJjYTFkZDU5NzIifQ"
},
{
"resource": "repo://TFM/Features/ExternalRequests/ExternalAuthCoordinator.swift#L43-L68",
"version": "repo-lines-v1:sha256:75bf711f2f0a811c485387403656e1ab2a650a37b834592192b092a5d7c53291:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzMjkxMWJiZTk2YTk0YjdjMDQ1Yzg3Y2I4OWIzMjdmNDU4ZDEyYjQ2MjgyYjA1Y2Q4Mzk3ODZiNTQ1NjI2MDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI0Y2RiMjAwNTk2ZTMxMWNlNTU5Y2U4MDQ0OWEzM2UwZjQ3MDkyY2RlYzUzYTk4YmMzNzhmMjA5ODZjYTE1ZWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZlYzA0YzQ1ZTlmNDc2NjQ1NmRiNDRlYzVmNzc4ZDg1NmNhZWYwMmVlZGJmZjRmNWQ0MjUxN2E3MmRjZGUzZjUifQ"
}
]
},
{
"id": "claim_6c0fa0b6b31441d99c95ef7caed28eaf",
"statement": "request_user_secret returns a one-shot secret handle rather than plaintext; ssh_exec consumes it only when its session run, host, tool, and purpose binding match.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSSHTools.swift#L368-L398",
"version": "repo-lines-v1:sha256:cb9d274af2cf8597e6f1f980c89a727c1918d02e74f6823041b01be3deb3a1ee:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI5NDExYmI4MTU0ZDk3MjI1YTkzY2I1N2RiYzBjMWQyNWJiNTFjMDY0OTI1YjExNTJmOWNhMjE1OTYyMzRlNmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmMjk0ZjkzNDI3Mzk0YWEyOTE5MjRlZTljNzcwNGU5M2FkYzNmYWVkZmY5ZGVjYzljZDQ4OTQwZmJjMmQ5ZGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkyZWE4NDk3MjE5MmRjZDM4NmQzOWEwMTg5MTc5MDA2YzVlZjk0MWFhYWM4MDMxNTgyNzYyODdlNDZjMjcxNDAifQ"
},
{
"resource": "repo://TFM/Infrastructure/MCP/MCPServerProtocol.swift#L212-L224",
"version": "repo-lines-v1:sha256:25766f6e2406b151006120962301eb408397aa5d1f831ae50372c5089b966bc8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU0OWE5NzMxOTQ4MzRkNTUzMGQzYTQ0ZWI0ODE2MWVhYTc1Y2RmODU2ODNhZDNkMzg0OTUwMWM2NTE1ZWQ5NTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIyMjU5ODI0N2IxZjM4NjljNTgyNDMwZGIyY2E4NDcxMGM5NjY2NjRiODg0OGI1YjVkOWQxMTg5NzEzMWFhY2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZiYmJiMjA4YWJiMTY3MGJlODQyZTJmY2VhMGRkYzZlZGZhNjM4MTNjOTc2OGJkZDNlZWNjZTkwMjc4Y2VlZDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3NGY0ZThmYzg0YTRlZGJmZjlkMWY4OGJiYzRlOTMwMWRiZTUwYWQ5MWJiODdhZWE3MmQ5MjAyZWYzYWZjZjEifQ"
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift#L163-L220",
"version": "repo-lines-v1:sha256:8f55eddb350b48ec03a92dc56e1188a661f025bc60a8e98de8a95b9105539a9b:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgyYzhlMmNiZTdiN2JiODBiOWJlYWI5NWViOTcwODljNmIyNDVlZDg4OWNkZjhhNDk4ODhjNGEzNzEwOTM5MTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
},
{
"id": "claim_8fbd1f89a02b48c49d7cbd189d1627c1",
"statement": "Uploads and downloads use separate ten-minute, session-bound capability tokens in Authorization headers rather than the long-lived MCP token; they share a four-active-transfer budget and are revoked by session/host/stop/token-rotation/direction-disable events.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L311-L326",
"version": "repo-lines-v1:sha256:eb9cda7e1398b7fa0b8a8ff215711bf4bc391fb6f96540c58b8f7344276b5923:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4NzdlMzllNDYyZWE2MDM5YWE1ZGM3OWU3M2YxZjU5YjEyMTIzYWJhZjk3MWMyZDRhOTRmZjFiNjFlNDMyMzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmNTk1ZDE1Yjg4YzFiYWY5ODE3OWJjMjlmMzI5ZTcxN2M1ZmFhMDBlOWQwNTI1MmU2NWIyNDhmYTM5MGUyZjMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY0ZTFiNDI2NzhjZDRiMTViZWQ0NzI4YjQ4M2NiM2NhNmRjMzRiMjE1ODljNzE2MDE1ZDZhZTM3N2QzYmYyZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUxNzhmNjIxM2Q1ZjA5ZDExZjczMWU2MzEyZDFjYTMxNTcxNjIyYTZjYTE4Zjk4YjVlNmQwMjkwMTdhOWY4MTkifQ"
},
{
"resource": "repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift#L217-L277",
"version": "repo-lines-v1:sha256:d932d52dc4c2673b397e64c53fb9d013fcdd8f5cc135869bf63dad2fb393c972:eyJzZWxlY3RlZExpbmVDb3VudCI6NjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBiNDMzNDI0MjE2YWM3OWRlMjVmMTZiNjFmODIxYTM1OGM0ODliNDJlYzBhY2Y2OWRkMzI5ODk1NzM1NmZmYzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyYWI1NmFjMGE4NjliZjgwOWVlZTFiZGRjZTM4OGFmMDc3YzlmYjM2NzI1MjFkYzdmYzk1ZTIwOWExMTc3Y2EiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcyOTgxOGE2Mzk0NGMzYjc3YmZhMGU0MGEwN2ZiNTc5YTkyMjcyNWNlMzJiNjUwNWU4ZGQ0MGY0M2ZkNzE5NzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFlYzNlZTBmMDUyZjE0NzNjYTM3NWYyZmY1ZTY4YzFkZDAyODU0YmEzYTRkZDYyYzNlNjg0ZDQ5Mjg5Mjg1NjMifQ"
},
{
"resource": "repo://TFMTests/MCPDownloadTests.swift#L247-L319",
"version": "repo-lines-v1:sha256:960f275d7a66407224cfe6e6973db15085e58706655344d702c9efc80dd6733b:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ0N2FkMzZiNjQ5NDIzNzFmZTMwMWU4OWMzZGJjNmQyYmQ4MjU4ODVhNGE5NTllMTJiYmFmMWZhNTZjZTQwODUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVkOWNjZWIxYmRlYmU3M2M2MzkwMmYxMTdlNDAyMzkyNzRiNTlmMTExYWU1ZGM1MGRhOWIyM2YyNTJkYmM1ODYifQ"
},
{
"resource": "repo://TFMTests/MCPTransferTicketTests.swift#L12-L25",
"version": "repo-lines-v1:sha256:b25d86a95f72b93aeaf1ff4ca22da9028f3ad52f88d1dd66e310fd6e2dbff9ba:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwYzU5Y2UwYjcwZDAxOGFhYzUwOTMzMWFjNGMwZjlmYjk0MDgyNTU2NzYxMjM1ODc3YzcwMGRmMjIyMGQwNWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI4MTU3MjlhYTk3ZjQwZGY3NDY2ODM4Y2FjZTY3NjUyYzAyZjczZTQxMjQ2MmU4YjFkZTAwZDQ4NDgxY2UzNjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEyZTQ1ZTBmY2JmMjQ2NjYzZmU1OTFkYzJhOTFmNTQyN2I0MmZlYzUwMTIyN2E3OGRlODljNjI0ZjdmMDBlM2UifQ"
},
{
"resource": "repo://TFMTests/MCPUploadTests.swift#L170-L183",
"version": "repo-lines-v1:sha256:5652af48187376a120fac2185df737eeea357f6e0fec8c18d97ef34bcd8cb881:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA3ODU3MjU4NGVjYmQ1YTAzZmVmYmE2ZDMzYjQwMWZiYTFjNzIxMDA0YmZjNjljZDA4MzdmNTg4OWRiNzY3YjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxNjExMzgyNGIzMGY1OGRkNDk3NDEwN2E0MDNlNzcxMzU3MjJmODM3YmU1YmNjZTJhMGY0YjQ3ZWYzNTNiMTkifQ"
}
]
},
{
"id": "claim_1735b2aa4f0b41dd839e59df1c437cee",
"statement": "The upload capability is atomically claimed before its body is read, streams with backpressure, verifies exact length and SHA-256 before commit, and only resumes at a verified acknowledged offset.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L313-L316",
"version": "repo-lines-v1:sha256:c75606a9803f7fecddb06690c9c755ea85aeda572211f872c297bc3498ef4229:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDMyYzhkMTFkZWUxM2Q1OGVhZTU2ZDgwNTM1NGEyZTI3OTA2YjYyMTM4MTVjZDM4YWQwZDkwYjk0ZTAyZjZlNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTJmYTE1ZjE3NzllYzdhOTVjMzVlMWY5Zjk2ZjdhNTk4NzhiODIwMjMwY2EzOWI0ZDgyNmIxYWUxYWM0ZmU3MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZmMxZWYzMTZjNjQwOWU1MmRmNjllYzdjZDk0ZDljYTk5ODYwMjFmOGZiNDczZmY5MjJkMzdmNGNiY2U1ZmVlYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWFjZjc0MGQ4ZTAxY2Y1ZDFmYTkwNzcwYjRhOTk3YWJiNWZkYTVmZTBhNzM5OGEyOGZmZGI2NDc2NzFiZmRkYiJ9"
},
{
"resource": "repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift#L238-L277",
"version": "repo-lines-v1:sha256:1e6a4938731ea4995bc2158010fa44a577ffc2875ac5422b910d72b7b4f2f83e:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3NWNkMThmZTdmZmY5NGZmOWZjYzM0YzZiZjRkN2E3ODBiOTNkNDQzNzQ3MGEzOWUxNzY0OWJiZDc5ZTA3NzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyYWI1NmFjMGE4NjliZjgwOWVlZTFiZGRjZTM4OGFmMDc3YzlmYjM2NzI1MjFkYzdmYzk1ZTIwOWExMTc3Y2EiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA1NzBkNWJiYmQ1ODFjNGE4N2Y0MzQ1M2UyNzBkYmYyNTI3ZTUyZjRmZWRiYTJhZDBlNjFjNzc3NmMyZjRjNmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFlYzNlZTBmMDUyZjE0NzNjYTM3NWYyZmY1ZTY4YzFkZDAyODU0YmEzYTRkZDYyYzNlNjg0ZDQ5Mjg5Mjg1NjMifQ"
},
{
"resource": "repo://TFMTests/MCPUploadTests.swift#L138-L153",
"version": "repo-lines-v1:sha256:d5a699b94a84346bad72bc23b2949008961c5950dfb4372cb799a368d5640756:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3ZTQ5ODIyYjI5NTBmNjk4ODlkNGQ2ZWMxNmVhODA4YzAzM2VmYjg5YzVhMjRkMWE4ZDBhYjdmMTRiZTMwZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwNDkwNTdmZmYzMTI0YmI1Zjg4NGIwN2ZhOTM4MmY4OWM5OWYzZmNiNDM3MmEyNzM4N2M0M2JkYzQ1ZWYyMDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
},
{
"resource": "repo://TFMTests/MCPUploadTests.swift#L16-L45",
"version": "repo-lines-v1:sha256:76eac58ab509219efc87394272fa4f8b9cd1a4d536657160e9cef6e5cba8af4e:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlmY2VkNmIzYWFmM2IzNmM0NzAzNjhkNTU0YjBmMDNiZjBhMjVkNzQ5YzQ4ZjMyMjA2YmQyNDI1ZjI5Njk2ZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU1ZDNlYzM2MGVlNTljOTZkOWMxMTllZDExZGFjMTJkYTcwMTM2MTRlZGMwM2ZiYTk2MmJlZWYyZjE4N2M3OWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliZTNjNmIwMjM5ODhlMjA5YmZkOGMzMDY1ZmM4MWIwNDFiYTk5MDQyNzcwZWFmM2E1ZGUyMGJmN2M5ZjY1ZDcifQ"
},
{
"resource": "repo://TFMTests/MCPUploadTests.swift#L312-L338",
"version": "repo-lines-v1:sha256:b03677327e85c65f6949e96f77c8a4fd85bf408dfdf72c2348b5a2e62b4c8965:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI1YzdhNDUyMGUxNmI0YzUwNGMzOTRhMzA0YmI0YTgzZDM4ODQ2NGZmZTFlNjM2ZTNkNTI5ODViYTlmMjc4NDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjExZjE5ZjhlZGVkNmQ5MjQ3N2RiNGIyOGEwZjEyOGY3YmVhN2RhNzY4ZTYzNDk3ZjMxNTI5YzliMTNkMjI3YTEifQ"
}
]
},
{
"id": "claim_5cc40f4e3cea406a9769e7cfbd77c66c",
"statement": "A download ticket does no remote I/O until GET; downloads stream regular files without staging, support only a validated continuation Range, and do not mark success until source validation, send completion, checked close, and lease release succeed.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L316-L321",
"version": "repo-lines-v1:sha256:c521d862fd133f0f313354b53d4a1c9c9610d0fab7f94ab2199eda846fc05183:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTJmYTE1ZjE3NzllYzdhOTVjMzVlMWY5Zjk2ZjdhNTk4NzhiODIwMjMwY2EzOWI0ZDgyNmIxYWUxYWM0ZmU3MSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiY2I0YWRlMTU1Y2RkMGY4OTE2M2EyMzliYTVkYTFhNDRjZWIwNDNiNzFjZjMwNDBkOTBlODVlYzFlMmFmYmU3OSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiY2RlOWYzNjBmMzZhNTc5NzhmYWVkNDJjNTAxZTJkZTVlMWQ1NjYzMmIzZTNiNjlkMGZiOWNlMTc5NGZlMzVlZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTQ2NTk4NzczM2I5NWE0ZTBkYmRlMTY2MTVjNzA5MTdjMmRiNWIxMjYwMDU3OGIyZGNjYmRkNmY2MGExMGZiZiJ9"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L63-L79",
"version": "repo-lines-v1:sha256:6d2d2c94a832b6099ceebc2e310be31584972e05e53521424e0a83989596d335:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlMGY1MDQzYWYwMmFlOTFhMmVkYzNmYWNmNjk4ZThmZGFiMDljMWI0YTk0ZmIxODE4YTUyNzY4MzAzZDM3MzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkwZjc0YTk2NWQ3YjBjOGMyZWJhYWE2ZDliOGRjYzc2OGQ2NjM3MzU3MmUyYWMwODY3ODgwMDZmZjcyZjIzMTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJkMTFiYTMwZGM1OGFkNDczY2Y4M2E1ODcyZDU0YjZkZjk3YjE2YWQ3NDVlYmVlOWVhOWY0NTg5ZTZiNzVlYmMifQ"
},
{
"resource": "repo://TFMTests/MCPDownloadTests.swift#L142-L179",
"version": "repo-lines-v1:sha256:49d3273f513d94220b6540841e37ee411a8a3490d71deac5baf4ec9915b0925a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiMzdkYTVhNjc3MDQ5YzAyZjU2NGYzZjNiOTI2YmRiMTBjNGVlZDczNmI3NDc3MTE5MGFiMzNjMjU5NjRkYTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE2ZWFiODMzNzI3NjY0NzYzMTczN2YwZTExNmQyY2U2NTIxMzAxODA5NTI2ZDRlYjQ1OTkzMWVjZWMzYTk0N2QiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI4Njk3YzYyNGM1YzY0NGRmZjJjMzljMzllNzgxYzRmYjJhZThmMzFhYzEzOGE1YzVkNWM4NmE3OTE3MmVhYmEifQ"
},
{
"resource": "repo://TFMTests/MCPDownloadTests.swift#L16-L78",
"version": "repo-lines-v1:sha256:ef3c31640c4c2acccb8cb162c7b9fc15396df9507b3ac020321327d834b9ffc1:eyJzZWxlY3RlZExpbmVDb3VudCI6NjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQzZTA4MDZiYjIwZDQ3YzU3Y2U1NWI1OThlMzJiYzgyNmJmYmU4YWNjZjE2MWU1OWU4YTFjNGJjNTRjNjBjYmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkyOTVkNTY5YTlmZjM5NWNkN2MxMzZmYWZmZWY5NGZhNmJhZDU0NWZmMTE2MDIyN2Q1NjVlNGUwYjAxZDdlMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM5NThhZGVkMTUwMDU0YWQ3M2Q4NWU2OTc0NmNlYmE4MzllNjk4MjBkYzZjMmNiOTRhYzkyOTU2OWZiMDhmN2MifQ"
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift#L19-L56",
"version": "repo-lines-v1:sha256:6c9d4ab2ea40427641fcf155c2d918077ce5493e34d3fcc1fa9a926828e77996:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhMjczMjdhYTBhZWQxZjcyNmEzMmNjNjM0OGRkNjYzNjkxNjM4OGU3OTZiM2M3YmNmNDdkNWZhNTE2OTBjZGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ1MTEyNGM0ZTYwZWVkMjRiODk4YmNlNjk4NjMyOTRlNjJjZTliYTg0NDMxYmJhYTIzMTYzZjY4NWJjMzgzNWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
},
{
"id": "claim_1b436fd9e17b4d40a35c6c84fc8c4fe7",
"statement": "The termind-mcp executable forwards newline-delimited stdin JSON-RPC to the loopback HTTP endpoint with a Bearer token, retains session and negotiated-version headers after initialize, emits responses on stdout, and best-effort deletes its session at EOF.",
"evidence": [
{
"resource": "repo://TermindMCPBridge/main.swift#L109-L130",
"version": "repo-lines-v1:sha256:4b0af7bee6f0f7d20c1f50e99d9ff54805bf9306b28f10aee8ee646a4a2209d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIyMjM0MWZjYTQzNTFmOTBiYzJlZTdlMDU0M2FiY2NmOGMyNmQyNDQ4ZjM2NjJhMTMzNjkyZjE4ZTM4NTkxNTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdiYzA0MzAyOWJiOTU2MjMyYzRhNmEyNDc3OGZlYTY1ZjhlYzBmYWUwZWI5MzkxM2U5OTM2YjBjZjU1NWEwMzkifQ"
},
{
"resource": "repo://TermindMCPBridge/main.swift#L4-L89",
"version": "repo-lines-v1:sha256:f0dc917a6f7b9765dd6c5504f028594035370070e80760584ae763c99844e5a1:eyJzZWxlY3RlZExpbmVDb3VudCI6ODYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0ODcxYWY5NDg1Yzg3ZThjMGM0ZGNhN2IyYTI3MThiOWY5YTJmN2QxM2RlYWM1Y2MyYTY5YzgyNWVhY2ViZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE1Zjg2NzQwNGJjMDM4MzA0MWMzZTZhNzBkNjFhMDJlY2U5MjVmZDI0NTVmY2IyYWRmNmEzMDVlMDk1NzEzNGMifQ"
}
]
},
{
"id": "claim_986f78895b9e4325a67200aae5554924",
"statement": "Client setup commands use direct HTTP for Claude Code, Copilot, and OpenClaw, while Codex and Hermes use the bundled termind-mcp bridge with URL and token environment variables; command generation is disabled when its required token or bridge is unavailable.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/MCPClientSetupCommand.swift#L3-L52",
"version": "repo-lines-v1:sha256:775676079246dcf2e0078e7137fa10f4972f7de64d28607c346123778644985e:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3YzlmNTZlZTRmNzY1YmRlOGJkMzM2NzZmNTNlNjAwOGM1Y2NhMjU5ZTJjNmU4NWU2MWQ0NTIyOThiODlmNWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFMTests/MCPClientSetupCommandTests.swift#L17-L110",
"version": "repo-lines-v1:sha256:676f68b4f8a905336cf6f8b0b5bc81a72bcf7ea601c3b8f4e551d921c3876c36:eyJzZWxlY3RlZExpbmVDb3VudCI6OTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBiOTg0YjBlZTVlMDZlNWRlNzQzMTYwZjc2MTlkMDNiMjNmMTFjOTU2ODUxYmU5MWRmNDUzYmVlY2UzMzU4MzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjExMTM5NDQ5ODE1YWRkNzZiMTM3OGJkODhiMDU3MmQ5MTk5MjA2YTdhYTQyZmM2ZGVjYTk2MjkzYWRjMGMxZjQifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,206 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:65a192526c7077d01d0e5a58245de0d19f7c103accfcb0d8ed32d612ea0bb477",
"claims": [
{
"id": "claim_d34d7b16495a44a4a946d3dc9e0456f4",
"statement": "Ordinary Xcode builds, tests, and screenshot builds must retain `-onlyUsePackageVersionsFromResolvedFile`, because the repository directs builds to the pinned resolved dependency versions rather than allowing a fresh dependency resolution.",
"evidence": [
{
"resource": "repo://AGENTS.md#L26-L34",
"version": "repo-lines-v1:sha256:a91f88bee69fc799fe765bb122f6b5106642c565be05fb945780ea3d3248ebf3:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTczYmEyNjc2YzMzZGE1MjMyNTFkNWNjZjUzNjViODFhMGEwMjMyZWU3MGI3OTFlNmJjMTNmYTIyNTFhMGQ4MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYjNkZGYwYjM4NzRlMWFmZmJlMzgwYTg1YWUxM2E2MDNhMzNjZmNmMDQ4YzBmNDM0NTNmYThkOTY4OTcyOTk2OCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzE4ODJlOTJlMDU3MTI0MDRlN2M4MWQ2Mjc2NTIzMWQ5Y2VkZjg5MGNlNmUwZTVlMDBhZDk2NzIzOTA5YzA3OSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTMwM2VlYzhlNjU1MjZiMzI1MWUyNDRmNjljMGIwOTMwY2ZmNTFiZDhiODRkMzZhMzk1NzJlZDg3YjIyOWZkOSJ9"
},
{
"resource": "repo://Scripts/run-mac-marketing-screenshots.sh#L43-L51",
"version": "repo-lines-v1:sha256:9474f3899cd27c703003d0bd9b0541dac067c03e0babf5d69c8c4018e4966ba5:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZWNhOTQyYzcyNGNmZmM3NzY4ZWYzZmM5MmZmYTJmM2QwMDg4OGM4ZWFhYThiYWI5MWVmM2M1NDczYWQ5ZDNmNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMWJkMWIzODk5MDdjMTI3Mzc5NzM2NWEzZjhiNDVlYWFiNjJhNDQzODllYTg4YzdlYzJkYTA0ZDY2OGJkYmRlYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmY4NTJmMGUyNmY4YTJjZTYyNDQxNjcyMTJhOTc5MzYxYjljMWVkNTQ0NDU3MWRmYjZmMTJlYmMyNTQzZWRhOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjhmOGYwNGFmMDdmMGVmY2RiNTdkMWJiMjlkMjQwZjhkM2FlOGRiMDhkYzEwMmUxY2IyMjhkYmIxMDhmOGI3NyJ9"
},
{
"resource": "repo://Scripts/run-mobile-marketing-screenshots.sh#L161-L167",
"version": "repo-lines-v1:sha256:714b87dbb33b249ff4afd6b97b11bd3242291ef48f7922ca6754f6762cbfc1f2:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjg1Y2YyZWExYzhiZDM2MTk5ZGUyYTlkM2M0MzFmMWM1MDQ5ZmNkZTdlMGIzNWZhNjQxZTBkNzQwYWZjZTQwMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZjM2ZWJiNDZhZTk4ZTQzYTkxNjAzNDczYzY5YzdkNWE0ODcwODNmZjgyZWMyODA2MThiYmE1NmUzMGVhZjMxMCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiM2U0MDU5Y2Q2YTY3ZTE0MTUyYjg4Njg0OTM0NTgwNDljNzY0NTNiYTlhOTkyMzYyMTI3YWJhNTkwOWUyNDExMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjcxMzllODgyYmE1Yzc2YWU0YzcwM2I0YTMyZWFlNGI5YmY2OWNiOTYyNzAyN2RhMmVhZjQ1N2JkOThhMDJkMiJ9"
}
]
},
{
"id": "claim_65fcfe9af8eb41a3967800a39eb84530",
"statement": "The project’s primary native build entrypoints are the `TFM` macOS scheme and the `TFI` generic iOS Simulator scheme; the TFM build also builds the MCP bridge and AgentKit, while TFI builds the mobile app and shared frameworks.",
"evidence": [
{
"resource": "repo://AGENTS.md#L26-L31",
"version": "repo-lines-v1:sha256:388a61ace4d6d2e8a6a9fe6a9a2b0ee6a67122ab831f7d0a49eba6d9e9cd10e5:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTczYmEyNjc2YzMzZGE1MjMyNTFkNWNjZjUzNjViODFhMGEwMjMyZWU3MGI3OTFlNmJjMTNmYTIyNTFhMGQ4MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDgxNGI5ZThhM2Q1ZWE2YjA0MmVlOWE3OWU0NGM0Y2IzZmM5NDRkNjdlOWI2ZjNlYmEzOGNkYTFhOWZiZjM1OSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzE4ODJlOTJlMDU3MTI0MDRlN2M4MWQ2Mjc2NTIzMWQ5Y2VkZjg5MGNlNmUwZTVlMDBhZDk2NzIzOTA5YzA3OSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMjBhMGVhOWU0ZTc5NDI3YWMyNzUwOTk4ZTg2M2ZiOGE2ZDEzNDI5YjRhZmM0ZmEwOTdiOThhZTQzNTc1MGU3NSJ9"
}
]
},
{
"id": "claim_1a9166d8adfa413f8574be310dec6512",
"statement": "The default resolved-package `TFM` test command runs macOS and shared Swift tests, while an available iPhone or iPad simulator destination is required for TFI tests.",
"evidence": [
{
"resource": "repo://AGENTS.md#L29-L31",
"version": "repo-lines-v1:sha256:b01fe78aa30f13a1b9b6592963253ce9311901af610a5e20419e2e04a1e8b6ff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNDVhM2YxNTdmNDc0Zjc4OTI2NzY0MjhmMTE0NWE5YjBlZDU5OTg4NDNmNTU0YTAzNzNiMmIxMjFhN2E2Mjg0MCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDgxNGI5ZThhM2Q1ZWE2YjA0MmVlOWE3OWU0NGM0Y2IzZmM5NDRkNjdlOWI2ZjNlYmEzOGNkYTFhOWZiZjM1OSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMWY0MzVkMzdiNmYzMWNjNmFhZjdjOTFmZGY3Zjg0Nzc5Nzg2NDgyZWE0MGI4N2I4ZTIzMWFlOGQ3OWY4ZmUwYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMjBhMGVhOWU0ZTc5NDI3YWMyNzUwOTk4ZTg2M2ZiOGE2ZDEzNDI5YjRhZmM0ZmEwOTdiOThhZTQzNTc1MGU3NSJ9"
}
]
},
{
"id": "claim_5f8616d759174a4c8ab58ccf50cf9ee0",
"statement": "Swift formatting is configured for four-space indentation and 120-column lines, and the repository’s strict formatter lint covers production/test Swift roots plus `TermindMCPBridge`.",
"evidence": [
{
"resource": "repo://.swift-format#L1-L7",
"version": "repo-lines-v1:sha256:c46d5fca7dea21cd01539ab52f6b003ceb930d0c40ee74115bff80802d41ac38:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTZmYjA4ZmRhMWFjYjk1N2I2MTE2YmQzNzgxMWExZmU0MWEwMTYxMWMwNjMxZWRiZjc4NmQ2ODg5YTI3YTU1YyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjAsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSJ9"
},
{
"resource": "repo://AGENTS.md#L32-L38",
"version": "repo-lines-v1:sha256:71f75264f5d3b24ae9a173eae068137790f39cf7e2e2b1c4ff1ba75cf9c4d3e2:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRiZGQxZGM1ODQ0ZmFhNTZhNGM4NmQ5ZjkyNzA2OGJmM2E4ODM3MzBiNDRjYzFiNzkxOWE5MjFmNmM5Nzc3YiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYTNhZjBhNjM0NDY4YzEwZjBkYzVlODJmZDJlNjI4MTcyZmU0NjA1NTFlNzY3NWFlNGQzOWNhMzFlNDE5Y2M2OCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYjAxZmU3OGFhMzBmMTNhMWI5YjY1OTI5NjMyNTNjZTkzMTE5MDFhZjYxMGE1ZTIwNDE5ZTJlMDRhMWU4YjZmZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYTAyZjA5NDM5NjA4ZjcyZGY0MzQxYzNiZWJlODVjNDFiMGI1YWQyNmFmZjY1ZTYwZDhjZGI2MzAzNjAyNjAxMSJ9"
}
]
},
{
"id": "claim_db3ecae69f064431b6a671d976bf846b",
"statement": "Mac tests marked `.requiresVisibleWindow` run only when the test host has `TERMIND_WINDOW_TESTS=1`; command-line opt-in uses `TEST_RUNNER_TERMIND_WINDOW_TESTS=1`, and routine validation leaves window/focus tests disabled.",
"evidence": [
{
"resource": "repo://AGENTS.md#L40-L44",
"version": "repo-lines-v1:sha256:e338764617da1424b56fb4b3d8eeb6b688285fa246721671afbd893a11c72e92:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTdmYzk4NmVmMDFlZTVmNThjNmYxZmEyNjViOGE2NDEzMTE2OGY4YWE1OTkzZDc4ODZkOTZjNmUxODk4OTQzMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDFkYTg3Nzk4Y2M5NTc1N2I3NzQ0NThlYzQ5Yjg0MWRjYWMzODA1MWQ5MjljZGI5ODE5MGJiMTdiMjdkZmQ4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L11",
"version": "repo-lines-v1:sha256:b8b2903d1009b119d2daa9cc5915fe34eab19cf61490b33adc02693393f4c95f:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
},
{
"id": "claim_ec9d22a2932b42bd80eae69e73f89de5",
"statement": "`Scripts/check-zh-localization.sh` validates the target catalog JSON and, for both `zh-Hans` and `zh-Hant`, rejects missing locale entries, unfinished or empty translated string units, and specified Chinese/Latin or punctuation spacing violations.",
"evidence": [
{
"resource": "repo://Scripts/check-zh-localization.sh#L3-L63",
"version": "repo-lines-v1:sha256:b37758f253f9959a2d7753b617b2cbeabf5d669ea6e0a24b89b4deaa44fb6e82:eyJzZWxlY3RlZExpbmVDb3VudCI6NjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg4ZmM2MzM2NjdkMDMwMDczMWJkZDg0NDcyZGM0MjRlMWY5YzY0MTc1ZWEyYmFkYjY2NjQ3MmQ5MWFlYjRlZmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxMTdmYTAwNmJhOTIwODUwMGIyOTMwY2U2OWNiZGU0MzZjNjQ3YWZhOTE3Y2I3Mzk2YTliYzkxMTFhNDZkZDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ5NjIyZmFlMmFiMDJmZTM1OWVkMTUwOTY0YTkyNjUzNjk3YmZiMjM1ZTIwOTQ3YWEzYzNmMzg1NDg0ZTk3YmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc4OTQ2ODJhNmM3OGFiNDA4MTM1NDJjNWNhZjRhYTFiYTAzNTc4YzUxY2Y3YTI4ZTU0MDVlZDJhMDUyMzBhNWEifQ"
}
]
},
{
"id": "claim_289bc88ffb654cb89575cee5856f3436",
"statement": "App-facing text belongs in `Frameworks/Resources/Localizable.xcstrings` and metadata in `InfoPlist.xcstrings`; changed English strings require finished Simplified and Traditional Chinese translations in the same commit, while AgentKit’s catalog must be built with `../AgentKit/Scripts/build-localizations.sh`.",
"evidence": [
{
"resource": "repo://AGENTS.md#L46-L48",
"version": "repo-lines-v1:sha256:5e69d5ddf8b0181f834edfe8f463b1ddc71ce0c0c26beaa6f4dc0cb63b7f1c67:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiN2ViNmVkNjM3YmU2ODNjNzYxMmY2NzdlYTllMWE1NmI5NjU5OWU3NzJmNmQ3NjkwYjQyMzc0MGNkMTRhZmZmNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODQ1MThlZDQyNWZhZWNhNTgxNGExYzEwMTU0ZjEzMjgxOGViM2VjMGI2ZTgzOThkZjQ5NGI4YWRmN2MzYTI0NiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjZhNzFhZDgxY2FlOGI3MGJiZDYwMzkxNzllYTExZmU0OGExODY0YzdmMDcwNzU2MDQwYWJlOTYxNmVhNmMyYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMGVkYzQzMzI5OGFkNTgxMjllZTBhODg1MmMxM2Y1MjkyMGRhYWY5NGE4YzY0YTQ4NzFlZWVmNDZlMTMxNWVkMiJ9"
}
]
},
{
"id": "claim_5cb32e4cb4ad43229d505772452cf610",
"statement": "`AppLanguageTests` verifies canonical explicit English, Simplified Chinese, and Traditional Chinese language tags and verifies that the Simplified and Traditional catalogs resolve independently.",
"evidence": [
{
"resource": "repo://TFMTests/AppLanguageTests.swift#L12-L40",
"version": "repo-lines-v1:sha256:6d29d5e56f1e9628570f1ccc9b04a767ebf7a8770405f1e520df679cad0ba7a2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQzMTIzODBkOGU0ZTNiYjlhNzg4OWEwZGMxNmVhMDNkODJkYjU1Zjk1NDg5ZmFhMWI3NTNlMzMwODllZjRlZDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2NGI0NjIzNmYwZmExMjhlY2QwNDhmMGUyZDMzNDFiNjYyYzQ2NjA3N2I3MmZiYTg5OGY0MTZlZWYxNjljMjQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NTJjOTcxMTBhMDM1ZjNkYjQ2MWIzM2VjZmQ1MzAwNzk5ODMxZWJlYjdlMmEzOThkMzJiY2ZmNTJlYjFlNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMwZjhmZWVmOTQyZDljODcwMDUzOGE0MGM4Nzk5YTZhNDdkNzM0N2ExNGMxZmMwYmI1NWQ0Mzk2NTA5Y2QyZDgifQ"
},
{
"resource": "repo://TFMTests/AppLanguageTests.swift#L80-L89",
"version": "repo-lines-v1:sha256:620bdd8a67249fd08f6ea1e3b77a03c9da65deeb43ab84295c0f62fe31899f63:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUzZGM3YjkyZTE3YmQ1OWUyMjQ4M2RjMDdlZWM5NWUxMTIxYmU5Y2ZjYmJkNzU5ZWRmOGVhYzc2NGEwYTlkMjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY0MTJmYmM2NGI2MzE3YTMwMmRiODZiZTI1ZjFhYjU1M2Q5NTk2ZjM5M2FhODM2OWJlYzFkZTU4NmRjMTE1OTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk0ZTdkMmVlYzM0ZjNiMzZmMmI1NDhjNTJiNzhiYzBhZjJlNmNhMThlNjc5NmY5NTMyODc1MjgzYTcwM2Q5NjcifQ"
}
]
},
{
"id": "claim_9001476115de4dc3a10921fa323b9f08",
"statement": "The LandingPage production build is `astro check && astro build`, and build output is emitted to `dist/`; the project recommends `npm ci` followed by `npm run build` for locked production validation.",
"evidence": [
{
"resource": "repo://AGENTS.md#L33-L34",
"version": "repo-lines-v1:sha256:759c2b50a118c461d626f39e61caaf6e3e769f097a419a3e47f981dad24ceb88:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNGFjZDgyMzljNjkzZmFmMmJhMmY5NDIxMzJiMzY3MDA3ZDBlOThhNzhlODIyNGJjZWNkZjljYzc4N2QwNWZjOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYjNkZGYwYjM4NzRlMWFmZmJlMzgwYTg1YWUxM2E2MDNhMzNjZmNmMDQ4YzBmNDM0NTNmYThkOTY4OTcyOTk2OCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNTk2MWFhYjc5NWU4NjA0MDU0ZWJmMjdlNTVkZmM0NWU2NzljMzMyNTBmYzdjYzRhZDQwMGMwNzk2ZWY5YTEzNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTMwM2VlYzhlNjU1MjZiMzI1MWUyNDRmNjljMGIwOTMwY2ZmNTFiZDhiODRkMzZhMzk1NzJlZDg3YjIyOWZkOSJ9"
},
{
"resource": "repo://LandingPage/README.md#L10-L17",
"version": "repo-lines-v1:sha256:7ccde33af3c6d70715018d38c434cac90c3ce7f9ab94942bddf007ea9a72aa8c:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZWQ2NGE4MDg5YzkxOWY2ODk2OWZkM2FkMTgzMDJhNDEyM2RhZjQxM2Y0OTYzMTA5YzEzNGYzNzkwMzFlNGU2NiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjY0ZDkxYzMxNGRjYTllNzBhYTNkMTAzZGViMzUwNmM0ZmRiODQ1MzU3M2VjNDQxZDdjNmYyNzcwZDNhMGY5MCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzFmNTQyNDdlNzIxMzMyMzc3YTJmNWIwOTAxYjAwMjhmMWUxZTllMDA3NzYxODdhNzFjZDI4YjRjYTI0MWQ3MyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjkzYmVlZTU4ZTNkODI1ODdhZWNjMDgwZTZjMjYwZDg2ODNkM2YyMmJkNGRiYmUyNjU4M2M1YmFhMmI3YTI1NCJ9"
},
{
"resource": "repo://LandingPage/package.json#L1-L21",
"version": "repo-lines-v1:sha256:832181dd1c57382ec69ce1f74d60047f776261ae8136c2185e51f09ebf1dccd3:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2ZmIwOGZkYTFhY2I5NTdiNjExNmJkMzc4MTFhMWZlNDFhMDE2MTFjMDYzMWVkYmY3ODZkNjg4OWEyN2E1NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI3ZTU3ODhkNWQ5ZDczZDI0YTgxZGJjMGE1YTc0YmZhODJjOWMzYjNhZjk5ZTUyYWY3OTZlOTBiNDY4YThhM2QiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjowLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_45a54a6ec2084c94aa32989e12bd8f00",
"statement": "The macOS marketing screenshot script requires macOS 27.x, builds TFM for testing with resolved packages, waits for a focused ready window, verifies image dimensions, and writes captures while backing up previous assets.",
"evidence": [
{
"resource": "repo://Scripts/run-mac-marketing-screenshots.sh#L43-L51",
"version": "repo-lines-v1:sha256:9474f3899cd27c703003d0bd9b0541dac067c03e0babf5d69c8c4018e4966ba5:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZWNhOTQyYzcyNGNmZmM3NzY4ZWYzZmM5MmZmYTJmM2QwMDg4OGM4ZWFhYThiYWI5MWVmM2M1NDczYWQ5ZDNmNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMWJkMWIzODk5MDdjMTI3Mzc5NzM2NWEzZjhiNDVlYWFiNjJhNDQzODllYTg4YzdlYzJkYTA0ZDY2OGJkYmRlYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmY4NTJmMGUyNmY4YTJjZTYyNDQxNjcyMTJhOTc5MzYxYjljMWVkNTQ0NDU3MWRmYjZmMTJlYmMyNTQzZWRhOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjhmOGYwNGFmMDdmMGVmY2RiNTdkMWJiMjlkMjQwZjhkM2FlOGRiMDhkYzEwMmUxY2IyMjhkYmIxMDhmOGI3NyJ9"
},
{
"resource": "repo://Scripts/run-mac-marketing-screenshots.sh#L8-L19",
"version": "repo-lines-v1:sha256:093fa5e9175516af40e0a58ceff0ff23d0181e7d7df7d24c6a2dd5b672300d2d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY0ZWRlZjRlMTNjYzFkMTZkMzc2MDIyYzVmZDlkOTU0MWRiZjkzZDQyMGJkYzZkYmEyOTM2MmIwNGE0ZTRlYzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZlZTVkOTQ1YjQ0YWRkZDEwYzc4ZTMwMDk4MTQyZjBkM2ExMWYzODZkZjdlNWU3ODNkZDk4MDIwOGZkMGI1MjMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU1NTc3ZDc2N2NlOWY0NmRiMDlmZjJiOWExMjUwNDJlNzg2NGNlZDIyZWYxNjIxYjIwNzIxYjNmZjcyM2Y1ZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUxZTUxOWUwZDBiNDg3NGIzMDA4ZGYyYzI1YTczYjEyNzE5NGY0OTk2NjI3NzA3YTk1YzMzYTNkN2Q1NDg1NjcifQ"
},
{
"resource": "repo://Scripts/run-mac-marketing-screenshots.sh#L94-L150",
"version": "repo-lines-v1:sha256:3ec63f24140f2fe5ab30697272a56e495bbd29d5426845eead08c2ddd155d85f:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc3MzYyZDc1ZWNlN2I1YTM0MjQwMTU3ZmNkYzUzMjgwMDIwZDFhNDNjNzIzOTE3OGFhMDFjZjBlMTM1ZmRlYzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwN2E2YTMyZDQ4MjQ4MzhiZjM4YzNjNDA4OTFjNjUxYzYwZmQzYmFjYTdjMWI3Yjk2MDA5ZjQzOTZmMWVjYjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUwMmI3ODZlYjEwMGEwZTZlNGZmMDIzYTk3YjFmN2EyYjMxMjVhMTMxNjIzNGI5NzMzMjgyYjRjYjI4M2FjNmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjZDRhMWI5Mzk2NTkwY2MzN2FhNGQyZDU4ODAwYTBmMWRhZDVlYWFjYWYzYzY5YmM5ZTgzNTZjOTM0YWVkNzUifQ"
}
]
},
{
"id": "claim_b6d98fab165c427faea71a8b3730739f",
"statement": "The mobile marketing screenshot script requires an iOS/iPadOS 27 runtime, uses resolved packages for its TFI build-for-testing, runs `MobileMarketingScreenshotTests` for `en`, `zh-Hans`, and `zh-Hant`, and fails if the expected number of captures is not received.",
"evidence": [
{
"resource": "repo://Scripts/run-mobile-marketing-screenshots.sh#L135-L195",
"version": "repo-lines-v1:sha256:40e63bba3dc7a114d25b544b4df8eda84296202213a92584f7aba9f246617e17:eyJzZWxlY3RlZExpbmVDb3VudCI6NjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkzNjIzZWFmN2NjYjljMTBjMDNkZWY2OTgxZDAwZGZhNmUxYTFiMjhhMmFkYzFlMzg0MGQ5NDNiMTc0ZDkyY2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ3YzA3ZDViNjk2NWFiNWNlOTMxMjI5ZGVjNDA0ZmExMmMwZDljMDQxN2Y3NmNmZmEzZmIxOTc0MDVlOTc5MjgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5N2RjZmE0MWZhN2E1Nzk4OWE4M2NhZjdkYzNkMTVlNTNhYjljNjVlMjE5MDIwM2Y0NWRkOWI5NjYzY2YyZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZkNmUwNDI1NmVlNTQzNmUwYWRkNzEzNDE4ODk2ZDY4YzEzOGZkYmNhZmIzMmJjMDMzZjczOTA2YTNlYmZhYjEifQ"
},
{
"resource": "repo://Scripts/run-mobile-marketing-screenshots.sh#L79-L83",
"version": "repo-lines-v1:sha256:b17e386bad4556c1e3c2130d48fe8728e40c96a43f75301025f0a9a37fb80010:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYjAwOWYxZGQzMjMwYzcxMTYxZDg1MDI1YjRjODQ5YWEwZWM3ZDc1NmIzMjMwMDhiZmZlMTA1MzM3ZjVlN2U3YyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNWZkNzdjZmI1NzAxNGRmYzkxYjc1YmQ4ZmM4ZTY0ZDg0MTQ3YWEwYjlmNjIyOTZkZTRjYTI2ZjYwODg3ZDFiNyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDE1YWMzNDhlMmM0YzVhMWMxNmNkNjQzZTViNzg0ZTc1ZTdlMDkwYmNjODQ4NTgwMjRkYTcxYWEwOGMzZWVhZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWVhM2M3Y2Y3MzMzMjRkNzI5MTZlM2EwODEwMGIxMDJmMmJiZWNhMTdkOTE4YTM4NTcyMzU5NmY0MGNiMWY2NyJ9"
},
{
"resource": "repo://Scripts/run-mobile-marketing-screenshots.sh#L9-L21",
"version": "repo-lines-v1:sha256:de0db02c0474119da87611422e7481b9df01e05d6b8c6444f78b1256f1dd7b33:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3YzMxM2NhMDZjMmM3M2Q4NjQzZjM4NmE4YjVhYTdiMDA5NjE2MDEzYjQ3ZjAzODcyODM4MWYxNTVlYzY3ODUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM0YTJiZWNmZjhhZmIzNGRiMjYwZGFiYzk2OTE1ZmZlY2ZkZTg0ODkyOTU0MWM2MTkzZGU2ZDE2NGMyMWU4ZGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRmY2NmNGY4MWJkOWI1ZWY3MGY2NTczNTU4OTZjNGY3NTcxMWE2YmU5MTIwYTM2MmIwOWMzZTEyMjEzYWNhZGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA4NmFiNmRiMjVlOGQ3ZDQ2MTIxM2NkODcyN2U4NjU0NDc3NTBiMTUyMmE4YzQxMTI5OTM0Y2UyMmEzZjIyNWMifQ"
}
]
},
{
"id": "claim_787a0b8744354bdc9eed7aa16a6a6594",
"statement": "AgentKit is declared as an up-to-next-major remote package with minimum version `0.14.0`, while `Package.resolved` pins it to release `0.14.0` at revision `ffc4aa41c8854142aa47c35231e57f56f961ba9f`.",
"evidence": [
{
"resource": "repo://Termind.xcodeproj/project.pbxproj#L2837-L2844",
"version": "repo-lines-v1:sha256:444f908545e708b1d395265e4292e5529193fc19d4f609c8b5e06f6d68e13abe:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDhlMTQzODY5ZWI0MzVjMzZmNTljZTI5N2IxYWYxNzc3NThjMzVhNzFlNzJiMDQ2MTY2ZjkzNTNkODcxM2E3MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzYwYjg4YTA1ZDViNTM4NDc2MDIyOWJlNjA1NzJmZTYyYjFjMjljZGM1N2VkYjVlNjk1MWRhYTRmZDQ2YzgwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzExMTg1YzI4MDExZTZiNWFiYjU1YzRlOTQ5MjMyMTkwMzE1YWFmNGZhYzU4MzhhMDFjMWZmNTQyMjgwZmFiOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2M5YzA1MzMwYWQ3YTFmNDVhMmI2NDU2MTQ4OGZmY2NjZGY5Yjc3YzZmMDA0ZjBkYzRmNTBiOWRhZWFiYjdmNyJ9"
},
{
"resource": "repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved#L3-L12",
"version": "repo-lines-v1:sha256:020558cd6c690f48bb07a00cf6e6c34889c9e5c497fbbab4f1a9466cbc996851:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5ZmQ1MzQ0YWM2NzYwMjNjOGZkM2FhMmZjNWQxMThiZWYyNzNlZWNkMTYzMWY1MWEyZThlNThlNGUwYWJmMGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFmMGNkYjk3MmE3YmZiN2VkMjQ2ZjlmZjY3MjM4NWU1NWY0OTY4ZmMxMTA0M2RjNWI2ODRkNTFkZmEzMWRiY2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg2MGUwYTQwMzczZmI1MWNkNWM5NjhlYjkwYmM4MDA5YzkxZjYwZDBhMzgyZGUwOTEzOTFjOGUzYjZiMDJmNDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY2OTQ3NDIzZWZiNmI1NTAwYTRjZDg5NDM2NWUzOGUyZGIwYmQ2NDA0MjJiZWFlMjQxMDljY2NkOWI4ZjAxNTEifQ"
}
]
},
{
"id": "claim_4210116e410941d98e7d962dcd708ce2",
"statement": "A Termind change that depends on AgentKit must follow the release/bump/re-resolve sequence: test and release the sibling package, bump `minimumVersion` in `project.pbxproj`, then re-resolve so `Package.resolved` records the new revision; both files belong with the app-side change.",
"evidence": [
{
"resource": "repo://AGENTS.md#L16-L18",
"version": "repo-lines-v1:sha256:79d9222951afd1cde2967f4987b4aa7b4347f1510f1fc4d1141010690b9c8bff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGI2ZWFiNGFjNWIwNmRiMjY5NmQ0ZDUzZTJlN2YwZDE3MzhmMWI3NTAyY2UyZWY1YjcwMzIzZjg3NjdjYTllNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRkZTk1MTMwNGUxYWVlNjRiM2IyYmY3NWZkMzI2YjAyZGM0OTE5YjlhODM4MGZjZTY1YTAyY2VjOTE3MzdjMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWM1NjRmZjMwNzY2N2QwZTgzMGJkYjkxYmY1MDYwY2FlODNhMjc2NzRkNTU5NWNiYTU0ZGMwNmQzNmE2NWMzYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWYxZjNmMTg5YTBiZTIyMGIzYjA0YmIwYzc0MTI2OGE5MzE4OGU1YzY0OTMzZGUyNzU0YzI3ZTZkYzRmZTE0NSJ9"
}
]
},
{
"id": "claim_c0b02f23d4044dc89a147355e5058757",
"statement": "Repository policy prohibits committing secrets, `.env` files, build products, and user-specific Xcode data; `.gitignore` excludes derived Swift/Xcode outputs, Node/Astro outputs, and local environment files.",
"evidence": [
{
"resource": "repo://.gitignore#L45-L49",
"version": "repo-lines-v1:sha256:9985bda83dc4a7b4978e55362a6269836341f7c3dd122eaedfbbadfc4ace5900:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOWMzZmRhYzZkNTZmOWIwYzEyZjUwZWMwZGVhMjFhOGZkNGZiYmQ0YWM3MTM0NzUzYmRiMzllNDllMThjNDQyNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMTAxNmUxYjk2YmJiYjEwNTY5NWE0NjU1NGI0NzMyNjc5NTA5NTJiZTg0NGIwN2ZmZGI0N2EyMDc3OGNhZWE4YSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiN2VmNWFlNDgxYWFkOTU4YmZhYmE3NDVkMmYzZjg5YjJhMDE1MDg4ZTdiNTE5MmQ2NThjMDg0MjZhMWYyMTgyYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWUzYjY0ZmJkMGE1YjlkZDk0NWMxYzk5Yjk0MWE1ZjJkZWM3Mjg4NWM2NmRlM2RjOTA5ODRiOWQxNzRkNjI1OCJ9"
},
{
"resource": "repo://.gitignore#L7-L29",
"version": "repo-lines-v1:sha256:28513ea594acc7764aca28eced9c12cc5d6c0a019b43fbb8e3392860b99eef69:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY4MDI3NzQyZTc4ZDM0ZWE1MjNiMjllOTdjYjRmNzk5NWJjMmEzZWI4OGY5NmIyOTBjNTdmOGI5MTUwZjE5NWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlOWEyODY4YjUwOTBiOWU4MTk1M2I3Y2Q4MzE2YjMwMDJlN2NkNjg5NzMyMGMyYWE2OWVlNzFmYzI3YmUzYWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ3YjIxNDZmZTAwMjRlZjA1NGIzMTAxNzk4ZDRkYmViOGM2MGMwZGI4NTk4ODAwMGFhY2UzNWVmZDgwZjk4Y2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ5NDZkMjVhM2MyYjNlMTk1MjZiNWJiODVmODdmYTE0ZDQ5ZTk2OTgwMTJmNWQxZWEzNzI4NzFiNTM0MDk3NjQifQ"
},
{
"resource": "repo://AGENTS.md#L50-L52",
"version": "repo-lines-v1:sha256:c11f26108030abfcf1f2cdd98655ff0116e1d44180c4d5eec36e9b6bb15895e9:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjRjMjMzMjczNTc4NTMyYWE3NWIxM2ZiMzRjYzkwYjdkMDIwYWVkNDhmNjY1YTE4MjYxNjdiOTAwMjljN2MzYSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTAzYWFlMjllMDYzMTZkNmRhNmY4YzJhOTFmNmU0NGE2MTJmYWJkNzkzYWQxZjVhMWZjYTUyMDZiY2VkYTQ3YyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMjE3MWVmNzc1NWEyMTNkNzkwZTA1OTU2ZGNhOTRiZjE5Nzk4YmYwNGZhOTNhOGE3MjE0OTgyNTczMDdiM2UwYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWIxYmM1YmM0YTIzN2Y1NzhlNmFmNGE0MTVkMDY0N2Y5OTEwYjAzYjM2NGUxZTI3YzFmMWRiYWE3NDNkMDNiYSJ9"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
+122
View File
@@ -0,0 +1,122 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:cade63e93115426143be255179f6a32b2c867cf7a7b539dab9b264dcdca0cff3",
"claims": [
{
"id": "claim_83870f4f1ad6403ea0d8bd8775729a76",
"statement": "Termind is one Xcode project with native `TFM` macOS and `TFI` iPhone/iPad targets; shared frameworks are layered beneath the apps, while platform UI and lifecycle remain app-owned.",
"evidence": [
{
"resource": "repo://AGENTS.md#L3-L14",
"version": "repo-lines-v1:sha256:ebfbb4e4dd7e3beb5093f7d76de4ba789e0b467bdd86cf37e4cc42c6f70d7f22:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3NmYxY2NlMDU0ZTZlYjE0YTIzZTg4MDI2Mjc0ZmI0YzA0ODM5YTcxYjY2ZmZjY2VhYzkzOWUyZGM0ZjRhYTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJmNGQ3NzU3NjdlNzBiMGI3ZDE3YjNhNTkzNmM2ZDY2NDc3YmE3NzZlMTNmYzM5NmEyOGMxODY5MzQyMjQwODIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhZGU5Y2M2MTdlODVmZTg2MzFjMWQ2ZjhiZTAzZTViZDE4NmQwYzhjOTI1ZjY0ZGIzMmU0ZGI4YTBlYTY1NGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkMzUwNTE2MzRmYzcyMzY3ZGVlYTFhZTI4NzFkMjk0MTY2ZDNlNDM5MTgwOTdiOGUzMTVlZmE3OTU1ZDM5YjcifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L6-L21",
"version": "repo-lines-v1:sha256:b687a0b8e3c97a67e3bed2cbdb289acbe8239cfd271818b526c130ef16d8031a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdkYTliZjc4MWZiZWRhMjE5NTEyZmJmMmU2NTRmNWI2OGViNjJkYTFkMTE3NmNmZjJiMWViZDkxZGMwMzhhNjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVkZTI2OTNjNDgwYTVkOWI2NGJlZDk2Y2UwOGQ2NDNhMDgxNDNjMWI1MjZjNzA0MDg2NTk5MDc1M2I2ZTQ0OTciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUwZTViYTA2NzEwM2E4ZWU5NDBiZTFkZTIzYTRiOTczNzU4ZmYyMGZjZTFmMmIyM2JkNzA4YmQ5OGY5N2Y0NDUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk4YzFlYjFkZGU1NDQzMjdmMzNiYzcwNTdhMDZiYWEwZDU5N2NiZGExNzIwOWE3Y2QwMjVmMzQwMDg2ODk4ODkifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L188",
"version": "repo-lines-v1:sha256:363e2bafaf7e2967b4b7b04ce0bad053d5b9ed639768c3c4b98c8f9ac339ee0e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxMDYxYjk2MWM1YjA4MWJiZTM0NDlhZDQ5MjM0NTE3NjVkNjU0YTg0NzM5NGNhYzZmY2QyYjdmYTkyMTllMDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
},
{
"id": "claim_f82e18c98f0b4638a0f5284b0a2bee24",
"statement": "A safe change must preserve the lifetime split: durable app services are app-wide, desktop navigation/workspaces are window-local, mobile navigation is scene-local, and live transports belong to the workspace or session that opened them.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L45-L70",
"version": "repo-lines-v1:sha256:3a7990666a403f4d2997ffea80a867cf3afde14ec23da5d6552ae7062c9d7a64:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhMmVmYTE0MmJjM2QwNjU0NWIyZmI1OWViYTY4NzBkODE5NjYzMmFkY2Y3NjEyM2U4Yjk1ZDVkYzNjNzUxYTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVlMzEwOWI5YTgxNTdmNzg4MDg2YWMxZTkzMDI5NjA1MmYzYTA3ZTU5NDc3ZDU4ODQ3Njk0MTYwOGM2OTUyNDEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFiYmE4MjFiOGQxYTY2MWIyNDRiZGI4YThiMDhhZTE3NzJhNjNhNGI5YjI1ZGFiOGRmMDZjYjEzYTMzNmRmYTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBhZmI0NzhhMjdhNDA0NDY5ZjljYThiMTgzZmQ4Y2NlZGI3ODVlNTI1NzU4MTE5NDc4YmY0OTYyYzE5ZmZjZTUifQ"
},
{
"resource": "repo://TFI/App/TermindIOSApp.swift#L19-L33",
"version": "repo-lines-v1:sha256:78cdd316a915930837af24416a90eddddd5619a5c74f1c6ea36d13500cec5f90:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmODI0YzlmYjRjY2M1MWYzMjAwNzJiNmNjNzQ2YWVkZWU2MmQ3YmNhZGY5NDI4MmJjMjdjZjNkMjc5ZWQ4YTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwOWRlZDA1YTMwZTBiMDk1ZjI3NWRkNTcwMzRmNzU2NTgzNjBjOWQ4ZWIyNTg3NjNjNGI0MDMwYmM5ZGRjYjEifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L155-L190",
"version": "repo-lines-v1:sha256:1f72d15f0dcd1608fbb34ebbfc5845f177dafab50c5667294536a17e3cd7f0f6:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwNTgzMDJjZDFmMDQ4ZTE3MzU1MTUxODA0NzRjYmI4M2YwZjhkZDNmN2I3ZjUyODI4ZDU1ZmUxYjg1MmIxOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ0MTA0N2ZkYjNiOWIzMTYwZTU0NWEwOThlOGJhY2E1ODA1YTJlZmFjNGI3YWRkNmYxM2IyNDg4NWJjNmY4ZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjZGEyMmE4ZWYyODNjOGFmOTJjZDlmMmY2ZTA4MzdkODg4MjdjYjBkZGM2OWNlNDFkMTAwZDFiOTdjYWM5MmMifQ"
}
]
},
{
"id": "claim_883b0f81c5004c90949c5300c242dce2",
"statement": "`TermindApp` is the macOS composition root: it creates the SwiftData container and app-wide services, uses in-memory storage for tests or screenshot demos, and fails startup rather than silently replacing an unavailable local database.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L21-L139",
"version": "repo-lines-v1:sha256:d7c034ab508974511acbdcd459b5cb2869b11ad59663723ae8f36b41cf39cdd7:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE5LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI4YmNjNjExYWYyM2E5MWMzYjcyN2QwYWNlNGRlMjIyNDJmYzQ5MDZjNzE5NGE2MzQ5MTliNjVkNzAzZGQwMGIwIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OGVhYmQ5MmNkYjZlMGVhMmViNTIxZDAzNGY0MjllZmZiOTlkYWMxMjM4NzI3MzJlZjhlODU1MTMzN2Q5ZTdmIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlYThjMTliZTVkODNlNWE4Njc3NjVlN2JmYmZkODdhMDY0MGJiNGM5OThiODYxMjFjZTc3ZTVkYjE3NTA0MDExIn0"
}
]
},
{
"id": "claim_d8fbea4ef15c4224a4cd3e9cb2155c85",
"statement": "`TermindIOSApp` performs language migration and creates a single live or testing `MobileAppModel`; its window injects the model container on success and presents an unavailable-data view when startup composition fails.",
"evidence": [
{
"resource": "repo://TFI/App/TermindIOSApp.swift#L5-L33",
"version": "repo-lines-v1:sha256:1574c44f26f386fca5834af375adbea23b9471aaca384b9aa647006e94caec2e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0MDI1ZTA5ZDBlYTM3ZDMyNTYyMDVjODkwYTg5YjU0NmE0MDcwNTg4MDJmZWUyZDY1N2Q2ZjJmODg5MzllMTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwOWRlZDA1YTMwZTBiMDk1ZjI3NWRkNTcwMzRmNzU2NTgzNjBjOWQ4ZWIyNTg3NjNjNGI0MDMwYmM5ZGRjYjEifQ"
}
]
},
{
"id": "claim_da188fce4fea4fc496b3f09eed8f55b8",
"statement": "Architecture boundary tests enforce that shared layers do not import app targets or forbidden platform/storage/transport dependencies, Application does not depend on concrete implementation layers, and SwiftData models are owned by Persistence.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L206",
"version": "repo-lines-v1:sha256:8fa9db32089b6d351da07281bb6f34969d6feb24c764b507df907c0b40db8182:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyMzk2YTZjMGFlNGEyMDI0YjE2OWE0NWY3MjdmZjYwNWE4NDI4NjdkODJlYjJjOTNkYmNkNmVlNDg4YmExYWEifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L64-L106",
"version": "repo-lines-v1:sha256:08c476cc632f29ebd0f9b7221558d60dc77bb9ac8d88d819e4d8841a8372d835:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4NWJlNTRjNmM2MGZmZjQ5ZTllOTU1Mzg1YjMzZTc4ZTRkNGQ4ZDJkNmUwMWQzMzJkNjhiNjg3MTA0OTkxYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ"
}
]
},
{
"id": "claim_8489acfc41234c788210e9464a75fcb0",
"statement": "AgentKit is a separately versioned remote package: it owns host-neutral agent runtime behavior, while Termind owns SSH/SFTP tools; cross-repository work requires an AgentKit release followed by a project minimum-version bump and resolved dependency update.",
"evidence": [
{
"resource": "repo://AGENTS.md#L16-L18",
"version": "repo-lines-v1:sha256:79d9222951afd1cde2967f4987b4aa7b4347f1510f1fc4d1141010690b9c8bff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGI2ZWFiNGFjNWIwNmRiMjY5NmQ0ZDUzZTJlN2YwZDE3MzhmMWI3NTAyY2UyZWY1YjcwMzIzZjg3NjdjYTllNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRkZTk1MTMwNGUxYWVlNjRiM2IyYmY3NWZkMzI2YjAyZGM0OTE5YjlhODM4MGZjZTY1YTAyY2VjOTE3MzdjMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWM1NjRmZjMwNzY2N2QwZTgzMGJkYjkxYmY1MDYwY2FlODNhMjc2NzRkNTU5NWNiYTU0ZGMwNmQzNmE2NWMzYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWYxZjNmMTg5YTBiZTIyMGIzYjA0YmIwYzc0MTI2OGE5MzE4OGU1YzY0OTMzZGUyNzU0YzI3ZTZkYzRmZTE0NSJ9"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L352-L356",
"version": "repo-lines-v1:sha256:425557967a3c8daba2a7af324081dff7809f5fdfdee4f2ce780c46819e9ba6d0:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTIzZDQxNmU1NjU1M2FiOWFiZjg0MjVkNjExMTI4MTQ4NjMxNDFlZmYzZTVhM2NhNDVlNDQzYzk1ZTAwNzA4MSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYzY1NjVkMWUyNTAzN2VjMzdhZWQ1Y2ViMzYxNDVkM2RhNzJlNzZjZmVmMDI0NDQzNzIyNzM5Mjg2NDYyMThjMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDA0NjZmNDJmZTgxYzZkOGQ0ZGI3YTVjNGUzNmI2OGMyYmQ4MTIwYTgxNTU1NGQ0ZTNlOGVlYTQwNDg1Yjg2YiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMmUyOWFiMjBkMjIzZGE3ZjFhODcyYzIxZWY1MmFjNTVhODMxN2RjOWI5OTQyZDc5NzUwYmU1OWQ0YjJmY2E2ZiJ9"
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:2a2bcccf7f6514fee0573fdd868c54bd98fa151a69e0eb4ae45f9b09fa2f956b"
}
]
},
{
"id": "claim_49b7e46dc58948ad8a9cfb47be7bd41d",
"statement": "Routine Xcode validation must use `-onlyUsePackageVersionsFromResolvedFile`; the repository defines TFM/TFI build entrypoints, strict Swift formatting, and a localization validation script.",
"evidence": [
{
"resource": "repo://AGENTS.md#L26-L34",
"version": "repo-lines-v1:sha256:a91f88bee69fc799fe765bb122f6b5106642c565be05fb945780ea3d3248ebf3:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTczYmEyNjc2YzMzZGE1MjMyNTFkNWNjZjUzNjViODFhMGEwMjMyZWU3MGI3OTFlNmJjMTNmYTIyNTFhMGQ4MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYjNkZGYwYjM4NzRlMWFmZmJlMzgwYTg1YWUxM2E2MDNhMzNjZmNmMDQ4YzBmNDM0NTNmYThkOTY4OTcyOTk2OCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzE4ODJlOTJlMDU3MTI0MDRlN2M4MWQ2Mjc2NTIzMWQ5Y2VkZjg5MGNlNmUwZTVlMDBhZDk2NzIzOTA5YzA3OSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTMwM2VlYzhlNjU1MjZiMzI1MWUyNDRmNjljMGIwOTMwY2ZmNTFiZDhiODRkMzZhMzk1NzJlZDg3YjIyOWZkOSJ9"
},
{
"resource": "repo://AGENTS.md#L40-L48",
"version": "repo-lines-v1:sha256:e0e8c9958812182ec2d7001a28a31979a8ef4bba9255fe9f04867d56046faca6:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTdmYzk4NmVmMDFlZTVmNThjNmYxZmEyNjViOGE2NDEzMTE2OGY4YWE1OTkzZDc4ODZkOTZjNmUxODk4OTQzMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODQ1MThlZDQyNWZhZWNhNTgxNGExYzEwMTU0ZjEzMjgxOGViM2VjMGI2ZTgzOThkZjQ5NGI4YWRmN2MzYTI0NiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDFkYTg3Nzk4Y2M5NTc1N2I3NzQ0NThlYzQ5Yjg0MWRjYWMzODA1MWQ5MjljZGI5ODE5MGJiMTdiMjdkZmQ4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMGVkYzQzMzI5OGFkNTgxMjllZTBhODg1MmMxM2Y1MjkyMGRhYWY5NGE4YzY0YTQ4NzFlZWVmNDZlMTMxNWVkMiJ9"
}
]
},
{
"id": "claim_03ad2c4c5a2442578285a13d8bbfc4c3",
"statement": "macOS tests that show windows or take focus are intentionally opt-in through `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` or `TERMIND_WINDOW_TESTS=1`, so routine validation remains headless.",
"evidence": [
{
"resource": "repo://AGENTS.md#L42-L44",
"version": "repo-lines-v1:sha256:a556c3aea2c14cdaa85d89a15243c4606e48562f600fe675a3e4f75594c7a07e:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2VkMDNiODMzODVkNTYyYTZmN2VhN2FjNzljMDRjOTAyYjliNDc1YmU2ZGRmMGJmZWU4NmJmNGY1MWYxMTAyOSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTAyZjA5NDM5NjA4ZjcyZGY0MzQxYzNiZWJlODVjNDFiMGI1YWQyNmFmZjY1ZTYwZDhjZGI2MzAzNjAyNjAxMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,198 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:85333b33c78f0f8066210d2b0b93e64fd7818b59990150b887a5d2d089d893f8",
"claims": [
{
"id": "claim_b7fbd64158554b8b8ca80a0a613b3bc3",
"statement": "Termind separates Swift Testing by ownership: FrameworkTests protects portable shared-framework contracts, TFMTests covers macOS composition/native interaction/remote-session behavior, and TFITests covers mobile composition, scene behavior, and mobile presentation.",
"evidence": [
{
"resource": "repo://AGENTS.md#L40-L44",
"version": "repo-lines-v1:sha256:e338764617da1424b56fb4b3d8eeb6b688285fa246721671afbd893a11c72e92:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTdmYzk4NmVmMDFlZTVmNThjNmYxZmEyNjViOGE2NDEzMTE2OGY4YWE1OTkzZDc4ODZkOTZjNmUxODk4OTQzMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDFkYTg3Nzk4Y2M5NTc1N2I3NzQ0NThlYzQ5Yjg0MWRjYWMzODA1MWQ5MjljZGI5ODE5MGJiMTdiMjdkZmQ4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://AGENTS.md#L5-L14",
"version": "repo-lines-v1:sha256:4d2ece4bd3cc980ac07ceebbe3c6f012cf2a17d5e087150df1ad69e91ea5b976:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYzOGJkODA4OGNkOThjMmEyYmY3Y2VlMDI4NjY1NDk0ZTkwNDBiNGJiMzUwYWIzMGNlYzk4ZjJmZjQ5ZDI1MjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJmNGQ3NzU3NjdlNzBiMGI3ZDE3YjNhNTkzNmM2ZDY2NDc3YmE3NzZlMTNmYzM5NmEyOGMxODY5MzQyMjQwODIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJkNWQ5OGQzMjUyMTczOThhMmMwODM4OWMxZTI4NTA0MjEwNjA0NjhlM2MyOTg3YTg0YjAxYzQzNGVlNmQ3MmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkMzUwNTE2MzRmYzcyMzY3ZGVlYTFhZTI4NzFkMjk0MTY2ZDNlNDM5MTgwOTdiOGUzMTVlZmE3OTU1ZDM5YjcifQ"
}
]
},
{
"id": "claim_46317f2e2a1c469cb75d414d61222c34",
"statement": "ArchitectureBoundaryTests protects layer ownership by rejecting forbidden imports and concrete infrastructure construction, requiring SwiftData models to remain in TermindPersistence, preventing shared frameworks from importing app targets, and forbidding local redefinitions of AgentKit-owned types.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L137-L206",
"version": "repo-lines-v1:sha256:d897c1acd03389dd4d7cf8d20bd9e1f7697c28f4e0736f406ce4f07a6b13f1cc:eyJzZWxlY3RlZExpbmVDb3VudCI6NzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjOWJmNjE2ZGNmNTM5YTBkNTRhMTM2YzY2NGM1M2EyNTllZmFkOWNmNWFmYTY5MDY5ZmEzOGI1MzE5OTQ0YzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0N2NhYjY3NzUxMmRjZWQ0YTIyMGVkZGQ4NjNlZDFlNDM1OTM0NmRiYTk4ZDljYjkwZDBmZjk2MjhjM2IzNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyMzk2YTZjMGFlNGEyMDI0YjE2OWE0NWY3MjdmZjYwNWE4NDI4NjdkODJlYjJjOTNkYmNkNmVlNDg4YmExYWEifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L64-L106",
"version": "repo-lines-v1:sha256:08c476cc632f29ebd0f9b7221558d60dc77bb9ac8d88d819e4d8841a8372d835:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4NWJlNTRjNmM2MGZmZjQ5ZTllOTU1Mzg1YjMzZTc4ZTRkNGQ4ZDJkNmUwMWQzMzJkNjhiNjg3MTA0OTkxYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ"
}
]
},
{
"id": "claim_b7909d224fe141669ceba8e0e7df3fda",
"statement": "MobileWorkspaceStore is a device-local workspace-intent store: it persists a versioned workspace-descriptor snapshot, migrates legacy arrays with deterministic duplicate-index allocation, and preserves unreadable bytes by disabling saves until a successful load.",
"evidence": [
{
"resource": "repo://TFI/Infrastructure/MobileWorkspaceStore.swift#L31-L84",
"version": "repo-lines-v1:sha256:4f35fc7eed35df1e05ad4bf4ac39ad8de492fd4362a6d501d9026fc401484a23:eyJzZWxlY3RlZExpbmVDb3VudCI6NTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJjYzJhMGUxNmJmYTJmOTQ0NGRjYWExOTQ2NjgyMGVkZmViYjRlOGIxZjM2ZjA2NDI0OGUxNmMzM2ZmNGM5OTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY1Njk5ZjYzN2FkMjM5YWIxNjY1ODdiZTI0ZTAyZGVmM2ZjOTA4YTMwNjFiNmZmMmM1ODE3NzNkY2FjOGZlOTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFI/Infrastructure/MobileWorkspaceStore.swift#L4-L12",
"version": "repo-lines-v1:sha256:84eaf6fe9f99a32f4dd09544034ab1280431f7726607f6c01ba8255bd4034c74:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDE0OTE4NmQ3MjRjYjkzMzkyMmE3ZTQxNDBlNWQzOGI0YjkwZDljNDJmNDFmZjQ0MjMzNmM2NWQ1Y2EwZGVkOSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTU4ZDRhOTEwNzQwNTlmMGM4ZDIxMzZmOWJmODA4MzQ2MTQ4ZmM4Y2ZiMzU0M2RkY2JjNzUwZTc1NzZlNzI2MyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjQyYTQyNjRhMTAwMzFhM2QyZGE2MDUzOWE4ODMyMzhlZjcyZDA5ZjE3NmMxYTMwOTQ3ZDdkNjdkZWJjYTBhMyJ9"
},
{
"resource": "repo://TFITests/MobileWorkspaceStoreTests.swift#L8-L106",
"version": "repo-lines-v1:sha256:f89327bd5e875c95ecbbc1ceea1775b637daaa5d1539444c0091541e0de689ab:eyJzZWxlY3RlZExpbmVDb3VudCI6OTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI0NDQ4MDMyZmY0NWRhMDgxNzExZDlkZDhiNzVkMzc5N2UyZTkyYjhlODIxYTNkNWZmZjhlNzkyNmNjYjY5M2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRiYzJiZWEwNjNiMmYzMTM0Yzc1NjY0ZDIwMzI5ODQxN2ZlMmRjZjI3MTE5NTE2MjIwMmRkNGI2MDY2MzFmNjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmMDhmOWE1NGExNjNiYTI3ZTAxYmI2ZGI3OTRmODQ1ZmM2Y2IyMTIyMjg2YWZhZTBlZWU2NTAzMTM5OTAyODUifQ"
}
]
},
{
"id": "claim_8de4a65c68ce4eea86eb1cc8590b29a1",
"statement": "Mobile workspace restoration does not persist credentials, commands, or live session state.",
"evidence": [
{
"resource": "repo://TFI/Infrastructure/MobileWorkspaceStore.swift#L4-L5",
"version": "repo-lines-v1:sha256:325bc9ab05fb7f1287a49144c0589886a0a44b31066e20c20943c12319f7a3d6:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDE0OTE4NmQ3MjRjYjkzMzkyMmE3ZTQxNDBlNWQzOGI0YjkwZDljNDJmNDFmZjQ0MjMzNmM2NWQ1Y2EwZGVkOSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDQ3NTE0MGUyNmU5YzVhMTcxMWQ2NDQ1YTE4YjdmNGFlMjAyMmY5OTNlZjYyODQwNzU1NDMwMWI5NmUwZGMyMCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTU4ZDRhOTEwNzQwNTlmMGM4ZDIxMzZmOWJmODA4MzQ2MTQ4ZmM4Y2ZiMzU0M2RkY2JjNzUwZTc1NzZlNzI2MyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNmI1NzZlZDZlMDFkNzVhN2I3NWJkNzRjOTVmZDRlYzg3YzAxZmEzYzg2OGU4ZTc1Mzk1Y2M2ODY3Y2M5YmJjMiJ9"
}
]
},
{
"id": "claim_fe3a96862cd14c95bd1eab463745974c",
"statement": "Mobile app tests establish that conversations are shared across scenes while assistant navigation, selection, and drafts are scene-local, and that external connection workspaces are ephemeral rather than Vault or saved-workspace records.",
"evidence": [
{
"resource": "repo://TFITests/MobileAppTests.swift#L40-L60",
"version": "repo-lines-v1:sha256:a30a6f3699e18c0c0418a6ba94f80dffc91924f42433be7cfef7e32339eca3d4:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA2MTY1NjI5NDdiMzAyYWQ2MTZhYWIyNGIyOTA3MGU2YmIxM2IzMWI1MGM2YTFlODVlNTM4NzIxMjExOGViYmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVmYWM0MGJmNGMzNjFmYjBkZjk2OTEwYTY4NjUyOTQ3OWNjYzlhZTYxZDhiYTc4MTgwZTRlNGQzMDFjZTJmYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU0MzIxMTJhYWQ2YzRmNGY1NzI2MGFlYTc0N2NkMTkxZjJmYzY1MmFlZmFhNGI0MTE2ODc1YzM3ZGY2OWY2OGEifQ"
},
{
"resource": "repo://TFITests/MobileAppTests.swift#L82-L97",
"version": "repo-lines-v1:sha256:5df6428ec900727f44626d2c096d50e92042158a81388fadcc35d921682677fc:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJiYTBlYWExNjRiMWFkNGRlZDY3YTA5MTJiOTczNzgyYjVlODFiMTk5MzljYWVkOTk4NGQ1YjhiZDkyZjVmMWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk0N2NmYWJkMWNhNjMyYzI3ZGI2NzhkMTk1ZmJiN2MxMzQ2MmE1YjNkYjA1N2FhZDMxODY3OWI5ZDk4NmQwNmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmZWMxZTJiYjEyZmY5NzEyY2M4MThiZWI1MDY3MTdjZjU0OWE2MDgzYWFjZTUzZDczNTBmZWRhODVkODhmMDQifQ"
}
]
},
{
"id": "claim_4cb4b76de2564105b980c29b639d1802",
"statement": "SFTPTransferContext lets queued transfers retain an authenticated primary connection after the UI owner releases it, closes that connection only when no owner or transfers remain, and opens additional connections from a snapshot through a noninteractive request.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L13-L31",
"version": "repo-lines-v1:sha256:7f016822f5e62b0349e69b24f267f7f4f992f45ab293e3f290c475d5da738acf:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY0ZjZmYjA4N2ExOTdmYmFlOTQzMjc3NjYxZDk3YTUyMjBiZTY2MDUyNmEyOGMxZjVlZmYzODA1ZmNjOGNlNWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIxYjkzZjYwZDI5N2E4M2YxYmNjZmU4MDI5ZjBiYjM5YjIwNDVjN2U1NGZhNGM5MDY5MWE4MGZkZTY5NjhlNzIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFjZjMzMmFhZmExODg1YWU1NDM2ODA5ZDg5Yjg3ZjU5ZDdlZjg4YTRjNDFiYzMzZjE0Yjg1ZjQwODhjNjk1ZmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFhNThjZjY1MGFmY2E3ODBmNzAyM2ZlYjBmZGRiMDA0MmY3YTEzNWU0YzViNjZmZWYzNTMyNTgxZGQ1NzY1MDQifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L212-L232",
"version": "repo-lines-v1:sha256:3e0dc4016575cf7f7b2909bf8dc370d8f005c92abb52516fcb3795052b00ec69:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ0MGY2MjA1OGZiNTRiY2Q2NzkyYWZhMWJhMWQyNDYyOTI4NTA3ZmQ1NzczZjljYzQzOTM4MzBmOTY4NzNjNWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3MTU4MTA0OTQxYjQ3MzkwM2I3NWZjZTc3Y2VlOWVkODc5MDlmYmY5NTk1NDE1YzhlN2M3YzhhZGU1NTA1ZTkifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L83-L97",
"version": "repo-lines-v1:sha256:318731d5f32cd2a82e924bddf0bfc5ea16c3e61aaf3657a42417d02f5661c5ab:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNhYjI5MjhiNzliNWJkMjU0ZDc3YmI3OTY1NTg5MGZiN2NlNmUzOTRiMTM1Mjc3ZDNhOTE5NjJjZmIyMDY4ZWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdkMzU1ODM2YmQ4ZGM0YzhkOWViNzg1NTFhNjMyNzAzMmE4YTNkOGE4ODYyYWY2MDNkNzMxYzBlMTY0ODM0ZjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE5NTc0YzEyODZmY2ZjNDZlODQ0NTdiNWUxNTc2NzliNDQyNDhiZGYyNWIzYTg5ODNjMjhhM2QyNzY4NGRmZTIifQ"
},
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L63-L108",
"version": "repo-lines-v1:sha256:eb48acd860adeeb8cb2e97326c168e6da60022567353533f5e35b8b7187639e2:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJkOWEyYzI1OTVkYzA1NzU3YWVkMjg4YjdmYmJjZjQzMzY1YjY5YTlkNzUxYjUzOWU2NmM4MDlkMTc3MWQ3NjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdiNGI3MTk3ZGYzZTE5NWZlNmIxOGI2YzhkM2Q4ZGNiZGExMDY2ZDUzZDZkY2NmZDFjMGFlM2I2MjIwODM4M2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAwMTA2MWZhOWJlNDg0MjcyZDg1NTRkMzUzZTExMmUwODZkYmNhZDA1Y2UxMjMzMTFkNGQ1YzkyMGY3MjEwYTUifQ"
}
]
},
{
"id": "claim_3053d0f489c3414b9a0db101eb006854",
"statement": "Transfer-context tests verify bounded per-host scheduling across multiple contexts, silent connection fallback behavior, and that cancellation or a retired generation does not trigger the PTY fallback.",
"evidence": [
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L129-L247",
"version": "repo-lines-v1:sha256:0c25c1e3e19475f49152efc9aba444dffcd103aa400b53c6ada1db5703b9998e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE5LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI5NGJlMWE4M2Y2Yjk1YjllMGU4MmU1MDc0MTQ3ZDM2OTg4NzBlZjY1MDVmMzAzMjBkYWM1ZmY4NzEzNWZmZmU4IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJiZDEyNGJkOTkwZGJmYWIwZWM3NTNhOGY4NGIyY2U5MTEyMzc1MjBhMTYzNDQ4ZGIwZWU5ZDg5YjczY2MxYWJjIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3Nzg4MWE2YmFiYzkzMDhjNzVhZDRjYjU3OWVlODhhNjY2NGFjNWMzMGI5ZjEzMmE3ZWVmM2JmZjAzZWY2NjQ3IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI3Y2UyZmFiMzc5NGU3NDNlZDhlMTlmMGU2OGM5Yzk4N2IwNTVjM2UxY2NiNGZjNWExZTI2MWVkZWFjNTU2OTQyIn0"
},
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L23-L61",
"version": "repo-lines-v1:sha256:36233b0246228b44f2b7a0e7fea9d6a72ba6cbe7d1a1c7aa190cedc5b9fc96d4:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFkNzZlMDQxNGIzOTY0OWFhZmNlOThkZTYxYTFjYWI2ODFiNDMwMzQ2NGMyNTljNjdjZjgwYzdjOTJiYmE2ZTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc5NWYxM2FlMjQ0MmVhMGZjOTUyNzkzMDJiZGVlYzg5YThjNTgwYzM1NmMwNjExNzQ3NThjZDJmNmFjZDY1N2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxMThhN2Q3NjM4NDU5Mzg3N2E0ZGEwODM2N2FjYzIwZWI1OThkNmQ5ZDAzYTVkMzc4ZDY0NGNiMzNkNTYyY2YifQ"
},
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L300-L364",
"version": "repo-lines-v1:sha256:d06e5469cc9891a6ce3427c2368ad915aae3aa487309cdae2a503425cdb98944:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ4NWRkNjE3Y2RmMjA3NmM2YTUxZjk3YjgxMjQ3ODA5NTI0MmQxYzVlYzU4ODVhNzkyYzQ4ZjllMGZmYzcwZTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIxM2ZjN2MzYzY3MWM3NmIxNWQ3NjdmNzU4NmY2NzA1ZDVmYmY3N2E4YTNjNWJmMTYzNDJmMjU1ZTIwMDdmOTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBiNGM0MzMwZGI0NGQzZDVlNmIxYTBkZjE2Y2E5NzZjYzMxMTI4OGIxOGM5YjEyY2U2Yzg1YzI4YjMyMWNmNjQifQ"
}
]
},
{
"id": "claim_dba1a016f55e488aa4e02551ff66af97",
"statement": "Security regression fixtures verify that agent authentication can use one-use credentials without mutating Vault state unless saving is requested, collect jump-host and destination authentication in route order, and coalesce concurrent authentication while preventing SFTP opening after cancellation.",
"evidence": [
{
"resource": "repo://TFMTests/AgentHostAuthenticationTests.swift#L129-L187",
"version": "repo-lines-v1:sha256:f7b1efd0534aeb856339e49a6605dc404d4383f12a440efb3f3b781f10ef0eaa:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImViMjQxOGE5ZjZmNjg4ZTJiN2YwODgzMmRlYzkzZWU1OGM2MDI4N2M0YzY2ZmEwYzVkYTNlYjY3NWZkMDVkMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZlMjBmZWY4NGZiM2E0MTNkMDRiMjg2MjZhNjNmY2E4MWFiZmRhNjM2NDY1OGUzNzA3ZmY3MzdlMDFkM2VkOWMifQ"
},
{
"resource": "repo://TFMTests/AgentHostAuthenticationTests.swift#L325-L373",
"version": "repo-lines-v1:sha256:ba42ca78a504462bbb4050865f055958b795c61d62b5c956bc45f548a1065803:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNiZGY5ODllNjcyMmRjZTFkNmZlZDhhOTI4MzFhMTU5YzYwMjA3MTUwNTIzMGZkNjc0ZWU0OTFkZTA2MWMzYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEzNGVmOTQ0NDZlNTA5MWI5NjUxMDU3MzczNGVmZjZmNjdiNTRiZDIyZWQyOWExMzdhMWU2Y2FlZDYxMzU5Y2QifQ"
},
{
"resource": "repo://TFMTests/AgentHostAuthenticationTests.swift#L431-L510",
"version": "repo-lines-v1:sha256:9399f5a52fe0d6e709bcee334564b850395c493c7b583ae6095497f78c3a217d:eyJzZWxlY3RlZExpbmVDb3VudCI6ODAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNiNDY0MGY5ZTJmY2JiODc4ZWU0NTg0M2RmMTRhZTYxNDgyZDRlNWU3MmE2YjcxZWNhYmI5OTQ5YzA3ZjdmZDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNhYjhlOTFhZmNiOGNhYzRiNWE3M2UxNDhkZDczOWY4NDk4MjVmMjQ1OTlhYmZmOTUzZmJkZmUyYzEyZDNjNTQifQ"
}
]
},
{
"id": "claim_963e67af43b241f1aa2a7613820c344d",
"statement": "SSH interaction-policy tests require forbidden requests to fail rather than show host-key or keyboard-interactive UI; additional connection snapshots retain references instead of credential material, and clearing a connection configuration consumes secret values shared by copies.",
"evidence": [
{
"resource": "repo://FrameworkTests/SSHInteractionPolicyTests.swift#L189-L245",
"version": "repo-lines-v1:sha256:7560898a835debb386dd98996192ebafa3389f3d48f2cd0b5a267cc86462601d:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdiNTQ3M2I0ZTBlYmEyN2Q2ZjAwMzFjMDIzMmFlOTZlNzcyNTkwMTA1MmY1ZGE2MGY3NmNjOWIwYzY4NjMzOGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVmNjA3ODI4ZDQxZDU5YjhjM2Y0YmZmOWQ0ZWQyZDRkODYyMzRlOGZmOGE4M2U5OTQ4OGYyMjhjNWQzMzMzZWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRjZWViYzViMDE1M2Q4MGZiNGU0MjFhN2EzMWE4MzQ3OWQ0Yjg0NzVlZTYyOWI2NmZlZGIzNzc2MjY3NDVlNTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
},
{
"resource": "repo://FrameworkTests/SSHInteractionPolicyTests.swift#L38-L71",
"version": "repo-lines-v1:sha256:05cb17904112816b584ad40075ff219adebb2bf83efc9e83a8d0fde061ad8413:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNlZTFiYmIzYjViOTY4OTgxM2EwYzMwOGQxZjcxZjQ0NTU3YzI4MjM5NjdhMzVkYzcwNzAzYjNmOGEyNWE0YmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgyMDZlODhkZWJhNDhkYjBjNDA1YWQyZWZmODEzZGE4N2MzOTY4N2QwZjczNzQxY2U0NGQyODBhNGQyNmYyNDAifQ"
},
{
"resource": "repo://FrameworkTests/SSHInteractionPolicyTests.swift#L8-L36",
"version": "repo-lines-v1:sha256:1adf4e9a2b0623e9514f4c2d05cdf676c9b57fa07e5442e4c85324de3346383b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNkNjFkNmE5MGI4ZTQzMWQyODM5MjFhZWY5ZTk5ODdlZjI5ZThmNWFkZmMwM2I0YjkzZjI5YWUzMjBiM2JmZWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk3M2I2N2JlNzFjZGFhMTVmNGY2MDZlOWIzNjAzZmNjMTkzZGU3ZWIzNzhmNWY1OWJhNjQ5ZDY0NGEyYWY4NjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFlMDVlZjQ5Yjg1NTY2ZGIwM2JjNTNlMTM2MDljZTM2MDYyOTk0NTc5OTAyYWUwNTUwYzJhZTEwNGEzNDY4MGEifQ"
}
]
},
{
"id": "claim_8d0709b664d94ebb8abcf7d7a20a7418",
"statement": "Persistence compatibility tests open historical SwiftData fixtures through the shared container factory, assert retained records and migration outcomes, and verify independent in-memory containers expose the full schema.",
"evidence": [
{
"resource": "repo://FrameworkTests/PersistenceCompatibilityTests.swift#L22-L89",
"version": "repo-lines-v1:sha256:86e0ea6e63d5624d21afc6b082e4d62104188200b4b484e2ef92513b8a3fcf68:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwY2NlMjYyMzJlNGRmZGY0MzdkMDRjNDAxN2I1MWQ5ZGY0ZGYyODVjYmFkNTI4YzcxMDY5ZTA5NGRkNjNhMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjljZDY0Y2U3MWNmNThiZmMxOGRjOGNlOTc3N2RlNjVhMGU4MjcyNDc2ZDUzMDUzNDdiZDYyNmI3YjFiZTJjMmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmNjM3YTI0NzMyOGUzMTA0MWU4Y2I4MjE3NzhiYTVkNjE3ZjNlYzIyNzE2ZTgzMTdjMTU2NTU4YTk0Mjg4ZTIifQ"
},
{
"resource": "repo://FrameworkTests/PersistenceCompatibilityTests.swift#L92-L175",
"version": "repo-lines-v1:sha256:350be9cb654f9d715e6fbcb7c7542f0ac949ed2b97a8573811e5a3219a3ca810:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI0MTI4ZTcwN2VhNWRkMTgxNDgzNzY5MTdiMzFiODgxZjcwYjdmYTlmN2VmM2U3NWI3Y2U1ZmU1MTRmNWRlNDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI3YzZkZjQxNTJiNzdkYWM0ODJmZmQ5M2Y3NWUyYTA0MTJkZTk5NDVhNWFiMmI3ZDY5ZDc2YjAyZGQzNTRiMmYifQ"
}
]
},
{
"id": "claim_a706a7dc8da049e8b69b01df1dfef698",
"statement": "Agent replay persistence tests verify frozen context/tool-result restoration, prevent replay-row duplication across later snapshots, remove replay backing on conversation deletion, and preserve a durable result recorded before the next snapshot.",
"evidence": [
{
"resource": "repo://FrameworkTests/AgentReplayPersistenceTests.swift#L12-L64",
"version": "repo-lines-v1:sha256:1d91c37540c7dea05756c281709cc014a95b0723c78284b8a979570f6e9ea3d6:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBiNTFmNjI3NGQ5NDk5MTAwOGM3NzI0OTMwMmZhOGQ5NjcxZDE5NmExOTk5MzdmOWM1ZDhmZDk1M2UzYmY0YjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJkYmFkZWE5NTg5OGQxNzlkNmY2NjRlMmZhYWU2ZjkxY2YxYmZlNDc3ZTRkNjAxMjBiOWU3NTFiZDNiOGIyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY3MzE2YzY1YWJjMWM2NmY5MWYzZjM4NWM3OTNkMjEzMjNlYjk3ZTkxZjNiNGVmYWI0OTNjMGE4YmY1YzUzZGIifQ"
},
{
"resource": "repo://FrameworkTests/AgentReplayPersistenceTests.swift#L66-L93",
"version": "repo-lines-v1:sha256:a7a6a69692b66acfabab87d67d6cdce42517ed039c7a5aca47c32a120bac565c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI5YzY1ZTM1MTNlYmM3YzUxNTU2ZTY5N2M1ZmM1OWQ4NzQ0M2Q0MTEwOWEzYzcxNWE1N2Q5ODQ5YzEyZWI3ODciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_90524ff4680948cd92bf801ba5d0ae93",
"statement": "MacOS tests that show windows or take focus must use the requiresVisibleWindow trait, which is enabled only by TERMIND_WINDOW_TESTS=1; normal test runs therefore skip them.",
"evidence": [
{
"resource": "repo://AGENTS.md#L44-L44",
"version": "repo-lines-v1:sha256:825a259b0fc873bd80b8a95ec1455eb28acf00cd15c03dd17d94e8bee428513c:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTczYTI2N2E2ZGNmZTczN2MyODUyYjY2OTkyNTViNWZlMWViYjYzMzVlZmZiYzgwZjA3ZWE0ZWExZTBhNzdlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L11",
"version": "repo-lines-v1:sha256:b8b2903d1009b119d2daa9cc5915fe34eab19cf61490b33adc02693393f4c95f:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,246 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:0ba005777749189c842f01e920cd1360444545e29e6b4fbbef9076c287cd0b9c",
"claims": [
{
"id": "claim_dc6281a3ccb7415ea961d1a954248647",
"statement": "Vault, Settings, and Metrics are separate CloudKit synchronization categories: each coordinator owns its own zone, engine lifecycle, journal-backed state, account binding, and upload queue, while sharing the CloudSyncLifecycle implementation.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L81-L101",
"version": "repo-lines-v1:sha256:ecf2e0b99654bee0d36c23d392374af498f6667c360125060da62c89fa06de5d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRmOTVhYmE2NjdhZmU0N2Y3YWM0N2QzZTY3MDI2MmNmNGIyMDkwNTg2Mzg0OGUwMDNmMDAwZjliN2JlODg2ZjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2MmE5MGM5NzgyYjE5NmZiYmIxMmRhOTY3MThmMmRmZWEyNmI2MDdlOTQyNzkzNzAzMWVhMGQxYzA2ODlhYWYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJmNjYzOTkwYWFjNGUwNWQxNWZjYjkwZWNmZGFlYzkwODczNmIzNzk4NGZkZWMwZWQ0Y2Q2NDg4YmZiZWIwNDgifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/MetricsSyncCoordinator.swift#L8-L27",
"version": "repo-lines-v1:sha256:f299ba814a14f274ccfccfa036ba77937d7bdf7e782390b086a3e2aeff813fb4:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxZGI5YzNkNzg0ZGI1YWRjNDAzNzM5NzJkNGFhZDQ2NzVhYTVmOGYxYmNlNzc2NDgyM2NjZjU2ZTNkZGE5ZWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJmYzcxZGM1ZTM3ZGFhOTNiYjAwMzg3MDNmNWI1MGY5NGM5ZWJmNDMxMzNlZmI2YWIxYzI0NDk5NzU2NjZhYmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhNDEzOTNjODU0MWVjYzQwZTdjMzZiM2Y2MmQ0YTFmMDY5MWRmOTI3NzZkM2E1YzRhYWU2OWQ4OWFhYTZhOWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYxMjE1OWY1MWUzNjExNmQ2OWY5M2MxOWJmMzdkMDEzODdiNjA5YWQxZDhiNjc3ZmMxNDI1MGZmZjI3MzZkNjUifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L8-L31",
"version": "repo-lines-v1:sha256:4f6d3393e2e44d20a6cc076dbfbd8c3a6aa993ecb248055a24de0b8484debe79:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJlNDhhMTRlZDczN2IwNzhiZDNkZWM5ODJlYzE2NmIxZWM2ODMyZmM2MGMyYmIzZjA1M2IzMWYxMjdlZDUxNzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJmYzcxZGM1ZTM3ZGFhOTNiYjAwMzg3MDNmNWI1MGY5NGM5ZWJmNDMxMzNlZmI2YWIxYzI0NDk5NzU2NjZhYmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhNDEzOTNjODU0MWVjYzQwZTdjMzZiM2Y2MmQ0YTFmMDY5MWRmOTI3NzZkM2E1YzRhYWU2OWQ4OWFhYTZhOWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYxMjE1OWY1MWUzNjExNmQ2OWY5M2MxOWJmMzdkMDEzODdiNjA5YWQxZDhiNjc3ZmMxNDI1MGZmZjI3MzZkNjUifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/VaultSyncCoordinator.swift#L10-L25",
"version": "repo-lines-v1:sha256:f3b49cbf16da49bb697cf0d0f3d8b4d8252a2c1d753c720782c904983d5b32d6:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNTVlMWZkMDI1MDQ0ZGNlYTJiNDg3NTQwYTk1NTgzODljM2E1ZDYyYWFlNzM1MWJiMTk0MmI1YTE2NGZmNjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJmYzcxZGM1ZTM3ZGFhOTNiYjAwMzg3MDNmNWI1MGY5NGM5ZWJmNDMxMzNlZmI2YWIxYzI0NDk5NzU2NjZhYmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYyMmMwMWQ0MzJiYWM3OGM0MWM3ODQ0ZDQ2MmUxZWJhNjZlMzRmMDk3MzYwNWU1NDY5YjM1ZjgzOWIwMWMzODAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYxMjE1OWY1MWUzNjExNmQ2OWY5M2MxOWJmMzdkMDEzODdiNjA5YWQxZDhiNjc3ZmMxNDI1MGZmZjI3MzZkNjUifQ"
}
]
},
{
"id": "claim_08c4268dbc5248c8b175c319aa2d0e2c",
"statement": "A category is enabled only when both the master iCloud preference and its category preference are enabled; the master and all three category defaults are on, and preference migration preserves explicit choices while deriving legacy settings.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/SettingsKey.swift#L17-L30",
"version": "repo-lines-v1:sha256:9a1ec7fb86b8f292f885c4ec867d8d8798e32ee30783eee847f9317e14240bb9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgwMGJkZGE0NjNhMGMxZjlkYjYzOGY1MzU0NTU3ZWUxNGFiNDY1MDk3NDNkYTU4ZDk5NGQyY2Y1ZGMzMzM1YTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjViN2ZjOThiOTk2NGQwMDNlNThmYjIyZWQ2OGE3ZTQ1Yjc0YjhjM2RmNjRiN2JkZjFjYjI2OTFmYzcxODdjMmMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE2MGMwNzRkZTA5MzNhZTg3NDFkNGM2YTYwNjcxOGVhYmU1YjJlYzQ2Mzk4NTcxNzUyNTFjNGY1ODE2MDJlZjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYzNjgwMmMwNjhkYjk0MTdlN2U2ZmUzYzBhOGQ0NmNjNGQ5ZmVhMGMyZTU5MWFhZWRkNDA5NjA4Njk2NmQ3NGIifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/SettingsKey.swift#L58-L69",
"version": "repo-lines-v1:sha256:85230eea0d635438531183dcb557b5d5c5eee88dd085dc8b73d7a2e254b6873e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM0NzMwMTYzMjhiZjFiZWViYzBjOTRmZjYyYmNlNWJiZTVlMjY3YjY1ZWE1ZmYzYzkzNDZlNTgzMTNiZWUzMmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRhYmNlZGQ0ZGJiYWI1MTJhZTRiYTNkZjQwMTBmMDY1MTY4MjA4M2ZmYTA1YTQwYTlkMTE0ZGZhYTY1ODE4MDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU2MTE1ZDkwNDc1NjMxOTg3YzE1NTVmYjIyOTdhNjgxZjBlNGMwMmRiZTA3MjYyZjU3M2UxMzkwNmE1Yjc3YTIifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L122-L140",
"version": "repo-lines-v1:sha256:3a91bc5a22960e2ce75f62f518c777ed253af0a1a34105436096077e0bdf4b68:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiMzk4YmYyMmYxODdkM2JhNDcxZjBlOGUwZTgzZGMzMzkwMjAxMjM5YjgwYWI5NGY3ZmQ2MDUxZTI0NzVhZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1N2M3Y2Q2OTJmNjFlNGIzMzVlYjhiNWRlOGYwNDQ3YTVjYTljZmQ0NDhmZjE5MmE1ODE5MjUzYzIzMTRkMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU2ODMwOGZkYjFlOWUxN2E5MTM4MWEzZjRkOGZiOWE3NTcyNzc1NTQzYWI2NWNlNzRhMmVjOWFkZDQ2MzhjMGEifQ"
}
]
},
{
"id": "claim_30d975ac9872412bb57fb1e2f2c9e3cd",
"statement": "Desktop starts or pauses all three coordinators according to the Vault-sync Pro capability, while mobile reconciles them only when a scene is active and that capability is available.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppModel.swift#L525-L536",
"version": "repo-lines-v1:sha256:054076d1b4d1b64030764eea525dc62c47eae25fcc1a49f2ef6c3873f365cffe:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE3Y2E3MWJkZmM2MGVhMzNkYWQ0YWI2NmNkYjBjNmM5MjUzOGY1NDA0NjRkYzY1OGExMTkwYjUyZTc3MGUyMmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ1MGZiNmUwZThhYmY3YmNiNjdkODIzMzJjMmVlOGZlNzY0NzYzZDFlZjA5ODc4NWM3ZmM4Y2Q1Zjk2ZmRkOGUifQ"
},
{
"resource": "repo://TFM/App/AppModel.swift#L328-L345",
"version": "repo-lines-v1:sha256:4aa1cb83ebc7adf699babefa551b027bc4669965f2cab1959209054daceb9005:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3MDMyZjUzOTcxNDA0YjMxMjM2MmZkYmQ5MzlmOGRlNjYzMGRiNGVhNTQ1Mjk5MTUxNDVlMjNmY2RjNTc0MGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdhNmVkNDJiNDliZDBjNGNkMDNiZmMwMzRkNzZiMzI2NjliZmYwOGYwOTE5OTRkMDUyNTIwODllYmEyNTEwNWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdlYWIxYTM2OTk4NGYxYTNmZTIxOWU5Y2MzZGI4YzY3MjI1OGU1ZGM3OGUxYTdlNmQ5OWE4MDcyYjA5Y2ZlMjkifQ"
}
]
},
{
"id": "claim_87e7a87a46194993bb8de42071a54f67",
"statement": "CloudSyncLifecycle requires account availability, account binding, engine creation, queued-record restoration, zone creation, and a successful zone fetch before it enables sending; local changes can be journaled while an engine is absent or the initial fetch is incomplete.",
"evidence": [
{
"resource": "repo://FrameworkTests/CloudSyncLifecycleTests.swift#L12-L34",
"version": "repo-lines-v1:sha256:2a65251ddbccd6058c1fdfcb9a8869a09c6a7dd58a34c19c5772e3d369c5fa7e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJkMDI5OTk4MGRjMGJmNzc3ZGM2Zjc2NGQ0NzFhZDRmMGQwMGVjZWZlY2ZiNTg4NTcwN2EwMTIwNTU4OTBmY2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjViZWUzMmEyZGRiZWI3ODY0NDc4MGQ5ZmEzYzQ5ODJmYzhiMjRjOWE0ODhmNTZhMDZiYTA4NjllNzdmZjEzYzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkNjU0YjY2YjAyZjQ3YTdjOThhY2JmNTFhYTNmYjU3MTM4YTFlYWE0NjE4MGM3YmI3OWFiNDU5NjA5OGM1MmUifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L158-L163",
"version": "repo-lines-v1:sha256:c5151699e44e427b5ccde5040bab169b6f4ef3afa61e67cae217856adf26230a:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNzAwYmI3NGJkZmU0ZTNlNGMzZGU2NDAyZWE1NDFkMzExYmViNTFmNDUyZGQ2YzlkNTgwYjJkNzlhNTFkZWRlMSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTRiMGIxNzFmNWUyOGNhOTFiZGRhM2MyMDM4MTg3MDJlYThiMzZmYTNjYTRjYjAzYjY0ZjIxMDBiMWRhZDhjNiJ9"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L197-L260",
"version": "repo-lines-v1:sha256:bed93db939e6335453c5ec7721167875e9d5c6578ac1bf5fc455bda23b2bca3c:eyJzZWxlY3RlZExpbmVDb3VudCI6NjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmZjZjZDU0MzRmN2FjOTAyZTE0MmI5Y2ZiN2Y0MmQ3ZmU5YzlhYTUxZTVjNmJmMzg5ZDA1N2E5ZmJmNDc3NTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2YTQwMTNhMTc2ZWY2ZWRmN2M3ZDE4Zjg0MGRiNzk0YjU1MDZjZDNmZWIwOWM1OTE3MzAxYjNmOTEwYWRlNDgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjExMjhjMDM5ZjQ4NmI2NGY2Y2MxZDNhNTVhNzNkMjI0MWNkYjYxMDU1OWM0ZGIyZmYyOGJlZmIxMjU2NTI0YmIifQ"
}
]
},
{
"id": "claim_a927137ffab84086a81c1f94cd05caac",
"statement": "Retiring a CloudKit lifecycle invalidates its operation generation, cancels the task and active engine, clears send readiness and authorization, and the current-engine identity check prevents stale operations or delegate callbacks from publishing after replacement.",
"evidence": [
{
"resource": "repo://FrameworkTests/CloudSyncLifecycleTests.swift#L58-L110",
"version": "repo-lines-v1:sha256:5491de5f94b2ee5d3197e3f53fea2bb36a10ace1970ce605bd7f8c5aa179e46f:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFhNDNiNDMwY2YwZWU5OTlkYjY3ZjA4OGFkYTAzZjI1YmU0NTk2Y2ZjNzVkOTJhZTU3OGQ2MjUyNTlhM2JkZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUxYjAyY2I2ODlhM2Q3ODM3M2Q4OTQzODI1OWQyMTIxYjU4YThkOGE5Mjg5MDFhMmVjNGQzNTk4ZmIyYWFjYWUifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L184-L194",
"version": "repo-lines-v1:sha256:58ac752d13ca10fbc4b28775de3a2d91f3badcc31e1b8e384b9cd10a927eeb16:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJkM2ZkMzBhMTczNWU4NTQzZjQzZTE3OTJlODliMDc2NWJlNjhmM2JlZTNlMGVlNDE5MGMzM2EyNDhiZmY3ZTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkNWY5ZDZlNjY2NzNjNWNiOWViMThhYWQxMWEzNGRiZjIwYmZiOTNiMTExNjVhZTNhYzM0YzhhYWQ2MDQ1NDIifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L263-L264",
"version": "repo-lines-v1:sha256:4f4ea6d2ce525958be4554cdf469c9da0b77141deb58a529d044961529cdeaed:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNWY0OTEwNTQ1MzU2NjMyNmI3MjIzYmEzOGE4NDNhYjEzNmZmODQyYzA1M2E5ZjJlNDc1NzJmOTM1NDEzNGZmNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDBhYzliOTcwMjdkNjdmMDZhZDM0ZDA1Mzc1M2M0MWZmNDA0NjJiM2JmODRjOWY4MWJmOWI3YmEyODFjZmE4OCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTAyZTA1Y2MwMDY4ZjYxYmYxMDlmZDAxOWVjM2Q5YmUxOWNiZGU1YTRjMzFhYTEyYmY5OGIxNDUzNzgxYTBhZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZGM5NzNkOTkzMTZjNzFhMjkwZjk1YWM4YTczMWQzYzMwMjFkNTk5NTZjYjEzYjE3NDNiOWVmMjg0OGQwN2Y2OSJ9"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L311-L321",
"version": "repo-lines-v1:sha256:6e8f85b1d17bb077aadfbc2677dfc94559a7b61bd7308989863e47a1c5eb1b5e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI3YWYyMjljNGQwMGYyYzU2ODY5ZGNmYjlmOGM0YjgzZDc5ZTkxYzQ2NDA0YjA2ZWNhZmRlY2U2MGUyOGMyMzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzYzIzNzgwZmYyOWQ5MGJlYWM2NGEwYjcyNDZjN2E5NTFiOGI1MTk4YjNiODg1YTJjZTBlODJiNzgyOGFjYTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5N2FjZTViZGVmZWVhZWVkYjJiMzQ1MzI2NWZjODgwMzRkNmE5OTRiMjZiYjBkYjIxZTA2YTRlZWVmODQxZmMifQ"
}
]
},
{
"id": "claim_7fa664c9558546daa18c03394bd3b6b6",
"statement": "On an account mismatch, synchronization stops pending user confirmation; confirming resets journal data for the new account before binding it, while account sign-out/switch events retire the engine and zone or environment resets requeue entries after clearing CloudKit metadata and engine state.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L165-L181",
"version": "repo-lines-v1:sha256:965c604f6d9011104426ca6d06900cf3ebd96455f204d3c23541648abd9675a5:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmZjhiMDlhMGNlYmVkMzhlMTc5OWJjMDUyMzNjMDQ3YzM4OTFjYTI3OTM0ZDZkZDQ1N2NiNWMzODIwNjcwODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRiOTEyYTJlZGFhMWI0YjgxNTk4NmJkOWYyNzk5ZTZhN2FlYmFmMmUzODdhNjYwZDZkNTJkNDY5M2FmZGIzZjkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk0ODE3N2EyODNjOTI2MzVhY2EyZGI0ZTA1Y2EzNjAyYzBkNmViYThiYjM5MTQ2N2JhYTNhZWYzOTMzMTJjZDYifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L207-L235",
"version": "repo-lines-v1:sha256:15bcbc011e0b22d79da91093cd554daec8bed7de45fb4490b944ac3d2d0f9434:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRhZDFhMzk5MmZhODY2MjlhNjZmZDhlODI4ZGM2ZmFjMjAyZGYxZDZmNTE5MDVhNjRkZDA2ZjUwMDljMTFlM2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAzMWQ2M2EzNTc5ODUxZGFlMmJlZjM4NGEyZTgzZTg1YjFmZjQyYzVkYjNiMmRlZjFkZWVjYWRkZDZlNWNlMmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRhMmMyY2Q3MjE2MTkyNGJhZmMzNTlkZTY0Yzg4MTg4ZGIwZmI4ODM5Y2VmNzBmNGI1YTBkNDVhNGMwOTYyZjYifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L287-L328",
"version": "repo-lines-v1:sha256:11ecf11eb6904906b9de92b4bf010b5d3a8ccf9e0ea27d5b1307868dd40a42c4:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzN2IzMDhlZWM0OTJlNzU2MzNlYjIyY2VlY2Y1ZGQ0MTQ3MDdhODJiYWQ2NTg1YzlmNjI1ODMxMDY3NzhiNmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFmMDNkZWFiOWY4YjcxYzE5NDk3YWMzZmQ0NjhkYTNlMGUwMTgwY2EwYzA4NWZjZWFlZmZhODcwZGNiMTMwNTgifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataVaultJournal.swift#L379-L408",
"version": "repo-lines-v1:sha256:0428a9f6d756fe80e13e507a377a26b3489a3fcd9a8d1001ae6cff22770392ea:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjNDRkZWU1NzRjM2JlMDY4OGRmY2JmYjVkNDAyYzA0ZGM0OTA1OTg1YmI2NGJjMThjYjc1NzNlY2IwMzE2NzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA5NzcwZjVkZjIzODBhNzcyODRhYTdhMjA3MWE1NDgyYWNkNmQ4NTAyNTMzNzZjZjVkYmY0MjI2NjUzMDZmYzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhkZGRkMmI4MmE2MDlhNmFiNzEyNzI1ODJmZWE1OTNhNmE3MmY2OGFjZWRiOTA4Y2U4OTZlNWNiOTJlYWI2NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI4NWQwZGRkYWNmZjUxYzIxYmU0YTdhMzhmMjM5OTdkYjNhZWJhODFkOGUyNjhmMTNmMTg5YWYzMGMzYzM4NDcifQ"
}
]
},
{
"id": "claim_bf221aec31bd4c8ea705b2c1ba4072ee",
"statement": "The durable journals record changed envelopes and tombstones for upload, retain CloudKit system fields, apply deterministic version-based merge decisions, requeue local winners, and clear upload intent only when the acknowledged version still matches the journal entry.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L296-L334",
"version": "repo-lines-v1:sha256:27a6507d7012a55fc301f5a547aa8bc82077f0c3a12aaf24e60fbde10bfea9f9:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVhN2Y4YTVjZTI4MmRjOTZlOGJjMGZhNzVjZjdmMjRmNTFjNWJlMjVjYTY0ODdkNmNiMDI3NmE2OTU1YmViOTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFlYjcwNDQ0NjQwNjA4ZDhmZTU2YzAxZGFjYjY4NTkzZTEzMGVlZWRlYmI0ZTRlZGM2NGFkMDY3MmJiM2QwZjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUyNWQwN2I5NTU3MmQ5MGEyNWI5YmEyZDhiNDBiOGE2MmYyMDFiOGI1N2EyNjJiYWYxZWNmMTVhODY4NzNiZjIifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/MetricsSyncStore.swift#L101-L165",
"version": "repo-lines-v1:sha256:60c566b41c26ac6468eaf53a39a6bd48b4d5b71222b39e204d471c5a6bd17924:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNkMjk4M2ZhNmNkMjk1ZDgyNTg4NGZlNGY5NDAzYjkxMzIwMjFiN2I4ZWJkNjk1M2EwYWNkOTk5MTJmODM4NjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQzMWFmOGYxNDQ5Zjg2YzIzMjZhMGRlNGY1ZmU5Yzk4MDJjMTNmNDBkZTgxNTQ0ZjhjYjIwNWRlMDA4ZDk0ODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEzMDliMWQ5ZDhlMDFmNTJkNjIwN2RiM2MyZmEyYjhhNWIxNGYzMGUwOWFmZmE3Njk3ZGY1YTZiN2M5MDBiYzUifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/MetricsSyncStore.swift#L54-L95",
"version": "repo-lines-v1:sha256:cc56e675681b0a5bf0ac4c2ed6606f17beabd0c02f3af1b4352f62d48dee80a1:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNiMjM5NzliNDZlZGI5MzdlNzNhYWEzMTAyMjAyMjJkZWFlZGQwMGIxM2ZlYTA3ZDU2NDkwMGU4MmViMTY0OGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZiYmQ3MzNlZDQ1ZmRlNTBiOWZmZmFlNGY0ZWI3N2UzM2I1NDRlZDJmZTBkMWU3ODQzMGFjMjY1NGQ4NmUwM2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdlMzA0MjcxMjhhMzk0NWU1NjBiNTk2NjZmYWQ1Nzg4YzQ1MTdmYTg3NWIxNzlmNzk0ZmY2OTIwMDEyMzMwYTQifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SettingsSyncJournalStore.swift#L113-L161",
"version": "repo-lines-v1:sha256:9a93e9d3f7187b30f9fb50b02a3f6a5e9c2af865ac4230ab57e1706d615a8d22:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNiMjM5NzliNDZlZGI5MzdlNzNhYWEzMTAyMjAyMjJkZWFlZGQwMGIxM2ZlYTA3ZDU2NDkwMGU4MmViMTY0OGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjliODY1YjI5M2I2Zjc1NWNlMTIyOWZiN2QxZDZmNTg5MjU5YWZjZDZiZGY0N2M3ODczZTYyNzJlZjAzNmI5ZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU3MjQ2Y2I5ZWQ4OTNlNTc2NzhiYzI1ZjQxMGY2Nzg1NWI3OTFmYzg0YjU1NjNkMmM2ZDM1NmRmZDUyZjk1ODEifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SettingsSyncJournalStore.swift#L167-L239",
"version": "repo-lines-v1:sha256:469cca48f056086ac60f81d2d321ded25a50175aef296db3e0d74eee4f7361fc:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkYzViOGY2ZWRlNjZkNTI4YTk1YTI1NWQwMjk3YTNlMzRlY2VhNTk1ZDBmMmM1YTNjMjc3ZTBkZGEyNjQ3NTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQzMWFmOGYxNDQ5Zjg2YzIzMjZhMGRlNGY1ZmU5Yzk4MDJjMTNmNDBkZTgxNTQ0ZjhjYjIwNWRlMDA4ZDk0ODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiYjdkZTkwMTM2NmM2M2Q1MDRiNmFkMDc4Y2VhOTJhMDA4ZGI5NzkzZTUxODkxMTI1NjIxN2Y4MWQyMTViYWEifQ"
}
]
},
{
"id": "claim_215dac4db05f4afaa901e5aa51d5bf1b",
"statement": "Coordinators quarantine invalid fetched records, do not translate physical CloudKit deletions into data deletion when a local journal envelope remains, and use CloudKit record conflict results to merge/requeue records rather than dropping changes.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L235-L334",
"version": "repo-lines-v1:sha256:a954a2d5e0e54c348c903c82d5da46003985c5f117a42d42c76b989187cbf04c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAwLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI3Y2JlNzFmODc3MmRmM2IwZGI2OTRmOGM3YmZjM2NmMzc5ZWQyMjkyNWU1ZTgyMzFkYTllYzk4ZDQ0MzRiNTIzIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI1MjVkMDdiOTU1NzJkOTBhMjViOWJhMmQ4YjQwYjhhNjJmMjAxYjhiNTdhMjYyYmFmMWVjZjE1YTg2ODczYmYyIn0"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/VaultSyncCoordinator.swift#L196-L281",
"version": "repo-lines-v1:sha256:dc52c35f8e9869db772c6f67b94dc57d01cda71128c34a1abc69cd2650f8f43a:eyJzZWxlY3RlZExpbmVDb3VudCI6ODYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjYmU3MWY4NzcyZGYzYjBkYjY5NGY4YzdiZmMzY2YzNzllZDIyOTI1ZTVlODIzMWRhOWVjOThkNDQzNGI1MjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3ZmIwOGJmYjIyNTk4ZmJiOWM0NTgyNjRmM2MxYzZiMDA2MTY4YjY5MTY2MmJjNTBhZTVjYzVlMjg2ZDU2ZmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNiNWU4NjlmMmYwMDFmMTE2YTkwNzVlNmE4MjRiYTQ1NWI3ODBiNjZhZTYwM2I4MmU1YTQ5NDM5NGVmNWJjYTgifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataVaultJournal.swift#L307-L336",
"version": "repo-lines-v1:sha256:98c206a0ce4a4d5a98628baba2d9bcecd3dc8b602a9fd07c51b05a96f6105a2a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNhZjBlNWI0MTBmZmYxY2UxMmNjYWNiMGU3NWVkNWIzMzQ4NTE0OTVjOGE1NWEzNjZiZmExNWE2NGM4YTFkNGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI5OTkxNGQwYmIxOTQ3YmQ5ZGY0MTQ0OGI5NTQ5YmIxZTUxMjE5YjZmOTVlYjAyMGNlZGQ2Zjc3MGU4MTkzMmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJmOGIyNjk0OTY4ZDU0NjY0NzdmMTE1ZDE3ZGVlNGE0MGY2NzkyYTY3YzY4ZDkzZTVjOTY1NjFiZTdjY2MzODEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU3OGRiODI2MGU4OTk1YWYyMjg0MDBhM2FiYjg0Y2Y1MjI3MzYzOGY2OWU4MTVjNTc5MDI1YTk0MmE5ZTg3NjkifQ"
}
]
},
{
"id": "claim_97b5c72b36a0402b9bc1cfcd918efcb2",
"statement": "Vault synchronization strips device-local expansion and identity-use metadata from outgoing envelopes and preserves local identity usage when applying remote configuration; Settings explicitly keeps debug/review and terminal typography keys device-local.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/SettingsKey.swift#L4-L14",
"version": "repo-lines-v1:sha256:5d2fe3af880ad8eef162becc00b07eaa94beb68a2a00f575a2d230cb16adaac7:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNiNTVjODY0YzFkM2E1ZTEzZWYzOGNiZTIyMWMzZjM4OWJhZGI2OThjYjA1MzQxZWRhN2ZmYzFiM2U0M2RlNTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdhZWIwMGEzODU4ZGRmODA5ODEyMTRkYTJiYzYzYmZjZTY0YjQ3NTE1ZDYwNDQ3MDdmOWFiNGNjZDliZDI1MjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE1OGQ0YTkxMDc0MDU5ZjBjOGQyMTM2ZjliZjgwODM0NjE0OGZjOGNmYjM1NDNkZGNiYzc1MGU3NTc2ZTcyNjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQzYzM3Zjc0MjU5M2I1MzcyYTU1NjAyZmZmYjZkYzE2ZmFjMDY5MDU4ZmUxNDE0NDg2MjIwMzYwNjgxZTA3OGMifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/SettingsKey.swift#L46-L49",
"version": "repo-lines-v1:sha256:8a77f82d7e289935c72cbb60441c5efe97b365ea2c4a35ea4e32ac190560984a:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDY5ZWRhM2Y3ZTYzOWMwNDVmMzAzZWZkYWM5ZTIzYjhhMWJkZDRlMGI2MDU0MGVlZjlkZDJhYjRhM2EyNTMxYSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOTEyOTdlMTdiZDY0ZDBhZjVjMDMxMDc5YTQzOTYwN2ZiZmZkMDEzNzM4NjNkMjE3NmFiZGQwM2QyODBkOTUzMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZWMzYjg3MzJjYzI1MGY1M2U5MTgyYTYwOWRmMmMxMGU1M2MwMGNkZDUzMjQ3MjFjMDAwODVlMzYxMjJiOGFlZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiY2RkYmI4NzAxMGRiYmY0ZmI0MzY5OGU4OTZiZmYwOTdjNzU4YTJkZDI2ZDYzOGE3NTQyMWJjMzgzNjYwN2ViMiJ9"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataVaultJournal.swift#L123-L146",
"version": "repo-lines-v1:sha256:65b2f8d89161d7e0ebbc5e959de6a7083d249228c9749cdd8f3a504a0e08bdb8:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI5MDQ0MmQyYzUxNDNlNjFlYWU5YmQwZWViMDU4N2VjNTA1ZmUyNjVjYmU4MDk4ZDgzOTc0ZWVjY2NkODk1NTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataVaultJournal.swift#L34-L65",
"version": "repo-lines-v1:sha256:e81dc7bac3b134b668502cd364bba460b861a78c050c217dd36f6f26b2616fb9:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVhNDI2YTcwYmQzZjVhZDc1ZTRhNGVlM2NiZDMyZGFkYmZiMjNhMWI5MGVhZTVlNzUxZTk5NWIyN2RjNDFhZjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc3MmY5Njk1Yzc0NjdjNzQ3NzNjOWNlN2ZjNDI5YzVkMGQwZTQ4N2YzYzUxZDE1ZDY2NjhhM2QyNDA3MmJiOTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ4MzgwYzMxY2E3OThlNWY2ZDVkN2Q1NDdkZThlNjE1ZGEyOGI1ZGQ5MWQwMTFmYmZkMGRmZDkzMWJhMjczNzgifQ"
}
]
},
{
"id": "claim_d01ba08797b0468cae57cc6ce786cb3c",
"statement": "AI secrets are not placed in Settings CloudKit payloads: Settings synchronizes references, marks accepted remote references as iCloud-backed, and authorizes new iCloud secret migration only after a successful fetch by the current Settings engine and while both master and Settings switches remain enabled.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L243-L260",
"version": "repo-lines-v1:sha256:89d835274a56d25254558ed08cdcbb82f53987327a32fc4f67b20bedb938cfa4:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0Njg3YWNhMWQ1N2EwYzBjODcyNDkyZjlmMmI3ZWRhNzJmOTQ5YTUzODEyZTExY2EyMDE4YTM2ZWQ0ODE5MTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2YTQwMTNhMTc2ZWY2ZWRmN2M3ZDE4Zjg0MGRiNzk0YjU1MDZjZDNmZWIwOWM1OTE3MzAxYjNmOTEwYWRlNDgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk1ZWNjNmU1MjhmNjk3ZTExM2Y4YzM4YzRkZTg5OGNmMTM0NTkzY2M2NTExNGFkNmEzOGRmZmJlNzgxN2NiNTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjExMjhjMDM5ZjQ4NmI2NGY2Y2MxZDNhNTVhNzNkMjI0MWNkYjYxMDU1OWM0ZGIyZmYyOGJlZmIxMjU2NTI0YmIifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L134-L149",
"version": "repo-lines-v1:sha256:91f832746ee1f2396e166f5a68a52938c18c70ab141ae8407671800550c08b1b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNkYTQ2NDE4NjQwOGQ0NDA0ZTZjM2E5Y2I1MDMwODQ1N2VmNzJiYTc1MWFiYzdjNGNkZGFjOTc1OTgxZDhjMzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc3MmY5Njk1Yzc0NjdjNzQ3NzNjOWNlN2ZjNDI5YzVkMGQwZTQ4N2YzYzUxZDE1ZDY2NjhhM2QyNDA3MmJiOTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NjU3OGYzZWQ4NDJiMDUyOWZmMTIzOGFjNjJhOGI0ZjMxYjViM2M5YTBmZGNmODk3ZjI5OWJiOGIzOTVkYTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwNWQ1YjczYTdmZWFiMWRjN2U0MDhjYThlOWU5M2YxYjdjM2NiMGVhZWUwN2M2NGJjZWEyZWExMjc5ZmJjMjQifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L92-L132",
"version": "repo-lines-v1:sha256:c2dbaa6d4506cda0f102f3c9aab68193d5da1fa3f0dff479208cf8a184ea6e20:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNlZDgzYzQyNGExMTczYmI0NWVlOTY0ZDQ3NzU5NjdhODQwNzVmMWI0ZjdkM2VkZmZiY2I5ZDM0N2JhZGM5NzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4MDlhMGM5MjFiNGJiYjEzMWFhMjQwOWI5MTkyOTAwYjM4NmY1NjE2NGIxNjkzNGQ5MmQ0YzI4ZjVmNzc5MmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBmMjRjMmJjNGVmMjcxY2QyNjgxMTIxZGQ4OGU4OGNhZDNjMjlhNDFiNGNhZTViMmIxZGNjNTljN2ZlNGY1Y2YifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift#L104-L110",
"version": "repo-lines-v1:sha256:19af89fdd121747ab1bc6d38c409a8d03b4413a3e7566aef200ad58c2ecbbcc3:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiY2ZjZGYwMWYxNTg1MWY3YTU2NzE4NjBkMzgxNTUyYjkwZjA3ZmNjNjZhNGM1MTZhMzIwNDAxZjZhZmMxNjE4OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZGE3ZDA5NDAxZmExNmFhMDE5NDQ0M2MzMDg5NjQ2M2U2YjU2OTk2NzcxZTRhODFjZWVkN2I1MTU5OTgyMmIwMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift#L48-L83",
"version": "repo-lines-v1:sha256:c3d04722ec812fc2b7d62fcdbfe6a36261616b1d7edf9e296dbbc88aee7a8612:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYzZlZGM3NGRjNGJhNzI4YWYxNWUyOWZlNDgxZjViZTgwOWY1ZWRhYjljZDMzMTQwMWZjZWRlMGIyOWE2OTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQyODdlYmRmMDU5M2M5ODU0NjZmOWQ4ZDgyMjc1MGU3OGU0MWRiMDYzY2FmYTA2Yjk4OTI0MTljM2E5ODkyM2QiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIxODUxNTlkNmU3YjE3MDdiMDA5NzY3Mjg1OTI2YTM2YzI5MmJkNzdhZTEyM2UyOTkwNjAzOTE1MGVkMGU2NjQifQ"
}
]
},
{
"id": "claim_763ee8bae53d453e8903018d882747cb",
"statement": "AISecretStore verifies an iCloud write before recording the iCloud location and removing the local copy, persists pending deletion before Keychain deletion, and retains the deletion marker to prevent delayed Keychain delivery from reviving a removed secret.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift#L26-L45",
"version": "repo-lines-v1:sha256:b1aeb1e1bed748d256768f6b1626f9ac8fec31f35244ae56d46368243297973c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE1NGNlZTY0YThkOWMxZTI3ZGU0ZTAyZjk1NzAwZjliMzAwMDllYTFlOWQ5ZjQ5ZDVhOTkxMThmYWZlODBjODciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhYzViOWJjNDkzOTIwNjMzODhmMThmYTgwZjZiNmY1NjQwMmNhNjIxYWJmOWZiYmQ5ZmZiNTMzYjIxY2ZiMDciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNmOGQxODFiNDA3YjNjNmNlODU1YTdlZmRiYzgwNmMzZjZkNDZkMmZjOTJlZmMwNmJhNGU1NTUwYzNlZGYxNTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjczMmE0OWU4OGIyMjA3NjBjNzliNjI4Y2UwZTg0MDcyMjExODgyZGFjMTkyMDRlNWM3OGZkZGU1NGM3ZDAzYmYifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift#L85-L89",
"version": "repo-lines-v1:sha256:d59b0f92ff16da784ee720d24ee2211f70c01655f8bc1a955a2f681dda530ffd:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNmY2NGY3ODZhMTViNjNiYzY2NmJkMDcxYmJiYmE1NWUzMDE1YzRiZGM1M2JhOTZjYzA4M2RlM2E2ZDVkNmE2NyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTk3NWEzMzUwYjgxOGZjMTc2YmJjZWFlODAwODRkNTEzMGMyNjI5NjlhMzQxNDIyMzZmMWE0NTAwNzk4Yzk3YSJ9"
}
]
},
{
"id": "claim_b5a9a81603ab425aa1d9436175848295",
"statement": "Settings uses compatibility record types for SSH and SFTP preferences in its existing zone, allowing older clients that filter record types to ignore newer preferences before decoding.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L11-L20",
"version": "repo-lines-v1:sha256:ba64e9fd7d03ea70c7260531f00825cc1976772f0275d81176a20f25e63564fb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYwNjg0Y2I2MGIyOWVkNTViY2FkMWU5MmNlMmExNjhiYjU3NmY5NTZiNjQyZGYwMDUyYjFiNmVjYmE2ZmIwZjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYzZmYyMmRiNDEwNzIxNDkwYzZmOTBiMWE1YmYwMzhlZGE2NmM4NTkzYmVmMTE1NjIyNjVjMzhhMTc4ZjQ5MDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjMDAzZmE4NDc1OGM2MmQ5OWQzODFmYzE2YjdlZWZkODcwMjg3ZWI4YjU1MTExNGM2NzYwNmU2MDlkNzgyNzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQzZGMzNDIxOWUwMzNmNGNjOWFhYjJlYzExODAyODFmNDEyNzE2N2Y1ZDAwMmU0NGE4MGExNDFiZTRiODcwMjgifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L336-L365",
"version": "repo-lines-v1:sha256:e314c414b55b9bc4bb5e4896cfbf869ee20e4644f31b5d436e3193e1245f9fac:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJlYTRjZDRlZGI0MDJmNDVmNThmMGJkY2UyZWI0MzVkNTgxOTZiZmYyNjU4MjdlNmE3OWE3YzZjOTZkYmI2Y2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3ZDA4ZWY2ODk0ODdmOWQxZWYzOWEyNDhjNWViNWY4NmEzMDUwYTZkY2Q2NzgyMDYwZDZmZDJkNTA4MWY1OWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBlMTk0NzllZWYyMjk1MzI3ZjQ1ODc4OGY4OTUwYjg1MGE0NTM2ZjE1NWE1MmUxYmZmYjk3MTIxZWU0MTUzNWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE3ZDdhNTk3NDA1NDc4NDg3NzUzOWZlYjQ3N2FiZDZhMTM0YjVmMmQ2YzYxYTQzMGE0MTMwMTZiMjE5YWRkNGQifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,308 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:1d92d75b2ce5b6df028b5364c4bf11bf06f448af163019a2c9cca92cc6e7ebe3",
"claims": [
{
"id": "claim_5ca6241ea6cc4ebbb915ccbe304f8430",
"statement": "SFTP transfer responsibilities are separated so `SFTPTransferCoordinator` owns queued transfer runtime and admission, `SFTPTransferContext` owns a generation-scoped primary connection and lease topology, while `SFTPClient` is a connect/disconnect facade and `SFTPChannel` performs the file operations.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L120-L160",
"version": "repo-lines-v1:sha256:90b011ae02e3bee10bcf09a48d4f9819fcca02e9e11cbcf34e581456a40567ff:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFjMWVlZmFhYWRhNDYyNWFiN2IyZTQwNzk5YWQ2ZDRiY2YyZGE2OThhZjJkNjgwMTg2MjBhNTlmZmU1MDFmMGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBjNzhlZGQ4OTljZjYzZTBiZTcyNjJmMzk3MjYxZTlkNjkyYjFiYWJmNzVmNjcwN2ZmZTE4YTMzOGE2MDhiZWYifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPClient.swift#L293-L387",
"version": "repo-lines-v1:sha256:d13284698bb7d87512d5e22228faad7cb963f3a537c313e3f5b404680c3f4ae1:eyJzZWxlY3RlZExpbmVDb3VudCI6OTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRhMjJkYmQyNGZjYzQ5MmI1NTU2YmIyN2M0NThhNTdhMzc2YjFkYjNmYjgxMGRmZThlZjE1YzEzZjMyY2YzNjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYzNjgwZjc0ZmIwMThlNmYzN2ZlOTdmMzhkOTUzOTY0ZjhhZTBkNzdkNDAxYzQyNDg0NzNmYzhmMmRkZjViZGQifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L12-L53",
"version": "repo-lines-v1:sha256:5d74ca0ee69c46d8e1bab2567619d54fc9a4b65da1dc6ddc4532cc8b83262a2b:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxYmE0NzE5YzgwYjZmZTkxMWIwOTFhN2MwNTEyNGI2NGVlZWNlOTY0ZTA5YzA1OGVmOGY5ODA1ZGFjYTU0NmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMyODc0OTcxOGI0MGQ4ZDY3NzliYThjNzg1MzFiYmZhNzEzYWM4MjE4YzA1NjJmOTUzZTZiZDUwYmM0YmRlMTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFhZTFhOWUzMzQyMjE5YzZiMWE3MGQ4MzAyNTllZDZmNjg0NTdlMDQ4OTg1Y2FmMDQ2NWI0MjYzNzVlYmU5NmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhhMjg1N2RjODAzMzBjNGMwOWNlZGI2ODU2OGE1OTVhNmU5ZmQxMWQ3YTg2ZTMyYmJlODViMDdkZjI5Y2IzYWYifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L77-L147",
"version": "repo-lines-v1:sha256:9fde17f24c66b4dc9e257e67453dd6559a5eac2de6793dd3ce326c83deb05821:eyJzZWxlY3RlZExpbmVDb3VudCI6NzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY5NmFiZTAwOGM2OTQ0YjBhMzJiZTcyZDM2Y2ZmMjNkMDc0MmE0MDEwMDIzY2I4NmFhNjYwNjAxMGFmMWM3NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhMGVkMjg2YjQ5ZDIxZWU3MWU4MTkxZTMwZWFlZGNjZmZjMjY1MjYyNDYyNzJhMTA1OGViYTI1ZTdlMWFmZGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE0N2RiZjRlZWMyNjY3YjEzNjllNTU1ZWNkZGNiNGFjYmJjMzY2Mjk3NzQyNTQ4ZTY1ODhhYThlNGIxMmJmODEifQ"
}
]
},
{
"id": "claim_626f073718804e6da44511f8f48bf716",
"statement": "Transfer checkpoints are process-local: `SFTPResumeState` tracks a temporary path, source identity, acknowledged offset and SHA-256 state, and the coordinator pauses recoverable connection failures rather than silently replaying them.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPResumeState.swift#L5-L75",
"version": "repo-lines-v1:sha256:330d9a23fc441766a58c6b9c951b173599df53da6a71cf6caf19fe57b7d571ff:eyJzZWxlY3RlZExpbmVDb3VudCI6NzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3MzllZGMxNmVmZDA2YWM5ZTRlZTU4ZDE4Y2UzNTJkOWNlYzBjM2JhM2ZlMmIxMmQ0ODgxMDM1YzU0MjlhOWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImEzZjk3NzJhODNhNmUxYTRmZjI1ZTQ3OWJjZDhlZThhNWNlZTYyZTIxOWQ2NmZiYjYxNTNjMjBiZmRkZDdmMzkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM0NmY4Y2RkMDA0NDk4MWZkNzI0N2EwYzg5MzE2ODM0ZDNlZGFjOWU1MTAwNThkNGMwNGNhM2RkODczYzFhYTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5NGMzNzI1ODJkNzM1MDg4YzFiMGI2MTEyY2EwNWIwNjY2ZTBjODc4YjEwNjRmMjNmMjJkZGZiZWUxYzg4OTIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L583-L622",
"version": "repo-lines-v1:sha256:83654c21350e2db1abfc5ac3b89a13506c63b446d857a1a41271467584e5a14b:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNkNzQ3Mzk4NzZjNjY5ZjYzMzM1YjlkYTk0MGE4NWVlOTc3YTQ3MTQ0NGI3ZGI0NmU4MWVkMWEzYTc3N2IwYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE4Mzk3NDg3MDYxMzY2ZWRlNTFhNjA0YjAwZjA0NzI4ZjZkYzg1M2VkNDZmYjQ0NGE5NjVjOWMwYjE0OTIxMTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU5YjYyNmIzMmQ2Y2MxMDAxODYxNThmODY3MWNmYzMwZDJiNWQ3NmIzOTkyMDk4ZGQ0Nzg0YTliZjJiMzA2MDQifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L273-L276",
"version": "repo-lines-v1:sha256:bc77a4beae1620345caed02ff365f7609b13818f1d30eeca413172d0c0162042:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjY1MDZhNmU1OWIxNzc2NTVmOWQ4YjU3MWExY2VlOGM5MDgzMTA3YjYxZjJjYWY5ZmM2NzZmMzg2MTA5MDE3MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZDA2NTQ5ODFjODYxMDljZDExZDQ0ZmM3ZTg1YmIyYjUxMDBhZWUyYTc2ZTJiZDFmYjlhZjI5NWY4NmNlZWU0ZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTgxMTNjNWY3YmRlN2E5ZWJiNmViMDM2ZDcwYWE3YjE2Y2Y0MTc3Yzg4N2UxODBhNWNiZTFlODliNmM3YjI1NCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOTc2MDg5YjE4ZWYyYjA2ZGM5ZTVmZDBhOWM4YTEzNjNhZjk1NWEwOTMxNjg2YWE3N2Y2NTlmNWNmNmYzNGI5MyJ9"
}
]
},
{
"id": "claim_818a4569bcc04a6d8723bc0c33eea5e7",
"statement": "Each transfer uses either a saved additional-connection snapshot, a managed transfer context, or an externally borrowed channel; saved connections are opened and disconnected per lease while a borrowed connection has no coordinator disconnect action.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L12-L24",
"version": "repo-lines-v1:sha256:8d0ec6eae0d8d140a55f76bd72194ef2d5b7ab64038f4850b45446fb8893e3f1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY1NDIzNjhjNzY5Y2UzYTE2NDhjMzJlZjg5NWEzYzlkZmJiZTJlYThmYWIxNzdhOThjZTE3NzM5NGIzNDYxNzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0OTdmOTNjNGYzZjQxMjAzYzdkMzliMmU4NjNhYmVmYTJlOWQ0YTVmNDE2ZDM5ZTgyYzk4NDBlNTAxYzZiYTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFhY2MwZDYyYTljNDhjMDAxNmE1OTg4YmYzYWUzNTMyNjQ4OTIzZDI5NTQ0Y2Q1ZWYyMTI4YTJiZTliMmUwZmEifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L721-L754",
"version": "repo-lines-v1:sha256:38dcea035a2368e5cccf70caa2c7d5458fbc58b71a8ee0e3dd3ee8a939a53be6:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg5NGNlMTJjYTMyYzRjOGQ4NTVjOWUxOTRhZTIyODM2MDQwMWRlNjE2MDg1NzU3YzhkZjM1ZjBmOTVmZDZjMGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlmMDBiZDgzOTVjOWRhM2Q3Y2FiZTBhNjE1YzIxNTVlYTEzNDAzNTc4MDZhMGQ0OGQyZDRjZGYxZjc2MmRmZjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAxMWFhZDQ2NWQ3ZjhmMzA2YzAyMzg0MDM5NTJiNGM5NTFmNGNiMDY5NTQ0NmYwMmU0YzI0MjI2ZGY1ZmNhMDMifQ"
}
]
},
{
"id": "claim_bc86e5644e2a40afb3891299c5ff994a",
"statement": "Local uploads and remote copies preflight destination directories and targets before enqueueing; only after a conflict policy is selected do they resolve directory and target conflicts and enqueue resulting jobs.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPLocalUploadPlanner.swift#L88-L161",
"version": "repo-lines-v1:sha256:6adcc1244bd44adeef3eddddb95214967693e1d49b17d46d821a8bde8642424b:eyJzZWxlY3RlZExpbmVDb3VudCI6NzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5OWQ0ZmJlNDdmYTFkZjE5ZTUyMjA4ZTIxNDNiMDA1YTY1Y2MyNWNkMTVlOGY2ZDY3Yzg2YmY1NTlhYTk4MzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRhOWY4NmQyOGU3ODRmOWZkMzFmYjcyZDE1ZjYwY2JjZWFhZmRkNjY5Y2JkNWI2ZGE3ODg4YTAyMzMyMWViYjkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgwNGY4OWZjMGVjOThjOTgyNDE4M2U3OTVkM2VkZDE5ZTkzMGY3YmM0NzFmOTAxMmFhM2Q1MDNiZTJmODk3NGIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteConflictResolver.swift#L29-L108",
"version": "repo-lines-v1:sha256:c7f1e553652d731596a3452928db1d5140bf6bd904f629ae94351fcb08fb6798:eyJzZWxlY3RlZExpbmVDb3VudCI6ODAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ2NjA3MTkzNDhiOGEzNWE4MjczZjBiODkzYzJmOGVjM2MxZDIwYjdhZWFkZmEyOTRjMjM2OGQzYjU4NWY0YTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIwMjczZjM3ZjZkMzM4ZjAzZDdjYmI4MjQyMjZjODc1YzY5ZjU5MjdhMTE4NjA0YzcxNmI5MjMxM2NjNjVkMmIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteTransferPlanner.swift#L247-L314",
"version": "repo-lines-v1:sha256:3122a8a4964f190c461651d9b24b0de2b078ca4e8193b8a6955d29e51f799a75:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5OWQ0ZmJlNDdmYTFkZjE5ZTUyMjA4ZTIxNDNiMDA1YTY1Y2MyNWNkMTVlOGY2ZDY3Yzg2YmY1NTlhYTk4MzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdkMTEyYmNjZWUyYzNkNDhkNzlkMjY2OWQ3OTk5YmEyNzQ1MWVmZjFhMTcwMTJhOTA0MGQzYWQwOTU2MjViYjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgwNGY4OWZjMGVjOThjOTgyNDE4M2U3OTVkM2VkZDE5ZTkzMGY3YmM0NzFmOTAxMmFhM2Q1MDNiZTJmODk3NGIifQ"
}
]
},
{
"id": "claim_935270dc00054cc7865662ce4419a869",
"statement": "Conflict policies can skip an item or subtree, replace a conflicting target, or select a next available Keep Both name and map descendants; replacement of a directory validates remote child names/paths and deletes children before their parent.",
"evidence": [
{
"resource": "repo://FrameworkTests/SFTPRemoteConflictResolverTests.swift#L32-L120",
"version": "repo-lines-v1:sha256:19367f227f10082a0bf87e63f65e21ecb486bfcaaa1b8a6c12c94621fffb9a1b:eyJzZWxlY3RlZExpbmVDb3VudCI6ODksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVhMjRmZTRkODUwYWI0NjgxZTlhM2JmOGVlN2MzNTU0YTU4NGE0MGFhMGE4ODcxMzUwY2ExNjViNDg2OGY2YjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4MWFhNGU1MWQ5NTZiYjY2MGQ2YjI3NTAwOTg3MjFmMGNjM2Q1NzU2NWZkN2FlZTE1NDBkY2RmNDdiMGQzMzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJiOWViMDZiY2ZhZWEyOGI1ODAyYmYxMzFlYzUxNzQxOGVjYzVjZWZmMTBkYWNmZTZiOWQ3YjdjMWMxNzY1ZGQifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteConflictResolver.swift#L64-L139",
"version": "repo-lines-v1:sha256:28d778016aa95e6f6dab143baf585a968461962189e7c716646365dc757ffb59:eyJzZWxlY3RlZExpbmVDb3VudCI6NzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0MzcyMWIwYjQwMDJjMDA2MTk2ZmRlNmIyYzhiNGY4ZWMxNmRmYWU1NDUyZjA0NzQ3NzMxNTM4ZGJkOWYxNzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhhMTU4NzU1MGRjNjY4YWJhODM4ZTM1NWM1NjUwZTc0ZDFmM2I2ZDQxYmE4MThmN2IyN2UyMzQ1ZTJhMWMzNjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_1d12ace041f7420595fa047e57edf098",
"statement": "Same-host remote-copy planning rejects copying an item to itself or a directory into its own subtree, and copy execution streams directly between SFTP endpoints using shared-transport I/O or an in-process socket relay instead of local staging.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L575-L705",
"version": "repo-lines-v1:sha256:e1fcddd68a2edd040d223eac7b05e4eb02a4c4cb797cbe9239588b74f3bc845c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMxLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI2ZWRlZjM2OGUzMDY2MGY5N2M2ZjBiODYwNTM0MWJiYWMyNWZjZWRhMzkyYWUyYWViNzc1YjVkMjcxNDc3MGZiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI3YzNkMTdkM2Q4Mzc3ZTAwNzRjYTViNmQwYjRhMTRjZGMxNDk5NzUyYjY3NWVhM2IxMzk1MTc0YzVmOGMzYjBmIn0"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteTransferPlanner.swift#L221-L230",
"version": "repo-lines-v1:sha256:ed047994fbb068bb82cf3478120d1030e059961d843ea28faf53f28c05470011:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmMjMyMWVlZWE5ZWQ2MTc3ZWI5N2Y5YWQ5NDVjMjg1ODE1OGFlMjg2MmRlODMzNDVlNDQ4NzI4NjI1ZGFiMGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU2N2E4NDIwODFmNmE4MDg4ZWM4NDViNTNhMTgwYjQ3ZDM3ZDJmMDM1ZGU3ZjdiZTUyY2E4ZjZlYzY1NDNmNzIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVlMzkzNTNhM2EwYjlmY2MwODkxMjljYThkZDE0NjBhMjAyZjI0Y2I1Y2QxZTFiZGUyMTZhOThjM2NkNWFhNDEifQ"
}
]
},
{
"id": "claim_2a1daddaaa914749849e3c6af304cbdf",
"statement": "The process-wide scheduler grants logical-file permits under global and per-host limits, charges a cross-host copy once globally and once to each endpoint, rotates hosts then work sources while preserving FIFO within a source, and excludes overlapping exclusive borrowed resources.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift#L133-L166",
"version": "repo-lines-v1:sha256:ac5dc1b9b48d0a40dc164abad62d8f1e9bda60b1b93b86f32937666de5ffdbcb:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc3MTNjNjAzZWU5NjQ5OTU5OTJhMmUyZjYxY2ZkYTY5OTU2ZDM1MDU5YmU3ZDYzYjhkYjBhMDMwMmQ2OTUxMjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFiYzYwMWFhNzYyMDE0MDcxOWE4ZmI2ZDcwMzBhYjQ0ZDI4ZWM5NTIxMGY5YTNlZTY2NWJhNmI5YzA5MDVmOTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4NTExNDMwNzk3NTU2OWExNzJhZGZhNDAwMDdmOTFjNzE1NmE2MzU1MDZmZDAyNzIzM2FhMWU3MmVjZTdmNzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQzZDA3Mjc0YzRjMmFjYzlkMDg2ZDE2ZGJiOGEzYzM4OTAyZTVmZDgzNzFkNDEwNGNkYmY1N2IyZmFlZTI2ZWYifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift#L29-L59",
"version": "repo-lines-v1:sha256:e5766ed7530d7a126f5332f4983aadc634531286238a47a13c533136d8359095:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk4MzMxZDIxZmVjZDMyZTdkMTUyOTg5OTZjMDkxOGJhZDVhNGViNGMyNzE3OGJmMzRlZTA4ZmU1OTk2YWU3YTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjNDQ5NTAwMmM4MWJiMDZiMjkxYzJiZTgzMzljM2NjZWRkZjdiYzVkZWIxZmMxNjgyYzU0ZTlhMjEzNjdlNDgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJkNzEwZTdkOWVmMjI4ZGE0YzUxYTcyY2Q4NGMyOTIyMDU5NGNmZWI2ZDQwZTgyNGRiNjI4MTQ4N2Y5YzAwOTcifQ"
},
{
"resource": "repo://TFMTests/SFTPConcurrencySchedulerTests.swift#L32-L113",
"version": "repo-lines-v1:sha256:48d1b351f0acf522015965eecb894a9e957f2210826b1795916a34310cb405a3:eyJzZWxlY3RlZExpbmVDb3VudCI6ODIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEzYjgwZmU4NzVkYWJkOGI0NzcxMGYzNTlhZTZjZWJiYjU0M2UyODNiYmI3YzE1N2ZlY2FjNmEzZDk2YjIxMjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJmZmVkYzgxYmM2OTM2MTY4ZGNlODA0NGEzMmQ3NDg0NDVhZjI3MjFlYTcxYWFjOTkwNTc3NzE3NDU3N2I5YTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3MmQ1MzlmYTY4MmY3YjM3OGQ4YmUwMDAwOTFlODNhNTc2OTRiMmIyMmNkNWI5MzI5ZGQ1NWM4OWFjZWRiZWMifQ"
}
]
},
{
"id": "claim_700c385bcb054747a3caa61e80e35682",
"statement": "SFTP preferences default to 30 global and 10 per-host transfers, normalize limits to supported ranges, and in Smart mode select channels for unknown sizes and files through 64,000,000 bytes but prefer connections above that threshold.",
"evidence": [
{
"resource": "repo://Frameworks/TermindDomain/Transfers/SFTPPreferences.swift#L3-L46",
"version": "repo-lines-v1:sha256:fb21f79fbec67a7addfb826ee8cb8cb2c60fe1b9db9b9c64446c343b13460ced:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZkYmFjZDY2ZTAwMmIyMjBjZmJmODIwNjAyMGI4YmY3NDhiMjU2MTM3Mjk1YTQxYjY0NDg1ZmM4N2Q1NjhkZDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg1NjlhODFjNDA0OGI5NGZlYjQ5OTE5ZDA4ZDkwNDU1NTBjNzNjZTMwMGE1NjQ5Y2I0NDMyZWU0NmYyZmU1NzUifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift#L169-L182",
"version": "repo-lines-v1:sha256:6ede6cd5e9b2351dbd9fd55c595e761d34c268db3f909d18087b64fa1ecf06d3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVkNjQzODE2N2U1MmE1YjVlOTM5OTdiNzcxZDBhMzcxOTc4ZjdmYzU4M2FiMjE4MDZjNzlhNWUwYTJjZTIwYTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4YWNlOWI3NWYyZWQ5ZTRiMDk4NTZlNGJjYjFhMDJiMzVjNzY1MzRjNzhiZjM0MjZlYjllYWQxNWM2YmUyYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFmNjU1MDc5MjZlNjQ1MWUzZmYzNWIyNWUzNTM0MmU5N2ZiY2YzYTI2YTgwNzdmNzFjMTJkYmQ1YjM4OTYwMzMifQ"
},
{
"resource": "repo://TFMTests/SFTPConcurrencySchedulerTests.swift#L7-L30",
"version": "repo-lines-v1:sha256:17ec895194d1226bd9693c140cb453d4f30add3eb193a93ae0c527e6da2cb426:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDhjODFjZmIyYTA0ODQ3MTVmZGVhY2E4NTI1NDA1NjVkNDIzMTU5YWVmMWM4NGM0MDE2YmZjZWMyMjcyODIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkMTZmOTdkOTZhZjllZjZjYjY3NGUyNzIxZTU3MmQ2YTFlNWRkOTY4MDJmOGIwZmIxM2RhZGVkNGI3NjYwNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjZWM0NGYyMzYxNDlmOTRhMjViZjU1ODMyODM3YWMzOTIxMGIyYjc4ZGFiYTNhYzM2NTMzMzNjMjE3YTc1YWYifQ"
}
]
},
{
"id": "claim_3036a5fd4a754ee3a99e2517729f6d03",
"statement": "A transfer context keeps browser control channels independent where possible: channel-only work uses sibling channels or serializes the primary, connection-preferred work silently probes an additional connection and falls back to channels on non-cancellation failure, while cancelled probes do not cache the fallback capability.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L212-L233",
"version": "repo-lines-v1:sha256:1bb24096c7f97226882d922be0e39f04a07e285d60f97213b22e2de68750b12f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ0MGY2MjA1OGZiNTRiY2Q2NzkyYWZhMWJhMWQyNDYyOTI4NTA3ZmQ1NzczZjljYzQzOTM4MzBmOTY4NzNjNWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVjYjQ3ZGIxYzczMmI0YTcxYTBhYzE4NmE0ZDMzNTQ1ZGM4NTAyMjE3MTgzMDhiNDY3MTQwM2ZiYTEyMzhmZmIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L99-L188",
"version": "repo-lines-v1:sha256:66bc442c33d6cd347e25766a912d6e5aa904ff35fbd79cb65d9b0da8bdef9739:eyJzZWxlY3RlZExpbmVDb3VudCI6OTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM1NDUwN2Y4NGExN2EwZDY2Zjc1NzU0ZGJmZmEyZjJhODNmZmYwODg4NWUyMmEyNDI5ZmRlNmQzNTljNzVmMjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzYmRlNWRjNDUwMWI5ZTk1NWQxN2ZjZThlMmZkMGEyYTIwNzkwMTQwYjNhYWVjNTQwYTJhNmYyMGZhY2M1MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNlMjMzODU2ZGRmZDZjYmUwMzUyNmJmZTEwMjcwYWYwMDc5MGZjZTQ4YTgwODQ0MzdmN2MwZGE4YzJhMTJmODcifQ"
},
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L232-L263",
"version": "repo-lines-v1:sha256:c7a31fa1e5bc20eb1412ee29eb2ea76a614b5cbe4a7da26c9d33540f94e5c417:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxOWMzYzgyNTlhZGFjZTI1Y2ZmOWE3ZGNiOTFhZTZiMjRlZjgyMjRmMmE4ZmFlOTQ5MmQwZmQ3ZDliYjY2ZjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc3ODgxYTZiYWJjOTMwOGM3NWFkNGNiNTc5ZWU4OGE2NjY0YWM1YzMwYjlmMTMyYTdlZWYzYmZmMDNlZjY2NDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRmOTcyNDhkMDRlMGQ2Y2MxZjRlYTJjNGFkMmJhMDZjNmEwZDAwNmZjODY0NmJmODUxZGZjZmRmOGE1MjRlYTgifQ"
}
]
},
{
"id": "claim_8698b1a8c6e848e08bb2b77442bb0ec5",
"statement": "Terminal upload resolution donates a successful independent preflight connection, falls back to the PTY SFTP channel only for a non-cancellation preflight failure, and does not fall back after cancellation or retirement.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L4-L16",
"version": "repo-lines-v1:sha256:81bf790759e09ee43c6da3cee80d3c93bcef669682955c4706c49d869e59c70e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjliOTRiMTE2Zjg4NmViMmNkMTY5OGY1MWM0NjkzZThmNTFiZjg5OWUzZjcyZGMyMTgxNTU2MWNmZmFkMDliZGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM0NmY4Y2RkMDA0NDk4MWZkNzI0N2EwYzg5MzE2ODM0ZDNlZGFjOWU1MTAwNThkNGMwNGNhM2RkODczYzFhYTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNjZmE0YWVlNTEyNjcyMGE1ZDhkY2RmZWIyMTk0MWE0OTk1NmUyMjg4NjQ2ODAyYTU4ODVkZDU4NGI2OWFmOWUifQ"
},
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L23-L61",
"version": "repo-lines-v1:sha256:36233b0246228b44f2b7a0e7fea9d6a72ba6cbe7d1a1c7aa190cedc5b9fc96d4:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFkNzZlMDQxNGIzOTY0OWFhZmNlOThkZTYxYTFjYWI2ODFiNDMwMzQ2NGMyNTljNjdjZjgwYzdjOTJiYmE2ZTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc5NWYxM2FlMjQ0MmVhMGZjOTUyNzkzMDJiZGVlYzg5YThjNTgwYzM1NmMwNjExNzQ3NThjZDJmNmFjZDY1N2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxMThhN2Q3NjM4NDU5Mzg3N2E0ZGEwODM2N2FjYzIwZWI1OThkNmQ5ZDAzYTVkMzc4ZDY0NGNiMzNkNTYyY2YifQ"
}
]
},
{
"id": "claim_e24441ce11d14529bbb92b47e251b984",
"statement": "Uploads and downloads use temporary destinations and source/prefix validation for explicit resume: uploads write a remote temporary then rename after checks, downloads commit a local temporary only after remote identity validation, and prefix SHA-256 mismatches fail resume.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L354-L404",
"version": "repo-lines-v1:sha256:7d7494364cf16f9948e6458389a464e1b113eb7b821371d77e362b5d7446e822:eyJzZWxlY3RlZExpbmVDb3VudCI6NTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY1ZDNlOTQ3NzhkZDcwMzNhNTMyYTViM2UyNTAzYTA3NDg5NzViY2NjYzEyZDViZmU5NTY2NDcwMWM2OGVjMDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNmODNkZTQzMDI2Mzg1NDYxOWU0NWNlZjc2MGVmMWMxMzIzZGNlODYxYWE0MWI0NTQzOTA0MzIyMmI5NWE4ZmQifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L416-L483",
"version": "repo-lines-v1:sha256:5bd87d47c6cffdaa2987867bd0720a0c5504e1fbfebcb857165609de619f4101:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVlNDZhNmIwOTUyMmM5YzM1YWI2YzVmMTliMTJhODE5NTM1OTYxNDE5MWFjNGQwMjY0ZGQ1YmJiNGE3NGIwOGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMxMTZlYTM2ODRlMDU5NWMyYzhkODkzODExZjQ5YTY4ZTQwYTUwZjY5MTgzODNiNjQyNWZiNWYyNWUxOGQ4YWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhjMTE3MGNlMjFlMjI2YThlY2NmMzMyM2Y1YjllNTllZWYzMjFkMDVmODM4ZTVkMjY5ZmI5YjAwOWFhZjBlZGIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L807-L909",
"version": "repo-lines-v1:sha256:4abfadd58520aca9064a5e1c82b30410463154cfa9d563a03b0b28eb93f956b5:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAzLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0M2U4ODJjZWYwOGQ3N2M1MGI3MTg3YTljMjE4N2U0NzY5ODU0ZWI2MWQ2MGVmODA2NzU0YjU2MDYyYzcxYzZiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJkNjIxNzcyY2VmNWRmYWU3YjZmM2NkNzMwYTc4MDhjNjI1Mzc2YmE5ZTYzNDUzMDZlNmNjMGRiYjA1ZTQ3YjYyIn0"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L985-L1031",
"version": "repo-lines-v1:sha256:7def63e7fd3865752a31c1ae6b89e7e69e06aa433741223385ac1655a97366f4:eyJzZWxlY3RlZExpbmVDb3VudCI6NDcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZjODhjOGZhMjNhM2IyNmM3NzM4NDQ4MjA1NWYxZWZhMjZjMTMxMDVmYTg5ODkxZWRmMWRlYWQzMzBjMjg0OTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc4YzhiZjNiYTZkZGVlNmYwZWE5ZWU0ZDc5ODgxMzIzNGFjY2VlNjExZjc5OWNhYTU4Zjc1NzgxYmM5NjBhODkifQ"
}
]
},
{
"id": "claim_324670ec88b9484ea91967b111e9824f",
"statement": "Cancel or terminal failure attempts cleanup of the partial temporary file and surfaces cleanup failure with the partial path, whereas a paused transfer retains its checkpoint and partial destination.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPResumeState.swift#L62-L68",
"version": "repo-lines-v1:sha256:8303a901336ebc76ffbaa2775eb10d0d77d93b001b1a87f2991336ad7c0e49ec:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMGJlMTBlZTcwNmU0YTgxYWMyZjIxZjEwMWNjYTczYjM4MTdmZGVmZDUxZmE0NmZhYWM0MjZkNGRjN2MxN2E1OCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmYzZTM3ZjY3OWNkNjY3MDJiNzFmM2Y5OGQ3YjJiNjJlMDAwYTMzYWRiNDg5MTU0N2M2NmE5MmQ0MTI0YjE3OSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTkzMDI3MjVlYWQwNTQwMmU3MDEwMjRmMGMwY2YwZTU0YWY1MzA3OTBmMDVlMmZiMDEyZTUwNjBlYzg2YmQ3NCJ9"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L415-L440",
"version": "repo-lines-v1:sha256:d1194bac20219edfbf617bd4c2615e62c73d6437f669dd4258ef044e22bf8adf:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZlNTNjNzVjNWM1NGUzNmNiNmUyMGUyYzhkYzkyZjhjNmM5NzhiM2ZiOWRjZjQ0ZjllMjBkZjY2MDlhYWYyMjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMwNmM3ZDc1YWZmZTJhMzQ5MDM0MzlkYjZiMTNkOGI4ZDRkNzNhYWMyMjBkZjdkYjEyOThmZGZmNDUyYTUwMjUifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L583-L612",
"version": "repo-lines-v1:sha256:20f2dabd05c5eb8d10427699b3cd64bc17f196e781b97714fe504f077c484de9:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNkNzQ3Mzk4NzZjNjY5ZjYzMzM1YjlkYTk0MGE4NWVlOTc3YTQ3MTQ0NGI3ZGI0NmU4MWVkMWEzYTc3N2IwYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE4Mzk3NDg3MDYxMzY2ZWRlNTFhNjA0YjAwZjA0NzI4ZjZkYzg1M2VkNDZmYjQ0NGE5NjVjOWMwYjE0OTIxMTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ2Mzc4Y2MyZjU5MmEwZDA0ZDQ4NzdjMTVkNmFlOWM5NWQ2YjUwOGY2Mzc2MzUyNDJmNjFiMDEyM2FhMTRmOTQifQ"
}
]
},
{
"id": "claim_8e8c3854dcf54b8b9ac7dff62c98654f",
"statement": "Closing a pane releases only its transfer-context ownership: queued or active transfers retain the primary connection until references and slots drain; pausing a detached transfer permits closing that unused primary and explicit resume reacquires silently.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L266-L272",
"version": "repo-lines-v1:sha256:83641429cf561bea741854d35b409eee62288b4d33bb0daa419add169f40555b:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzI5ZGY4NjM2NjEwZWE3NTQ0MDhkOTMyYmNlM2ZjOWY1YTEwNGJmZDRjOTQ4YjRjZTk2YjNmZTJkMzA0YTI0NiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMDUxZjYwM2ViMDM1M2U0MGUxMjg4OWQ2MTk1Mzc2OWFlODQwYjc3ZDFmYTUxZGY3YzNiYWZlNmFmZjIzY2NhYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNmM0ZjYxZDRhYTM3OTExNDhhNTI0ZmY3MDZhYTlhODYyNDAwNmQ0Y2ExMjNlYzc1ZThiNDM5NGViZmRiN2E5ZSJ9"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L64-L97",
"version": "repo-lines-v1:sha256:4079f40db8b76586216a89ad208f08b158862900934c18f558b6547325807aef:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMyYjcyNTVhOWE4ZDA5ZDUyNDU5OWFjZDY5NjhkMThmNjZiNmUwMTAxYzk5MDU3MGU1MzlkOWIwOTkwNmI5ZDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0OGNiM2Y1NzQ0MjU2YTYzYjRhYzFiY2M0MTUyNzYyYmI5NGE0N2JkOTI1ZjBjZTJlZjAyYzVhYzBkNzY3ZTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE5NTc0YzEyODZmY2ZjNDZlODQ0NTdiNWUxNTc2NzliNDQyNDhiZGYyNWIzYTg5ODNjMjhhM2QyNzY4NGRmZTIifQ"
},
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L280-L298",
"version": "repo-lines-v1:sha256:1aa1aa82116bf71195ff88abfa3c2b9daa1a85bfbed0f5951bf05eb7de2fc39a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0YmVjOWQyMDIzZDcwZmI0NDNkMGJmYTdjOTAyMGMxNzBmZGFiY2IxMDA2N2EzMzI1OWU0ZWEyYmI4NTgyYTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc3ODgxYTZiYWJjOTMwOGM3NWFkNGNiNTc5ZWU4OGE2NjY0YWM1YzMwYjlmMTMyYTdlZWYzYmZmMDNlZjY2NDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzODcyN2UzZmYxMmExMGJmNDZlMjM5MGU5MWUxZGJhZDQxYWI0MzQ5NjA1NTE5NDNkYTRmMmY3ZGFlZjkzMmEifQ"
},
{
"resource": "repo://TFMTests/SFTPTransferContextTests.swift#L63-L108",
"version": "repo-lines-v1:sha256:eb48acd860adeeb8cb2e97326c168e6da60022567353533f5e35b8b7187639e2:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJkOWEyYzI1OTVkYzA1NzU3YWVkMjg4YjdmYmJjZjQzMzY1YjY5YTlkNzUxYjUzOWU2NmM4MDlkMTc3MWQ3NjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdiNGI3MTk3ZGYzZTE5NWZlNmIxOGI2YzhkM2Q4ZGNiZGExMDY2ZDUzZDZkY2NmZDFjMGFlM2I2MjIwODM4M2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAwMTA2MWZhOWJlNDg0MjcyZDg1NTRkMzUzZTExMmUwODZkYmNhZDA1Y2UxMjMzMTFkNGQ1YzkyMGY3MjEwYTUifQ"
}
]
},
{
"id": "claim_1400b627041b49d2a7d26125feb80f17",
"statement": "`SFTPEditService` tracks a managed temporary copy for a regular remote file, reuses it for a compatible repeated open, records route identity without credentials, and invalidates editing when the route or supplied connection destination changes.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L16-L45",
"version": "repo-lines-v1:sha256:95196d110d5262abb186fa1e22be1a445e652879393728107f36cad84123c5af:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE0NWZiMzU0NjkwNzUzZmJlZGUyNTQxNWRiYTAzOWU3ZDM5NGFmMmNjYmQ0ODJkZjcyOGU1NzY2MzIzYzIzYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ4NjU5NWU4YTdmMzlkMDY4OTYzZWViMzg2YmEzMDAwZmIxMDYzOTYxODExNDg3YTBhNDRiOGIxZDA5ZDgxYWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxN2MwZGQyYjg5MWI4ODlmNzUzNjc5YjJmNTEyYzUxOTAwNDNmZmMzZTc2ZjMzODUzZWZlYWM4MDhhZDY1MzYifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L305-L325",
"version": "repo-lines-v1:sha256:78d7428d4292815e8ebb94d51de4da7b369d6fe7dc7e87af4d479b9508c22b53:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBmOTNiYWNkZTAwODU2NzU4Yjg0ZWUzODQxNTY4ZTM0MThkYmIxNjU4ZmY2MjkwMjc5OGMzYjQ5OTBlNTg0ODgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L66-L140",
"version": "repo-lines-v1:sha256:fb189f5d9bae54784ec2de8f8de9268b81c796ca038b4c06cd89150dd62bd99a:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc1Mjg2ZWJlZjBkNzVjOGYyNWMyZTkzNGIyNWYxMmE2MGJmYmI0MGNhYTk3MWEyMDgwMGRhZmQ0NmEyNjNiZDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjllMjM3YTBkYmU2MzE1NDhhMjM0ZWE3YjZiOWNkYmM5OThlODYxMjA2NjYzOTEzZGVmM2I3Mjk1MDI3ODY2YTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZmNDc0NzdhOWIwOGJiN2Q5NzA2NzZmOGI4M2JkNmZhM2Y2MzY0MjI3YTEwNGNjYzEwZjAzM2ZhNjI2MmE1OWYifQ"
}
]
},
{
"id": "claim_2d6d1bf77933486990ad9949ad3dae49",
"statement": "External edit upload is explicit and conflict-checked: the service skips an unchanged digest, requires a replacement confirmation for a changed or insufficiently versioned remote target, binds confirmation to the observed version, and queues an immutable local snapshot only after validation.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L236-L303",
"version": "repo-lines-v1:sha256:f103e619fe3cc4ed24936d41a6e081d862c9d7822f3e3c2e7e441758d30b7415:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRmOGQ2NjJjMzJhNTBjZGE2ZDlhMmRhNjQ4MmFmODU3NzNlZGI4MmQ4N2UzZWVkMGQxYWZmZDRhNjQ0MzQ0ZjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2Y2YzYjNhYzM3Y2UxNWQyOWE3NzRkMmMzOTQ2ZTM0ZmU3M2FiNWJhYWJmNGU0NDY3YTE5NDEzOWFlOTc5YWEifQ"
},
{
"resource": "repo://TFMTests/SFTPEditTests.swift#L88-L120",
"version": "repo-lines-v1:sha256:ba5ec096f4acab05c38a6f26bc2b306c72fc69c1d2b3ef6c33cf88f2062a0f42:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIyY2QxY2NlMzdiMzM4NGI2OWM2YjdmNTQ2ODNmYjg1ZGEwM2Y3YjhjOWVkODQ5YTZiNTE3NjQ0OGQ5OGNhNGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdiNjQzMjk3NDJlZjNiZWMwOGVhODkyMzIxZTRhM2Y0YmUzYzRiNTcwNGUxNGFiZWRiNzg0MGVmODk5NmM2MjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlZmNmM2Y3OTU5ZjMwODdiYWI0MTMzYTRlMDQwODUwNWI1ZTQ5YWM0ODcxYmUzMTdiOTc5ZjBmNzdlMmE1YjQifQ"
}
]
},
{
"id": "claim_1ce6df0a5cb34ddb98dfbee5ef8f3536",
"statement": "Edit uploads pass an expected remote version and permissions into the transfer; the channel validates before temporary-file creation and again before rename, preserves permissions, and the service acknowledges only the snapshot digest so later local edits remain dirty.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L836-L909",
"version": "repo-lines-v1:sha256:c04ddbb1b6e5f6cbd9a208532b34ab340c01adc7bb12075ff7b71bdfb551322b:eyJzZWxlY3RlZExpbmVDb3VudCI6NzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI2ZWEwM2U3NGJlOTdmNTEzMmI5YTdlNjFhNjZmZjAyMjA5YWRmY2ZmYzZmYmQ1ZjY2YWZiMjJhNzZlOTE2NmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ2MjE3NzJjZWY1ZGZhZTdiNmYzY2Q3MzBhNzgwOGM2MjUzNzZiYTllNjM0NTMwNmU2Y2MwZGJiMDVlNDdiNjIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L267-L295",
"version": "repo-lines-v1:sha256:4474c245e4e6b3ca8276331b828cddbbedbfd5d0b2ac17f1d96bae89038b57b7:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYzMTVhN2NlMjM2N2M4OGNlNTg1NjU4ZTVkYWQ1MWUzMmIwMGI5YjcwZTVlZmE2ZTY0ZjQwOWRlZGVlZDg3ZTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRmNjdhNWYwM2IzMDA5OTNiMjZjNjMwMTI0ZWIzZWE4ODk2YTMwNWQ5NDk3ZmQzOTg5ZGMyYTUwYjNkMWIzOWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZkZDQ3M2Q0NzJmZjlhZDM5MzViNGNlNTY3ZTVjOTc0Njg3OTkzNjU0ZGE1MTMyMmQ0ZWQxZDA4ZDM2NmFiOGEifQ"
},
{
"resource": "repo://TFMTests/SFTPEditTests.swift#L105-L120",
"version": "repo-lines-v1:sha256:f6bb9724023a6c45fc0529540d392d0e35bdd9f331f281adf48aade1ed0a8061:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdiNjUzNzJmNDI0YTA4Yzk1YWNkZDY5YzZiZDNhZmUzYTdjOTU1YWMxNjA1ZDFhNDVkMWZjZTNlYTE4NDVkNDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZlZTllMjFlMmRjNDk2MWY5Njg0ODJiNDE4OTk5NWJhN2E1ZWRiNjE3ZDg5ZjQ0OTdmNjc4ODc0MjZlNDgxNzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlZmNmM2Y3OTU5ZjMwODdiYWI0MTMzYTRlMDQwODUwNWI1ZTQ5YWM0ODcxYmUzMTdiOTc5ZjBmNzdlMmE1YjQifQ"
}
]
},
{
"id": "claim_f2cffb64376d43beb3b8b2bd35468e67",
"statement": "Discarding an external edit stops tracking without deleting its local copy; active uploads cannot be discarded, paused uploads are cancelled and cleaned first, and host invalidation blocks further uploads while retaining local changes.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L186-L234",
"version": "repo-lines-v1:sha256:f79bcae078f272498fec1bece7d52642b3a4dbc4a76496d2d335d678457e08bd:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5ZDlhNmIwZWVkYTY0YWZhNmJjZjIxNDc5YjA0ZmNhMDNmNGIzNzQ1YmVhZWY1ZmI3NWJhNjdmYTA5YWY0ZGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZhOWI0MjRmNGVlNmM4Nzk2YWQ2N2ExNTdhN2EwYWQ4OThmNTRhYWZjNGVjZWZmMjg5ODBhNGZjMzQxYmNjY2YifQ"
},
{
"resource": "repo://TFMTests/SFTPEditTests.swift#L140-L152",
"version": "repo-lines-v1:sha256:bcdf8780ea4fe3ea5b159c8b2baf68b94e90e5461c6e13701dbf0bb737c6596f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkYzFiOWFlYzllYTA4MGM1MGVjOTY0N2U3YmIxNmUzZWM5OGNkMzE4YmEzMTA2N2U0MDZhYjhiOGFiYWRiZDQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI3OGE1ZDQ4MzY4MTg3MDQzMmY2MWViODQ1YjMzMWI4MDk1YzJjMzI2YzAyMDcyZGZiZDgzN2I1ZDIyNjVmODUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJjN2NkMWNhMTU4OWVkNzVkZTI3NDM4MzY1Y2ZjOTVlMzIwZmM3NmM2NGFjZDkyZjIwNzAxMGRhZWFjOGMzMjUifQ"
},
{
"resource": "repo://TFMTests/SFTPEditTests.swift#L232-L269",
"version": "repo-lines-v1:sha256:f0b3c63aa48580eccd3314edc9803bd670393ee8ed3d7842df171bbc4e4dbd1e:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNhZGE1MTU3Nzc4ZjNjOTJhNmZjNjM0MmE1MjZlNmJjNzY3YTFkNWVlNTI2ZmRlYjM3MzlkNDJhZmI4MWJlMDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ5MTRkNmJjZWRlMWQwYWIwNjFlZGYzZWNhN2U4NmVjYzY1NzIzODhiNjc4ZDlmNmJiN2U4ZDAzNjQ4NDgwNmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5M2JlOTgzNDEyZjAwYmIwOGE5NDY5ODZkNWMwYzQ5MzY1N2YxNDg3MDZiOTRjOTk5NGJlNjhhZDkxMjhhODEifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
@@ -0,0 +1,164 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:a66e72891fdef94d2c7a41807ade26ed1ac61b901548af5b7c4fd82d60480f47",
"claims": [
{
"id": "claim_69a9de4ce918417c8a44c6c87c9f6564",
"statement": "`SSHConnectionPreparation` resolves a target plus ordered jump-hop configurations before transport opening, performs Keychain-dependent resolution in a cancellable detached task, and applies strict Known Hosts preparation or defers unknown-key approval according to the selected trust policy.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Connections/SSHConnectionPreparation.swift#L8-L111",
"version": "repo-lines-v1:sha256:e8dccb3482f88aa1739cd3284764baa20f2772b93909c49e615bfc96cb8fa042:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA0LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI2Mjk0OGRiOTNjODVkYTYzNGYwMTU3NWYxN2ZmNzkwZjlhNTMyOGM1YjcwOWI4MDUxOTY2YWMwZWIzZjAzZDg3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI1OTA5YTUzYTYxOGQwMjhlMWQzMDAwYzBhN2FiY2VlY2JlNWZiMzdmNGU1MTFlZmU0NjY0M2ZhZDZlNjY4NzJmIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI2YTU2MzA1Y2E0NzVhZDc3Yjc1ZTNhNzM1ZGU5Nzc2OGI1MDVhNjk3Zjg0MjE1M2RiY2JmNmI0M2NhNjdhMDZlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI2Y2M4NmMwMmE1YmE3YTliYmQyMzg1YjRkMTg0YzgyMTNjYzk5M2JiOTU5M2FkOGNmMDkxMzA3YjMxYjQ3ZmIxIn0"
}
]
},
{
"id": "claim_32fd02ab237543c0ba6c1b23aceed666",
"statement": "A configured proxy is attributed to its owning route host and is not a Journey endpoint: proxy connection and authentication remain on Local or the preceding SSH host, while only the next host SSH connection advances route progress.",
"evidence": [
{
"resource": "repo://FrameworkTests/SSHConnectionPreparationTests.swift#L9-L50",
"version": "repo-lines-v1:sha256:e6d5da4e37a39a15e266186e258fc146b2abe02bb95116f90026471378600cf4:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZjOTYyNjM5YzhhOWQ3NjFkOThjY2JjOWVlMDU0ZDNlMzhlMDJhODRhNjQ2NjI3MzgwYzYzYmQ3YWI1N2U3YjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFkZGFlOWU5MzFmZDdlY2JiMjgwOTliZDgwMTdlNDc0YzRlOWEyYzQ3YWIwNDNmNmE1OWQ5MDNjYzAxMjRkOTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg4NWFlOGFmNTlhNGYzMTIxNjk5N2VmNTA4NzU4NzUwNzBlZGQ2MmEzMTc1ZDJkZjc4ZDExY2QzNDMyZTNhZmQifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/Connections/SSHConnectionPreparation.swift#L190-L226",
"version": "repo-lines-v1:sha256:fe3ca236926ed04b784df0df23fdc28577affe4c5b98b748c1c316603850d949:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1NDYzNjBjMjlkNzhmNzM2NTZkNDE3NmI5ZWE1NWQ0NTcyMWJiM2I1ODg1Y2MwODhjZTdhNzU3YzhhNTFhYmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIzZTAyYjZkNTk3NTA1YTQyOGFkNDUyMTBlNDRiZTA1N2U3MjI0NWU3ODYzMjc0NWY5ZjhiNTQ1MDg5ODk5OTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBjMDkwMDc0ZTgwNWM0YjE5Y2QyZDM5OTAyOWE2MGQ3OTI3YWVkMzc4ZTMzYTlkNmZmZTMxZWM2NGY3MTRjMTcifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHRoutedSocket.swift#L131-L176",
"version": "repo-lines-v1:sha256:bd9a12d4a6fb1dfe3bf37a37fb642d2bf4b5c8f9281190cd67ea39c5d0f6b120:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQzMmI5YzZlMTY4NGUxNjRkMzJhNGFkNDM5ZWRlZTM4Zjc2MzFhZjAwOGNiZWM1YWIwZTRiYjI3ZGU1NzRmOTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhMzhjNzYzMDBmZjE3NDFlNzkwNTg2MjA1ZmVkODY0ODE2MDgxNDg2YmQzYTY1MTI4YTFiYjhhM2FhYTJhNWQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIxODYzOTA2YzcwNWM4M2U1NzI3MzkwYmM1Mjc5YzcxNTU5MTNjZGMwYTUxZTY5NGU5ODFmZDk0ODFlMTgzOGMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRhMzI0OWIzNzVhNmM5MzI3NzM1ZDM0YmRmNmQ0YmMxYWIyZjY0ZmZhYzE0MDE5YzQ5NWExOWIxY2RjYmExOGMifQ"
}
]
},
{
"id": "claim_922ef5ecc1b44306a5c9521d381b159b",
"statement": "SSH routing authenticates each jump on the current transport, opens a `direct-tcpip` bridge toward the next proxy or destination, and negotiates a following proxy over that bridge before the next SSH handshake.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHRoutedSocket.swift#L311-L385",
"version": "repo-lines-v1:sha256:48ac8992fe9a1d4947401f2f3fc060b8381fcf13dbfe9e7536e0fcfa0d69744b:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1N2NiYzg3NDE3MzRkMDAwYmVhNGEwODJjNGYxM2RhMzUxZjNhNGQ3MWVmZDFhNmUwYmVhNWU1OWE0YmM2OTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI0YWNmZDMzN2E3NDdhNDU5OGZkZjIzYzhjNzA0N2ViODAyOTE5MTQ3Mzk4MDE3ZmNlZDU0YWJmMjZkNjkxNzIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHRoutedSocket.swift#L40-L110",
"version": "repo-lines-v1:sha256:e3358a81fec73d65c6ecd95c741d3c0435c9813a2e3b153a3933d0cc905e48af:eyJzZWxlY3RlZExpbmVDb3VudCI6NzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRmOTFmYThhMjIyYWQyODY0MWIwYTRjM2ViY2IxNzU2YmQ0NzY3YTA5MjVmODIxNDQ2ZWY1ODQ2ZDMzYTI4NDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiZWNkMDQ0NWJmNGEzYTg5NTcwNTczNGE0YmEyYjFjYzQxMjRiNzM1NzYyYWY0ZWYxYzQyODcyNTkyMThlNzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZiY2IyOGEwNGY2MDA1YTBjNDMyNzA1Mzg4ZjRlYjJkYjkwOTY3MzQ3YTI2NWY4YmY5YTA4ZDA4OTg5MTQ2ODEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ"
}
]
},
{
"id": "claim_367fb447cd734995ac18f7a51cc01309",
"statement": "Host-key authorization treats an external MD5 constraint only as an additional handshake constraint: a matching expected identity bypasses interaction, a conflicting known-host set still rejects, and an unknown identity requires an authorizer or fails closed.",
"evidence": [
{
"resource": "repo://FrameworkTests/SSHHostKeyAuthorizationTests.swift#L53-L104",
"version": "repo-lines-v1:sha256:9e438aad1855f8d1b87ce612294037317570c6fa74711c44d1d66ccc9608055c:eyJzZWxlY3RlZExpbmVDb3VudCI6NTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFkNWJkZmQzMzZiYzAwNmE4YjNhZTBlZDY0YWNlOTliMDRkODY5YjFmYjNlNThiNWM3ZWQ0MTU4ZjEyY2VlMGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMzOGI1NWY2NDJiZmU5ODRlYzkwMjJkNWRkMTE5Mzk2MDAzODQxMWZjMTI5OGZmOTE4YTg0Yzg1YTNiZTFkYzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYyNDhkZjhlM2VkYjgyM2EyYTNmZjg3MjZkNmQ0MmQxZTY5NWU1MTU3Y2JmZjlhYzgxZWRlZDkzMzgzZjI0YjgifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L1769-L1800",
"version": "repo-lines-v1:sha256:2a95b550e19f2151c426ba2500ae37ae4a37088682d593255586f3a5fdc32c2c:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc2YzVkM2ZiZGE5YWY3ZjFhN2I2NDYwYTQyZDBmNTZhM2U2M2UzNjZhMDAwYjY1OTMyYWExMjczMDkwNmMwZjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM2YjRlMjdjYjRkOWM0N2NjN2FlZjY2Mzg5MjBiYWExMTdiZDlmMjgzMGE5Y2MzZmUwY2I2MTU0YWQ0MjgwOGIifQ"
}
]
},
{
"id": "claim_91e5ae67592c468da9b173bb6199e156",
"statement": "Persistent Known Hosts trust is independent of Host records, while a Continue Once approval stays only in the live controller; persistent approval saves the key before resuming and disconnect rejects a pending decision and clears temporary keys.",
"evidence": [
{
"resource": "repo://FrameworkTests/SSHHostKeyAuthorizationTests.swift#L106-L188",
"version": "repo-lines-v1:sha256:926ab6983c95d0e17b5cdd437a03717211f03a6a3fd9e40849db40989bbeb77d:eyJzZWxlY3RlZExpbmVDb3VudCI6ODMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRkYTU4ODI4ZDdmNWNiYWU3NGNkZGVhYzUwMjcyNDc0ODQzZGE5OTU4ZmFkNTgxM2ZlZDg2YjgwZjM3ZjU3NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIwZDhlZjdlZGUxOGI4MjNhMjI1MWZjMDg2ZWUwYzczY2JjZjFmOGVjNjA3ZTk1YzQzOTI1OThhZDkxZWJmNzcifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L73-L80",
"version": "repo-lines-v1:sha256:9fc00c398aaa4d3ebc27866f8575deae29f617912ed44e3d1c26355d2dcf97fc:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTA1YWIxMjU1NTRkOWFmYTljODI4ZjIyMThmODYwNjVhNTRmZjdiM2ZiNDZkNmU2NTRlNjJiZWIyYjFkYjVmMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTc2OGI0ZmIzZjc4M2NjYmRjYzE1MjI5YzZlYTAzODE2ZjlkN2QzM2JmODMwYmM4MjE3MTVjZGRkMjc4NWZiNiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMDMwYWIyNjVkMzY3NzQ0MmI4MmY0N2RkMmQxMzM5N2FmNmU1ZWY4YmUxODUwZDZhMGIxNDQ4MGQ4ZjViOGZmMyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDIxY2U2MmZjYzU4ZDViNWUzNTczNWIzZmNkOTZkODg1YTM5ZWZiY2JjNjhiOGIwNDQzNjIyODRhZjI1NWNkMiJ9"
},
{
"resource": "repo://TFMTests/ConnectionJourneyTests.swift#L355-L366",
"version": "repo-lines-v1:sha256:245fa698fcd751e872f40864bc7d436d2502742151efc14af5b4a50f0fa2932e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc1MGIzNzg3MWQ1NTNkODQ2MTM4N2M1OTk5ZDVhNzczMTYxNDVlY2U0NTE4OTAyNzJjOGZlYjA0OGM4ZDRhNTAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
}
]
},
{
"id": "claim_1596335d0a2f4f5eb2ae457734004b2c",
"statement": "SSH credentials and proxy/jump secrets are one-shot configuration material cleared at connection boundaries; interaction-forbidden requests remove interaction-dependent credentials and reject trust or prompted keyboard-interactive authentication.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/SSHConnectionTypes.swift#L151-L180",
"version": "repo-lines-v1:sha256:b34609490f90971a26be17de676fce55de6c08c8965d1e58b69ff68f8cb378a5:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzYTZkNGMyYTg2Yjg5NzFlZWJmNzljZjcwMDEzNmQxODg5YzkyYjhmZWRjYmE4YzEzMDczMTI1NWRiNWVlNDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA1NmZlNWM5NTVkNTM0ZDMwMjgzODc4NjZmMmMwZmQyNzM0YjAzMjlkMmYzZmNmODJmZjNmODFiMjE1NzlhN2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAyNmRjZTI3YmE2N2MxMGJlY2JkOWU3ZjJkN2FhMmEzMjRkMjIyZDNjZmIzNTZlNjljOTlhZDI4N2VlZGRmMDIifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/SSHConnectionTypes.swift#L408-L450",
"version": "repo-lines-v1:sha256:835c132dc63fefad928c3f17ab9991cd5af2cd2912121d01b6b8ffc81e0e7149:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY4ZTdlMWRhMGY0OGExZjNlZjYwZmU2YTU2ZDljMDU0YjNjN2ZiMDU3OGY1OThlODVmYzc3Mzg0YzZjZjk3MTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBmYzVkOGVjN2Q1M2E5MTkzMzI1NjYzZGMwZTdjYmZiZDgzZTg3ZGY3N2UxYzk2NmI2NjU3ZmU2NTc4NDBlMGQifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L914-L988",
"version": "repo-lines-v1:sha256:3732dbf5351a5a0c23984a5dd3c7bf44a75f66b6bae7115a9214a864cf34b666:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVkMWE0ODkwODI0YmYyMGZkZTA5MjhiZjQ4Zjk0Nzc5YTAxYzNkNzkyOGM5Nzk0NTk3MDAyN2MzYWM1NzkwNGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNkNzc2Mjk0NmE3Zjc5ODMzZjcyN2FlYWE0Y2RmZmI0OGI2ZWYwMjYxMTQzYmFjZGJjOTJjNzk4MDQ5ZDUwMDgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ"
}
]
},
{
"id": "claim_957e6f34ffdd4bbfb231a401cdb3f4ce",
"statement": "`SSHConnection` serializes libssh2 calls through `SSHConnectionWorker`; worker cleanup increments a generation, cancels timers, fails commands, closes channel owners and the authenticated transport, preventing stale socket/timer work from affecting a retired connection.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnection.swift#L78-L153",
"version": "repo-lines-v1:sha256:7cd8c03c5d2ee902ee2accbed4ca2892ab57d59c7c6225ab2de05047d41f05ee:eyJzZWxlY3RlZExpbmVDb3VudCI6NzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM0MTkzNDlkZmY3ZmIxZGEzODM0YWMzYjUxZTliNTlhNWZkOWI4YjZhMzVkZDBjOThhZGVjMjljNTJiOTUzNTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM1MGI1OGFlYTllY2ZmNWFlNGEwNDFmY2UyYmNhYjIzY2FkOGI4ZWExZjU2NWQ4MDE2ZWQ0MDAxZGJiYTc0NzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnectionWorker.swift#L268-L301",
"version": "repo-lines-v1:sha256:4cd12c5fccc9f779f95ae2b5289b4241a9d9b99f97305b6fefd2b520e5050763:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkwZjIyZmNiMjA4MjEzNDM3ODYyZTNmNDlhMzM4YTgzY2I2NzY1NTkyNWY4NjRlYWY3ZTAzZGJmODBmODcxMDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEzYjM0ZWI3ZGU1NTFhNDc0NDE1MzFiOWRhNTAxMjM3YTMxYTRmYjhmOGI1ZTU3N2QxMTQxOGVlMTUxYzQwZTIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnectionWorker.swift#L645-L679",
"version": "repo-lines-v1:sha256:eb81bd33e95c2dbc8e9ad0444c4054091d8e242258def4a449593ba0789b0f3a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcxNWQ3MzE0NWU0NmY0OWE3Yzk5Zjk1NDhhMjk3YWVjOGFlOWVkNGQyMjBiYmRhMTNlZDIyYzQ3NTBhNjZmMzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4MDkxMDBhYjE3ZjFhYzI2YmVjYjNkYzU3MzcxNDg2ODI4MDg0ZmUwZjM1OTA1MDYyNWQ2MmM0MTE5NGM2ZTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgwNGY4OWZjMGVjOThjOTgyNDE4M2U3OTVkM2VkZDE5ZTkzMGY3YmM0NzFmOTAxMmFhM2Q1MDNiZTJmODk3NGIifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnectionWorker.swift#L8-L13",
"version": "repo-lines-v1:sha256:92fd271a1a3ceb358cb764b1ac22be475cfbb4b79a9742035373c5292146cc68:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDIzOTBjYWZjY2E4NDkxYzVmODcxZjY0OWVkZTFiMGRjYWMyZTZjMmFkNzk3ZDU0MWM1MTJjNGYwNzM1ZjM5ZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzAwNTE1NjFjZDU4MjRhN2MzYzgwZWY0ZjFiYzEyYzNjNmM2Nzk5NDAyYzgzNDYzODZhY2ZlOTM3MWJhNDUzMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZWRkYjg1NzgwMGE1ZDcyNDdmZjIzYzVjZDVlNTJjNTQ3YmJmNGJjMzY1YjlhNzQyNjk5ZWUzM2RiYjI4OTJjMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMmM3MjQ3YmNiZGE0ODI2ZjM3NTljMzI1ZjMzNmVjNTdmMDlmNWNiNjAxZDFiZjE1ZWZiZTYwNWU3ZDU1ZmE3NCJ9"
}
]
},
{
"id": "claim_42c9e8f115d54eed818fdd19063fb088",
"statement": "Desktop restoration does not reconnect live Workspaces, whereas mobile persists only connection-free workspace descriptors and cold launch performs no session or network restoration; mobile background expiration closes transports and foreground can resume existing workspace intent.",
"evidence": [
{
"resource": "repo://Memory/ARCHITECTURE.md#L45-L70",
"version": "repo-lines-v1:sha256:3a7990666a403f4d2997ffea80a867cf3afde14ec23da5d6552ae7062c9d7a64:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhMmVmYTE0MmJjM2QwNjU0NWIyZmI1OWViYTY4NzBkODE5NjYzMmFkY2Y3NjEyM2U4Yjk1ZDVkYzNjNzUxYTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVlMzEwOWI5YTgxNTdmNzg4MDg2YWMxZTkzMDI5NjA1MmYzYTA3ZTU5NDc3ZDU4ODQ3Njk0MTYwOGM2OTUyNDEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFiYmE4MjFiOGQxYTY2MWIyNDRiZGI4YThiMDhhZTE3NzJhNjNhNGI5YjI1ZGFiOGRmMDZjYjEzYTMzNmRmYTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBhZmI0NzhhMjdhNDA0NDY5ZjljYThiMTgzZmQ4Y2NlZGI3ODVlNTI1NzU4MTE5NDc4YmY0OTYyYzE5ZmZjZTUifQ"
},
{
"resource": "repo://Memory/ARCHITECTURE.md#L484-L497",
"version": "repo-lines-v1:sha256:dc5d6d0351149cdf7131b71d2015a16e4b17d7e723f026e52d8ffb65b150e229:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmMGI4ZWYzNTgwMzAyODcyMDZlMGQ2M2FhYzNiMzAyNjFiODQ5Nzg2MWJjMDkwYTkyMTlkMDhhZjJmNWIyODEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVlYzBmZDY2ZTUyMDdlNTBhNTkxYThjYWViNjc0MjBjMGY4NzVkZGVlYmI4Mzk3NDgxY2M4YmRjYzAxNGQ4ZTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyMzg3ZTdkMjcwM2M0MGJhOWNmYWNkYzk4ZTJlNDNkOWYzYWU5YWVhMjhiY2MwODI2MjI4ODg5MzgzZmRiZDkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM2Nzk5NDA5YjQ0NWVlYzMwNThhNzg5NDU5NmVkMTM4YmM5ZTY1NzFjNjQ0YzhkMzNhOGM0NTJhOTkwZjY0NDkifQ"
},
{
"resource": "repo://TFI/Features/Workspaces/MobileWorkspace.swift#L1051-L1093",
"version": "repo-lines-v1:sha256:fbbd6aa6c600fb47badb453ae29fadf02d4eee77b793e62a39a4e5284ed2d3f1:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiMjBmNmMyMmZmMjQ5M2I1OGJmMmNhYjNkMzU5Yzk3OWU5ZTJhMjE1NDIxMjUzNGU4NGFiODM2MWJlZDgyNzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ1NDZkMzEzNDZkMjg3Y2Y4YTM3NDhhMmNlZTU4ODE1OTFmNTJlNTVjOTM2MDZhM2IzYmM4MDU2OGQxZWQ0MzIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2ZGMzODIwMjNmZDQ2NDhkYjQzZmZhNjFjNWJmYjQ3ZjliOTZjZTIyZjFmNGI2OGYxZTczZGY3ODkxN2VlMDkifQ"
}
]
},
{
"id": "claim_9a93b3ff203840439f52c6e9b9586c47",
"statement": "Telnet uses an independent direct-or-proxied TCP transport with generation-guarded callbacks, incremental Telnet negotiation and charset conversion, and consumes an automated password once; it is not an SSH trust, jump-host, or SFTP transport.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L151-L232",
"version": "repo-lines-v1:sha256:0e6b815e7e2ca336ef225ca526990670f09a69dd4e152c12c72958087d8eea11:eyJzZWxlY3RlZExpbmVDb3VudCI6ODIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI1NzA0M2EzYmQxMzJiYzI1MGJlMmZhMzZiODg4NzQyYTkxYWJlMzg1ZGQ2NjdlYmE0ZGJlN2U0Yjc3YTlkZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJlNTZiNmUwYTJmM2ExZDc3Yzk1NmVkNzBkZjVmOTg2ZDZkNzdjNTZmNGU4NjczNWRkYjVmNGRiNThhNjZjZGMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFiZjkxNjNmY2E0MTg4YTMyYzQwOWUzOGNhZjljNmUyODA5Y2E1NzRlMzQwZTBhMTMyMjU2ZWU3NTMyNGUxZTcifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L324-L401",
"version": "repo-lines-v1:sha256:4dc2ebee2e7b4d237580c96c8c6e766f0f1fa5de7381f375a9ff5549e1f15cfe:eyJzZWxlY3RlZExpbmVDb3VudCI6NzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2MWQxODI3ZTg0Zjg4MTFjMGJjNWJmNGRjZTcxNTIyZDhiOGQzNDA1NTI1NjE3YTRmMWNmYTcyOGE5MzdiODMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5OGViOTg0ZDg2NjM3YzAxOWE5ZTQ3OWM0YTYyNzkyNTZmMzJlYzZjYmExODUzZTgwN2FkZmMzNGQ1MGNjMGMifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L456-L488",
"version": "repo-lines-v1:sha256:5fee67ed0a235dea88e2a44179c52621dd4430d5d0df84142d6ab43f12b6f19d:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4MTVhZjQ0Y2NjYmY3M2ZiOGFlYTRkMmE1ZWUwNTFkMTllMmUyMDMzMWQ3ODVlY2MzOThmMjBlMzgwZDk5ZDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJiOTg0MmMxZjExMTk5ZmUyZDVhZjJmNzhkOTdiZjQ2NDc5ZjA0NTQ0NzQ5ZmZhNGJjMWQxMGUxMDhjMTUyMTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgyMWVhZDE2YTdlMjJmMzJkNWNhOWM2NzRmOGUzNWY0YmNkN2RmZWZhNmQ4MjViYjQwOTc3YTJjMzdiNzViY2UifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L77-L148",
"version": "repo-lines-v1:sha256:1022163f76089c5b97496b41e7db77def5dbe2cc6ec72eb7e3713123db729f2b:eyJzZWxlY3RlZExpbmVDb3VudCI6NzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdiMGE4OWZhY2U5NDE1ODFiNTg4NDc4OTU5Y2YzMTJkNTEwMzdmZWViZTgzMjFmN2MzNDNjMmM1M2QzMTg2YmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQzNDU2OWJiNmExNjBkOTQxMzM3ZmVkMDI5N2ZmZGU4YTUyMDdiZGVmNTZkZTFmNWYyZjRmOTYzMDk1ODExYTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc2ODA5YWVmZjFjMmQ1MWUyYWU0MGFjZWM5NWQ2Y2ZiOWJhMjU5M2I2MjFjNDUwOTRhN2RkOWY4MmUwMGFmNDQifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-22T00:31:10.149Z"
}
}
+2 -2
View File
@@ -1,7 +1,7 @@
{
"updatedAt": "2026-09-22T00:31:10.151Z",
"updatedAt": "2026-09-22T01:10:02.666Z",
"command": "init",
"model": "host-agent/omp",
"model": "gpt-5.6-terra",
"status": "interrupted",
"language": "en"
}
+96
View File
@@ -0,0 +1,96 @@
{
"schemaVersion": 1,
"pages": {
"/openwiki/architecture/platform-runtime.md": {
"pageVersion": "sha256:7d2268951977dcbe8bf9e3bfa6b79ec69cb3d55c72a1c242cc8b944a0fb88ec5",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/architecture/system-boundaries.md": {
"pageVersion": "sha256:95ae2f50f3a459aa6c5502c11c301d3783446a4c86117684b7d4092e7e88a15f",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/concepts/agent-runtime-and-assistant.md": {
"pageVersion": "sha256:4737dc09eb90c0420b880bf2fab094f9135192ed24ce438943b5251eea09c18b",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/concepts/commerce-localization-and-product-surfaces.md": {
"pageVersion": "sha256:13ee440b075102e79b27dd13511c49632f448d22bca95bd6a15fe2a7573ee4d8",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/concepts/persistence-and-secrets.md": {
"pageVersion": "sha256:f80158b701ee0dc77c084e3efa79baac40aee8b745e4db59ad684daf439dc8d4",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/concepts/remote-services-and-forwarding.md": {
"pageVersion": "sha256:1ba92bb80b68bc0bcc82b721f3e819856f8ea736469dabc908eca371f6250395",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/integrations/mcp-server-and-bridge.md": {
"pageVersion": "sha256:31386cf38a0d16ee1dd92c94cf5aa7c8d8ca1d97425ea06d79ca64e53609daab",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/operations/build-test-and-release.md": {
"pageVersion": "sha256:65a192526c7077d01d0e5a58245de0d19f7c103accfcb0d8ed32d612ea0bb477",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/quickstart.md": {
"pageVersion": "sha256:cade63e93115426143be255179f6a32b2c867cf7a7b539dab9b264dcdca0cff3",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/testing/behavioral-boundaries-and-fixtures.md": {
"pageVersion": "sha256:85333b33c78f0f8066210d2b0b93e64fd7818b59990150b887a5d2d089d893f8",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/workflows/settings-and-cloud-sync.md": {
"pageVersion": "sha256:0ba005777749189c842f01e920cd1360444545e29e6b4fbbef9076c287cd0b9c",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/workflows/sftp-transfer-and-external-edit.md": {
"pageVersion": "sha256:1d92d75b2ce5b6df028b5364c4bf11bf06f448af163019a2c9cca92cc6e7ebe3",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
},
"/openwiki/workflows/ssh-session-lifecycle.md": {
"pageVersion": "sha256:a66e72891fdef94d2c7a41807ade26ed1ac61b901548af5b7c4fd82d60480f47",
"completedBy": "openwiki/0.5.2",
"completedRunId": "a38b6393-91cd-4070-8273-be41641508b6",
"gitHead": "c5e86d52bd6fc24857962d4cf31c7c84c8e80671",
"sourceFingerprint": "sha256:baaf5b7a122eb12537d25d975900c89cbe5e8b754729fab4f905415d6a4a633d"
}
}
}
+1
View File
@@ -0,0 +1 @@
A code wiki for this repository.
+4
View File
@@ -0,0 +1,4 @@
# Files
- [Platform Runtime, App Composition, and Lifetimes](platform-runtime.md) - How Termind composes shared services and persistence on macOS and iOS, and where app-wide, window-local, scene-local, and session state begin and end.
- [System Boundaries and Dependency Ownership](system-boundaries.md) - Static framework layers, platform composition roots, persistence ownership, and the external AgentKit boundary that keep Termind changes dependency-safe.
+179
View File
@@ -0,0 +1,179 @@
---
type: architecture
title: Platform Runtime, App Composition, and Lifetimes
description: How Termind composes shared services and persistence on macOS and iOS, and where app-wide, window-local, scene-local, and session state begin and end.
tags: [architecture, runtime, macos, ios, lifecycle, dependency-injection]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-dc9295278cc250ed20567540
resource: repo://TFI/App/MobileAppDependencies.swift
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-c8d832474c03f5ebad7b0578
resource: repo://TFI/App/MobileRootView.swift
- id: openwiki-source-e43a0da5ab77c2fc3554244d
resource: repo://TFI/App/MobileSceneModel.swift
- id: openwiki-source-6c9f797fc6a1e7ce639b72b8
resource: repo://TFI/App/TermindIOSApp.swift
- id: openwiki-source-b822b041afbf829d09a8555a
resource: repo://TFITests/MobileAppTests.swift
- id: openwiki-source-2c8d92432bb6dac7ede21141
resource: repo://TFITests/MobileForwardingLifecycleTests.swift
- id: openwiki-source-4dbea0ff2808163cb4ecdd8f
resource: repo://TFM/App/AppModel.swift
- id: openwiki-source-873894299539cce9a737a860
resource: repo://TFM/App/RootView.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-22e92f96394f292a731fc6fb
resource: repo://TFM/Platform/MainWindowCoordinator.swift
- id: openwiki-source-531f6567ecf96fd4b0c5e97a
resource: repo://TFMTests/ExternalConnectionURLTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# Platform Runtime, App Composition, and Lifetimes
Termind has separate native application targets—`TFM` for macOS and `TFI` for iOS/iPadOS—but both compose the same layered frameworks into a platform-owned runtime. The application target owns startup, native lifecycle hooks, dependency assembly, platform UI, and the boundary between durable app data and live UI/session state. Shared frameworks do not import either app target.
The most important lifetime rule is: **stores, coordinators, and durable-data services are app-wide; navigation, presentation, and desktop workspace ownership are local to a window; mobile navigation is local to a scene; live transports belong to the workspace/session that opened them.** Do not move state across those boundaries merely to make a UI path convenient.
## Lifetime map
| Scope | macOS | iOS/iPadOS | Examples |
| --- | --- | --- | --- |
| Process / app model | One `AppModel`, retained in `TermindApp` state | One `MobileAppModel`, created before the `WindowGroup` | SwiftData container, host library, settings and sync coordinators, shared remote coordinator, histories, transfer and forwarding services, entitlement/review state |
| Native window / scene | `WindowModel` per main window | `MobileSceneModel` per SwiftUI scene | destination, selection, sheets, navigation routes, focused-value command routing, scene-local assistant navigation |
| Workspace and session | Desktop `Workspace` and panes are owned by one `WindowModel` | `MobileWorkspace` instances are shared by `MobileAppModel`; a scene selects one | terminal or SFTP UI, connection journey, transport, terminal state, workspace-specific operations |
| Durable state | SwiftData, Keychain, supported UserDefaults and sync stores | Same categories, plus local `MobileWorkspaceStore` descriptors | Hosts and settings, secret references, histories, mobile recent workspace descriptors |
| Ephemeral runtime state | Never restored as a live connection | Never restored as a live connection | SSH/SFTP transports, authentication journeys, one-shot URL credentials, in-flight runs/transfers |
A useful consequence is that sharing a desktop `AppModel` does **not** make its `WindowModel`s share selection, sidebar/search state, or workspaces. Conversely, mobile scenes share the app's live workspace registry, so opening the same saved descriptor from multiple scenes reuses one workspace and one initial connection attempt; each scene still owns its selected destination and selected workspace ID.
## macOS composition
`TermindApp.init()` is the desktop composition root. It determines whether it is running tests or a debug screenshot demo, constructs one SwiftData `ModelContainer`, prepares settings and metrics persistence, makes the Keychain-backed secret store, and assembles `AppModel` with repositories, sync coordinators, logging, histories, and the common `RemoteConnectionCoordinator`. Startup fails closed: an inability to open the local database calls `fatalError` rather than substituting an empty store.
```mermaid
flowchart TD
Launch["TermindApp init"] --> Store["TermindPersistence makeContainer"]
Store --> Persistence["Settings and metrics persistence"]
Store --> Hosts["HostLibraryModel and SwiftData repositories"]
Launch --> Secrets["KeychainSecretStore"]
Launch --> Logging["LaunchFileLogService"]
Launch --> Remote["RemoteConnectionCoordinator"]
Persistence --> Sync["Vault Settings and Metrics sync coordinators"]
Hosts --> App["AppModel app-wide runtime"]
Secrets --> App
Logging --> App
Remote --> App
Sync --> App
App --> Group["WindowGroup main"]
Group --> Root["RootView"]
Root --> Window["WindowModel per window"]
Window --> Workspace["Window-owned Workspaces and panes"]
App --> AuthWindow["External authentication Window"]
```
This diagram shows the desktop composition root and the split between one app runtime and per-window workspace ownership.
### Shared desktop runtime
`AppModel` is the cross-window coordinator and service owner. It owns the host and credential projections, known-hosts/snippet/forwarding/transfer libraries, terminal and SSH/SFTP settings, histories, AI/skills/memory, metrics, entitlement and review controllers, remote connection coordination, SFTP edit/transfer services, forwarding, MCP services, and sync/outbox integration. It also owns the global conversation store and one speech transcription coordinator, avoiding duplicate conversation state and competing audio taps across windows.
The model keeps only weak registrations for open `WindowModel`s. Registration injects shared stores and coordinators into a window and attaches that window's assistant library to the process-wide conversation store. Fan-out operations—such as a host route change or deletion—find registered windows and disconnect or close the affected window-owned workspaces. This is coordination, not ownership transfer: the window remains responsible for its own UI and workspaces.
`TermindApp` creates a `WindowGroup(id: "main", for: UUID.self)`. Each scene receives a fresh `WindowModel`, places it in `RootView`, and injects the same `AppModel` and SwiftData container through the SwiftUI environment. `RootView` registers the window on appearance. The independent `Authentication Request` window is intentionally reserved for external authentication presentation rather than normal Window-menu creation.
### Window-local desktop state
`WindowModel` contains the state that may legitimately differ in another desktop window: navigator destination, dynamic workspaces and panes, sidebar and search behavior, workspace selection, local presentations, and window-specific assistant surfaces. `RootView` preserves mounted workspace-native views when a different destination becomes visible so terminal grids, scrollback, and SFTP UI state survive navigation.
A host-opening action is centralized in `AppModel`, which records connection history and chooses the requested protocol, but it opens into the caller's `WindowModel`. A batch can deliberately create separate window-local workspaces or one workspace with several panes. External SSH/SFTP/Telnet URLs likewise create a temporary workspace in the target window without adding a saved Host; Telnet URLs containing an advisory password require explicit confirmation first.
`MainWindowCoordinator` binds native `NSWindow`s to `WindowModel`s. It processes new-window and workspace-move requests, preserves system-restored frames, saves normal window size only at appropriate boundaries, and unregisters then closes a model when its native window closes. The AppKit delegate handles Dock reopen/new-window behavior and may retain the process after the last window according to menu-bar metrics configuration.
### Desktop lifecycle and termination
The AppKit delegate starts native appearance/login handling and, outside tests, starts metrics activity and the metrics menu once `AppModel` is available. On app activation it refreshes entitlement state. On termination it first checks for pending external edits; after user confirmation, it saves window sizing and invokes `AppModel.shutdownForTermination()`.
Shutdown is deliberately idempotent and bounded by the delegate. It suspends memory and edit monitoring, stops metrics, speech, windows, SFTP work, external authentication, forwarding, and the outbox; concurrently awaits MCP and SFTP cancellation, then closes agent background commands and connection pools. The delegate replies to macOS when cleanup completes or after a three-second fallback, preventing an unbounded quit wait.
## Mobile composition
`TermindIOSApp` runs language-preference migration and constructs exactly one startup `Result<MobileAppModel, Error>`. It selects `.testing()` dependencies when XCTest is detected and `.live()` otherwise. The `WindowGroup` either injects the shared model container into `MobileRootView` or presents an unavailable-data screen if construction failed; unlike macOS, failure is surfaced in the first window instead of terminating the process.
```mermaid
flowchart TD
Launch["TermindIOSApp init"] --> Deps["MobileAppDependencies live or testing"]
Deps --> MobileApp["MobileAppModel app-wide runtime"]
MobileApp --> Container["SwiftData ModelContainer"]
MobileApp --> Services["Libraries sync transfer forwarding assistant metrics"]
MobileApp --> SharedWorkspaces["MobileWorkspace registry"]
MobileApp --> Group["WindowGroup"]
Group --> Root["MobileRootView per scene"]
Root --> Scene["MobileSceneModel per scene"]
Scene --> Nav["Tab and navigation selection"]
Scene --> Selected["Select shared MobileWorkspace"]
SharedWorkspaces --> Session["Workspace-owned SSH SFTP or Telnet session"]
Root --> Phase["scenePhase"]
Phase --> MobileApp
Phase --> Background["Suspend or expire runtime work"]
```
This diagram shows that mobile scenes have independent navigation but select from app-wide live workspace instances.
### Dependency assembly and test seams
`MobileAppDependencies` is the mobile assembly seam. Live dependencies create a launch file logger and a single `RemoteConnectionCoordinator`, which is passed to both mobile workspace connections and metrics; the same logger is passed to forwarding. Test dependencies use in-memory mode and permit replacement of the host repository, defaults, background-task manager, workspace connection services, metrics services, review controller, container, workspace store, live-activity controller, and forwarding factory.
`MobileAppModel` creates or receives its `ModelContainer`, then builds the host repository, outbox, Keychain or in-memory secret store, settings/metrics persistence and sync coordinators, host and credential libraries, AI/skills/memory, assistant, metrics, transfers and SFTP edits, forwarding, histories, and live activities. Production uses `Termind.store` under Application Support; tests or supplied repositories use an in-memory container and do not enable production live activities or sync coordinators.
The app model wires cross-service invalidation at construction. Host deletion and route changes invalidate edits, cancel transfers, stop/reconfigure forwarding, remove relevant metrics/history, and disconnect or close live workspaces as appropriate. Remote sync application similarly computes a change plan before replacing the local projection, so route-affecting changes retire affected runtime work rather than leaving it attached to stale configuration.
### Scene-local navigation, app-wide mobile workspaces
`MobileRootView` creates `@State` `MobileSceneModel` for its scene and reports `scenePhase` to the shared app model. It uses one sidebar-adaptable `TabView`, but each tab hosts its own `NavigationStack`; adapting the tab UI does not replace the feature tree. The scene model owns destination selection, selected/pending workspace IDs, connection-picker and editor presentation, external-link confirmation, local assistant-library route, review page, and recency used to choose an already-open workspace. Focused scene values route commands to that scene.
`MobileAppModel`, rather than a scene, owns `workspaces` and the persisted descriptor list. `openWorkspace(_:)` first returns an already-live workspace; otherwise it validates the saved descriptor's Host, constructs the workspace, publishes it, and then starts its connection. Publishing before connecting is an invariant: multiple scenes selecting the same descriptor share an instance and cannot trigger duplicate first connections. A scene only selects/presents that shared workspace.
Mobile persistence deliberately restores **descriptors, not sessions**. On cold launch `loadRecentWorkspaces()` reads descriptors, removes those whose Hosts are absent, and publishes no live workspace or connection; it also clears leftover Live Activities. A descriptor contains local identity/title/kind/duplicate-index information, while initial commands, paths, connection secrets, and transports stay outside it. Opening a saved descriptor connects it on demand. Closing removes both the live instance and descriptor; externally linked temporary workspaces are not persisted.
### Mobile foreground and background boundaries
Scene phases are aggregated by scene ID. The app only enters global background behavior when every tracked scene is backgrounded, so one backgrounded scene cannot suspend work still visible in another. On that transition it stops edit monitoring, suspends memory and sync, pauses metrics and outbox work, suspends recording, and starts a finite platform background task. If the task expires, it asks each live workspace to handle background expiration, stops forwarding, pauses transfers, and expires assistant work. It updates Live Activities but does not use them to retain connections.
When any scene becomes active, mobile reenables edit monitoring, finishes the background task, asks existing workspaces to resume, reconciles sync according to foreground entitlement, restarts the outbox and metrics, refreshes entitlement asynchronously, and updates activities. Returning before expiration therefore preserves healthy connections; after expiration, workspace recovery follows the workspace's reconnection journey. Expired forwarding and pending interactive authentication are stopped rather than silently restarted on foreground.
## Ownership invariants and safe extension points
### Preserve these boundaries
- **Do not make a window or scene the owner of app services.** Inject app-wide services into per-window/per-scene presentation models; use the central model for operations that must affect all live owners.
- **Do not make app-wide navigation state.** Desktop window destination/workspace collections and mobile scene selection must remain independently mutable.
- **Do not persist live connection state as restoration.** Mobile descriptors are intentionally limited; desktop state restoration must not reconnect active workspaces merely because a window returns.
- **Publish shared mobile workspaces before `connect()`.** Changing this order risks duplicate live instances and duplicate connections across scenes.
- **Retire runtime resources before replacing configuration.** Host deletion, route changes, and remote sync need to invalidate workspace sessions, transfers, edits, forwarding, and dependent services through their existing callbacks/change plans.
- **Keep test composition explicit.** Extend `MobileAppDependencies` or `AppDependencies` when a platform integration needs a substitute; do not add test-only global singletons to production code.
### Adding a shared service
For a service that must be unique across windows or scenes, construct it at the platform composition root, place it on `AppModel` or `MobileAppModel`, and provide narrow callbacks or accessors to local UI models. Decide its shutdown/suspension contract at the same time: macOS termination must include it in `shutdownForTermination()`, while mobile must define whether it pauses on all-scenes-background, expires with the background task, or safely survives foreground transitions.
For a service that represents navigation, focus, a sheet, an editor draft, a desktop workspace/pane, or a scene-specific command target, keep it in `WindowModel` or `MobileSceneModel`. For a connection or terminal/browser state, keep it on the workspace/session and ensure the app-level lifecycle only invokes its explicit suspend, resume, disconnect, or close APIs.
## Focused verification
Tests exercise the lifetime contracts rather than merely constructing views:
- `MobileAppTests` verifies saved descriptors reopen on demand without replaying commands or paths, and that two scenes selecting one restored workspace create only one connection.
- `MobileWorkspaceConnectionRecoveryTests` verifies background expiration disconnects affected mobile workspaces and foreground resumes them, while a quick foreground return preserves a healthy connection.
- `MobileForwardingLifecycleTests` verifies all-scenes background is required before expiration, and expired forwarding/authentication does not revive merely on foreground.
- `DockMenuTests` verifies Dock-created desktop windows receive distinct `WindowModel`s in the Welcome state and retain per-window UI state independently.
- `ExternalConnectionURLTests` verifies external desktop connections are temporary and unsaved, including the Telnet-password confirmation boundary.
See [System Boundaries](/openwiki/architecture/system-boundaries.md) for framework ownership, [Agent Runtime and Assistant](/openwiki/concepts/agent-runtime-and-assistant.md) for shared agent execution state, [Persistence and Secrets](/openwiki/concepts/persistence-and-secrets.md) for storage policy, and [SSH Session Lifecycle](/openwiki/workflows/ssh-session-lifecycle.md) for per-session connection behavior.
+130
View File
@@ -0,0 +1,130 @@
---
type: architecture boundaries
title: System Boundaries and Dependency Ownership
description: Static framework layers, platform composition roots, persistence ownership, and the external AgentKit boundary that keep Termind changes dependency-safe.
tags: [architecture, modularity, dependencies, persistence, agentkit, swift]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
- id: openwiki-source-7a9c6d90cba4ebd1d1398673
resource: repo://Frameworks/TermindPersistence/TermindPersistence.swift
- id: openwiki-source-1c845e5af67c400566be83bd
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift
- id: openwiki-source-d2d4c06f734241db3badc1f5
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-cd0be716a2446029f345525a
resource: repo://Termind.xcodeproj/project.pbxproj
- id: openwiki-source-105d05d558f14996921a83f6
resource: repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-6c9f797fc6a1e7ce639b72b8
resource: repo://TFI/App/TermindIOSApp.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-d3d065330c730839f5cc6112
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# System Boundaries and Dependency Ownership
Termind is built as two native applications around shared static frameworks. The boundary is intentional: reusable layers model policy and ports, infrastructure implements those ports, and `TFM` (macOS) and `TFI` (iOS/iPadOS) compose the result with native lifecycle and UI. A safe change starts by placing the responsibility with its owner rather than importing a convenient concrete dependency into a lower layer.
```mermaid
flowchart TD
Domain["TermindDomain values and rules"] --> Application["TermindApplication ports and use cases"]
Domain --> Infrastructure["TermindInfrastructure local and cloud implementations"]
Application --> Infrastructure
Domain --> Remote["TermindRemoteInfrastructure SSH SFTP Telnet"]
Application --> Remote
Infrastructure --> Remote
Persistence["TermindPersistence SwiftData schemas and stores"] --> Infrastructure
Domain --> Presentation["TermindPresentation reusable SwiftUI policy"]
Application --> Presentation
Domain --> TFM["TFM macOS app composition and UI"]
Application --> TFM
Infrastructure --> TFM
Remote --> TFM
Persistence --> TFM
Presentation --> TFM
Domain --> TFI["TFI iOS app composition and UI"]
Application --> TFI
Infrastructure --> TFI
Remote --> TFI
Persistence --> TFI
Presentation --> TFI
AgentKit["AgentKit pinned remote package"] --> Application
AgentKit --> Remote
```
This diagram shows the permitted ownership direction at a high level; apps assemble shared layers and are never dependencies of them.
## Layer responsibilities
| Owner | Put here | Keep out |
| --- | --- | --- |
| `TermindDomain` | Portable values, domain rules, records, and protocol-neutral concepts. | UI, persistence APIs, security/network frameworks, CloudKit, StoreKit, SSH C libraries, and terminal implementations. |
| `TermindApplication` | Use cases, feature models, repository and service ports, connection/import policy, and cross-feature policy. | SwiftUI/AppKit/UIKit, SwiftData/GRDB, concrete Keychain/network/SSH implementations, and concrete infrastructure construction. |
| `TermindInfrastructure` | General implementations such as in-memory repositories, CloudKit-backed sync, metrics parsers, logging, StoreKit, and settings/Vault services. | Native app targets and platform UI. It may depend on Application, Domain, and Persistence. |
| `TermindRemoteInfrastructure` | SSH, SFTP, Telnet, Keychain-backed remote credentials, host-key/authentication mechanics, transfers, forwarding, and the Termind-specific agent tools. | App targets and their UI; a feature should use its injected services rather than construct remote transports itself. |
| `TermindPersistence` | Every SwiftData `@Model`, versioned schema, migration plan, SwiftData repository/store, and `ModelContainer` factory. | Application-infrastructure implementation dependencies, remote infrastructure, and app targets. |
| `TermindPresentation` | Reusable SwiftUI presentation policy and content: formatting, forms, summaries, transcript/tool-card rendering, and terminal presentation helpers. | AppKit/UIKit, SwiftData/GRDB/Persistence, remote transport infrastructure, and app targets. |
| `TFM` / `TFI` | Native UI, platform adapters, dependency assembly, lifecycle, window/scene ownership, and platform-specific resources. | Shared implementation that should be portable; no shared framework may import an app target. |
`Frameworks/Resources/` is compiled into both application bundles. It is the place for shared resources such as localization catalogs, while app-owned icons, metadata, signing, native adapters, and platform behavior remain in `TFM` or `TFI`.
### Dependency rules that are enforced
`ArchitectureBoundaryTests` scans production source imports rather than relying on conventions alone. It prevents Domain from importing platform/UI, storage, security, networking, commerce, SSH, or terminal frameworks. It prevents Application and app feature code from importing UI/storage/transport implementation frameworks or constructing known concrete persistence, SSH/SFTP, and URL-session symbols. Presentation is separately prohibited from depending on platform UI, persistence, or remote infrastructure.
The checks also prohibit all shared frameworks from importing `Termind` or `TermindIOS`. Application may not import Infrastructure, Persistence, or SwiftData, and Persistence may not import Infrastructure or Remote Infrastructure. Thus depend on a port exposed by the owning higher-level module; do not repair an awkward dependency by a re-export, forwarding alias, generic “Core” module, or an app-to-framework reference.
## Persistence is a single-owner boundary
`TermindPersistence` exports the complete current schema (`TermindSchemaV30`) and builds a `ModelContainer` using its migration plan. Its factory rejects an in-memory request that also supplies a file URL and configures the store with CloudKit disabled; platform composition roots choose *where* the store lives and retain the container, but do not define the model set or construct a substitute container.
This separation matters for migrations: all SwiftData models, frozen historical schemas, migration plans, and container construction stay together in Persistence. The boundary test rejects `@Model` declarations everywhere else and requires Persistence to contain Swift files. A new persisted SwiftData entity therefore requires a Persistence schema/migration decision—not a model embedded in a feature, app, or general infrastructure module.
Both app roots call `TermindPersistence.makeContainer`. Desktop turns an unavailable local database into a startup `fatalError`, avoiding silent replacement with an empty store. iOS builds a `MobileAppModel` during startup and displays an unavailable-data screen when composition fails. See [Platform Runtime, App Composition, and Lifetimes](platform-runtime.md) for the app/window/scene lifetime split and platform-specific failure handling.
## Composition, resource, and state ownership
The app targets are composition roots. `TermindApp` creates the desktop `ModelContainer`, keychain store, sync persistence/coordinators, repositories, connection coordinator, logging, and app-wide `AppModel`; it injects the shared model and container into its window scenes. `TermindIOSApp` chooses live or testing dependencies, creates one startup `MobileAppModel`, and injects that model's container into its `WindowGroup`. This is where a concrete implementation becomes a port supplied to feature code.
Do not use this as permission to move live state into the app-wide layer. Durable stores and cross-window coordinators are app-wide; desktop navigation and workspaces are window-owned; mobile navigation is scene-owned; live SSH/SFTP transports remain with the workspace/session that opened them. Refer to [Platform Runtime, App Composition, and Lifetimes](platform-runtime.md) for the detailed ownership map.
## AgentKit is an external, host-neutral boundary
`AgentKit` is a separately developed remote Swift Package dependency at `https://github.com/AkinoKaede/AgentKit.git`. The project declares a minimum version and `Package.resolved` pins the build to an exact release revision. Xcode builds that resolved remote package, **not** a sibling `../AgentKit` working tree; an uncommitted sibling change cannot affect Termind.
AgentKit owns the host-neutral agent runtime: its loop, approval gate, provider adapters, MCP client, built-in tools, and their core types. Do not redefine AgentKit-owned runtime types in Termind, and do not edit AgentKit to add the Termind name, SSH, SFTP, app UI, or other host-specific behavior. A cross-repository change must be released and tested in AgentKit first, then consumed by bumping the project dependency and resolving `Package.resolved` in the same Termind change.
Termind owns host-aware behavior on its side of the boundary. `TermindRemoteInfrastructure` defines `TermindAgentToolEnvironment` with injected host resolution, connection pools, authentication, metrics, background commands, and optional scratch workspace. `TermindAgentTools` creates the SSH/SFTP, host-listing, metrics, and host-facing scratch tools; `AssistantToolRegistry` registers AgentKit’s built-ins first and supplies the Termind catalog as additive tools. This preserves a single runtime-owned built-in namespace while allowing Termind to supply the capabilities that actually touch Termind hosts.
## How to make a dependency-safe change
1. **Classify the responsibility.** Put stable values and rules in Domain; an abstract use case or port in Application; a concrete general service in Infrastructure; a remote transport/security implementation in Remote Infrastructure; schemas and SwiftData stores in Persistence; reusable view policy in Presentation; native assembly or lifecycle in the appropriate app.
2. **Make dependencies point inward through a port.** If an Application or feature model needs persistence, keychain, SSH, or network work, extend or inject an existing protocol/service rather than import and construct its concrete implementation.
3. **Keep persistence changes atomic.** Add models, schemas, migration behavior, and container-facing repositories under `TermindPersistence`; preserve historical schemas and do not create an independent app-level container.
4. **Keep host behavior out of AgentKit.** Add SSH/SFTP or Termind-specific agent functionality through `TermindAgentTools` and injected Remote Infrastructure services. Release AgentKit separately only for genuinely host-neutral runtime behavior.
5. **Validate the boundary, not only the feature.** Run the architecture tests after a dependency or ownership change, alongside the affected feature tests. Their source scans deliberately fail when a forbidden import or concrete construction crosses a layer.
The most common failure modes are a UI feature importing Persistence “just to fetch,” Application importing a concrete transport “just to connect,” a shared framework importing an app target for a native helper, and putting host-specific behavior in AgentKit. Each creates a reverse dependency or duplicates an owner; use injection at the existing boundary instead.
## Focused verification
`TFMTests/ArchitectureBoundaryTests.swift` is the focused regression suite for these constraints. In addition to layer imports and SwiftData ownership, it checks that AgentKit runtime type names are not redefined locally, limits `ListViewKit` to an explicit native-list allowlist, keeps forwarding/mobile authentication feature-owned, and ensures the forwarding benchmark is independent of app and test targets. The checks fail closed if an expected production root is missing or contains no Swift files, so relocating source cannot silently disable the safeguards.
For normal project validation, use the resolved dependency graph rather than allowing a fresh resolution:
```sh
xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test
```
Use the corresponding `TFI` build/test command when a change affects the mobile target. See [Build, Test, and Release](../operations/build-test-and-release.md) for the full command set.
@@ -0,0 +1,190 @@
---
type: agent runtime concept
title: Assistant, Agent Runtime, Skills, and Memory
description: How Termind assembles AgentKit into durable assistant conversations, applies approval and host-security boundaries, and manages skills, scratch workspaces, and device-local Hermes memory.
tags: [assistant, agent-runtime, approval, persistence, skills, memory, ssh, sftp]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-66f32c7d0994c9f18c0e5a98
resource: repo://.build/verify-zh-hans/ios/SourcePackages/checkouts/AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift
- id: openwiki-source-5f99e8af445e073ffe9bc257
resource: repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift
- id: openwiki-source-1c48f72c0c7a3164d7d5c715
resource: repo://Frameworks/TermindApplication/Agent/ConversationModel.swift
- id: openwiki-source-76220f10b4e23e3c61a811be
resource: repo://Frameworks/TermindApplication/Agent/TermindAgentPolicy.swift
- id: openwiki-source-7397a04f40a393c81b0ca52d
resource: repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift
- id: openwiki-source-e14697ea11a99078be3adee9
resource: repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift
- id: openwiki-source-28d6772acb1a409d29ff1973
resource: repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift
- id: openwiki-source-e1a028bd99d4dbe6d1e14f6a
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentScratchTransferTools.swift
- id: openwiki-source-1c845e5af67c400566be83bd
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-715de8d16be5a3d06ae915ad
resource: repo://TFMTests/AgentPersistenceTests.swift
- id: openwiki-source-d57db929d0047db53dd73cdd
resource: repo://TFMTests/AgentRuntimeTests.swift
- id: openwiki-source-1d8dcc1fdf14c37b90cc9e07
resource: repo://TFMTests/AgentScratchTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# Assistant, Agent Runtime, Skills, and Memory
Termind's Assistant is a durable conversation product built around a host-neutral agent loop. **AgentKit** owns the model-provider adapters, run loop, context pipeline, approval gate, MCP client, generic built-in tools, secret broker, and generic scratch/skill/memory tool interfaces. **Termind** owns the host-specific integration: SSH and SFTP tools and transport pools, Vault-backed host resolution, application policy and prompts, SwiftData conversation persistence, Hermes memory lifecycle, and the UI that renders events and collects approvals or SSH challenges.
This split is a security boundary as well as a modularity boundary. A model proposes tool calls; it does not gain direct access to a PTY, Keychain material, stored credentials, another conversation's workspace, or the persistence store.
## Responsibilities and assembly
`AssistantExecutionController` is the application entry point for a draft. It prevents overlapping starts, archived/history-changing conversations, unfinished attachments, and unauthorized use before it records the user turn. It compacts first when needed, resolves the chat provider and its credential, freezes run-level choices, assembles the tool registry, and starts a fresh `AgentRuntime` through the `ConversationModel`.
A runtime is deliberately single-run. It owns one event stream and one event consumer. `ConversationModel` owns the live runtime and projects its events into visible messages, tool cards, approval and input queues, run summaries, and the authoritative model transcript. The visible message list is not replay history: tool calls and results are separately rendered as cards, so replay must use `transcript`.
Tool availability is fixed at run start. A tool-capable model receives the resolved skill catalog, AgentKit built-ins, and Termind tools; a model without tool-call capability does not receive the skill/tool catalog. Session facts, plan posture, surface availability, and the memory-session identity are captured in an `AgentTurnContextSnapshot`, rather than reread from mutable UI state while the run is executing.
Termind composes the registry in this order:
1. AgentKit generic tools, including scratch, skill, memory, fetch/search, task, plan, secret, and MCP support.
2. Termind's host tools: host/metrics discovery, `ssh_exec`, terminal suggestions, SFTP operations, and the host-facing `scratch_pull` / `scratch_push` endpoints.
3. Discovered MCP tools, which are additive and cannot shadow a built-in or Termind tool name.
## Turn lifecycle
A submitted prompt is persisted as part of the run snapshot before model work begins. AgentKit streams a provider turn, emits ordered UI and durable events through a shared `AgentEventChannel`, validates any complete tool call, then schedules execution. Tool results are appended to the model transcript and persisted before the following model round. This preserves a grammatically answerable transcript even for refusal, cancellation, or failure paths.
```mermaid
sequenceDiagram
participant User
participant Conversation
participant Controller
participant Runtime
participant Gate as Approval Gate
participant Host as Termind Host Tool
participant Store as SwiftData Repository
User->>Controller: submit draft
Controller->>Conversation: record user turn
Controller->>Controller: compact and freeze context
Controller->>Runtime: start request and registry
Runtime->>Store: save running snapshot
Runtime->>Runtime: stream provider turn
Runtime->>Runtime: validate tool schema
Runtime->>Gate: authorize when policy asks
alt approved
Gate-->>Runtime: allow
Runtime->>Host: execute SSH or SFTP work
Host-->>Runtime: bounded result
Runtime->>Store: record durable tool event
Runtime->>Store: save transcript snapshot
Runtime->>Runtime: next model round
else denied or review failure
Gate-->>Runtime: deny
Runtime->>Store: save refusal result
end
Runtime-->>Conversation: ordered events and terminal state
Conversation-->>User: messages and tool cards
```
This sequence shows one assistant turn, including the persistence points around tool execution.
### Streaming, steering, and cancellation
While a run is live, a further user message is queued as steering rather than starting another run. It becomes visible and durable only at the next model boundary, when AgentKit delivers it to the model; if the run has already ended, the UI returns queued text and attachments to the composer. This prevents history from claiming that a message was delivered when it was not.
Stopping a conversation cancels the runtime and its tool work, discards run-scoped secrets, marks running cards interrupted in the presentation, and returns undelivered steering text. `stopAndWait()` waits for the runtime's cancellation/persistence path before clearing live ownership. Termind also invalidates pending preparation when its controller is cancelled, recording an interrupted snapshot rather than launching a stale run.
## Approval, secrets, and trust boundaries
Approval is evaluated after schema validation and tool preflight, before execution. Invalid arguments never reach the approval UI or the tool. The policy layer is stronger than permission mode:
- **Deny** always refuses the call.
- **Approve** executes without an additional approval prompt.
- **Ask** routes to the user under `askForApproval`, to Guardian under `approveForMe`, or is pre-approved by `fullAccess`.
`fullAccess` does not bypass schema validation, host-key trust, SSH authentication, secret binding, scratch containment, network/fetch restrictions, or tool-specific capability checks. Guardian review is only configured in `approveForMe`; it has a bounded timeout and failures, malformed output, inconsistent decisions, and critical-risk approvals fail closed. If the conversation disappears before a manual decision, the approval broker denies the request.
SSH authentication and host-key prompts are Termind interactions, not model-visible tool data. `AgentHostResolver` exposes public host metadata to `list_hosts`, but resolves Keychain-backed credentials into connection configuration without serializing them into tool results. Authentication context is shared only across overlapping attempts for the same destination; after successful authentication it clears staged submissions and cached secret-bearing configuration. Stale generations reject late callbacks and host-key decisions.
`request_user_secret` is only for command standard input, not SSH login. Its handle is scoped to run, tool, host, and stated purpose, single-use, and is removed from replay and durable history. Plaintext secrets must not enter model requests, Guardian review, events, logs, SwiftData, or Hermes memory.
## Host tools and plan mode
Termind tools operate through noninteractive per-command SSH channels and exclusive SFTP leases; they never type into the user's interactive terminal. `terminal_suggest` creates a user-operated command card and never executes it. The standalone Assistant can discover and target configured hosts even without a sidebar session; session context is only an optional default target.
Plan mode freezes at submission. It permits investigation, reads, and policy-allowed commands, but host-specific planning registrations refuse direct remote writes, deletes, and scratch pushes. A plan is drafted in scratch space and presented as the final action; presenting it does not itself suspend a run awaiting a decision.
## Scratch workspace containment
Each tool-capable conversation has an `AgentScratchWorkspace` keyed by its conversation ID under Termind application support. It survives later runs in that conversation, but one conversation cannot read another's scope. Scratch paths are normalized and bounded; escapes, absolute paths, parent traversal, control characters, excessive depth, and symlinks are refused. Entry and byte quotas are enforced before mutation.
The recommended remote-edit route is `scratch_pull`, local scratch editing/diffing, then `scratch_push`. File bytes remain outside the conversation/model transcript: pull reports metadata rather than file contents. Push is an Ask action; its preflight records bounded, redacted evidence and a digest. Execution re-reads the staged file and rejects it if its digest differs from the approved digest, so approval cannot be reused after content changes.
A fork copies its scratch scope before creating the forked conversation and removes that new scope if persistence fails. Deleting a durable conversation removes its scratch scope after deleting the conversation graph; cleanup failure is reported separately because the durable deletion has already succeeded.
## Durable conversations, replay, and recovery
`SwiftDataAgentRunRepository` stores conversations, runs, messages, replay backing, attachments, tool invocations/results, reviews, ordering metadata, and compaction records. It writes messages by message ID rather than run ID, so replaying prior conversation history into later run snapshots does not duplicate historical rows. Tool event persistence is restricted to durable lifecycle events rather than streamed token deltas.
A saved context snapshot preserves the original session and policy baseline for replay, retry, edit, and fork behavior; legacy absent context remains unknown rather than being replaced by current UI state. Persisted text, tool arguments, titles, reasoning, and attachments go through redaction. In particular, secret handles are replaced with expired lifecycle content on restore, and sensitive header values are redacted.
Compaction changes the **model-facing** transcript, not the scrollable display history. Its summary record is persisted before the live conversation applies it; after recovery the model receives a synthetic compaction summary plus recent messages while the user can still read the full original conversation. Editing a user message truncates the target run and later runs atomically, creates the replacement turn, and removes compactions whose boundary was removed.
At repository initialization, every nonterminal persisted run becomes `interrupted`; Termind never replays unfinished execution automatically. Restore reconstructs completed tool cards and can recover a durable tool result that was recorded before its next transcript snapshot. If an outcome remains unknown, repair records an explicit unknown/refusal result rather than assuming a call was never dispatched.
```mermaid
stateDiagram-v2
[*] --> Restored
Restored --> Completed: terminal run stored
Restored --> Interrupted: nonterminal run on launch
Interrupted --> Ready: history and cards restored
Completed --> Ready: history and cards restored
Ready --> Running: new submitted turn
Running --> WaitingApproval: Ask action pending
WaitingApproval --> Running: allow
WaitingApproval --> Running: denial result recorded
Running --> Completed: terminal snapshot saved
Running --> Cancelled: stop and cancellation snapshot
Running --> Failed: error snapshot saved
Cancelled --> Ready: next submitted turn
Failed --> Ready: next submitted turn
Completed --> Ready: next submitted turn
```
This state diagram distinguishes recovery from automatic resumption: interrupted work is visible and recoverable as history, never silently rerun.
Conversation metadata mutations are persistence-first. Archive clears pinning and prevents editing; archive/delete are guarded while a run or compaction is active. Reordering commits the whole ordering update before changing the in-memory library. These rules avoid UI state claiming a history mutation that failed to save.
## Skills
Skills are global app-managed packages, not per-conversation data. A run snapshots its enabled catalog at startup, so enabling or changing a skill does not alter a run already in progress. Reserved skill names cannot be shadowed, and collisions remain visible but paused.
A skill is procedure-bearing only when read through `skill_read_file` from its `SKILL.md`. Supporting files, package frontmatter, tool output, remote files, web pages, and MCP responses are untrusted reference data—not instructions or authorization. Skill installation is acting-only, revision-bound, and subject to normal tool approval; a skill cannot grant permission to execute a command, write a file, transfer data, or bypass other policy.
## Hermes device-local memory
Hermes memory is optional and disabled by default. AgentKit supplies the memory tools, screening/learning model, revocable session snapshots, and access interface. Termind supplies Settings and lifecycle management, while `GRDBMemoryStore` alone owns the memory database at `Termind/HermesMemory`; SwiftData remains the source of truth for conversations.
The GRDB store opens lazily, so disabled memory does not create or open its database. It keeps memory state, frozen per-conversation prompt snapshots, review checkpoints, a redacted conversation/message index, and an FTS5 search index. Conversation history is copied into this separate index only after successful relevant history changes; indexed text is redacted and compaction-only synthetic messages are excluded.
A memory session receives a frozen snapshot for its conversation. Memory reviews use a compare-and-apply base state, so a stale review cannot overwrite newer memory. Disabling memory invalidates sessions, cancels indexing and reviews, and closes the database while preserving stored data. Destroying memory first persists disabled/destroy-pending state, revokes contexts and joins ongoing work, then closes and removes the owned directory; failure remains disabled and is retried on a later launch. Memory and credentials are device-local and are not synced.
## Focused verification
The focused tests establish behavior that is important when changing this area:
- `TFMTests/AgentRuntimeTests.swift` covers schema-before-approval/execution, approval mode routing, Guardian timeout/failure fail-closed behavior, single-use secret handles, steering delivery, tool cancellation, registry shadowing, and durable-event filtering.
- `TFMTests/AgentPersistenceTests.swift` covers redaction, interrupted-run recovery, replay deduplication, tool-result repair, deletion of the persistent graph, edit truncation, fork persistence, and compaction restoration.
- `FrameworkTests/AssistantConversationOperationsTests.swift` verifies persistence-first archive/rename/order mutations, activity guards, and immediate stop before a queued runtime can begin.
- `TFMTests/AgentScratchTests.swift` verifies workspace containment, symlink refusal, inter-conversation isolation, quotas, and bounded reads.
## Change guidance
When adding a tool, define a strict schema, choose an explicit tool policy and planning registration, validate/normalize inputs in preflight, and ensure the tool returns bounded/redacted data. Host mutations must remain behind the same authorization and trust checks whether invoked directly, through MCP, a skill, or a scratch workflow. Do not add a shortcut that serializes SSH credentials, secret input, raw scratch/remote file contents, or unredacted provider data to a transcript, event, log, SwiftData, or Hermes index.
@@ -0,0 +1,131 @@
---
type: product-surface-concept
title: Commerce, Localization, and Product Surfaces
description: Explains StoreKit-derived Pro access, native paywall and review ownership, localization completion rules, and the app, widget, screenshot, and marketing-site surfaces that present the product.
tags: [commerce, storekit, localization, product-surfaces, marketing, widgets]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
- id: openwiki-source-b2f57db7a90dcc30dd3886da
resource: repo://Frameworks/TermindApplication/FeatureModels/AppReviewController.swift
- id: openwiki-source-b37c974aaea12bd08606d67d
resource: repo://Frameworks/TermindDomain/Commerce/ProAccessTypes.swift
- id: openwiki-source-3aa42bdd0f8eaf866f06599f
resource: repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift
- id: openwiki-source-eae5d91412d0e2847dacd5b6
resource: repo://FrameworkTests/AppReviewControllerTests.swift
- id: openwiki-source-103853faf6b28763354a1c79
resource: repo://LandingPage/package.json
- id: openwiki-source-554fe71f1ba6efebee0d020c
resource: repo://LandingPage/src/lib/marketingImages.ts
- id: openwiki-source-35f05e7077ecf965940a0dd7
resource: repo://Memory/MARKETING.md
- id: openwiki-source-41a7ded3800c9422f058a3ef
resource: repo://Scripts/check-zh-localization.sh
- id: openwiki-source-60d4159ef162d09de4f4b469
resource: repo://Scripts/run-screenshot-demo.sh
- id: openwiki-source-9fc915d39c61b81a60426eb3
resource: repo://StoreKit/Termind.storekit
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-e43a0da5ab77c2fc3554244d
resource: repo://TFI/App/MobileSceneModel.swift
- id: openwiki-source-0ffab0ae6452f870ce4a0efe
resource: repo://TFI/Features/Commerce/MobileProView.swift
- id: openwiki-source-4bb1006b8fba7cd74268940b
resource: repo://TFI/Features/Settings/MobileMCPSettings.swift
- id: openwiki-source-4c2de67bfdb2238d765a642a
resource: repo://TFI/Features/Workspaces/MobileWorkspaceView.swift
- id: openwiki-source-637644793f7e37cc057eb973
resource: repo://TFI/Platform/MobileLiveActivityController.swift
- id: openwiki-source-d1ffd558b3360478aa85b5af
resource: repo://TFIWidgets/WorkspaceLiveActivity.swift
- id: openwiki-source-4dbea0ff2808163cb4ecdd8f
resource: repo://TFM/App/AppModel.swift
- id: openwiki-source-2b65afedbf9d80b1d387f50a
resource: repo://TFM/App/ScreenshotDemo.swift
- id: openwiki-source-766dc23f16ac26a41a5b5c22
resource: repo://TFM/Features/Commerce/ProPaywallView.swift
- id: openwiki-source-0da64bbb5811b467bbf89b7f
resource: repo://TFMTests/ProAccessTests.swift
- id: openwiki-source-0dd012e3740bcc348fc36ccb
resource: repo://TFMTests/StoreKitTrialTests.swift
- id: openwiki-source-0f8d0f9d08d6674698dd054c
resource: repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
## Scope and ownership
Termind keeps the commercial decision inside the shared infrastructure and domain layers, rather than treating a screen as the source of truth. `ProAccessController` is the observable, main-actor StoreKit adapter used by both app targets; `EntitlementStatus` and `ProFeature` define the shared access contract. Native macOS and iOS views own their respective paywall presentation and subscription-management affordances, while StoreKit supplies localized products, prices, billing periods, eligibility, and purchase outcomes. The checked-in `StoreKit/Termind.storekit` configuration is a local test fixture; App Store Connect remains the production storefront authority.
The two supported products are the family-shareable lifetime non-consumable `com.akinokaede.termind.pro` and the family-shareable annual auto-renewable subscription `com.akinokaede.termind.pro.annual`. The local configuration defines the annual product as yearly with a two-week free introductory offer, but UI must use StoreKit metadata rather than hard-coded storefront price, period, or eligibility.
## Entitlement-derived Pro access
`ProFeature` is the complete gate vocabulary: AI Assistant, terminal-file upload, remote MCP, the built-in MCP server, Vault/iCloud sync, and unlimited Metrics. Callers must use `canUse` to condition state or `require` immediately before the protected action. `require` records the requested feature and raises the shared paywall flag when access is absent, preventing a caller from continuing merely because it can render a control.
```mermaid
flowchart TD
Launch["Controller starts"] --> Observe["Observe transaction updates"]
Launch --> Refresh["Read current entitlements"]
Refresh --> Lifetime{"Verified lifetime entitlement"}
Lifetime -->|yes| LifetimeAccess["Lifetime Pro access"]
Lifetime -->|no| Annual["Read latest annual transaction"]
Annual --> Subscription["Classify subscription phase"]
Subscription --> Granted{"Trial subscribed or grace"}
Granted -->|yes| Pro["Pro feature is allowed"]
Granted -->|no| Free["Feature requires native paywall"]
Observe --> Refresh
```
This shows the entitlement resolution path used by `ProAccessController`; product metadata loading is separate from access resolution.
Access is based only on verified StoreKit transactions. A valid, non-revoked lifetime entitlement takes precedence over annual status. An annual transaction grants Pro during an introductory trial, active subscription, or verified grace period; billing retry, expiry, revocation, and verification failure do not. Cancellation does not itself remove access before expiry. The controller consumes `Transaction.updates`, including deferred Ask to Buy approval, finishes verified transactions after refresh, and schedules another refresh at a currently access-granting entitlement's expiration. It refreshes independently from product metadata, so a metadata/network failure clears offers and reports a recoverable catalog error without taking away already verified access.
The controller serializes duplicate operations: it prevents a second purchase while processing or pending, tracks the specific pending product, treats user cancellation as non-error, and uses `AppStore.sync()` followed by a refresh for Restore Purchase. A successful verified purchase or restore closes the paywall; a restore without qualifying entitlement reports that no active purchase was found.
### What remains free
The gate set is intentionally narrower than the product’s general remote-workspace experience. Free users can still use the ordinary workspace, SSH/SFTP work, Vault, settings, and the first three Metrics cards. The enforced boundaries are: assistant execution; dropping files onto an SSH terminal; creating/editing/connecting remote MCP servers; enabling or resuming the built-in macOS MCP server; iCloud Vault, Metrics, and Settings synchronization; and Metrics cards beyond three. When Pro sync is unavailable, sync services pause rather than attempting background synchronization; when built-in MCP access is lost, an enabled server is suspended. Local Vault and workspace data are not erased by that transition.
### Native paywalls
Both platforms render native SwiftUI commerce views from the same controller, but presentation is platform-owned. macOS uses a shared `ProPaywallPresenter` to elect one main-window sheet owner; iOS presents `MobileProView` as a native sheet and invokes the system subscription-management sheet. Both offer annual/lifetime selection, StoreKit-derived offer details, restore, privacy and terms links, and communicate that Family Sharing is supported and AI-provider charges are separate. On macOS, subscription management uses Apple’s account URL; only a purchaser-owned subscription is eligible for management controls, not family-shared access.
## Review invitation policy
`AppReviewController` centralizes the cross-platform budget for asking StoreKit to show a review prompt. It persists attempts—not presentations, ratings, or completions, which StoreKit does not reveal—and is deliberately disabled under XCTest. A live controller observes active app surfaces and may arm a request only after an active workspace-to-approved-review-page transition. Mac review pages are selected Vault pages plus Settings and App Settings; mobile additionally enumerates Vault hosts, Keychain, snippets, and known-hosts pages.
Eligibility requires at least seven days since first use, three distinct active local dates, five minutes of foreground workspace time, no prior request for the current app version, and at least 120 days since the prior attempt. After the qualifying transition it waits three seconds, then records the version and attempt timestamp *before* calling `requestReview`. Interactions, navigation, blocked presentation, focus changes, surface removal, or activation of another surface cancel a pending invitation. Presenters also block while onboarding, editors/routes, errors, external authentication, or Pro commerce is active. The explicit “write a review” link records an attempt and restarts cooldown, but does not claim that a rating occurred.
## Localization as a release invariant
User-facing app strings belong in `Frameworks/Resources/Localizable.xcstrings`, which is compiled into every app bundle; bundle metadata belongs in `InfoPlist.xcstrings`. The separate AgentKit runtime owns its own `../AgentKit/Localizations/Localizable.xcstrings`; its catalog must be rebuilt with `../AgentKit/Scripts/build-localizations.sh` after changes because a plain Swift build copies those resources rather than compiling them.
Any new or changed English app string requires completed `zh-Hans` and `zh-Hant` translations in the same commit. Preserve placeholders and Chinese punctuation conventions. `Scripts/check-zh-localization.sh` requires `jq` and rejects invalid catalog JSON, missing locale entries, unfinished string units, and Chinese/Latin or punctuation spacing violations. Run it in the normal commit pipeline even when localization was not intentionally changed; run `AppLanguageTests` when behavior changes. Product configuration likewise carries English, Simplified Chinese, and Traditional Chinese names and descriptions, so App Store Connect updates must remain synchronized with the local fixture and the localized product copy.
## Mobile Live Activity and widget boundary
The widget extension is an iOS product surface, not a second workspace implementation: `TermindWidgets` exposes only `WorkspaceLiveActivity`. The app serializes all activity start, update, and end operations to avoid close-last/open-new races, retains at most one restored active or stale activity, and ends duplicates. It starts only after an explicit workspace opening intent and `ActivityKit` permits it; ordinary updates cannot resurrect a user-dismissed activity. It ends the activity when no workspaces remain.
The activity payload deliberately excludes credentials and terminal output. It provides aggregate counts and up to six focused-first workspace summaries, truncating titles to fit payload/layout limits. The Lock Screen and Dynamic Island expose deep links for the focused activity or individual visible workspaces; the app accepts only strict `termind://workspaces` and UUID-shaped `termind://workspace/<id>` routes, switching to the list or selected workspace respectively. The widget adapts the session row from six to five or four entries to fit, and supplies an All Workspaces link when summaries are omitted.
## Demo, screenshots, and marketing-site boundary
Screenshot/demo data must not modify production behavior. In DEBUG macOS builds, `ScreenshotDemoConfiguration` parses exactly one `--termind-demo=<scene>:<language>` argument and fails fast on duplicate, malformed, unknown scene, or unsupported language input. It binds the fixture scene and `AppLanguage` together, supporting `en`, `zh-Hans`, and `zh-Hant`; the helper script builds the pinned TFM scheme and launches the app with matching Apple language/locale overrides. Demo content uses isolated in-memory models and bundled fixture hosts, with preconditions when required fixtures are absent.
Marketing capture uses real feature views with fixture-only data: mobile tests mount real views in system windows, while macOS captures the production `WindowGroup` through `ScreenshotDemoConfiguration`. Asset source captures are organized by feature/device/locale; the sanctioned locales are `en`, `zh-hans`, and `zh-hant`. UI chrome and marketing copy are localized, while terminal command and transcript content remains English. A UI change affecting a captured scene must be recaptured in every locale rather than fabricating missing platform UI or changing product behavior for an image.
The public site is a separate Astro app in `LandingPage/`, with strict TypeScript and `npm run build` running `astro check && astro build`. It imports an explicit allowlist of framed marketing images through `src/lib/marketingImages.ts`; do not copy marketing sources into `LandingPage/public`. Its formal routes are English `/`, Simplified Chinese `/zh-hans/`, and Traditional Chinese `/zh-hant/`; compatibility `/zh/` redirects to Simplified Chinese. Website work must validate the production build and visually check English plus Chinese routes. App Store screenshots and storefront metadata remain release artifacts, not runtime app configuration.
## Change and verification guide
- For an access change, update `ProFeature`/callers and `ProAccessController` together; test entitlement phases, verification failures, pending Ask to Buy, restore, and metadata failure separately. `StoreKitTrialTests` exercises the local `SKTestSession` configuration, while `CommerceConfigurationTests` catches drift between product identifiers and the fixture.
- Treat local StoreKit testing as insufficient evidence for production: configure and verify App Store Connect metadata and use Sandbox/review environments for storefront prices, subscription lifecycle, restore, Family Sharing, and cross-device behavior.
- For paywall or review work, test both platform presenters and the shared controller’s cancellation, persistence, cooldown, and multi-surface rules. Do not infer a rating or prompt display from an attempt record.
- For text or product-copy changes, complete all three languages, run `Scripts/check-zh-localization.sh`, and run `AppLanguageTests` where applicable.
- For widget/deep-link changes, test bounded payload construction, restoration/duplicate handling, and route validation. For marketing changes, run `npm run build` in `LandingPage/`, preserve real device chrome, and recapture affected locale/platform combinations.
+6
View File
@@ -0,0 +1,6 @@
# Files
- [Assistant, Agent Runtime, Skills, and Memory](agent-runtime-and-assistant.md) - How Termind assembles AgentKit into durable assistant conversations, applies approval and host-security boundaries, and manages skills, scratch workspaces, and device-local Hermes memory.
- [Commerce, Localization, and Product Surfaces](commerce-localization-and-product-surfaces.md) - Explains StoreKit-derived Pro access, native paywall and review ownership, localization completion rules, and the app, widget, screenshot, and marketing-site surfaces that present the product.
- [Persistent Data, Migrations, and Secret Boundaries](persistence-and-secrets.md) - How Termind owns SwiftData and GRDB durable data, evolves compatible schemas, projects records through repositories, and keeps credentials in Keychain-backed and runtime-only boundaries.
- [Remote services and forwarding](remote-services-and-forwarding.md)
@@ -0,0 +1,129 @@
---
type: persistence and security concept
title: Persistent Data, Migrations, and Secret Boundaries
description: How Termind owns SwiftData and GRDB durable data, evolves compatible schemas, projects records through repositories, and keeps credentials in Keychain-backed and runtime-only boundaries.
tags: [persistence, swiftdata, grdb, migrations, keychain, secrets, security]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-4ddcdd630c9bc1c622a037df
resource: repo://Frameworks/TermindApplication/SecretStoring.swift
- id: openwiki-source-4f78037bc69b6dfc293aca3d
resource: repo://Frameworks/TermindApplication/SSHConnectionTypes.swift
- id: openwiki-source-cd3e43e60522274ce1f1908b
resource: repo://Frameworks/TermindApplication/SSHSecret.swift
- id: openwiki-source-8a2e7d4db4b334995f8eaf61
resource: repo://Frameworks/TermindPersistence/AgentPersistence.swift
- id: openwiki-source-1d9bb30e44318b5d16259035
resource: repo://Frameworks/TermindPersistence/AIPersistence.swift
- id: openwiki-source-ec0a64adad50721ec500ebc2
resource: repo://Frameworks/TermindPersistence/AISecretStore.swift
- id: openwiki-source-e14697ea11a99078be3adee9
resource: repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift
- id: openwiki-source-fe1dc993163bb9ff61397be7
resource: repo://Frameworks/TermindPersistence/HostPersistence.swift
- id: openwiki-source-28d6772acb1a409d29ff1973
resource: repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift
- id: openwiki-source-9eb2234b02897ade8e405374
resource: repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift
- id: openwiki-source-63e25c47c9c7d38b354f4123
resource: repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift
- id: openwiki-source-7a9c6d90cba4ebd1d1398673
resource: repo://Frameworks/TermindPersistence/TermindPersistence.swift
- id: openwiki-source-e918380c206900db181ca1d8
resource: repo://Frameworks/TermindPersistence/TermindSchemaV30KnownHostModels.swift
- id: openwiki-source-8180b26ed2e301082e5e7b15
resource: repo://FrameworkTests/IdentityCredentialUsageTests.swift
- id: openwiki-source-8428b9f5de49b8a561d93fa5
resource: repo://FrameworkTests/PersistenceCompatibilityTests.swift
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-1d1efb20e239b1f2142f6cb7
resource: repo://TFMTests/SettingsSyncTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# Persistent Data, Migrations, and Secret Boundaries
Termind separates durable *metadata* from secret material and live connection state. `TermindPersistence` is the sole owner of SwiftData models, schema history, migrations, and container construction; application and platform layers select the store location and inject contexts into repositories. Credentials are represented durably by non-secret references and storage provenance, resolved only through `SecretStoring`, and converted to wipeable runtime objects only for a physical SSH connection attempt.
This is a safety boundary, not merely a storage abstraction: plaintext credentials must never enter logs, sync payloads, `UserDefaults`, or ordinary persistence. Runtime authentication state is also excluded from domain records and restoration. See [System Boundaries and Dependency Ownership](../architecture/system-boundaries.md) for the framework ownership rules and [Assistant, Agent Runtime, Skills, and Memory](agent-runtime-and-assistant.md) for assistant-specific durable data.
```mermaid
flowchart TD
App["TFM or TFI composition root"] --> Container["One process-wide SwiftData ModelContainer"]
Container --> SwiftData["Termind SwiftData store"]
SwiftData --> Metadata["Hosts identities keys settings agent runs"]
SwiftData --> References["Credential references and secret location metadata"]
References --> Keychain["Keychain device or iCloud secret material"]
App --> GRDB["GRDB HermesMemory SQLite directory"]
GRDB --> Memory["Memory snapshots and searchable history"]
Keychain --> Resolver["SecretStoring resolution"]
Resolver --> Runtime["SSHSecret one-shot runtime allocation"]
Runtime --> Session["Live SSH session"]
```
This diagram distinguishes durable SwiftData and GRDB records from Keychain material and session-only secret allocations.
## Store ownership and startup
`TermindPersistence.makeContainer(inMemory:url:)` is the single SwiftData entry point. It exposes the complete `TermindSchemaV30` schema, attaches `TermindMigrationPlan`, disables SwiftData CloudKit integration for this store, and rejects the invalid combination of an in-memory store and a file URL. Both apps retain one container for the process and construct separate `ModelContext` instances where independent repository contexts are needed; they do not assemble a partial schema per feature or scene.
The desktop root makes container opening part of initialization and uses a `KeychainSecretStore` for live composition. The mobile root creates its Application Support parent before opening `Termind.store`, or chooses an in-memory container and `InMemorySecretStore` for test/injected configurations. Store-open errors propagate out of these composition paths rather than being silently replaced with a new empty database: data availability is an explicit startup failure condition.
### Repository projections and atomic mutation
SwiftData rows are persistence representations, not the feature API. `SwiftDataHostRepository` projects `PersistentHost` and `PersistentHostGroup` into `HostLibrarySnapshot` values and publishes revisioned `AsyncStream` changes. Host upserts update or insert the row, then use one commit path that advances a database revision, records Vault mutation information, saves, and only then publishes the mutation. On failure it rolls the `ModelContext` back.
Deletion is a durable saga, not an immediate blind removal: `requestHostDeletion` atomically writes a pending-deletion marker, outbox jobs, and the revision. The snapshot hides marked hosts. Later steps remove dependent jump/snippet/history/forwarding references and finally remove host-owned identities, the host, and the marker. This lets a crash expose either the live host or a complete, resumable deletion intent rather than a partial state.
Agent conversations use a separate SwiftData repository with similarly deliberate projections. `SwiftDataAgentRunRepository` stores run snapshots, messages, context/replay backing, tool invocations/results, reviews, compactions, and ordering. It writes only new message IDs rather than duplicating replayed earlier turns, sanitizes persisted text and tool-call JSON, and marks nonterminal runs interrupted when the repository is initialized. Loading orders transcript rows by run and sequence, then restores recorded tool results that were committed before the next transcript snapshot.
## Schema evolution: preserve the past exactly
Historical SwiftData model shapes are deliberately frozen. A `VersionedSchema` hashes the types it names, so retroactively editing a type used by an already shipped schema can make an installed store unopenable rather than migrated. The migration plan therefore retains every schema from V1 through V30 and stages each adjacent migration. When a persisted shape changes, introduce a version-specific model and replace it only in the new schema; do not “clean up” an old model definition.
Examples show why this matters:
- V1–V6 identity and SSH-key shapes remain represented by frozen types so their fields and defaults retain the historical schema checksum.
- V11’s provider model remains frozen while V12 changes address representation; legacy columns in the live provider model are folded on read to preserve the former endpoint behavior.
- V30 removes the obsolete persisted Known Host mismatch flag by replacing the V29 known-host model, while retaining hostname, port, algorithm, fingerprint, and date.
`PersistenceCompatibilityTests` opens original V1 and V14 fixture stores and verifies their data survives; it also checks a file store can reopen, that in-memory containers use the full schema but remain independent, and that representative version upgrades retain data while giving new fields their intended defaults. Treat these compatibility fixtures as a release contract when changing entities, defaults, migration stages, or storage enum raw values.
## Secret references, not secret persistence
A durable identity, SSH key, AI provider, or MCP record may contain `credentialRef` plus public/configuration metadata, but not the credential plaintext. The `SecretStoring` port separates string passwords from stored SSH-key credentials and resolves them by reference plus device/iCloud storage selection. Its runtime extensions turn fetched values into `SSHSecret` or `SSHResolvedKeyCredential`; `InMemorySecretStore` exists for tests and injected configurations, while app composition supplies Keychain storage.
AI secrets apply the same rule with an extra migration-location record. `PersistentAISecretLocation` stores only a reference, whether its secret is in iCloud, and a deletion marker. `AISecretStore` accepts only nonempty `termind.ai.` references; reads return no secret for pending deletions and otherwise ask Keychain directly. It never writes secret bytes to SwiftData.
For new AI secrets, iCloud use requires coordinator authorization plus both master iCloud and Settings-sync switches. A successful migration first writes and verifies the iCloud Keychain value, records `usesICloud`, then removes the device copy. Once a reference has migrated, later writes remain in iCloud even if the switches are disabled. Remote reference metadata marks the location as iCloud without treating an old device copy as authoritative. Deletion persists `pendingDeletion` before Keychain removal and retains that tombstone so delayed Keychain delivery cannot resurrect a secret.
## Runtime-only authentication material
A session receives resolved credentials, not a database record. `SSHCredentials` wraps password, private-key, and passphrase values in `SSHSecret`; `SSHConnectionConfiguration.clearSecrets()` clears target credentials, proxy secret, and jump-hop secrets while preserving non-secret network data and `SSHAuthenticationReference` provenance. The provenance contains IDs, username, and capability flags so later connections can re-resolve current Keychain material, but it does not retain a plaintext password or key.
`SSHSecret` owns a single non-copy-on-write byte allocation shared by its copies. It clears source `Data` when taking ownership, exposes its NUL-terminated bytes once through `withUnsafeCStringAndConsume`, wipes/deallocates the allocation before return, and rejects a second consumption. Explicit clearing is idempotent. Interaction-forbidden connection requests additionally replace credentials that require a passphrase or user-presence authorization with `interactionRequired`, so silent auxiliary work cannot prompt for or consume protected authentication material.
A successful saved-secret read used to prepare an actual connection updates an identity’s local `lastUsedAt`; availability checks and missing reads do not. Route preparation batches target, jump, and proxy identity usage into one persistence update, and failed usage persistence rolls the local update back so it can be retried. This is intentionally usage metadata, not authentication success and not a secret cache.
## GRDB Hermes Memory is a separate durable store
Hermes Memory does not share the SwiftData database. `GRDBMemoryStore` is an actor that lazily creates and exclusively owns a `memory.sqlite` queue and its directory, so constructing a disabled memory feature does no filesystem work. On first access it enables WAL and applies the `hermes-v1` migration, which creates memory state, frozen conversation snapshots, review checkpoints, session/message history, an FTS5 index, triggers, and an ordering index.
Memory updates run in database writes. A review is accepted only when its expected base `AgentMemoryState` still matches; otherwise it returns `nil` without recording the review. History replacement deletes no-longer-present sessions and only stores user, assistant, and tool messages after visible-text/JSON redaction. Search uses trigram FTS for queries of at least three Unicode scalars and a case-insensitive fallback for shorter queries. `close()` releases the queue; `destroy()` closes it first and removes the entire owned directory.
The focused Hermes tests prove disabled memory creates no files, snapshots survive a close/reopen, stale background reviews cannot overwrite foreground changes, indexed history is searchable and removed with history replacement, and destroy revokes old access before a later enable can backfill retained conversation history.
## Change checklist
1. **Adding SwiftData data:** put the `@Model` in `TermindPersistence`, add it to the current schema, decide whether a new frozen schema/version and migration stage are required, and extend compatibility coverage.
2. **Changing an existing persisted shape:** preserve the old type and semantics; add a new version-specific model rather than editing a historical type. Test an actual prior store or fixture, including defaults and removed fields.
3. **Adding a repository mutation:** project persistent rows to application values, save related durable state atomically, roll back on failure, and publish observations only after a successful save.
4. **Adding a credential:** persist only a stable reference and non-secret provenance. Use `SecretStoring`/Keychain for material; exclude it from logs, CloudKit/sync records, `UserDefaults`, SwiftData/GRDB ordinary records, and reusable session snapshots.
5. **Passing a secret to transport:** use the runtime secret owner, clear it at every success, error, cancellation, and teardown boundary, and retain only non-secret identifiers when a reconnectable configuration is needed.
@@ -0,0 +1,144 @@
---
type: "Reference"
title: "Remote services and forwarding"
openwiki_generated: true
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-ca49232858afa421bf33a03b
resource: repo://Frameworks/TermindApplication/Metrics/ServerMetricsModel.swift
- id: openwiki-source-21096ca5afd2c8baca7c623c
resource: repo://Frameworks/TermindDomain/Connections/PortForwardingRule.swift
- id: openwiki-source-89716908f306ca7371832cce
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/PortForwardingController.swift
- id: openwiki-source-20118197848107cfa8e87aa9
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHForwardingConnectionPool.swift
- id: openwiki-source-d371db64770fd2fcc301086b
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHMaxSessionsPolicy.swift
- id: openwiki-source-600c0f7b9ebcdcb58b4a0d05
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHMetricsSampler.swift
- id: openwiki-source-8c4abf5c09db535e2818e3c4
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift
- id: openwiki-source-52a93fdcfe9295de26f2b72d
resource: repo://FrameworkTests/SSHMetricsSamplerTests.swift
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-7468ad597251e97aa63a1c55
resource: repo://TFMTests/PortForwardingReconnectTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
SSH is a shared transport substrate, not a single shared runtime. Terminal sessions, Metrics, port forwarding, SFTP, and Agent work can all use SSH, but each feature owns its own intent, connection lifetime, interaction surface, and recovery policy. In particular, a live authentication result or a forwarding listener is memory-only: it is not restored from saved Host or forwarding-rule data. See [SSH session lifecycle](/openwiki/workflows/ssh-session-lifecycle.md) for the general connection journey and [Agent runtime and assistant](/openwiki/concepts/agent-runtime-and-assistant.md) for Agent-specific transport ownership.
## Service boundaries
| Service | Primary owner and connection shape | Interactive behavior | What it does not inherit |
| --- | --- | --- | --- |
| Interactive terminal | `SSHPTYChannel` opens a PTY and shell on its own authenticated connection. | Its connection journey may obtain trust, credentials, and keyboard-interactive answers. | It does not make those answers durable for later physical connections. |
| Metrics | `ServerMetricsModel` runs one serial worker per selected Host; `SSHMetricsSampler` performs bounded SSH exec requests. | Metrics owns its own `ConnectionJourney`, host-key authorization, and authentication queue. | It does not start a terminal shell or use terminal environment variables/startup snippets. |
| Port forwarding | `PortForwardingController` shares a host-scoped forwarding transport among explicitly started rules; it optionally creates an `SSHForwardingConnectionPool`. | The first open can present the forwarding Journey. Recovery and auxiliary opens forbid interaction. | It does not persist a connected transport, listener, temporary password, passphrase, or once-only trust decision. |
| Agent SSH/SFTP | Agent SSH and primary Agent SFTP share an Agent-owned pooled Host transport and fair libssh2 owner. | Agent interactions use Agent queues, not a terminal or forwarding prompt. | It is not a forwarding pool or an interactive PTY session. |
A `PortForwardingRule` is a portable saved description, not a listener. It identifies a Host and has `local`, `remote`, or `dynamic` (SOCKS5) kind, bind address/port, optional target address/port, label, and color. Dynamic rules deliberately erase target fields; a valid rule needs a nonblank bind host and port in `1...65_535`, while local/remote rules also require a nonblank target and valid target port. Rules remain independent of Host renames, but Host deletion removes its rules.
## Interactive terminal channels
`SSHPTYChannel` authenticates a connection, acquires a session-channel lease, opens a libssh2 `session` channel, requests an `xterm-256color` PTY, and then starts the remote shell. It owns terminal dimensions, byte conversion, output, and teardown. An SSH channel budget is therefore per physical SSH connection, rather than a process-wide limit.
`SSHMaxSessionsPolicy` supplies that per-connection `SSHChannelBudget` from the configured ceiling (default 10, valid range 1–100). PTY, exec, and multiplexed SFTP subsystem channels acquire FIFO leases from the same budget on a connection. A policy update changes live budgets and admits queued work when capacity permits; reducing the limit does not revoke active leases. Cancelling a queued request or closing the budget resumes it with cancellation. Direct/forwarded TCP channels, remote listeners, and jump bridges are forwarding mechanics, so they do **not** consume this OpenSSH-style session budget.
```mermaid
flowchart TD
Policy["SSHMaxSessionsPolicy"] --> Budget["Per connection FIFO channel budget"]
Pty["PTY shell"] --> Budget
Exec["Exec command"] --> Budget
Sftp["Multiplexed SFTP subsystem"] --> Budget
Budget --> Lease["Channel lease"]
Lease --> Open["Open session channel"]
Tcp["Forwarded TCP and listeners"] -. "excluded" .-> Open
```
This diagram shows admission of SSH session channels; forwarding traffic bypasses the session-channel budget.
### Shell-only setup
Host environment variables are encoded using the connection charset and sent as SSH environment requests **after** the PTY request and **before** the shell starts. A server denial of an individual variable is non-fatal and reports only its name through the rejection handler; another environment-request error fails the connection. This behavior is intentionally PTY-only: exec, SFTP, Metrics, Agent, and forwarding channels do not inherit these values.
Shell integration is likewise a terminal concern. When enabled, the PTY channel queues `RemoteShellIntegrationBootstrap.startCommand` after shell startup. Its state machine suppresses its probe/install exchanges from terminal output where possible, preserves ordinary banner/prompt output, and becomes non-blocking if the remote probe is late or the user types. It is not a generic SSH bootstrap mechanism and must not be added to metrics, forwarding, Agent, or SFTP routes.
## Metrics: bounded exec sampling, not a login shell
`ServerMetricsModel` stores the selected metric cards and runs a detached serial worker for each enabled SSH Host. The worker resolves an SSH connection preparation with challenge-capable trust and keyboard-interactive handlers, connects a newly made sampler, then samples on a roughly two-second cadence. It publishes the base point first; GPU, filesystem, and process details are optional follow-up work. Filesystems are refreshed only while a detail view is observed and no more often than 30 seconds. On failure it disconnects and retries with exponential delays from 2 seconds to a 60-second cap; cancellation, disabled selection, sleep, stopped model, or a changed generation retires the work.
`SSHMetricsSampler` wraps its connection in `SSHExclusiveConnectionAdapter`, so its commands have exclusive use of that sampler connection. It uses bounded exec calls rather than a PTY: the primary Linux probe has an 8-second timeout and 256 KiB payload limit; filesystem and process probes use 5 seconds with 512 KiB and 1 MiB limits respectively. It recognizes exit status `42` as unsupported primary metrics and recognizes `42` or NVIDIA's `6` as no GPU; other nonzero, truncated, malformed, or oversized output is a read failure.
Remote shells can emit banners, OSC sequences, or exit-hook text around an exec command. The sampler wraps every command in `__TERMIND_METRICS_BEGIN__` and `__TERMIND_METRICS_END__` markers, parses only the enclosed payload, and permits a small framing allowance beyond the payload limit. Invalid primary-sample diagnostics redact the address section before logging and record sizes rather than treating raw remote output as safe telemetry.
Focused tests in `FrameworkTests/SSHMetricsSamplerTests.swift` verify that framing ignores shell preamble/trailer, that absent/truncated/oversized frames fail, and that unsupported/GPU exit codes retain their special meanings.
## Forwarding: explicit intent and host-scoped runtime
A rule runs only after `PortForwardingController.start(_:)` validates the rule and confirms SSH is enabled for its Host. The controller creates or joins one `PortForwardingConnection` for that Host and route, snapshots the selected pool limit at that first start, and gives all active rules on that context the same Journey/authentication surface. Starting a later rule on an already connected context installs only that rule. Stopping one rule unregisters it without disturbing peers; the final stop retires the context and its transport.
The visible rule state moves through `stopped`, preparation/trust/authentication/connecting stages, `starting`, `running`, reconnecting, or `failed`. Each rule start has a generation, and callbacks must match both the current context and generation. This rejects stale connection counts, delayed listener creation, and late open success after stop/restart or configuration retirement.
```mermaid
stateDiagram-v2
[*] --> Stopped
Stopped --> Preparing: explicit Start
Preparing --> AwaitingTrust: host key needed
Preparing --> AwaitingAuth: credential needed
AwaitingTrust --> Connecting: approved
AwaitingAuth --> Connecting: submitted
Preparing --> Connecting: prepared
Connecting --> Starting: SSH connected
Starting --> Running: listener or rule installed
Running --> Reconnecting: transport loss
Reconnecting --> Running: silent recovery
Reconnecting --> Failed: interaction required
Failed --> Preparing: explicit Retry
Preparing --> Stopped: Stop or invalidation
Connecting --> Stopped: Stop or invalidation
Starting --> Stopped: Stop or invalidation
Running --> Stopped: last rule stopped
Reconnecting --> Stopped: Stop or invalidation
```
This is the controller-facing forwarding lifecycle; a shared Host context can carry several rule generations concurrently.
### Connection pool and dispatch
On macOS, a Host-configured forwarding maximum is normalized to 1–64 (default 1). With more than one requested connection, `PortForwardingController` selects `SSHForwardingConnectionPool`; otherwise it uses one `SSHForwardingConnection`. iOS can preserve the synced Host setting but runs one forwarding connection. The pool always opens a primary connection first. Only local and dynamic rules need the fan-out pool: they register with every healthy slot but keep one pool-level local listener per rule. Accepted sockets are assigned to an eligible slot with the fewest flows for that rule, breaking ties round-robin. A remote rule stays on the primary worker, so remote forwarding remains single-worker.
After the primary opens, the controller supplies an additional-connection request resolver and the pool fills missing auxiliary slots. It limits simultaneous opening/installing work to four. A new slot installs every non-remote registration before becoming eligible; if setup fails it is disconnected rather than published. Losing an auxiliary schedules retry after 1, 2, 5, 10, then 30 seconds; a slot stable for 60 seconds resets this retry progression. Interaction-required, host-trust, credential, or cancellation failures require manual action instead of an automatic auxiliary retry, leaving the pool below target. If the primary fails, the pool promotes an existing slot and recreates remote rules there when possible; with no replacement it reports failure.
```mermaid
flowchart TD
Start["Explicit rule start"] --> Primary["Open primary SSH connection"]
Primary --> Kind{"Rule kind"}
Kind -->|"remote"| Remote["Start remote listener on primary"]
Kind -->|"local or dynamic"| Register["Register rule on healthy slots"]
Register --> Listener["One pool local listener"]
Listener --> Accept["Accept TCP flow"]
Accept --> Choose["Choose least loaded eligible slot"]
Choose --> Pump["Open forwarded channel and pump flow"]
Register --> Fill["Open auxiliary slots up to target"]
Fill --> Install["Install existing shared rules"]
Install --> Register
Fill --> Retry["Retry transient loss with capped backoff"]
```
This diagram shows pool fan-out only for local and dynamic forwarding; a remote listener does not fan out.
The first physical connection may use the forwarding Journey to collect host-key approval, credentials, or keyboard-interactive answers. Its recovery and every auxiliary connection are silent opens with interaction forbidden. Their reusable snapshot keeps route/network and identity references, not temporary passwords or passphrases. A remembered host key can permit recovery, but “continue once” trust cannot. If a silent open needs interaction, recovery fails/degrades rather than showing a form; an explicit Retry starts a new interactive Journey. Existing TCP streams are never migrated or replayed to a replacement worker.
A route/Host configuration edit, deleted/replaced rule, or explicit stop invalidates the relevant runtime. Cleanup cancels retry/open work, stops listeners before closing transports, and waits for cleanup where needed so an old bind cannot race a replacement. Local/dynamic listeners use `SO_REUSEADDR` to tolerate `TIME_WAIT`, not `SO_REUSEPORT` or live shared binds.
## Operational and change guidance
- Treat port-forwarding maximum connections as a throughput/concurrency control, not a universal latency improvement. The historical benchmark report documents loopback results and limits, and explicitly keeps remote forwarding single-worker: [Memory/PORT_FORWARDING_PERFORMANCE.md](repo://Memory/PORT_FORWARDING_PERFORMANCE.md).
- Preserve readiness-driven, bounded forwarding I/O. The forwarding transport uses immutable queues and socket readiness; plaintext queues pause at 2 MiB per direction/flow and resume below 1 MiB, while encrypted output is bounded per SSH session. These are per-flow/session guardrails, not a global process memory cap.
- Do not merge service lifetimes merely because they share SSH primitives. A forwarding listener/pool, a terminal PTY, a metrics sampler, and Agent transport have different owners and retry/authentication boundaries.
- Test lifecycle changes with the focused forwarding suites. `TFMTests/PortForwardingReconnectTests.swift` covers shared-context reconnect, capped backoff, generation rejection, silent recovery, remembered versus temporary trust, and cleanup ordering. `TFMTests/PortForwardingFeatureTests.swift` covers rule normalization/validation, Host-route constraints, deletion cleanup, persistence behavior, and command rendering.
+16
View File
@@ -0,0 +1,16 @@
---
okf_version: "0.2"
---
# Files
- [Termind Engineering Quickstart](quickstart.md) - A task-oriented guide to finding the right Termind owner, lifecycle boundary, workflow documentation, and focused validation before making a change.
# Directories
- [architecture](architecture/)
- [concepts](concepts/)
- [integrations](integrations/)
- [operations](operations/)
- [testing](testing/)
- [workflows](workflows/)
+3
View File
@@ -0,0 +1,3 @@
# Files
- [MCP Server, Transfer APIs, and Stdio Bridge](mcp-server-and-bridge.md) - How the macOS-only Termind MCP listener authenticates local clients, executes host tools through external UI authentication, and provides scoped HTTP SFTP transfers. Covers the bundled termind-mcp stdio bridge and MCP session lifecycle.
@@ -0,0 +1,194 @@
---
type: integration guide
title: MCP Server, Transfer APIs, and Stdio Bridge
description: How the macOS-only Termind MCP listener authenticates local clients, executes host tools through external UI authentication, and provides scoped HTTP SFTP transfers. Covers the bundled termind-mcp stdio bridge and MCP session lifecycle.
tags: [mcp, macos, loopback, authentication, sftp, bridge]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-1fc00d0407016efa5a0378eb
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSSHTools.swift
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-a62bfbbc7de13a894444718b
resource: repo://TermindMCPBridge/main.swift
- id: openwiki-source-b8fca76c89564e16eccfbb53
resource: repo://TFM/App/MCPServerController.swift
- id: openwiki-source-76b1cdca4a02038756187f92
resource: repo://TFM/Application/MCPServer/MCPServerTools.swift
- id: openwiki-source-d485ebb339c77875a3b2701e
resource: repo://TFM/Features/ExternalRequests/ExternalAuthCoordinator.swift
- id: openwiki-source-ef4c6426a19087a6c49e4841
resource: repo://TFM/Features/Settings/MCPClientSetupCommand.swift
- id: openwiki-source-26497da8830feaa637835d00
resource: repo://TFM/Infrastructure/MCP/MCPServerProtocol.swift
- id: openwiki-source-9d465cf017037915bf209e49
resource: repo://TFM/Infrastructure/Networking/LoopbackHTTPServer.swift
- id: openwiki-source-a0f4f642e37695357bc9150d
resource: repo://TFM/Infrastructure/Security/MCPServerTokenStore.swift
- id: openwiki-source-4cacabcabe7b6b079746d10e
resource: repo://TFMTests/LoopbackHTTPServerTests.swift
- id: openwiki-source-b466ff39828d4aa83b5bcd74
resource: repo://TFMTests/MCPClientSetupCommandTests.swift
- id: openwiki-source-3a14ee4cab03c2311718178e
resource: repo://TFMTests/MCPDownloadTests.swift
- id: openwiki-source-68b561c9d2ab2d5950aafbb2
resource: repo://TFMTests/MCPServerSessionTests.swift
- id: openwiki-source-b59748ce00aec28962cc3761
resource: repo://TFMTests/MCPServerTokenStoreTests.swift
- id: openwiki-source-8d265a8732f0af93c5d4e274
resource: repo://TFMTests/MCPServerToolsTests.swift
- id: openwiki-source-ab28127e1f3476825a1e3482
resource: repo://TFMTests/MCPTransferTicketTests.swift
- id: openwiki-source-47dc468698b2904f0004ee04
resource: repo://TFMTests/MCPUploadTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# MCP Server, Transfer APIs, and Stdio Bridge
Termind’s built-in MCP endpoint is a **macOS-only, local integration boundary**. The desktop app owns the listener, the tool registry, external authentication UI, audit trail, and transfer lifecycle; an MCP client supplies JSON-RPC requests. The listener accepts only loopback connections and authenticates normal MCP traffic with a device-local Bearer token. It is not a remote-access server and iOS does not start a local MCP listener.
The endpoint is normally `http://127.0.0.1:7391/mcp`, but the port is configurable. The server is off by default and requires the MCP Server Pro entitlement to enable, configure, rotate its token, or change exported tools.
## Components and ownership
| Component | Responsibility |
| --- | --- |
| `MCPServerController` | Desktop lifecycle, settings, Pro gating, device token, port restarts, status/client count, and attaching HTTP/protocol/transfer handlers. |
| `LoopbackHTTPServer` | TCP listener on `127.0.0.1` and `::1`, Bearer and Origin checks, bounded ordinary request handling, and byte-route dispatch. |
| `MCPServerProtocol` | Streamable HTTP JSON-RPC sessions, legacy SSE compatibility, protocol negotiation, tool discovery and invocation. |
| `MCPServerTools` | Deliberately limited external tool registry, executor, audit registration, per-session secret broker, external authentication routing, and transfer coordinators. |
| `ExternalAuthCoordinator` | Queues UI-mediated SSH login, host-key confirmation, and secret requests separately from Termind-origin authentication. |
| `MCPUploadCoordinator` / `MCPDownloadCoordinator` | Issue and track distinct, scoped byte-transfer capabilities rather than placing file contents in MCP JSON-RPC. |
| `termind-mcp` | A separate macOS executable that translates newline-delimited JSON-RPC on stdin/stdout to the loopback HTTP session protocol. |
This division keeps AgentKit’s execution machinery from becoming the network or UI owner: Termind injects its host resolver, pooled SSH/SFTP connections, authentication registry, background commands, metrics reader, and audit model.
## Startup, gating, and token operations
`MCPServerController` reads enabled state, port, and disabled-tool names from `UserDefaults`; disabled names are intersected with the known export set. Enabling, choosing a port, changing a tool, and rotating a token request Pro access. Startup refuses to run without both entitlement and a usable token, configures transfer URLs with the selected port, then starts the HTTP server. A port change restarts the listener. Loss of Pro access stops it; returning access resumes it only when the user had enabled it.
The long-lived server token is generated from 32 secure random bytes and encoded as URL-safe Base64. It is stored only in this-device Keychain storage. Older iCloud-stored values are migrated only after a verified local copy exists, then the cloud copy is removed; a failed migration remains retryable rather than silently losing the credential.
**Rotation is a revocation event, not just a preference update.** The controller stops transfers and all MCP sessions, replaces the HTTP token, and disconnects existing HTTP connections. Clients must update their configuration with the new token; a token/port change invalidates copied setup commands.
## Listener security boundary
`LoopbackHTTPServer` creates listeners specifically bound to IPv4 loopback (`127.0.0.1`) and IPv6 loopback (`::1`) with `acceptLocalOnly`; it does not bind an externally reachable interface. It limits connections to 64, headers to 64 KiB, and ordinary MCP request bodies to 4 MiB. Normal routes require `Authorization: Bearer <server-token>` and compare token bytes in constant time.
If an `Origin` header is present, it must be a bare HTTP(S) loopback origin: `localhost`, `::1`, or a `127.x.x.x` address. Clients without `Origin` remain supported. Unauthenticated/invalid-origin requests are closed after their response so an unconsumed body cannot be reused on a persistent connection.
The two file byte routes are intentionally different:
* `/uploads/<id>` and `/downloads/<id>` do **not** accept the long-lived MCP token. They are authorized by a per-transfer capability in the `Authorization` header.
* Upload authorization and atomic claim occur before the body is drained; download handling receives a cancellation token tied to the TCP connection.
* Capability values are not query parameters, and a browser `Origin` must pass the loopback rule.
## MCP session request handling
The primary transport is streamable HTTP: clients `POST` JSON-RPC 2.0 to `/mcp`. `initialize` creates an independent session, returns `Mcp-Session-Id`, and negotiates the supported streamable protocol version. Thereafter the client must send both that session header and the exact negotiated `MCP-Protocol-Version`. `notifications/initialized` enables tool listing and calls. Notifications receive `202`; malformed JSON-RPC and invalid call parameters receive protocol errors.
```mermaid
sequenceDiagram
participant Client
participant HTTP as Loopback HTTP
participant Protocol as MCP protocol
participant Tools as MCP tools
participant Auth as External auth UI
Client->>HTTP: POST /mcp with Bearer token
HTTP->>HTTP: verify token and loopback Origin
HTTP->>Protocol: forward bounded JSON request
Protocol->>Protocol: initialize or validate session and version
Protocol->>Tools: list descriptors or call enabled tool
opt SSH, host key, or command secret needed
Tools->>Auth: enqueue request for client and session
Auth-->>Tools: user response or cancellation
end
Tools-->>Protocol: tool result and audit metadata
Protocol-->>HTTP: JSON-RPC response and session header
HTTP-->>Client: HTTP response
```
This shows the normal streamable MCP request path. Authentication is routed to the local Termind UI rather than returned as an interactive protocol prompt.
There is also a legacy compatibility transport: `GET /sse` opens an SSE stream and emits an endpoint event for `/messages?sessionId=...`; clients post messages there and receive responses as SSE messages. `GET /mcp` is deliberately rejected because streamable HTTP does not expose a standalone SSE stream.
A session owns a UUID run ID and a `SecretBroker`. The protocol supports at most 64 sessions, sweeps idle sessions after 30 minutes, and reports client count to the UI. A session with active transfer work is retained rather than expired. Explicit `DELETE /mcp`, listener stop, token rotation, or expiry finishes legacy streams, cancels session copies/transfers and external prompts, unregisters audit state, and discards all brokered secrets.
## Tools, policy, and external authentication
The exposed registry is an allowlist—not the complete AgentKit catalog. It includes host discovery and cached metrics; `request_user_secret`; `ssh_exec` and `ssh_wait`; ordinary SFTP inspection/mutation/copy operations; and upload/download ticket/status tools. Scratch workspaces and generic fetch tools are intentionally excluded because an external MCP client has no Termind conversation backing them.
Disabled tools are removed from discovery **and** invocation, not merely hidden. Changing a tool switch rebuilds the registry immediately; `sftp_upload` and `sftp_download` also enable or revoke their directional transfer coordinators. This makes disabling a transfer direction revoke existing tickets rather than allowing old URLs to revive after re-enablement.
Calls execute with `permissionMode: .fullAccess`, but this is not a bypass of system safety boundaries: tool schemas, path validation, host key checks, SSH/SFTP authentication, secret bindings, and capability rules still apply. The MCP executor uses an approval broker whose manual fallback denies external calls; individual tool preflight policy still classifies safe/read-only versus changing operations.
When SSH credentials, keyboard-interactive answers, host-key trust, or a command’s secret stdin are needed, the tool creates a request in `ExternalAuthCoordinator`. Its handler is labeled with the MCP client name and session run ID and presents through the desktop UI. External requests are queued and independently cancelable by session; stopping MCP cancels external requests while preserving app-origin authentication requests. This is a critical boundary: `request_user_secret` is for secret standard input to `ssh_exec`, not SSH login. It returns only a one-shot handle bound to the session, host, tool, and stated purpose—never plaintext to the MCP client.
Tool audit records are registered per MCP session. The UI can show client, tool, host, summarized arguments, duration and byte counts, but deliberately excludes file bodies, stdin, stdout, and stderr.
## Capability-based SFTP transfers
Large or binary data does not travel in the 4 MiB MCP body. An MCP call creates a transfer ticket and returns a loopback URL, method, scoped Bearer capability, and identifier; status is queried using the ticket ID through MCP. Ticket creation itself does not open SSH, local files, or the remote source.
Upload and download are separate state machines and separate capabilities, even though they share a global budget of four active slots. Each ticket is bound to the creating MCP session/run, host, remote path, direction and intent; its 256-bit token expires after ten minutes. Waiting and paused tickets expire, while active work is allowed to finish. Each direction permits up to 64 unfinished tickets, retains up to 256 terminal records for 30 minutes, and terminal status remains queryable during that retention interval. Host/session revocation, server stop, token rotation, or disabling the matching direction cancels/revokes work.
### Upload: `sftp_upload` then `PUT /uploads/<id>`
The upload ticket binds the expected byte count, SHA-256 digest, target path, and overwrite intent. The byte route accepts only its capability and required binary request shape, claims the ticket atomically, and streams with backpressure into a dedicated SFTP operation—no scratch workspace or whole-file staging. The remote write commits only after exact length and incremental digest verification. A duplicate/parallel claim cannot replay committed bytes.
Interrupted uploads can resume only from the coordinator’s acknowledged remote offset. The client must provide matching `Upload-Offset` and suffix `Content-Length`; the remote prefix is verified before continuation. Digest mismatch, truncation, cancellation, or cleanup failure does not publish a successful remote file. The status may report a possible temporary remote path if cleanup fails. Uploads never overwrite directories; `overwrite` is only meaningful for an existing regular file.
### Download: `sftp_download` then `GET /downloads/<id>`
Creating a download ticket performs no remote I/O. On GET, the coordinator accepts regular files only, opens a dedicated SFTP stream, fixes the length, and returns binary bytes without local staging. It does not support `HEAD`, body/query credentials, or arbitrary ranges. A client may use one `Range: bytes=N-` continuation from its saved length; invalid range returns `416` without consuming a waiting ticket, and a resume verifies the existing prefix and source metadata before headers.
The server pulls no more than 64 KiB per send and revalidates bytes, size, and modification state at EOF. Success requires source validation, completion of the HTTP send, checked remote close, and lease release. A failure before headers is safe JSON; after headers the connection closes without appending JSON to binary content. Consequently, clients must poll transfer status and verify their local size/hash—an HTTP `200` and `Content-Length` alone do not prove persistent success.
## The `termind-mcp` stdio bridge
Some MCP clients expect a stdio command rather than HTTP. The bundled `termind-mcp` executable is a protocol forwarder only: it does not expose another listener or implement Termind tools. It reads one JSON-RPC object per stdin line, sends its original bytes to the configured loopback URL as HTTP POST, and writes each JSON response as one stdout line. Diagnostics go to stderr.
By default it uses `TERMIND_MCP_URL` or `http://127.0.0.1:7391/mcp`, and requires `TERMIND_MCP_TOKEN`; `--url` and `--token` override those values. Invalid stdin lines are ignored with an error on stderr. For HTTP failure or reachability failure, requests with an `id` receive a JSON-RPC `-32000` error; notifications produce only stderr diagnostics. On EOF, it best-effort sends `DELETE` with the established session ID.
```mermaid
sequenceDiagram
participant Client
participant Bridge as termind-mcp
participant HTTP as Loopback HTTP
participant Protocol as MCP protocol
Client->>Bridge: JSON-RPC initialize on stdin
Bridge->>HTTP: POST with Bearer token and JSON body
HTTP->>Protocol: initialize request
Protocol-->>HTTP: session ID and protocol version
HTTP-->>Bridge: HTTP response with Mcp-Session-Id
Bridge-->>Client: JSON-RPC response on stdout
Client->>Bridge: subsequent JSON-RPC line
Bridge->>HTTP: POST with session ID and version headers
HTTP->>Protocol: dispatch request
Protocol-->>HTTP: JSON-RPC result
HTTP-->>Bridge: HTTP response
Bridge-->>Client: JSON-RPC response line
Client-->>Bridge: stdin EOF
Bridge->>HTTP: DELETE with session ID
```
This shows bridge-side negotiation: it captures `Mcp-Session-Id` from the initialize response and `protocolVersion` from its result, then supplies both on subsequent requests. It uses an ephemeral `URLSession` and is not a credential store.
For direct HTTP clients, settings generates quoted setup commands for Claude Code, GitHub Copilot CLI, and OpenClaw. Codex and Hermes use the bridge and pass the URL/token through environment variables. Missing token disables all generated commands; missing bundled bridge disables only those bridge-based registrations.
## Operations and focused verification
* Enable the server in macOS settings only after Pro access is available, generate or rotate a token, then copy a client registration command. Treat that token like a local credential and update every client after rotation, port change, or moving the app when using the bridge.
* Use the server status and connected-client count to distinguish stopped, starting, ready, and failed listener state. Listener failures stop transfers; invalid port/token storage disables activation rather than exposing a partially configured server.
* To immediately cut off an external client, disable the server or rotate its token. To reduce surface area, disable individual tools; disabling either transfer tool revokes its tickets.
* Test changes at the correct seam: `MCPServerSessionTests` exercises initialization, version/session requirements, tool discovery, legacy SSE, and deletion cancellation; `MCPServerToolsTests` verifies allowlisting, disabled tools, session-bound secrets, and ticket creation; `MCPUploadTests` and `MCPDownloadTests` cover resume, claim, digest, cancellation, status, and wire behavior; `MCPClientSetupCommandTests` checks exact, shell-safe client registration arguments.
## Related pages
* [Agent runtime and assistant](/openwiki/concepts/agent-runtime-and-assistant.md) — tool execution, approval, and secret-handle semantics.
* [Persistence and secrets](/openwiki/concepts/persistence-and-secrets.md) — Keychain and local-secret ownership.
* [SFTP transfer and external edit](/openwiki/workflows/sftp-transfer-and-external-edit.md) — shared SFTP channel and transfer behavior.
* [SSH session lifecycle](/openwiki/workflows/ssh-session-lifecycle.md) — SSH authentication, trust, and pooled connection lifecycle.
@@ -0,0 +1,190 @@
---
type: release operations
title: Build, Validation, Localization, and Dependency Release Operations
description: Safe, targeted validation and release procedures for Termind’s Xcode targets, localization catalogs, screenshots, Astro landing page, and pinned AgentKit dependency.
tags: [operations, build, testing, localization, release, agentkit, screenshots]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-ea70eb6c045047448e446296
resource: repo://.gitignore
- id: openwiki-source-a2cca747926cafc62fde5fb2
resource: repo://.swift-format
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
- id: openwiki-source-103853faf6b28763354a1c79
resource: repo://LandingPage/package.json
- id: openwiki-source-c76cbada020604024adadb22
resource: repo://LandingPage/README.md
- id: openwiki-source-41a7ded3800c9422f058a3ef
resource: repo://Scripts/check-zh-localization.sh
- id: openwiki-source-6a4176e7d97bf05b3983882c
resource: repo://Scripts/run-mac-marketing-screenshots.sh
- id: openwiki-source-9621f35145a32a9f8391084b
resource: repo://Scripts/run-mobile-marketing-screenshots.sh
- id: openwiki-source-cd0be716a2446029f345525a
resource: repo://Termind.xcodeproj/project.pbxproj
- id: openwiki-source-105d05d558f14996921a83f6
resource: repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
- id: openwiki-source-793d7861000adc19f0c3df01
resource: repo://TFMTests/AppLanguageTests.swift
- id: openwiki-source-a08489338be00125d646c77e
resource: repo://TFMTests/VisibleWindowTestTrait.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# Build, Validation, Localization, and Dependency Release Operations
This page is the operational playbook for proving a change without accidentally changing the dependency graph or committing local artifacts. The repository has one Xcode project with the macOS `TFM` and iPhone/iPad `TFI` schemes, shared-framework tests in `FrameworkTests/`, and platform tests in `TFMTests/` and `TFITests/`. The Astro landing page is a separate Node workspace under `LandingPage/`.
Choose the narrowest quiet check that proves the changed behavior, then expand to the affected target or default suite before delivery. Preserve complete failure output: a green unrelated build is not evidence that the changed feature works.
## Baseline safety rules
- **Use the resolved package graph.** Every ordinary Xcode build, test, and screenshot build must retain `-onlyUsePackageVersionsFromResolvedFile`. Without it, Xcode may resolve newer dependencies instead of testing the revisions recorded in `Package.resolved`.
- **Keep artifacts and secrets local.** Never commit secrets, `.env` files, generated build products, `DerivedData/`, `.build/`, `build/`, `*.xcresult`, `LandingPage/dist/`, `node_modules/`, or user-specific Xcode state. These are ignored because they are machine- or run-specific, not release inputs.
- **Keep commits focused.** State the outcome, affected layers, and verification in the PR; include bilingual UI screenshots where the change calls for them. Run the Chinese localization check as part of every commit pipeline, including code-only changes.
- **Validate the owner boundary as well as behavior.** A dependency, persistence, or framework-ownership change should include the focused architecture boundary tests; platform/UI changes need the relevant platform target and feature tests.
## Native build and test entrypoints
Run commands from the repository root unless a command changes directory.
### Build the affected product
```sh
xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile build
```
This is the desktop build entrypoint and also builds the macOS app’s MCP bridge and resolved AgentKit dependency.
```sh
xcodebuild -project Termind.xcodeproj -scheme TFI -destination 'generic/platform=iOS Simulator' -onlyUsePackageVersionsFromResolvedFile build
```
This builds the mobile app and shared frameworks. For an iOS test run, replace the generic destination with an installed iPhone or iPad simulator destination.
### Test narrowly, then at the appropriate scope
The default macOS test entrypoint runs macOS and shared Swift tests:
```sh
xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test
```
Constrain a run when a focused suite directly establishes the changed contract, for example:
```sh
xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test -only-testing:TFMTests/AppLanguageTests
```
Use the matching mobile scheme and a concrete simulator for `TFITests` work. Typical focused choices are the test file that names the changed feature, `TFMTests/ArchitectureBoundaryTests.swift` for dependency placement, and `TFMTests/AppLanguageTests.swift` for language-selection/catalog behavior. Do not use an unrelated focused test as a substitute for the affected default suite.
### Formatting is a strict check
Swift formatting follows `.swift-format` (four-space indentation and 120-column lines). Lint all owned Swift production and test roots before delivery:
```sh
xcrun swift-format lint --strict --recursive Frameworks TFM TFI FrameworkTests TFMTests TFITests TermindMCPBridge
```
A companion change in AgentKit must also pass its equivalent command over `Sources Tests` from that repository.
## Window tests and screenshot operations
Most routine tests should remain headless. macOS tests that show windows or take focus explicitly use `.requiresVisibleWindow`; the trait enables them only when the test host sees `TERMIND_WINDOW_TESTS=1`. Xcode forwards `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` into that host environment.
Opt in only for the named rendering/interaction suite being investigated:
```sh
TEST_RUNNER_TERMIND_WINDOW_TESTS=1 xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test -only-testing:TFMTests/ChooserInteractionTests
```
In Xcode, set `TERMIND_WINDOW_TESTS=1` in the Test action environment. Existing screenshot tests may retain their own dedicated opt-in variables; offscreen layout and logic tests remain part of normal validation. This separation prevents a routine test run from activating the app, stealing focus, or becoming display-dependent.
For an isolated interactive desktop demo, use a supported scene and one of the three supported languages:
```sh
Scripts/run-screenshot-demo.sh <hosts|workspace|agent|command|metrics|metrics-detail|app-settings> <en|zh-Hans|zh-Hant>
```
The script uses a dedicated `.build/screenshot-demo` derived-data directory, builds `TFM` with the resolved-package flag, and launches a Debug app with matching Apple language and locale arguments. It is for inspection rather than a general regression test.
Marketing screenshots are controlled capture workflows, not ordinary test artifacts:
```sh
Scripts/run-mac-marketing-screenshots.sh
Scripts/run-mobile-marketing-screenshots.sh
```
The macOS script requires macOS 27.x, accepts constrained scene/locale environment selections, builds for testing with resolved packages, waits until the capture window is focused, verifies dimensions, and writes captures under `Marketing/Screenshots/Captures` while backing up prior images. The mobile script requires an iOS/iPadOS 27 runtime, builds once for testing from resolved packages, runs `MobileMarketingScreenshotTests` on the selected supported simulators for `en`, `zh-Hans`, and `zh-Hant`, and verifies its expected capture count. Treat output as a reviewed product asset: recapture the affected platform and locales after a captured UI change, and do not commit transient derived data.
## Localization gate
User-facing app text belongs in `Frameworks/Resources/Localizable.xcstrings`; bundle metadata belongs in `InfoPlist.xcstrings`. Any new or changed English string must ship with finished `zh-Hans` and `zh-Hant` translations in the same commit. Preserve format placeholders and Chinese punctuation conventions.
Run the catalog gate before committing; it requires `jq` and accepts an optional catalog path:
```sh
Scripts/check-zh-localization.sh
```
The script first validates the catalog as JSON. For each Chinese locale, it rejects absent localization entries, string units not marked `translated`, empty values except for the empty key, and invalid Han/Latin or punctuation spacing. It exits nonzero at the first category of failure, so fix the catalog rather than bypassing the check. Run `AppLanguageTests` when language behavior changes; those tests cover canonical language preferences and ensure Simplified and Traditional Chinese resolve independently.
AgentKit owns its separate runtime catalog at `../AgentKit/Localizations/Localizable.xcstrings`. After changing that catalog, run the package’s catalog build step because a plain Swift build copies its resources rather than compiling string catalogs:
```sh
../AgentKit/Scripts/build-localizations.sh
```
## Landing-page validation
`LandingPage/` is an independent private Astro package. Its production build runs both `astro check` and `astro build`, emitting output to `LandingPage/dist/`:
```sh
cd LandingPage && npm ci && npm run build
```
Use `npm ci` when reproducing the locked dependency graph; use `npm run dev` for local iteration. For website changes, visually check English and Chinese routes in addition to the build. The site keeps its screenshot inputs deliberately narrow: it imports an explicit allowlist of framed assets rather than copying full-resolution captures into `public/`. `dist/`, `.astro/`, and `node_modules/` are generated and must remain uncommitted.
## AgentKit: release, bump, and re-resolve
AgentKit is a separately developed, host-neutral remote Swift package. Termind’s project specifies an up-to-next-major minimum version, while `Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved` pins the actual build to a precise AgentKit tag and revision. Therefore Xcode builds the resolved remote release—not an uncommitted sibling `../AgentKit` working tree.
A cross-repository change has a strict three-step lifecycle:
```mermaid
flowchart TD
PackageChange["Implement and test AgentKit change"] --> Release["Tag and push AgentKit release"]
Release --> Bump["Bump AgentKit minimumVersion in project.pbxproj"]
Bump --> Resolve["Re-resolve and record tag revision in Package.resolved"]
Resolve --> AppCheck["Build and test Termind using resolved packages"]
```
This shows the required ordering from a host-neutral package change through Termind consumption.
1. **Release AgentKit first.** In `../AgentKit`, make the host-neutral change and validate it there:
```sh
cd ../AgentKit && swift build && swift test
```
Format its `Sources` and `Tests`, then tag and push the package release. Do not add Termind names, SSH/SFTP behavior, or UI to AgentKit; those stay on the Termind side of the integration boundary.
2. **Bump the app requirement.** Update AgentKit’s `minimumVersion` in `Termind.xcodeproj/project.pbxproj` to the released version.
3. **Re-resolve and commit the lock result.** Re-resolve Swift packages so `Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved` records the released version and exact revision. Commit both the project requirement and resolved file with the Termind-side code that requires them, then validate with the resolved-package build/test commands above.
Do not skip the release or resolve steps: a project-file bump alone does not establish the exact revision used in ordinary builds, and local sibling edits are invisible to that build. Likewise, do not casually refresh the lock file during unrelated work—the resolved graph is a reproducibility boundary.
## Release-oriented checklist
1. Identify the smallest affected product surface and run its focused tests.
2. Run the affected TFM or TFI build/test using `-onlyUsePackageVersionsFromResolvedFile`; include architecture tests for boundary changes.
3. Run strict Swift format lint for Swift changes.
4. Run `Scripts/check-zh-localization.sh` for every commit; complete both Chinese translations and run `AppLanguageTests` when localization behavior changes.
5. For landing-page changes, run `cd LandingPage && npm ci && npm run build` and inspect English/Chinese routes.
6. Run visible-window tests only with explicit opt-in and a narrow suite; regenerate marketing captures only through their dedicated scripts when product imagery changes.
7. For AgentKit work, complete release → minimum-version bump → re-resolve, and commit both dependency files.
8. Inspect the staged diff for secrets, local environment files, derived data, build output, and accidental lock/artifact churn before committing.
CloudKit production deployment and signed-device delivery are separate release evidence, not consequences of a successful local build. For the sync-specific deployment matrix and operational prerequisites, consult `Memory/SETTINGS_SYNC_RELEASE.md`.
+3
View File
@@ -0,0 +1,3 @@
# Files
- [Build, Validation, Localization, and Dependency Release Operations](build-test-and-release.md) - Safe, targeted validation and release procedures for Termind’s Xcode targets, localization catalogs, screenshots, Astro landing page, and pinned AgentKit dependency.
+90
View File
@@ -0,0 +1,90 @@
---
type: engineering quickstart
title: Termind Engineering Quickstart
description: A task-oriented guide to finding the right Termind owner, lifecycle boundary, workflow documentation, and focused validation before making a change.
tags: [engineering, architecture, routing, testing, macos, ios]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-cd0be716a2446029f345525a
resource: repo://Termind.xcodeproj/project.pbxproj
- id: openwiki-source-6c9f797fc6a1e7ce639b72b8
resource: repo://TFI/App/TermindIOSApp.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-d3d065330c730839f5cc6112
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# Termind Engineering Quickstart
Termind is one Xcode project with two native products: `TFM` for macOS and `TFI` for iPhone/iPad. They compose shared static frameworks, but platform UI and lifecycle remain app-owned. Start from the task you intend to change, identify the state and dependency owner, then use the focused tests that protect that boundary. Source and tests are authoritative; `Memory/ARCHITECTURE.md` records the current ownership and safety contracts to read before changing dependencies, lifetimes, persistence, execution, permissions, or secrets.
## Before editing
1. **Read the narrowest routing page below**, then follow its cited code and tests. Do not use this page as a substitute for the detailed workflow.
2. **Locate the owner before adding an import.** `TermindDomain` holds portable values and rules; `TermindApplication` holds ports, use cases, and cross-feature policy; Persistence owns all SwiftData models and container construction; infrastructure implements concrete services; `TFM` and `TFI` own native UI, composition, and lifecycle. Shared frameworks must not depend on either app target.
3. **Classify the lifetime.** App-wide services and durable stores are shared; desktop navigation and workspaces are window-local; mobile navigation is scene-local; an SSH/SFTP transport belongs to the workspace/session that opened it. Do not turn transient connections or credentials into restored state.
4. **Keep secrets and remote behavior at their existing boundaries.** Metadata can be persisted, while secrets are referenced through Keychain-backed storage. SSH/SFTP, host-key trust, and transport ownership belong on the Termind side of the host-neutral AgentKit boundary.
5. **Plan the regression check alongside the change.** Add or update the focused test that demonstrates the contract, then run the appropriate build/test command using the resolved package graph.
## Task-routing map
| If you are changing… | Start here | Also inspect | Focused validation |
| --- | --- | --- | --- |
| App startup, dependency assembly, window/scene behavior, backgrounding, or shutdown | [Platform Runtime, App Composition, and Lifetimes](/openwiki/architecture/platform-runtime.md) | `TFM/App/TermindApp.swift`, `TFI/App/TermindIOSApp.swift` | Relevant `TFMTests` or `TFITests` lifecycle/window suite |
| A module import, framework placement, SwiftData model, shared resource, or AgentKit-facing API | [System Boundaries and Dependency Ownership](/openwiki/architecture/system-boundaries.md) | `Memory/ARCHITECTURE.md`, `TFMTests/ArchitectureBoundaryTests.swift` | `ArchitectureBoundaryTests` plus the affected feature tests |
| SSH, Telnet, proxy/jump routing, trust prompts, credentials, or workspace reconnect | [SSH, Telnet, Trust, and Workspace Session Lifecycle](/openwiki/workflows/ssh-session-lifecycle.md) | Remote Infrastructure callers and the owning session feature | SSH preparation, host-key, authentication, journey, and session tests |
| Terminal services, metrics, port forwarding, channel limits, or shared remote transport policy | [Remote Services: Terminal, Metrics, and Port Forwarding](/openwiki/concepts/remote-services-and-forwarding.md) | `Memory/ARCHITECTURE.md` remote-session contracts | The relevant terminal, metrics, or forwarding suite |
| SFTP browsing, transfer scheduling/topology, conflict behavior, resume, external editing, or cleanup | [SFTP Transfer, Scheduling, and External Edit Workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md) | The feature owner plus `SFTPTransferContext`/scheduler callers | Matching SFTP transfer, edit, conflict, or mobile SFTP tests |
| Assistant turns, approval, host tools, skills, scratch space, agent persistence, or Hermes memory | [Assistant, Agent Runtime, Skills, and Memory](/openwiki/concepts/agent-runtime-and-assistant.md) | AgentKit boundary in [System Boundaries](/openwiki/architecture/system-boundaries.md) | Agent, approval, scratch, skill, or memory suites in `TFMTests`/`FrameworkTests` |
| Hosts, Vault records, migrations, Keychain references, repositories, or data compatibility | [Persistent Data, Migrations, and Secret Boundaries](/openwiki/concepts/persistence-and-secrets.md) | `Memory/ARCHITECTURE.md` and persistence compatibility tests | Persistence, repository, secret, and migration tests |
| CloudKit selection, sync lifecycle, journals, account transitions, settings, or secret-upload authorization | [Settings, Vault, Metrics, and Cloud Sync Workflow](/openwiki/workflows/settings-and-cloud-sync.md) | `Memory/ARCHITECTURE.md` sync contracts | Sync lifecycle/coordinator and affected feature tests |
| macOS MCP server, external authentication, transfers, bearer tokens, or `termind-mcp` | [MCP Server, Transfer APIs, and Stdio Bridge](/openwiki/integrations/mcp-server-and-bridge.md) | `TermindMCPBridge/` and MCP server/transfer tests | MCP token, server-session, upload, download, and bridge tests |
| Entitlements, StoreKit, localization, widgets, screenshots, or marketing/landing-page work | [Commerce, Localization, and Product Surfaces](/openwiki/concepts/commerce-localization-and-product-surfaces.md) and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md) | `Frameworks/Resources/Localizable.xcstrings`, `LandingPage/`, relevant app target | Localization check, relevant app tests, screenshots, or `npm run build` |
| Choosing a regression seam or a representative test across framework and platform targets | [Testing Strategy and Behavioral Boundaries](/openwiki/testing/behavioral-boundaries-and-fixtures.md) | Existing tests nearest the feature | Narrow behavioral test first, then affected target suite |
## The ownership decisions that prevent most regressions
### Put behavior with the correct layer
A feature model should depend on an injected port or service, not construct a database, Keychain store, SSH client, or network implementation because it is nearby. `ArchitectureBoundaryTests` actively rejects lower-layer platform/storage/transport imports, duplicate AgentKit runtime types, and SwiftData models outside Persistence. Treat a boundary-test failure as an architectural error, not a test to work around.
AgentKit is a separately versioned remote package. It owns the generic agent loop, approval gate, provider adapters, MCP client, and host-neutral tools; Termind owns SSH/SFTP tools and registers them additively. A change that genuinely spans the package boundary must be released in `../AgentKit`, then update AgentKit's `minimumVersion` in `Termind.xcodeproj/project.pbxproj` and the resolved revision together. A sibling working-tree edit is not used by Xcode's resolved build.
### Preserve runtime and failure boundaries
The macOS app constructs its model container and app-wide services in `TermindApp`; failure to open the local database terminates startup instead of silently substituting a blank store. The iOS app creates one `MobileAppModel` at startup and shows an unavailable-data view when that composition fails. Test and screenshot modes explicitly select in-memory/test composition rather than modifying production persistence behavior.
Remote trust and authentication are part of the real connection attempt: route preparation supplies a snapshot, while Remote Infrastructure completes socket, handshake, host-key authorization, and authentication. The feature that started the connection retains its journey UI, retry lifetime, and workspace/session ownership. This is why a trust, route, or credential change should be traced through both its shared remote policy and the initiating feature rather than patched in a single screen.
## Validation baseline
Use the narrowest test that proves the changed contract, followed by the affected product suite when risk warrants it. Keep `-onlyUsePackageVersionsFromResolvedFile`; without it an ordinary build can resolve a dependency revision different from `Package.resolved`.
```sh
xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile build
xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test
xcodebuild -project Termind.xcodeproj -scheme TFI -destination 'generic/platform=iOS Simulator' -onlyUsePackageVersionsFromResolvedFile build
xcrun swift-format lint --strict --recursive Frameworks TFM TFI FrameworkTests TFMTests TFITests TermindMCPBridge
Scripts/check-zh-localization.sh
```
Use an installed iPhone or iPad simulator destination for `TFI` tests. Keep visible-window macOS tests opt-in with `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` and a narrow `-only-testing` selection; routine checks should stay headless. UI string changes require completed `zh-Hans` and `zh-Hant` translations in `Frameworks/Resources/Localizable.xcstrings`; landing-page work is separately validated with `cd LandingPage && npm ci && npm run build`.
## Change checklist
- Identify the domain and owner in the routing map; read the detailed page before implementing.
- Trace callers and callees across the integration boundary; include lifecycle, retry/cancellation, persistence, and cleanup paths—not only the happy path.
- Preserve architecture contracts in `Memory/ARCHITECTURE.md`; update the record and boundary tests if an intentional ownership rule changes.
- Add a targeted regression test at the layer where the behavior is observable, and run the relevant focused check.
- Run resolved-package product validation, strict formatting, and the localization gate appropriate to the changed surface.
- Inspect the diff for secret material, accidental generated artifacts, unintended `Package.resolved` churn, and cross-layer imports.
For operational detail, commands, localization, screenshots, and the AgentKit release procedure, continue with [Build, Test, and Release](/openwiki/operations/build-test-and-release.md).
@@ -0,0 +1,139 @@
---
type: testing strategy
title: Testing Strategy and Behavioral Boundaries
description: Focused regression strategy for Termind's shared frameworks and macOS and mobile targets, with fixtures that protect persistence, security, lifecycle, architecture, and UI contracts.
tags: [testing, regression, fixtures, architecture, persistence, security, lifecycle, ui]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
- id: openwiki-source-b347308e8c5cc6c0b0d29b7d
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift
- id: openwiki-source-017f5e2abe9b13df755a5322
resource: repo://FrameworkTests/AgentReplayPersistenceTests.swift
- id: openwiki-source-8428b9f5de49b8a561d93fa5
resource: repo://FrameworkTests/PersistenceCompatibilityTests.swift
- id: openwiki-source-db40aa993661b07f1a9aff6d
resource: repo://FrameworkTests/SSHInteractionPolicyTests.swift
- id: openwiki-source-350d4a794cfef67e406ddf9b
resource: repo://TFI/Infrastructure/MobileWorkspaceStore.swift
- id: openwiki-source-b822b041afbf829d09a8555a
resource: repo://TFITests/MobileAppTests.swift
- id: openwiki-source-9b78a7e39bfa08bea5192722
resource: repo://TFITests/MobileWorkspaceStoreTests.swift
- id: openwiki-source-cfbc34def649c94f760c5695
resource: repo://TFMTests/AgentHostAuthenticationTests.swift
- id: openwiki-source-d3d065330c730839f5cc6112
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-53e2b2fd2e661123f63e69e1
resource: repo://TFMTests/SFTPTransferContextTests.swift
- id: openwiki-source-a08489338be00125d646c77e
resource: repo://TFMTests/VisibleWindowTestTrait.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# Testing Strategy and Behavioral Boundaries
Termind uses Swift Testing to test a behavior at the layer that owns it, rather than treating the test tree as a second implementation. `FrameworkTests/` protects portable framework contracts; `TFMTests/` exercises macOS composition, native interaction, and remote-session behavior; `TFITests/` protects iPhone/iPad composition, scene behavior, and mobile presentation. The targets use `@Suite`, `@Test`, and `#expect`.
A useful regression test establishes an observable invariant at an integration seam: what is persisted and migrated, which credentials and prompts may cross a connection boundary, when a resource remains alive after a UI owner disappears, or which state is shared versus scene-local. Avoid testing private mechanics merely because they exist. Test real transports or windows only when the contract requires them; otherwise inject a small in-memory repository, secret store, responder, client, or actor-backed harness.
```mermaid
flowchart TD
Change["Changed behavior"] --> Owner{"Who owns the contract"}
Owner --> Shared["Shared framework contract"]
Owner --> Desktop["macOS composition or interaction"]
Owner --> Mobile["Mobile app or scene behavior"]
Shared --> FrameworkTests["FrameworkTests fixture-based regression"]
Desktop --> TFMTests["TFMTests integration or rendering regression"]
Mobile --> TFITests["TFITests integration or rendering regression"]
FrameworkTests --> Scope["Run focused suite then affected target"]
TFMTests --> Scope
TFITests --> Scope
```
This flow selects the narrowest test target that owns the behavior, then expands validation only as the affected product surface requires.
## Suite ownership and seams
### Shared frameworks: durable rules and ports
Use `FrameworkTests` for behavior intended to remain identical across macOS and mobile: value/rule behavior, repository and persistence adapters, migration compatibility, settings synchronization, host-key policy, and presentation-independent controllers. These tests should normally run with deterministic in-memory state or a temporary directory and should not import an app target.
Persistence tests are compatibility tests, not just encode/decode checks. `PersistenceCompatibilityTests` opens historical fixture stores through `TermindPersistence.makeContainer`, verifies retained records, checks migration outcomes, and confirms independent in-memory containers expose the full shared schema. When changing a SwiftData model, migration, or repository behavior, cover the old-store input and the post-migration contract; do not limit coverage to a newly created store.
Agent replay persistence demonstrates the same principle for durable runtime state: an in-memory `SwiftDataAgentRunRepository` must restore frozen context and tool result projection without duplicating replay backing across subsequent snapshots, and deletion must remove that backing. A fixture should deliberately model the timing boundary it protects—for example, recording a tool result before the following run snapshot—rather than requiring a live provider.
### macOS: composition, security, and resource lifetime
`TFMTests` owns desktop composition and native interaction seams. `ArchitectureBoundaryTests` is a source-level regression suite: it rejects forbidden imports and concrete infrastructure construction in layers that must stay abstract, confines SwiftData models to `TermindPersistence`, prevents shared frameworks from importing application targets, and prevents local declarations from shadowing types owned by AgentKit. Run it whenever moving code, changing framework dependencies, adding persistence types, or crossing the AgentKit boundary.
Security-sensitive tests should make the boundary explicit with a memory secret store and an authentication responder, never production secrets. `AgentHostAuthenticationTests` verifies that one-use credentials can configure an SSH/SFTP attempt without mutating the Vault unless saving was requested; it also covers route-order prompting for a jump host and destination, prompt/connection coalescing for concurrent work, cancellation before SFTP opens, rejected-credential retry, and stale authentication generations. These are safety contracts: a future refactor must not persist an ephemeral secret, merge unrelated challenges, or let an old callback erase newer authentication state.
The complementary shared `SSHInteractionPolicyTests` covers noninteractive follow-on connections. An `SSHAdditionalConnectionSnapshot` retains route and authentication references rather than credential material, and an interaction-forbidden request must not surface host-key or keyboard-interactive UI. Protected-key credentials become an interaction-required marker while a password fallback remains usable; runtime `SSHSecret` values are consumable once and clearing a copied connection configuration invalidates every credential copy.
SFTP transfer tests use a controlled `TransferChannelHarness`, a `TransferChannelClient`, and temporary files instead of a real server. They establish lifecycle and scheduling behavior that is easy to regress in UI work:
- Closing a desktop pane releases its UI ownership but lets queued transfers retain the authenticated connection until work completes; cancellation releases the final connection.
- A silent independent connection is donated when available. If it requires interaction, upload falls back to the PTY connection; it must not fall back after cancellation or a retired generation.
- Scheduler capacity remains bounded across contexts for the same host. Fallback from extra connections to sibling channels does not increase capacity, and a PTY fallback does not retry independent connections for large files.
- Additional connections use the forbidden interaction policy, so detached/background work cannot open an authentication prompt.
Those tests are intentionally actor-driven and use polling only to wait for observable harness state. Prefer this style for races: hold the transfer at a known point, make the ownership transition, then release it and assert the terminal state and disconnect count.
### Mobile: app state, scenes, and device-local restoration
`TFITests` owns `MobileAppModel` composition and mobile scene behavior. Mobile app tests build `MobileAppModel(inMemory: true)` or supply dependency seams, which permits assertions over the actual shared schema and repositories without using the user's database or Keychain. Representative tests verify that scenes share durable conversations while navigation, selected conversation, and composer drafts stay scene-local; shared SwiftData history is observable from fresh repositories over the same container.
External connection URLs are another ownership boundary: opening one creates an ephemeral workspace and does not create a Vault host or saved workspace descriptor. Conversely, closing all workspaces disconnects each live workspace and is repeatable. Background-expiration tests provide a controlled connection service and cover resume intent, foreground recovery, and rejection of retired callbacks. A lifecycle change must preserve the appropriate one of these contracts rather than merely asserting that a view updates.
`MobileWorkspaceStoreTests` protects the device-local restoration format. The store contains connection intent only—workspace descriptor identity, host reference, title, kind, and duplicate index—not credentials, commands, or live session state. It migrates legacy arrays into the versioned snapshot while allocating missing duplicate indices deterministically by host and kind. If bytes are malformed, unknown-version, or invalid, loading and later saving fail while the original bytes remain untouched; a successful load is required before replacement. Add a fixture for every format transition and for corruption behavior, because silently replacing unreadable restoration data with an empty list loses recoverable user state.
## Fixture design rules
1. **Inject at the owner boundary.** Use `MobileAppDependencies.testing`, in-memory repositories, `MemoryHostSecretStore`, a responder closure, or a protocol test client to replace I/O while retaining the production coordinator/model. Do not duplicate production policy inside a mock.
2. **Keep fixtures isolated.** Create a unique `UserDefaults` suite and remove its persistent domain in `defer`; use a UUID-named temporary directory/file and delete it in `defer`. In-memory containers must be newly created when isolation matters.
3. **Make adverse timing controllable.** Actor-backed harnesses should count opens, prompts, disconnects, active work, and release signals. This lets a test assert cancellation, coalescing, or teardown deterministically instead of sleeping against a real network.
4. **Assert both state and prohibited side effects.** For security and persistence, verify not only a successful configuration or migration but also that the Vault, original bytes, secret store, prompt queue, or connection count did not change when policy forbids it.
5. **Test boundaries, not file names.** A regression belongs beside the narrowest suite with authority over its observable contract. Add a higher-level target test when framework correctness alone cannot prove platform assembly, lifecycle, or UI behavior.
## UI and visible-window policy
Offscreen layout and logic tests remain ordinary tests. A macOS test that presents a window or takes application focus must opt in with `.requiresVisibleWindow` on its suite or test. The trait is enabled only when the test host has `TERMIND_WINDOW_TESTS=1`; without it, those tests are skipped. Rendering and interaction suites use this convention so routine macOS validation remains headless and does not steal focus or depend on a display.
Run a named visible-window suite only when its interaction contract changed, for example:
```sh
TEST_RUNNER_TERMIND_WINDOW_TESTS=1 xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test -only-testing:TFMTests/ChooserInteractionTests
```
In Xcode, set `TERMIND_WINDOW_TESTS=1` in the Test action environment. Existing screenshot suites can retain their dedicated gates. A visual change still needs behavior-appropriate coverage: an offscreen test for state/policy, a visible-window test for focus/presentation when applicable, and screenshot/marketing capture only where that workflow owns the deliverable.
## Change-to-regression matrix
| Change type | Primary regression seam | Required behavior to protect |
| --- | --- | --- |
| Framework dependency or data-owner change | `ArchitectureBoundaryTests` plus affected framework suite | No reverse import, concrete implementation leak, duplicate AgentKit type, or SwiftData model outside Persistence. |
| SwiftData schema, migration, or durable agent record | Persistence compatibility/replay fixtures | Old stores open, records retain intended values, interrupted timing remains recoverable, and deletes clean backing rows. |
| SSH credentials, prompts, host trust, or agent authentication | Authentication and interaction-policy fixtures | Ephemeral secrets stay ephemeral, prompt scope/order/coalescing is correct, forbidden work stays noninteractive, and secrets are invalidated after use. |
| SSH/SFTP transfer scheduling or pane/session teardown | `SFTPTransferContextTests` with a controlled channel harness | Concurrency bounds hold, background transfer ownership survives UI teardown, cancellation cleans up, and fallback does not invite interaction. |
| Mobile workspace, scene, restoration, or background lifecycle | `MobileAppTests` and `MobileWorkspaceStoreTests` | State is shared or local at the intended scope, external sessions remain ephemeral, restoration is safe, and callbacks cannot revive retired state. |
| macOS rendering or focus behavior | Focused offscreen test plus `.requiresVisibleWindow` suite when needed | Default tests stay headless; opted-in tests prove the user-visible interaction. |
## Execution strategy
Start with the test that names the invariant, then run the affected product target using the resolved package graph. The default macOS entrypoint runs macOS and shared Swift tests:
```sh
xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test
```
For mobile changes, build/test the `TFI` scheme against an installed iPhone or iPad simulator. Retain `-onlyUsePackageVersionsFromResolvedFile`: validation should use the revisions in `Package.resolved`, not silently resolve a different dependency graph. Run strict formatting for Swift changes:
```sh
xcrun swift-format lint --strict --recursive Frameworks TFM TFI FrameworkTests TFMTests TFITests TermindMCPBridge
```
This page complements [System Boundaries and Dependency Ownership](../architecture/system-boundaries.md), [Assistant, Agent Runtime, Skills, and Memory](../concepts/agent-runtime-and-assistant.md), and [Build, Validation, Localization, and Dependency Release Operations](../operations/build-test-and-release.md). The operational page defines the full build and release commands; this page defines what a focused regression must prove before those broader checks are meaningful.
+3
View File
@@ -0,0 +1,3 @@
# Files
- [Testing Strategy and Behavioral Boundaries](behavioral-boundaries-and-fixtures.md) - Focused regression strategy for Termind's shared frameworks and macOS and mobile targets, with fixtures that protect persistence, security, lifecycle, architecture, and UI contracts.
+5
View File
@@ -0,0 +1,5 @@
# Files
- [Settings, Vault, Metrics, and Cloud Sync Workflow](settings-and-cloud-sync.md) - How Termind independently synchronizes Vault, Settings, and Metrics through CloudKit, including lifecycle gates, durable journals, account and environment transitions, conflict handling, and AI-secret upload authorization.
- [SFTP Transfer, Scheduling, and External Edit Workflow](sftp-transfer-and-external-edit.md) - How SFTP browser operations become scheduled transfers, choose an SSH topology, resolve conflicts and resume safely, and support explicit external-file editing without durable staging or replay.
- [SSH, Telnet, Trust, and Workspace Session Lifecycle](ssh-session-lifecycle.md) - Traces how Termind prepares SSH and Telnet connections, routes them through proxies and jump hosts, authorizes server identity, consumes credentials, and retires or restores live workspace sessions.
@@ -0,0 +1,143 @@
---
type: synchronization workflow
title: Settings, Vault, Metrics, and Cloud Sync Workflow
description: How Termind independently synchronizes Vault, Settings, and Metrics through CloudKit, including lifecycle gates, durable journals, account and environment transitions, conflict handling, and AI-secret upload authorization.
tags: [cloudkit, synchronization, settings, vault, metrics, secrets, swiftdata]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-9fbc733f79d51a7265ee9e4a
resource: repo://Frameworks/TermindApplication/SettingsKey.swift
- id: openwiki-source-1d1f503a260f304a969fcee4
resource: repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift
- id: openwiki-source-3effdff7f6b04e2a66d8f651
resource: repo://Frameworks/TermindInfrastructure/Cloud/MetricsSyncCoordinator.swift
- id: openwiki-source-04ef2b2f02773f8833db9a8b
resource: repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift
- id: openwiki-source-eaa9d39ab551840299164d96
resource: repo://Frameworks/TermindInfrastructure/Cloud/VaultSyncCoordinator.swift
- id: openwiki-source-65a2da12a42f42fb0850078e
resource: repo://Frameworks/TermindPersistence/MetricsSyncStore.swift
- id: openwiki-source-6df73854db20ee83905a634c
resource: repo://Frameworks/TermindPersistence/SettingsSyncJournalStore.swift
- id: openwiki-source-9eb2234b02897ade8e405374
resource: repo://Frameworks/TermindPersistence/SwiftDataAISecretStore.swift
- id: openwiki-source-bc351b6c699ff4bbf9f8c2b1
resource: repo://Frameworks/TermindPersistence/SwiftDataVaultJournal.swift
- id: openwiki-source-bf7a64e7c819eb9279e2f9e4
resource: repo://FrameworkTests/CloudSyncLifecycleTests.swift
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-4dbea0ff2808163cb4ecdd8f
resource: repo://TFM/App/AppModel.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# Settings, Vault, Metrics, and Cloud Sync Workflow
Termind synchronizes three **independent categories** in the private `iCloud.com.akinokaede.termind` container: Vault records, application Settings, and Metrics selections. Each category has its own coordinator, private custom zone, subscription, `CKSyncEngine`, durable journal state, account binding, environment marker, pending queue, and status. The shared `CloudSyncLifecycle` supplies the safety protocol, but it does not make category state shared. Pausing Vault, for example, neither retires Settings/Metrics engines nor revokes Settings’ secret-upload authorization.
This workflow is CloudKit replication built around a SwiftData journal, not SwiftData’s CloudKit integration. `TermindPersistence` owns the journal models and the coordinator applies accepted remote envelopes back through the relevant persistence facade. Platform app models own coordinator lifetime and apply resulting snapshots to their runtime models.
## Categories, switches, and runtime ownership
| Category | Coordinator and zone | Content boundary | Default control |
| --- | --- | --- | --- |
| Vault | `VaultSyncCoordinator`; `TermindVaultV1`; `VaultItem` | Hosts, identities, SSH-key references, known hosts, snippets, forwarding rules, and workspace templates | `vault.sync.enabled` plus `icloud.sync.enabled` |
| Settings | `SettingsSyncCoordinator`; `TermindAIConfigurationV1`; `AIConfigurationItem`, `SSHPreferencesItem`, and `SFTPPreferencesItem` | AI configuration, skills, search, terminal, SSH, and SFTP preferences—not credential material | `settings.sync.enabled` plus `icloud.sync.enabled` |
| Metrics | `MetricsSyncCoordinator`; `TermindMetricsV1`; `MetricsItem` | Persisted metrics selections, not samples or active monitoring | `metrics.sync.enabled` plus `icloud.sync.enabled` |
All master and category switches default on. A category is enabled only when the master `SettingsKey.iCloudSyncEnabled` and that category’s key are enabled; an absent preference uses its category default. `SettingsKey.migrateSyncPreferences(in:)` migrates the old Settings selection and derives an initial master choice without discarding explicit opt-outs.
`AppModel` starts all three coordinators only when the Vault-sync Pro capability is available, pauses all of them when entitlement is absent, and routes accepted remote snapshots to the corresponding app-wide models. On mobile, `MobileAppModel.reconcileSync()` starts them only while at least one scene is active and the same capability is available; otherwise it pauses them. This makes synchronization app-wide and entitlement/lifecycle-controlled rather than window- or scene-owned.
## Lifecycle: fetch before send
Every coordinator adapts its own journal to `CloudSyncLifecycleStore` and implements `CKSyncEngineDelegate`; the lifecycle owns the engine session and operation generation. It first checks the CloudKit account and user record, binds or requests confirmation for the account, resets incompatible CloudKit metadata when needed, creates an engine, restores queued journal record names, ensures its zone exists, and fetches that zone. **No send is authorized until that fetch succeeds for the current engine.** Local edits still enter the durable journal while sync is paused or while the fetch is in progress.
```mermaid
stateDiagram-v2
[*] --> Disabled
Disabled --> CheckingAccount: start when category enabled
CheckingAccount --> Paused: disabled or pause
CheckingAccount --> Unavailable: account unavailable
CheckingAccount --> NeedsConfirmation: bound account differs
CheckingAccount --> Preparing: account and user accepted
Preparing --> Fetching: engine queued and zone created
Fetching --> ReadyToSend: current engine fetch succeeds
Fetching --> Retired: pause account change or replacement
ReadyToSend --> Sending: pending journal records
Sending --> ReadyToSend: send completes
ReadyToSend --> UpToDate: no pending records
Sending --> Retired: pause account change or replacement
UpToDate --> Sending: local changes
UpToDate --> Retired: pause account change or replacement
NeedsConfirmation --> Preparing: confirm account switch merge
NeedsConfirmation --> Paused: disabled or pause
Retired --> CheckingAccount: enabled restart
Unavailable --> CheckingAccount: retry
Paused --> CheckingAccount: enabled restart
ReadyToSend --> Failed: terminal or quarantine error
Failed --> CheckingAccount: retry
```
This state diagram shows the per-category fetch-before-send gate and the account-change confirmation path.
A lifecycle runs at most one tracked operation. It gives each operation an ID and only lets that ID clear the operation or publish an error. `pause()` or an account transition retires the engine: it changes the operation ID, cancels the task and engine operations, clears readiness, and removes the engine. Completion handlers and delegate events must also satisfy `lifecycle.accepts(engine)`, which requires identity with the current engine and an enabled category. Thus stale generations cannot publish status, provide a record batch, authorize uploads, or clear a replacement operation.
Retryable CloudKit errors—network failure/unavailability, service unavailable, rate limit, zone busy, and truncated results—leave the category in a syncing state for retry. `notAuthenticated` becomes an unavailable sign-in status; other errors are failed. A journal quarantine reason or terminal outgoing-record error takes precedence over an otherwise up-to-date status, preventing a false successful indication.
## Account, zone, and environment transitions
The journal persists serialized engine state, `boundUserRecordName`, `pendingUserRecordName`, and the last successful sync. Before creating an engine, the lifecycle compares CloudKit’s current user record name with the binding:
- With no binding or a matching account, it stores the current account and proceeds.
- With a different bound account, it records the new user as pending, reports `.accountChangeConfirmationRequired`, and does not create an engine or upload anything.
- `confirmAccountSwitchMerge()` resets journal state **before** binding the pending account, then retires and restarts. The account reset removes deletion tombstones, marks live records for upload, clears CloudKit system fields, serialized engine state, and last-success time. It therefore avoids carrying an old account’s deletions into the new account.
- CloudKit sign-out retires the engine and reports the category’s sign-in message. A different sign-in or switch accounts retires it and requires merge confirmation; a same-user sign-in can continue.
The current `TermindCloudKitEnvironment` bundle value is also compared with a category-specific `UserDefaults` marker. On change, the category keeps envelopes but requeues them, discards system fields/change tags and engine serialization, clears last-success time, saves, and records the new environment. This prevents Development metadata from being reused in Production. If CloudKit reports the category zone deleted or returns `zoneNotFound`, the lifecycle similarly resets/requeues the journal, asks the engine to recreate the zone, and retains the account binding.
## Journal and replication protocol
A journal is the durable outbox and merge authority for each category. Bootstrap creates baseline envelopes for an initial local snapshot. Local persistence writes compute only real differences, assign an ordered version using the installation writer ID, mark changed records `needsUpload`, and retain deletion tombstones. Because journaling happens independent of lifecycle readiness, edits made while disabled are accumulated and sent later; no-op saves do not advance versions.
Each pending envelope is encoded into a CloudKit record with envelope metadata (`formatVersion`, `kind`, `entityID`, `modifiedAt`, `counter`, `writerID`, and `isDeleted`) and a payload hash. The coding layer uses inline bytes below its limit and a local `CKAsset` for larger payloads. Journal-held CloudKit system fields are reused on subsequent saves and updated from fetched/saved records, enabling ordinary CloudKit optimistic concurrency.
On fetch, coordinators process only their zone and accepted record types. They decode and validate envelopes, quarantine malformed or unsupported payloads with their received bytes and reason, merge valid envelopes in a persistence transaction, retain remote system fields, and notify the app only after accepted values are applied. A physical CloudKit deletion is not treated as a user deletion: if a local journal row still exists, it is marked for re-upload. Logical deletion is represented by an envelope tombstone.
Merge is deterministic: newer versions win; an older remote value causes the local value to be requeued. For equal versions whose payloads differ, encoded bytes provide a deterministic tie-breaker. Settings and Metrics additionally collapse multiple fetched versions of one key before deciding, so batch delivery order does not affect the result. A `serverRecordChanged` save failure applies the server envelope and either recognizes an identical local version as uploaded or requeues the winning local result. Successful sends clear `needsUpload` only if the journal still holds the sent version, so a newer local edit cannot be incorrectly acknowledged.
Vault projections deliberately remove device-local presentation/usage metadata from envelopes: group/package expansion is normalized and identity `lastUsedAt` is omitted, while applying a remote identity preserves the local usage timestamp. Settings likewise excludes explicitly device-local defaults such as debug/logging, review history, and terminal font family/size/follow-theme-size. Settings record-type compatibility is intentional: SSH and SFTP preferences use distinct types in the Settings zone so older clients can ignore newer records before decoding.
## Settings references and secret authorization
Settings records carry credential **references**, never secret material. After accepting a remote provider or MCP-server envelope, `SettingsSyncCoordinator` calls `AISecretStore.acceptRemoteReferences`, marking those references as iCloud-backed so an old device-local copy cannot override a delayed iCloud Keychain value.
Secret migration is coupled to the Settings lifecycle, not merely to a preferences toggle:
1. A current Settings engine must successfully fetch its zone.
2. Only then does `CloudSyncLifecycle` invoke the Settings `authorizeUploads(true)` callback and set `isReadyToSend`.
3. Before a send and when its change-batch delegate is asked for records, `SettingsSyncCoordinator` migrates references found in provider, Vertex, and MCP configuration.
4. `AISecretStore` permits new iCloud copies only when that authorization is true and both master and Settings switches remain on. It verifies a copied iCloud value before recording the iCloud location and removing the device copy.
5. Pausing, account retirement, or a failed initial fetch leaves or returns authorization to false. Therefore a stale engine cannot migrate/upload secrets merely because Settings was once enabled.
The store retains pending-deletion markers before deleting Keychain values and never reads them again as live secrets; this prevents late Keychain delivery from resurrecting a deleted credential. Once a reference is known in iCloud, later writes stay there even if a switch is turned off, while newly created secrets under a disabled or unverified workflow remain device-local.
## Operations and extension guidance
CloudKit deployment is separate from a passing local build. Deploy and validate the private container schema in Development and Production, preserving category zone names, record types, and subscription IDs; deploy `SFTPPreferencesItem` before clients upload it. Run signed-device checks across multiple devices on one account and explicitly test offline edits, per-category and master pause/resume, delayed Keychain delivery, account switching, and Pro expiration. See [Build, Validation, Localization, and Dependency Release Operations](/openwiki/operations/build-test-and-release.md) and `Memory/SETTINGS_SYNC_RELEASE.md` for the release matrix.
When adding a synchronized category, do not share an existing coordinator or journal. Create a category-owned zone/subscription/record type, persistence journal/state/quarantine models, coordinator record coding and delegate handling, independent enable/environment keys, and an adapter to `CloudSyncLifecycle`. Preserve fetch-before-send and current-engine checks in every `nextRecordZoneChangeBatch` implementation. Decide which fields are truly portable before adding them to envelopes; normalize or omit device-local runtime/UI metadata, and keep credentials in Keychain behind references.
When evolving a record, retain decode compatibility and validation. Unsupported or malformed records should be quarantined rather than partially applied, and a migration that changes a record identity must clear incompatible system fields and engine state. Do not turn a physical console deletion into silent data loss; retain tombstone semantics within the envelope protocol.
## Focused verification
- `FrameworkTests/CloudSyncLifecycleTests.swift` verifies fetch gating, accumulated local changes, retry behavior, operation/engine retirement, account confirmation/reset ordering, environment and zone resets, and error-status precedence.
- `FrameworkTests/CloudSyncCoordinatorLifecycleTests.swift` verifies category isolation and confirms that Settings secret authorization follows a successful fetch and is revoked on account retirement.
- `TFMTests/SettingsSyncTests.swift` covers local mirrors, Settings journal/merge behavior, independent toggles, device-local exclusions, wire compatibility, and AI secret migration/deletion behavior.
- `TFMTests/VaultSyncTests.swift` covers stable envelope names, tombstones, deterministic merge/requeue behavior, local metadata exclusion, large payload assets and corruption rejection, and environment resets.
For persistence ownership and Keychain boundaries, see [Persistent Data, Migrations, and Secret Boundaries](/openwiki/concepts/persistence-and-secrets.md). For app-wide coordinator construction and platform lifecycle behavior, see [Platform Runtime, App Composition, and Lifetimes](/openwiki/architecture/platform-runtime.md).
@@ -0,0 +1,227 @@
---
type: workflow
title: SFTP Transfer, Scheduling, and External Edit Workflow
description: How SFTP browser operations become scheduled transfers, choose an SSH topology, resolve conflicts and resume safely, and support explicit external-file editing without durable staging or replay.
tags: [sftp, file-transfer, ssh, scheduling, external-editing, lifecycle]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-46ef2fcd9e3aba751015021b
resource: repo://Frameworks/TermindDomain/Transfers/SFTPPreferences.swift
- id: openwiki-source-dd3df578da8881d8ba0638e6
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift
- id: openwiki-source-f45e107ba4ae15ff23a99333
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPClient.swift
- id: openwiki-source-b9bae3a52f35a3a412f81e10
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift
- id: openwiki-source-79d8ded739aa8dd4fa3f5cdf
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift
- id: openwiki-source-cc90954475bbeee75514baf8
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPLocalUploadPlanner.swift
- id: openwiki-source-b28dbb18976feec837ed23fe
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteConflictResolver.swift
- id: openwiki-source-af958b0e71cef7f5910893cc
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteTransferPlanner.swift
- id: openwiki-source-3adf61411195abda93bf88fc
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPResumeState.swift
- id: openwiki-source-b347308e8c5cc6c0b0d29b7d
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift
- id: openwiki-source-c4b6e224fdbea6dcd393344d
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift
- id: openwiki-source-d92ce4bb378fe3506b55c85a
resource: repo://FrameworkTests/SFTPRemoteConflictResolverTests.swift
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-83498f1ebb2addd4dded3bc1
resource: repo://TFMTests/SFTPConcurrencySchedulerTests.swift
- id: openwiki-source-bdee3a21bf24d48b877a78fe
resource: repo://TFMTests/SFTPEditTests.swift
- id: openwiki-source-53e2b2fd2e661123f63e69e1
resource: repo://TFMTests/SFTPTransferContextTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
## Scope and operating model
SFTP file work is split deliberately: browser and application models prepare batches and own UI choices; `SFTPTransferCoordinator` owns queued transfer runtime, admission, progress, cancellation, and completion; `SFTPTransferContext` owns a generation-scoped authenticated primary connection; and `SFTPChannel` implements actual libssh2 file I/O. `SFTPClient` is only the connect/disconnect facade around its primary channel. This division lets standalone SFTP, browser transfers, terminal-drop transfers, and edits share atomic write, resume, and copy mechanics without sharing a pane lifetime. [^architecture-sftp] [^client-channel]
The important safety boundary is **no durable staging and no silent replay**. Checkpoints—temporary path, source identity, acknowledged offset, and SHA-256 state—live only in `SFTPResumeState` in the running process. A recoverable connection failure pauses instead of retrying; a user must explicitly resume, at which point the source and already-written prefix are verified. A restart therefore cannot recover or replay work. [^resume-state] [^coordinator-outcomes] [^channel-prefix]
A transfer can use one of three connection forms:
- **Saved** — create a fresh `SFTPClient` from an additional-connection snapshot and disconnect it after the transfer.
- **Context** — borrow a lease from a browser/terminal `SFTPTransferContext`, which can select a sibling channel, an additional silent connection, or the primary channel.
- **Borrowed** — use an existing externally owned channel, serialized by its borrowed-connection identifier so two jobs do not operate it concurrently. [^connection-forms] [^lease-selection]
## Browser paths: prepare, validate, enqueue
Browser actions are two-phase rather than mutating during drag/drop preparation:
1. An upload planner expands selected local roots into remote directories and regular-file jobs, then performs a remote preflight over all prospective directory and file targets. A remote-copy planner first obtains a remote manifest and performs the analogous preflight at the destination. The UI can show the resulting conflict count before a policy is chosen. [^upload-preflight] [^copy-preflight]
2. On the selected `TransferConflictPolicy`, the enqueue phase resolves directories first, transforms or suppresses descendants, resolves individual targets, and only then calls `enqueue` or `enqueueRemoteCopy`. `skip` suppresses the affected item/subtree; `replace` permits overwrite and recursively removes a conflicting destination directory; `keepBoth` chooses the next available extension-aware name and maps descendants under it. [^conflict-resolution] [^upload-enqueue] [^copy-enqueue]
3. The coordinator persists a queue row in `HostLibraryModel`, retains any managed context for that transfer, retains local security-scoped access while I/O runs, and publishes byte progress only while the row is still the matching running generation. [^enqueue-runtime] [^transfer-progress]
Conflict inspection precedes mutation. Preflight identifies conflicting directories and targets without creating, deleting, or queuing a transfer; directory resolution is the first operation allowed to mutate the destination. Recursive removal validates each listed child’s name and expected path before descending, then removes children before their parent, preventing a malformed server entry from redirecting deletion. [^conflict-preflight] [^safe-recursive-delete]
For a same-host remote copy, planning rejects copying a file onto itself and rejects a directory target within the source subtree before conflict handling. Cross-host work is still a direct SFTP-to-SFTP stream: it does not materialize a local intermediary. When endpoint channels share the same SSH transport, the implementation alternates bounded reads and writes; otherwise it relays bytes through an in-process socket pair while download and upload run together. Both paths validate source size/identity and write a temporary destination before rename. [^self-copy-guard] [^copy-streaming]
## Admission, fairness, and SSH topology
`SFTPConcurrencyScheduler` is process-wide admission for data operations. Capacity counts logical files, not connections or channels: a remote copy consumes one global slot and one per-host slot for each distinct endpoint. Metadata work is outside this data admission path. The scheduler rotates anchor hosts and then sources (`workspace`, `agentRun`, or `batch`), retaining FIFO order within each source queue; it grants only a request whose every endpoint remains below the per-host limit and whose exclusive borrowed resources are free. [^scheduler-contract] [^scheduler-fairness]
Preferences default to 30 global active files and 10 per host, constrain global to 1–100 and per-host to 1–50/not above global, and select `smart`, `channels_only`, or `connections_preferred`. Updating preferences drains queued work with the new values; an already-admitted permit retains its selected mode. In Smart mode, unknown sizes and sizes through 64,000,000 bytes use channels; only a larger known file prefers an additional connection. [^preferences] [^mode-selection] [^preferences-update]
```mermaid
sequenceDiagram
participant Browser
participant Coordinator
participant Scheduler
participant Context
participant Channel
Browser->>Coordinator: enqueue validated file job
Coordinator->>Scheduler: acquire global host source permit
Scheduler-->>Coordinator: permit and scheduling mode
Coordinator->>Context: reserve slot and acquire lease
alt channels only
Context->>Channel: open sibling or serialize primary
else connections preferred
Context->>Channel: silently open additional connection
alt silent open fails
Context->>Channel: open sibling or serialize primary
end
end
Coordinator->>Channel: upload download or copy
Channel-->>Coordinator: completion or error
Coordinator->>Context: release slot and transfer ownership
Coordinator->>Scheduler: release permit
```
*Admission applies global/per-host fairness before a context chooses the concrete SSH channel topology.*
A context keeps the browser **control** channel independent where possible. `channelsOnly` opens sibling SFTP channels, falling back to a serialized primary lease rather than silently opening another connection. `connectionsPreferred` probes one additional connection without interaction; success marks the context connection-capable, while a non-cancellation failure marks it channel-capable for later jobs and leaves active work untouched. A cancelled probe does not cache that degradation. The special terminal preflight role can donate a successful independent connection to the first job; if independent preflight requires interaction, terminal work uses its PTY transport and fixes the generation to channels. [^context-topology] [^context-probe] [^terminal-preflight]
The coordinator acquires two endpoint leases in stable context-ID order for a remote copy and shares one lease when both endpoints are the same context. This avoids competing acquisition order and needless duplicate use of one transport. [^remote-copy-leases]
## Transfer state, resume, cleanup, and ownership
The visible states are queued, running, paused, completed, failed, and cancelled. Pause before admission cancels the admission task and immediately changes to paused. Pause during I/O cancels the operation; recoverable connection errors also become paused except resume-validation failures, which are failed. Cancelled or failed non-paused work performs cleanup, while completed and paused work retain the checkpoint needed for their respective outcomes. [^transfer-control] [^coordinator-outcomes]
```mermaid
stateDiagram-v2
[*] --> queued
queued --> running: permit admitted
queued --> paused: pause
queued --> cancelled: cancel
running --> completed: operation commits
running --> paused: pause or recoverable loss
running --> failed: nonrecoverable or validation failure
running --> cancelled: cancel
paused --> queued: explicit resume
paused --> cancelled: cancel
completed --> [*]
failed --> [*]
cancelled --> [*]
```
*The coordinator never transitions a paused transfer back to work without an explicit resume request.*
Uploads write to a generated remote `.termind-part-…` path with exclusive creation, validate the edit policy if present, and rename only after length/prefix checks; downloads write a local temporary path and replace/move it only after remote identity validation. Resume verifies the original source identity plus the SHA-256 prefix of the partial local or remote destination. A committed rename interrupted before bookkeeping can be recognized only by checking that the temporary is gone and the destination has the expected size and prefix. These checks make resume safe within the live process, rather than a claim that the remote protocol supplies compare-and-swap. [^channel-atomic-resume] [^channel-commit-recovery] [^channel-prefix]
Cancellation and terminal failure try to delete the local download temporary or remote upload temporary. If cleanup itself fails, the state is failed with `SFTPTemporaryFileCleanupError`, including the partial path; it is not silently hidden. Pausing intentionally retains the partial. [^cleanup]
Closing a pane is not transfer cancellation. `releaseOwner()` merely drops the pane’s ownership; queued and active jobs retain the context connection until their transfer references and active slots are gone. When a pause has released its transfer reference and the owner is gone, the unused primary is disconnected; a later explicit resume reopens silently from the snapshot. Conversely, `retire()` disconnects a failed primary and prevents it from being installed into a replacement browser generation. [^context-ownership] [^context-close] [^pause-ownership]
## External edit lifecycle
`SFTPEditService` is application-scoped and tracks one managed local copy per `(hostID, remote path)`. Opening validates that the target is a regular file, downloads it through the same coordinator into `TemporaryDirectory/TermindEdits/<UUID>/`, records a remote baseline/version and local SHA-256 digest, and returns the existing copy for a compatible repeated open. It stores route identity—not credentials—alongside the copy, and invalidates tracking if the host route or connection destination no longer matches. [^edit-open] [^edit-destination]
The service observes local copies and rechecks their digests. It uses file observation plus a one-second pass, with a forced full hash every 30 ticks, so editor atomic-save replacement and preserved timestamps are detected. Clean records remain reusable; cards represent dirty state rather than ownership of the copy. [^edit-monitoring]
```mermaid
sequenceDiagram
participant User
participant EditService
participant Coordinator
participant Remote
User->>EditService: open regular remote file
EditService->>Coordinator: queue download with version receipt
Coordinator->>Remote: download managed copy
Remote-->>EditService: committed remote version
EditService-->>User: local editable URL
User->>EditService: explicit upload
EditService->>Remote: inspect current remote version
alt changed or metadata unavailable
EditService-->>User: request replace confirmation
else validated or confirmed
EditService->>EditService: snapshot local copy
EditService->>Coordinator: queue upload with edit policy
Coordinator->>Remote: validate then atomic upload
Coordinator-->>EditService: committed version
EditService-->>User: update baseline and digest
end
```
*An edit upload snapshots local content and validates the remote version before the transfer is admitted; it is never an automatic save.*
Upload is explicit. Before taking an immutable local snapshot, the service hashes the current local copy and returns without work if its digest equals the last uploaded digest. It then reads the remote attributes: a changed baseline, a missing modification time, or an unconfirmed replacement returns `true` so the UI can request confirmation. Confirmation is tied to exactly the observed remote version and expires if it changes again. [^edit-conflict]
The upload’s `SFTPEditUploadPolicy` carries the expected version and original permissions. The channel validates the destination before creating its temporary file, preserves permissions on that file, validates again before rename, and fails closed for a non-file destination. On success, only the uploaded snapshot digest becomes acknowledged; an edit saved during the upload remains dirty and needs another explicit upload. [^edit-policy] [^edit-snapshot]
Discard is intentionally non-destructive to user work: it stops tracking and forgets digest observation but never deletes the editable copy. An active/preparing upload cannot be discarded. A paused upload is cancelled and cleaned first; if cleanup fails, the record remains so the error/partial path stays visible. Host invalidation cancels attached uploads and prevents new uploads while retaining the local copy. [^edit-discard] [^edit-invalidation]
## Operational guidance and focused verification
- Treat `SFTPPreferences` changes as future admission policy, not a way to tear down active transfers. Choose Channels Only for servers/routes where extra connections are undesirable, Connections Preferred for independent transfers when silent credentials are available, and Smart for the size-based default. [^preferences] [^preferences-update]
- Never add persistence for `SFTPResumeState`, transfer contexts, borrowed channels, or edit route credentials. The intended recovery behavior is a visible paused/failed state and an explicit user decision, not launch-time replay. [^resume-state] [^architecture-sftp]
- When changing planner or resolver code, preserve the sequence **preflight → user policy → directory resolution → target resolution → enqueue**. Moving deletion or directory creation into preflight would violate conflict validation before mutation. [^upload-preflight] [^upload-enqueue]
- When changing connection lifetimes, test both owner release and terminal transport fallback: a pane close must not interrupt retained work, but a last unused context primary must disconnect. [^context-close] [^pause-ownership]
Focused tests cover the materially risky cases: scheduler fairness across hosts/sources, cross-host capacity accounting, and the Smart threshold; topology fallback, cancellation of a silent probe, pane-close continuity, and resume after release; conflict mapping, cancellation points, and safe recursive delete; and edit confirmation, immutable snapshots, loss-to-pause, invalidation, observation of atomic saves, discard, and cleanup. [^scheduler-tests] [^context-tests] [^resolver-tests] [^edit-tests]
[^architecture-sftp]: `Memory/ARCHITECTURE.md` § “SFTP and external edits”, lines 248–296.
[^client-channel]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPClient.swift#L293-L387`; `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L120-L160`.
[^resume-state]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPResumeState.swift#L5-L75`.
[^channel-prefix]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L985-L1031`.
[^connection-forms]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L12-L24`.
[^lease-selection]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L721-L754`.
[^upload-preflight]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPLocalUploadPlanner.swift#L88-L103`.
[^copy-preflight]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteTransferPlanner.swift#L221-L260`.
[^conflict-resolution]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteConflictResolver.swift#L64-L118`.
[^upload-enqueue]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPLocalUploadPlanner.swift#L106-L161`.
[^copy-enqueue]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteTransferPlanner.swift#L267-L314`.
[^enqueue-runtime]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L237-L269`.
[^transfer-progress]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L531-L614`.
[^conflict-preflight]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteConflictResolver.swift#L29-L62`.
[^safe-recursive-delete]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteConflictResolver.swift#L121-L139`.
[^self-copy-guard]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPRemoteTransferPlanner.swift#L221-L230`.
[^copy-streaming]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L575-L705`.
[^scheduler-contract]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift#L29-L59`; `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift#L133-L150`.
[^scheduler-fairness]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift#L154-L219`.
[^preferences]: `Frameworks/TermindDomain/Transfers/SFTPPreferences.swift#L3-L46`.
[^mode-selection]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPConcurrencyScheduler.swift#L169-L182`.
[^preferences-update]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L149-L165`.
[^context-topology]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L99-L188`.
[^context-probe]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L212-L233`; `TFMTests/SFTPTransferContextTests.swift#L232-L263`.
[^terminal-preflight]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L4-L16`; `TFMTests/SFTPTransferContextTests.swift#L23-L61`.
[^remote-copy-leases]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L624-L695`.
[^transfer-control]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L349-L413`.
[^coordinator-outcomes]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L583-L622`; `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L797-L819`.
[^channel-atomic-resume]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L354-L404`; `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L416-L483`.
[^channel-commit-recovery]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L807-L909`.
[^cleanup]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift#L415-L440`; `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPResumeState.swift#L62-L68`.
[^context-ownership]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L64-L97`; `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift#L266-L272`.
[^context-close]: `TFMTests/SFTPTransferContextTests.swift#L63-L108`.
[^pause-ownership]: `TFMTests/SFTPTransferContextTests.swift#L280-L298`.
[^edit-open]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L66-L140`.
[^edit-destination]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L16-L45`; `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L305-L325`.
[^edit-monitoring]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L142-L184`.
[^edit-conflict]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L236-L303`.
[^edit-policy]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L836-L909`.
[^edit-snapshot]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L267-L295`; `TFMTests/SFTPEditTests.swift#L105-L120`.
[^edit-discard]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L205-L234`; `TFMTests/SFTPEditTests.swift#L232-L269`.
[^edit-invalidation]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPEditService.swift#L186-L203`.
[^scheduler-tests]: `TFMTests/SFTPConcurrencySchedulerTests.swift#L7-L150`.
[^context-tests]: `TFMTests/SFTPTransferContextTests.swift#L129-L364`.
[^resolver-tests]: `FrameworkTests/SFTPRemoteConflictResolverTests.swift#L9-L167`.
[^edit-tests]: `TFMTests/SFTPEditTests.swift#L12-L269`.
+198
View File
@@ -0,0 +1,198 @@
---
type: workflow
title: SSH, Telnet, Trust, and Workspace Session Lifecycle
description: Traces how Termind prepares SSH and Telnet connections, routes them through proxies and jump hosts, authorizes server identity, consumes credentials, and retires or restores live workspace sessions.
tags: [ssh, telnet, connection-lifecycle, host-keys, proxy, workspace, security]
verified:
- by: openwiki/0.5.2
at: 2026-09-22T00:31:10.149Z
sources:
- id: openwiki-source-5aa101e9f8e2906832f58121
resource: repo://Frameworks/TermindApplication/Connections/SSHConnectionPreparation.swift
- id: openwiki-source-4f78037bc69b6dfc293aca3d
resource: repo://Frameworks/TermindApplication/SSHConnectionTypes.swift
- id: openwiki-source-e980c605b1828a2d960bfd5e
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnection.swift
- id: openwiki-source-ab74624bdc6b7046d91bcbac
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnectionWorker.swift
- id: openwiki-source-8c4abf5c09db535e2818e3c4
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift
- id: openwiki-source-04973e11e30eed9faa5cb86b
resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHRoutedSocket.swift
- id: openwiki-source-1f7380cad037b68eb1bec322
resource: repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift
- id: openwiki-source-7d8c92c7f508941f92360dcd
resource: repo://FrameworkTests/SSHConnectionPreparationTests.swift
- id: openwiki-source-2635e6aecc48e14adbb07b91
resource: repo://FrameworkTests/SSHHostKeyAuthorizationTests.swift
- id: openwiki-source-1970087a236604bd6a1f375d
resource: repo://Memory/ARCHITECTURE.md
- id: openwiki-source-492f738896225c6b3acf7d2f
resource: repo://TFI/Features/Workspaces/MobileWorkspace.swift
- id: openwiki-source-85c3f954351f96433cb1fb4b
resource: repo://TFMTests/ConnectionJourneyTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" }
---
# SSH, Telnet, Trust, and Workspace Session Lifecycle
## Scope and ownership
A remote session is deliberately assembled in layers. Application code snapshots a route, identity choices, known-host expectations, and transient submissions into `SSHConnectionPreparation`; Remote Infrastructure opens the routed socket, completes each libssh2 handshake and authentication, then gives the feature an authenticated transport or protocol-specific client. `RemoteConnectionCoordinator` is the application-facing factory and one-shot connection boundary: it produces PTY, multiplexed SSH, or SFTP owners and disconnects an owner if its initial connect fails, so callers never receive a half-open session.
The session feature—not the coordinator—owns user-facing `ConnectionJourney`, host-key and keyboard-interactive queues, retry timing, and the decision to keep or discard a workspace. This separation is important: a terminal, an SFTP browser, Metrics, or forwarding can share preparation and transport policy without sharing UI lifetime or an interactive prompt.
```mermaid
sequenceDiagram
participant Feature
participant Prepare as SSHConnectionPreparation
participant Opener as SSHConnectionOpener
participant Route as SSHRoutedSocket
participant Remote as Server or jump host
Feature->>Prepare: resolve route and one shot credentials
Prepare-->>Feature: SSHConnectionConfiguration
Feature->>Opener: open authenticated connection
Opener->>Route: open direct or routed socket
Route->>Remote: proxy negotiate and SSH hop handshake
Route-->>Opener: socket to destination
Opener->>Remote: destination handshake and host key
Opener->>Feature: request approval if necessary
Feature-->>Opener: accept or reject
Opener->>Remote: authenticate
Opener-->>Feature: authenticated connection
```
*SSH preparation resolves data before transport opening; trust approval occurs on the actual handshake path.*
## Prepare the route and attribute proxies correctly
`SSHConnectionPreparation` is a MainActor-safe value snapshot whose potentially blocking Keychain resolution happens in a detached task before socket work begins. It requires a nonempty target route, resolves every jump before the target, and creates an `SSHRouteHopConfiguration` for each jump. A strict `.requireKnownHost` preparation fails if any route node has no expected key; `.allowChallenge` defers that decision to the live handshake. Credential lookup distinguishes an unavailable secret-store error from an absent credential, permits username-only identities to reach server authentication, and avoids reading a protected key before a required passphrase has been supplied.
Each node may carry a separate proxy configuration and proxy identity/submission. The proxy password is resolved independently from SSH credentials and becomes an `SSHTransportProxy` with `ownerHostID` set to the host whose proxy it is. This preserves a key UI and retry invariant:
- A proxy is **not** a `ConnectionJourney` endpoint.
- The first proxy belongs to **Local**; a proxy used after a jump belongs to the preceding authenticated SSH host.
- Proxy connect, proxy authentication, failure, and retry are displayed against that preceding endpoint. Only the subsequent host's SSH connection advances the route.
`SSHRoutedSocket` enforces the same physical order. It connects to the first jump through its proxy, authenticates that jump, opens a `direct-tcpip` channel to the next proxy or host, and repeats. A proxy after a jump negotiates over the bridge before the next SSH handshake. Proxy errors retain the owning host ID, letting the feature request the correct proxy-specific credentials rather than mislabeling the destination as the failing endpoint.
```mermaid
flowchart TD
Start["Start route"] --> First{"Any jump hosts"}
First -->|no| Direct["Open target socket through target proxy"]
First -->|yes| JumpSocket["Open first jump through its proxy"]
JumpSocket --> Hop["Handshake trust and authenticate jump"]
Hop --> Bridge["Open direct TCP channel to next endpoint"]
Bridge --> Proxy{"Next endpoint has proxy"}
Proxy -->|yes| Negotiate["Negotiate proxy on bridge"]
Proxy -->|no| More{"More jump hosts"}
Negotiate --> More
More -->|yes| Hop
More -->|no| Destination["Handshake trust and authenticate target"]
Direct --> Destination
```
*Each proxy is negotiated before the SSH session for the host it leads to, while journey attribution remains at the preceding endpoint.*
## Host-key authorization: persistent trust is independent of a Host
Known-host entries are endpoint trust records, not properties of a `Host` record. Editing or deleting a Host must not move or remove shared trust; multiple identities can be trusted for an endpoint. A temporary approval is held only in the live connection controller and is added to that attempt's expected identities without writing Known Hosts. A persistent approval writes the known-host entry **before** the pending attempt is resumed.
After each handshake, infrastructure observes the negotiated key algorithm and SHA-256 fingerprint. Authorization has a fixed precedence:
1. An optional URI-style `SSHHostKeyConstraint` is checked first. Its legacy MD5 match is an additional out-of-band constraint, not durable trust.
2. A matching expected Known Hosts identity succeeds with no authorizer call.
3. A mismatch against a nonempty expected set fails. Even a matching provisional constraint cannot override an existing, conflicting Known Hosts set.
4. For an unknown key, an authorizer may accept or reject an `SSHHostKeyChallenge`; absent an authorizer, unknown trust fails closed.
Thus a matching external-link fingerprint can reject the wrong server and can annotate a first-use prompt, but it cannot create, replace, or override persistent trust. This also means approval is made during the real handshake-to-authentication attempt, rather than by a separate discovery connection that could observe a different peer.
```mermaid
flowchart TD
Seen["Observe handshake host key"] --> Constraint{"Constraint present"}
Constraint -->|yes| Match{"Constraint matches"}
Match -->|no| Reject["Reject mismatched host key"]
Match -->|yes| Known
Constraint -->|no| Known{"Expected set contains key"}
Known -->|yes| Auth["Authenticate"]
Known -->|no| Existing{"Expected set nonempty"}
Existing -->|yes| Reject
Existing -->|no| Prompt["Ask shared authorizer"]
Prompt -->|accept| Auth
Prompt -->|reject| Reject
```
*Known Hosts remains authoritative; provisional URI constraints only narrow what may be accepted.*
`SSHHostKeyAuthorizationCoordinator` exposes one pending decision to a session feature. Continue Once records temporary identity for that host; Trust and Continue persists it; disconnect rejects and clears a pending decision. Keyboard-interactive authentication follows the same ownership pattern: the C callback blocks only its dedicated transport queue while an async handler answers literal server prompts. A request ID and cancellation state ensure that a late responder cannot satisfy a later challenge; cancellation wakes the condition and shuts down the socket so libssh2 cannot continue with empty answers.
## Authentication and secret lifetime
A configuration carries credentials only for one physical connection attempt. Its `SSHSecret` values are shared mutable secret owners, so copies of the configuration can be invalidated together. `SSHConnectionConfiguration.clearSecrets()` clears target credentials, proxy password, and every jump credential. Public entrypoints defer that cleanup on both success and failure, and the authenticated opener also clears at its own transport boundary. Retrying resolves saved material again; a temporary password or key passphrase is not a reusable connection snapshot.
Credentials may be a password, software private key and optional passphrase, Secure Enclave key, or the marker `.interactionRequired`. Authentication tries the resolved configuration at the relevant hop or destination. When an operation forbids interaction, `SSHConnectionRequest.enforcingInteractionPolicy()` replaces credentials requiring a passphrase or user presence with `.interactionRequired`, clears software secret material, makes host-key authorization throw `SSHInteractionRequired`, and permits keyboard-interactive only when there are no prompts. This is how silent additional connections avoid unexpectedly displaying password, trust, MFA, Touch ID, or device-password UI.
Keyboard-interactive is available to routed hops and the target. It preserves host, port, username, connection ID, and round number in the challenge; answer count must exactly equal prompt count. Time spent waiting for the user extends the libssh2 callback budget, while answers themselves are transient and never a cache.
## Transport and channel ownership
An authenticated SSH connection has one serial libssh2 owner. `SSHConnection` is an actor facade over `SSHConnectionWorker`, whose private dispatch queue serializes all library calls. It can multiplex independent non-PTY exec channels and SFTP channels on the one authenticated session, while a channel budget limits SSH “session” channels. Exec commands use a private channel and an owned, zeroizing input queue, so a command's working directory or stdin does not leak into another command.
The worker's generation token invalidates socket events, timers, and scheduled pumps after cleanup. Disconnect increments that generation, cancels timers, fails outstanding commands, closes multiplexed SFTP channels and the channel budget, and closes the authenticated transport. Connection-level socket failure is reported once, then uses the same cleanup path. This establishes two related invariants: libssh2 is never entered concurrently, and a retired connection cannot have a stale event revive or mutate its replacement.
Feature models apply the same idea at the UI boundary. `RemoteSessionConnectionController.progressHandler(attemptID:isCurrent:)` forwards route progress to `ConnectionJourney` only for the current attempt. Mobile workspaces replace their UUID generation when connecting, backgrounding, exiting, or retiring work, and guard every asynchronous completion against it. Late connection, transfer-preparation, socket, and timer callbacks therefore cannot attach an obsolete transport, clear newer state, or enqueue work after explicit close.
## Retry, retirement, and workspace behavior
A connection failure before the first successful session remains a failed journey requiring an explicit user retry. Once a session has connected, `RemoteSessionConnectionController` can schedule recovery through `SessionReconnectController`; it pauses recovery for trust or authentication interaction and resets recovery state on disconnect. Retiring a session cancels prompt queues, rejects pending host-key approval, clears temporary trust, stops reconnect work, and hides the journey.
The platform rules intentionally differ:
| Situation | Desktop macOS | Mobile iOS and iPadOS |
| --- | --- | --- |
| Window or app restoration | Native scene/frame restoration restores window presentation, not live Workspace transports. Dynamic Workspaces are window-owned and are not reconnected simply because a window is restored. | `mobile.workspaces.v1` stores only ordered local descriptors such as workspace ID, Host ID, kind, title, and duplicate index. Cold launch shows Recent entries but creates no sessions, history, or network activity. |
| Reopen/select | Mounting a preserved desktop workspace does not repeat authentication; explicit retry or reopen may. Moving a workspace preserves its surfaces, transport, splits, and state. | Opening a descriptor reuses or registers one live workspace across scenes and makes at most one initial connection attempt; a failure needs explicit retry. Peer switching retains the live workspace. |
| Background/foreground | Desktop quit/close follows owned-session teardown; independent transfers and services have their own lifetime. | Background expiration closes transports but retains workspace intent. Foreground resumes existing workspaces when their recorded foreground-resume intent is set. |
| Explicit close | The owning window closes its own sessions; closing a pane removes empty workspaces without transferring ownership. | Explicit close removes the live and recent entry and never retries it. |
Telnet is intentionally a separate terminal transport rather than an SSH fallback. `TelnetConnection` opens direct TCP with `NWConnection`, or obtains a proxied socket through `TerminalSocketConnector`; its own UUID generation rejects stale Network and socket callbacks. It performs incremental IAC negotiation, NVT line conversion, terminal type and NAWS support, and applies the configured charset only to application data. Optional username/password automation responds to recognized prompts, consumes and clears the password after use, and falls back to manual interaction when the expected flow does not materialize. It has no SSH host-key verification, jump-host route, SFTP channel, or shell integration.
```mermaid
stateDiagram-v2
[*] --> prepared
prepared --> opening: connect
opening --> waitingTrust: unknown key
opening --> waitingCredentials: local or server challenge
waitingTrust --> opening: accept and retry attempt
waitingCredentials --> opening: submit one shot credentials
opening --> authenticated: handshake and auth succeed
opening --> failed: unrecoverable failure
authenticated --> recovering: transport loss after first connect
recovering --> opening: scheduled retry
authenticated --> retired: close background expiry or owner teardown
waitingTrust --> retired: reject or disconnect
waitingCredentials --> retired: cancel or disconnect
failed --> opening: explicit retry
retired --> [*]
```
*The feature owns visible waiting, recovery, and retirement; transport resources are installed only after authentication succeeds.*
## Operational guidance and focused tests
When changing connection code, preserve these boundaries:
- Build only `SSHConnectionPreparation` snapshots from UI/store state; do not carry plaintext through retry state or reusable snapshots.
- Keep proxy submission and SSH submission separate, and preserve the proxy `ownerHostID` so the Journey stays on the prior endpoint.
- Do not make a URI fingerprint or temporary approval durable trust, and do not bypass authorization on a known-host mismatch.
- Put callbacks from sockets, timers, detached preparation, and authentication behind the current attempt/generation check before touching feature state.
- Have the owner that opened a client retire it on every failed connect and on explicit close; do not transfer a half-open client to a workspace.
The highest-value regression coverage is concentrated in `SSHConnectionPreparationTests` and `SSHHostKeyAuthorizationTests`: proxy attribution and one-shot proxy submission, missing proxy-password ownership, username-only and passphrase ordering, secret-read accounting, constraint-versus-Known-Hosts precedence, temporary versus persistent trust, and cancellation of pending trust. `ConnectionJourneyTests` validates endpoint progression, proxy attribution, pending-route behavior, retries, temporary host keys, multi-key trust, and the fact that editing a Host does not relocate Known Hosts. `MobileWorkspace`'s generation guards cover the platform-specific late-callback and foreground-resume boundary.
## Related pages
- [Platform runtime and lifetime ownership](/openwiki/architecture/platform-runtime.md)
- [Persistence and secrets](/openwiki/concepts/persistence-and-secrets.md)
- [Remote services and forwarding](/openwiki/concepts/remote-services-and-forwarding.md)
- [SFTP transfer and external edit workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md)