docs: update wiki

This commit is contained in:
Kaede Akino committed 2026-09-24 12:31:48 +08:00
1 parent d9968bcc3d
commit c5ded0e526
40 files changed
+2344 -462

No files matched your search

+110 -6
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:938bc144219bb79a0ab503a5b01f70a4d0c95bf6ba6fc1ba47f7c2d39c0ad1d6",
"pageVersion": "sha256:9059f7f4ba5240e5a8338db6e44d6066ad086428faf2ce68e5033ee3443e5fee",
"claims": [
{
"id": "claim_5a53c5a47b7445f7a7b6f8865297a805",
@@ -8,11 +8,11 @@
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift",
"version": "repo-file-v1:sha256:414ce4495383d17da60f76df64b09ae0330227dccec58c227b79b6bfdaedd8aa"
"version": "repo-file-v1:sha256:842f0c1470aea8aaa36c9efe011771c7bc01ae48284e95f4463a9764de948d04"
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -194,7 +194,7 @@
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift",
"version": "repo-file-v1:sha256:414ce4495383d17da60f76df64b09ae0330227dccec58c227b79b6bfdaedd8aa"
"version": "repo-file-v1:sha256:842f0c1470aea8aaa36c9efe011771c7bc01ae48284e95f4463a9764de948d04"
},
{
"resource": "repo://TFM/Design/DesignTokens.swift",
@@ -432,7 +432,7 @@
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift",
"version": "repo-file-v1:sha256:414ce4495383d17da60f76df64b09ae0330227dccec58c227b79b6bfdaedd8aa"
"version": "repo-file-v1:sha256:842f0c1470aea8aaa36c9efe011771c7bc01ae48284e95f4463a9764de948d04"
},
{
"resource": "repo://TFM/UI/Components/WindowToolbar.swift",
@@ -515,10 +515,114 @@
"version": "repo-lines-v1:sha256:9fe71383b1a7409737a0423116f0442d840d99b9d3f67c5897150557f9d1d3a5:eyJzZWxlY3RlZExpbmVDb3VudCI6OTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg3MzY5NzUyNDZiMjY4NTZkODdhYThjYjM1ODA1MjJjYTJkYzA2MTVkNTIwMmExZjIxYjY4MWY0YjFjYTdiMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2YzNhMTM0ZGMwMjM4ZTVmN2QzOTU3YWJlNDczNmM2OGRiM2U1MDBkYzhmNTY3YTA2ZjEyY2RlNDE1NzlhZDgifQ"
}
]
},
{
"id": "claim_70291dc0993f43d7810661b979761e29",
"statement": "The main scene's fresh ordinary WindowModel starts at Vault/Welcome; registration injects shared connections, host and metrics models, history stores and a shared conversation store while each window retains its own workspace and query state.",
"evidence": [
{
"resource": "repo://TFM/App/AppModel.swift#L500-L510",
"version": "repo-lines-v1:sha256:8d60f7c0c86800b462208ebcb7d3485bdafba13671b3ea8f9e70e14fb11cb7ab:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyZGM1ZjhiMjc2YWM4MjBlNzdjMWZkYWIwYzU1NGFkMGE5Yjk5YzNiMGIzYmI2N2U3NjM4NmIwNDM0NjQzNTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI3OGFmZWJkYzQ2Njc5MzZiOTQ2NDFhMWQ1YWFmMzQ5Y2QwNjUzOGVjY2IzODBmYmJhZGRiOGU4NGVlODJlMWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyYzU5NzJkMDQ5NDFjYjgyODk0NTM4MzExMWFjZGVmYmY0YTdlZGU5OWU4N2RjNDdhNzk3ZWJhODcxZGU4YTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRjZjgxOTQwODBkMTUyYWZkZWRmMTYzMDBlODcyMDMwOTc1YzIxYjNmZWZhODAwMGE2YmFmMWFjMDkwYTBjODEifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L187-L219",
"version": "repo-lines-v1:sha256:cd2c77eee97db34a3239f11c536d64e576b6097d8fa611a860d9e3c543f89ba8:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxMDk3ZDRjZTdkZDAyOWU5OGI2YWFkMjViMDFiYzEzNzhjOTdlMzA5YmRjMDY0YTM0ZTI2NTQ4MTFmMTgxYWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZThjZDVkNTA2ZmYwYjY4ODQ3MTFjMmMxNTI1YjdiY2UwMmY0NDMxMDU2YTk3Y2E0ZDQ1NWY3N2Y5MTg4MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQwMmQ5OGU3M2M3ZmQxZDQ4ZjUzNjdjZmY5NGFlNGYzNDlhZTYzZmIyMWRiYzkwZmYxYjZhNDViYjNmOWQ5MzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdiOTZhMjE0MmNhYWZkMTdiNGEzYzMwYjI3MDMzZWIxMDMxOWZjNzEwOTFhMTc5NzY4YWQ3YTVjNmU3NmE2YjAifQ"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L23-L99",
"version": "repo-lines-v1:sha256:d04d539d7de70dcf43a41a5038eefba6f66a1a8f32b838cfb7f1c6cc27ba72eb:eyJzZWxlY3RlZExpbmVDb3VudCI6NzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY5NmFiZTAwOGM2OTQ0YjBhMzJiZTcyZDM2Y2ZmMjNkMDc0MmE0MDEwMDIzY2I4NmFhNjYwNjAxMGFmMWM3NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFhNjhmZTVkYjBlM2E1OGFhNGZhOGY5YTA2NjlkYTRjMTNlMzNlOGIwNTZjOWIyMjY4NjdmOWU2NmJjOTA1MjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyYWI5MjFkZTcwNzQ1M2ExZmE2NzA4ZjljMDI3MTQ4M2UwODFkMjFlNWI1ZGU1ZDEzZjBlNzYwNjBiNzYzZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxNDc0ZjAxOWNlNjI5YmVmNzc0NDgzZDgzMjMxOWUzYWE3YTZlMmVjMjc0MjEwMWQwZGJlNzMwNGZiM2YyNzgifQ"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L308-L323",
"version": "repo-lines-v1:sha256:fcace42c034b475e6a1d022e076df28e4ae6ef54d07c860cd308001c86334b0a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyODgwNTA4Y2FkZTAwMmU3ZWE3Y2MxZGNkMmEzZjgxNTJkMWViMDlkMTU4MmU1ZmFiNjc0YzY5NzkyZDk3NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY2YzNiMDAxYjdkMTQ5NmVkZTZkODI5ZTNjNzRhOTIzYzJjYWE0NzhkNzY3YjY2NzY3YTlkM2ZiZTk5N2Q0NDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIzYjMwYWI4OTJjMWI3YzZjNzYwNmRmYTAxMWE5NmJhNzdlZDZlZjZjMWNiMGJlYzI4ODA1ZDU2Nzg4MTQ4ODIifQ"
},
{
"resource": "repo://TFMTests/MultiWindowTests.swift#L74-L100",
"version": "repo-lines-v1:sha256:20ec2655a06421bc688bd28739588f5b89147cf3e62baf967a2656f9e03a0bd2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAyNDAxZTdmMmNkN2RlOTYxOTJlZDY4MjA0NGIyZDdiYjViZWVmYjhlMDU3NmZkNWM4NmY2MmQ4NjE3MTM1NTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJjZDY5MzQ3YjVlOWFlOGMzZjFlZmVlZWMwYzAzNmZlZWU0MzI5NjFhMGRlOTZiZmE0MDE5YTI3NTA4MWZkMGMifQ"
}
]
},
{
"id": "claim_6e670351edb340cf983825afaa3cb37a",
"statement": "The main WindowGroup suppresses automatic XCTest windows by default in debug unless TERMIND_WINDOW_TESTS=1, and disables main-scene restoration for tests and screenshot demo launches.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L14-L33",
"version": "repo-lines-v1:sha256:25a8c6dff46ec83a0b40c47dd446a1d70c15967cf565eb5ac2ccc23b9210ea1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhMmRiNjZmNGE1MzI1NzVkYzUwZmJjOTFjZjRiY2E4YjE1ZDdlOGQyYmU5ZjVjYzE4ZTA2NjI2NTljMGE1ZjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwNGE1NDQyNzMwZjkzNjk5ZjI1YzU0MTNiZDc0NTViMzZiYWNiYzNkMmVmZTU3MDA0MmFmMTdhNDU5OTUwNDMifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L196-L219",
"version": "repo-lines-v1:sha256:aaa519f879ab100ca6831150681b52adb7013af1c105ac40772fdaea28a1298e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwNTgzMDJjZDFmMDQ4ZTE3MzU1MTUxODA0NzRjYmI4M2YwZjhkZDNmN2I3ZjUyODI4ZDU1ZmUxYjg1MmIxOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZThjZDVkNTA2ZmYwYjY4ODQ3MTFjMmMxNTI1YjdiY2UwMmY0NDMxMDU2YTk3Y2E0ZDQ1NWY3N2Y5MTg4MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ0MTA0N2ZkYjNiOWIzMTYwZTU0NWEwOThlOGJhY2E1ODA1YTJlZmFjNGI3YWRkNmYxM2IyNDg4NWJjNmY4ZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdiOTZhMjE0MmNhYWZkMTdiNGEzYzMwYjI3MDMzZWIxMDMxOWZjNzEwOTFhMTc5NzY4YWQ3YTVjNmU3NmE2YjAifQ"
}
]
},
{
"id": "claim_f98b1f7a7b0243d1b3633d16bbb655e8",
"statement": "RootView binds native NavigationSplitView visibility to the window's sidebar state and keeps all workspace children in its detail deck while layering the selected non-workspace destination above them; its floating status bar appears only when a workspace is selected.",
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift#L29-L70",
"version": "repo-lines-v1:sha256:5d42f029a82524958f747a6f23483b5ca7b44c1f9abf9c46df9f75c5970a87bc:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY5MDFkZDM3NjU2Yzk2MTY4Yzk2ZTUxYzMyNTZiMDdhZWIxZGU0NzY0Yzk4N2VjNmQ3ZThmZTVjMmQ0NWNjZjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYyMmUzZWI1YzYwZTQ4ODIwMDE2MTYxODU3NjJmM2MxZjgyZTJkZWQ0MTkxNGNjMGM3YTFiYTBjNTcxOTc5ZTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjMmM2OGRmMzhkZTU2YmE2MjcyOWRmODk2OWQ4MGE2MjYwMWFmZGI2YmFjOGZiZGI1ZmVlYjliNTVmNjg4ZTgifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L331-L399",
"version": "repo-lines-v1:sha256:054998fef71ac9721b7f72ad534a20be5456ea2ec14025075617742f5264f968:eyJzZWxlY3RlZExpbmVDb3VudCI6NjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjNDc0NDhjZWU5YTg0ODgwNmY4ODExZjNhMmJjMDM2YWFlMzcxY2UwMDkyNzczYTQyMzk4ZTkzODVhNWU5MDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc5NDg1Njg5NjMzNWRmZjM2ZTdkN2ZhNWU5Y2EzMTAzMGEwNDk3MDgwMTg4ZjdjNzg1MzMwZTQyN2Y3N2Y0YjQifQ"
}
]
},
{
"id": "claim_ec386f8c9959431c87081ed1aede8b97",
"statement": "A persistent window activity bridge reports key-window activity and the focused SSH session's optional remote title independently of whichever pane view is rendering.",
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift#L434-L462",
"version": "repo-lines-v1:sha256:4a2c9ac3436472bf38f6133678fe7869c5579ec2c505ec462f1b9c2ed4fd2433:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3ODVhZjQ2YTU0ZmRlMmQ2OTY2N2FmMzAzNjhiNjUyZGM3MTY0N2M4NWVkMjY5OThmMTE0Nzg3N2FjZWY0NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2NjMwOTVmN2UyZWVkMzY5Y2MyMWQ4ZDk4Mjk4NjdjNDI5NWNjNmExMmMxOWE1ZDFkY2I2ZDRjNWZiNWRhODUifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L501-L548",
"version": "repo-lines-v1:sha256:16ca203c39874b928440230d80b4debb4e5b509c080941decf080c348709b6c8:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE1MjM0NjFlMjQwZGI1NWM2ZjdkMGQ4NTU0ZWJlMDM0MWIwOTFmZTk5NWI5YmU1NTNlNjE3MzNlYmM4ZWI1ODUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE1YmMyNGE1ZTA4MDMzNjk4NjUyODFmYzJhMmQyZDg1Y2E4ODY1N2MyN2ZmNWY5MTM5NTg2Mjc1NzI3NzJiYTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L72-L82",
"version": "repo-lines-v1:sha256:efebb19ced7e2e70c6d08aeff7113b7959b7669b42cdaeaca66b70f09cb67f39:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2NGE3MjFlNGM4MTlmMDg1ZmYwY2IwYWVkNjg2YjgyNGY1MmZhOGM5MzA4OWY2YWMxOTU5ZjAxMWJlNTZiMWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkxNjUwYjQzOGI1ZjY5ZTI3ODdhYTZhNjJjODEwZjU4ZjMyZGIzODQ3ODUzYjA4NTQ2ZGY3ZmM5Zjk5ZDI1MzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQyYTc0OTNmYTgzZDczNmE3YzEzNzZjOWU2MDJlMDZjNjMyMzFlNGE4OWVjMzYzYWMyNmJiYTY2NjUyMGUwNTQifQ"
}
]
},
{
"id": "claim_d1fea77d65bd4f9f97305e5389597bae",
"statement": "Settings routes are window-local and Back climbs the route hierarchy before restoring the previous destination, falling back to Vault when the previous workspace no longer exists.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L58-L91",
"version": "repo-lines-v1:sha256:dabf8ad89481961f99d67b77951ffa94c484b04a1cda63111875e59987946dfd:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFhYzNlYjg3YzY0MDcxYmQ1ZWE4MjIzMDNmODg3OWEzMzljZDA4NTVkMGUyNDA0NDk1YWIzNmY1NmRkMWE4MjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwZTNiMDdhZmRiOTQ5MzMwZmQzYmFlYWE2YWE1Njc2ZTQxYmQwOGQzOGQ4OGRmNDljYTkyYzRmMTJlMjljNTgifQ"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L584-L620",
"version": "repo-lines-v1:sha256:09ee17ae6dec430f48790f3ffc1eb6e268c2beae85238bd679a3e6d1a23b2718:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ3N2U2ZGVlZjczYTA3ZTg4ZmQxZTk2ZDA3ODU0ZGZjYjI2Y2MzMjM2OWU3OTg0YmEwNjc5ODY4MGQyMzM0NjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzOGRhMDk0NzRiODU3ODdiN2ZiYzJlYjFmNDUzZjdlMGE4ZDMyYWVhNTFkYTZhYmU5YWY2YzI4M2IyZWQ2MWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MmU3MDJiOGI2MTYxNmJjNTI0MGY2N2VkNWM2NGIwMDgyMjdhZDJkZDhiOGUwMzcxYjI0YzRlYmUxNzgwYzYifQ"
},
{
"resource": "repo://TFMTests/SettingsNavigationTests.swift#L94-L135",
"version": "repo-lines-v1:sha256:3d145ffc1d21e8dca2c168bf743d81343270397c08312fbe1e1b4d346efb2a68:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjNTNiZDQ4OWQ2YWQ3YjRkZGM1N2ZjZWRmNzczYWNmZjBlODllMjNlY2I1ZGMzNjgxMDg1NWJhMjQ2YjhhY2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc2YWQxYWNkZGZlYTA2OGY1OGMxYTFhZjc1ZjczNmVjZGUzNTEwNjNkOTY2MzUwNjA3MzllYzkyNDhhOTM1YzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRhMmFiM2YzMzAxN2UwMjAxNzA3ODE2MTkxYTgzNTdhMGZiNmMxNzdlZTllMDU4ZWRhZmJhZjUxYzZiZTJhYTYifQ"
}
]
},
{
"id": "claim_a2b685f134854a0bb6948e3ce65f50e9",
"statement": "SettingsPageView cleans up incomplete provider, MCP server and skill drafts on route changes or disappearance, so leaving Settings does not preserve an unfinished editor unconditionally.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L198-L230",
"version": "repo-lines-v1:sha256:c452b24bac854e836d8336333344cc3b53143555cfca728802125619d8755309:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiNmE0N2NjYzUyMzA3NTRiYzM5M2QxNTBhZTJmMWUyZTA1ODcyNDNmMDYwNTJkMjdlNDVhZGQwZTI2ZThkMzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY5Y2EzNjgxODVkZGMxMmUyZmNhZDdmNjEwYjVkYTkzMzhhOTg0NzBlZmM2ODJlOWI1MDkwNDM2NGFhM2EzZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIxMzJkOTY2ZWQ0MWIwOWU4ODE4ODkwNGFmZGFmNTQ0NGFiOWQ1ZjUxMDRiZDhmYWUxZmVmYTIzOTQ3NDhjNWUifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L93-L108",
"version": "repo-lines-v1:sha256:db0cdc606501db2f512721e050b7e0b4991b51c176cbeb289e952653a3a8a600:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ1NzM5OGMwZjAzNzM4YjI2YWE2YzA1NzMyYTE3YzJjMzBiMGI0NzhhMWZjZDc1MDkyODcwOWM4YzJiOTdmZDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNlMmU0OTU1MTE1NmQ2ZGVhMDY4YTgwZjUxODI4ZmM3ZjRlMGI1YTdiNjMxMDIyODhiYmM1ZGIzNGVhNDZlYjkifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-23T17:44:09.687Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,18 +1,26 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:c98dff9d40631bc19e57fdb22630d6e71b61e9ae4bb1c36d272e7afcd5b7adeb",
"pageVersion": "sha256:6104dff58c8230d240a00bc70ad61ae5e2e6b2fb6e27794965ddfa1ed6b1c3a1",
"claims": [
{
"id": "claim_72f9329a158e418cbf0fd6394f82815e",
"statement": "Shared Domain, Application, Infrastructure, Remote Infrastructure, Presentation, and Persistence modules have enforced dependency responsibilities, while TFM and TFI own platform UI, adapters, composition, and lifecycle.",
"statement": "TFM and TFI own native UI, adapters, composition and lifecycle; non-presentation shared modules cannot import either app or AppKit/UIKit/IOKit/ServiceManagement, while TermindPresentation has a separate, broader import ban on implementation/storage frameworks and app/platform modules. Application and Persistence have additional directional dependency exclusions, and source tests enforce only their listed imports and token checks.",
"evidence": [
{
"resource": "repo://AGENTS.md",
"version": "repo-file-v1:sha256:632f6d657005b76fedd90a1e9c7d1f76a878dd5b8025fd4cc066d89f7234ce42"
"resource": "repo://AGENTS.md#L3-L18",
"version": "repo-lines-v1:sha256:62217327b79d7297650cd02141e4ab8f1dcd1de6e6bd18c026467d1c9a0f2565:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3NmYxY2NlMDU0ZTZlYjE0YTIzZTg4MDI2Mjc0ZmI0YzA0ODM5YTcxYjY2ZmZjY2VhYzkzOWUyZGM0ZjRhYTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkZGU5NTEzMDRlMWFlZTY0YjNiMmJmNzVmZDMyNmIwMmRjNDkxOWI5YTgzODBmY2U2NWEwMmNlYzkxNzM3YzIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhZGU5Y2M2MTdlODVmZTg2MzFjMWQ2ZjhiZTAzZTViZDE4NmQwYzhjOTI1ZjY0ZGIzMmU0ZGI4YTBlYTY1NGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE1ZDk3ZjJlMDczOTEwM2Y3NTEwNTI5YzYwNWY4NDkyMzE3ZDQyZjQwOTcxMDRhZjJkZDIwYjhlMjZmYTJjZjcifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189",
"version": "repo-lines-v1:sha256:533ff177b0412702e1b6b394a55e194a0822100402bf01b72c9a251a120fd83c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZlNzcxZDQzY2JjOWYwMmY5OWUzNTkwNGQ0N2I4MTQ5YTliODZmZmE2M2Y5OTQ1Yzc1ODk2NGM2YzllNzZlZDUifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L331-L355",
"version": "repo-lines-v1:sha256:a70dc1fabcec376d76875d93c5fe83e7477f91afab3cd081fd0d3c7340ddaa41:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwODJlYzhiMDRiNTlhNjdhZWFhYmYxOTVkNWE5Y2I4YWJkMGE3NjBjZDc4YjE1MTNhNzg3MTA0MGE3N2Y0Y2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0ODVjOTkxNGE0ZTFmMmY4YzUzZGM1MzYyODQ3NjI5MGQwZDAxYmFkZTA0NzQzYjVlNjczOGYyNTk4Y2M0YTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L64-L106",
"version": "repo-lines-v1:sha256:08c476cc632f29ebd0f9b7221558d60dc77bb9ac8d88d819e4d8841a8372d835:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4NWJlNTRjNmM2MGZmZjQ5ZTllOTU1Mzg1YjMzZTc4ZTRkNGQ4ZDJkNmUwMWQzMzJkNjhiNjg3MTA0OTkxYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ"
}
]
},
@@ -30,11 +38,11 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
@@ -608,7 +616,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFMTests/AppTerminationTests.swift",
@@ -644,7 +652,7 @@
},
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings",
"version": "repo-file-v1:sha256:b3bb65bafaf0fec7f526e66d0d6a2f0573996ebd7f23192be9adffb448dff93a"
"version": "repo-file-v1:sha256:4f4306f2a6cb887d5b85a0f1c26e4ec4fb873d46adaadb1491ca1be3c54ed93b"
},
{
"resource": "repo://Frameworks/TermindPresentation/Strings/AppStrings.swift#L1-L6",
@@ -687,10 +695,102 @@
"version": "repo-lines-v1:sha256:cbb25b46763f864654c3ac4a6dd7504e694a1e1a21d4dd0b4c09be63ef968f99:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ2ODljOGU1OGVkNzE3ZmM0Y2U4ZjA1MTJmNWRiOTFlM2YwOGQyZTZiZDI5MWE3NTU4YTkxNjM3NmU0OTc0MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ"
}
]
},
{
"id": "claim_657ae50739614778b2b19dfe8d10b3b7",
"statement": "The macOS app is its own XCTest host: DEBUG test detection uses an in-memory SwiftData container, suppresses automatic windows and restoration for ordinary tests, and requires an explicit visible-window opt-in for tests that show windows or take focus.",
"evidence": [
{
"resource": "repo://AGENTS.md#L38-L46",
"version": "repo-lines-v1:sha256:070213e98b52cec4fdee409349c32e94d42a6a1c41a2f6b5e43523d08e46b11b:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTdmYzk4NmVmMDFlZTVmNThjNmYxZmEyNjViOGE2NDEzMTE2OGY4YWE1OTkzZDc4ODZkOTZjNmUxODk4OTQzMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDFkYTg3Nzk4Y2M5NTc1N2I3NzQ0NThlYzQ5Yjg0MWRjYWMzODA1MWQ5MjljZGI5ODE5MGJiMTdiMjdkZmQ4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L14-L33",
"version": "repo-lines-v1:sha256:25a8c6dff46ec83a0b40c47dd446a1d70c15967cf565eb5ac2ccc23b9210ea1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhMmRiNjZmNGE1MzI1NzVkYzUwZmJjOTFjZjRiY2E4YjE1ZDdlOGQyYmU5ZjVjYzE4ZTA2NjI2NTljMGE1ZjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwNGE1NDQyNzMwZjkzNjk5ZjI1YzU0MTNiZDc0NTViMzZiYWNiYzNkMmVmZTU3MDA0MmFmMTdhNDU5OTUwNDMifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L196-L230",
"version": "repo-lines-v1:sha256:78f019aebda1d52b1314cea5b2016d0de3654df1128d7a353152df4c4b1901e4:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwNTgzMDJjZDFmMDQ4ZTE3MzU1MTUxODA0NzRjYmI4M2YwZjhkZDNmN2I3ZjUyODI4ZDU1ZmUxYjg1MmIxOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjZDE3ODg3ZDhiOWFjYjJlZjc4ZGRkZmJiNTJkMWEzM2UwZWI2MDRlMmU1NDczMjI5OGZhNmUyMjgyMjc3N2YiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ0MTA0N2ZkYjNiOWIzMTYwZTU0NWEwOThlOGJhY2E1ODA1YTJlZmFjNGI3YWRkNmYxM2IyNDg4NWJjNmY4ZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM3OTYxNjQyMmZhZGE5MzNmYjVmNjE4MmEwMTZkOWQyY2QzZmUzNzA5YTc5NDZkNTY2ZGVhZjQyYmMyZGQwMmQifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L50-L59",
"version": "repo-lines-v1:sha256:df43cacb6c3f82b257c13a277d4e5b926ed0b8fa1a7f4eddff14820ddabcb010:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjMjU4YjdiNGY1YjRhZjg4NjE4ZDI4NGJkODg1Y2VmYzNiMmQxOWRhMTk5OTlmN2ExNDI0YmQxMDliMjNjZjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQyOWZhYzk0ZDIwZGIyY2RjNzE5NGYyY2M5OTg3MDdiNzgyN2I0MmJjNDI1NGY1OTJmYjZiNTE3MGIxMWZhNTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRhMzY1Mzg4MWY4OTIzZGEyYWJmM2JhZDNmMmJhYjNiZGI4YTM2Njk1YjY5MmY5YjlmNmExMWI3NWQ4MjkwZjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgxMzg3NGYyODJlNzVmMWQwNDYwMTg5Mzc2MDhkZjBjMDRkZThlOWI3ODQ3ZGJiNjNlYzBlN2MyZGEzZjIyMzAifQ"
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L12",
"version": "repo-lines-v1:sha256:647fdf978ecd85719df899c592ebd2386dcf8c24b7371545e9ab0dcf3e0402df:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
},
{
"id": "claim_6bf9afb864f146b0a31354503aeeb5c4",
"statement": "The mobile app runs its real scene with testing dependencies under XCTest, while mobile key-window integration tests require explicit opt-in and disabled parallel testing; manually authorized StoreKit tests likewise remain opt-in.",
"evidence": [
{
"resource": "repo://AGENTS.md#L42-L46",
"version": "repo-lines-v1:sha256:6245a22c3122ab4ea6e92fba5efecc31066e1cc232f01cd9beee123f12eb8f74:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTczYTI2N2E2ZGNmZTczN2MyODUyYjY2OTkyNTViNWZlMWViYjYzMzVlZmZiYzgwZjA3ZWE0ZWExZTBhNzdlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://TFI/App/TermindIOSApp.swift#L12-L34",
"version": "repo-lines-v1:sha256:82863fc0284f2bb6a15996cec480f52171a1bb6241e565a4a60cec80d102152a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhiY2M2MTFhZjIzYTkxYzNiNzI3ZDBhY2U0ZGUyMjI0MmZjNDkwNmM3MTk0YTYzNDkxOWI2NWQ3MDNkZDAwYjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNmYTc4NDM4ZDRhOWM4YzI5OWQ1NmJlNDRmNDNhN2Y1YWQ5M2FjYjRlMzllNzI1Y2YwMjYwYjY0OWQ4NjA5YWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwOWRlZDA1YTMwZTBiMDk1ZjI3NWRkNTcwMzRmNzU2NTgzNjBjOWQ4ZWIyNTg3NjNjNGI0MDMwYmM5ZGRjYjEifQ"
},
{
"resource": "repo://TFITests/MobileEditorToolbarTests.swift#L7-L14",
"version": "repo-lines-v1:sha256:548867f824e81d16cd474c538a7cfe69cd4facd65ee848a074a3efa3bb4d02bb:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZWY5MjllMmY3NmM4ZjhlNDUyZWZlMTVlMGUzNzY4ODVlYTEyMmY2NzA3ZmRiZjk0NmQzNDZhNmI3MGZkMzVkNyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTA5NmUyNjdlNmFlYTMwNDJmNjA2ODcxMmYyOWZmNDAyNGY2ZjE0MmI5MzJhNDExY2M4M2UzYTJlNTlhYzM5ZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiM2U1NmQ3MWMzNzQ3MjBmMjJhNGUwZDViNzVhNWY2YTZjYzEzMWQ2YWM5ODA2N2QwZWYwNjc3NzVkOTNmMmMzYyJ9"
},
{
"resource": "repo://TFMTests/StoreKitTrialTests.swift#L10-L19",
"version": "repo-lines-v1:sha256:754f75e284aba045815665f1f66f780e8c0a491cd7fbfc4a0e4b81734c6b7e0a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiYWY5YmFlYjFlZTk1YTkyYjNkM2IxMWMwNzgxZjcwMDQ0YWY1NjA5MGRlOTI5NzIzZmMxYmU0N2ExZGJlN2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYxYzIwNDFhNGM4YzY4ZGRhNjVmMmNmN2U0ZDM5NDViOWQ1ZTljMjczZDEyZWY2NDZiYWU2YWU1OWI1MDljYjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVhZDZhZmM3NjI3N2FlMDBiZGZhZDQzODg4OTk2NTAwZjgyMTQzMTkwMjJjYjJlYjdiNmMwNWQ1OWQ4YmY1MzYifQ"
}
]
},
{
"id": "claim_f7731d3ba5e1434a9fca26bd7392e636",
"statement": "Both shared app string catalogs are manually maintained; a single target's stale extraction flag cannot justify removal, and catalog edits require manual keys, Chinese translations and canonical Xcode-compatible formatting with generated catalog symbols disabled in the project.",
"evidence": [
{
"resource": "repo://AGENTS.md#L48-L69",
"version": "repo-lines-v1:sha256:26697577d9457afd4d5953ff5464ff3ce8419e303deb7f51ea1d9644abdfc2ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdlYjZlZDYzN2JlNjgzYzc2MTJmNjc3ZWE5ZTFhNTZiOTY1OTllNzcyZjZkNzY5MGI0MjM3NDBjZDE0YWZmZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg0NTE4ZWQ0MjVmYWVjYTU4MTRhMWMxMDE1NGYxMzI4MThlYjNlYzBiNmU4Mzk4ZGY0OTRiOGFkZjdjM2EyNDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4NmYwZmMyNmM4NWViY2IwODgwNDgxN2JiMGQzZGJkN2EwOWE2MWE1N2RhOWEwNTk3YWFjOWU3NWQwZDc0OTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlZGM0MzMyOThhZDU4MTI5ZWUwYTg4NTJjMTNmNTI5MjBkYWFmOTRhOGM2NGE0ODcxZWVlZjQ2ZTEzMTVlZDIifQ"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L1-L6",
"version": "repo-lines-v1:sha256:a4f7e4e8cd45a6a2e257248bc9cef3775d26f29a5f556dc4f80c9f52b74cddea:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDY4MmNiZGI0YzhiMDc1MThiZjQ4NmM1ODk5MGZjMzkxNzgzYWEyMGE5MTZiZmIyN2FkMjExZWIxZDVjMzY0MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOWVlYjY0YTVlNDE3MWJjNjIxOGQxYzVhMjRjOTYwYWY3YzUyOGYyYjBmMzU3NWFjNmFjN2VlYzE5M2ViNzM2MyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWFhZjc2MzdjYjZlN2U1ZGI4NWQ2MzQyNzQ2MDE0ZGYwNDFjY2Q1NThhOTIwYjI5ZWI2YWM3MTlkN2JhZjVjMiJ9"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L75-L80",
"version": "repo-lines-v1:sha256:6c71ea7347ff9717c89060d589415e0ed157060322ff0439a96fa684359794ff:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDk3MzhkYzIzYzYwZjQ0NmMxNGQ3MTNmOWRiODZkNWNiNWMyOTcyOTI3YjQ1MWYyZjI3OWZjYWM4ZWMzZDM5OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTc0MTRjYzM0NWNjNmQ5MTY1YTdhOTk3ZWUzZGRkMjU1ZTExNjMxZjRkZWI0OWE2ZTI2MzNlNGRiNjljNTFhYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTZiNDZlMTg5ZWQyZWEzODEzZWI3OTY0ZjcwYjNkMTBjZDUxZTFhMGIyZGNkYWNhODk4N2QxNGNmOTA3NzYxMyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMzYxYjQ1OTI5ZjJiYjIzYjY4NWM1NDdmNjdkOGI2ZTY1NGU2NDQ5YTYzOWQyZDc2ZjVmN2VmY2ZhMWVlMGNjOSJ9"
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj#L2390-L2400",
"version": "repo-lines-v1:sha256:a5e12a77a7764bfcbd2896f54217211f096a94bc1df7541e2f1159eecdaabde6:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJiNGY1ODNhODRkZDg3NDc4YTRlNmIxY2JhM2I0NjUyZDlhNjI5NjVmNTJhYWQ5M2I3MDJkZTU1YjlmY2Y2OWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFkNDQ2NDFiZDU3YzRmZjlkZjE2NjExN2I0YjMwZmZkMjM2OWU0MjYzMmJlNzU1NjhlNTc2MmZhMjUzMDQ2MWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJlNzdiMjEzMTgzZTI4YWFhMDQ1ODg2NjI4OTg3MmIzMjYwZDgyZjU4YWZlZDYxODY2NDFlM2I0MzY0NjdmYjkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI2YjJlMTUzMzgyM2IyMmIzODkyNTcyZGEyZDMwZDMzNjhhZDY2Y2I1OWQ2OGMyODAzY2EyNzA5NmE0N2NhZDQifQ"
}
]
},
{
"id": "claim_30fa6fb3a20846278d3e974449f71b27",
"statement": "Localization checks complement rather than replace rendering coverage: the SwiftSyntax copy checker flags selected UI literals in TFM and TFI, while the Chinese catalog checker verifies normal form, valid JSON, finished zh-Hans/zh-Hant translations and spacing; neither proves semantic reuse or display-time correctness.",
"evidence": [
{
"resource": "repo://Scripts/check-presentation-copy.swift#L5-L18",
"version": "repo-lines-v1:sha256:092f3212071893f610272a62e0dee5a7c9296cffe95064fc25cc8ed65bc5ce27:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkYTY4ZDE3MmNlYjAzZWM2MjVmYTAwZDYyY2NkMGIwNGViYjIzOTNjMjRkMzQ1NTU0YjMwNTdmZGU4ZDQ4NTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFkZDI0NDU4MmI2ZmIwM2QyM2I4NDE1YWJlY2QzNDZiMGM5ZjQ2NmI2Zjc1MmIwNjgxODljZTdlOWEyZGMzNTAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU3OTQzZmRkMjkzYzI3Yzk5YmQzZmU4MjlmOGZlY2EzYTFkZjc3MDZmYmMyNTIzZjAxNDE1ZDgzNjA3ZTVhMzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU3NmIxOWU5ODgxNmYxMjE5NjE3ZjQzZTljMTM2ZDZiNTcxMGQ5ZmVmNzAzZmFhNThkMzVkNjY4NGIxMWYwODUifQ"
},
{
"resource": "repo://Scripts/check-presentation-copy.swift#L64-L87",
"version": "repo-lines-v1:sha256:e567e2575025771a0f17f7c9e93126a63ce6c603b8f0c2e32035f9f7731d4860:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA1M2I1YzQ2NjY5ZmJhOTI5Y2YxNmEyNmEzM2U2MGVhNWIwYzFkNzg3OTc0ZTMxNzk2OTllMWU5MzMxMTFhMDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU1ZjZlYjBjY2QyNTMzMWVlNTZkZDAwN2Q2MjczOGQ0NDAxMjIzMWViMmI2NDhmNzhhYjA2ODc5Y2Q5MGNkNWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://Scripts/check-zh-localization.sh#L14-L83",
"version": "repo-lines-v1:sha256:66d33c11a796d748134e553af6f6bc5b8dd19a82d14280b913d46da6a3505ef5:eyJzZWxlY3RlZExpbmVDb3VudCI6NzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI2NTZiMjUzMzVjOGI1YjI4YTBjNjRhMjVkZjBjYWJmNjJkMDVkZjhhNTliOWRmZDc5OTUwZTQxMTUyOTg0Y2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxMTdmYTAwNmJhOTIwODUwMGIyOTMwY2U2OWNiZGU0MzZjNjQ3YWZhOTE3Y2I3Mzk2YTliYzkxMTFhNDZkZDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhkMGFhZDJlMDgzZWJhNzdiYWQ5NWFjZGRjNzc3MjIwMGNkM2IzNzQ5NTIzNDUzY2E0ZGQ2MDQyMzM5NTMwODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc4OTQ2ODJhNmM3OGFiNDA4MTM1NDJjNWNhZjRhYTFiYTAzNTc4YzUxY2Y3YTI4ZTU0MDVlZDJhMDUyMzBhNWEifQ"
},
{
"resource": "repo://TFMTests/PresentationCopyTests.swift",
"version": "repo-file-v1:sha256:a37d54e2ef924e188aa580f0af11121b3862816e04ff51ccc5a6fd024a01e1b6"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
+46 -14
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:c49415f8bc3f829076c2361a4f7e5a7f8ebcfe6ea0548bee4d615d0ad7df8ee6",
"pageVersion": "sha256:751205f27f04ee23745dd8b6b671c9a7dd342d6e1dffb1cc4a5d00b31733bea7",
"claims": [
{
"id": "claim_34230e88036241baad093fb8de5bac8e",
@@ -8,21 +8,21 @@
"evidence": [
{
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:2707fdefa5e5b61d74a8007e3e4cc90ce473cb9aaae0a52b2a80c63fd79583c3"
"version": "repo-file-v1:sha256:d274fb868d56884ebf7706a94731dbf0be5e7940b49d30176e970088d833b455"
}
]
},
{
"id": "claim_2324a55cebbd45be98b1e10c43bd8612",
"statement": "Shared frameworks cannot import either app target, while Domain, Application and Presentation have additional implementation and platform restrictions enforced by ArchitectureBoundaryTests.",
"statement": "ArchitectureBoundaryTests check app-target imports and selected implementation and platform imports across shared frameworks: five non-Presentation frameworks share a no-app-import list, Presentation has its own storage and platform import list, and Domain and Application receive additional restrictions; these exact-import guards are not a universal prohibition on conditional platform UI in Presentation.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L164-L187",
"version": "repo-lines-v1:sha256:45ac2d747c736c3bb9821104587d21ef897e4ec32ff8b25b11479a6ca7608f89:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk3OTk5ZWY4ZDk0Y2NkYzU3ZmJhZDE1NzllYmJkZTM4YjIwYTUyNDk0ZGMyYWYxNGFiZGU2MjY5NmJiMTMwOGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzNzgzMjY0N2Y5NWFkMDc0NDExNjM1OThlMWU5MDhiZDM0YmUxMTBkNjNkZGE1N2FjMTc5NjIwM2VjZmNmYjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM5YjJkYjM3YThjY2FiMDIzMTkyOGUwZGY0MzcxOTc3ZWQzYzQwNzBkYTlkMDUwMjEzMzQyYmMwMmQyOGE0YWYifQ"
"resource": "repo://Frameworks/TermindPresentation/LinuxDistributionBrandColor.swift",
"version": "repo-file-v1:sha256:dc888ab474f9bf142ccbe6f491d10866aad087367807b170f91f61d19debcc3c"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L70-L122",
"version": "repo-lines-v1:sha256:99e13181818902dd10a0752232d9b88d1202274b2d8bb1f6662e37bd185bcdb5:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZkOTZjN2U3ZTUxOGViZWYxZjQ2ZGJiNmM3OGRmYTM5MjBkZjE3OGE0NmQ1MTQ0MGFjY2YwNjc3ZTE5YjMyMDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg5MjdkODJhMjlhYzUyNjBiY2I0NjJkZjEwYmI2MmQ3ZjUwODg1ZjAwNWVmY2MwMTcyY2Y0ZjRjMDliZjE0MTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU3MzQyYWI0YTU1NDg5ZmFhZjMxZDM3NTgwY2YzZjI5MmYxZmUwMjI2MzhhMWRkZGQxNzM0YTBiYzZkM2ZhZjAifQ"
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
@@ -40,7 +40,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift",
@@ -62,7 +62,7 @@
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:2707fdefa5e5b61d74a8007e3e4cc90ce473cb9aaae0a52b2a80c63fd79583c3"
"version": "repo-file-v1:sha256:d274fb868d56884ebf7706a94731dbf0be5e7940b49d30176e970088d833b455"
},
{
"resource": "repo://TermindMCPBridge/main.swift#L4-L87",
@@ -92,7 +92,7 @@
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:2707fdefa5e5b61d74a8007e3e4cc90ce473cb9aaae0a52b2a80c63fd79583c3"
"version": "repo-file-v1:sha256:d274fb868d56884ebf7706a94731dbf0be5e7940b49d30176e970088d833b455"
}
]
},
@@ -144,7 +144,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -158,7 +158,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -242,7 +242,7 @@
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L137-L189",
"version": "repo-lines-v1:sha256:5e582ad2f3ec4728109feafbf32361c1b58e79da16cc678a79d1606293005434:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjOWJmNjE2ZGNmNTM5YTBkNTRhMTM2YzY2NGM1M2EyNTllZmFkOWNmNWFmYTY5MDY5ZmEzOGI1MzE5OTQ0YzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0N2NhYjY3NzUxMmRjZWQ0YTIyMGVkZGQ4NjNlZDFlNDM1OTM0NmRiYTk4ZDljYjkwZDBmZjk2MjhjM2IzNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3ZGE0ZTRmODRkMjdmYjAxMTA1N2E3YjdmMzE0ODI3NmQyOWUyOTUyNDU3ZWE4ZTYyMmUzMmU4MWU4NTVlYmMifQ"
"version": "repo-lines-v1:sha256:596e28f0be427d781f699f2ec66edc6540d7ed4daa80117fac0d53acf4bf9434:eyJzZWxlY3RlZExpbmVDb3VudCI6NjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjOWJmNjE2ZGNmNTM5YTBkNTRhMTM2YzY2NGM1M2EyNTllZmFkOWNmNWFmYTY5MDY5ZmEzOGI1MzE5OTQ0YzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0N2NhYjY3NzUxMmRjZWQ0YTIyMGVkZGQ4NjNlZDFlNDM1OTM0NmRiYTk4ZDljYjkwZDBmZjk2MjhjM2IzNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3ZGE0ZTRmODRkMjdmYjAxMTA1N2E3YjdmMzE0ODI3NmQyOWUyOTUyNDU3ZWE4ZTYyMmUzMmU4MWU4NTVlYmMifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L221-L236",
@@ -279,10 +279,42 @@
"version": "repo-lines-v1:sha256:c0afba6920715469b1143421a486cab4c58af4d861f4f079b3c67a50a57cc3c9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIxNTg2NDk5Mjk3MTM5ZTRkMWUwMTM1MTU3MDkyNGM1Nzk5MTUyOTI3ZGJiMDM0MDI5MzljNDhkY2RlZjczYWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk2YzJjMzg2MTg1ZDA1MGMyNzY2Y2RkNDZjZDM3OTg2ZTY3NmRhYmU1ZmEwNDk2MTE1ZGQ0M2U5M2ZkNjYxMTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVjMDlmOGY2NDVmNjBmNGRjZGE1MGIxY2IxMzBmMDJmZGY5M2E4YTRkYjY4OWI2ZjBhZGNmYjBkMmQyNDRhYTEifQ"
}
]
},
{
"id": "claim_a0e27081121948aeb3e1e435b9f8cd3a",
"statement": "Shared Presentation has conditional AppKit and UIKit imports for rendering despite the architecture test's exact-line import exclusions; the import guard matches only unindented `import Module` lines, so it does not prove that all shared presentation views are platform-independent.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPresentation/LinuxDistributionBrandColor.swift",
"version": "repo-file-v1:sha256:dc888ab474f9bf142ccbe6f491d10866aad087367807b170f91f61d19debcc3c"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
{
"id": "claim_b5515606ef1b471fab01f25d11947ad8",
"statement": "ArchitectureBoundaryTests enforce selected import and construction restrictions on native Application, UI and Features directories rather than a universal ban on native feature imports of shared frameworks; the AgentKit shadow-declaration guard scans the desktop source tree for an explicit set of runtime type names, not every AgentKit-related type across all targets.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift",
"version": "repo-file-v1:sha256:48b3039f44d716afaacc3e0986a88fcaad3a32d6fa00a68dba265b82e0efc284"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift",
"version": "repo-file-v1:sha256:48fbe838ab08ba66ab64b0889b966cfbb8164b73efab2d65345af3bc05bcbb03"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:ccc1ba644b43a27d74cef3704aee00fa50111b7d7b6a3fc02a7e293007483fa3",
"pageVersion": "sha256:7e34ef5b96eb24065e35c51caa369a71f930de2671f013463e2df8e3d65c9d68",
"claims": [
{
"id": "claim_8e9cf2adb50847f98fcd4516cb0ed521",
@@ -16,7 +16,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift",
@@ -26,7 +26,7 @@
},
{
"id": "claim_b243e53015154ed1b22bf60930c55bec",
"statement": "Platform-local Application directories contain injected service/use-case state rather than native UI or persistence implementations, and architecture tests reject forbidden imports and concrete construction in those layers and feature code.",
"statement": "Platform-local Application directories hold use-case and injectable service state rather than native UI or schema implementations; architecture tests reject forbidden imports in both, concrete implementation tokens in desktop Application and both apps' Features, and enforce SwiftData models and repository declarations in shared Persistence.",
"evidence": [
{
"resource": "repo://TFI/Application/Connections/MobileWorkspaceConnectionServices.swift",
@@ -37,8 +37,12 @@
"version": "repo-file-v1:sha256:c99ebdee2a7701a25c37531517337f025cc59567b67c1af1a497447954c1d8c2"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L235-L274",
"version": "repo-lines-v1:sha256:9bddcb6ff15532544ceadc059fd7214d2612941cad1250023fd1d7eaeeca4324:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY1OTA5MTcwYzNlY2JiYmJiZDIzZmIxZWUzZWY0NDNkMjkzZGQ5ZjMwNDc0NjIxZGQzMWNiMDVjOGQ2NGZmNmUifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L64-L106",
"version": "repo-lines-v1:sha256:08c476cc632f29ebd0f9b7221558d60dc77bb9ac8d88d819e4d8841a8372d835:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4NWJlNTRjNmM2MGZmZjQ5ZTllOTU1Mzg1YjMzZTc4ZTRkNGQ4ZDJkNmUwMWQzMzJkNjhiNjg3MTA0OTkxYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ"
}
]
},
@@ -82,7 +86,7 @@
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
@@ -160,7 +164,7 @@
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift",
"version": "repo-file-v1:sha256:241630ccbe213a2cc448dcf534a36eff0d093f8c529b8e34c2757a59d3d14c10"
"version": "repo-file-v1:sha256:2e33baa61dd8708d8d37adaf715a6d4caa9cf849b87a291186a927a744e9d9e0"
},
{
"resource": "repo://TFM/Features/Vault/VaultView.swift",
@@ -198,7 +202,7 @@
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:2707fdefa5e5b61d74a8007e3e4cc90ce473cb9aaae0a52b2a80c63fd79583c3"
"version": "repo-file-v1:sha256:d274fb868d56884ebf7706a94731dbf0be5e7940b49d30176e970088d833b455"
}
]
},
@@ -212,7 +216,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Platform/MacDeviceName.swift",
@@ -226,7 +230,7 @@
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -406,11 +410,11 @@
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift",
"version": "repo-file-v1:sha256:414ce4495383d17da60f76df64b09ae0330227dccec58c227b79b6bfdaedd8aa"
"version": "repo-file-v1:sha256:842f0c1470aea8aaa36c9efe011771c7bc01ae48284e95f4463a9764de948d04"
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift",
@@ -425,10 +429,108 @@
"version": "repo-file-v1:sha256:3fce60dc27ea37748137125c239ad6e18ff3b63d7ef73ce6baef93bda80148fc"
}
]
},
{
"id": "claim_0220e5036be24002af0a808d4bc3ee83",
"statement": "Desktop Settings navigation belongs to each WindowModel: opening Settings remembers the previous destination, back traverses parent routes, and closing resets the route and restores the destination or falls back to Vault if its workspace disappeared; SettingsPageView renders the selected route within RootView's detail overlay.",
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift#L346-L394",
"version": "repo-lines-v1:sha256:f0b2ae44180a4334c03b0e087292f318df3a66f475b3fbbdfc60784351930cb0:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExZGM3ZDc4ZWRlZDE0NzliZDk3YTZjN2UzYWQ0OGQxNzFhNjRhZTNlMTQ1MGNhNjBlZGRlYzY0YTViOTFlZTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2MTcxMDUwNWVkNzc3MzZhNzZlZmNmOGM1YWMxNzUxNzczYjg1Mzc0NzhjN2U2YmJlM2Y4YTNiNDA4ZmNjMjkifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L58-L149",
"version": "repo-lines-v1:sha256:10f0fed49378d9f7a2ddac810f1c86ff61874ccfc29c6ab67aadcb99816692cf:eyJzZWxlY3RlZExpbmVDb3VudCI6OTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFhYzNlYjg3YzY0MDcxYmQ1ZWE4MjIzMDNmODg3OWEzMzljZDA4NTVkMGUyNDA0NDk1YWIzNmY1NmRkMWE4MjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2NGU4MmVhYjMyZTQwNmIwMDI0ZTZiMDYzMGJlMjNhZGExMDUzMjdlYThkZTUxMjI1YjU1YjQzNDE4NmJmZGYifQ"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L584-L620",
"version": "repo-lines-v1:sha256:09ee17ae6dec430f48790f3ffc1eb6e268c2beae85238bd679a3e6d1a23b2718:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ3N2U2ZGVlZjczYTA3ZTg4ZmQxZTk2ZDA3ODU0ZGZjYjI2Y2MzMjM2OWU3OTg0YmEwNjc5ODY4MGQyMzM0NjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzOGRhMDk0NzRiODU3ODdiN2ZiYzJlYjFmNDUzZjdlMGE4ZDMyYWVhNTFkYTZhYmU5YWY2YzI4M2IyZWQ2MWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MmU3MDJiOGI2MTYxNmJjNTI0MGY2N2VkNWM2NGIwMDgyMjdhZDJkZDhiOGUwMzcxYjI0YzRlYmUxNzgwYzYifQ"
},
{
"resource": "repo://TFMTests/SettingsNavigationTests.swift#L94-L150",
"version": "repo-lines-v1:sha256:86f77f7e477207951e0d4388f9fd27e2e88da14693f1a872841b5d6665d46d47:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjNTNiZDQ4OWQ2YWQ3YjRkZGM1N2ZjZWRmNzczYWNmZjBlODllMjNlY2I1ZGMzNjgxMDg1NWJhMjQ2YjhhY2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc2YWQxYWNkZGZlYTA2OGY1OGMxYTFhZjc1ZjczNmVjZGUzNTEwNjNkOTY2MzUwNjA3MzllYzkyNDhhOTM1YzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNjYWMwYTgxNGYxNDlmMGViYjc1NWRhZGQ0MjdlN2FkMDU1Y2E4ZDc3NzJmMzkxMjE2NzM1ZDA1ZTY2ODM4MTQifQ"
}
]
},
{
"id": "claim_7bd0ca0cf2ce40878d78e4eb9f4b0a06",
"statement": "Desktop Settings assembles category forms over app-owned settings and services rather than owning MCP or sync lifetimes; remote MCP editor presentation is Pro-gated, and the local MCP server has a separate Settings route.",
"evidence": [
{
"resource": "repo://TFM/App/MCPServerController.swift",
"version": "repo-file-v1:sha256:148237060fb32863988d3fce056529b2032e381e1b8da4070eee592134c86bff"
},
{
"resource": "repo://TFM/Features/Settings/MCPSettings.swift#L11-L52",
"version": "repo-lines-v1:sha256:1327455785cf186f8aab83c6651d28ec37cac5dd7fcb60cc647f71ca97306a01:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImEyMTQ1MDA2MTczNGI2NTZhNTJjMmVjOWE4N2E1YWQyODFiZjQzN2I1YjI1MTcwZDFlOTJlZWUwMGJjNTYyM2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc5NDUyMDA3NDIxZjVkMDUxZDljMDZhODJmNmI0NWZkMTNiMWM1MmNlOGEzNmI3OWE3MzdkZTkyOTllZjNmNWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAxOTcwZmQ2NjY0N2E3MGY0YWU0Mzg1OTI5MTM4ZmU0MmZhYTQ3N2UyMGU0ZDZkYWUwN2M2MjU4MWZmNjNiZGIifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L110-L192",
"version": "repo-lines-v1:sha256:11dcc3790b8c08f8b9de6507fb5af0432abf66e27c14a8594fb21e626e298a79:eyJzZWxlY3RlZExpbmVDb3VudCI6ODMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzZTZlMjQ4MzhhNTIxMzQxNzA1OTIxOGEwN2UzNWUyZjFjNmNkZTk0Mjg3NDZhZGNlOWVhNmI4ZTFmN2Y2M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgwNWFjZjVlYWEzYTQ3ZTc1YzVkNzNiYjk5NDYxZmY4MTI2ZTc0NjgyODQ4MTI1Nzc4NDk4MjQ3YjZjNmZiOWEifQ"
}
]
},
{
"id": "claim_509686b489d446b5b4ff572408a9aa4d",
"statement": "When leaving a desktop Settings editor or Settings itself, empty provider, invalid new MCP server and blank new skill drafts are discarded; configured provider and substantive skill drafts survive, while a new MCP server must lock its namespace or be removed.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L198-L230",
"version": "repo-lines-v1:sha256:c452b24bac854e836d8336333344cc3b53143555cfca728802125619d8755309:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiNmE0N2NjYzUyMzA3NTRiYzM5M2QxNTBhZTJmMWUyZTA1ODcyNDNmMDYwNTJkMjdlNDVhZGQwZTI2ZThkMzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY5Y2EzNjgxODVkZGMxMmUyZmNhZDdmNjEwYjVkYTkzMzhhOTg0NzBlZmM2ODJlOWI1MDkwNDM2NGFhM2EzZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIxMzJkOTY2ZWQ0MWIwOWU4ODE4ODkwNGFmZGFmNTQ0NGFiOWQ1ZjUxMDRiZDhmYWUxZmVmYTIzOTQ3NDhjNWUifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L328-L350",
"version": "repo-lines-v1:sha256:a3a2a4c940bbff434561cf2acab4878edfc677414148da377551e33ba164a5a3:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg2ODMwN2I0ODJlNzM2N2YyMTczZGI5OGNhNzcxOTZmMmQyNzNlZDFlMTY2Zjc4MGE4MzU3Y2I2ZjQwOTg1YTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNmODAyYWRhYjBhYzQ3NjAxOWI4NDMyMWNkMTdmMDFjN2UyYWYwN2E1ODc3MjUwNTc2NTk0YTQ0ZmMyZGEyMTcifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L93-L108",
"version": "repo-lines-v1:sha256:db0cdc606501db2f512721e050b7e0b4991b51c176cbeb289e952653a3a8a600:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ1NzM5OGMwZjAzNzM4YjI2YWE2YzA1NzMyYTE3YzJjMzBiMGI0NzhhMWZjZDc1MDkyODcwOWM4YzJiOTdmZDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNlMmU0OTU1MTE1NmQ2ZGVhMDY4YTgwZjUxODI4ZmM3ZjRlMGI1YTdiNjMxMDIyODhiYmM1ZGIzNGVhNDZlYjkifQ"
},
{
"resource": "repo://TFMTests/SettingsNavigationTests.swift#L152-L230",
"version": "repo-lines-v1:sha256:16f5b26a60ea6919f3d1977ef7ee7510cdf55def362902724836219664a0ff14:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjZTZmYmI1NjcyMTYxMGY0Mzg1ZWM0NTM3MGJkZDgxMTEwNGY3MDUzNjY5ODAyNWUxODkwOWQzODQ0YjA2YWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxYWNmMDYzYmVkZDhkNzg1ZGQ0NDIxMGQwYTRhNThlZDI1M2UxZDQyOTc1YTY5YzAwN2FiNzI4YWVkZWU0NTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAyMzA1OWJiYjhjZDJlNmY0MGRkZjM0YjhlYzc1M2U2Yzk5NzgxY2M3MWNkMmZmYTM3ZGU1MDE0NjY4MTVhNGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
},
{
"id": "claim_9e6e3f94002a4a178ed7306862b3933c",
"statement": "Desktop app composition creates shared app state and a per-window model; a failed local container initialization aborts startup, while AppDelegate defers quit to recheck pending SFTP edits, cancel on refusal, or save window size and await cleanup with a one-time three-second termination reply.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L174-L219",
"version": "repo-lines-v1:sha256:554507d924b9d343a6821a30c09fe44d4e1275127b1f026a2d8b3707b0da5f4e:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE3NDM2MjdlZDk4ZTAyYjU3OGY1MjY5Yzc2MGVlNTg0ZWU1NDJjM2UzYzlhNDQwODkxY2QxNTE2MjVhNTlkZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZThjZDVkNTA2ZmYwYjY4ODQ3MTFjMmMxNTI1YjdiY2UwMmY0NDMxMDU2YTk3Y2E0ZDQ1NWY3N2Y5MTg4MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI5NTM4NThiMDRkNmQ1NmU0ZDVjMTM0MTU4ZjQwODQ0ZDVkZWQzMzM5YjFmMmFmZmYxZDM3MGM1ZTg1MjdmNTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdiOTZhMjE0MmNhYWZkMTdiNGEzYzMwYjI3MDMzZWIxMDMxOWZjNzEwOTFhMTc5NzY4YWQ3YTVjNmU3NmE2YjAifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L242-L269",
"version": "repo-lines-v1:sha256:67080297bd6b924a1092c93cb7aab4709a44a416c41dcc574da11714682c884b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZkNjgzYjc5NGVkOWI1NjQ2Y2Q2ZTZjMGEyYmMzYTk4YTFjN2NiYmMzMDUxZWZiN2E0NWQzYWI5MWI0MDRhZmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNlODNmYTc4NzYyNTJmYmNhNDIwMjk4OGFjYzgwODMyNjI4NzQ2ODc5ZjM5MzQ3YTNhMDJiYThjYzJjNGRhYjAifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L35-L58",
"version": "repo-lines-v1:sha256:e66f0511b931256238124fc46de712e88dca37528f959616f8cc1188709e5e8d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRhY2Q2MzRlMzM0OTk5OWMxZjJiZGE2MmM1YjE2NjljZmQ0ZjM2NmQzZmFkMmZkMzY2YTQ3ZjAyZmJhZmJkN2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZTg1YmI2MTQ1ZGM4ZDE4OWJhMzEyOTRhNDk4Njc0ZjU4M2RlZjE4ODIwM2JiZDJlZWVhYWQyN2Q3OTNjYmEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY5Mzc5Yzg0N2Q1YWE4ZTg0ZjYwN2JmMGQ0NzI3YWE5YWJlYjg4NDkyNTQzZDk5NjhjOGJmOWEwNWQ2ZmNiZWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQxMmJjZjU5NmJmOTk3NWM2Y2ZhOTU1NWJhZjAwMjBiZmM4OWFkMjA1N2U2YWNmNzQ3NzJjZTJlNWIxMDQxMTAifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L420-L459",
"version": "repo-lines-v1:sha256:15368b9dce6b39324240ee54e87263fd354089e2c4260c622cd4f119c7dc1306:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhiMTg2M2Q4Njg3OTcxYTY0ZjViOTdkMmI1YTMzNmYyYWE0NTIzYWU3MjU2MDIxOTg2YTQ2MjdlY2ViMTUxMzEifQ"
}
]
},
{
"id": "claim_112f072ad3df45b8ab527def78b30c47",
"statement": "RootView keeps workspace content mounted in a persistent deck beneath non-workspace destinations, so switching to Vault, Assistant, Metrics or Settings hides but does not destroy session views.",
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift#L346-L394",
"version": "repo-lines-v1:sha256:f0b2ae44180a4334c03b0e087292f318df3a66f475b3fbbdfc60784351930cb0:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExZGM3ZDc4ZWRlZDE0NzliZDk3YTZjN2UzYWQ0OGQxNzFhNjRhZTNlMTQ1MGNhNjBlZGRlYzY0YTViOTFlZTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2MTcxMDUwNWVkNzc3MzZhNzZlZmNmOGM1YWMxNzUxNzczYjg1Mzc0NzhjN2U2YmJlM2Y4YTNiNDA4ZmNjMjkifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L6-L11",
"version": "repo-lines-v1:sha256:71f489a06539141f1fc08a70b85519a73c3f759957b64aaea1221ef482f7a653:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjg2OWM0NjBiYjViODM0YzhmNzhjOGMyMTMyMDI1OGJlZmMwZWZkYTMxNmZlMTYzNjQ4NjU3M2FkOTIwYmY1OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYzc3N2Y5YWY4NDlhM2IwODYzODJlMmZkNDAyMmVlOGUyMjAzNmMyMDA1YTY1ZjMzYzU2NjFjMWU3ODM4NjhlNiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNTcxZGE3NDM0NTdjMDNhMjQwNDRhMTk3NTQ2MGE2YzQ4OTllODBiNzUyOGUzMDRkMzE0ZDY3ZmU1NWE0MTYwNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMzIwZjY1YTkzMzE4YjA2MzQ2MWUzYjYwMDdmNjY2OWEwNjg3ZDkzNmUzMmY1NjhmZWUyNDM5MzJhOTgxZTY5NSJ9"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:c9416474abac2fb6a994f2dbb1a11cf40a0a27206ea9c15f27f13fc432cbf121",
"pageVersion": "sha256:001c373a89ad6a49f16c0c02fdae97d6ed7f14188b6056c45c2517f2c0aff5bc",
"claims": [
{
"id": "claim_bd9f5ddda6b6466eb79c622b02fd73f2",
@@ -12,15 +12,15 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:2707fdefa5e5b61d74a8007e3e4cc90ce473cb9aaae0a52b2a80c63fd79583c3"
"version": "repo-file-v1:sha256:d274fb868d56884ebf7706a94731dbf0be5e7940b49d30176e970088d833b455"
}
]
},
@@ -30,7 +30,7 @@
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -44,7 +44,7 @@
},
{
"resource": "repo://TFM/App/RootView.swift",
"version": "repo-file-v1:sha256:414ce4495383d17da60f76df64b09ae0330227dccec58c227b79b6bfdaedd8aa"
"version": "repo-file-v1:sha256:842f0c1470aea8aaa36c9efe011771c7bc01ae48284e95f4463a9764de948d04"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift",
@@ -58,7 +58,7 @@
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -86,7 +86,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -230,7 +230,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Platform/MacDeviceName.swift",
@@ -336,7 +336,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFMTests/AppTerminationTests.swift",
@@ -443,10 +443,114 @@
"version": "repo-file-v1:sha256:70c19f3e43a90319319e4c871c95ffc0f7244c8dd265efaa796f3c8bc2cd8f96"
}
]
},
{
"id": "claim_fccd0b9456cb495bb6c515cfcf80437e",
"statement": "The macOS app entrypoint cleans old context attachments, sets up its scrubber client and selects launch language before constructing runtime services; a debug screenshot launch builds an in-memory container and returns an isolated demo AppModel with demo hosts, AI, metrics and onboarding rather than falling back from a failed production store.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L174-L176",
"version": "repo-lines-v1:sha256:7e521f0009c7097b3075811418a0f0975f3a229ce9bb3012a58b7cd360f45681:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTc0MzYyN2VkOThlMDJiNTc4ZjUyNjljNzYwZWU1ODRlZTU0MmMzZTNjOWE0NDA4OTFjZDE1MTYyNWE1OWRmNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYjk1Mzg1OGIwNGQ2ZDU2ZTRkNWMxMzQxNThmNDA4NDRkNWRlZDMzMzliMWYyYWZmZjFkMzcwYzVlODUyN2Y1MyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNzQ3Y2Q5NDhmZjUyMmQ4MjAwYzZlYzJlMWY3YWM1ODdiYTExODM5OGQxOWMxZmM0Y2JhZDM4NThkNjU4ZWNlMSJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L41-L70",
"version": "repo-lines-v1:sha256:b472676aa8091f471664b71818156d6d1ac8449730885e855c5a10df58377d6b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhiY2M2MTFhZjIzYTkxYzNiNzI3ZDBhY2U0ZGUyMjI0MmZjNDkwNmM3MTk0YTYzNDkxOWI2NWQ3MDNkZDAwYjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1NWUzNDQwZWZmODhjNGJiYTg5MGEyNzcwZTIxYzE4MmVhNzEzNGUzMWY5MDE3OGI5YTI1YTU2YTFlZWQ2YmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4ZWFiZDkyY2RiNmUwZWEyZWI1MjFkMDM0ZjQyOWVmZmI5OWRhYzEyMzg3MjczMmVmOGU4NTUxMzM3ZDllN2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMxNWU1MzZjNGQ3N2U0MTM0YmYyMDg2YThjZjRmN2Q2ZGQwMWFjNTg1ZGNhZDI1MDJiNGVmMDllMWJmMzE4YWUifQ"
}
]
},
{
"id": "claim_1f7dc75586cb42f6b5f062dd33a7b4f0",
"statement": "In DEBUG XCTest launches the real macOS app with an in-memory container and test-isolated metrics defaults, no cloud sync coordinators, disabled file logging, unrestricted Pro access, and no persisted default window size; database construction failure still triggers fatalError rather than resetting production data.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L122-L175",
"version": "repo-lines-v1:sha256:917ab766cf4f2b83f00816d13cc3a851b65147c1dd2f80b2d1ac4dab7f58d3fb:eyJzZWxlY3RlZExpbmVDb3VudCI6NTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA4ZTY4MmQ5OGE5NGIxZTE4NmE4N2NmNjRlZmFlMTliYzIwY2VjNDAwZDU3ZWVjZDI3MGYzNGU3NzljMjQ5YjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFjZTZlNGYzYTNiZjViNjhmZDQ5M2UyOTA0ZGU1M2IyY2ZhMzI0MzEwNjIwN2E4MDFiOGZkZTc0M2RmYWIzZTciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1OTljM2FjNmY1NzQxMDgzZTgwMmM5NjU1MmEwNzJlN2YzY2VmMWMyYTUyYjE2ZDRlNTJiNWNmNTIwYjdhMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L16-L22",
"version": "repo-lines-v1:sha256:5383266e29c54e8811432a17570cd59e6ed3742ae2a18e1c9d9632dedde6b1f3:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTdjNmQ0ZTMxY2UxNDA5MjIwZWY2NTIwNzEzZDJiM2MwNjc4MWVhOTQwYmRjNTVkYWNhMzE0Mzc1MjUwMTQzZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYTM5YzQwNzgyNWM2YWE4YWQzYjExMzRhODU0Mjg1ZDMzZjVkNDY2ZjM4ZGQzZDVjY2JmMDQ2NWYwODU5M2ZmMSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzEwYmYxOWZlNGNjNzhjZDE3MWFjOGMxOWVlYmUzNzUwNzhiNGY4Yjg5NjI5MDAwOTY4NGU5OWEyZWIzNjkyNSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTZiMWY2MDRhMzM3OTVmNzJjNTQyN2U5MjAzYTcwNzU4Mzc4NzZjYTZhOGZmNjE3ZDgzNzJjZDlkYWRjMjE1NSJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L50-L57",
"version": "repo-lines-v1:sha256:fc28d8317e47b1c3cb32d2fa431ed45690867ae8caaaadf9acbd2be1b2a111de:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMWMyNThiN2I0ZjViNGFmODg2MThkMjg0YmQ4ODVjZWZjM2IyZDE5ZGExOTk5OWY3YTE0MjRiZDEwOWIyM2NmMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiY2MxODM1YzBhNmE5ODhkMzM1NTZmZDE1OGYwZWU0MDA3MzZhNTQxOTkyNGVkNjQxYjY4ODlmYWEwMGZlMjE0MCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNGEzNjUzODgxZjg5MjNkYTJhYmYzYmFkM2YyYmFiM2JkYjhhMzY2OTViNjkyZjliOWY2YTExYjc1ZDgyOTBmMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWNhM2IwMGJkMGIxZDUzOTAxMTYzODJjYWZjNWRlZWVlNGRkYjY3M2VjNTUxZWU0OGY1ZGRhOGJmMjBjNjMwNyJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L76-L101",
"version": "repo-lines-v1:sha256:606a63643684a811910ad0ed4e8b477ad39e315ce9c77ebeb18ae7b68a9ca221:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyNzlkY2I2NTU2MzE1MmY1YTdkZDIwNDYxMTk2MmVkZTJiODAzNWVhNTRhOGMyN2M5ZTZlMGJhMTU2NTJlYTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjMGEyZDBmN2FkODhiZTk0MWZiNGJjMzQ3NDU0YWYxYjY1OWNhYTIyODNjMmRiMmQ4NWU2YzI4NjAxNDRiZGMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkyZGFhZGJiZmE1NzAwNjhiNDYxYWY1MDJjOTQ3MDEwZTc2MDEwYjI5Mjc1MmM3OTU1MjBjYTMyMjNlOTg1NmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3NjZlNDVkMTk4N2YxMTRlNzc5MGExM2QzZDM1YjU2NjI5OTY4OTRiM2QxN2NjYjRjOTM4ZjI4YzhjOGRiNDMifQ"
}
]
},
{
"id": "claim_5874b2c45a3c4a08ab0f4486501f2ca4",
"statement": "By default DEBUG XCTest suppresses automatic macOS main and authentication windows and disables restoration; setting TERMIND_WINDOW_TESTS=1 opts in to automatic windows but not restoration, while screenshot mode permits automatic launch and disables main-scene restoration. Dock reopening is blocked during suppression, the last closed fixture window cannot terminate the test host, and visible-window test suites are gated explicitly.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L196-L238",
"version": "repo-lines-v1:sha256:8183691e92ae9413ef6e456a14e6f8a7b0c7ddf69f49a2e4e46d53689ac11ea0:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwNTgzMDJjZDFmMDQ4ZTE3MzU1MTUxODA0NzRjYmI4M2YwZjhkZDNmN2I3ZjUyODI4ZDU1ZmUxYjg1MmIxOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUyOWM5Nzc5MTJhZTRkOWI4ZGJlYzYyMDU4YTQyNzk4ZTc3Yjk4MGI4NjdhZjE5Y2MzNTEyMjc3YTMxNDdjZGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ0MTA0N2ZkYjNiOWIzMTYwZTU0NWEwOThlOGJhY2E1ODA1YTJlZmFjNGI3YWRkNmYxM2IyNDg4NWJjNmY4ZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L24-L33",
"version": "repo-lines-v1:sha256:885f3d9ad4ecf5f68ecbc79357f5d99d7350076b5db84f5942179995c1725a91:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjllOGZkMDU3ZmYxMDg5ZWQ5NzJiZDYxNzZhNzc5MmI0MjI0NThmMDdmN2RhY2ZhZDA5MDExM2U1MTU4Y2E0NjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU3M2ZkN2I1OTVlNjU3OGFkMDhjZWIyZjgxY2U3NDU5OTEzNzBhNWU4MDE3ODkyZGJmZjk2YzAwY2ZiNzQ0OWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwNGE1NDQyNzMwZjkzNjk5ZjI1YzU0MTNiZDc0NTViMzZiYWNiYzNkMmVmZTU3MDA0MmFmMTdhNDU5OTUwNDMifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L351-L367",
"version": "repo-lines-v1:sha256:eab9b1a3afe7e792bd08ca884fb3f682839eb1cde10d40ba20ef71e771f25203:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2Y2JmMWEzM2ZlOWQ1MWIwZWY0MDc2MzM5Y2MxMDBhZTIwZThhYmM5Njk2ZTM5ODYwYWNiZjZlNWFkNmU0OGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ2MGY0MzMyOTU2ZjUzMDhmNDU2ODQyYzcxMTkxYTkwMmYwZGVmODk0MjRkOTNjMGUxMWMwYTM2ZTJjNTY4NjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkMTU1MDhmMmNlNjBhOTI3MjFkNDQzZWQyZWU1Mzk5NDQ1YjUxNzFkNWE3YmNkMWIxYWNmZDRmZWY0NGZhMmEifQ"
},
{
"resource": "repo://TFMTests/AppTestHostTests.swift#L7-L19",
"version": "repo-lines-v1:sha256:60ce47d566b59e31bca54a0e1db7710e2ac2848e4de104d20b985be33cefc082:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImEyZGRmZDFmOGUyNjE1MDM2ZDU5NmVmNDA2MDUzZWJjZjY2MDZlNjI5NDdmYmNiMjMxMjU1MDlmNmNmNjhmMDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0NDY3NTVhZGY2NjFjYTE1YzMzMTRlYTU3MzMwNDk2ZDdmYWZiMzBhNDJlZjAwZTRiN2U1YjkzZWE3ZDg2NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L12",
"version": "repo-lines-v1:sha256:647fdf978ecd85719df899c592ebd2386dcf8c24b7371545e9ab0dcf3e0402df:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
},
{
"id": "claim_f4928952c3594603be6c9a616d38734d",
"statement": "On accepted macOS termination, the delegate saves normal window size and starts async cleanup; pending external SFTP edits prompt a quit confirmation, and cancellation replies false and resets the termination latch without starting shutdown.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L420-L452",
"version": "repo-lines-v1:sha256:209641db46bb153b0476bd566ee4d717edc93bb27063d85095bf219df72b7583:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliOGJlZDVmYjA1YjU1Mzk2MGFiMDVlYTU4ZjI2ZDA5MGQ2MDY1NTE5ODkzZGNmOTllZmQ5ZTc1NGQ3Y2VhOGMifQ"
},
{
"resource": "repo://TFM/Platform/MainWindowCoordinator.swift#L137-L145",
"version": "repo-lines-v1:sha256:495f1d0c3876072cb82ae11fa0108f25fbcb2a2d8b8d372f90373cc1127cd620:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzE4ZWMyNjM3MDg0MWMzN2I5ZDA5NjVmMmU0MWVjNzA5YjMzYTNlMGIwZDY5OGUxYjA0ZTViYThkOWMyZDRhZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2U0M2FkODljMjVhZDQwZjdkZmI2M2E4YmYyMTE4MDBiODA4ODY1MTgxMWMyMGQ5NjJiZWU0Y2YyYzkxODljMSJ9"
}
]
},
{
"id": "claim_9efb4c00c1ef403eac3fb83c056e048e",
"statement": "A macOS login launch configured to open quietly still creates its normal window and hides the app; a one-shot key-window observer with a three-second disarm prevents subsequent user-opened windows from being hidden.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L386-L418",
"version": "repo-lines-v1:sha256:14872f2fb0ad6cc4229d2ee10216f3ae106c413beb407c9d6e4f4a9715e1e67d:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZlMWRlMDE2MzEyOTVkYWI4OTJmZjVjZGUyNzFlZjc5ZDQwM2NjZTlkODNjNzczODk2NzM2ODVjMTIyYTlkMWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY5MGE3YjI3NGUyNDE4MTRiZWM2N2VjNGQzZmQ0N2I4MTcwNmIyZTgzN2ZmMjNhYjhlZWY1NzBlOTI2YWFhNTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUxMzk3NzgyYzBmZjNmMDk1NjMyMWZlMTM2OTVlN2MyMDk5YTVhZmE1OTA5MjBlMWNmYjJmNDUxYzU0NjYzOTMifQ"
}
]
},
{
"id": "claim_c2967b8e486b4abbbe29443dfdf1f5b7",
"statement": "RootView retains the per-scene WindowModel in SwiftUI state, exposes it as a focused scene value and registers it with the shared AppModel; native restored windows keep their system frame without replaying a pending workspace move or sharing another window's workspace state.",
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift#L12-L27",
"version": "repo-lines-v1:sha256:83688e26829f58520c3a1708b0dba404afc769843fb45588034eaa933bd07381:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI0YTU0NzRjYTQyZGYyYjU5YWQ4MzRlZTEzYjFiNTczYTlhNzkxOWM1ODg1NDZjOTg4MWI5Nzc5MWMwZTliODEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ4ZjE0OGYxNWFlNTBkMmE3MjZlMGRhYmNhMWI2NWQ0NzVmNTYyYmI5YTlmZWMxZmVjMWEzM2EyYzdjZDIwYjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZkMjk5MDMyMTk5YjM3NTAwZDdiYmRhMTQ4OGI1N2YyNmFjYzUyYjgwZTA1MmQ2MzAzNmZkNmRiZGIyNzMyN2IifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L194-L212",
"version": "repo-lines-v1:sha256:4b3637c55af0e1d8ebb304d2f9e4c1fceb6884b990d189bb7ba41f196f512b89:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBhZDFjODhkMzAwYTM1MWU4M2RhYTc0YzdkYmQ4NmNlMDk1NDNjYWM4YWNlOWE3OWNkZWE2NTA4YjAxNTc5MTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkxOWJmOTM3N2ZiZmU5NWM3NWIxNThlY2NhMjMwMTRlZmMwN2ZkNzZjNmI5Zjk4NjAwNGZlNDcxNDk2OGRiNmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkzODYxNjc2YTBjZTEwMDk4YTM5MjEzZDU4ZjcyZDBjZDRlNzk2MjE5MzM1MGNiNmMwY2M3ZjgyOGU0MjhjODIifQ"
},
{
"resource": "repo://TFM/Platform/MainWindowCoordinator.swift#L201-L227",
"version": "repo-lines-v1:sha256:dc0f10cca572eadef37a1914b123c075ca9cf5a4110ba83cc2f96453abfe83fb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVkMWQzZDYzMmM5MThkZmFiYzJkZmViZTQ0MmMxM2I3MDA2YTgxNzlmZjg5MDYyNDk5ZjBmZTMzNzRjYjFkZjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmNGVkYjE4NDBiNmE1NzQzNDljYjhiNGEyYTJjMGY3YTk1YjAwYzg1NDhiZDAxZDgwNjdhMjc0OGQwYjA5ZjQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMxNTFjMDIzNTg2OTk0MDFhZDg1ZTkxZjZjNGU1YWQzYWU3ZmU5NGE3YWNjOTc0YTg5MTQ4MzZlNzIzZDg3NDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcwMDBiNjk2MDUxNmRkZmFhYjQyNTg0NTZkYTBiYjY2NWE5M2NiYjc5NjI2MjJiYWIzZTA1ZGNlOTJlYmQwMmQifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:70bc54bbf1c2da2b34e500a403c70203791f10430ee4ba3d69f9de85b70608d2",
"pageVersion": "sha256:5da26732bd32ecc9204c2c8c832f9607e8c614aaa83c5f5a8cd2d4a636dab549",
"claims": [
{
"id": "claim_085ce722f39f48eea75366ec3b3f7554",
@@ -10,31 +10,19 @@
"resource": "repo://AGENTS.md#L5-L13",
"version": "repo-lines-v1:sha256:5bf8f722418eac38057a37c2f664f7f78762650fe7e8d0d55318d6aa97bcaba3:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjM4YmQ4MDg4Y2Q5OGMyYTJiZjdjZWUwMjg2NjU0OTRlOTA0MGI0YmIzNTBhYjMwY2VjOThmMmZmNDlkMjUyMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZmQxNDRhYTY2MzdkYjRiY2Q3MWYxZmE2NDc0MGI1YTJmMDk1YzZiYWYyM2JlOWU1NzJhMGE4Y2VkODJkNzIyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmQ1ZDk4ZDMyNTIxNzM5OGEyYzA4Mzg5YzFlMjg1MDQyMTA2MDQ2OGUzYzI5ODdhODRiMDFjNDM0ZWU2ZDcyZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWQwMTdmYTAzMWI3MzUzMDUxZTQ5YWQxNjI0YTFhNjBlMjAzYzhmYTljN2QxYjE0YjY2ZjU3YjlkMTU5Mzg5NSJ9"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189",
"version": "repo-lines-v1:sha256:0d3b3a4cd81181b5228a2cfa0b6a89f30ffcaa8a77112e9c8ed819cc29a59663:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ3NDI5ODQ5YmU0MTZhMzMzMmY5NTcyYmY1NTM5ZDkzOTZjNDEzMjY1MWE4MzhiZGRhZGIzN2IwNzg1OWViMmUifQ"
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:2707fdefa5e5b61d74a8007e3e4cc90ce473cb9aaae0a52b2a80c63fd79583c3"
"version": "repo-file-v1:sha256:d274fb868d56884ebf7706a94731dbf0be5e7940b49d30176e970088d833b455"
}
]
},
{
"id": "claim_07d6c15b703242fa94b68c4f347d23a1",
"statement": "ArchitectureBoundaryTests use exact import and selected-concrete-symbol scans: Domain disallows specified platform/UI, storage, security, network, commerce, SSH and terminal imports; shared Application disallows specified UI/storage/transport imports and selected concrete infrastructure symbols; Presentation disallows platform UI, persistence and Remote Infrastructure imports. Desktop and mobile source subroots have separate, narrower guards.",
"statement": "ArchitectureBoundaryTests apply distinct exact import checks rather than blanket prohibitions: Domain excludes its specified UI/storage/security/network/commerce/SSH/terminal imports; shared Application additionally excludes TermindInfrastructure, TermindPersistence and SwiftData, and Persistence excludes Infrastructure and Remote Infrastructure. The five non-presentation frameworks exclude app targets and specified native UI/system imports, while Presentation has its own rule excluding app targets, UIKit, AppKit, storage, Infrastructure, Remote Infrastructure and StoreKit but permitting SwiftUI.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189",
"version": "repo-lines-v1:sha256:0d3b3a4cd81181b5228a2cfa0b6a89f30ffcaa8a77112e9c8ed819cc29a59663:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3ZGE0ZTRmODRkMjdmYjAxMTA1N2E3YjdmMzE0ODI3NmQyOWUyOTUyNDU3ZWE4ZTYyMmUzMmU4MWU4NTVlYmMifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L245-L284",
"version": "repo-lines-v1:sha256:146f497ac082e0d24fde43c2c3634ae38d1859c8e7bbbf409a449786b408834c:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwODJlYzhiMDRiNTlhNjdhZWFhYmYxOTVkNWE5Y2I4YWJkMGE3NjBjZDc4YjE1MTNhNzg3MTA0MGE3N2Y0Y2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0ODVjOTkxNGE0ZTFmMmY4YzUzZGM1MzYyODQ3NjI5MGQwZDAxYmFkZTA0NzQzYjVlNjczOGYyNTk4Y2M0YTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRjMWEzMTY4MmVjNjVjMDk2NWZhMjRjYzEyZDEwODJiNjhlYzk2NTRmYWIzYzM4YTllYjAwZmVhMTgxMTFhM2IifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L64-L106",
"version": "repo-lines-v1:sha256:08c476cc632f29ebd0f9b7221558d60dc77bb9ac8d88d819e4d8841a8372d835:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4NWJlNTRjNmM2MGZmZjQ5ZTllOTU1Mzg1YjMzZTc4ZTRkNGQ4ZDJkNmUwMWQzMzJkNjhiNjg3MTA0OTkxYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ"
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
@@ -78,7 +66,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -184,7 +172,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Platform/MacDeviceName.swift",
@@ -230,7 +218,7 @@
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
@@ -247,10 +235,56 @@
"version": "repo-lines-v1:sha256:fca958a7ad62418ce0a9e8b6086dc052497d2a11aba31a72de600c9fb3446d61:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjljYTg5MWJmZjdhYzFmN2NlYWFlNDBlZjA1MTA2NmJlOWVmZTQ3YjRlNDI4MWU4NmMzMTliZTJjNTVlYmNlNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOWI2MmY2MGQ4NTkwYTU3OWNmNDZmOGQ2NzM3OGM0YzU3MmI5NjJjZWNjZGI5MGM3YTVmN2I0MmI5NjA3ODJhNCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNWZmNzZlNDczNTc5ZjY2ZjA4ZDYwNzE5YWQ5ZWI0MGZhZGRhN2M5ZTE2NjFlZjY4MzM5MzAyZDYwNDI3ZDFhZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjdlNmMwMmJkYjc5NzI3MjI1ZDU2Y2UwOThlNjgyNWQ4MTFiZWFkOGRlMDcyYTEyOTA4NTllNWE5NmNmODQ0NiJ9"
}
]
},
{
"id": "claim_76ac57d610d04da49cb1f6807d768594",
"statement": "Desktop Application rejects its specified UI/storage/transport imports and desktop Features rejects specified storage/transport imports; mobile Application rejects SwiftUI, UIKit, SwiftData, GRDB and TermindPersistence while mobile UI rejects SwiftData, GRDB, TermindPersistence and TermindRemoteInfrastructure. Selected concrete-symbol checks apply to shared Application, desktop Application/Features and mobile Features, not mobile Application/UI.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
{
"id": "claim_e4f31aa2cfee4a1ea67b16710ce0ab73",
"statement": "ArchitectureBoundaryTests separately reject SwiftData repository declarations outside Persistence across apps, shared frameworks including Remote Infrastructure and Presentation, bridge, benchmark, widget and workspace-activity support; a declaration parser distinguishes definitions from mere references and requires a repository declaration in Persistence.",
"evidence": [
{
"resource": "repo://Scripts/swiftdata-repository-declarations.sh",
"version": "repo-file-v1:sha256:203aa343c49de9718ed1481fc0c5dd047202bebb7559f3a8a515b9e9ace96763"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
{
"id": "claim_0409598d88a44f24a64ebb556d02fccc",
"statement": "Desktop AppDependencies groups injected repository, remote connection, synchronization, logging, and optional shutdown services and offers in-memory host dependencies for tests; mobile live dependencies share a logged RemoteConnectionCoordinator across workspace and metrics services, whereas testing dependencies default to in-memory storage and replaceable services.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppDependencies.swift",
"version": "repo-file-v1:sha256:b9c7b9c73b191cdd8258d18c2a5f8cfd43ff774aea1d6c96a7d634de7f712179"
},
{
"resource": "repo://TFI/App/TermindIOSApp.swift",
"version": "repo-file-v1:sha256:e9b1f42fece05a48a98387a1c658a59225b62cdc85338269a6e04c3fea6e68f0"
},
{
"resource": "repo://TFM/App/AppDependencies.swift",
"version": "repo-file-v1:sha256:b35f9e1c3d3976abf2fac5fa1650429652983bc3c14459be73cc2cb4cd330bbb"
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:f24b2cea65e79274b316c5533385ff4f19e1c67e892b1014ed24109c0efd5779",
"pageVersion": "sha256:3dd8177bccfc507cc1d0d45b6694c75ca379337c1b914c5f199fb132ea37dd86",
"claims": [
{
"id": "claim_70c5c3da992944188e719c65adc9b06c",
@@ -116,15 +116,23 @@
},
{
"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.",
"statement": "Native wrappers own paywall sheet presentation and account actions: macOS elects one main-window sheet owner and opens Apple's subscription URL, while iOS presents `MobileProView` and invokes the system subscription-management sheet; both route purchase and restore to the shared controller.",
"evidence": [
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift",
"version": "repo-file-v1:sha256:a031bc4b356fac3f56a8ae282d2a3732a97699557a5c720d728b6c841e6528d4"
"resource": "repo://TFI/App/MobileRootView.swift#L41-L43",
"version": "repo-lines-v1:sha256:0fabaebf4041d2500ce606d6aef2447be1b2871b22d96118aaca1ab02930e43a:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTA1MjQxNzNmYTEwYmVlNTc4ZDZmYmFlMGIwYzE1YWVjM2NiYTE5MWFmMzU5NzM0NTQxNjRjNzhhOGFjYjZlNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZmU0ZjdiNzZkMGU4MjhiM2VmY2MxMTQ5NjEwZDk0NzNlZTc1YzM3ZGVhODQ0NzczZWRiZGYzOGZiNmQyNTYzZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYjdjNjlmZjhkMjMzZjI5NDliNDdkOTc5MmUwYTQ2MDhkYWIwOTk4Mzk1ZTRkNzFmZmM2MDAzYzMzNGIyNzQ4NyJ9"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift",
"version": "repo-file-v1:sha256:691c17b9026d8ec2b4961e345d66f1d226eb4a8e119018d30615d821a1ae0445"
"resource": "repo://TFI/Features/Commerce/MobileProView.swift#L13-L55",
"version": "repo-lines-v1:sha256:9c90515fd2d959ed05eb5f1995097190050fb75ed74c3d2bc6f035667dd48dfb:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4MjFmMTM3MGVjN2JlMThlNDBlMWI1OGE2NGMxZGEzMDY0ZTk2NTUxZmUwMzdiNTE0OGJjM2JkZWI4MTliZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L15-L30",
"version": "repo-lines-v1:sha256:e29addb0ef75c4dd3b14b06834cdfc29507e8d28bcf3df8949f3075c38816988:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU2MTc0MGI5Y2FmN2I5NGNiNjM3MTQyODBmMjA1NDUzNWYyODY1MjMzYWM2NzBjM2YwNjFiZjkxNjZjYTMxOGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFlNTVmZWUwYmQ2ZTFjZDgyYjBhNjZjMGFmZDQ4YjJiNmMwOTYyMzljNDc3MWU1NTgyM2RjZTYzYzY3ZWYzYzYifQ"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L69-L100",
"version": "repo-lines-v1:sha256:a64b8b7603fc6c3a7cb5e257bedbf519cb7ce4c8b3806c37a176b1eb3d83d234:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3NTYzODYxNjFmN2ZiOWMwZGU0MWVlMWMxZmU1MDM4MmY0YThiMjZlYjFjM2Q2M2Y4MWYzN2ZmOGQ3YjY1NDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
@@ -241,68 +249,76 @@
"statement": "App entrypoints use live StoreKit access outside test/demo or in-memory setups, then reconcile subscription-dependent sync and built-in MCP on macOS status changes and sync on iOS Pro access or scene-activity changes; mobile sync also requires a foreground active scene.",
"evidence": [
{
"resource": "repo://TFI/App/MobileAppModel.swift#L170-L171",
"version": "repo-lines-v1:sha256:dd2fc8113f87491d3793a976f6352a7a21c41fd71bc1bb19069ad665023bfcda:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMWZiZWM1ZjkzOTExMzNjZTY2NjU3ODI3MzFlYTFmYTQ3YzNhZjY0MTdkN2ZmMjRiM2U2NWRmNDdiNzRmNTEzZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGQxYzgxYTE2MGVhMjIyNjg0NGMxMmQzYTEyMjhkYThjZDczOGRjMWU4YzllOWRiZWYzNGM3MjIzOTcyYWQxNiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTM1NmFmZWY3ZTBkZThjMWFhYzdjOTUxZDk0ZWY4NWQ2YWMzZWJmNmUzY2I2ZGQ2ZTM1MGRjZWFjYjNkMmNlNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZDQ2Y2I1OTE3OWNkODkwZGYwYmQzNmFlMWNkYWNlNzRkY2Q1NDg4N2I4MjFiMThjNWUyMTU0YTAxYTgxOTFlYSJ9"
"resource": "repo://TFI/App/MobileAppModel.swift#L157-L172",
"version": "repo-lines-v1:sha256:47ea9385a72b40801f914cf46dd8cee949e1e53241b2eb03a72111a5f310186e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwMDc4NTkwOGZlY2YyODUxNWNhMDMxOGZkYjI4ODhhNjU4ZTQyMjVkZWZjMTAxNWExYWFmNzUxZGQ3OTUwNTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkMWM4MWExNjBlYTIyMjY4NDRjMTJkM2ExMjI4ZGE4Y2Q3MzhkYzFlOGM5ZTlkYmVmMzRjNzIyMzk3MmFkMTYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlmN2M4NjBjOTAzOGM2ODEzOWVjMTYzOGNiZThkNDYzNzYxMDYyOGY0NGU4MTk1OThjYmY2YjA0Y2MzOWIzNWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ0NmNiNTkxNzljZDg5MGRmMGJkMzZhZTFjZGFjZTc0ZGNkNTQ4ODdiODIxYjE4YzVlMjE1NGEwMWE4MTkxZWEifQ"
},
{
"resource": "repo://TFI/App/MobileAppModel.swift#L560-L600",
"version": "repo-lines-v1:sha256:9b75da6c368a22be4ea7671f9bee2c752a26e2c6242a6736aaf264cbbaeeec23:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA1NmJiMzc2MzhmOTFkYjA1YTlmNzMzNDYwZTdkZDk3OWI1ZDkzZjk1NDM1ZmRkMWU1ODVkM2VjZTcxOWE1MWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhjYjZjMGI5MTEwNmU0NmYwYTNkNTc5ZmYxN2E2MGM3OTg5OGNiMjdlYmJhYWQwZTE2OWY4ZTg3NDNmMzQ5NTIifQ"
"resource": "repo://TFI/App/MobileAppModel.swift#L561-L592",
"version": "repo-lines-v1:sha256:732361941e85bc6b1310b5ce379fe87c719620e03e6ff6f870b870f9e79d553a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJiNDUwODY5MDY5MjI5ODFhMmRlMDMzM2UzMDI2NDVjYzU4OWQ1NGRhYjM2YzdiMDI5ZTMxZDI4ZGQzMDMwNjgifQ"
},
{
"resource": "repo://TFI/App/MobileRootView.swift#L41-L66",
"version": "repo-lines-v1:sha256:768d045bd06100e92eed2837742f40428687f24feb6964bcca513f99f29eef4b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUwNTI0MTczZmExMGJlZTU3OGQ2ZmJhZTBiMGMxNWFlYzNjYmExOTFhZjM1OTczNDU0MTY0Yzc4YThhY2I2ZTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYyYjNhNjBlZjYyMjJkNGZkM2EwNzU4NWQ2NjEyM2Q0YmU3YmVkMTU5Y2I5YzJjMzcxNTJhNzdlNDA1NmNjN2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZlNGY3Yjc2ZDBlODI4YjNlZmNjMTE0OTYxMGQ5NDczZWU3NWMzN2RlYTg0NDc3M2VkYmRmMzhmYjZkMjU2M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRhYTA1ZWU2ODZmZjc3MmYxNjNhNTA3YTEwMmZiMTlmMzM0MzVlMjAxZWU1YjZhYzlmMDI0Y2QwYTNjMTRhNDYifQ"
"resource": "repo://TFI/App/MobileRootView.swift#L49-L66",
"version": "repo-lines-v1:sha256:71239163ff663c4014c578683a144f2b286a8d894129b4b153ef8d49b3ed1276:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwNmIyOTNhY2FiZjI2YWJjZmZmNDhiYzNlZmVkZTIzZmEyMDFiYjA3MDMzMDMxYzcwOWVkZDc2NmQ1YjQ2NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYyYjNhNjBlZjYyMjJkNGZkM2EwNzU4NWQ2NjEyM2Q0YmU3YmVkMTU5Y2I5YzJjMzcxNTJhNzdlNDA1NmNjN2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5MzEyMzk0OTNhNjBlYTFkOTllZWQyZjE3MTljZjEyNjZmMThlNTE5ZDQxZTZmODNiMjYwNjg3ZjUxZTA3OWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRhYTA1ZWU2ODZmZjc3MmYxNjNhNTA3YTEwMmZiMTlmMzM0MzVlMjAxZWU1YjZhYzlmMDI0Y2QwYTNjMTRhNDYifQ"
},
{
"resource": "repo://TFM/App/AppModel.swift#L347-L360",
"resource": "repo://TFM/App/AppModel.swift#L348-L361",
"version": "repo-lines-v1:sha256:0144b1d4de1e5cd79445ffdd9ae6316b81b0a6f8665e43607608488e301005e8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhiYTVlYmQ0MmUzYTYwMzMzYzc0YjRlNjMxYWIyMTYzYmNlMGEwNTQ2Mzk5NzNiY2UwOTdjMGQ1M2UyODgxNDQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY5MWEwM2RhNGM3ZDMxZDk4YjI2YjJlYTcyNzg0YzlkOGExNjEyOTE3Y2RjZmE0NjBkOWEyYTZjMDQxODg1NDUifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L200-L210",
"version": "repo-lines-v1:sha256:a3f04a62c88e099adc46191b71e6b004a9c2cbdccb4b777962cef996af006818:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5NzVmZDQxMjc1ZDdmNDI4ODc3MjMxOWJlNDBiZjZiMGRmM2E1NDM0ZDFhYzk5MTBiMzdiZTVmYmYyODAzNjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ1NTY3N2E1MzNjYmY2YjY3ZjlkY2RiNTg0ZjAwZTM3NmUyYWEyZDZmY2I4NjEzNDdlYTc2Mjg4NmVmZTM4NGMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjljN2E0ZWRjMTBkYjIwNmU2ZjQ2MWJkODRmYjE0Yzk4ODQ3N2IyMTAzNzY2ZDQxZWY1NWYzMmRlYjVhZmIyNzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFhNmMwNDUwNjcxZGI4YTEwMzQ4OGJmMTRlYzc4NmI5NTk3NmY3NTM4NTBiZTUzNGNjNDIyMzcwMzk1NDkyMDQifQ"
"resource": "repo://TFM/App/RootView.swift#L204-L215",
"version": "repo-lines-v1:sha256:f9f9dc0e685e9f439a0bccc6292d2a412122832345af1c9658c8ece976ba4e76:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5NzVmZDQxMjc1ZDdmNDI4ODc3MjMxOWJlNDBiZjZiMGRmM2E1NDM0ZDFhYzk5MTBiMzdiZTVmYmYyODAzNjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4Yjg0NWI2OGU2NWU3NWUwMzkxYjNlZTUwNmZjZDE1MGM0M2EwN2JmOWY1NWVmN2JlN2JlM2Y0Nzg1NmQ4NTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjljN2E0ZWRjMTBkYjIwNmU2ZjQ2MWJkODRmYjE0Yzk4ODQ3N2IyMTAzNzY2ZDQxZWY1NWYzMmRlYjVhZmIyNzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY4MDVjYmNmMTFkN2QwMTUxZDlmZTBlNDk2MTAzMWQ0NGVmNWE0ZTY2OGY4MTUwZGRhODM1Nzk5Mjk3NWJhMGMifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L103-L106",
"version": "repo-lines-v1:sha256:d7a35235421f01a6dbee1cfc2c3f3947990480cc7da3f8b1eeb7d4eadf443a0b:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDhlNjgyZDk4YTk0YjFlMTg2YTg3Y2Y2NGVmYWUxOWJjMjBjZWM0MDBkNTdlZWNkMjcwZjM0ZTc3OWMyNDliMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODc1YTE5OTFkY2Q5ZWFkYjc1NGE1NGY4NjUzYzllNWFjMzU3ZTI5ZmQyZmU3MGFlODlkZTFkMWEyYTk0MjMyYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTJhMjBiZDdhZmI2MWE5NzFiMDc4OWQ4Mjc2MjYzMmQxNmEzYjc2ZTkxN2I1MDBiYmM3ZTE0N2ZlZmI5MWE4YiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWU1ODNlNGYzYmVkNjE2Zjk5MjAyZTU3NzEzNmNkZTdhMzdkOWIwMGFjZTQzOWJmZGUwYWRhNzNlMGMzMTBiNSJ9"
"resource": "repo://TFM/App/TermindApp.swift#L122-L125",
"version": "repo-lines-v1:sha256:d7a35235421f01a6dbee1cfc2c3f3947990480cc7da3f8b1eeb7d4eadf443a0b:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDhlNjgyZDk4YTk0YjFlMTg2YTg3Y2Y2NGVmYWUxOWJjMjBjZWM0MDBkNTdlZWNkMjcwZjM0ZTc3OWMyNDliMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODc1YTE5OTFkY2Q5ZWFkYjc1NGE1NGY4NjUzYzllNWFjMzU3ZTI5ZmQyZmU3MGFlODlkZTFkMWEyYTk0MjMyYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzU5OWMzYWM2ZjU3NDEwODNlODAyYzk2NTUyYTA3MmU3ZjNjZWYxYzJhNTJiMTZkNGU1MmI1Y2Y1MjBiN2EwYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWU1ODNlNGYzYmVkNjE2Zjk5MjAyZTU3NzEzNmNkZTdhMzdkOWIwMGFjZTQzOWJmZGUwYWRhNzNlMGMzMTBiNSJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L24-L50",
"version": "repo-lines-v1:sha256:c0fcdf8d21b0f802f826a33abe78870a19d40443c08b8f5640fa5d1e10b247d5:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIzYTI4ZTc0YzkwYzJlOGQ0YWIyYzUyZmI5NGE0NGI0OGY2MDc3YzFjZGU3YzJlZDNkYzljYjkwOTY5YjNiZmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIwMzE5MmFhZThlNmRiM2Y5NzNjMjI2Mjg0MjQ3YzliNjg4MWFjMTUxMjhlMzhkNzdiYzZjMjQ0NzI4ODVmZWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5MGYxODJjOGI0OTgyMDk3OTA2NTZlNmY3YzcyNGVmMTM4YzcxMjBlY2NhMDU4ZDczMmU2ZjU5NTc1ZDQwZWEifQ"
"resource": "repo://TFM/App/TermindApp.swift#L41-L70",
"version": "repo-lines-v1:sha256:b472676aa8091f471664b71818156d6d1ac8449730885e855c5a10df58377d6b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhiY2M2MTFhZjIzYTkxYzNiNzI3ZDBhY2U0ZGUyMjI0MmZjNDkwNmM3MTk0YTYzNDkxOWI2NWQ3MDNkZDAwYjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1NWUzNDQwZWZmODhjNGJiYTg5MGEyNzcwZTIxYzE4MmVhNzEzNGUzMWY5MDE3OGI5YTI1YTU2YTFlZWQ2YmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4ZWFiZDkyY2RiNmUwZWEyZWI1MjFkMDM0ZjQyOWVmZmI5OWRhYzEyMzg3MjczMmVmOGU4NTUxMzM3ZDllN2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMxNWU1MzZjNGQ3N2U0MTM0YmYyMDg2YThjZjRmN2Q2ZGQwMWFjNTg1ZGNhZDI1MDJiNGVmMDllMWJmMzE4YWUifQ"
}
]
},
{
"id": "claim_a0b96f4616604105b434514165c7592b",
"statement": "Both native paywalls derive trial and renewal copy through `ProOfferPresentation` from StoreKit's validated annual product and eligibility, falling back to an annual subscription without a trial if the offer is missing or unavailable; an unavailable plan cannot be purchased.",
"statement": "Both paywalls feed controller-validated StoreKit annual metadata and eligibility into shared `ProPaywallContent` and `ProOfferPresentation`: an ineligible or missing free offer uses annual renewal copy without trial; unavailable products and processing prevent purchase.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift",
"version": "repo-file-v1:sha256:183451c066b1cd740d3d30fce8d3bae5b981ec65fd5d56fec667abf80839c053"
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L233-L275",
"version": "repo-lines-v1:sha256:d55c7ef58f0c3ab5ff0a485fc7b05e817518125df6d6400bd8149740903285d3:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJkODA2NTg5YjQ0MDNmNDUzMTEzMDVhZjY5MzQzMGUzMzk3NTE2NWViNDc0NjM0YzA0YmE4YThmNTJkZThiNGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNhMjNkOWQ5NzIyZTUzNWFkZTI2ZGMzNWQ2MWRjNTRjOTUyNmEwMjczODE4MGZmODgyODJmMGM4M2FhNDcyZjciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNjMjZhNmNiNzg0ZDlkNTI5ZmMzNGVlY2QxNGQwZjZjNzE4OTRiOTRiNzY1NDY0ZDk0MTUyZmY4MzcxM2I5ZWMifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProOfferPresentation.swift",
"version": "repo-file-v1:sha256:42aa3b8a9a279c72d7f6a57504a3d87e43cdaaeccebb0051a272b19c2229d35d"
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L32-L47",
"version": "repo-lines-v1:sha256:703045e28f12924d2dc7b05569bdc9b0d47d35be6264aabdd3c835f4113f6f0e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ1YjQ0OTYxYmNlNmI5Y2E5MGRhYjNmNzU5OTM3ZGM2ZTU2YmIyZTkxNmZiNWU4NmJmZjc1ZWY3YzllMzRkZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBjOTkxNTM4NTA2Y2ZmYWNhM2MzZTliYjhjNThkY2Y0NTBjMzFmOGZlN2FiN2ZmZTUwNjk1MTBiNjA0NjMwNDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ0MTQ4Yzg4MjUxYTUzM2M3MjFmNDYxOTI1YjIzMjNhOWI2N2QxMTcxZDNkY2M0NTBhN2NjYWM5ZTA3YmEzNzIifQ"
},
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift",
"version": "repo-file-v1:sha256:a031bc4b356fac3f56a8ae282d2a3732a97699557a5c720d728b6c841e6528d4"
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L128-L165",
"version": "repo-lines-v1:sha256:5b5a6173035535064124cf3f649d935500a9a10cc4fc6ce4e839b5abc3e8a42f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1N2U2YzM3M2E4NmNiYzcyYmVjNTMzYTNlMjUyZDk5MDQyYmU0ZWMzOTc0NzdhMTg2YTkxOTQ1MzVkOWJiYzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlkZDA3MzVhZTkzNzA0ZTc5Zjc1ZWU4ZDE5NjI2YTA0YWYzZmZhY2QxMjZhODk0NzQ3NTQ4Zjc1ZjJkMzExZjQifQ"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift",
"version": "repo-file-v1:sha256:691c17b9026d8ec2b4961e345d66f1d226eb4a8e119018d30615d821a1ae0445"
"resource": "repo://Frameworks/TermindPresentation/ProPaywallPresentation.swift#L40-L55",
"version": "repo-lines-v1:sha256:90f880541980539533bdd23ce7540c97824c6cbd223bc483a0af57a1d9c1b26e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY1NmEzNmY4ZGFlMGM2OWRlZTYyZGMxZDdiMTA3Nzc0MTRmZTlmOTMzMzFjM2IzNGNmZDdjNWRkOTFhNGU2NzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2Yjk4YmQ4NmY2ZTkwNDZlOWZjNWQ1MGJhOWYwMjRkOTdlOWI2MzIxOGIwMDAxNDk2Yjk2OWQ5NzlhMjZiYzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlhNmUzY2E3NGJmMGM4MjZjMmRlMjVmZDQ4MGQ0YTAwMTU4ZWQwOGJlNGI3NWNiOGU0OThkMzc4YWE2ZWZmZmQifQ"
},
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift#L39-L46",
"version": "repo-lines-v1:sha256:5f93a0023c244953bc4fbcc0b5995a09dce5d8c8286048ee21cc8d3896695662:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzMwNTIxMTYzMjc2MDNiZTBjOGE1MDJhNjkyZTg3ZGM1YWQyY2VhZDhhMWFjMGM4NWQ4Mjk3NTJkMDE3ZjQ2MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzNhNmVhYjJiNzljNTE0NzIzNTc3Zjg4ZmEzNzMxYWRkZTAwNTY0NDVlNTRiMGE4ZjEyN2VmODQ1MTI4ZjdlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWQ3NmRiMzU3YTAwNGVlYzU4ZWE3YmJiZGRhYjc3MTA3MDQwMTVlYWE4OGQ1NWYxNzJmMTJkNTk4MzYzYTFjZiJ9"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L50-L57",
"version": "repo-lines-v1:sha256:c176828cb5bb7f55f3d0cee6529805e7fdef3911c6d7b66f3ce51cac95a5de91:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzMwNTIxMTYzMjc2MDNiZTBjOGE1MDJhNjkyZTg3ZGM1YWQyY2VhZDhhMWFjMGM4NWQ4Mjk3NTJkMDE3ZjQ2MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiN2E3NzU3MmY0YTZlOTc0MDhmYWI2YmEwYzI0YTkxN2M0YzI0NzZhOWEwMmNlM2I3MTI2M2U3NGY1YjNlYTAyMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWQ3NmRiMzU3YTAwNGVlYzU4ZWE3YmJiZGRhYjc3MTA3MDQwMTVlYWE4OGQ1NWYxNzJmMTJkNTk4MzYzYTFjZiJ9"
}
]
},
{
"id": "claim_263358b0ab424869a92b6de729584fb2",
"statement": "`AppLanguageTests` verifies Pro offer localization in English, Simplified Chinese, and Traditional Chinese, and checks that both app string catalogs have finished Chinese translation units.",
"statement": "`AppLanguageTests` verifies explicit-language Pro offer copy in English, Simplified and Traditional Chinese, language preference migration, regional Chinese lookup, token terminology, forwarding placeholder ordering and selected plural resources; the shell checker, not these tests, enforces whole-catalog Chinese completion for both app catalogs.",
"evidence": [
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings",
"version": "repo-file-v1:sha256:b3bb65bafaf0fec7f526e66d0d6a2f0573996ebd7f23192be9adffb448dff93a"
"resource": "repo://Scripts/check-zh-localization.sh#L11-L85",
"version": "repo-lines-v1:sha256:242b5da53ebb89db32384eaa3a3e8ef2dd048530f1098b001c966421e9c821f9:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkYWZlZGViNWMxYjY5NTM5YWQ3ZDY4MjlhZGQ3NTkxOWEyMWIwMjkwYTM2MDMxMTUxMWRlM2M1YmY3MGU0MjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzOTljNGUwYTRmNDI2YjhlNDA4MzZiNzc1YmUyYWJjMmU3Njc1YTcyZWQzN2UwOTBhZjA2ZTVhYTc2ZTNhNTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc0MjdhZWRmOThkZmEyZjc1Y2RjZTdlNmNiOTVkYzdjZTNkNjhmMjE5NmMzYzRjMDJjYTFiNzFlMGE3MTBiMTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFMTests/AppLanguageTests.swift",
"version": "repo-file-v1:sha256:a87e1a9c1edef71dacdd135cda2b3772e2e6eccfb3d07d42934c9ea04400920e"
"resource": "repo://TFMTests/AppLanguageTests.swift#L12-L197",
"version": "repo-lines-v1:sha256:bcf0fdc1713ef8a7b6c78f56bd02a8a7abf39c3863d1355b5b03ce3c0a6c2133:eyJzZWxlY3RlZExpbmVDb3VudCI6MTg2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJkMzEyMzgwZDhlNGUzYmI5YTc4ODlhMGRjMTZlYTAzZDgyZGI1NWY5NTQ4OWZhYTFiNzUzZTMzMDg5ZWY0ZWQ1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3NTUyYzk3MTEwYTAzNWYzZGI0NjFiMzNlY2ZkNTMwMDc5OTgzMWViZWI3ZTJhMzk4ZDMyYmNmZjUyZWIxZTVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJhNDNiZGFlZjU5ODliODFjNGZlNDJlM2FmZWUwYzM5YjAyMDBhZTJhN2Y1YTg2MjQ0MjJiOTczN2JiNGMwMDIwIn0"
}
]
},
@@ -344,7 +360,7 @@
"evidence": [
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings",
"version": "repo-file-v1:sha256:b3bb65bafaf0fec7f526e66d0d6a2f0573996ebd7f23192be9adffb448dff93a"
"version": "repo-file-v1:sha256:4f4306f2a6cb887d5b85a0f1c26e4ec4fb873d46adaadb1491ca1be3c54ed93b"
},
{
"resource": "repo://TFM/Features/KnownHosts/KnownHostsPageView.swift",
@@ -354,15 +370,27 @@
},
{
"id": "claim_137ed623bcf445d8ab1d56f5ae80920a",
"statement": "The mobile Snippets surface separates empty-library from no-search-results states, offers creation of snippets, packages, and nested subpackages, and offers either deleting a package with its snippets or keeping snippets; package-tree count copy and these creation labels have finished Simplified and Traditional Chinese entries in the shared string catalog.",
"statement": "Mobile Snippets distinguishes an empty library from no search matches, offers new snippets, packages and nested subpackages, and gives package deletion a remove-with-snippets or keep-snippets choice; its package-deletion message selects a count-sensitive shared resource, while section-header counts are locale-formatted numbers.",
"evidence": [
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings",
"version": "repo-file-v1:sha256:b3bb65bafaf0fec7f526e66d0d6a2f0573996ebd7f23192be9adffb448dff93a"
"resource": "repo://Frameworks/TermindPresentation/Strings/Presentation.swift#L18-L21",
"version": "repo-lines-v1:sha256:54af340b7820078d5e504c6ed845f74721e4e77fa7e55964ef18bd107c1f19c1:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2I4MTkzYzk1ZjQyZTUxYTFkYWVmNDAzZGE5NDZiZGFkMGFmMzk4NWFhMWRlZjkyNWNmY2ZiYjAxZDU4YTU1NCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTllNzYzNTVjZjExOTk0ODBjM2Y5OTgzNmIxNDg2Yzg0MWQ4OTFmYWFkOTA0YzYwOGUwOTMwMjJkMzc1N2FlZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOGRhMTcyMGQ2MDcxOTI4ODc1NTk0YWFmN2M2YTI3MmU3YTc3MjdiYmNmNGI1NDgzNTMyOTkxZWVkYmMyNGE0NyJ9"
},
{
"resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift",
"version": "repo-file-v1:sha256:57caab3fc7e74b38a5e9efa11df8de834c2a05a01f9e4900502e4feed5cb919b"
"resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L141-L155",
"version": "repo-lines-v1:sha256:e3b76c2a248df8d7763f7d278a213a6e67c37b1bff14aed4042c30bc98cd6059:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiYTYzZDkzNmVmZmQxZTZiYjIxMjI0YjA1NmFmNjdiM2Y2MjNiNzNkNDVhZjhkN2FjZjc2NWM0Nzg1YmVhNjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE3MjQyMWVlNDljODI3MWRlYThkMWUwYTc5ZDJkMjJmMDg4NDQxM2NkMDdiYmNjMDhhNDIyN2Q2NTI2NDIwZTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBkYjQxY2ZhN2E1MjI5MTk4MDk4ZDhlYzc3YjMxZjg1NWY0N2Q0ZGE4OWFlMjc0ZWM4ZTZhNzY1OTk4M2Q5NGMifQ"
},
{
"resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L198-L227",
"version": "repo-lines-v1:sha256:4868e16645ae70b80f284e1eb39f79f400f412593d4255515a9d5992ccb6faf5:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwYTg4ZDc1YTNjZjcyMDQ5OWM0OTU1ZDI4MWQ5YWU3YTdiNmYzNzdkY2RkZTQ2ODllMDIyZTUyY2U2ZWIyYzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMyNDZiYWYyNTc2MDRiODVhZGE3ZTQ3MGU2MTMzZDM3ZTNhYjczNTNlNTRlZmU3ZmFiYzc0NzRmZmNmZGVmMWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVjYjk1YWE1NTNlYTdmOTYzNDA1NjU3YjFiN2MwNmU4MzY5OTdmNDdkNWMzMmI0MmM2MWRmOGRlN2E4MDg3MDUifQ"
},
{
"resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L339-L355",
"version": "repo-lines-v1:sha256:eb1616a1038883448af2a4f25af5066c726f4bdaa3ae5670b13f9b75b017759f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZmMDgwNDY4M2FiNDA4MWU4ZjVlODhmNDJhZGVmNGYwY2UxMGRjOGRjOTUwY2JkOTQ4NGQ3OTdkNGZjYWE2YmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg2MmM2NGVkN2Q1NDYwMzdlNzBkMmQyNzlmMDA5ZDRkMTZhN2JiZGQxMDZkN2IzNTgyNjJiMWUyNzg4NmM0Y2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE4Zjg1NDZlNDMzZDc4NjQzODA2NmJjNjllMDg1MGZlNWIyNjU3MDBmYzBlNDM4ZGU4MWRiM2ZjMTJiOWM0ZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE2NDYzZDMyYTdjZGMyMjlhNzg4MjkyMjFkY2E4OTFjOGJiMTBkZTM0N2NkOTdiMjU3Zjg2N2Y4ZjA5OWFmMmIifQ"
},
{
"resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L59-L95",
"version": "repo-lines-v1:sha256:ee7c8f9fdfa76a9fe2c5401972572c9f29429c89faa38d58eab592418d3610c2:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVkOGZmZjY4MDgwNGJkZDg1NjgzYWU5MTc5YzNlNTdjOGUyOTdlNjM2YjI0MjAzNTJlMWQ3YWJlOTc0OWVkOGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkyN2FlYWRlOTVkYmRmZDdkM2NhZWVhZTc5MmUwZWMzMjQxNTE3YjA2MjYyNjA4M2ZlMzYyMzRiOTQzNjg2YTYifQ"
}
]
},
@@ -386,19 +414,27 @@
},
{
"id": "claim_0dc4305d926c43fa9b2d56ac760f614b",
"statement": "Language tests verify explicit-language Pro offer copy, catalog completion for Chinese in Localizable and InfoPlist, Simplified versus Traditional lookup, and assistant token-unit terminology distinct from security-token labels; mobile tests cover known-host add/edit titles and opt-in real-window card captures of Snippets, Known Hosts, and editors in all three app languages.",
"statement": "Focused localization tests cover explicit-language Pro offers, Simplified/Traditional lookup, assistant versus security-token terminology, forwarding placeholders and selected plural forms; mobile card tests cover Known Host editor titles and opt-in real-window captures in all three app languages, while the catalog checker enforces whole-catalog Chinese completion.",
"evidence": [
{
"resource": "repo://TFITests/MobileCardRenderingTests.swift",
"version": "repo-file-v1:sha256:90ca1c139d848451a57fd799f86760b088037baebb619bb8192fe677710d2077"
"resource": "repo://Scripts/check-zh-localization.sh#L11-L85",
"version": "repo-lines-v1:sha256:242b5da53ebb89db32384eaa3a3e8ef2dd048530f1098b001c966421e9c821f9:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkYWZlZGViNWMxYjY5NTM5YWQ3ZDY4MjlhZGQ3NTkxOWEyMWIwMjkwYTM2MDMxMTUxMWRlM2M1YmY3MGU0MjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzOTljNGUwYTRmNDI2YjhlNDA4MzZiNzc1YmUyYWJjMmU3Njc1YTcyZWQzN2UwOTBhZjA2ZTVhYTc2ZTNhNTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc0MjdhZWRmOThkZmEyZjc1Y2RjZTdlNmNiOTVkYzdjZTNkNjhmMjE5NmMzYzRjMDJjYTFiNzFlMGE3MTBiMTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFITests/MobileCardTests.swift",
"version": "repo-file-v1:sha256:939145e6d44815a490719611e084759af0b697d128342d64d522ff842f4c3f3b"
"resource": "repo://TFITests/MobileCardRenderingTests.swift#L10-L15",
"version": "repo-lines-v1:sha256:e1681df181d4a3da4b6c95642b35c5d54d4373812047ea74e2d8a58de9ce5801:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOWI3Yzc2ZTYwMzQwZWUxMGNhZGFjMDI0YThjNmFhYjJjYTg4NjRmNjdlOWI2ODlhMTFhODc0OTMyY2E1OTdlZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzA5OGE1N2Q2YjdjZDc5ZjYyOGUxNDcwZjhjYzhiNTFlNDg4NDQ4ZWNjZjYyNjUyZTkzMzM2ZGQxODk2NWZiZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNzAzOTk1NDMwYmU3ZGVkYmIxODNhNGZhMTEyYWUzZDJiNzE3YzM3N2UxMWYzZTdkYWUyZjUyYzBjNjU0ZDE2OSJ9"
},
{
"resource": "repo://TFMTests/AppLanguageTests.swift",
"version": "repo-file-v1:sha256:a87e1a9c1edef71dacdd135cda2b3772e2e6eccfb3d07d42934c9ea04400920e"
"resource": "repo://TFITests/MobileCardRenderingTests.swift#L95-L160",
"version": "repo-lines-v1:sha256:365e7a1aaadc77102c15c78125fd3d3bfeac73bcf1833fb8a20b135aa4aa00b9:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxM2Y0MmNjNDk2ZDAyYTU4ZmIxZGQ4NmM4MWQxN2NjZjY5NTQ5ODk2NjM5NTQ1MWRiNTkzMTg2YmZhMGNhNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxMjRiZTQyNDU3MTA0MzVjMmE5OGM0NTZjMzNkNjJiMWI5YmRiNjVlYTMwMDRkNjZmZjcxNWU4MmZkM2ZjZDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNlY2M2Mjg1MjI2NmZiNTk1NjVjYmRhNjhhNTBmNjE5MDc2OGNhMWYwYjZkMTZmOTQ1NjMzNjVjNTE5MTgzYzYifQ"
},
{
"resource": "repo://TFITests/MobileCardTests.swift#L100-L110",
"version": "repo-lines-v1:sha256:86262ee7e293839d7daf64d62bc3a41d42e9e678530b41df1feeeae5f756a708:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwOThhNTdkNmI3Y2Q3OWY2MjhlMTQ3MGY4Y2M4YjUxZTQ4ODQ0OGVjY2Y2MjY1MmU5MzMzNmRkMTg5NjVmYmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU0Njc3MWY1OTc1OTNmM2RmMmYwMmExNWY5NzU5NDkxYzExYjc1OTNiNzExNTBlMzM1ZjAzOTZlYWU5MWFhYTgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhZjE2N2ViZGY4NjZhYTM5ZjE0NjlmMDVhMjE1NDFlNGJmMjBlOTAxNDQxOThlYzg0OGNiMzhkMDVlN2RkNTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYyYTQ4OTNlNmE2NWFhZDk2MGMwN2ZjMDMwMDdjZmMzNTliYTM2Y2EyZTAzYzU5ZmZjMzc4MTM1MmI5YjY1M2YifQ"
},
{
"resource": "repo://TFMTests/AppLanguageTests.swift#L80-L197",
"version": "repo-lines-v1:sha256:87016025058ddfb585ad40b9a3a40c38945e1d50536cdc13fb7468c651be663c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE4LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJlM2RjN2I5MmUxN2JkNTllMjI0ODNkYzA3ZWVjOTVlMTEyMWJlOWNmY2JiZDc1OWVkZjhlYWM3NjRhMGE5ZDI3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJmNDEyZmJjNjRiNjMxN2EzMDJkYjg2YmUyNWYxYWI1NTNkOTU5NmYzOTNhYTgzNjliZWMxZGU1ODZkYzExNTkwIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJhNDNiZGFlZjU5ODliODFjNGZlNDJlM2FmZWUwYzM5YjAyMDBhZTJhN2Y1YTg2MjQ0MjJiOTczN2JiNGMwMDIwIn0"
}
]
},
@@ -463,10 +499,138 @@
"version": "repo-lines-v1:sha256:b88059d0a3d5d90e5b1a5051a317026c144f6169564dd25d102760fb7f446e5b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTc1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI3MmJiNmQ1NzgzMTJmNjJmZGQ3OWM4ODdhMGNjNmVkMDRjZDkwOTQwZjFhYWE3ZTlhNTAyMGVmNjkyOTFhOTU3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJjYWM1MTVjNDRmMTU5ODk5M2QwNmMwNzlkMmQwNWEwZjc5MWMzZWRlNDUzMTMyNDA3NGUzZDY2Y2ExNTFmYmY1IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI4Y2QxYTdmOTRjNDA3ZGQzZTMxY2ZiNmE3OWRmZDQzMGQzMTU3MjI5MjViZDczY2UwNGM0YjFmMjA4MTA0NjdjIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIxMmI5MDFmNWExZTMyNGJhMzA3ZWIxYTdiOWU4YmY2M2Y1NWNhYTM1MDE0NTFlNWM5M2Y3YWI1MjkwZDJhMjE2In0"
}
]
},
{
"id": "claim_23f89546b51e4dbe9abfc989b8902b7d",
"statement": "Shared `ProPaywallContent` owns both platforms' status and date presentation, feature list, picker, restore, reload and legal/disclosure UI; the macOS snapshot advertises built-in plus remote MCP, whereas iOS advertises remote MCP only, and the requested Metrics feature adds a free-limit explanation.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L168-L209",
"version": "repo-lines-v1:sha256:3d71a01655c41419887fb2d6c707010b5636168a8ea3a5d73b97d789b2450355:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4OGMwZmY3ZDlmMDg2YmRlNjQ2ZmJmNDg5NTU2Y2MxZmQyMjg2YzM2MTk2MTVhODczYWU3OTJjYmJkN2VmYTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE4N2JjNzNmOTI1NGIzMzkwOTIyM2Q3ZWFjNDFiNjU1NTAzYWY4ZmRkNDRiNmFkZjg5ZGQ2MWI0YzExZTJjM2QifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L33-L53",
"version": "repo-lines-v1:sha256:31f9e6064afb1f93cffc818e227eb00fd10d2179ace0df56676b3a532744f74a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5Yzk2NTJkODc4YmVkYzBkZmQxNzU1NDRkNDc1ZmFmNTdkNTY5N2M0MGU2NzBhOGZjMWIzZjQ4NjZmYWY1ZjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxMjRkMzMzZjVhY2QzZjc4ZjVlMmFkNjRmM2MzZWYxNjZmZDk2NzdiM2VkZDBlNjRjNzZkOTE4NjQwNmVhYjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0ZDIyN2E0Y2FmNWQ1NDFmMzU1ZTc1YWEwMmFiM2IxNTMwNjcyNzg0MThmZmY3MGQzMDhiMDY5NWJiYTc3MmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0ZTlkNjE4OTFhMDNmZjc4NjQ4ZjcyMzc0NWJiZTVjOTNlNTFiNWQ2NzAwNDJlNDQyOTkyYTRmNTNhOTgzM2UifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L71-L125",
"version": "repo-lines-v1:sha256:bb7a79324b9957a5c8eb18df96fa5ed9f49e8841c3f37fa2fb5ef3e8e50f0aba:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI3MjNhMDQzZWFkMWM4NTJhZDlhNjRmOGQwZmVkMjhhNGQ1MjNkNzQ5YzE0OTEzNjAyYWFlNmVkMGU4MDBmZDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZkZjBjZTgzZWM3ZGRiODk1MmRkM2Y3NDI3YjMyN2VlZjZhOTZiMTI0NGE3MTU5YzIzNmZkZjdlYmU4NTY5OTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdiNGNmMjkzNTAzNmYwYzA5OGIwMTlmMGUwZjRmZWQ0NDA0NmRiZjhlZmUzZTEyZmJjYzU5YzlmYzJhNjY2NTgifQ"
},
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift#L39-L46",
"version": "repo-lines-v1:sha256:5f93a0023c244953bc4fbcc0b5995a09dce5d8c8286048ee21cc8d3896695662:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzMwNTIxMTYzMjc2MDNiZTBjOGE1MDJhNjkyZTg3ZGM1YWQyY2VhZDhhMWFjMGM4NWQ4Mjk3NTJkMDE3ZjQ2MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzNhNmVhYjJiNzljNTE0NzIzNTc3Zjg4ZmEzNzMxYWRkZTAwNTY0NDVlNTRiMGE4ZjEyN2VmODQ1MTI4ZjdlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWQ3NmRiMzU3YTAwNGVlYzU4ZWE3YmJiZGRhYjc3MTA3MDQwMTVlYWE4OGQ1NWYxNzJmMTJkNTk4MzYzYTFjZiJ9"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L50-L57",
"version": "repo-lines-v1:sha256:c176828cb5bb7f55f3d0cee6529805e7fdef3911c6d7b66f3ce51cac95a5de91:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzMwNTIxMTYzMjc2MDNiZTBjOGE1MDJhNjkyZTg3ZGM1YWQyY2VhZDhhMWFjMGM4NWQ4Mjk3NTJkMDE3ZjQ2MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiN2E3NzU3MmY0YTZlOTc0MDhmYWI2YmEwYzI0YTkxN2M0YzI0NzZhOWEwMmNlM2I3MTI2M2U3NGY1YjNlYTAyMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWQ3NmRiMzU3YTAwNGVlYzU4ZWE3YmJiZGRhYjc3MTA3MDQwMTVlYWE4OGQ1NWYxNzJmMTJkNTk4MzYzYTFjZiJ9"
}
]
},
{
"id": "claim_7b2466f37c1e461980ca5ddfd472a1b0",
"statement": "The shared paywall presentation exposes subscription management only for purchaser-owned subscriptions, retains processing/errors even for active entitlement, offers product reload when either price is absent, and denies purchase without the corresponding available priced product or while processing.",
"evidence": [
{
"resource": "repo://FrameworkTests/ProPaywallPresentationTests.swift#L24-L89",
"version": "repo-lines-v1:sha256:a5cb03426dc1b6530d8380dfab14b95fe1bfe1bc42e812aafb7098fe54f8158e:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUxZjZjMWM3ODMyMDQ0YzBjZDFhYTU2ZTJkMDI3OTM3M2YzZmVhZGM3ODE0YjZmZWE2OGUzYzI0NmU0ZGMwNWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNmOWIyZTM1NzdkOTc2NTc0YTBhYWM4MGM2MGM4NjlhZTdmOTE1OWY4MmVhMGJiNWYyNDY2MjNiYTAzNDY4ZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE4MDllYWE3MWRjNmZkZDE0MjUwOTY0ZjJlYTgwMjI2NzE0NWE1NDhhMDRjMmZlNjRmMTJlYzRlMjQxNzUyYWIifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L128-L200",
"version": "repo-lines-v1:sha256:6d41035dda8bfb01027cb747f34e8d9c06914e4401f1e50172ea350451a6c6af:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1N2U2YzM3M2E4NmNiYzcyYmVjNTMzYTNlMjUyZDk5MDQyYmU0ZWMzOTc0NzdhMTg2YTkxOTQ1MzVkOWJiYzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY5YTY2N2Y0ZTJhNTI1NzRkMDU1MmQ4ZjE3ZDEzNTU3MzJmYjk0ODQ2ZGI4ODc4OGQ1OWQ2N2RiNGM1MmEzMGMifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallPresentation.swift#L40-L55",
"version": "repo-lines-v1:sha256:90f880541980539533bdd23ce7540c97824c6cbd223bc483a0af57a1d9c1b26e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY1NmEzNmY4ZGFlMGM2OWRlZTYyZGMxZDdiMTA3Nzc0MTRmZTlmOTMzMzFjM2IzNGNmZDdjNWRkOTFhNGU2NzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2Yjk4YmQ4NmY2ZTkwNDZlOWZjNWQ1MGJhOWYwMjRkOTdlOWI2MzIxOGIwMDAxNDk2Yjk2OWQ5NzlhMjZiYzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlhNmUzY2E3NGJmMGM4MjZjMmRlMjVmZDQ4MGQ0YTAwMTU4ZWQwOGJlNGI3NWNiOGU0OThkMzc4YWE2ZWZmZmQifQ"
}
]
},
{
"id": "claim_ca826c563a8d4bc4835573ba21d58ce4",
"statement": "`ProOfferPresentation` converts StoreKit `weekOfYear` trial durations to full days for locale formatting, suppresses trial badge and trial-term detail without a duration, suppresses annual terms without both price and billing period, and keeps lifetime no-renewal detail independent of annual product availability.",
"evidence": [
{
"resource": "repo://FrameworkTests/ProOfferPresentationTests.swift#L136-L150",
"version": "repo-lines-v1:sha256:ada212a40f933e7f46b3c7c49a9f3b2b8bd4032d91276bdc06aa298b62fabef5:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYwOGEyOGM3NzkxM2IwYmFhOWExZWNkMTg2YmY1NWJhMzAyMmFjMmQ0Yzc0YjM1YWRmMmEwNmI0Mjg3M2EyZWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzOWYwMGMwZTA0OWMxM2E3MmQzZjllMGZjOWIxYTVhYTVmMTg3YTJhNmFhNTEzYzM0MDYzNzIwN2M3NGZjMDYifQ"
},
{
"resource": "repo://FrameworkTests/ProOfferPresentationTests.swift#L38-L69",
"version": "repo-lines-v1:sha256:2bdd46925065e4b31ec0651030540bd19de312f20746369e11c42b074a1b9d42:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiNmM5ZmU4MmRhYmQwNmFlMWEyNzRiZTY5MjlhYTg1MDdmMDk5N2UxNTIwMmU4ZmZkMjI2Yjk5OWMxZDAzY2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJkOWQ5YWUxOTdmNTRiMzYzZWYwNWFkYmE2MzU0YzJhMTQ0YjMxOTI2MGMzOWM0ZmM0ODI0YTIyZGFkN2JkOGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdkMTc3NWRhY2FmNDJiNTIzZjU4MmQzOGQzNDNjMmU3NTMyOWZlOWQ0OWQ3ZTBiZTc3NzJlMGRjOTZjYjc3ZDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFlYjdjMmY5M2FjOWFlZGU1MjU4NWFmMzYxZmNiZjZhZDljN2NmNmM1OGY0YTliYTg2NjZjMjM1Njg3YTc0Y2MifQ"
},
{
"resource": "repo://FrameworkTests/ProOfferPresentationTests.swift#L7-L23",
"version": "repo-lines-v1:sha256:f817d719b495371dcfb08bb5c8bd75a1eb1ff0ccad0e48b5becd35874006e39b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUwNzRlYmYwOGUxZDhmZGRjOGQyYjg1MGNhMGVjZWY5ZWZjNGFiYjA2YmYwYzQzNTJhY2U2NWUyZDExN2Q0YmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMxZWZhMzlmOGY0MWQ5NjFiNGRkODgwMmI2OTZjOWVlODBhZDBjZmZkOTMxYjFiNDVlMGJhYmM0N2RjZjQ5OTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmNmE0NjE1OGFhNmI0OWExNWJjYWY0YzlmNTUxYzBkZjJjZTYyYzg4ZTYwNTFiYmY2NzMxZDRkNzdiNGY0NGUifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProOfferPresentation.swift#L15-L66",
"version": "repo-lines-v1:sha256:cee58982755b6a10823cbeaacd536d17b1484a0e045b818c4c151d825c27a0c9:eyJzZWxlY3RlZExpbmVDb3VudCI6NTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4ZmIyNmNiMTk1YmY3OGVlZGFkNDEwMDkyN2E4OWQ5ZTc2M2MxMmE2YThlNzFhYWM4MTFlYjRmY2I3MTdlMjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxOTc0YjQyZmE3YTA0M2Q0Y2Q0NTIxYzg3ODYwMDhkMDM2YWIxNjY3MjkwODUwODYzZDdhNDFjNmRjNTc0NzMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJkN2RhMDAzYzM3ZjI4ZDUwNDllMjdhODFiNTIxYjBjZjA0ZDBhZTYzMzM2ZTFlNGZmOWIzM2JlMGMyMTZhMzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
}
]
},
{
"id": "claim_9e5dcbfb0e4c4a6ebb3d30af40da4805",
"statement": "Both shared app string catalogs are manually managed: normalization sets every extraction state to manual and canonical Xcode formatting without deleting stale keys or altering translations, while the Chinese check verifies normalized catalogs and completed Simplified and Traditional units; stale extraction from one target is not grounds to delete a shared key.",
"evidence": [
{
"resource": "repo://AGENTS.md#L48-L69",
"version": "repo-lines-v1:sha256:26697577d9457afd4d5953ff5464ff3ce8419e303deb7f51ea1d9644abdfc2ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdlYjZlZDYzN2JlNjgzYzc2MTJmNjc3ZWE5ZTFhNTZiOTY1OTllNzcyZjZkNzY5MGI0MjM3NDBjZDE0YWZmZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg0NTE4ZWQ0MjVmYWVjYTU4MTRhMWMxMDE1NGYxMzI4MThlYjNlYzBiNmU4Mzk4ZGY0OTRiOGFkZjdjM2EyNDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4NmYwZmMyNmM4NWViY2IwODgwNDgxN2JiMGQzZGJkN2EwOWE2MWE1N2RhOWEwNTk3YWFjOWU3NWQwZDc0OTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlZGM0MzMyOThhZDU4MTI5ZWUwYTg4NTJjMTNmNTI5MjBkYWFmOTRhOGM2NGE0ODcxZWVlZjQ2ZTEzMTVlZDIifQ"
},
{
"resource": "repo://Scripts/check-zh-localization.sh#L11-L85",
"version": "repo-lines-v1:sha256:242b5da53ebb89db32384eaa3a3e8ef2dd048530f1098b001c966421e9c821f9:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkYWZlZGViNWMxYjY5NTM5YWQ3ZDY4MjlhZGQ3NTkxOWEyMWIwMjkwYTM2MDMxMTUxMWRlM2M1YmY3MGU0MjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzOTljNGUwYTRmNDI2YjhlNDA4MzZiNzc1YmUyYWJjMmU3Njc1YTcyZWQzN2UwOTBhZjA2ZTVhYTc2ZTNhNTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc0MjdhZWRmOThkZmEyZjc1Y2RjZTdlNmNiOTVkYzdjZTNkNjhmMjE5NmMzYzRjMDJjYTFiNzFlMGE3MTBiMTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L1-L6",
"version": "repo-lines-v1:sha256:a4f7e4e8cd45a6a2e257248bc9cef3775d26f29a5f556dc4f80c9f52b74cddea:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDY4MmNiZGI0YzhiMDc1MThiZjQ4NmM1ODk5MGZjMzkxNzgzYWEyMGE5MTZiZmIyN2FkMjExZWIxZDVjMzY0MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOWVlYjY0YTVlNDE3MWJjNjIxOGQxYzVhMjRjOTYwYWY3YzUyOGYyYjBmMzU3NWFjNmFjN2VlYzE5M2ViNzM2MyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWFhZjc2MzdjYjZlN2U1ZGI4NWQ2MzQyNzQ2MDE0ZGYwNDFjY2Q1NThhOTIwYjI5ZWI2YWM3MTlkN2JhZjVjMiJ9"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L75-L80",
"version": "repo-lines-v1:sha256:6c71ea7347ff9717c89060d589415e0ed157060322ff0439a96fa684359794ff:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDk3MzhkYzIzYzYwZjQ0NmMxNGQ3MTNmOWRiODZkNWNiNWMyOTcyOTI3YjQ1MWYyZjI3OWZjYWM4ZWMzZDM5OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTc0MTRjYzM0NWNjNmQ5MTY1YTdhOTk3ZWUzZGRkMjU1ZTExNjMxZjRkZWI0OWE2ZTI2MzNlNGRiNjljNTFhYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTZiNDZlMTg5ZWQyZWEzODEzZWI3OTY0ZjcwYjNkMTBjZDUxZTFhMGIyZGNkYWNhODk4N2QxNGNmOTA3NzYxMyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMzYxYjQ1OTI5ZjJiYjIzYjY4NWM1NDdmNjdkOGI2ZTY1NGU2NDQ5YTYzOWQyZDc2ZjVmN2VmY2ZhMWVlMGNjOSJ9"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L97-L127",
"version": "repo-lines-v1:sha256:26d3ca462ef0501fa83b81598f8af234c64c8303b8c6e420735fdd32caaaceb8:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiMzk3OTMzYTI0YTgwMWVlOTIzMzI3YmQ2OWEwMTA0OWMwNzc5MTUwMjFjZjJlYzM5ZGRhNGY4MWFhODM3ZTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhY2QwNjFjNGE0OWIwMjdkZTY0MjUyYTZhNTZlM2ZiNThjNTIxYjNlMzUwOGRhZGFlN2FkYzFkNDA2ZDI4ZTkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcxMTc5YzVmOTVhMDJlMTg2NTczYjkzNDhhYTYzOTZkNjZiNDUzNjgwZWEzODNjM2M1ZjUxMGFiYThhNGZlZWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkyZTI1MTEwNDUwNTM2Njc5NDMzOWI2ZTRhNDZkZGY1MDBlNzNlNWJmZjBhMjQzYjU5ZmQzNjI0OGE0YWI0YjEifQ"
}
]
},
{
"id": "claim_6656160cabd74b2c9387b5713a3afeba",
"statement": "`AppLanguage` writes canonical explicit-language tags to `AppleLanguages`, removes the override for Follow System, migrates older Simplified Chinese preferences and treats unsupported stored tags as system language; catalog lookup selects the effective app-bundle localization including regional Traditional Chinese.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/AppLanguage.swift#L3-L37",
"version": "repo-lines-v1:sha256:2f7cfdc084f8251409d1a61d892f2d2d9ebeb8fb7405e6f2ace5f33bcdf6ebc3:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwZTE4NTRiZjA4NjFkOWY2MDlmMzQ3YTE0NzE1ZmM1ZjE4NTRjYTI2NjBhYzhhYzY1ZDk1YTFjOWE1ZGFhY2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUyM2ZjMDUxYmQzNDMwODljOTYyMzJkMjBlMzlhZjJjZmU4MDQ2ODQ1NmQxN2M5NzEyMzhiOTNmMTRkZTU4MjEifQ"
},
{
"resource": "repo://Frameworks/TermindApplication/AppLanguage.swift#L40-L101",
"version": "repo-lines-v1:sha256:32a3341d190601d3d9a385d057203b2152b1d685b4dab2b863d357704a204853:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVmZmE4ODM4NGY1ZGJhZjgwNWMxYmQ1OGZmZjBiOTVhOGY3ODBmOWE1MjAwYjUyYjk5YjlkYjIxNjcyYTAzZTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFMTests/AppLanguageTests.swift#L12-L89",
"version": "repo-lines-v1:sha256:221c22bc8a6d1b8b791760075364fa12c9920a45d8b49bde460de02c3dc6fa6a:eyJzZWxlY3RlZExpbmVDb3VudCI6NzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQzMTIzODBkOGU0ZTNiYjlhNzg4OWEwZGMxNmVhMDNkODJkYjU1Zjk1NDg5ZmFhMWI3NTNlMzMwODllZjRlZDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NTJjOTcxMTBhMDM1ZjNkYjQ2MWIzM2VjZmQ1MzAwNzk5ODMxZWJlYjdlMmEzOThkMzJiY2ZmNTJlYjFlNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk0ZTdkMmVlYzM0ZjNiMzZmMmI1NDhjNTJiNzhiYzBhZjJlNmNhMThlNjc5NmY5NTMyODc1MjgzYTcwM2Q5NjcifQ"
},
{
"resource": "repo://TFMTests/AppLanguageTests.swift#L123-L134",
"version": "repo-lines-v1:sha256:d899741cbafb6d9990e1c82b6684e6f98373d57606845bee1fe3edb3c888e415:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzNTFjNDM0MmE4MjllMmYzYThkYjZjZjhlNzA5MjcyY2I3ZGNlNjdiNTVjNTA3NGE3MzJlNzNjMDUxYTc4MjMifQ"
}
]
},
{
"id": "claim_a6a1fd7834a946f6ae42fbcfd0e92adc",
"statement": "`ProOfferPresentationTests` exercises weekly-trial duration conversion, eligibility, missing metadata and caller-supplied localization; `ProPaywallPresentationTests` exercises status/date meanings, canceled renewal, family ownership, product absence and progress/error behavior.",
"evidence": [
{
"resource": "repo://FrameworkTests/ProOfferPresentationTests.swift#L7-L150",
"version": "repo-lines-v1:sha256:863b13245debf950942efa4b14ec6daa15ab433d584be238d1860e8e20c9d71d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQ0LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJlMDc0ZWJmMDhlMWQ4ZmRkYzhkMmI4NTBjYTBlY2VmOWVmYzRhYmIwNmJmMGM0MzUyYWNlNjVlMmQxMTdkNGJlIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIzMWVmYTM5ZjhmNDFkOTYxYjRkZDg4MDJiNjk2YzllZTgwYWQwY2ZmZDkzMWIxYjQ1ZTBiYWJjNDdkY2Y0OTk0IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwMzlmMDBjMGUwNDljMTNhNzJkM2Y5ZTBmYzliMWE1YWE1ZjE4N2EyYTZhYTUxM2MzNDA2MzcyMDdjNzRmYzA2In0"
},
{
"resource": "repo://FrameworkTests/ProPaywallPresentationTests.swift#L7-L89",
"version": "repo-lines-v1:sha256:4c14c5b53e5f318d21cbec321fdddbc17154e6902886d5798fa3ab3f519dddb2:eyJzZWxlY3RlZExpbmVDb3VudCI6ODMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1NjlmMTMyNDk2MmJkOWU1ZGYxNjRiZjdiZDA4Zjg4YmRhNzBkYTE1ZDFhODg2OGM2ODJjNDUyOTQyYjA0M2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjljMTIwMDNkYTFiMWY0NjNhYWMzYTU5ZjZlZjcwMmNkOWNkZTE4MjAzZGJjODRiM2E5YzhlMTc4MWM4NGUxZDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE4MDllYWE3MWRjNmZkZDE0MjUwOTY0ZjJlYTgwMjI2NzE0NWE1NDhhMDRjMmZlNjRmMTJlYzRlMjQxNzUyYWIifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:e48470e3b9537dec53eb00cd0a9706bdc523befa7d56e33a4febb1c153129a6c",
"pageVersion": "sha256:ce2823da7595d02f213dbd22d558873d3b27f8157eab9bd8d171fef116cc09a9",
"claims": [
{
"id": "claim_e50b505da2214c6781fa8eb1a146dacf",
@@ -16,7 +16,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -30,7 +30,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -468,7 +468,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift#L30-L38",
"version": "repo-lines-v1:sha256:4b22e5f4357b3b75549a2df873a4f7396eeff7b7c727404bdc8196d0f05c7011:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMWMyNThiN2I0ZjViNGFmODg2MThkMjg0YmQ4ODVjZWZjM2IyZDE5ZGExOTk5OWY3YTE0MjRiZDEwOWIyM2NmMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiY2MxODM1YzBhNmE5ODhkMzM1NTZmZDE1OGYwZWU0MDA3MzZhNTQxOTkyNGVkNjQxYjY4ODlmYWEwMGZlMjE0MCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNGEzNjUzODgxZjg5MjNkYTJhYmYzYmFkM2YyYmFiM2JkYjhhMzY2OTViNjkyZjliOWY2YTExYjc1ZDgyOTBmMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWNhM2IwMGJkMGIxZDUzOTAxMTYzODJjYWZjNWRlZWVlNGRkYjY3M2VjNTUxZWU0OGY1ZGRhOGJmMjBjNjMwNyJ9"
"version": "repo-lines-v1:sha256:fc28d8317e47b1c3cb32d2fa431ed45690867ae8caaaadf9acbd2be1b2a111de:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMWMyNThiN2I0ZjViNGFmODg2MThkMjg0YmQ4ODVjZWZjM2IyZDE5ZGExOTk5OWY3YTE0MjRiZDEwOWIyM2NmMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiY2MxODM1YzBhNmE5ODhkMzM1NTZmZDE1OGYwZWU0MDA3MzZhNTQxOTkyNGVkNjQxYjY4ODlmYWEwMGZlMjE0MCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNGEzNjUzODgxZjg5MjNkYTJhYmYzYmFkM2YyYmFiM2JkYjhhMzY2OTViNjkyZjliOWY2YTExYjc1ZDgyOTBmMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWNhM2IwMGJkMGIxZDUzOTAxMTYzODJjYWZjNWRlZWVlNGRkYjY3M2VjNTUxZWU0OGY1ZGRhOGJmMjBjNjMwNyJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L57-L88",
@@ -605,10 +605,66 @@
"version": "repo-lines-v1:sha256:99e8c3c311bf8ac02b14dd46b5be07ae2a313a7dec6b6fc526610ce40e400ee5:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkwNmQwMjc3NGU4ZGE1NWVmNGQyYWYxZGUyNDliYmFkNmVlMWU4Y2FhNWM0OGYyNWY5ZjQxMTA4MjI0ZjVlZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY5NTkyZjUxY2NiZGExM2ZlMzVjNTI4ZWQ4NWQ0OGNlYzBlN2ZhNGI4YjMxMTBiMjAyYTkxOWY3MjU2NGQ0OTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJkNDU3YjJhYWRhZTY4NzQzNzY2M2EyNTQxN2Y5MGRkNTQ1MTMxNmViZjQzN2Q1MDY5MTQ3ZTY2NzhhZDg3MmMifQ"
}
]
},
{
"id": "claim_2d0f5018482d47b68fea5e69763bc82f",
"statement": "macOS `TermindApp` opens the shared factory during initialization with a default file-backed store for normal launches, but DEBUG XCTest and screenshot demos use an in-memory container; screenshot demos return before live persistence wiring, and the retained container is injected into both main and external-authentication window scenes.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L196-L226",
"version": "repo-lines-v1:sha256:a421409a9872a0df9ea5f19f2f67ea3528a8482e847d32da2aa24f00cfa8ade2:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwNTgzMDJjZDFmMDQ4ZTE3MzU1MTUxODA0NzRjYmI4M2YwZjhkZDNmN2I3ZjUyODI4ZDU1ZmUxYjg1MmIxOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ0MTA0N2ZkYjNiOWIzMTYwZTU0NWEwOThlOGJhY2E1ODA1YTJlZmFjNGI3YWRkNmYxM2IyNDg4NWJjNmY4ZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFkMmZhMjBjODhjNDc3OTE2N2NiMWM3ZjY2MzA3MGZmMGU3NTA2ZGVkYzIyZmM2ZjEwZWViNjM3ODNlZWMzNDYifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L35-L71",
"version": "repo-lines-v1:sha256:e219e549d2e60ee59ac2efad3b4e83e8b36878ea4ffa0d5d72f2d8238b3b0091:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRhY2Q2MzRlMzM0OTk5OWMxZjJiZGE2MmM1YjE2NjljZmQ0ZjM2NmQzZmFkMmZkMzY2YTQ3ZjAyZmJhZmJkN2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0N2Y4YTRmZDhlNjlhM2FiY2ZlYzY3NWY2YjI0OThiNzJmNWFhNTEzOTllZjcyOGRhMTNmZTdiNjkxMTM5OWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY5Mzc5Yzg0N2Q1YWE4ZTg0ZjYwN2JmMGQ0NzI3YWE5YWJlYjg4NDkyNTQzZDk5NjhjOGJmOWEwNWQ2ZmNiZWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ4Y2E4ZDY0YjZmMjMzMTkyOGYyYWU4Y2E4ZDhiMTY0N2IxNjg0MmExNTQzNjBmMjQ4YjU4NmI1M2JiMTAxYzgifQ"
}
]
},
{
"id": "claim_2a5a7d3c3bd74405a46fcc9040ec50b6",
"statement": "The fixed V28 compatibility fixture is generated from the historical Persistence framework at 0dc173d4b1d190071d35bc66f80ebb767d8b950c, with a recorded expected checksum and synthetic credential references rather than stored secret bytes; it includes a host, identity/key reference, group, snippet, known host, event and existing installation ID.",
"evidence": [
{
"resource": "repo://Scripts/generate-v28-fixture.swift#L6-L69",
"version": "repo-lines-v1:sha256:5beabfbd05c3d76b1ffc0f62e6934520a3128f10d6b584a5ef7fcc3465f2b746:eyJzZWxlY3RlZExpbmVDb3VudCI6NjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY2ZmMwZjM3MzFlNjkwMGFhZmQ5ZDQ5NTczODIzZjc1NzQzM2Y3ZTc0OWY2OTQxYjNmZWU4ZDI3YzFjZDRhNGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3ZmIwOGJmYjIyNTk4ZmJiOWM0NTgyNjRmM2MxYzZiMDA2MTY4YjY5MTY2MmJjNTBhZTVjYzVlMjg2ZDU2ZmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhNDEzOTNjODU0MWVjYzQwZTdjMzZiM2Y2MmQ0YTFmMDY5MWRmOTI3NzZkM2E1YzRhYWU2OWQ4OWFhYTZhOWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
}
]
},
{
"id": "claim_1f9249c55c7d49d9a8840637ee80ca43",
"statement": "The V28-to-V30 Host replacement keeps historical `port`, `identityID`, and `charset` column names for SSH while defaulting new Telnet fields; V30 replaces the historical Known Host shape to remove its obsolete mismatch flag, and V31-to-V34 migration assigns existing connection events the stored installation ID and creates an independent device record.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L757-L800",
"version": "repo-lines-v1:sha256:7419ad512cc7f1dabbf722269e63f70e7ec279f4b06382d291feeae84737ef19:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwNTY5MjAzNmI4ODhlYmYzYjc5YjEzNWU0MDMyN2YxYTFhNzFlZjY1MWM5OTI3ZjE2MWQwNzFmN2Y5MWMzMDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI2NmIzYTEyZjYyMTVmOWFhMzI1MzQyOWZlYTU2NDgyNDZhZjc5NTk0YWI4YWMzZjRkZGI3ZGI2Y2ZiNjQxYWYifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L884-L907",
"version": "repo-lines-v1:sha256:a962ad2544bd8bafd0828c7a29b8873c1825ad48e3c9e0c545948e729258e280:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjMWIzN2U0NGUyNGYzZDQwYWMxNmI5YmM4OWFmNGI0NDhlZGE3M2U5NDcyMjljNzI0NGQ5OTQxNGYwYzM3YTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExNWY2MzcwNjFhMjIyYzZhZjU1ZTM3ODc2YTljMmMzN2RhMjJmZmJhYjBjZDcyNWE3MzgxNDRkMjUyOTE5ZTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNhZWQ3YzJkNTQ2YTEwZmI3ZDRkZjM1NWE3ODZlOGViZTRjZTJiMzgxMzZmNTI5ODVlNWVmOTAwYjgxMTBiMDEifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV29HostModels.swift#L7-L48",
"version": "repo-lines-v1:sha256:822a0928dd1f722d9b0733d7b73d2be2c33875af01d165875cdd4c941941a90d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJlNjUwOGQ1YTdmMTg4YjhiMGU0ZjhiODFhNGJiZjgzY2RjYmNjY2JlMWMzMWQ2MThiNjQzZGYxYWM3YjFmNjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjMzhlN2E1MTJhYWNkZmM1YTZjYjAzZWM4NDBmODkzZGE2YzMyYmJiZjIxNjljMDhlNDJhNjViMjQ3ZDdhYTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkYTMxMmZlMTU1NzA0MzkzMzRiYzkwMGRiNDQyOTUzNjJmMzg5ZjVjNmVkOGU0MTViODIyYzBmN2YwNDJjNDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5NDIxYWM2M2VmOGRjMzlmNDZjZmZjNzllZDFjMDQ2ZTg2MmUwMmE1NGY3MzRhYjYxYTJmMmRjZmE3YTNhODAifQ"
}
]
},
{
"id": "claim_7779716cb3614abf88c8b606f3c89825",
"statement": "The V28 fixture compatibility test copies a historical store to disk and opens the same path twice through the production container factory; on each open it checks projected Host/Identity/key and ordered environment settings, snippet and known host, connection history with original installation ID/device backfill, and default workspace preferences, rather than only checking current in-memory schema declarations.",
"evidence": [
{
"resource": "repo://FrameworkTests/PersistenceCompatibilityTests.swift#L60-L144",
"version": "repo-lines-v1:sha256:4561b141f81b56941320a35e8389bea59dc6291fc22b2e7b359b58f0ed816631:eyJzZWxlY3RlZExpbmVDb3VudCI6ODUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdkZmY4ZDRjNGJlMTRmZDZjZjc4YmQ1ZmI2N2JkNTNkNGVjZWI0MTljNjVhMzFhNWQ2OTQ3NzA2OWE2Y2ExMGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFkZjBmY2E5ODUzMjVjMDQ5ZTY0ZWE5ZmE2MTE3ZjI4NjY0YTcxNzlkMGY2NWEyNjRiNTcyOGNiMTg5NTA4MTIifQ"
},
{
"resource": "repo://Scripts/generate-v28-fixture.swift#L17-L69",
"version": "repo-lines-v1:sha256:e949a10c53afe5f53e1a7c8e28a24b912a30ffd4ad4cc1846e1b51e23048d6dd:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNjY2UxZWFiMmVkZGMwYWU3YzFmN2ZjNTk0NzM4MTc4YTQ2MzYyMGE4NzA3YWQ1ZTM3YTY4MjgxOWU5YWI3MGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3ZmIwOGJmYjIyNTk4ZmJiOWM0NTgyNjRmM2MxYzZiMDA2MTY4YjY5MTY2MmJjNTBhZTVjYzVlMjg2ZDU2ZmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ3ZDVjYzY0ZmExNzhlZjNmOTA2MTc5ODE4NjcwZjc3YmM1MzMxZjM2OWYyZDU0MmI2Y2FkZTRkNWQyMDZkMDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:5be04fadb09bbb3c62238bb4033b4d66e3eca9f81df3588da05b6edf81c17e9d",
"pageVersion": "sha256:a71d66817c91463fad3b26f544059b3945dd6e5564036981c101550db75f8c4e",
"claims": [
{
"id": "claim_3a403468456840acbfe0a524b90d5717",
@@ -12,7 +12,7 @@
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"version": "repo-file-v1:sha256:cda33d82d48452a5e1059be4ddbf0b4d924cc192e100f6cb785eeed60cd1e1f6"
}
]
},
@@ -220,7 +220,7 @@
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift",
"version": "repo-file-v1:sha256:241630ccbe213a2cc448dcf534a36eff0d093f8c529b8e34c2757a59d3d14c10"
"version": "repo-file-v1:sha256:2e33baa61dd8708d8d37adaf715a6d4caa9cf849b87a291186a927a744e9d9e0"
},
{
"resource": "repo://TFM/Platform/TerminalFontCatalog.swift",
@@ -264,7 +264,7 @@
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift",
"version": "repo-file-v1:sha256:241630ccbe213a2cc448dcf534a36eff0d093f8c529b8e34c2757a59d3d14c10"
"version": "repo-file-v1:sha256:2e33baa61dd8708d8d37adaf715a6d4caa9cf849b87a291186a927a744e9d9e0"
},
{
"resource": "repo://TFM/Features/Settings/TerminalCustomConfigurationEditorSheet.swift",
@@ -595,10 +595,124 @@
"version": "repo-file-v1:sha256:b7bdc9c7e0f80d81f6610283c947786cfc0f0d13dc06ddd683a4240e1236b38a"
}
]
},
{
"id": "claim_cdde9c6b33f04ce081c8cfdb01423a94",
"statement": "Shared AppStrings owns on-demand localized presentation resources for both apps; SwiftUI's swiftUIKey bridge preserves interpolation metadata, while AppLocalization resolves resources for native copy against a requested locale and app-bundle localization. Architecture tests reject app-local AppStrings declarations and presentation-copy tests cover English and two Chinese scripts.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/AppLanguage.swift#L3-L38",
"version": "repo-lines-v1:sha256:4c50b6fcfb4d1d025125ee2174892c77b178cab2241ff27229f2563474bbb6e4:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwZTE4NTRiZjA4NjFkOWY2MDlmMzQ3YTE0NzE1ZmM1ZjE4NTRjYTI2NjBhYzhhYzY1ZDk1YTFjOWE1ZGFhY2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZjMzFjOTc5OTU1OTg3NjNkODgzOWYyNjM3YjhiMGEwYTFkNzEzNjlhMGM2YmI0ZTczNTE3NGM0YjQ2OGU4YmIifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/Strings/AppStrings.swift#L1-L6",
"version": "repo-lines-v1:sha256:fc75544a0cec27d904ec80a42dc9c6dde7922c9e73b2e1d3d66401e16002c5e1:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRhOWI3NWY2NGIxMDZlYjU0NGRlMjAxZjU5OTEyMmQ3NWFiYzQ4M2M1YjE1NmJiYTZjMDVjMGY5NTZkYmMzYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOTQzOTNjNmIxNDE5MzcxNzhiY2QzOGZmOGMzYzllMDIwYzJhN2MwN2ExOTk1M2QyZmQ5NTQyZDBkNjFhNDczZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjAsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSJ9"
},
{
"resource": "repo://Frameworks/TermindPresentation/Strings/LocalizedStringResource%2BPresentation.swift#L1-L9",
"version": "repo-lines-v1:sha256:544eaa4a367c1eea144d39cc11339da9d578689777ef65032c516c6282fcaef5:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRhOWI3NWY2NGIxMDZlYjU0NGRlMjAxZjU5OTEyMmQ3NWFiYzQ4M2M1YjE1NmJiYTZjMDVjMGY5NTZkYmMzYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjAsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSJ9"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L191-L203",
"version": "repo-lines-v1:sha256:d17c13b78d253be7e4a7cb7af1c9ac96dfac710b133d086ed60e517a79104614:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM5YjJkYjM3YThjY2FiMDIzMTkyOGUwZGY0MzcxOTc3ZWQzYzQwNzBkYTlkMDUwMjEzMzQyYmMwMmQyOGE0YWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3ZGE0ZTRmODRkMjdmYjAxMTA1N2E3YjdmMzE0ODI3NmQyOWUyOTUyNDU3ZWE4ZTYyMmUzMmU4MWU4NTVlYmMifQ"
},
{
"resource": "repo://TFMTests/PresentationCopyTests.swift#L10-L32",
"version": "repo-lines-v1:sha256:ea7d9fad83978ad1d910dc1acff92f3c253474a1c520c9f11100ae935a2be644:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyYmI2ZDU3ODMxMmY2MmZkZDc5Yzg4N2EwY2M2ZWQwNGNkOTA5NDBmMWFhYTdlOWE1MDIwZWY2OTI5MWE5NTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjZDFhN2Y5NGM0MDdkZDNlMzFjZmI2YTc5ZGZkNDMwZDMxNTcyMjkyNWJkNzNjZTA0YzRiMWYyMDgxMDQ2N2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk0OTFlMWY1ZjkzYTU5OTJlZGExM2IzNzJkZTcxYTJiOGFmNTVjMjAyNjE3MGI0NzA3NzJlZjcyYTA2ZjQwYmIifQ"
},
{
"resource": "repo://TFMTests/PresentationCopyTests.swift#L153-L179",
"version": "repo-lines-v1:sha256:c99e1ac8888258a65ce6ed7b442f83bff9cd4e9b26f826a3993c2d12d48700ca:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0M2Q0ZjYwMWU4ZTJmZTYwNTExYTIxYWY5MGVkNWM0MzYzOTVhMjlhMTE2YWY0MjljNDE5Njc1NDQ5YTc0ODYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgzZWI4ODU5ODRkZGRiM2Y1ZDgxYzM3M2I4OTkxYjk3ZTViYzc5YWZkYmIzODk4NGJjMGU5MWQ2ZTkxZjZjOWYifQ"
}
]
},
{
"id": "claim_dad7ecbd0a284649add65208cadbab04",
"statement": "The desktop Settings index offers App, Terminal, Connections, AI and Sync category routes (Developer only in DEBUG); Logging is a separate optional debug entry, and Pro opens the paywall without adding a Settings category.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L10-L56",
"version": "repo-lines-v1:sha256:28db360a8f3c137ca8b3054cfb7f37c727e9ce728db127f5fa0b920261a46070:eyJzZWxlY3RlZExpbmVDb3VudCI6NDcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRlYmQzMzZiY2VhYzhiNzBlNGRkMTliN2IzM2I4YTE2MDcyNTQyZWNjYzJlNWExYmExZDY0YjI3ZTIwN2I2OWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkYTMxMmZlMTU1NzA0MzkzMzRiYzkwMGRiNDQyOTUzNjJmMzg5ZjVjNmVkOGU0MTViODIyYzBmN2YwNDJjNDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE2ZTljNzViZGUzNTExNzAzZTZlZjFlMGI0NjdkNWU3N2M3M2E0MDk4OTY1MjJlMTlmMjVkZjVkYzFlZjBlOWQifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L110-L191",
"version": "repo-lines-v1:sha256:5e995aae0948f3bcdd85b73bb5c9d0e7d3c68903ee26517a04299e57e5d8c0d9:eyJzZWxlY3RlZExpbmVDb3VudCI6ODIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzZTZlMjQ4MzhhNTIxMzQxNzA1OTIxOGEwN2UzNWUyZjFjNmNkZTk0Mjg3NDZhZGNlOWVhNmI4ZTFmN2Y2M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUxMjU4NGZjOWZmMTNkNWY1YThkMTQ3MTU3ZTViNjY2YzE1NDU1ZWFmZjM4MGMxNzFiYzI1YTFjYTA5YjUxYjAifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L233-L280",
"version": "repo-lines-v1:sha256:17607864f1eee2ff2a8d338ad5d137ba3f5ae89479a98598eed75645c434304d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk3MTY2MzVlOGIyNjUzNWNmNTNiOTk2OTgwOGExYzUxYmM2MjYxOTdkZTc3OWFmM2E2YWUwYTIxNTM5ODE5NjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1NWUzNDQwZWZmODhjNGJiYTg5MGEyNzcwZTIxYzE4MmVhNzEzNGUzMWY5MDE3OGI5YTI1YTU2YTFlZWQ2YmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYwNWEyY2MyNzYzYTAxNjE2NmRlNTIxYjAxZjZkY2E1ZjFiODkzYjQ1MmU4Yjc0NjY5ZGUwMjI1M2U0NzczNDAifQ"
},
{
"resource": "repo://TFMTests/SettingsNavigationTests.swift#L13-L39",
"version": "repo-lines-v1:sha256:5e8d5d8072d9e3b193c109cefc3181af663bcdabc690b5beaf89c31739e6ee3f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI3Y2U4MGEzNzE4MWIyZDA2NjBmNjE4NmRhZGE4OWUzMWI4YmY0MTgxNTljZmRkODkxOGEyNTA3MGQ4Yjg5ZmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NTJjOTcxMTBhMDM1ZjNkYjQ2MWIzM2VjZmQ1MzAwNzk5ODMxZWJlYjdlMmEzOThkMzJiY2ZmNTJlYjFlNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVhOGQzYTYyYTA4ZTliNGYxOTAzNTEyNzYyOThiMDg3ZTU5YWRjZmYyOWY0ZTkyNDBmMTczMTUxZjBjZmZjN2YifQ"
}
]
},
{
"id": "claim_302551bca7084b0d8c7e5cd15a47a2c4",
"statement": "Desktop SettingsRoute defines a parent hierarchy: category and Logging lead to index, AI detail routes lead to AI except provider models which lead back to the provider, and terminal configuration leads to Terminal. Toolbar Back walks this hierarchy and then restores the window destination; if the displaced workspace no longer exists, it falls back to Vault.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L58-L91",
"version": "repo-lines-v1:sha256:dabf8ad89481961f99d67b77951ffa94c484b04a1cda63111875e59987946dfd:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFhYzNlYjg3YzY0MDcxYmQ1ZWE4MjIzMDNmODg3OWEzMzljZDA4NTVkMGUyNDA0NDk1YWIzNmY1NmRkMWE4MjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwZTNiMDdhZmRiOTQ5MzMwZmQzYmFlYWE2YWE1Njc2ZTQxYmQwOGQzOGQ4OGRmNDljYTkyYzRmMTJlMjljNTgifQ"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L584-L620",
"version": "repo-lines-v1:sha256:09ee17ae6dec430f48790f3ffc1eb6e268c2beae85238bd679a3e6d1a23b2718:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ3N2U2ZGVlZjczYTA3ZTg4ZmQxZTk2ZDA3ODU0ZGZjYjI2Y2MzMjM2OWU3OTg0YmEwNjc5ODY4MGQyMzM0NjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzOGRhMDk0NzRiODU3ODdiN2ZiYzJlYjFmNDUzZjdlMGE4ZDMyYWVhNTFkYTZhYmU5YWY2YzI4M2IyZWQ2MWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MmU3MDJiOGI2MTYxNmJjNTI0MGY2N2VkNWM2NGIwMDgyMjdhZDJkZDhiOGUwMzcxYjI0YzRlYmUxNzgwYzYifQ"
},
{
"resource": "repo://TFM/UI/Components/WindowToolbar.swift#L637-L644",
"version": "repo-lines-v1:sha256:0be7f9d5156feebab19ead62158eb38bd060556000b71940e6cf09df511d7aba:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTYxZTk2OTYyYzRlYjljMDljZGJhNTBiZGMxMDg3MzhkODU0ZWUzNmJiZjZjMzBmMDE1OTRkZDMyMjhhYjI2MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjljYjJhNDM0NDI4YmI3ZTg4ZmY0NzIwODc2OGJmNDc3YjdiMmI2ZTExNDg3ZDA0ZWMyZDE5Y2Q4OTNkNGRlYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTdlYjdlNzcxMzMyMTA5ZGQyMzlkOWUwZTg2MDA2ZTIyZWJiNjdiYjY0MzJhNmU0M2Q0OTYzODYwMGJhNmI4YyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiODNjN2MzMzQyNjU4OGNiN2M4YzkwZWE5M2Y1NGZmNGViNGFkODk4NTVhMzIzMDgwMzdkYjQwODVhYzcyOWNiYiJ9"
},
{
"resource": "repo://TFMTests/SettingsNavigationTests.swift#L76-L150",
"version": "repo-lines-v1:sha256:2105d76124e619c6ca5caa583e18093b5073eaf984215d9623fe9e53eb71e6b1:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNjYWMwYTgxNGYxNDlmMGViYjc1NWRhZGQ0MjdlN2FkMDU1Y2E4ZDc3NzJmMzkxMjE2NzM1ZDA1ZTY2ODM4MTQifQ"
}
]
},
{
"id": "claim_ff3a079017fb4a2ebde8336217c51117",
"statement": "On desktop SettingsPageView handles route-change and disappearance cleanup of provisional AI drafts: empty unconfigured providers are discarded outside provider/model-list transitions, new MCP servers require a valid draft and lockable namespace, while a skill with written content is retained as a draft. This policy remains in the app-owned Settings route rather than shared form fragments.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L198-L230",
"version": "repo-lines-v1:sha256:c452b24bac854e836d8336333344cc3b53143555cfca728802125619d8755309:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiNmE0N2NjYzUyMzA3NTRiYzM5M2QxNTBhZTJmMWUyZTA1ODcyNDNmMDYwNTJkMjdlNDVhZGQwZTI2ZThkMzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY5Y2EzNjgxODVkZGMxMmUyZmNhZDdmNjEwYjVkYTkzMzhhOTg0NzBlZmM2ODJlOWI1MDkwNDM2NGFhM2EzZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIxMzJkOTY2ZWQ0MWIwOWU4ODE4ODkwNGFmZGFmNTQ0NGFiOWQ1ZjUxMDRiZDhmYWUxZmVmYTIzOTQ3NDhjNWUifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L328-L350",
"version": "repo-lines-v1:sha256:a3a2a4c940bbff434561cf2acab4878edfc677414148da377551e33ba164a5a3:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg2ODMwN2I0ODJlNzM2N2YyMTczZGI5OGNhNzcxOTZmMmQyNzNlZDFlMTY2Zjc4MGE4MzU3Y2I2ZjQwOTg1YTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNmODAyYWRhYjBhYzQ3NjAxOWI4NDMyMWNkMTdmMDFjN2UyYWYwN2E1ODc3MjUwNTc2NTk0YTQ0ZmMyZGEyMTcifQ"
},
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L93-L108",
"version": "repo-lines-v1:sha256:db0cdc606501db2f512721e050b7e0b4991b51c176cbeb289e952653a3a8a600:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ1NzM5OGMwZjAzNzM4YjI2YWE2YzA1NzMyYTE3YzJjMzBiMGI0NzhhMWZjZDc1MDkyODcwOWM4YzJiOTdmZDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNlMmU0OTU1MTE1NmQ2ZGVhMDY4YTgwZjUxODI4ZmM3ZjRlMGI1YTdiNjMxMDIyODhiYmM1ZGIzNGVhNDZlYjkifQ"
},
{
"resource": "repo://TFMTests/SettingsNavigationTests.swift#L152-L194",
"version": "repo-lines-v1:sha256:cbb422dd0e61a3be95809d7cd0d05336b2f1ddc6e1bb447546a9829b25f6be91:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjZTZmYmI1NjcyMTYxMGY0Mzg1ZWM0NTM3MGJkZDgxMTEwNGY3MDUzNjY5ODAyNWUxODkwOWQzODQ0YjA2YWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAyMzA1OWJiYjhjZDJlNmY0MGRkZjM0YjhlYzc1M2U2Yzk5NzgxY2M3MWNkMmZmYTM3ZGU1MDE0NjY4MTVhNGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI0MGU2YmE0YmYwOWUxMDA5YzU3OGFkOWM0OTEwYTlkZGM1YjllYzcxOGEwMTQzZjU3NzY1ZTExOWMyOWIwMWIifQ"
}
]
},
{
"id": "claim_448e7889c68c4c11be889d4797c9523e",
"statement": "Mobile Settings uses a registered scene-owned tab with its own NavigationStack and native category NavigationLinks; the mobile paywall is a sheet controlled by app pro state rather than a desktop SettingsRoute destination.",
"evidence": [
{
"resource": "repo://TFI/App/MobileFeatureRegistry.swift#L109-L119",
"version": "repo-lines-v1:sha256:a26f9a733a3316c512801ee8f189a1b77e1677e5f0a4c109c7fd11a733388808:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA4OGViYjNlYTg3MjEyM2Y1YzgwNzlkMzgwNDVjNzg0ZGNmMmE5ODFkNGYyY2JjODg3Y2Q4YWJjYjYwMTcyOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNlZDg1NWMzNzBlMzk4NjAyN2Q2MmRhMjk1YTc5YmYyNDQyOWUzNjNiYTgxNTYyMGI3YzE3M2FhMWQ1MTYxZTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
},
{
"resource": "repo://TFI/App/MobileRootView.swift#L28-L48",
"version": "repo-lines-v1:sha256:30a351e3c0abf226e061ade5201d2297b365ff5604773f29391b734e5dbed5a0:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ0ZDhiNmFhZTdkZTg4YjQ5MzJhMjFhNWVmMTMzMmFiYTEyZmNhYTA2NWM3OWQ1OTJkYjczY2JhNTU4MGNkMGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZmYWNkMjQzYjA4NDgxYmFiYjc1ZjYyODJiNTZkNTNmMWUwMTY1NDAyMTQ0NTMyZWUwOTgwMDBkZWI2NDVlNGMifQ"
},
{
"resource": "repo://TFI/Features/Settings/MobileSettingsView.swift#L10-L64",
"version": "repo-lines-v1:sha256:f0bf636962deca627602edf644d1d8dd8ad83022fac111640908c45a7f6f8666:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM5ZjliMzlkOGVhZjY1OGY2NGVhMDdlNjhkYjU4M2Y3ZmQ2Y2YzYzcxMTJkOTEzZmI4YTIxODcxZDIzMTg5ZjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-23T17:44:09.687Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:c5bc5f9ca5aec9baf7cef84a0e408483976858073900fb97ece8c7c68129cfdb",
"pageVersion": "sha256:f65ef3bece82ac4bd0a4c9c9d91292ac8e315454fa3fe24bf01b7a39f1209c54",
"claims": [
{
"id": "claim_b47979774aa94e7dae517a6894c508d4",
@@ -136,7 +136,7 @@
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift",
"version": "repo-file-v1:sha256:81652bfa7ed8a9fcce7ddb2e714c8b13bdb94006619b036a5e614ff613088433"
"version": "repo-file-v1:sha256:0af4f94727be60dd95c0e63c2f30f3a6be0412c60376c5b293c55b1984902e23"
}
]
},
@@ -325,10 +325,66 @@
"version": "repo-lines-v1:sha256:7e49cb710fe6531fd703953ff8e825394d457513e3338f6f31ef36dc2d21c462:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyODgwNTA4Y2FkZTAwMmU3ZWE3Y2MxZGNkMmEzZjgxNTJkMWViMDlkMTU4MmU1ZmFiNjc0YzY5NzkyZDk3NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZmYTk0OWU0N2NlZTA3MjhmODU0YWI1YjAwNDFkMDc3OWM0NjQ4NzEwOWMwNzM3ZTE5OTRhYmIzMzMxMzAxNmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZkZDgxODQxYzE0YTcxYzljODI3ZmQ0NjRhZjU2MTYxMDVlYTBhZGVmZjVjZjZjM2E4NDc5YjE1MmI3Y2FhMGUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5MzU3YjJhYjcyNTNjYzgzZjIxNTAxMzlhZTI2NmU0NTZiNjMzMjA2YjJjYWFlNjlkOWY5ODYyNmFlNjkxYjkifQ"
}
]
},
{
"id": "claim_0241af0eba824e84bd339abd23a4ab87",
"statement": "Both transfer-ticket tools use the MCP executor to validate a configured host and create a waiting capability without opening SSH, SFTP, local files, or the remote source; actual remote I/O begins only when the separate HTTP byte route claims the ticket.",
"evidence": [
{
"resource": "repo://TFM/Application/MCPServer/MCPDownloadCoordinator.swift#L91-L109",
"version": "repo-lines-v1:sha256:c3433e38f2b31aa5d84e8752723b10775b6a64e8303a3f0b2d7e97d66978c0d8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc4NDhhMmM0NmViMzA3MWJlZGJkYmNjY2VhNmMwMGYzNzk2YjkwOTBhMjZlMjc0MTRkYTBhYjI5MTk0M2I0MTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjEwNzA5YjAxNWIyZjcyNTQxMzVhZGI1MDQ3OTExMGE0MDBiYjMxNGZiZWNiOTJmZThiNDJiMGViYzdhNmE3ZTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiMmIxMTc3ZGMzZjUyNDJhZGJlY2IxMWI2MGI5ZjY2NDEyMWRhZWIxMTQxMmM3ZmRmNjkxN2Q5YTNmNDQxODIifQ"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L38-L81",
"version": "repo-lines-v1:sha256:e9fca4d423496dccbac76c863f3c0e5b5160ecea10e354b1d3303a0b40f421a2:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ4MjYyY2I4OTdmZGU1NjJkZTUzYzg1NzhhYmY3YmNhYWY3ZDUyYjkxZjM2ZmFjZjY2OTc3MzdhMTM0MjY5MzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNmMjBmOGQxYjQzMTkzYmQ1ZDE1NDIzMDkyODRlYTc5MmM4ODVhZmEwODI3MDUwNDkyOGE5NTU0MDQ2ZjkzNGMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkMjZmOTBjMWRkOTRmMGJlNDRlN2QyNjZhZGJhNmIzMGNkYmYwNTg0NzVhMGI0MWZkMDU2OGJlZTcwNmQ1ZTUifQ"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift#L94-L117",
"version": "repo-lines-v1:sha256:a78aa22397d37536cd99f0191544af6588a764be64e93005edec08e8089ec45d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUwNWVhMzNmMDU2MDExZDBlMjkyMzhhN2EyNDhhM2JhYjZiNTkzNDA5ZjA5YWM0ODc0ZWYyMWU5MDY3MzFmYzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyNzZjMWQxZjk3ODVlNTU2MGQwYmI1Zjc5YzJlOTc5OTk3YjcwY2RlZDFmM2I2OGVlYjBjZDE5MTBhZTIyN2EiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjEwNzA5YjAxNWIyZjcyNTQxMzVhZGI1MDQ3OTExMGE0MDBiYjMxNGZiZWNiOTJmZThiNDJiMGViYzdhNmE3ZTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU5YTRhOGYyMzE0N2JkYmQ3MjhkNjIxMmUwNDk2NmVhOWNhMzJlZjk5ZmM2MjA2MjIwYzc4ZTgzN2E0MmQyMjIifQ"
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift#L19-L97",
"version": "repo-lines-v1:sha256:247193706f98b629f5f10d2c41bded0e359f00c7d23791fb6ea175dc61a510e8:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhMjczMjdhYTBhZWQxZjcyNmEzMmNjNjM0OGRkNjYzNjkxNjM4OGU3OTZiM2M3YmNmNDdkNWZhNTE2OTBjZGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ1MTEyNGM0ZTYwZWVkMjRiODk4YmNlNjk4NjMyOTRlNjJjZTliYTg0NDMxYmJhYTIzMTYzZjY4NWJjMzgzNWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmY2IzZGJlMDQ2NjZkNGFjNmNkOTEwODMzZGJhZmZmNGU0NThhZGYyYjlmNWQ4Njg1MmNmOTc3MTM3NDNkNDIifQ"
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift#L315-L337",
"version": "repo-lines-v1:sha256:24a629d87f57f464fa7415a8e251e55045fce548eda82519d75629465d3c7e58:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYzFmMTg4ZjE0MmVkN2E4MjQ2ODBiMjA3MTcyYzU1MTliYzYxNGE0OGZkYTdjZjE2N2VkYjhkZGY3OTk1NmMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA2YTNlYjNjMDM4NzBjZjE0OTI5OTc4YTE3YTRjMWQ5MmU0YWZmOWUwM2ZiYmEwMmU2MTI2ZTg0OThhZTRjMDQifQ"
}
]
},
{
"id": "claim_c1f6943d9e924ef48d9a2fc77fc1873e",
"statement": "Transfer status is authorized against the creating MCP run and a still-registered client, not possession of a ticket ID; ending the session removes that run's transfer tickets and makes their status unavailable.",
"evidence": [
{
"resource": "repo://TFM/Application/MCPServer/MCPDownloadCoordinator.swift#L111-L117",
"version": "repo-lines-v1:sha256:e804a54026e840d280fd7a9df5c5dcca9be27641cf23845146a8ef0d6e8da5ad:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTJkZjA1NGVmYzVhOWY4MWQxZWFlNzhlZjk5Y2M1ODYyNDVjMjY3NTA4ZGJjODY0NjU2N2ZmZmRmNTJkZGI1ZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzcxYmFhMjBiMTUwNzE0MzllNWQxMDE4MTc3NmIxMjljZGU2N2ZlOTM2ZjY5NDU2OTQ4NGRmMmI4ODJlYWMwMyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiY2JhYjAzNjBhMTRlZDVjMDQ5N2U5MGQyNzgzMzg0Mjg3NTY4ZTExMzc0YTFjYjc0Y2Q4NzY0ZGE3OTA3ZWIzZSJ9"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPDownloadCoordinator.swift#L349-L357",
"version": "repo-lines-v1:sha256:bd553cc5a9eb6468ee6dcbfc3048d1f19f8ba8013b2f6b5d0757a2a89936c47c:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODk5NmMwZGRjMGE5N2JjMDU0MDc4ZTkwZTY4N2E4ZjIzMDNiNjUyMDI4NmRjODdlNmRhNDA2ZTIzZTYyMmVhZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZDNjNjgzMWE3MjZhMjg3YThjNjNjMWZmNWU3NWEyNTZiMjY0ODRhODQyYzhkMjBhMTBkZGZlYjJiZmZkMzYwMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiY2U5NDhlYWZhZDQ5Mjk4NzYyOGNlYTk0NGQzZjRmNTlhYzk0MjhkNDc2ZWE3Zjg2ZTMwMWQ5ZjFkOWY1NmFhMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYzM0MTkxMGI1MGYzMTc5NzdhZmJkNzM4NTgxZWYyNDg1YTIxMmNmM2M0ZTRjNzI5NTdjMWI1YzA5ZjYyMmZjNiJ9"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift#L120-L126",
"version": "repo-lines-v1:sha256:3637d24d179f09f662a42a7d9962a94f5bf8d3820324cf7d112379ef862674f9:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTJkZjA1NGVmYzVhOWY4MWQxZWFlNzhlZjk5Y2M1ODYyNDVjMjY3NTA4ZGJjODY0NjU2N2ZmZmRmNTJkZGI1ZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzcxYmFhMjBiMTUwNzE0MzllNWQxMDE4MTc3NmIxMjljZGU2N2ZlOTM2ZjY5NDU2OTQ4NGRmMmI4ODJlYWMwMyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYTk4OGU1MDBiNTZhMWFlNDhiZjFjN2MyMTYzMDM1MmY0OWM2YzhmYzllZTg1NjRjOWViNzNjZWVmNWQ5MWExMyJ9"
},
{
"resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift#L206-L215",
"version": "repo-lines-v1:sha256:521e80eaa0c1a9b90c0c4a4dce2a491a38ed37adc74c6883448388da1fdaa78c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg5OTZjMGRkYzBhOTdiYzA1NDA3OGU5MGU2ODdhOGYyMzAzYjY1MjAyODZkYzg3ZTZkYTQwNmUyM2U2MjJlYWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQzYzY4MzFhNzI2YTI4N2E4YzYzYzFmZjVlNzVhMjU2YjI2NDg0YTg0MmM4ZDIwYTEwZGRmZWIyYmZmZDM2MDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUyMDI5MDNkNGQ2YzVhYTcyNDAyMjM3YzAwMzQ0NjZmNmJlNWYxMmJiN2MzMzQ5MTc4YzNjZmY1NDhlYzFjNWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZkNmMyNmM5ZDExMmUwOWFiZTBlN2NhZWE0MGVkZmMxYmUxZjQxMWMyMTNmOWY2YjFkYTA5YzRlYmZlOTZkN2UifQ"
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift#L39-L56",
"version": "repo-lines-v1:sha256:474aa4d028a8445127cb3f63d6614ffecd6eaaf87c3d8b446bd3daa3831d8c31:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQyNGZiNzQ5MzYwYjE0ODIzMWIyMTBhNzlmNDMwODNhNTkzNDI2NjljOWUyY2Q4YWJkODRlOTdhMmUyYTU1YzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhZDdhMTM5NDI3Nzk2YmNlZTljNzUxMGYwZGVlOTQ3NWNhZmZiMWNjZjRmNzhjYWM0ZmUwMTllY2Q3MTJjZGUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
},
{
"resource": "repo://TFMTests/MCPServerToolsTests.swift#L82-L96",
"version": "repo-lines-v1:sha256:9c6e53696f588c039fffd8afb0f21f7172fbba39c72aeaa272a77bd04bc396dd:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQyNGZiNzQ5MzYwYjE0ODIzMWIyMTBhNzlmNDMwODNhNTkzNDI2NjljOWUyY2Q4YWJkODRlOTdhMmUyYTU1YzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0OTI0MTU5YjFhMWU2ZmQ1NTg1YmVlNjY3ODVlMDRjZWNhZmE4YWY4MGNhZGM1MThiMjNiMTY4OWFkNDlmZjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-23T14:32:50.942Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:7391dbb4e86cdf0b4e24c3d6d8731bdb1e5ee8e00f512f8352c88041084935f1",
"pageVersion": "sha256:a29579912ea05cbc2cd3810d36bc482b362019aafdc135813b9d3144ab428e4d",
"claims": [
{
"id": "claim_d34d7b16495a44a4a946d3dc9e0456f4",
@@ -64,7 +64,7 @@
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L11",
"version": "repo-lines-v1:sha256:b8b2903d1009b119d2daa9cc5915fe34eab19cf61490b33adc02693393f4c95f:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
"version": "repo-lines-v1:sha256:647fdf978ecd85719df899c592ebd2386dcf8c24b7371545e9ab0dcf3e0402df:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
},
@@ -289,10 +289,108 @@
"version": "repo-lines-v1:sha256:0b6cb21f0f1757fb3cb296d655faedee32d0eaa595497a26b5baf658ab80d29e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTU1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0Y2YwOWViMGM1NzQ0ZmI5NzMzMWI5OGZmM2ZiZjA1YTYwMmJhM2Y3ZjY3ZTVkYTViZTkwOTUwMzNmNjI1ODI1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI0NDFjM2NhNDkxMWNhYWY3OWU3YTE2OTM5ZDY3ZDg5OTY2YTg0N2ZkMDc3ZTRhZDU5ZjM0MTk3ZWFhY2QwOWY5IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI3YTM1NmNjMGQwZDg1YzZlMGE3N2M0MGU5NDIyNWQ2N2QwNmM2MDhlNmQwZmI5MjI2OGFkNWM2OTA4ZGRkMGY5In0"
}
]
},
{
"id": "claim_8b23a3b66bdb44b9a0cba917ad94a10b",
"statement": "In Debug XCTest runs the macOS app host detects the test configuration and suppresses automatic main and external-auth window launch unless visible-window opt-in is set or a screenshot demo is active; test-mode scene restoration is disabled, so gating individual tests alone is not relied on to prevent app-host windows.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L14-L33",
"version": "repo-lines-v1:sha256:25a8c6dff46ec83a0b40c47dd446a1d70c15967cf565eb5ac2ccc23b9210ea1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhMmRiNjZmNGE1MzI1NzVkYzUwZmJjOTFjZjRiY2E4YjE1ZDdlOGQyYmU5ZjVjYzE4ZTA2NjI2NTljMGE1ZjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwNGE1NDQyNzMwZjkzNjk5ZjI1YzU0MTNiZDc0NTViMzZiYWNiYzNkMmVmZTU3MDA0MmFmMTdhNDU5OTUwNDMifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L196-L230",
"version": "repo-lines-v1:sha256:78f019aebda1d52b1314cea5b2016d0de3654df1128d7a353152df4c4b1901e4:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwNTgzMDJjZDFmMDQ4ZTE3MzU1MTUxODA0NzRjYmI4M2YwZjhkZDNmN2I3ZjUyODI4ZDU1ZmUxYjg1MmIxOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjZDE3ODg3ZDhiOWFjYjJlZjc4ZGRkZmJiNTJkMWEzM2UwZWI2MDRlMmU1NDczMjI5OGZhNmUyMjgyMjc3N2YiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ0MTA0N2ZkYjNiOWIzMTYwZTU0NWEwOThlOGJhY2E1ODA1YTJlZmFjNGI3YWRkNmYxM2IyNDg4NWJjNmY4ZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM3OTYxNjQyMmZhZGE5MzNmYjVmNjE4MmEwMTZkOWQyY2QzZmUzNzA5YTc5NDZkNTY2ZGVhZjQyYmMyZGQwMmQifQ"
}
]
},
{
"id": "claim_dd11225a36704e1da07b1a76f4472da3",
"statement": "Presentation copy for either app is defined as shared `LocalizedStringResource` through `TermindPresentation/Strings` and cataloged in the shared app resources, while generated catalog Swift symbols are disabled in favor of the `AppStrings` API.",
"evidence": [
{
"resource": "repo://AGENTS.md#L48-L69",
"version": "repo-lines-v1:sha256:26697577d9457afd4d5953ff5464ff3ce8419e303deb7f51ea1d9644abdfc2ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdlYjZlZDYzN2JlNjgzYzc2MTJmNjc3ZWE5ZTFhNTZiOTY1OTllNzcyZjZkNzY5MGI0MjM3NDBjZDE0YWZmZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg0NTE4ZWQ0MjVmYWVjYTU4MTRhMWMxMDE1NGYxMzI4MThlYjNlYzBiNmU4Mzk4ZGY0OTRiOGFkZjdjM2EyNDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4NmYwZmMyNmM4NWViY2IwODgwNDgxN2JiMGQzZGJkN2EwOWE2MWE1N2RhOWEwNTk3YWFjOWU3NWQwZDc0OTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlZGM0MzMyOThhZDU4MTI5ZWUwYTg4NTJjMTNmNTI5MjBkYWFmOTRhOGM2NGE0ODcxZWVlZjQ2ZTEzMTVlZDIifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/Strings/AppStrings.swift#L1-L6",
"version": "repo-lines-v1:sha256:fc75544a0cec27d904ec80a42dc9c6dde7922c9e73b2e1d3d66401e16002c5e1:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRhOWI3NWY2NGIxMDZlYjU0NGRlMjAxZjU5OTEyMmQ3NWFiYzQ4M2M1YjE1NmJiYTZjMDVjMGY5NTZkYmMzYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOTQzOTNjNmIxNDE5MzcxNzhiY2QzOGZmOGMzYzllMDIwYzJhN2MwN2ExOTk1M2QyZmQ5NTQyZDBkNjFhNDczZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjAsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSJ9"
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj#L2390-L2400",
"version": "repo-lines-v1:sha256:a5e12a77a7764bfcbd2896f54217211f096a94bc1df7541e2f1159eecdaabde6:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJiNGY1ODNhODRkZDg3NDc4YTRlNmIxY2JhM2I0NjUyZDlhNjI5NjVmNTJhYWQ5M2I3MDJkZTU1YjlmY2Y2OWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFkNDQ2NDFiZDU3YzRmZjlkZjE2NjExN2I0YjMwZmZkMjM2OWU0MjYzMmJlNzU1NjhlNTc2MmZhMjUzMDQ2MWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJlNzdiMjEzMTgzZTI4YWFhMDQ1ODg2NjI4OTg3MmIzMjYwZDgyZjU4YWZlZDYxODY2NDFlM2I0MzY0NjdmYjkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI2YjJlMTUzMzgyM2IyMmIzODkyNTcyZGEyZDMwZDMzNjhhZDY2Y2I1OWQ2OGMyODAzY2EyNzA5NmE0N2NhZDQifQ"
}
]
},
{
"id": "claim_d3289095cb654c0898ea8404efd74e27",
"statement": "The two shared app string catalogs are maintained with manual extraction state; the normalizer's write mode preserves translations while applying Xcode-compatible formatting, and its check mode rejects drift and duplicate JSON keys. A target's stale extraction flag alone does not justify deleting a shared entry.",
"evidence": [
{
"resource": "repo://AGENTS.md#L56-L65",
"version": "repo-lines-v1:sha256:1eb06590617aef1c63c9d660962cf3826015a58f9ead873d23de2e1462f121ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzNDU2ZDI2MjFhMzNhNWJmYTZiYzUwM2FmOWEyN2M3ZDJjZjE1NWFlMTFlMjlhYmQ5YmMyMjE1M2ViYmQ2NDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI3MjcyZTU1ZWI5NmY2YmE2ZDUyNWRjNmI1YzM2YTJlNzFkYmQyNmExYzJmMzE4NGE5NGQ3MWJmOTA5YWQxNzUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIzMWQ4ZWFiOTUwMzE4YTFjOWM4ZTkyMDNlOTNjMWRhYWM3YmEzMzFjNDUzNzg1MDc1MDcwOTU0ZmQwMmM1YTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU2NGU1MDBlMWExMTM0YTIyOTU5ODNmNTRjNDJjYmYyNWY2NWQ5ZjAwMWFjMzlmNTliNTI3MDQ5NjdkOWMzOWMifQ"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L1-L6",
"version": "repo-lines-v1:sha256:a4f7e4e8cd45a6a2e257248bc9cef3775d26f29a5f556dc4f80c9f52b74cddea:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDY4MmNiZGI0YzhiMDc1MThiZjQ4NmM1ODk5MGZjMzkxNzgzYWEyMGE5MTZiZmIyN2FkMjExZWIxZDVjMzY0MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOWVlYjY0YTVlNDE3MWJjNjIxOGQxYzVhMjRjOTYwYWY3YzUyOGYyYjBmMzU3NWFjNmFjN2VlYzE5M2ViNzM2MyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWFhZjc2MzdjYjZlN2U1ZGI4NWQ2MzQyNzQ2MDE0ZGYwNDFjY2Q1NThhOTIwYjI5ZWI2YWM3MTlkN2JhZjVjMiJ9"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L27-L32",
"version": "repo-lines-v1:sha256:d1d0362149f97c2befc73dc7843234f12a50ffe10927986dabcb9e3139658162:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNzMxODk1MmU2NzhkYjUwNTY2MTViYTZlNDYxMWZkMWU1NzMyMjYwNzA4YjRmOTVjY2I1ZDhmNTNjZWUzZDg5MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNzU4OWI5ODNjZWU2MDMxYjBlNTZiMjA1YmUzOWYwNDJkMWE2ZDZjN2I2NWQ4ZDg5NzBmYzMwYjhkZWYxNjEzMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTk4YjA2M2Q5YjQ3ZTY1Mzc5NjI1NTcyY2NlMTk3NjY5ZDU3NjdlMTJjMThiZTA3NTY1MmI4Y2Q5ODFjZThkNSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZDcyMjMxMDZmZDg3NDJiNzBlYTIzM2Y5ZGMzNTlmNGIwMmJiYjA2OWI3MjgzZWVmNzYyNDk5NTE2YmQ3YjljOCJ9"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L75-L80",
"version": "repo-lines-v1:sha256:6c71ea7347ff9717c89060d589415e0ed157060322ff0439a96fa684359794ff:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDk3MzhkYzIzYzYwZjQ0NmMxNGQ3MTNmOWRiODZkNWNiNWMyOTcyOTI3YjQ1MWYyZjI3OWZjYWM4ZWMzZDM5OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTc0MTRjYzM0NWNjNmQ5MTY1YTdhOTk3ZWUzZGRkMjU1ZTExNjMxZjRkZWI0OWE2ZTI2MzNlNGRiNjljNTFhYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTZiNDZlMTg5ZWQyZWEzODEzZWI3OTY0ZjcwYjNkMTBjZDUxZTFhMGIyZGNkYWNhODk4N2QxNGNmOTA3NzYxMyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMzYxYjQ1OTI5ZjJiYjIzYjY4NWM1NDdmNjdkOGI2ZTY1NGU2NDQ5YTYzOWQyZDc2ZjVmN2VmY2ZhMWVlMGNjOSJ9"
},
{
"resource": "repo://Scripts/normalize-string-catalogs.py#L97-L137",
"version": "repo-lines-v1:sha256:04a5a77778f16a8b773d6bae16c86e041fc62aa32ca0bb19c75b50c3493d7d4f:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiMzk3OTMzYTI0YTgwMWVlOTIzMzI3YmQ2OWEwMTA0OWMwNzc5MTUwMjFjZjJlYzM5ZGRhNGY4MWFhODM3ZTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2MjMzYjNmZmVhMzJhMjNkZjUzMDY1MzQzNDhmMmRlZTc3NmE1YTZmNzRmYjUzMzE3NWRkYzUzOWE4ZmU0NjQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcxMTc5YzVmOTVhMDJlMTg2NTczYjkzNDhhYTYzOTZkNjZiNDUzNjgwZWEzODNjM2M1ZjUxMGFiYThhNGZlZWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNkNDEzNDBjYzIzOWExNTljZTliNjAyMmU5ZjYzMjI4MzJlMmVhZDc2Y2FlOWU0NzU0ZDIxMGViOGZiNmQ1ZTgifQ"
}
]
},
{
"id": "claim_4f997647e9c54f8caf23bd151004f962",
"statement": "The presentation-copy gate uses SwiftSyntax to scan the macOS and iOS app Swift source for hard-coded presentation literals and fails with locations when such text should move to shared presentation strings; it is run alongside the Chinese catalog check.",
"evidence": [
{
"resource": "repo://AGENTS.md#L48-L55",
"version": "repo-lines-v1:sha256:a3a3a4e50d9ec51c6791c3487b4bafeaa6d323f5d9ac8d61aa62fd24f1ec0f92:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiN2ViNmVkNjM3YmU2ODNjNzYxMmY2NzdlYTllMWE1NmI5NjU5OWU3NzJmNmQ3NjkwYjQyMzc0MGNkMTRhZmZmNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTg2ZjBmYzI2Yzg1ZWJjYjA4ODA0ODE3YmIwZDNkYmQ3YTA5YTYxYTU3ZGE5YTA1OTdhYWM5ZTc1ZDBkNzQ5MiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYzRkY2Q2ZjFjNTFjZjNkNGEzYWM4NTBkNTM5N2RlNGJiNGJlMDE5ZWNlMWE4Y2U2M2MzZTIxN2I3MTExMWFjOSJ9"
},
{
"resource": "repo://Scripts/check-presentation-copy.sh#L1-L9",
"version": "repo-lines-v1:sha256:3d159813494cb6c9293d191af96b133579ab09fead4e5a9a86298d3d56d6e646:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYjg3NWY5Mjg1NDZhZWU3ODU1Y2IxZGI5YWZjOGFiM2YxYThhMzRkNDNkZTViYmQ2MmY3MDc2ZDdiYTlmMzkxNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZDQ2YWM3MWNmMTU0Y2IwMzE5ODVlMWU2MmZhZDA1YmQ3MjI4ZmYyZTQ2YmM0YTA5NWZlNjI2Zjc2ODhlMWI1NSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjAsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSJ9"
},
{
"resource": "repo://Scripts/check-presentation-copy.swift#L26-L60",
"version": "repo-lines-v1:sha256:41b8485c80a5f462bd6dbaa16924bfbeb34ba18abfdaca67f4a507c62b0b0c0b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzNTVkNTljNDRiY2QxMzk2NmU4N2Y5MDI2NWJhYjZmYzdiNmM1MTA4Nzg4M2Q5YmQyZDM0ODgwYmMyNjYyNWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1NmQzNzFhY2NmNmY5MThiYTA2ZjZmNGQ4NDhjZWZiYzcxMmQ3ODFiYzM3NDA3N2VhNmYzMjJhMDBmMGJmNzUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjZmNmZjI1YzkwYmEwN2M0Y2U3Y2UxNDkxOTEwMWU4M2IwMGRjYmE0YmM1ZWI2NjNjZmRhNDlhNDY5N2ZkNTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
},
{
"resource": "repo://Scripts/check-presentation-copy.swift#L5-L18",
"version": "repo-lines-v1:sha256:092f3212071893f610272a62e0dee5a7c9296cffe95064fc25cc8ed65bc5ce27:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkYTY4ZDE3MmNlYjAzZWM2MjVmYTAwZDYyY2NkMGIwNGViYjIzOTNjMjRkMzQ1NTU0YjMwNTdmZGU4ZDQ4NTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFkZDI0NDU4MmI2ZmIwM2QyM2I4NDE1YWJlY2QzNDZiMGM5ZjQ2NmI2Zjc1MmIwNjgxODljZTdlOWEyZGMzNTAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU3OTQzZmRkMjkzYzI3Yzk5YmQzZmU4MjlmOGZlY2EzYTFkZjc3MDZmYmMyNTIzZjAxNDE1ZDgzNjA3ZTVhMzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU3NmIxOWU5ODgxNmYxMjE5NjE3ZjQzZTljMTM2ZDZiNTcxMGQ5ZmVmNzAzZmFhNThkMzVkNjY4NGIxMWYwODUifQ"
},
{
"resource": "repo://Scripts/check-presentation-copy.swift#L64-L87",
"version": "repo-lines-v1:sha256:e567e2575025771a0f17f7c9e93126a63ce6c603b8f0c2e32035f9f7731d4860:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA1M2I1YzQ2NjY5ZmJhOTI5Y2YxNmEyNmEzM2U2MGVhNWIwYzFkNzg3OTc0ZTMxNzk2OTllMWU5MzMxMTFhMDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU1ZjZlYjBjY2QyNTMzMWVlNTZkZDAwN2Q2MjczOGQ0NDAxMjIzMWViMmI2NDhmNzhhYjA2ODc5Y2Q5MGNkNWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
}
]
},
{
"id": "claim_753869908c9d48d992613e989a70014f",
"statement": "`PresentationCopyTests` provides focused regression coverage for localization resources across three languages, including native menus, count-dependent copy, and SwiftUI resource bridging, beyond the catalog validity gate.",
"evidence": [
{
"resource": "repo://TFMTests/PresentationCopyTests.swift#L153-L179",
"version": "repo-lines-v1:sha256:c99e1ac8888258a65ce6ed7b442f83bff9cd4e9b26f826a3993c2d12d48700ca:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0M2Q0ZjYwMWU4ZTJmZTYwNTExYTIxYWY5MGVkNWM0MzYzOTVhMjlhMTE2YWY0MjljNDE5Njc1NDQ5YTc0ODYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgzZWI4ODU5ODRkZGRiM2Y1ZDgxYzM3M2I4OTkxYjk3ZTViYzc5YWZkYmIzODk4NGJjMGU5MWQ2ZTkxZjZjOWYifQ"
},
{
"resource": "repo://TFMTests/PresentationCopyTests.swift#L9-L76",
"version": "repo-lines-v1:sha256:2d2a60ac4e983f4d2d8ade2d753befda1825eb89a34ce6a5dd07e61f5aa70cf6:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1MWYzMTJmMTE0ZjY1ZDc1ODBhNWRjOWQyNWNhZDJiZmM3NDJmNmJhNjNlOGRmNWEzNjQ0ZTE1ZTYwNDk5NmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NTJjOTcxMTBhMDM1ZjNkYjQ2MWIzM2VjZmQ1MzAwNzk5ODMxZWJlYjdlMmEzOThkMzJiY2ZmNTJlYjFlNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJlYWVkMzI5NzZkYjNjMTdlMjA0ZmZjZjZmYjVlMTUwNDliMmEzYzk4MGNhNjk3ZmVmMWI4Mzk2Y2NlYzRjYjcifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:ca6fe1e6d38481b7e92b09c44bcf391ba3c18250e658b39e774491480747b2fe",
"pageVersion": "sha256:3fdb6fea6ac8d8927120a183ee809996260dd8b78d2cb2acd9573701d5e9ff56",
"claims": [
{
"id": "claim_bca4a6f8574343d5b8310421bbdd595d",
@@ -201,10 +201,78 @@
"version": "repo-file-v1:sha256:fb1177900e93b9a2d3f30d4b728e61381d7d1336226ac22610e85779b8d0dadc"
}
]
},
{
"id": "claim_d9bd498c7bb54f79af60a63cf83c303c",
"statement": "The shared SwiftData container uses V34 and the migration plan with CloudKit mirroring disabled; the plan preserves a frozen V28 Host endpoint on the V27→V28→V30→V31→V34 upgrade path, while V29, V32 and V33 are not migration endpoints.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L748-L815",
"version": "repo-lines-v1:sha256:4b4ed3e06b0a78e93f812452711c7de7ffdfa90036e002c9a801562d8dd2caee:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ5ZDdjY2VkZmM5NzFlYzg0YTY4ZGJhYzZlNDg5NTI3ZGJhZDVhMjcxNmQ4NzRlOGYzZjgwMTJjYTFkMWQ5ZmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMyNzEzMGYzYzFhZWM1ZDRiODIxZjcwODBmYzFkZDUyNzRmNWQ4M2VjYzdmMWRlZjJlNzU2Y2Y5MTIwZDIxN2UiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5NTg0Njc2ZWZjMGU1YjI4MWYyNzViYTgwNjYwMzY0ZTRlMTI1MjkzOGZjMGRiMjZiMzVhNjE4MDgzMjM4ZDcifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L883-L909",
"version": "repo-lines-v1:sha256:c48361cb01db8f7aaa9df243e632fac2fa84552f08bacd3ae48f32c70948cdbf:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUyOGVjZTU4Nzc5NTgyZmI0YmY3Zjc4NTJkNzBjOGE0NWZlMjU3YWIyNTc5NTZiMDU0N2NhZDc3ODkwNjNlYzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhYWU4YTBjYTc2Zjk4ZjdiN2RjNzk4NDk1MWQ2M2U1N2RiM2M2NDU1NzljYTUxYmFkNmE1MzlkNjE0ZWRiYmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUwNTE1MDdlYTM2YmZiNzAxMWE3NzhiZjcxMWIxNWUzN2U0Y2Q0ZmE5M2UzY2RiNDBhMjhmNzI1YjZlMTM2ZmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L4-L23",
"version": "repo-lines-v1:sha256:8c60738deb877ed1b9047d779675ce26ace9d679e2bf4e8b9e6eed90258d3fce:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzMzA4NTlkNjgzODAyNWFiM2Y2NjIxNTU5NWM4N2JiZWI1ZDVlMDlmNTIxMjk3YmY2MzI3NTUwYzgxYzBjYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4OTUxYTVlMDA0MTE2ZjBmM2Y1MzVjODgxOTBiNmUwNmU3NGFmZGZlYjU2MTc0MTA0YTIzYzQyZjJiYTNlZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
}
]
},
{
"id": "claim_e06d853729a54aeb97f6e6851e8d6c6b",
"statement": "V28's stored Host port, identityID and charset survive V28→V30 as SSH-specific values, while Telnet fields are introduced with disabled and default values; changing historical persisted shapes would jeopardize installed-store compatibility.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV28HostModels.swift#L7-L35",
"version": "repo-lines-v1:sha256:48595ba6a10953470c8fa461f76ad38ded5dd2673a3af0ed5c5fbcdee3ed40fd:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ1YmNjZjg3NmJjMDFjZDNmMDU4YWZmZTBjZWJiYzU3ZTkyNTBmMGM5ZWI5ODlkMjAxODM0NDExOTFkYTk5NzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjMzhlN2E1MTJhYWNkZmM1YTZjYjAzZWM4NDBmODkzZGE2YzMyYmJiZjIxNjljMDhlNDJhNjViMjQ3ZDdhYTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkYTMxMmZlMTU1NzA0MzkzMzRiYzkwMGRiNDQyOTUzNjJmMzg5ZjVjNmVkOGU0MTViODIyYzBmN2YwNDJjNDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5NDIxYWM2M2VmOGRjMzlmNDZjZmZjNzllZDFjMDQ2ZTg2MmUwMmE1NGY3MzRhYjYxYTJmMmRjZmE3YTNhODAifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV29HostModels.swift#L7-L48",
"version": "repo-lines-v1:sha256:822a0928dd1f722d9b0733d7b73d2be2c33875af01d165875cdd4c941941a90d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJlNjUwOGQ1YTdmMTg4YjhiMGU0ZjhiODFhNGJiZjgzY2RjYmNjY2JlMWMzMWQ2MThiNjQzZGYxYWM3YjFmNjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjMzhlN2E1MTJhYWNkZmM1YTZjYjAzZWM4NDBmODkzZGE2YzMyYmJiZjIxNjljMDhlNDJhNjViMjQ3ZDdhYTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkYTMxMmZlMTU1NzA0MzkzMzRiYzkwMGRiNDQyOTUzNjJmMzg5ZjVjNmVkOGU0MTViODIyYzBmN2YwNDJjNDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5NDIxYWM2M2VmOGRjMzlmNDZjZmZjNzllZDFjMDQ2ZTg2MmUwMmE1NGY3MzRhYjYxYTJmMmRjZmE3YTNhODAifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV29HostModels.swift#L92-L113",
"version": "repo-lines-v1:sha256:d4c3f6b04a4410518a99104ec119f1cf0ee8976d5e4f858697af6eb1a80cb2dd:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA3NWRlZmY2MzY2MmFiOTZiNDQyNWEzNmU1ZDg5MzA1YzgzYzc2MTkyYjVjNzcxMTgzODQ5ZjY2ZDQ5MzBmMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdmMzkzOThkYjE5ZDhiNTViMjA0MmRlMTMyOTI1NWViNDE4Y2I3MWVmY2Q5YjEyMzFmODk4ODY1NmZiMjQwODUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE4OTc1ODkwMWNiNDI4N2M3MGZhNTY4ZTlmZTgxMWNiYjY4Mjk3MTU0MmIzZjAwMGUzY2ZjNWQxNjlhYjAyMWIifQ"
}
]
},
{
"id": "claim_4bbc9c1130e14f2d92c92ae2b77c7705",
"statement": "The historical synthetic V28 disk fixture is generated against an older Persistence build rather than current models; its compatibility test copies the disk store, opens it twice through the normal container factory, and checks retained Host and related Vault data, default Telnet fields, device/history backfill and workspace defaults.",
"evidence": [
{
"resource": "repo://FrameworkTests/PersistenceCompatibilityTests.swift#L60-L144",
"version": "repo-lines-v1:sha256:4561b141f81b56941320a35e8389bea59dc6291fc22b2e7b359b58f0ed816631:eyJzZWxlY3RlZExpbmVDb3VudCI6ODUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdkZmY4ZDRjNGJlMTRmZDZjZjc4YmQ1ZmI2N2JkNTNkNGVjZWI0MTljNjVhMzFhNWQ2OTQ3NzA2OWE2Y2ExMGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFkZjBmY2E5ODUzMjVjMDQ5ZTY0ZWE5ZmE2MTE3ZjI4NjY0YTcxNzlkMGY2NWEyNjRiNTcyOGNiMTg5NTA4MTIifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L887-L907",
"version": "repo-lines-v1:sha256:3b2210e481a8147ee7a43ad5ba997d358ecc2ea6c04ba60e0cc96cf4548bf98d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY5NWYyM2YzNzI1ZTkzNTU0ZjQwNGNhMzBhMWUzOWY0YTU1OGU3NmU5MWY5MThkZDBmNDE0Y2JkMGU3MmUwZDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI3ZGNkMjg5MWJlMDA0OGJkZjgyZmViMDU5YjJlM2RhOWNhNDJmMmU1ODllMTg1MDQ3MzVmMWU4NDYzNTFiZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNhZWQ3YzJkNTQ2YTEwZmI3ZDRkZjM1NWE3ODZlOGViZTRjZTJiMzgxMzZmNTI5ODVlNWVmOTAwYjgxMTBiMDEifQ"
},
{
"resource": "repo://Scripts/generate-v28-fixture.swift#L6-L21",
"version": "repo-lines-v1:sha256:4f7f40344507ad155a1f284dccbb5654a2485548e8ae55bfe045f55c3a1d4749:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY2ZmMwZjM3MzFlNjkwMGFhZmQ5ZDQ5NTczODIzZjc1NzQzM2Y3ZTc0OWY2OTQxYjNmZWU4ZDI3YzFjZDRhNGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZmYWY5OWU1MjY5MGI1YjQxNzJmNzFhOTgwOTYwMDRlOTc5N2Q3M2I5ODllMzAyNGQyNzcyODI3NTI2MmYxYTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhNDEzOTNjODU0MWVjYzQwZTdjMzZiM2Y2MmQ0YTFmMDY5MWRmOTI3NzZkM2E1YzRhYWU2OWQ4OWFhYTZhOWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM4MzM3ZGI0ZjFhOTM5ZTllODc1ZjA5MzM0NmU3OTRiMjlhZjI3YTU1MThhNzg2Zjg0MWVjNjFmNGJlODBhOWUifQ"
}
]
},
{
"id": "claim_0b988903106b49299748ae7421068475",
"statement": "The mobile V28 startup test instantiates the app twice using the migrated disk container and checks Host, identity and history projections; it is an in-process fixture integration check rather than proof of signed-device installation upgrade or CloudKit delivery.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L11-L23",
"version": "repo-lines-v1:sha256:9695ebe26846d201675edfe4e44e6558dc7af1791205abc9adc27563d41ed6da:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc4YWU2MDczOTViZjM1MjFhMWUzZThmYWZlOTM5MDQzNTE0MTBiMGFkMjU1MjdkODQ3OWRlZjlmN2UxYmFlODQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdmYTMwYTU3YzgzMTk5ZWRmMDI5MzNhNDFlNmFiNmQwNzQ3ZjYwMTI1NDg3YjExNTE0Y2JlZWRlZWQxZmMzN2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFITests/MobileAppTests.swift#L34-L63",
"version": "repo-lines-v1:sha256:99e8c3c311bf8ac02b14dd46b5be07ae2a313a7dec6b6fc526610ce40e400ee5:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkwNmQwMjc3NGU4ZGE1NWVmNGQyYWYxZGUyNDliYmFkNmVlMWU4Y2FhNWM0OGYyNWY5ZjQxMTA4MjI0ZjVlZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY5NTkyZjUxY2NiZGExM2ZlMzVjNTI4ZWQ4NWQ0OGNlYzBlN2ZhNGI4YjMxMTBiMjAyYTkxOWY3MjU2NGQ0OTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJkNDU3YjJhYWRhZTY4NzQzNzY2M2EyNTQxN2Y5MGRkNTQ1MTMxNmViZjQzN2Q1MDY5MTQ3ZTY2NzhhZDg3MmMifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:76527be96d18cc256d454398aec2031cb797ac37445daf0203a76e982af8ceef",
"pageVersion": "sha256:31b25b8f676ef671d6853f726cbc282183f00b5870b6f2918c68a4f6a0bb8941",
"claims": [
{
"id": "claim_3d431c8c7b804187a1ef5a7d9178c430",
@@ -71,10 +71,152 @@
"version": "repo-lines-v1:sha256:6a76d54ef19ad5c6b564234115af5f6d34dd4d600f01435ccb6ed36cebdbdf5f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNkMDE3YjUwYWY0OTFiMzExZTAwMzA0N2UzMGMyYWUxMDFkZDRkZjllMzRkNmE5YmI5OGEyZTIzZjIzNDI4NWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEzMGQ3MDNjMjIxZGFkNmRhMzg4Yzk5MjdjOTQyN2I5YTY5NTBiYmNlZTliMzM0NGY4OGY4YjAxOTZmNGU0OWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk3YWNjMWEyNTVjNDVmNzk5ZTAyYjM4Zjg1MGVmOGIzMDMwOTNiZTE5OTZiMDIwNTE5MjU0YzRkNjYyYTViMzAifQ"
}
]
},
{
"id": "claim_7eed8502681647e3b00a1c1790fba036",
"statement": "The commerce controller validates the annual product as a family-shareable yearly auto-renewable subscription and the lifetime product as a family-shareable non-consumable; annual trial availability requires purchasability, account eligibility, and a zero-price introductory free trial, while the annual product remains purchasable without an offer.",
"evidence": [
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L233-L277",
"version": "repo-lines-v1:sha256:e42a37717e805b2d21cb3234150599869fd34f85f77dec2e9cf3920c4d226229:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJkODA2NTg5YjQ0MDNmNDUzMTEzMDVhZjY5MzQzMGUzMzk3NTE2NWViNDc0NjM0YzA0YmE4YThmNTJkZThiNGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5ODRmZjdhMjc0MmNkMDc3Y2U0NWZjZjIxOGVlMGZmMTc4YTJiYzBiOTc4MDhhY2U3NGYyYmRmYmVjZGNkYmQifQ"
},
{
"resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L32-L47",
"version": "repo-lines-v1:sha256:703045e28f12924d2dc7b05569bdc9b0d47d35be6264aabdd3c835f4113f6f0e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ1YjQ0OTYxYmNlNmI5Y2E5MGRhYjNmNzU5OTM3ZGM2ZTU2YmIyZTkxNmZiNWU4NmJmZjc1ZWY3YzllMzRkZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBjOTkxNTM4NTA2Y2ZmYWNhM2MzZTliYjhjNThkY2Y0NTBjMzFmOGZlN2FiN2ZmZTUwNjk1MTBiNjA0NjMwNDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ0MTQ4Yzg4MjUxYTUzM2M3MjFmNDYxOTI1YjIzMjNhOWI2N2QxMTcxZDNkY2M0NTBhN2NjYWM5ZTA3YmEzNzIifQ"
},
{
"resource": "repo://TFMTests/StoreKitTrialTests.swift#L128-L164",
"version": "repo-lines-v1:sha256:b00676fac063f4927270b5510524b38b5cc3ded9c0d2dcfd1ac1e5f585c7abfd:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIxYWEwN2RmOTM4Mjk3YjkxNzI3NTYxZWU3Yzc3ZGViNzJhYmI1MDM4YWQwOGI2MDVjMDcxYWQ4ZGEwOTY5YTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFlYWQ2ZmJhZmJjM2M2NzBkM2I1MjZlNmFmZTJiYTc2MTgzYWI2NWI5MjdhMDdkZjdjYjI4YTQ0YjFjNjE4NzcifQ"
}
]
},
{
"id": "claim_e219fb3e466543deaebd93dfd94cb8d2",
"statement": "Mac and mobile adapters pass controller-derived entitlement, price, trial, and purchase state to the shared paywall, reload products on opening, and choose lifetime when only lifetime metadata loads; Mac provides the MCP-server disclosure and subscription URL while mobile provides remote-MCP-only disclosure and the system management sheet.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L107-L120",
"version": "repo-lines-v1:sha256:62d1b06874b1ad47f5ded0c2b6a4209eba6191c1e98d56fafb3549ccd199b855:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY5ZWVkZDFhMzlkZWU0ZTdjMThmOTYxM2QxMzNjZWExNWRjZGY4YjI3MTQ0NDBlYWFkZTAxZWUyYWJhYzdkYmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxZDlkZDY2ZWIwMzMyM2Q3NWNmNmZiMWE0ZjgxYjYxODNiNjczODcyYWEzY2JmMzg4YjI2ZTYxMjIyZDYzNDQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZmMmM3NTNjZGFmNzhkMDA3NTk0ZDM1ZTg0NDczNzI0ODZkMjRjYjcwZGM5NTc5MDViNDU1OTM2MzIwNzg4Y2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ5YmE2YjhjM2UzYzgwYTY0MmEzMzdiOTk1YTU3NWVjN2E4MDhlOWQ4OGI1YWE5M2Q1ZGViYzM1NmM3MzllNDkifQ"
},
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift#L13-L56",
"version": "repo-lines-v1:sha256:874097d435efac8111266f28abb629aa93f87af36757834e5a0c1c25e35d1651:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4MjFmMTM3MGVjN2JlMThlNDBlMWI1OGE2NGMxZGEzMDY0ZTk2NTUxZmUwMzdiNTE0OGJjM2JkZWI4MTliZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L15-L67",
"version": "repo-lines-v1:sha256:012ba9aeea83b71db8e1c2b7a2760feed485f3ee061faa191bc32f71820b9056:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU2MTc0MGI5Y2FmN2I5NGNiNjM3MTQyODBmMjA1NDUzNWYyODY1MjMzYWM2NzBjM2YwNjFiZjkxNjZjYTMxOGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU1OGIwNjRhZTAyZGQyYTZlOTI3NjAwY2RkZjgwNGVhYzUyNTkyMTFlYTEwMWJlNTgyOGE5OTE5OWZmYzUxN2IifQ"
}
]
},
{
"id": "claim_167d12430fef483f80d8bc2eabc4dd22",
"statement": "Shared offer formatting converts StoreKit week-based trial periods to days, shows a trial badge and free-then-renewal detail only with eligible duration, distinguishes eligible annual, paid annual, and lifetime purchase titles, and does not fabricate annual detail when price or period is missing.",
"evidence": [
{
"resource": "repo://FrameworkTests/ProOfferPresentationTests.swift#L6-L70",
"version": "repo-lines-v1:sha256:60ef7fbc455c1e236654ba64c14069a8cff2a658c9ce4ea7047dcd5ba43bcc0b:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhjNjNlZTI4M2Q5MTUxOTc0MGIxMTE5MTQxNDdkYTNjM2MyNzdmMTI4NGRmOTM5MGRkNzNmNmVmMmI5NDA4N2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyOWM1Zjc3YjVjZTI0ODU0M2UyMGFjOWRkZGFhNjU3OTY5MzZhMmM4ZDE2N2NjMzRiZGM1MDM3N2RhYjg2MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRkYmZlM2Q1MGM1NzliYTgyYTdlOGFiN2VlN2QyNTE4ODI4YjM1MDU3MmY1OGE3NzY5YjEyOWZhNTA2NzcwNDYifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProOfferPresentation.swift#L10-L67",
"version": "repo-lines-v1:sha256:06ff85d27423f24f58325dfccc7448ca9133b4cddb5f872827bf7432c70e34f4:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVjYjc4YTBhYmU3YWE5YTA1YmY5NDJhYWZhMmQ0Y2Y5NjQ0ZTVlZDc4MjAwYTcyZTYxY2EzMDM1YmU5ZTc2ODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQxMzhhY2VhNDZjMjMzMjEzZjFiZDc5MWEzMWQ5YTFmODMzOWE2N2RmOTIwMjQ0YWYxNjhlMWRlMmI2NzQyMjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_f93e686ba3e74d45b7f9376c8a16ef55",
"statement": "The shared paywall disables unavailable plans and purchases during processing, offers a metadata reload if either price is missing, reserves subscription management for account-owned subscriptions, and moves purchase actions into scrolling content with stacked plan cards at accessibility text sizes.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L128-L199",
"version": "repo-lines-v1:sha256:5722d58a00887fa366219221f4c35d92d3084607634e28256f731666a2637639:eyJzZWxlY3RlZExpbmVDb3VudCI6NzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1N2U2YzM3M2E4NmNiYzcyYmVjNTMzYTNlMjUyZDk5MDQyYmU0ZWMzOTc0NzdhMTg2YTkxOTQ1MzVkOWJiYzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk0MWYzMzI4NTI5YjRhZTI4ZWJiZDQ4ZDQ1MWYwZmFhYjNjODZmN2I3MDU0MzYzMTRkOTEwZDlmM2M5NzQ4OTAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVkOWM1OThjOWU0NjM0OGU1OGY0MWUzNTcyZGJjZjMyMmE4MDk4YjdlZmI1YTU3MjhlNjc1NjQ1ZDMxMzUzOGMifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L211-L275",
"version": "repo-lines-v1:sha256:c2e2e9b91735a4c10d351fc2373a12848df14d1c9f32a49ea77a8aa2606093d7:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVjODQ1ZDM4ZjFkNmU1NTdhZDZiOTNjMjA1YmIyYmM4OGUyNDMyZWNkMTdiNjg2YjBkMzNlYTE2MDY4MjlmM2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYxOWFiZjRjZDJhNWYzMGIyMzQzZTVlZTM4ODk0YjU3OGE4ZjM5MTEzN2VkNjBhYzVhNjNkZWM0ZDNiMjQzYTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU1ZjgwZTFlNjVhMDVmNzM0ZTEzY2NmNmUxYzU3NmMxNGM0YTFlMDNlYWQ3NzM2ODEyNzlmM2I2MTNiNDRmZmEifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L33-L53",
"version": "repo-lines-v1:sha256:31f9e6064afb1f93cffc818e227eb00fd10d2179ace0df56676b3a532744f74a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5Yzk2NTJkODc4YmVkYzBkZmQxNzU1NDRkNDc1ZmFmNTdkNTY5N2M0MGU2NzBhOGZjMWIzZjQ4NjZmYWY1ZjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxMjRkMzMzZjVhY2QzZjc4ZjVlMmFkNjRmM2MzZWYxNjZmZDk2NzdiM2VkZDBlNjRjNzZkOTE4NjQwNmVhYjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0ZDIyN2E0Y2FmNWQ1NDFmMzU1ZTc1YWEwMmFiM2IxNTMwNjcyNzg0MThmZmY3MGQzMDhiMDY5NWJiYTc3MmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0ZTlkNjE4OTFhMDNmZjc4NjQ4ZjcyMzc0NWJiZTVjOTNlNTFiNWQ2NzAwNDJlNDQyOTkyYTRmNTNhOTgzM2UifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallPresentation.swift#L40-L54",
"version": "repo-lines-v1:sha256:10a769e4a8ca878d417a7e8c44ba763f69ce2645be3d74edfc6df8467cdc49c1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY1NmEzNmY4ZGFlMGM2OWRlZTYyZGMxZDdiMTA3Nzc0MTRmZTlmOTMzMzFjM2IzNGNmZDdjNWRkOTFhNGU2NzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2Yjk4YmQ4NmY2ZTkwNDZlOWZjNWQ1MGJhOWYwMjRkOTdlOWI2MzIxOGIwMDAxNDk2Yjk2OWQ5NzlhMjZiYzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2YWQ2NzNhZjRlYTgzM2UzZDM2MWMzYThlOWZlYjkyOWEzMWUxMWIxNWZhNWJjNTA4NWUwYmEwZDAxMGYyOTQifQ"
}
]
},
{
"id": "claim_05ecbf885d914e9ab0ece0332cebc467",
"statement": "The offer's trial, annual-renewal, lifetime-no-renewal and purchase-button strings have Simplified and Traditional Chinese localizations, and shared paywall content resolves the offer strings using the view locale.",
"evidence": [
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings#L17611-L17627",
"version": "repo-lines-v1:sha256:557b8e9985da58902d2ee42482d365fba2e1c3cdaac45f23a6a6f587c7d4483b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiMzBhMWQzZmE2NzhhOTc1YmU5NzIxMDIyODdkYmRiZDI5YTJmYmFiZWI2NGE3ZTFmZGI0MWVkYjFkOGMzMmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFmMGNkYjk3MmE3YmZiN2VkMjQ2ZjlmZjY3MjM4NWU1NWY0OTY4ZmMxMTA0M2RjNWI2ODRkNTFkZmEzMWRiY2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZmY2VjODBlODg3ODI1Y2ViYTZlYjFlYjc1M2ZlN2EyMmY5MDM3NmUxNTBhNzZlNTg2ZTUyNzZiMDI2ZTNiNjIifQ"
},
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings#L231-L263",
"version": "repo-lines-v1:sha256:8bf9a770467aaf10c6543f043cf0a0fa382c576dbf6ce60269128055a5a82e71:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk5YzQ5M2MxOTIxNDcxMjQ0YzMyMDRhYTdmZGEzOTYzYzAxMjc0MmFmZDgzNmMwYmVkOTc3NmZkYWY3ZTY3YzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjliNjJmNjBkODU5MGE1NzljZjQ2ZjhkNjczNzhjNGM1NzJiOTYyY2VjY2RiOTBjN2E1ZjdiNDJiOTYwNzgyYTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjZTM0NTVmZTdmYzM0MGFlMDhlZDExOWU2YmQ5OGI5YzEzNDQ2ZmFkMTgzZTc3NjU5YWUxOGIyYzUyZGMxMWYifQ"
},
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings#L24761-L24776",
"version": "repo-lines-v1:sha256:ab4874b1bfe47c848a7b305f090586537b7c35fdfb28894eedf41067147ed35c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI3NDU1OTQ4ODc4YmE4OGYyN2M3NWNhOTgzMDEwY2IxYjhjNjlhNmUwYmU3MmM1NTgyYTcwYmQxMzRlZGE5OGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjliNjJmNjBkODU5MGE1NzljZjQ2ZjhkNjczNzhjNGM1NzJiOTYyY2VjY2RiOTBjN2E1ZjdiNDJiOTYwNzgyYTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc1MWM0MTU3YTYxOTgxYTk4NzYyNzhkMjUxNTkyYWY2NGE0NTQyMWQ5YTZlMzllNDNlZWFjYWNkZDZiMTE2ZDkifQ"
},
{
"resource": "repo://Frameworks/Resources/Localizable.xcstrings#L288-L303",
"version": "repo-lines-v1:sha256:df043e5fd6e2a888537e9feb1969ecc54377e8f9055a864f90a9df5a97eafff0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImViYzdlZDBlNjEyMTljMjk2YmJhNTJhNTFiOGI0MmI2ZGIxMWU1ZGIzODhiNTg1MmMzNDk2MmVlODIxMTJhYjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjliNjJmNjBkODU5MGE1NzljZjQ2ZjhkNjczNzhjNGM1NzJiOTYyY2VjY2RiOTBjN2E1ZjdiNDJiOTYwNzgyYTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFjZDA1Zjg1MmZiOWY5YjUxYzQxOTFhNWFiMTk2M2FjMmJkZmY1YjcxNTc5OWI1NjIwMGUxOGFhMTk5NTE2MTIifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L136-L156",
"version": "repo-lines-v1:sha256:ba5ce846539b674f4ee4b6cea957309a25de7251d73d610a1659eab8df3f8bd9:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE3MzE5YjEwYzgxN2UxODU5YWZmYWEwYjdkY2EwMTI5NTM2NzVkOGM4MzRhMjhjMDFhN2M1YjQzOGI5ZGI5OGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhkYjMzOWMxN2Q0Y2M1NGU3MGM0ZmNmZWNiNjExYmI5ZTdkMzYzZjI1YjE4ZTA5MjNhMWQzMDZjYzk1OTI0ZTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZlM2Q2MGE2Yzc1NWFjODIyMzczZTExN2VlNWRjN2JiZDg4MjJjNmFhMzMxMDJmMjllZDZhNjc1YTgzNjM3Y2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVlZjBiMTAxMTcwNGRlNGVkMjBlZTAwYjEyZTY1ODIzMjRkNGIyYzgzMWMzZDM0YzRjMDllMTJkZDgxYWY4NzgifQ"
}
]
},
{
"id": "claim_0bb4eb4f4b7c4e4eb2ef50ee15a2ceac",
"statement": "Offer and presentation unit tests cover localized weekly duration, eligibility, missing metadata and entitlement display; Mac and opt-in mobile rendering suites capture free and subscribed shared paywalls in English and both Chinese variants at regular and accessibility sizes without contacting StoreKit.",
"evidence": [
{
"resource": "repo://FrameworkTests/ProOfferPresentationTests.swift#L6-L70",
"version": "repo-lines-v1:sha256:60ef7fbc455c1e236654ba64c14069a8cff2a658c9ce4ea7047dcd5ba43bcc0b:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhjNjNlZTI4M2Q5MTUxOTc0MGIxMTE5MTQxNDdkYTNjM2MyNzdmMTI4NGRmOTM5MGRkNzNmNmVmMmI5NDA4N2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyOWM1Zjc3YjVjZTI0ODU0M2UyMGFjOWRkZGFhNjU3OTY5MzZhMmM4ZDE2N2NjMzRiZGM1MDM3N2RhYjg2MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRkYmZlM2Q1MGM1NzliYTgyYTdlOGFiN2VlN2QyNTE4ODI4YjM1MDU3MmY1OGE3NzY5YjEyOWZhNTA2NzcwNDYifQ"
},
{
"resource": "repo://FrameworkTests/ProPaywallPresentationTests.swift#L6-L89",
"version": "repo-lines-v1:sha256:2cac517c6e29b315636b8e7f83213a3cc503bc9c5b4837db26141b20727ed263:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkzMjJmYWE0NjA3YWQxM2Q4ZDhhM2VlOTVjMjQ0ZjViOTlmODFkNDVhOWE4NTc2Nzg0YWUxNTM2NGU1YjZlZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyOWM1Zjc3YjVjZTI0ODU0M2UyMGFjOWRkZGFhNjU3OTY5MzZhMmM4ZDE2N2NjMzRiZGM1MDM3N2RhYjg2MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE4MDllYWE3MWRjNmZkZDE0MjUwOTY0ZjJlYTgwMjI2NzE0NWE1NDhhMDRjMmZlNjRmMTJlYzRlMjQxNzUyYWIifQ"
},
{
"resource": "repo://TFITests/ProPaywallRenderingTests.swift#L7-L77",
"version": "repo-lines-v1:sha256:e97a64821b0a86e3366b122874974d6490fd4dbc998965d0b6c2a3472f04eb05:eyJzZWxlY3RlZExpbmVDb3VudCI6NzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdhMjdjNGRjZDU0ZTBjMDI5YmM0ZDdjMWVhZTk2NTdiOTcwMWNkZTgxNjQ3Y2Q1ZDQyNTQwMmEwYjUyZjc1YmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ3MGMxNjI2NDZiYTYzOGQ5YmE5ZjQyYTdlYjQ4MmI4NzZmZDMyODgxNWNiZThmOWRkMTk4NzA0ZWI5ZjA1ZjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNjOTNjOWIzMzllMTcxNTg1ZGFmNzQ4MmNlOWM1YmUyNzljYzEzZTk1MGM1NjI2YjU3NTM3MTdhM2RiZjA4NDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmM2UzN2Y2NzljZDY2NzAyYjcxZjNmOThkN2IyYjYyZTAwMGEzM2FkYjQ4OTE1NDdjNjZhOTJkNDEyNGIxNzkifQ"
},
{
"resource": "repo://TFMTests/ProPaywallRenderingTests.swift#L7-L59",
"version": "repo-lines-v1:sha256:bb36a7e6c836fff23ff6dbd3d588a55c397379cad0ed8abab7b9e8e14053e1fd:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2NmE3Mjg3NWNjZDc4MTM5NTk4Y2IwZDM1OGI5MzczZDM2ZTlkYTQyMDE3NzA4MTkwZGE3M2JmNGE3Zjk1NzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ3MGMxNjI2NDZiYTYzOGQ5YmE5ZjQyYTdlYjQ4MmI4NzZmZDMyODgxNWNiZThmOWRkMTk4NzA0ZWI5ZjA1ZjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyOWM1Zjc3YjVjZTI0ODU0M2UyMGFjOWRkZGFhNjU3OTY5MzZhMmM4ZDE2N2NjMzRiZGM1MDM3N2RhYjg2MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmM2UzN2Y2NzljZDY2NzAyYjcxZjNmOThkN2IyYjYyZTAwMGEzM2FkYjQ4OTE1NDdjNjZhOTJkNDEyNGIxNzkifQ"
}
]
},
{
"id": "claim_bfdb3849716843bd941c4d567891acf5",
"statement": "Localized final App Store JPG boards are organized into English, Simplified Chinese, and Traditional Chinese sets for Mac, iPhone 6.5-inch, and iPad 13-inch; these exports are distinct from the screenshot captures and device-frame inputs used for the website.",
"evidence": [
{
"resource": "repo://Marketing/AppStore/en/mac/01-three-screens.jpg",
"version": "repo-file-v1:sha256:4bb52a843824a43e8d19a4930c59a3ec37fae381e806bd4c02b0aed614a980ff"
},
{
"resource": "repo://Marketing/AppStore/zh-hans/iphone-6.5/06-vault.jpg",
"version": "repo-file-v1:sha256:01b2ec95f0e134c358c73b6f121c8e5856e78c0c9362831fed6e2d2591a35700"
},
{
"resource": "repo://Marketing/AppStore/zh-hant/ipad-13/06-vault.jpg",
"version": "repo-file-v1:sha256:536ccf9e8449b92ea3ff55b30280d51cfcc7415ffacc36b26ea545110fa9c15a"
},
{
"resource": "repo://Marketing/README.md#L3-L13",
"version": "repo-lines-v1:sha256:4f2a865e16e47099ad22ef4a06f99683c799ad690a13f1569c1497d83f3dff1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4NzQzYjljZGY1NjdmODk4M2JlODU4YjA4ZmRkZmZlYWUzOGNkZDQ0OTk0NjNlZjE1Yzk2OWYwMmNmNWViZTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU4OTZiMTE1N2FjN2Q2OThjYjcwMmQxYTA1YmM5Y2QzZDUxYjkzZTRmM2NiNzkzNjkwY2NjNjRkODA0MzBlODEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkMmJiY2I4NGRkZmQxZTkxM2ExZjAyMWY5YTM3YmMzMjJmMjMxMjg5YTRhNzc5M2FhYTZhZDRiMjVjMzkxZTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3MDgwZDlkNDRhZDkxYTJkNmY5NjJlNjZkODFlZmY2OWMyMmFjZjEzNTQyNGQ4NTcwZjgyYjExMDJkZWRmYjEifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-23T10:08:51.776Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
+89 -17
View File
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:4ca8ed0d3907d7e2d599519e36b77ec2d5c598e3a3d8f43fc8416a561a027ee0",
"pageVersion": "sha256:458b480a78f04e037b471dec7e5c900b9cece88c2b6c6615e842624264bc6d1c",
"claims": [
{
"id": "claim_83870f4f1ad6403ea0d8bd8775729a76",
@@ -11,12 +11,12 @@
"version": "repo-lines-v1:sha256:ebfbb4e4dd7e3beb5093f7d76de4ba789e0b467bdd86cf37e4cc42c6f70d7f22:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3NmYxY2NlMDU0ZTZlYjE0YTIzZTg4MDI2Mjc0ZmI0YzA0ODM5YTcxYjY2ZmZjY2VhYzkzOWUyZGM0ZjRhYTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJmNGQ3NzU3NjdlNzBiMGI3ZDE3YjNhNTkzNmM2ZDY2NDc3YmE3NzZlMTNmYzM5NmEyOGMxODY5MzQyMjQwODIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhZGU5Y2M2MTdlODVmZTg2MzFjMWQ2ZjhiZTAzZTViZDE4NmQwYzhjOTI1ZjY0ZGIzMmU0ZGI4YTBlYTY1NGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkMzUwNTE2MzRmYzcyMzY3ZGVlYTFhZTI4NzFkMjk0MTY2ZDNlNDM5MTgwOTdiOGUzMTVlZmE3OTU1ZDM5YjcifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L188",
"version": "repo-lines-v1:sha256:363e2bafaf7e2967b4b7b04ce0bad053d5b9ed639768c3c4b98c8f9ac339ee0e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxMDYxYjk2MWM1YjA4MWJiZTM0NDlhZDQ5MjM0NTE3NjVkNjU0YTg0NzM5NGNhYzZmY2QyYjdmYTkyMTllMDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189",
"version": "repo-lines-v1:sha256:533ff177b0412702e1b6b394a55e194a0822100402bf01b72c9a251a120fd83c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZlNzcxZDQzY2JjOWYwMmY5OWUzNTkwNGQ0N2I4MTQ5YTliODZmZmE2M2Y5OTQ1Yzc1ODk2NGM2YzllNzZlZDUifQ"
},
{
"resource": "repo://Termind.xcodeproj/project.pbxproj#L934-L1088",
"version": "repo-lines-v1:sha256:957dba2c7d7a125e70bc9bfc61b04998e61dd951dad8d88cbda83cc1716c4ab7:eyJzZWxlY3RlZExpbmVDb3VudCI6MTU1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0YjI1MmM0OTA4MWRmODIzZDdiMTIzMDgxZjVhODQxMTE3YTYwYzJmZGYxNzVkYjA0NTk4NjE2N2RlMGUyYzMxIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiIzZWMwMTY1ZTRhZWNkN2FjNjlkYWZhYTcyZmU5YTYyNTA1MzI1NDJhMGUxNzNiZDY2MmViYzQ1MGMxODNhZmEwIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5NDU2MmVkZDViMGMyYTY0MTAxOGYzZGU4Yjg0MDY0ZmJjMWE3ZTEwMDM5ZDQzNmUyNzU0NmJlNDc3MjJlOGVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIzOTkyYTI3NDZkZjE5YzZiNzFiZjVlNjUyMzg5MGUwY2YwYTk3Y2RmYTY0Y2E1ODdlNTU3MjNmNWZlNzY0YzVkIn0"
"resource": "repo://Termind.xcodeproj/project.pbxproj",
"version": "repo-file-v1:sha256:d274fb868d56884ebf7706a94731dbf0be5e7940b49d30176e970088d833b455"
}
]
},
@@ -34,7 +34,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift",
@@ -48,7 +48,7 @@
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -64,15 +64,15 @@
},
{
"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.",
"statement": "ArchitectureBoundaryTests enforce root-specific import restrictions: five non-presentation shared frameworks cannot import app targets or AppKit/UIKit/IOKit/ServiceManagement, while Presentation has a separate rule allowing SwiftUI but excluding app targets, native UI, storage and implementation modules; shared Application cannot import Infrastructure, Persistence or SwiftData, and scanned SwiftData model declarations belong in Persistence.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L164-L187",
"version": "repo-lines-v1:sha256:45ac2d747c736c3bb9821104587d21ef897e4ec32ff8b25b11479a6ca7608f89:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk3OTk5ZWY4ZDk0Y2NkYzU3ZmJhZDE1NzllYmJkZTM4YjIwYTUyNDk0ZGMyYWYxNGFiZGU2MjY5NmJiMTMwOGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzNzgzMjY0N2Y5NWFkMDc0NDExNjM1OThlMWU5MDhiZDM0YmUxMTBkNjNkZGE1N2FjMTc5NjIwM2VjZmNmYjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM5YjJkYjM3YThjY2FiMDIzMTkyOGUwZGY0MzcxOTc3ZWQzYzQwNzBkYTlkMDUwMjEzMzQyYmMwMmQyOGE0YWYifQ"
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189",
"version": "repo-lines-v1:sha256:533ff177b0412702e1b6b394a55e194a0822100402bf01b72c9a251a120fd83c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZlNzcxZDQzY2JjOWYwMmY5OWUzNTkwNGQ0N2I4MTQ5YTliODZmZmE2M2Y5OTQ1Yzc1ODk2NGM2YzllNzZlZDUifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L207-L223",
"version": "repo-lines-v1:sha256:bb65a8050531c288646a62d024e2c5ce82632ce10e8f598b6d9de35f3de1606f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxYmE0NzE5YzgwYjZmZTkxMWIwOTFhN2MwNTEyNGI2NGVlZWNlOTY0ZTA5YzA1OGVmOGY5ODA1ZGFjYTU0NmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNlNDNhMjAwNmYyNDA5MjZmMDAwYzdlNGI5MzIxNjY5M2MyNGRkZjU3MWQ3YTM3MDRjNGU1MmM4MWI1ZjBkZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzOWVhMmE5NzQ2MjU5N2MwNmU3ODEyZDZmYWRkNzJkMTNmMTYxMDliYTBkZTgwOWQ3MjRlM2E3NTQ1ZjZhNzkifQ"
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L235-L250",
"version": "repo-lines-v1:sha256:f8c236519e8486d9e23370a1125780885a560563104317d8b0667fde12b5c048:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUzYjE5NGU2YjQ5ZWRkNTYzZmFiOGI5YjcwZTYyNWJiMDg0ZWFiMGYyNTVjOGJhYmNlNjBmMzExNWU4OGE4YzMifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L64-L106",
@@ -138,11 +138,15 @@
},
{
"id": "claim_54a92b4e0f4b4678a15dea08e22fd005",
"statement": "On macOS the last window closes the app only when menu-bar metrics is disabled and metrics is not keeping it running; a quit request rechecks pending SFTP edits and lets the user cancel before beginning termination.",
"statement": "During Debug tests closing the last macOS window does not terminate the test host; otherwise last-window termination requires menu-bar metrics disabled and metrics not keeping the app alive. A quit request rechecks pending SFTP edits and permits cancellation before starting shutdown.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"resource": "repo://TFM/App/TermindApp.swift#L351-L359",
"version": "repo-lines-v1:sha256:72b0ea3d0ed1f3a746b2322cc7dfcf974afdc9cce02dda03d97e5862dea07ce9:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZjYmYxYTMzZmU5ZDUxYjBlZjQwNzYzMzljYzEwMGFlMjBlOGFiYzk2OTZlMzk4NjBhY2JmNmU1YWQ2ZTQ4ZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDYwZjQzMzI5NTZmNTMwOGY0NTY4NDJjNzExOTFhOTAyZjBkZWY4OTQyNGQ5M2MwZTExYzBhMzZlMmM1Njg2MSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjc3ZDhiZmVlYmRjZDdlZWJlYWRkYzZhMjNlNjNiN2JiOTQ2ODg0ZmMwZjUxZmEyNzE4NWRlMDYxMDMxMjg1MyJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L420-L452",
"version": "repo-lines-v1:sha256:209641db46bb153b0476bd566ee4d717edc93bb27063d85095bf219df72b7583:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliOGJlZDVmYjA1YjU1Mzk2MGFiMDVlYTU4ZjI2ZDA5MGQ2MDY1NTE5ODkzZGNmOTllZmQ5ZTc1NGQ3Y2VhOGMifQ"
}
]
},
@@ -156,7 +160,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFMTests/AppTerminationTests.swift",
@@ -209,10 +213,78 @@
"version": "repo-file-v1:sha256:632f6d657005b76fedd90a1e9c7d1f76a878dd5b8025fd4cc066d89f7234ce42"
}
]
},
{
"id": "claim_0187d73734334572b7b620cec0bf0337",
"statement": "The Debug macOS test host launches the real app but suppresses automatic main and external-auth windows unless TERMIND_WINDOW_TESTS=1 or a screenshot demo is active; it disables main-scene restoration during tests and screenshot demos, while focus-changing tests independently require a visible-window trait opt-in.",
"evidence": [
{
"resource": "repo://AGENTS.md#L42-L42",
"version": "repo-lines-v1:sha256:825a259b0fc873bd80b8a95ec1455eb28acf00cd15c03dd17d94e8bee428513c:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTczYTI2N2E2ZGNmZTczN2MyODUyYjY2OTkyNTViNWZlMWViYjYzMzVlZmZiYzgwZjA3ZWE0ZWExZTBhNzdlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjc0N2NkNGE1NTI3OTAxN2Q1ODYxMzE3ZjlhZDcwZWY0ODIwZTFiOTAxYzI4MDFhYjE1MTdjZGI5NjhiZjliYiJ9"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L14-L33",
"version": "repo-lines-v1:sha256:25a8c6dff46ec83a0b40c47dd446a1d70c15967cf565eb5ac2ccc23b9210ea1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhMmRiNjZmNGE1MzI1NzVkYzUwZmJjOTFjZjRiY2E4YjE1ZDdlOGQyYmU5ZjVjYzE4ZTA2NjI2NTljMGE1ZjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwNGE1NDQyNzMwZjkzNjk5ZjI1YzU0MTNiZDc0NTViMzZiYWNiYzNkMmVmZTU3MDA0MmFmMTdhNDU5OTUwNDMifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L196-L239",
"version": "repo-lines-v1:sha256:333120a2044361002eece5704e67f3457d94c141f098be4a406cbf62b276d333:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwNTgzMDJjZDFmMDQ4ZTE3MzU1MTUxODA0NzRjYmI4M2YwZjhkZDNmN2I3ZjUyODI4ZDU1ZmUxYjg1MmIxOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ0MTA0N2ZkYjNiOWIzMTYwZTU0NWEwOThlOGJhY2E1ODA1YTJlZmFjNGI3YWRkNmYxM2IyNDg4NWJjNmY4ZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjZGEyMmE4ZWYyODNjOGFmOTJjZDlmMmY2ZTA4MzdkODg4MjdjYjBkZGM2OWNlNDFkMTAwZDFiOTdjYWM5MmMifQ"
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L12",
"version": "repo-lines-v1:sha256:647fdf978ecd85719df899c592ebd2386dcf8c24b7371545e9ab0dcf3e0402df:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
},
{
"id": "claim_b528e73c08f746a39a8731af370991ff",
"statement": "RootView registers each window with the shared AppModel and publishes a focused window value while its own WindowModel owns navigation and workspaces; switching destinations preserves mounted workspace native views.",
"evidence": [
{
"resource": "repo://TFM/App/RootView.swift#L194-L213",
"version": "repo-lines-v1:sha256:f02230c1b5e2bf5f434b78334c147ac1c4d41d0886ec8c79fb3019e4d3ebeac2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBhZDFjODhkMzAwYTM1MWU4M2RhYTc0YzdkYmQ4NmNlMDk1NDNjYWM4YWNlOWE3OWNkZWE2NTA4YjAxNTc5MTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyN2Y2Nzg2ODRlNDYxODQyZThlMDcwNTdiNmFlMDg2N2NkYmEyMjkwZGViM2VkODk1YzIwNTAxNDZkMDhhYTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkxOWJmOTM3N2ZiZmU5NWM3NWIxNThlY2NhMjMwMTRlZmMwN2ZkNzZjNmI5Zjk4NjAwNGZlNDcxNDk2OGRiNmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlMzE1MGI0MzY3YWExZTg4ZDZlOTQxNmMzZGQ4NDRlOTc3MmMzMjhiNTljMjY3NjdmZGRkNDA4MGUwNjUwMWMifQ"
},
{
"resource": "repo://TFM/App/RootView.swift#L6-L27",
"version": "repo-lines-v1:sha256:9e6dac71f6b9a7441a08f31ef7e8e440d18a1cf97a6bb9af9d010b39724aa881:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4NjljNDYwYmI1YjgzNGM4Zjc4YzhjMjEzMjAyNThiZWZjMGVmZGEzMTZmZTE2MzY0ODY1NzNhZDkyMGJmNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU3MWRhNzQzNDU3YzAzYTI0MDQ0YTE5NzU0NjBhNmM0ODk5ZTgwYjc1MjhlMzA0ZDMxNGQ2N2ZlNTVhNDE2MDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZkMjk5MDMyMTk5YjM3NTAwZDdiYmRhMTQ4OGI1N2YyNmFjYzUyYjgwZTA1MmQ2MzAzNmZkNmRiZGIyNzMyN2IifQ"
},
{
"resource": "repo://TFM/App/TermindApp.swift#L187-L203",
"version": "repo-lines-v1:sha256:a7d70070584bd66d911f3ae3eaade025c65085c42818ea1cb9bf1b2a0d34d4ae:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxMDk3ZDRjZTdkZDAyOWU5OGI2YWFkMjViMDFiYzEzNzhjOTdlMzA5YmRjMDY0YTM0ZTI2NTQ4MTFmMTgxYWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwYWNiNzk5ZWEyMjY2MWRjODkyYmE4MGY5ZWIyN2RiOTAwYjVkYWI2Y2E3MzU5NzBkNWYyZTdkYTZmOTdlOTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQwMmQ5OGU3M2M3ZmQxZDQ4ZjUzNjdjZmY5NGFlNGYzNDlhZTYzZmIyMWRiYzkwZmYxYjZhNDViYjNmOWQ5MzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYxYjg4OTkyYTk4Y2Q1MTZkNTQ0MGMxYTE1NTkxMmJhZDcxODRiZGE0YWEwYWNmZDRkN2FjZGQ4ODM4ZmEyNGIifQ"
}
]
},
{
"id": "claim_2baa07e628804de49c78d71d67707aa8",
"statement": "App-facing copy is shared through TermindPresentation/Strings and manually maintained string catalogs; catalog edits require normalization and both presentation-copy and Chinese localization checks, and simplified and traditional Chinese translations must be finished with changed English copy.",
"evidence": [
{
"resource": "repo://AGENTS.md#L48-L69",
"version": "repo-lines-v1:sha256:26697577d9457afd4d5953ff5464ff3ce8419e303deb7f51ea1d9644abdfc2ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdlYjZlZDYzN2JlNjgzYzc2MTJmNjc3ZWE5ZTFhNTZiOTY1OTllNzcyZjZkNzY5MGI0MjM3NDBjZDE0YWZmZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg0NTE4ZWQ0MjVmYWVjYTU4MTRhMWMxMDE1NGYxMzI4MThlYjNlYzBiNmU4Mzk4ZGY0OTRiOGFkZjdjM2EyNDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4NmYwZmMyNmM4NWViY2IwODgwNDgxN2JiMGQzZGJkN2EwOWE2MWE1N2RhOWEwNTk3YWFjOWU3NWQwZDc0OTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlZGM0MzMyOThhZDU4MTI5ZWUwYTg4NTJjMTNmNTI5MjBkYWFmOTRhOGM2NGE0ODcxZWVlZjQ2ZTEzMTVlZDIifQ"
}
]
},
{
"id": "claim_fe774ac0ecb245ad83a3758899fa9637",
"statement": "MobileAdaptiveLayoutTests is serialized but does not use the mobile UI environment gate, unlike opt-in mobile key-window integration suites; narrow nonparallel runs are appropriate when investigating its process-wide UIKit fixture.",
"evidence": [
{
"resource": "repo://AGENTS.md#L46-L46",
"version": "repo-lines-v1:sha256:20f70f81c29f72ceb3b8c0d0ed710e433bbc08043f50f8fa17d7544dbd06708d:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjc0N2NkNGE1NTI3OTAxN2Q1ODYxMzE3ZjlhZDcwZWY0ODIwZTFiOTAxYzI4MDFhYjE1MTdjZGI5NjhiZjliYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L1-L12",
"version": "repo-lines-v1:sha256:735aeb1ae7990f7a990b773d9e676fd70275a5136e98a7624ffd794b84a34d95:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxZDIyM2ViNzYwNDc0MTY0MTMxNmYwZTgzMmExODM1ZTc3MzhmNzllYmU5NTliN2Y2MDU4ZWUxYjg3NDM0MWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjOTBhMjQ1NjkwOGRmYjQ5MzRjMTkzMzMxZTc5YTZkYTUzNzk3OGM0ZWJkMzY0NzAwYzU1YTgwM2Y1ZTQxNTciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjowLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI2OGZiMDhkYWQ0M2JkYWZhZmVmZjYzZGEwMjA2Y2Y3YzBlZTUyOWI5NmQyZDcwZGZhNzlhOTk3NzQ4YjcyYmEifQ"
},
{
"resource": "repo://TFITests/MobileEditorToolbarTests.swift",
"version": "repo-file-v1:sha256:b7bdc9c7e0f80d81f6610283c947786cfc0f0d13dc06ddd683a4240e1236b38a"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:bd374d594e69582542f2b267631be92bb7c5d0c89c99882257f71531e17a7447",
"pageVersion": "sha256:59829b8d5e54cff352e757dfa8ee42e5f875587624a61c6a6ab4b7e0f56d505a",
"claims": [
{
"id": "claim_b7fbd64158554b8b8ca80a0a613b3bc3",
@@ -18,11 +18,19 @@
},
{
"id": "claim_46317f2e2a1c469cb75d414d61222c34",
"statement": "ArchitectureBoundaryTests protects import and model ownership, rejects local AgentKit type redefinitions, and checks that all three CloudKit coordinators retain the shared safety gates while the lifecycle stays independent of SwiftData and Persistence imports.",
"statement": "ArchitectureBoundaryTests enforces module-specific import and concrete-construction rules, keeps SwiftData models and repository declarations in Persistence, guards selected AgentKit and presentation type owners, and checks CloudKit delegates retain shared upload/quarantine gates while the lifecycle stays independent of SwiftData and Persistence; these source-level checks complement runtime safety tests.",
"evidence": [
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift",
"version": "repo-file-v1:sha256:cba31c98549c0bb9eee68a82b0924fa9c6433e6d9a37e82b549af9432e2f2757"
"resource": "repo://FrameworkTests/CloudSyncSafetyTests.swift",
"version": "repo-file-v1:sha256:603f6e77ab33461d78203254b0746011e57d85070aa095fe60cf525ae9ad9dd7"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L137-L274",
"version": "repo-lines-v1:sha256:c60b429e689ffea7a9338292e5921a0c87f97067aeb0b9a7dfcf6942d0b6559e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTM4LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIwYzliZjYxNmRjZjUzOWEwZDU0YTEzNmM2NjRjNTNhMjU5ZWZhZDljZjVhZmE2OTA2OWZhMzhiNTMxOTk0NGM1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJhNDdjYWI2Nzc1MTJkY2VkNGEyMjBlZGRkODYzZWQxZTQzNTkzNDZkYmE5OGQ5Y2I5MGQwZmY5NjI4YzNiMzRhIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI2NTkwOTE3MGMzZWNiYmJiYmQyM2ZiMWVlM2VmNDQzZDI5M2RkOWYzMDQ3NDYyMWRkMzFjYjA1YzhkNjRmZjZlIn0"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L64-L105",
"version": "repo-lines-v1:sha256:228916a398677a68a14b8bcc405a7361bff7148080e8533610db6433dc754938:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc2M2YzMDBmMzYzYWM2YzU2YTViYTU1OTJiNWNhM2ZmOTc2YWEyNjQ0OTIyOWRkN2YwYThlMjRkOTkxNGYwNDQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4NWJlNTRjNmM2MGZmZjQ5ZTllOTU1Mzg1YjMzZTc4ZTRkNGQ4ZDJkNmUwMWQzMzJkNjhiNjg3MTA0OTkxYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ"
}
]
},
@@ -170,7 +178,7 @@
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L11",
"version": "repo-lines-v1:sha256:b8b2903d1009b119d2daa9cc5915fe34eab19cf61490b33adc02693393f4c95f:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
"version": "repo-lines-v1:sha256:647fdf978ecd85719df899c592ebd2386dcf8c24b7371545e9ab0dcf3e0402df:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
},
@@ -455,10 +463,118 @@
"version": "repo-lines-v1:sha256:648c396e63e3d377561261d0c495b200302fa5bdc075fbf3ce475869164f9b91:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTYxYjE0YjExYzI1ZjUyYWEwNzM3NmExMWJkN2VjNzgwYjJmYWRhZmFmMjAwMGViNWVmMzYxZDk0MWUyMDEyZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzYwYjg4YTA1ZDViNTM4NDc2MDIyOWJlNjA1NzJmZTYyYjFjMjljZGM1N2VkYjVlNjk1MWRhYTRmZDQ2YzgwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmRlNTQ0YjkwZjFiM2YxMTNhNGFhNmYwNjQyOGU5MGUwZDk1NTI0NWI0Yjk2N2E0ODhmZDEzZWU1OTc1ZDk5MSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWFlYWVmZGU3NTJmMmViMjYxZDMzOTY2ZmZiNzdiYmI2NzhlMjU3ZGI4YjlkY2ZkYzU4OGU0ODNmZGY5ZWIwMyJ9"
}
]
},
{
"id": "claim_86630e75723449c7914efdb16e333289",
"statement": "The SwiftData repository ownership check uses a SwiftSyntax-based script to distinguish declarations from references and textual decoys; its regression tests cover both positive declarations and negative comments, strings and references.",
"evidence": [
{
"resource": "repo://Scripts/swiftdata-repository-declarations.sh#L1-L16",
"version": "repo-lines-v1:sha256:203aa343c49de9718ed1481fc0c5dd047202bebb7559f3a8a515b9e9ace96763:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4NzVmOTI4NTQ2YWVlNzg1NWNiMWRiOWFmYzhhYjNmMWE4YTM0ZDQzZGU1YmJkNjJmNzA3NmQ3YmE5ZjM5MTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU3MTU5M2U0ZTRkNzMxNGJhMjI4ZmIxZDRiMzRlOTE5MTkxZWQ5MTVmODAzMzQyZDEzNzViYmYyNTI2MzkwNDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjowLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L252-L322",
"version": "repo-lines-v1:sha256:5f94dd59a3da5149ef5ba7a1733d15939468070f53ef49fbf29e604cc56d3287:eyJzZWxlY3RlZExpbmVDb3VudCI6NzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0NmIyNmIyZWI2YmY1YjdkNmM4NjgzM2FiOTEzYmEzNWZjZWMwN2E1NmUyNzFhNmQ5MzVjNDBlMjUyMTU4MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyMzk2YTZjMGFlNGEyMDI0YjE2OWE0NWY3MjdmZjYwNWE4NDI4NjdkODJlYjJjOTNkYmNkNmVlNDg4YmExYWEifQ"
},
{
"resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L372-L412",
"version": "repo-lines-v1:sha256:5752916d8687cf48132800042cd2ba6cf5d91670ab9f1d3d51e4b368454f175f:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA1Njc4MjE1Mzg3MWM5ZTExZTk3OThiMjExNzY1Zjk4MGY0ZTBkMTVhMGRkNmJkNzViOTQ2MjAyYzJlZmFjYmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjEzNWM1YTIzNjU4OTFkZDY2YTg2OTgwODY5YjEzYjU4NTNjNDVhZWY4Yzk4YjYzZmQ0NGU3NDJiNmZkZmI0ZTkifQ"
}
]
},
{
"id": "claim_d6d2ff72d3b54a13a944d55f71dd0ff5",
"statement": "Visible-window opt-in applies to macOS tests that present windows or take focus, not all renderers: the serialized macOS Pro paywall fixture captures offscreen NSHostingView content in a borderless NSWindow without activating it, while ChooserInteractionTests opts in before making its window key.",
"evidence": [
{
"resource": "repo://AGENTS.md#L38-L46",
"version": "repo-lines-v1:sha256:070213e98b52cec4fdee409349c32e94d42a6a1c41a2f6b5e43523d08e46b11b:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTdmYzk4NmVmMDFlZTVmNThjNmYxZmEyNjViOGE2NDEzMTE2OGY4YWE1OTkzZDc4ODZkOTZjNmUxODk4OTQzMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDFkYTg3Nzk4Y2M5NTc1N2I3NzQ0NThlYzQ5Yjg0MWRjYWMzODA1MWQ5MjljZGI5ODE5MGJiMTdiMjdkZmQ4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://TFMTests/ChooserInteractionTests.swift#L12-L30",
"version": "repo-lines-v1:sha256:7b4127f9eac31e0a0aacb435b24be7dec37c0f52f9fdaa175298488753380881:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU1Y2RiZGUzMzQyNDE0YzU2NjcyYTRmZjdlMDNmYjZkMmI4OTMzNjY1ODVhOGI2MGFjMTkyYjg5NDNhNjJlMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE1MDRiYTgzYjUwZjhiMzg2NTE2MDk2ZTJjY2Y0MTc4NTljMWRlYWYzMmM5NmMzNzA3ZDYxM2QzNGE0Y2FlMjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NTJjOTcxMTBhMDM1ZjNkYjQ2MWIzM2VjZmQ1MzAwNzk5ODMxZWJlYjdlMmEzOThkMzJiY2ZmNTJlYjFlNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUzM2UzOTdjNzdmNjhiYjk0YWJhNGY1NzRlMDg2OTU3ODc5ZTNjNGNmZjE1OWRiNmNkMmVlMDcyZDBiOTE1NjAifQ"
},
{
"resource": "repo://TFMTests/ProPaywallRenderingTests.swift#L7-L60",
"version": "repo-lines-v1:sha256:0bbd01cee237b8a650f38d05088fcda81a0e45ce8b2ce8d672ec11a0199b11cf:eyJzZWxlY3RlZExpbmVDb3VudCI6NTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2NmE3Mjg3NWNjZDc4MTM5NTk4Y2IwZDM1OGI5MzczZDM2ZTlkYTQyMDE3NzA4MTkwZGE3M2JmNGE3Zjk1NzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyOWM1Zjc3YjVjZTI0ODU0M2UyMGFjOWRkZGFhNjU3OTY5MzZhMmM4ZDE2N2NjMzRiZGM1MDM3N2RhYjg2MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ"
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L12",
"version": "repo-lines-v1:sha256:647fdf978ecd85719df899c592ebd2386dcf8c24b7371545e9ab0dcf3e0402df:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDZkYzRhNmI2NzJiZTRkMGI5ZjA5ODI5ZGNkMzgyYzEwMWJhMWMwMGQxZjYzNTY3MDI4OWFiNWE1NzBiNTYzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNkOTM2OTExYzY5MzE5OTAxOGFmMTI5ZTA3Njg2YjY5NjgyMDZmMjk0MmY2ZGViNzdkNWJjMmQ0MGI1ZTJhMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9"
}
]
},
{
"id": "claim_94dd0d711f1d47e48c224de19ca20ab9",
"statement": "The mobile Pro paywall rendering suite is serialized and opt-in under TERMIND_MOBILE_UI_TESTS=1 because it creates a key UIWindow for its UIHostingController and restores the previous key window after capture.",
"evidence": [
{
"resource": "repo://AGENTS.md#L46-L46",
"version": "repo-lines-v1:sha256:20f70f81c29f72ceb3b8c0d0ed710e433bbc08043f50f8fa17d7544dbd06708d:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjc0N2NkNGE1NTI3OTAxN2Q1ODYxMzE3ZjlhZDcwZWY0ODIwZTFiOTAxYzI4MDFhYjE1MTdjZGI5NjhiZjliYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9"
},
{
"resource": "repo://TFITests/ProPaywallRenderingTests.swift#L39-L77",
"version": "repo-lines-v1:sha256:6886a9b67355d62325cdc4c249185f62302c50b9e340d217bc75f80d85567878:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIzYjE4MGJjNDNkMDAwMjlmZTY2MjU0Y2NiMjFjOTRkYzY2N2I0ODhmNWFmYzA3YjkwNjNmYjc0OWYyZDlhYzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ3MGMxNjI2NDZiYTYzOGQ5YmE5ZjQyYTdlYjQ4MmI4NzZmZDMyODgxNWNiZThmOWRkMTk4NzA0ZWI5ZjA1ZjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRjZjE2YzhlMmM0OGNkNDA5YzJlZTIyOWUxMGE0NTlkZDE3MTgwYzlkNWViNzNjYTVjNDdmZmYyOTVkZDhjOTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmM2UzN2Y2NzljZDY2NzAyYjcxZjNmOThkN2IyYjYyZTAwMGEzM2FkYjQ4OTE1NDdjNjZhOTJkNDEyNGIxNzkifQ"
},
{
"resource": "repo://TFITests/ProPaywallRenderingTests.swift#L7-L13",
"version": "repo-lines-v1:sha256:d3dc005bdbc77011cd18847115638fb47df66d460d910fbca50357edb3b43bd3:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiN2EyN2M0ZGNkNTRlMGMwMjliYzRkN2MxZWFlOTY1N2I5NzAxY2RlODE2NDdjZDVkNDI1NDAyYTBiNTJmNzViYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZDgwMjdlMTg1MzEyM2RhY2E0ODI1ZGMwMjY3M2Y1YTE0YTY3OGE5Mjk5ZjA0OTk3ZjExYmZiYTM1MTg2ZmVmZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiY2M5M2M5YjMzOWUxNzE1ODVkYWY3NDgyY2U5YzViZTI3OWNjMTNlOTUwYzU2MjZiNTc1MzcxN2EzZGJmMDg0NiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTkyOWI0OTVjNzFjNzllMTFjZThlNTEwMGE5MzE5Njg4NjExODk4OTQ4MzI5N2VjMDc1NmExNzBjOWE0MTYwMCJ9"
}
]
},
{
"id": "claim_9db7395c8eaf4a9ca8a0794ed2c9628f",
"statement": "The platform Pro paywall rendering fixtures inject presentation values instead of contacting StoreKit and check shared content across free/subscribed status, English and Chinese locales and dynamic type sizes for horizontal overflow and usable scroll area; they record screenshots, but do not test purchases.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPresentation/ProPaywallContent.swift#L17-L54",
"version": "repo-lines-v1:sha256:35cbab506abd20b81e644657d7ecd47b9863025540a340989939cb3f0c6e5955:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVjYjc4YTBhYmU3YWE5YTA1YmY5NDJhYWZhMmQ0Y2Y5NjQ0ZTVlZDc4MjAwYTcyZTYxY2EzMDM1YmU5ZTc2ODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU0OWY1YWI2MDUyNjMwYzk2ZWRlNjBlODQ5NDQ0ZTkwYTk3ZTM4ZjI0YTBhMzczZmRjOWUxYmUxMDVkODQ5OWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc1YzZjYTI4OGM3NzFmN2NlMDJmZWFjOTRjNTMwNDJkN2QyMDljZjA0MTk4MjcxMGExN2RhMmNjYjgyMGNlN2YifQ"
},
{
"resource": "repo://TFITests/ProPaywallRenderingTests.swift#L7-L77",
"version": "repo-lines-v1:sha256:e97a64821b0a86e3366b122874974d6490fd4dbc998965d0b6c2a3472f04eb05:eyJzZWxlY3RlZExpbmVDb3VudCI6NzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdhMjdjNGRjZDU0ZTBjMDI5YmM0ZDdjMWVhZTk2NTdiOTcwMWNkZTgxNjQ3Y2Q1ZDQyNTQwMmEwYjUyZjc1YmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ3MGMxNjI2NDZiYTYzOGQ5YmE5ZjQyYTdlYjQ4MmI4NzZmZDMyODgxNWNiZThmOWRkMTk4NzA0ZWI5ZjA1ZjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNjOTNjOWIzMzllMTcxNTg1ZGFmNzQ4MmNlOWM1YmUyNzljYzEzZTk1MGM1NjI2YjU3NTM3MTdhM2RiZjA4NDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmM2UzN2Y2NzljZDY2NzAyYjcxZjNmOThkN2IyYjYyZTAwMGEzM2FkYjQ4OTE1NDdjNjZhOTJkNDEyNGIxNzkifQ"
},
{
"resource": "repo://TFMTests/ProPaywallRenderingTests.swift#L7-L60",
"version": "repo-lines-v1:sha256:0bbd01cee237b8a650f38d05088fcda81a0e45ce8b2ce8d672ec11a0199b11cf:eyJzZWxlY3RlZExpbmVDb3VudCI6NTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2NmE3Mjg3NWNjZDc4MTM5NTk4Y2IwZDM1OGI5MzczZDM2ZTlkYTQyMDE3NzA4MTkwZGE3M2JmNGE3Zjk1NzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyOWM1Zjc3YjVjZTI0ODU0M2UyMGFjOWRkZGFhNjU3OTY5MzZhMmM4ZDE2N2NjMzRiZGM1MDM3N2RhYjg2MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ"
}
]
},
{
"id": "claim_191f055b66394fe3bc4142cde1fdf59b",
"statement": "Shared paywall tests separate access and purchase availability rules from offer formatting: ProPaywallPresentationTests covers status/ownership and missing-price or processing purchase gates, while ProOfferPresentationTests checks trial duration, billing units and localized offer text with synthetic inputs and no StoreKit transaction.",
"evidence": [
{
"resource": "repo://FrameworkTests/ProOfferPresentationTests.swift#L6-L150",
"version": "repo-lines-v1:sha256:359f4ac6169cbc9002320d104e496817c4f25b92d55bdaa677859a53233e0463:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQ1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI4YzYzZWUyODNkOTE1MTk3NDBiMTExOTE0MTQ3ZGEzYzNjMjc3ZjEyODRkZjkzOTBkZDczZjZlZjJiOTQwODdhIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIzMjljNWY3N2I1Y2UyNDg1NDNlMjBhYzlkZGRhYTY1Nzk2OTM2YTJjOGQxNjdjYzM0YmRjNTAzNzdkYWI4NjEzIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwMzlmMDBjMGUwNDljMTNhNzJkM2Y5ZTBmYzliMWE1YWE1ZjE4N2EyYTZhYTUxM2MzNDA2MzcyMDdjNzRmYzA2In0"
},
{
"resource": "repo://FrameworkTests/ProPaywallPresentationTests.swift#L6-L89",
"version": "repo-lines-v1:sha256:2cac517c6e29b315636b8e7f83213a3cc503bc9c5b4837db26141b20727ed263:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkzMjJmYWE0NjA3YWQxM2Q4ZDhhM2VlOTVjMjQ0ZjViOTlmODFkNDVhOWE4NTc2Nzg0YWUxNTM2NGU1YjZlZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyOWM1Zjc3YjVjZTI0ODU0M2UyMGFjOWRkZGFhNjU3OTY5MzZhMmM4ZDE2N2NjMzRiZGM1MDM3N2RhYjg2MTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE4MDllYWE3MWRjNmZkZDE0MjUwOTY0ZjJlYTgwMjI2NzE0NWE1NDhhMDRjMmZlNjRmMTJlYzRlMjQxNzUyYWIifQ"
},
{
"resource": "repo://Frameworks/TermindPresentation/ProOfferPresentation.swift#L10-L54",
"version": "repo-lines-v1:sha256:4152465e31be5b3157292599779b5617789dd3ac4357bb6db1963c264aeb8760:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVjYjc4YTBhYmU3YWE5YTA1YmY5NDJhYWZhMmQ0Y2Y5NjQ0ZTVlZDc4MjAwYTcyZTYxY2EzMDM1YmU5ZTc2ODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQxMzhhY2VhNDZjMjMzMjEzZjFiZDc5MWEzMWQ5YTFmODMzOWE2N2RmOTIwMjQ0YWYxNjhlMWRlMmI2NzQyMjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNhNTEwYjNiYjBmYTRjNGZkN2I3Mjc0MWFkOWRjNzdkYzgxMWVmZWEwM2M0NzA2ZWY2YzJjMTFjZTBjNjg3MDcifQ"
}
]
},
{
"id": "claim_278bfb052af34e389b0cca2b311d1b31",
"statement": "Desktop and mobile Pro paywall views translate their access controller into shared ProPaywallPresentation and ProPaywallContent, providing platform-specific appearance and actions; desktop enables MCP server copy and mobile disables it.",
"evidence": [
{
"resource": "repo://TFI/Features/Commerce/MobileProView.swift#L13-L54",
"version": "repo-lines-v1:sha256:212373fc263345083ca3b5b3d8ee600d75600ce1437f08b2b518d6f27ec2abee:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk4MjFmMTM3MGVjN2JlMThlNDBlMWI1OGE2NGMxZGEzMDY0ZTk2NTUxZmUwMzdiNTE0OGJjM2JkZWI4MTliZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ"
},
{
"resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L15-L65",
"version": "repo-lines-v1:sha256:37082bec140bbc8fdecd8a3a0dd9d983c87d7d471fe4da8cb869ef65ec441b7c:eyJzZWxlY3RlZExpbmVDb3VudCI6NTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU2MTc0MGI5Y2FmN2I5NGNiNjM3MTQyODBmMjA1NDUzNWYyODY1MjMzYWM2NzBjM2YwNjFiZjkxNjZjYTMxOGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-24T01:58:11.184Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:0faf1be721afcf8b31f91b1eecaee9a38f8ef57809354348df75f81f1173aa02",
"pageVersion": "sha256:8f775546672e0828cfb5a48c814c06ccbf253e1a946a6abe96d13e04142679f5",
"claims": [
{
"id": "claim_ef9adaabb13c4328899d3e43b56b9fb5",
@@ -358,17 +358,61 @@
"evidence": [
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L1-L12",
"version": "repo-lines-v1:sha256:5430c3c8e5a1956b064f24f0c6d1340df4f71f4ad0614985b6dd8d6ed171e2cb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkYTliNzVmNjRiMTA2ZWI1NDRkZTIwMWY1OTkxMjJkNzVhYmM0ODNjNWIxNTZiYmE2YzA1YzBmOTU2ZGJjM2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjowLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
"version": "repo-lines-v1:sha256:d61c15f8e48112fa5f95e007d607a355e8769c69619ce792a7cddf388672002e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkYTliNzVmNjRiMTA2ZWI1NDRkZTIwMWY1OTkxMjJkNzVhYmM0ODNjNWIxNTZiYmE2YzA1YzBmOTU2ZGJjM2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjowLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L210-L293",
"version": "repo-lines-v1:sha256:420e5ea4ad979d3db1e12b580d6a970cdeee5ba6c4d048cf5d339f10b72c928b:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5NzE3NmZmODlmODZhN2U4MjkxYTZjODY4ZWQ2NTYzMTA3ODZhMmMwMmU1MjdiMmE1ZWI0MmM0NTllNzllYzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmOWIwMzZlYTA1M2VjNTc3Mzg3MTM0NTM5YTAwNzQ3NWQ1NGE3MDgxZmQ3YTE3NGMxZTQ2MTljMGUwZmJiYWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImViYWQyMmE0ZDU0ZmE4YmRiYjBjMTVjMTRlYjliYzdjM2IyZmZjODk0ZGEyZDg0OTlmYzIxZjBkMmIyZTc0ZGUifQ"
}
]
},
{
"id": "claim_bd0fc397962e4776a0a3c0dfb97173f1",
"statement": "Visible-window drag tests are skipped unless the test host has TERMIND_WINDOW_TESTS=1; offscreen Navigator geometry and payload tests run without that opt-in, while the single-click, native mouse-session and split-workspace tear-off tests are gated because they make a window key or activate the app.",
"evidence": [
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L13",
"version": "repo-lines-v1:sha256:6c50e1f862edd382ddceac73e1b1dde8b86d557bd530058778ea694cadacf036:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2ZGM0YTZiNjcyYmU0ZDBiOWYwOTgyOWRjZDM4MmMxMDFiYTFjMDBkMWY2MzU2NzAyODlhYjVhNTcwYjU2M2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjczZDkzNjkxMWM2OTMxOTkwMThhZjEyOWUwNzY4NmI2OTY4MjA2ZjI5NDJmNmRlYjc3ZDViYzJkNDBiNWUyYTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
},
{
"resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L12-L53",
"version": "repo-lines-v1:sha256:45502b4cb82ee47e91c5321578e0b829cdc073569607d61c16189572092876d3:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5NzE3NmZmODlmODZhN2U4MjkxYTZjODY4ZWQ2NTYzMTA3ODZhMmMwMmU1MjdiMmE1ZWI0MmM0NTllNzllYzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJlZWI4OWI3OTZlYjQ3NzczMmQ2NmNhMDYzZjdmN2JiZjNlMDdmNzZmZTc4MjRiMmNjNzZiMWRjODk4ZDE2NTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYxMTJiNTNkNzJiMWVjMTE0YzY4MDg3NmU1NmZlM2I2MDFhNDE1Nzc2YWYxZDI1MjlmN2NiNTA5NzViY2RkNzYifQ"
},
{
"resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L210-L293",
"version": "repo-lines-v1:sha256:420e5ea4ad979d3db1e12b580d6a970cdeee5ba6c4d048cf5d339f10b72c928b:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5NzE3NmZmODlmODZhN2U4MjkxYTZjODY4ZWQ2NTYzMTA3ODZhMmMwMmU1MjdiMmE1ZWI0MmM0NTllNzllYzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmOWIwMzZlYTA1M2VjNTc3Mzg3MTM0NTM5YTAwNzQ3NWQ1NGE3MDgxZmQ3YTE3NGMxZTQ2MTljMGUwZmJiYWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImViYWQyMmE0ZDU0ZmE4YmRiYjBjMTVjMTRlYjliYzdjM2IyZmZjODk0ZGEyZDg0OTlmYzIxZjBkMmIyZTc0ZGUifQ"
},
{
"resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L295-L387",
"version": "repo-lines-v1:sha256:2b121eae49ca13c02687dcaa64b06609d3d014e1cc8db3514211dc6736ac99fa:eyJzZWxlY3RlZExpbmVDb3VudCI6OTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4ZmRiMWE0ZmJiNDNlODMyMWI3MmU0Y2Y1ZmI2MDViMzJjMGRhMDlmMDVjZjQ2NjRkOTk1ZWFhYWZmZjk3YjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM2YWFlNmM1ODhlZTZlNzBiOTY4NjFmMGE4MWY1YzI3MzkxMTgxMGJhMTdmODMxZGIxMGJmNDQ1YTYwZWViMzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM4NmI0NDc2YjRiY2U3YmU2YWFkOWRjZmNiMTEwMjZhNzY0OTQ3YmRmNGRjNzQ2NDk1ZmVjNDAyYjc4MDA4M2QifQ"
},
{
"resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L55-L96",
"version": "repo-lines-v1:sha256:02061034f41d885cd2aab1df293e49405cef41086241d7fc4fc71a299f41a842:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiNmM5ZmU4MmRhYmQwNmFlMWEyNzRiZTY5MjlhYTg1MDdmMDk5N2UxNTIwMmU4ZmZkMjI2Yjk5OWMxZDAzY2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5NzE3NmZmODlmODZhN2U4MjkxYTZjODY4ZWQ2NTYzMTA3ODZhMmMwMmU1MjdiMmE1ZWI0MmM0NTllNzllYzYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFiNzc2OTE2ODQwNGI4ZDAwNTg3ZGNjODQ1ZTE3NmNlMGRhZjQwMDhlNTRjNWYxZjg0NDhlY2Y2YWYzNzVmMjEifQ"
},
{
"resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L96-L177",
"version": "repo-lines-v1:sha256:6fba3bef9775713845983f18e06271368b1656f81b829f467cfa73c73959f376:eyJzZWxlY3RlZExpbmVDb3VudCI6ODIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5NzE3NmZmODlmODZhN2U4MjkxYTZjODY4ZWQ2NTYzMTA3ODZhMmMwMmU1MjdiMmE1ZWI0MmM0NTllNzllYzYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc1MDFiZGRjMWFmMzZmYjk1ZmI2OWQ3MTA1MmNmMDJmZTJmNzU1ZTE0NTM2MThkOTMzZDNlZjNjYWMxZDUyM2YifQ"
}
]
},
{
"id": "claim_27ee248e02834d67b1f98cf736ba2a27",
"statement": "In Debug test runs the app suppresses automatic window launch unless TERMIND_WINDOW_TESTS=1 or a screenshot demo is active; this launch safeguard is independent of per-test visible-window gating.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L14-L33",
"version": "repo-lines-v1:sha256:25a8c6dff46ec83a0b40c47dd446a1d70c15967cf565eb5ac2ccc23b9210ea1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhMmRiNjZmNGE1MzI1NzVkYzUwZmJjOTFjZjRiY2E4YjE1ZDdlOGQyYmU5ZjVjYzE4ZTA2NjI2NTljMGE1ZjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwNGE1NDQyNzMwZjkzNjk5ZjI1YzU0MTNiZDc0NTViMzZiYWNiYzNkMmVmZTU3MDA0MmFmMTdhNDU5OTUwNDMifQ"
},
{
"resource": "repo://TFMTests/VisibleWindowTestTrait.swift#L4-L13",
"version": "repo-lines-v1:sha256:6c50e1f862edd382ddceac73e1b1dde8b86d557bd530058778ea694cadacf036:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2ZGM0YTZiNjcyYmU0ZDBiOWYwOTgyOWRjZDM4MmMxMDFiYTFjMDBkMWY2MzU2NzAyODlhYjVhNTcwYjU2M2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjczZDkzNjkxMWM2OTMxOTkwMThhZjEyOWUwNzY4NmI2OTY4MjA2ZjI5NDJmNmRlYjc3ZDViYzJkNDBiNWUyYTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-23T17:55:27.475Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:99d2b239428f25d840b99f415eab5ff6fa482e27820addafa7f175fb77fb805d",
"pageVersion": "sha256:79baf476eb5467b8d8b21e95dd285faa364f3ce83175ccf7f9598519a9df8f11",
"claims": [
{
"id": "claim_dc6281a3ccb7415ea961d1a954248647",
@@ -353,10 +353,82 @@
"version": "repo-file-v1:sha256:f7f74f7c300cfaaf1eacdb9f9fb162aa6e9fade3efbb8d6142476d53e4e28b59"
}
]
},
{
"id": "claim_9c12b6015a734671b748f80e1ada2d0f",
"statement": "The desktop Sync settings route renders `SyncSettings`, whose master toggle requires Vault-sync Pro access, reconciles app-wide access and attempts custom Host password migration to iCloud Keychain when enabled; the Vault selection also attempts that migration, while category selections independently set coordinator enablement and expose status, retry and account-merge controls.",
"evidence": [
{
"resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L151-L190",
"version": "repo-lines-v1:sha256:66a0ed585ba5eda17bb4962ba4bcb0bbaff51dda76dca39a0f59351bfa108eb2:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjZDE3ODg3ZDhiOWFjYjJlZjc4ZGRkZmJiNTJkMWEzM2UwZWI2MDRlMmU1NDczMjI5OGZhNmUyMjgyMjc3N2YiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ"
},
{
"resource": "repo://TFM/Features/Settings/SyncSettings.swift#L6-L107",
"version": "repo-lines-v1:sha256:cec04eeaafa3c1f73a9f9162fd52675bc175b4649c606ff17bf1ce9dc237491a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJkMjIyODE3ODM0MzU1ZTY3ODBkYTZlMzE2ZTAxYmEwNmIyOWViYjBjODRiM2I1MzAyZmNjOWFmZDQyMzBiNjBiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3ZjgzMzJmYTk5NjExMTAyYmI4MjkxM2E2YzAxZWFlOTdkNzkzMjdiZTU1YmU2NTg2MTAzN2NmNDhkZmFkOTIyIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MCwiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlM2IwYzQ0Mjk4ZmMxYzE0OWFmYmY0Yzg5OTZmYjkyNDI3YWU0MWU0NjQ5YjkzNGNhNDk1OTkxYjc4NTJiODU1In0"
}
]
},
{
"id": "claim_9b99b2f9d0ab4c8bad272d0bd8888d7a",
"statement": "V28's local Host model stores SSH connection properties as `port`, `identityID` and `charset`; the V28→V30 lightweight migration retains those property names as SSH fields and supplies default-disabled Telnet settings, while the live Host projection supports separate SSH and Telnet profiles.",
"evidence": [
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L757-L775",
"version": "repo-lines-v1:sha256:54515ad245652519758936aec589aab32d1e2640f4f321f4d1e31335367860ae:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwNTY5MjAzNmI4ODhlYmYzYjc5YjEzNWU0MDMyN2YxYTFhNzFlZjY1MWM5OTI3ZjE2MWQwNzFmN2Y5MWMzMDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU1Y2Q2ZWE5MDNjYmNmYmRiMmViNzE3NjY5ZjViMzY3NmUyMTlmMmZlZDc4YTY1ZTNkNzE1MTE1NTI1ZWRhOWMifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV28HostModels.swift#L7-L35",
"version": "repo-lines-v1:sha256:48595ba6a10953470c8fa461f76ad38ded5dd2673a3af0ed5c5fbcdee3ed40fd:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ1YmNjZjg3NmJjMDFjZDNmMDU4YWZmZTBjZWJiYzU3ZTkyNTBmMGM5ZWI5ODlkMjAxODM0NDExOTFkYTk5NzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjMzhlN2E1MTJhYWNkZmM1YTZjYjAzZWM4NDBmODkzZGE2YzMyYmJiZjIxNjljMDhlNDJhNjViMjQ3ZDdhYTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkYTMxMmZlMTU1NzA0MzkzMzRiYzkwMGRiNDQyOTUzNjJmMzg5ZjVjNmVkOGU0MTViODIyYzBmN2YwNDJjNDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5NDIxYWM2M2VmOGRjMzlmNDZjZmZjNzllZDFjMDQ2ZTg2MmUwMmE1NGY3MzRhYjYxYTJmMmRjZmE3YTNhODAifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV29HostModels.swift#L132-L249",
"version": "repo-lines-v1:sha256:8d877b4b722f723e8ee6fe53c6d05397973686efc9859a46518cd8c4eeacf50b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE4LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJhMmQ0NjhiYjc5MjE0YjE4ZDE2MjAzODVjNGFlZjI1NGFjMWJjZjgyOGM5ZjgxY2IwZTViM2M3N2UzNTVkMDY0IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJiY2IyZTFhYWQ5ZDNmZDlmOGQ1Yjc0ZDM2NWI0ODgzNmM5NzRkN2Q2MzY3YzU3NDBlNzcwZDhjYWVjOTg1ZDdiIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIxOWU3NjM1NWNmMTE5OTQ4MGMzZjk5ODM2YjE0ODZjODQxZDg5MWZhYWQ5MDRjNjA4ZTA5MzAyMmQzNzU3YWVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJiNGEzNjVhOTBlYzExZTkwNDMyNzUyY2Y5Mzc2ZWM1ZWQzNmI4MGJhNWU4ZTY4NTRmY2Y5ODk3MGQzMDQ0NDY5In0"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindSchemaV29HostModels.swift#L7-L29",
"version": "repo-lines-v1:sha256:df7f6bde434ad4e9f105dfa907684aedea0fe4acc2f3139c7915f165a53a52e3:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJlNjUwOGQ1YTdmMTg4YjhiMGU0ZjhiODFhNGJiZjgzY2RjYmNjY2JlMWMzMWQ2MThiNjQzZGYxYWM3YjFmNjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2NjU3ZjYwMzUzNDE3ODFlMGQ5MmJmNmUxYjlkNDIwMWUxYTUxNzIxZjk0YjY0ZTg3ZmY3MjNhZWNjMDAxMWQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkYTMxMmZlMTU1NzA0MzkzMzRiYzkwMGRiNDQyOTUzNjJmMzg5ZjVjNmVkOGU0MTViODIyYzBmN2YwNDJjNDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMzYjhkZWYyZGM0MmU0NGNhNzM3ZDg2ODI0ZjhmZDY4ZjNlMDdiZjk0NGNlMjBlOGI5YjlhZDM0MjAzMTRjNDgifQ"
}
]
},
{
"id": "claim_16ad59a234184f1e803b341427176e24",
"statement": "The local V28 Host migration does not itself change the Vault cloud protocol: `HostPersistence` loads migrated Hosts into a Vault snapshot and bootstraps/diffs its journal, while Host Vault records remain V1 envelopes; Host Codable retains legacy SSH wire keys and uses backward-compatible defaults for newer protocol fields.",
"evidence": [
{
"resource": "repo://Frameworks/TermindDomain/Hosts/Host.swift#L314-L385",
"version": "repo-lines-v1:sha256:99634d72db7ba2f0b13ed419c26184fa98a8d03a8b7254e5c85e410b4188115c:eyJzZWxlY3RlZExpbmVDb3VudCI6NzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM2OTdjOWNjZTZhYWY4OTM2Yjk0NTVhN2ZmOTA3MWMxNjNjZjNmMGViMDQxY2JmZjViOTQ3YWRjYTBkNTVlOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRmMzY0NjYxNThlYWRlMWYyMTBiMjg1NmRiMjc1ZmJlNDViNTVlZjhmMDdmMDRjNmZhNmFlMDFiNDcxNTdhZDciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMzYjZhNWZiOTJlY2IwODRlYjcyMTliYjZmNWJmYTY4YmNlMWM4ZGQwNDNlNjU4ZTI3NDQxOGJhNTNiNzdlMTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwZGVlZDg0Y2E4MGNhYjQzNGUxZjY0NDAyOGExODBiYTRkNWFmMTJmYjE0MDgxOGQ4MWEwNDdkNDhkMzAyY2QifQ"
},
{
"resource": "repo://Frameworks/TermindDomain/Vault/VaultSyncTypes.swift#L3-L35",
"version": "repo-lines-v1:sha256:814424b4967ba512411958dddd5c7010c1eb626878378f92985dc689f4c4a98a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRkZDRjNDNmZWQ0YjliYTU3ZWM3YjlmYzQwMjllNTdhY2Y4NDBkOWIxMTdlMzRmYTlkNjk1ZTE3OGY2Y2ExNzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliYTgyZmY0OGFjMWI3MTg1OTE5YjQzYzMzYTc2NzNlMDMzZDAyNmUyNTc2ODU5NTUxZTcxZDIxMDY0Njk3ODYifQ"
},
{
"resource": "repo://Frameworks/TermindDomain/Vault/VaultSyncTypes.swift#L76-L132",
"version": "repo-lines-v1:sha256:73ec843bd056029e2448b7853227d5691576e736f23411f1688507ffcff2c6b7:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc3NmE4MzA2NTBjOTkzZWQ3NjE4ZjBhMDhmYmZmOTU3MzQzY2FlNjIzNmJmNThmNjMyNWRkNWRiYTJjNjkxMDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmYzVkOGVjN2Q1M2E5MTkzMzI1NjYzZGMwZTdjYmZiZDgzZTg3ZGY3N2UxYzk2NmI2NjU3ZmU2NTc4NDBlMGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQzNzkzNzNhYTE4MzRlNThmODdjZmJjYjFkNGNiNWRiNzViNjc1OGZkYTlmZDA2MWFiYTE5OWMwNzI1NThhNTkifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L16-L63",
"version": "repo-lines-v1:sha256:966ac12efc1c2b09b658618d127306218aef5047b26e401860b504ed4329d93b:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4Y2U4MzMyMDVkNTUxNjkxY2Y4MmZmM2U3NGYzNGE1ZWQwYjg2MzFkNmYzYTZjMGJlYjNhNTJlOTVjNThjMWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAwNGYzODBlYjE5ZmQ0MDIwNzE1YTVlN2RhMzI4NzRkMmYwNGI3ZTA3YWNiOGYyMGVlNjcxODYzODdhMzJjY2QiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJjYWM1YTJhYjFkNGIyN2YxOGQ3ZGQ4YjYzYmZjYzg1M2I4ZTYyNTA1NTVlYzlhZWYyMmY1YzQwZmM0MjljYTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU2NjU1OGM3NmE1MjI1YjVlMGZkMTdjMmJiMzc2Yzk3MDc5NGE2ZjYxM2Q0ODRlY2I1MzE0OTM5MTMxZTUwOGQifQ"
},
{
"resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L4-L22",
"version": "repo-lines-v1:sha256:b674d7c2d231d5b2d374e10cd417076ab8795bb2bc586fc20b530a68b283e3ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzMzA4NTlkNjgzODAyNWFiM2Y2NjIxNTU5NWM4N2JiZWI1ZDVlMDlmNTIxMjk3YmY2MzI3NTUwYzgxYzBjYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4OTUxYTVlMDA0MTE2ZjBmM2Y1MzVjODgxOTBiNmUwNmU3NGFmZGZlYjU2MTc0MTA0YTIzYzQyZjJiYTNlZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ"
}
]
},
{
"id": "claim_18ad2d4336a34d6899c09a1ec2fca2ec",
"statement": "The V28 compatibility fixture tests local migration and repeated reopening through `TermindPersistence.makeContainer`, verifying preservation of Host SSH settings, default-disabled Telnet settings, related Vault state, and default workspace preferences; it is not a CloudKit replica test.",
"evidence": [
{
"resource": "repo://FrameworkTests/PersistenceCompatibilityTests.swift#L60-L144",
"version": "repo-lines-v1:sha256:4561b141f81b56941320a35e8389bea59dc6291fc22b2e7b359b58f0ed816631:eyJzZWxlY3RlZExpbmVDb3VudCI6ODUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdkZmY4ZDRjNGJlMTRmZDZjZjc4YmQ1ZmI2N2JkNTNkNGVjZWI0MTljNjVhMzFhNWQ2OTQ3NzA2OWE2Y2ExMGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFkZjBmY2E5ODUzMjVjMDQ5ZTY0ZWE5ZmE2MTE3ZjI4NjY0YTcxNzlkMGY2NWEyNjRiNTcyOGNiMTg5NTA4MTIifQ"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-23T10:08:51.776Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
"pageVersion": "sha256:a89c6117702461464b0ddad1ba9944e9c4658b630225e3a4f4bbc37d60d93623",
"pageVersion": "sha256:f143e764f73ec36677ac186baab67e5d566e192cbfb9c7016ce813655f7828bf",
"claims": [
{
"id": "claim_69a9de4ce918417c8a44c6c87c9f6564",
@@ -134,7 +134,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift",
@@ -166,7 +166,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -204,7 +204,7 @@
},
{
"resource": "repo://TFMTests/AgentHostAuthenticationTests.swift",
"version": "repo-file-v1:sha256:e0fc788e24877e6043dfa7d89ad5835df7e94f3b423fa0482e90f0e5447582aa"
"version": "repo-file-v1:sha256:bb052be075fed353e5e94e5f39e90ab900887cd223b8e0679bc3e7b133b4bcfc"
}
]
},
@@ -252,7 +252,7 @@
},
{
"resource": "repo://TFM/App/TermindApp.swift",
"version": "repo-file-v1:sha256:e1da1cc2ef0da4f4a01ee620e6854611b66a4381f4b8c36eb003ddfaa6e6eae9"
"version": "repo-file-v1:sha256:767a302e0718800b28861d17e1d3948765e7177bd0d10479acecc64ece3e1332"
}
]
},
@@ -273,10 +273,74 @@
"version": "repo-file-v1:sha256:75c3d7bda5bf9ce83518666d5801cf3e01f9bbc82ed5acdc557bf17c2c6d4efc"
}
]
},
{
"id": "claim_57916b8e9b3545d88b1a4c67adfb2602",
"statement": "For an Agent connection through a proxy whose saved password identity is missing, the authentication card retains the proxy-configured username while clearing the unavailable identity selection; an unsaved proxy answer changes only the attempt, while a saved answer persists proxy identity and username to the host store.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Connections/RemoteSessionHostStore.swift#L204-L246",
"version": "repo-lines-v1:sha256:737454e1fa8a61920ee3e34c7af10bf4f36ca4935eac228e8699a2d09d1641bb:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJkNWRjN2ZhYjc4NzNiMjBhOGYyNzk2ZjgzNzVhMGEwNmUyZDM5YzY3ZGEwNjg2Y2I5ZjViOTUwYjNjMGYyMTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU3OTdiOTZlN2ExZjVkZDg3ODA1MmY0MDRjYjUwYmE4MjQzNGQ5YTRkZDE1NWNiMzA4OGI5ZDFlZTkzYjgzZmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg4YjYzMWEzZjczZDAwNGU0OGVlMjNmNzliYTEyYjFlNTMxYzg4MzdhZDg5ZWMzYzA3NjBlNzlhYzJmMjUzZmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZlMzIwODM0NWZhOThjMjQxYzgyYmExZmYwZWRiODJlN2M4MDA2OTAyYjkyN2NkZmM2OTdjMmFiMGEwZmE4MjgifQ"
},
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L253-L289",
"version": "repo-lines-v1:sha256:6fa0516c8cf3114fb23aa2bf0a7d7131e29087e94e668260839495fc176f7332:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQzMTUyZWUzY2VjM2EzYzU1NGMzODJlMTA2YWNkYzc0YzhjYjI0MTkwMTBiZTMyZTFlZTdhODYyMDM5YTU5YWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0ZGQ1OTdlZGZjNmRlZjIzNzBhMjU2YTBhNWY3M2ZmN2E2NzEwY2ZmNGUzNDVlMmQ3MGJkN2IwMGIzYzdmYzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlZTNhYTNkNTFhMzZiNWU4MWI2OWU0OTU5NTJlNWNjNzE1OTVhOGYxNDgzNjc1MTU0YTZhYzk1OWQ5NmI5NDAifQ"
},
{
"resource": "repo://TFMTests/AgentHostAuthenticationTests.swift#L19-L52",
"version": "repo-lines-v1:sha256:c3b38ca0cac883982e318d3433bd5cbc81734e0f88c05718e8b0c5f6528da440:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc2MWQwZDcxMmRiYmNjYWEwNTFkMDA4MGI2NmQxNWI4NGNkODBhMzBiN2QxZDhkMmJkZDIyZjk3MTdiMjc2NzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNiMjYxMjQwZTk4NDk2MjA0MGJlNTU4ZDE3Y2EyNTExZWMxMWRkOTExY2NkMjRhMDNjYWE4M2ZmMTExMDkzYmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJjZWMyOGNlMGI0YWNhZTljN2YwNzA4ZWI4ZDZjZWYwNTI2Nzc3MjRhYTQ1NzFlZTczZWU0OTM4ZTczNDQzNzMifQ"
}
]
},
{
"id": "claim_cf9c4121d565433cb7f7d1feb0502e8d",
"statement": "When Agent authentication requires an identity followed by a protected-key passphrase, the passphrase response merges into the staged identity submission instead of replacing it, preserving any password fallback for that connection.",
"evidence": [
{
"resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L294-L329",
"version": "repo-lines-v1:sha256:d925718525a37bc092961c5c05b2ccacd440cb2910ed60bb01129e949b312713:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc5OTEwNTdiNzhjNGQyMTM1ZTI0MjNiZTJjOGIxMjlhYmM5MDc4NjBmMjgxNDEzYTllMTk2MTJlYzFhYWNkMWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhkYjMzOWMxN2Q0Y2M1NGU3MGM0ZmNmZWNiNjExYmI5ZTdkMzYzZjI1YjE4ZTA5MjNhMWQzMDZjYzk1OTI0ZTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJkYWMzNjNkZjhmZTRkOGUwM2Q1ZjU5YjQ4OGYzMTFiOGZiZjU1ODE1MzFhN2FiY2UwYzFhZTY0MWQ0NDhjZmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3NmFkN2Y2NTdmYjVkYWVhMTA1MGVmMjc3Yjg5NmE2ZWFiMmY4ODgyNGQyNDBiOTViZGZkNzUxMzNjZWI1YTEifQ"
},
{
"resource": "repo://TFMTests/AgentHostAuthenticationTests.swift#L259-L327",
"version": "repo-lines-v1:sha256:e7836618394f5671986aa1d9fcd00841da3896774446b7bacd6bc4397c1da145:eyJzZWxlY3RlZExpbmVDb3VudCI6NjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE3MjZjOGI1NGFlODc3NmM0MDE5ODdiYzAwMTliOWYyYjhhMzBjYjY4N2NmYmY1YzU0ZGQ3NmQwYzZhOWU1MDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVjYTg0MjI3NzlkYzUxMGRjMjM4N2RkNmZiZTdiZmQ1OWY0MDIxYmJlYmYxNjRhZGEwNmQxMzZkODAxZTRmOTkifQ"
}
]
},
{
"id": "claim_794d08c35cdd4a7eaf7110c942621f13",
"statement": "Closing the last desktop window does not necessarily terminate the application: the metrics menu preference and running metrics govern whether it quits, independently of the window-owned workspace transport lifetime.",
"evidence": [
{
"resource": "repo://TFM/App/TermindApp.swift#L351-L359",
"version": "repo-lines-v1:sha256:72b0ea3d0ed1f3a746b2322cc7dfcf974afdc9cce02dda03d97e5862dea07ce9:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZjYmYxYTMzZmU5ZDUxYjBlZjQwNzYzMzljYzEwMGFlMjBlOGFiYzk2OTZlMzk4NjBhY2JmNmU1YWQ2ZTQ4ZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDYwZjQzMzI5NTZmNTMwOGY0NTY4NDJjNzExOTFhOTAyZjBkZWY4OTQyNGQ5M2MwZTExYzBhMzZlMmM1Njg2MSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjc3ZDhiZmVlYmRjZDdlZWJlYWRkYzZhMjNlNjNiN2JiOTQ2ODg0ZmMwZjUxZmEyNzE4NWRlMDYxMDMxMjg1MyJ9"
},
{
"resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L1432-L1436",
"version": "repo-lines-v1:sha256:692e688d2c7eb2aaf96a505bef91f40bb87e7bcef1d9138a326f0d3173799053:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzkwY2NjNTIzMGVmMWE1NmExMmNhMmI2ODlkYjY2YjM1NDZlZjgxYTdjOGQ2NzQ0NmI4YjcxNDNjZGY2YjAzMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYjFlMmJjY2M1ZGZlOTMwMDI4M2NjOGUxNmU1OTBhMDAwNjVlZWY4OTk4YTMxZjQ4NzA0N2Q4ZDRkM2QyNDMxYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzM1OWRkMDg4NDA1ZjhlZTkxOWRmNmQ2NjQ2YWFhNDE4NDY0ZTcyNzIxNTQyNTNhNmFmMWM4ZmY5NTgyOTVmMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjRhNjY4ZWYwMjFjMDFlNTYxZDNiMzgxMTczZjk2YWJmZTA1NmE2MzJjNWQ4ODI2MDdhZDg1YzhjNWQ2YWU1ZiJ9"
}
]
},
{
"id": "claim_d1eefdcbcbc248c193c3e64a3f8f4bfa",
"statement": "A workspace trust approval resumes the pending live host-key handshake rather than opening a separate discovery connection; the feature pauses recovery while waiting and disconnect clears pending decisions.",
"evidence": [
{
"resource": "repo://Frameworks/TermindApplication/Connections/RemoteSessionConnectionController.swift#L126-L133",
"version": "repo-lines-v1:sha256:18f56a503c4a2eb4aa9fa4a4688ff3349dad5d1fe0d5583b0500ce0385fb3ce9:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNWViZmM2MDFlMzAzNmU2MjI2OTU0YWM3YzlhMGY1NTVmOTc5YmE0ZGIxMTEwNTE4MmJlNDQ2YjkxMmE3OGJkYSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTBmYjZlMDA4NzlmMTE4YTgwZmRmNDhmZTdiNDgxYzkxNTE3ZTc2ZTE2YTQ3ZmQwMjIzMDc2NWNlNjgwODU0NyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOGUwMDRjZWE4MDkyZWU3ZmJmZTI1YmJhYjgxNjIwYzMwMjM0MWE5Mjk3NjY5Y2JkNWYxMjBkMzlhM2UyM2M1ZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWYzYzJiZTljODg4NmMyYzVjMjgyNjM5OTgxMGZlNjIwNjRhZmFlYTI3ZGYxM2Y3NDk4YjgzZDIyZWU4MGM4OSJ9"
},
{
"resource": "repo://Frameworks/TermindApplication/Connections/RemoteSessionConnectionController.swift#L180-L217",
"version": "repo-lines-v1:sha256:acf1352d857c544ce5f29d43d59571d546d172b9627b845a86d7494d3d5b8c1a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMyOTllMzg4NGNhZGZlNGUwMzhjODk4NTEzNWU3MzgwMzMwZTBiOWY0NmMyYmZkNWUyOWJhYmNlMzIzYTI1MTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwMDhiOWJkNWE5OWIzMTIyMWQ1ODQ0NGQ4Zjg4ODEyMTJlMWE0NWUwMzNhM2U1YjExMmFjNjhiMTc1NWNjODciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjliYTBhNTliMjc2YmM2MGExODhmY2IzMGZhMzI1Yzg4ZjRlNjRmZjIyMGY4NzRiYzg5NGU2YzJjNzhmNGNiNjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZkZTE2ZTY1YWIyOGNkYzM0NmNhYjQ1YjA4NDNjOGVkMDM2NzllMmMyNzRiNGE1ODM3NjEzYTNjMDA5YzM1MWUifQ"
},
{
"resource": "repo://TFM/Features/Terminal/SSHSessionModel.swift#L751-L756",
"version": "repo-lines-v1:sha256:0789f22659ee4a9a432ffa2267065dbf30cd3656c4e3094d17e360d693be85f2:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZWVlNTQ2MzA2YjYxNTNmZTg5NDViNDE2MzY4YjBlMDRjY2QwMDljMGI0NGZiYzUyZWE4NzQ5YzNkNzgxMjRiMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTY5NzkzMDIxMjQ4MjU5NTQzNTM4ZTYzMTBiNTYzMTc4ZjY3ZmJhNmM3YTA3NWMwNDNhMGY4MmFmZjhmZTI0ZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZmJjNDQ1ZGIzNGRmZGU0YTVlOTc1MGI0Mzc1NzVjMjEzMTEwMmNiNTY0YjAzZmE2MDkzYjg3NjhiZTMwMzA4YSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjFjYjZiNWJkODBkOTk2YzNhZDlkZDdkNTNjYTg5MmZiNzA5NmZiYjhlODNlZGQ3NjdlMzAwNzQwZGNhOWRlYyJ9"
}
]
}
],
"verification": {
"by": "openwiki/0.5.2",
"at": "2026-09-23T17:44:09.687Z"
"at": "2026-09-24T03:18:19.992Z"
}
}
+3 -3
View File
@@ -1,8 +1,8 @@
{
"updatedAt": "2026-09-24T02:09:13.524Z",
"updatedAt": "2026-09-24T04:22:53.102Z",
"command": "update",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"model": "host-agent/codex",
"status": "complete",
"model": "gpt-6-sol",
"status": "interrupted",
"language": "en"
}
+102 -102
View File
@@ -2,88 +2,88 @@
"schemaVersion": 1,
"pages": {
"/openwiki/architecture/desktop-ui.md": {
"gitHead": "b281537bfa62d2db8af554b03a8f0967c27733f6",
"sourceFingerprint": "sha256:dab1c446986ff7603830f4c6a253228ca91492b389504c60d26f53f38380e77a",
"pageVersion": "sha256:938bc144219bb79a0ab503a5b01f70a4d0c95bf6ba6fc1ba47f7c2d39c0ad1d6",
"completedBy": "codex",
"completedRunId": "7375f231-f68e-46eb-8c8a-62ebe9af9b18"
"pageVersion": "sha256:9059f7f4ba5240e5a8338db6e44d6066ad086428faf2ce68e5033ee3443e5fee",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/architecture/engineering-invariants.md": {
"pageVersion": "sha256:c98dff9d40631bc19e57fdb22630d6e71b61e9ae4bb1c36d272e7afcd5b7adeb",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:6104dff58c8230d240a00bc70ad61ae5e2e6b2fb6e27794965ddfa1ed6b1c3a1",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/architecture/mobile-ui.md": {
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d",
"pageVersion": "sha256:4c542c28684e3b7da37260a82fc02b3b2f5d2c599dc1f719718ddb62bf10f701",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58"
},
"/openwiki/architecture/module-map.md": {
"pageVersion": "sha256:c49415f8bc3f829076c2361a4f7e5a7f8ebcfe6ea0548bee4d615d0ad7df8ee6",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:751205f27f04ee23745dd8b6b671c9a7dd342d6e1dffb1cc4a5d00b31733bea7",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/architecture/native-app-directories.md": {
"pageVersion": "sha256:ccc1ba644b43a27d74cef3704aee00fa50111b7d7b6a3fc02a7e293007483fa3",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:7e34ef5b96eb24065e35c51caa369a71f930de2671f013463e2df8e3d65c9d68",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/architecture/platform-runtime.md": {
"pageVersion": "sha256:c9416474abac2fb6a994f2dbb1a11cf40a0a27206ea9c15f27f13fc432cbf121",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:001c373a89ad6a49f16c0c02fdae97d6ed7f14188b6056c45c2517f2c0aff5bc",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/architecture/shared-module-directories.md": {
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d",
"pageVersion": "sha256:618178c6b617cf32ec87544339d8bd04d364b3f4976b3ec972d4b0ef9815823e",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58"
},
"/openwiki/architecture/supporting-system-directories.md": {
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d",
"pageVersion": "sha256:242f33860f22c9b7cd75981eeeb3fd39a85276dbc91f322a8ae0bb66528d3b5e",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58"
},
"/openwiki/architecture/system-boundaries.md": {
"pageVersion": "sha256:70bc54bbf1c2da2b34e500a403c70203791f10430ee4ba3d69f9de85b70608d2",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:5da26732bd32ecc9204c2c8c832f9607e8c614aaa83c5f5a8cd2d4a636dab549",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/concepts/agent-runtime-and-assistant.md": {
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d",
"pageVersion": "sha256:aaaf94253005ced015fa2396347f5d7c3da5f1bd246a50bc6a8b86a86ec9f1ca",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58"
},
"/openwiki/concepts/commerce-localization-and-product-surfaces.md": {
"pageVersion": "sha256:f24b2cea65e79274b316c5533385ff4f19e1c67e892b1014ed24109c0efd5779",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:3dd8177bccfc507cc1d0d45b6694c75ca379337c1b914c5f199fb132ea37dd86",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/concepts/persistence-and-secrets.md": {
"pageVersion": "sha256:e48470e3b9537dec53eb00cd0a9706bdc523befa7d56e33a4febb1c153129a6c",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:ce2823da7595d02f213dbd22d558873d3b27f8157eab9bd8d171fef116cc09a9",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/concepts/remote-services-and-forwarding.md": {
"gitHead": "4b4aa2adffa2e7c597ba3ac221ddd151221ce5fd",
@@ -107,32 +107,32 @@
"completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74"
},
"/openwiki/concepts/ui-design-principles.md": {
"gitHead": "b281537bfa62d2db8af554b03a8f0967c27733f6",
"sourceFingerprint": "sha256:dab1c446986ff7603830f4c6a253228ca91492b389504c60d26f53f38380e77a",
"pageVersion": "sha256:5be04fadb09bbb3c62238bb4033b4d66e3eca9f81df3588da05b6edf81c17e9d",
"completedBy": "codex",
"completedRunId": "7375f231-f68e-46eb-8c8a-62ebe9af9b18"
"pageVersion": "sha256:a71d66817c91463fad3b26f544059b3945dd6e5564036981c101550db75f8c4e",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/integrations/mcp-server-and-bridge.md": {
"gitHead": "6ed411897a6f4f6a80c8b9ce63b3306bc824d7f5",
"sourceFingerprint": "sha256:26925e2f07efa153566a3089165df52866385c547e9147a262f01c1680adc639",
"pageVersion": "sha256:c5bc5f9ca5aec9baf7cef84a0e408483976858073900fb97ece8c7c68129cfdb",
"completedBy": "codex",
"completedRunId": "f8bbfb90-abda-4ed0-834a-5128325b4e47"
"pageVersion": "sha256:f65ef3bece82ac4bd0a4c9c9d91292ac8e315454fa3fe24bf01b7a39f1209c54",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/operations/build-test-and-release.md": {
"pageVersion": "sha256:7391dbb4e86cdf0b4e24c3d6d8731bdb1e5ee8e00f512f8352c88041084935f1",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:a29579912ea05cbc2cd3810d36bc482b362019aafdc135813b9d3144ab428e4d",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/operations/cloudkit-release-readiness.md": {
"pageVersion": "sha256:ca6fe1e6d38481b7e92b09c44bcf391ba3c18250e658b39e774491480747b2fe",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:3fdb6fea6ac8d8927120a183ee809996260dd8b78d2cb2acd9573701d5e9ff56",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/operations/marketing-assets-and-app-icons.md": {
"gitHead": "b281537bfa62d2db8af554b03a8f0967c27733f6",
@@ -149,32 +149,32 @@
"completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d"
},
"/openwiki/operations/storefront-commerce-release.md": {
"gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38",
"sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704",
"pageVersion": "sha256:76527be96d18cc256d454398aec2031cb797ac37445daf0203a76e982af8ceef",
"completedBy": "codex",
"completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d"
"pageVersion": "sha256:31b25b8f676ef671d6853f726cbc282183f00b5870b6f2918c68a4f6a0bb8941",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/quickstart.md": {
"pageVersion": "sha256:4ca8ed0d3907d7e2d599519e36b77ec2d5c598e3a3d8f43fc8416a561a027ee0",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:458b480a78f04e037b471dec7e5c900b9cece88c2b6c6615e842624264bc6d1c",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/testing/behavioral-boundaries-and-fixtures.md": {
"pageVersion": "sha256:bd374d594e69582542f2b267631be92bb7c5d0c89c99882257f71531e17a7447",
"completedBy": "codex",
"completedRunId": "769f6312-b539-483e-994c-c87554b7cc58",
"gitHead": "00d70ba85faaf32ab875f887319349b2484b1132",
"sourceFingerprint": "sha256:24d72f16570e61c505e9143bf7363f923b4d0f5d41dc3d5a375e40ce25b4735d"
"pageVersion": "sha256:59829b8d5e54cff352e757dfa8ee42e5f875587624a61c6a6ab4b7e0f56d505a",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/workflows/desktop-drag-and-drop.md": {
"gitHead": "dd76e4ba56a934181c55e7bed864a5f14e19c405",
"sourceFingerprint": "sha256:46ef6185800e7e90b14c6a89dd09b4b7e5b3c11e2b6e96e2a2a5ccb8834b5d32",
"pageVersion": "sha256:0faf1be721afcf8b31f91b1eecaee9a38f8ef57809354348df75f81f1173aa02",
"completedBy": "codex",
"completedRunId": "f66e5004-b0af-476d-88da-24e0c56bde2f"
"pageVersion": "sha256:8f775546672e0828cfb5a48c814c06ccbf253e1a946a6abe96d13e04142679f5",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/workflows/file-drag-and-drop.md": {
"gitHead": "dd76e4ba56a934181c55e7bed864a5f14e19c405",
@@ -191,11 +191,11 @@
"completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d"
},
"/openwiki/workflows/settings-and-cloud-sync.md": {
"gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38",
"sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704",
"pageVersion": "sha256:99d2b239428f25d840b99f415eab5ff6fa482e27820addafa7f175fb77fb805d",
"completedBy": "codex",
"completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d"
"pageVersion": "sha256:79baf476eb5467b8d8b21e95dd285faa364f3ce83175ccf7f9598519a9df8f11",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
},
"/openwiki/workflows/sftp-transfer-and-external-edit.md": {
"gitHead": "dd76e4ba56a934181c55e7bed864a5f14e19c405",
@@ -205,11 +205,11 @@
"completedRunId": "f66e5004-b0af-476d-88da-24e0c56bde2f"
},
"/openwiki/workflows/ssh-session-lifecycle.md": {
"gitHead": "b281537bfa62d2db8af554b03a8f0967c27733f6",
"sourceFingerprint": "sha256:dab1c446986ff7603830f4c6a253228ca91492b389504c60d26f53f38380e77a",
"pageVersion": "sha256:a89c6117702461464b0ddad1ba9944e9c4658b630225e3a4f4bbc37d60d93623",
"completedBy": "codex",
"completedRunId": "7375f231-f68e-46eb-8c8a-62ebe9af9b18"
"pageVersion": "sha256:f143e764f73ec36677ac186baab67e5d566e192cbfb9c7016ce813655f7828bf",
"completedBy": "openwiki/0.5.2",
"completedRunId": "ce7d38d3-c709-4d1d-b9e5-b6dd471bfdcd",
"gitHead": "f955389374ae5d386defeb0a31ff5982b135ee73",
"sourceFingerprint": "sha256:1dc053dbb529565564f7ef968967bc093c3a859a2b48d210fec442b360814567"
}
}
}
+21 -5
View File
@@ -5,7 +5,7 @@ description: "How the macOS app composes its native window shell, persistent wor
tags: [macos, tfm, ui, navigation, workspaces, swiftui, appkit, design]
verified:
- by: openwiki/0.5.2
at: 2026-09-23T17:44:09.687Z
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-e09fb7bc8e7ca0579f6d446e
resource: repo://Frameworks/TermindApplication/FeatureModels/DeviceDirectoryModel.swift
@@ -23,6 +23,8 @@ sources:
resource: repo://TFM/Features/AI/TranscriptListView.swift
- id: openwiki-source-d35453512ef488d0cacdc06e
resource: repo://TFM/Features/Assistant/AssistantView.swift
- id: openwiki-source-cfe2a6b22338023c37a5b503
resource: repo://TFM/Features/Settings/SettingsPageView.swift
- id: openwiki-source-0854be84b166268626a3cb08
resource: repo://TFM/Features/Sidebar/WindowSidebarView.swift
- id: openwiki-source-9cfd8531aa60dcfb31f04e04
@@ -51,10 +53,14 @@ sources:
resource: repo://TFM/UI/Managed/ManagedCardPage.swift
- id: openwiki-source-23acce6fe9173a886d433b44
resource: repo://TFMTests/AssistantConversationMenuTests.swift
- id: openwiki-source-a22920a2a9767ac44e072c9f
resource: repo://TFMTests/MultiWindowTests.swift
- id: openwiki-source-98505b843db3ce6b8e4ca024
resource: repo://TFMTests/PersistentWorkspaceDeckLayoutTests.swift
- id: openwiki-source-dceb8d7e7c5bb09359e70052
resource: repo://TFMTests/ResponsivePageLayoutTests.swift
- id: openwiki-source-44cb7a6172854edbfc9b5ccb
resource: repo://TFMTests/SettingsNavigationTests.swift
- id: openwiki-source-578f30372fe67f8688f44b76
resource: repo://TFMTests/WindowStateTests.swift
- id: openwiki-source-91826a88f242f001f33fff89
@@ -65,7 +71,7 @@ sources:
resource: repo://TFMTests/WorkspaceNavigatorRenameTests.swift
- id: openwiki-source-a48980e81bab99fcd643df54
resource: repo://TFMTests/WorkspaceWindowMoveTests.swift
generated: { by: "codex", at: "2026-09-23T17:44:09.687Z" }
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# TFM Desktop UI Architecture
@@ -99,6 +105,8 @@ flowchart TD
Shared -. services .-> Window
```
Window composition and state ownership; the deck stays mounted beneath foreground destinations.
The main layers are:
| Layer | Responsibility | What should not move into it |
@@ -109,7 +117,7 @@ The main layers are:
| Feature views | Render projected state, present interaction, dispatch intent to owners. | Recreating connections merely because a destination appears. |
| Reusable renderers and native bridges | Collection interaction, layout, focus/native mounting, terminal/transcript presentation. | Resource-specific repository mutations hidden behind generic drawing code. |
`TermindApp` builds the persistence container and shared `AppModel` once. Its `WindowGroup(id: "main", for: UUID.self)` calls `makeWindow(requestID:)` for each scene: ordinary and restored windows receive a fresh `WindowModel`, while a debug screenshot launch without a request ID can receive a demo-configured model. `RootView` stores the supplied instance in `@State` and exposes it through the environment and focused scene values so commands target the correct window. The separate `Window` for external authentication shares app dependencies but is not a workspace scene; `.commandsRemoved()` keeps it out of normal scene-opening commands. The main scene uses the saved default window size and content minimum resizing; screenshot mode disables scene restoration.
`TermindApp` builds the persistence container and shared `AppModel` once. Its `WindowGroup(id: "main", for: UUID.self)` calls `makeWindow(requestID:)` for each scene: ordinary and restored windows receive a fresh `WindowModel` (which starts at Vault/Welcome), while a debug screenshot launch without a request ID can receive a demo-configured model. `RootView` stores the supplied instance in `@State` and exposes it through the environment and focused scene values so commands target the correct window. `AppModel.registerWindow` wires shared connections, histories, host and metrics services into that model and adopts the shared conversation store; its workspace list, queries, presentation routes and transcript cache remain window-local. The separate `Window` for external authentication shares app dependencies but is not a workspace scene; `.commandsRemoved()` keeps it out of normal scene-opening commands. The main scene uses the saved default window size and content minimum resizing; in debug builds XCTest normally suppresses automatic test windows unless `TERMIND_WINDOW_TESTS=1`, and tests or screenshot mode disable main-scene restoration.
`MainWindowRegistration` connects a real AppKit window to `app.mainWindows`. A **Move Workspace to New Window** action requests the UUID-valued main scene first; the source retains its live workspace until the destination registers. Only then does `MainWindowCoordinator` take it from the source and open it in the new model, preserving the running session rather than treating a move as a close/reopen. Closing a real window instead unregisters its model and `closeForWindow()` disconnects its workspaces and clears window-scoped caches. A restored scene has no pending move request and keeps its system-restored frame.
@@ -128,11 +136,13 @@ sequenceDiagram
Coordinator->>Target: open live workspace
```
Scene-request handoff: the source keeps the session until the target's native window registers.
A workspace move waits for native destination registration before changing ownership. A pane released outside its source window uses the same request mechanism: a split pane becomes a new workspace around the existing live pane, while a lone pane carries its original workspace and name. The detailed release, cancellation and animation rules are in [TFM Drag and Drop](/openwiki/workflows/desktop-drag-and-drop.md). [Source: `TFM/Platform/MainWindowCoordinator.swift` and `TFM/Features/Workspaces/WindowModel.swift`.]
## The window shell owns chrome once
`RootView` owns the split view, the window toolbar, search host, native window registration, title reporting, Quick Open, onboarding and app-level presentation bridges. It supplies one leading creation area, a principal Metrics page picker when applicable, and one Find slot following the content in front.
`RootView` owns the balanced `NavigationSplitView`: `WindowSidebarView` is the single leading column and the detail holds a persistent workspace deck with Vault, Assistant, Metrics or Settings layered above it. The sidebar visibility binding reads and writes `window.showsSidebar`; column widths and the window minimum adjust for available width. The floating status bar appears only over a selected workspace. The root also owns the window toolbar, search host, native window registration, title reporting, Quick Open, onboarding and presentation bridges. It supplies one leading creation area, a principal Metrics page picker when applicable, and one Find slot following the content in front. `WindowActivityReader` reports the focused SSH remote title for the window and key-window activity without tying either to a transient pane view.
The sidebar is one column whose mode rail switches between Navigator, Assistant, Snippets and History. `WindowModel.activateSidebarMode` is an **intent operation**, not just a property assignment: choosing Navigator from the full Assistant restores its prior destination, while choosing Assistant inside a workspace opens the contextual sidebar rather than hiding the terminal. Direct mode assignment remains available for presentation/restoration without these navigation side effects. History is unavailable for focused Telnet/serial sessions, and reconciliation moves away from an invalid mode.
@@ -147,7 +157,7 @@ Keep the following coordinates distinct:
- **Focused pane**: the session targeted by workspace commands.
- **Presentation route**: an editor, chooser, sheet, or other transient interaction.
They influence one another, but they are not interchangeable selections. `WindowModel` remembers return destinations for reversible trips to Assistant and Settings. If the remembered Assistant workspace has closed, Navigator falls back to Vault. Page searches, selections and archive presentation are window-local, so two windows may inspect the same shared data differently. The workspace collection and recoverable close stack live in its `WorkspaceDeckModel`; the `WindowSidebarState`, `WindowPresentationState` and `WorkspaceDragState` isolate the column, transient routes and live drag payload from session ownership.
They influence one another, but they are not interchangeable selections. `WindowModel` remembers return destinations for reversible trips to Assistant and Settings. If the remembered Assistant workspace has closed, Navigator falls back to Vault. Settings navigation uses a window-local `SettingsRoute` hierarchy: toolbar Back walks to the parent, then restores the prior destination, falling back to Vault if its workspace was removed. `SettingsPageView` cleans up incomplete provider, MCP and skill drafts on route changes or disappearance rather than treating a hidden Settings page as a persistent editor. Page searches, selections and archive presentation are window-local, so two windows may inspect the same shared data differently. The workspace collection and recoverable close stack live in its `WorkspaceDeckModel`; the `WindowSidebarState`, `WindowPresentationState` and `WorkspaceDragState` isolate the column, transient routes and live drag payload from session ownership.
### Navigator interactions and workspace lifetime
@@ -182,6 +192,8 @@ sequenceDiagram
end
```
Find command routing and keyboard handoff in the focused main window.
Find ownership flows through the active window; the sidebar mode does not choose the query.
On macOS 26+, a background `WindowToolbarSearchHost` supplies the system `.searchable` item without changing the persistent split-view branch; the toolbar slot itself is fixed by OS availability, not by navigation. On earlier macOS versions, `WindowToolbarLegacySearch` supplies a retained `NSSearchField` (or a compact Metrics-detail popover). The field owner and coordinator preserve editing/focus across toolbar bridge updates, handle terminal Return/Shift-Return and Escape, and release keyboard ownership on a real user exit so the pane can reclaim focus. Reserve toolbar height even when no Find target is available: removing the entire item would resize the content when switching destinations.
@@ -215,6 +227,8 @@ sequenceDiagram
Deck->>Deck: lay out active workspace at current size
```
Destination switching parks layout, not sessions or native workspace view identity.
Do not replace this with an `if selected { WorkspaceContentView(...) }` that recreates the terminal hierarchy. Equally, do not let parked workspaces handle invisible keyboard shortcuts: broadcast and terminal-find shortcut owners are explicitly disabled unless their workspace is active.
The floating status bar overlays the current workspace rather than docking below it. This avoids changing the pane's available height when entering a workspace. Command-generation feedback reserves clearance above that capsule instead of competing for the same bottom edge.
@@ -248,6 +262,8 @@ flowchart LR
Intent --> Action[Page-owned move or business action]
```
Managed-page rendering computes placement intent; the feature owns the resulting mutation.
The renderer resolves a pointer to a section and insertion slot; it does not need to know what a Host, key or snippet means. Selection and deletion state stay with their appropriate owners. Creation belongs in the window toolbar and contextual blank-area menus rather than reintroducing a special “New” tile into each data grid.
## Assistant: route state and native rendering are separate
+24 -15
View File
@@ -1,8 +1,11 @@
---
type: architecture-contract
title: Cross-Cutting Engineering Invariants
description: Cross-platform safety boundaries for durable Host deletion, Assistant preparation and run persistence, workspace restoration, and app-scoped services. Use this page to check ordering and lifecycle assumptions before changing shared behavior.
description: Cross-platform ownership and test-host contracts, localization gates, and safety boundaries for persistence, remote sessions, Assistant runs, and app-scoped lifecycles.
tags: [architecture, invariants, lifecycle, security, persistence, remote-sessions, agent, mobile]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
@@ -92,6 +95,12 @@ sources:
resource: repo://FrameworkTests/SSHInteractionPolicyTests.swift
- id: openwiki-source-f6e4a8e5d7aef42804ab0509
resource: repo://Scripts/check-presentation-copy.swift
- id: openwiki-source-41a7ded3800c9422f058a3ef
resource: repo://Scripts/check-zh-localization.sh
- id: openwiki-source-de562e98d49cbf6502c23c13
resource: repo://Scripts/normalize-string-catalogs.py
- id: openwiki-source-cd0be716a2446029f345525a
resource: repo://Termind.xcodeproj/project.pbxproj
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-e43a0da5ab77c2fc3554244d
@@ -122,6 +131,8 @@ sources:
resource: repo://TFITests/MobileBackgroundControllerTests.swift
- id: openwiki-source-16ec96bd78162e7e62effd0e
resource: repo://TFITests/MobileConnectionPickerTests.swift
- id: openwiki-source-7341d7b266d976d7aac5d161
resource: repo://TFITests/MobileEditorToolbarTests.swift
- id: openwiki-source-4dbea0ff2808163cb4ecdd8f
resource: repo://TFM/App/AppModel.swift
- id: openwiki-source-6570374eaac2e0278fa84640
@@ -142,14 +153,17 @@ sources:
resource: repo://TFMTests/AppTerminationTests.swift
- id: openwiki-source-d3d065330c730839f5cc6112
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-dc392b9979d99f5026bdeadf
resource: repo://TFMTests/PresentationCopyTests.swift
- id: openwiki-source-32c251eb2f83ec0be2f1a0e8
resource: repo://TFMTests/RepositoryOutboxTests.swift
- id: openwiki-source-0dd012e3740bcc348fc36ccb
resource: repo://TFMTests/StoreKitTrialTests.swift
- id: openwiki-source-9442022b3dba1be62a55f0f0
resource: repo://TFMTests/TerminalThemeTests.swift
generated: { by: "codex", at: "2026-09-23T17:44:09.687Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
- id: openwiki-source-a08489338be00125d646c77e
resource: repo://TFMTests/VisibleWindowTestTrait.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Cross-Cutting Engineering Invariants
@@ -171,7 +185,7 @@ sibling working tree is not the app dependency. Follow `AGENTS.md` for package r
| TermindApplication | Ports, feature models, connection/import policy, remote-file-system and sync/outbox use cases; Domain, AgentKit. |
| TermindInfrastructure | In-memory repositories, metrics parsing, StoreKit, Vault/Settings/Metrics CloudKit; Application, Domain, Persistence. |
| TermindRemoteInfrastructure | SSH/SFTP/Telnet, Keychain, keys, sampling, forwarding, transfers, scoped imports; Infrastructure, Application, Domain. C libraries stay outside portable framework tests. |
| TermindPresentation | Reusable SwiftUI policy/content, Ghostty themes, `TerminalPreferences` bridge; Application and Domain only. |
| TermindPresentation | Reusable SwiftUI policy/content, Ghostty themes, `TerminalPreferences` bridge; Application and Domain only. Its own import ban is stricter than the non-presentation shared-framework rule. |
| TermindPersistence | All SwiftData models, historical schemas, V34 live schema, migrations and container construction; no app dependency. |
| TFM / TFI | Native UI/adapters/lifetimes; shared modules never import apps. |
@@ -187,15 +201,10 @@ sibling working tree is not the app dependency. Follow `AGENTS.md` for package r
migration. `makeContainer` fixes the complete schema/plan; one container per process serves all scenes. Never
recreate a failed store silently. macOS retains its `Termind` location; mobile uses Application Support/in-memory
tests. Both apps share the CloudKit container and bundle-derived Keychain access group.
- Architecture tests fail closed on absent/empty production roots. Source checks guard dependencies, native-list
allowlists, AgentKit/SwiftData ownership and the single `AppStrings` declaration outside the apps; Strings files cannot
import app targets, AppKit/UIKit, TermindInfrastructure or TermindPersistence. The SwiftSyntax-based
`Scripts/check-presentation-copy.sh` detects selected UI-literal patterns in TFM/TFI; run it with
`Scripts/check-zh-localization.sh`. Neither check proves semantic reuse, correct runtime rendering or every possible
literal, so copy and wiring still need behavioral/visual coverage. Mobile and shared-framework import checks prohibit
storage/transport construction in feature layers; the CloudKit delegate check additionally requires all sync
delegates to use the shared lifecycle upload gate and quarantine/conflict validation rather than ad hoc change
batches. These are source-boundary checks, not a substitute for behavioral sync or UI tests.
- `ArchitectureBoundaryTests` enumerates Swift files and fails closed on absent/empty roots. The non-presentation shared-framework import test covers Domain, Application, Infrastructure, Remote Infrastructure and Persistence: none may import `Termind`, `TermindIOS`, AppKit, UIKit, IOKit or ServiceManagement. Its additional Application check excludes Infrastructure, Persistence and SwiftData, and Persistence cannot import Infrastructure or Remote Infrastructure. **Presentation is checked separately**, against app modules, AppKit/UIKit, SwiftData/GRDB, Persistence, Remote Infrastructure, Infrastructure and StoreKit. Do not attribute Presentation's broader ban to every shared module, or assume an unlisted import is tested. Domain and Application have additional implementation-framework import checks; app Application/Feature layers and mobile UI are checked separately for direct I/O/storage dependencies and selected concrete construction tokens.
- The source tests also constrain `ListViewKit` importers to a native-list allowlist, prevent selected AgentKit type redeclarations in TFM, and look for SwiftData `@Model` and repository declarations outside Persistence. They reject an app-local `AppStrings` declaration and prohibited imports within shared Strings. The CloudKit delegate check requires lifecycle batch/upload gates and quarantine/conflict handling, not ad hoc engine batches. These are syntactic boundary guards, not behavioral proof; see [System Boundaries and Dependency Ownership](/openwiki/architecture/system-boundaries.md).
- App-copy changes require explicit keys and finished `zh-Hans`/`zh-Hant` translations in both manually managed app catalogs, `Localizable.xcstrings` and `InfoPlist.xcstrings` (bundle metadata). Do not delete a key because Xcode marks it `stale`: extraction from one target cannot establish non-use in both apps. Normalize with `Scripts/normalize-string-catalogs.py --write` after editing, then run `Scripts/check-presentation-copy.sh` and `Scripts/check-zh-localization.sh` (the latter checks canonical formatting, catalog validity, completed translations and spacing). Keep `STRING_CATALOG_GENERATE_SYMBOLS = NO`; `AppStrings` owns the API. The SwiftSyntax copy check detects selected UI-literal patterns in TFM/TFI, not every literal, semantic reuse or runtime presentation; use `PresentationCopyTests`, `AppLanguageTests` and platform rendering tests where applicable. AgentKit's own copy/catalog is a separate release boundary.
- The **test host is the real app**, not a generic logic runner. In DEBUG, `TermindApp` detects XCTest, uses an in-memory container, suppresses automatic main/auth windows unless `TERMIND_WINDOW_TESTS=1`, and disables restoration for tests; screenshot demo has its own exception. Ordinary offscreen tests run without focus. Window/focus tests carry `.requiresVisibleWindow` and must opt in with `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` (forwarded as `TERMIND_WINDOW_TESTS=1`); manual StoreKit tests use `TERMIND_STOREKIT_TESTS=1`. Mobile uses testing dependencies in its real `TermindIOSApp` scene, while key-window suites use `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1` and `-parallel-testing-enabled NO`. Do not solve flaky host windows by enabling them for the default suite.
- V31 adds scoped quarantine/recovery models. Released V31 stores migrate directly to V34; V32/V33 were not distributed
schema endpoints. V34 replaces Host, connection-history and Identity models, adds device-directory and Workspace
preference models, and backfills history with the installation ID plus its initial DeviceRecord. Local schema changes
+1 -1
View File
@@ -1,7 +1,7 @@
# Files
- [TFM Desktop UI Architecture](desktop-ui.md) - How the macOS app composes its native window shell, persistent workspace deck, split panes, management pages and Assistant surfaces, with explicit UI-state and runtime ownership.
- [Cross-Cutting Engineering Invariants](engineering-invariants.md) - Cross-platform safety boundaries for durable Host deletion, Assistant preparation and run persistence, workspace restoration, and app-scoped services. Use this page to check ordering and lifecycle assumptions before changing shared behavior.
- [Cross-Cutting Engineering Invariants](engineering-invariants.md) - Cross-platform ownership and test-host contracts, localization gates, and safety boundaries for persistence, remote sessions, Assistant runs, and app-scoped lifecycles.
- [TFI Mobile UI Architecture](mobile-ui.md) - How the iPhone/iPad app composes registered feature stacks, scene-local navigation, shared runtimes, adaptive content regions, native terminal/transcript surfaces and mobile interaction policies.
- [Module and Directory Architecture Map](module-map.md) - A concise map of Termind's modules, second-level functional directories, build dependencies, and responsibility boundaries, with links to the detailed directory guides.
- [Native App Directory Responsibilities](native-app-directories.md) - Directory ownership in the macOS and iOS apps, including desktop window composition, MCP transfer policy, and mobile scene, sync, and background lifetimes.
+23 -6
View File
@@ -3,6 +3,9 @@ type: architecture map
title: Module and Directory Architecture Map
description: A concise map of Termind's modules, second-level functional directories, build dependencies, and responsibility boundaries, with links to the detailed directory guides.
tags: [architecture, modules, directories, dependencies, ownership]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-ed77bc20b48d193bace3dde6
resource: repo://.gitmodules
@@ -24,6 +27,8 @@ sources:
resource: repo://Frameworks/TermindInfrastructure/Cloud/VaultSyncCoordinator.swift
- id: openwiki-source-0b6ab59ec6a684de8101ff8e
resource: repo://Frameworks/TermindPersistence/SwiftDataDeviceDirectoryRepository.swift
- id: openwiki-source-0bf5c5e49b55e95efb864567
resource: repo://Frameworks/TermindPresentation/LinuxDistributionBrandColor.swift
- id: openwiki-source-d2d4c06f734241db3badc1f5
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift
- id: openwiki-source-c4b6e224fdbea6dcd393344d
@@ -52,10 +57,7 @@ sources:
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-0f8d0f9d08d6674698dd054c
resource: repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Module and Directory Architecture Map
@@ -83,7 +85,7 @@ These are orientation guides, not replacements for [System Boundaries](system-bo
| `Frameworks/TermindPersistence` | SwiftData models, historical schemas, migrations, stores, container factory, and GRDB-backed memory. | Owns stored representation, not a window or scene. |
| `Frameworks/TermindInfrastructure` | General concrete services: CloudKit, commerce, speech, logging, importers, and metrics parsing. | Separate from remote transport mechanics. |
| `Frameworks/TermindRemoteInfrastructure` | SSH/SFTP/Telnet, remote credentials, transfers, forwarding, sampling, and host-aware Agent tools. | Owns protocol machinery, not native interaction surfaces. |
| `Frameworks/TermindPresentation` | Reusable SwiftUI content, forms, formatting, transcript policy, and terminal appearance. | Does not own AppKit/UIKit surfaces or persistence. |
| `Frameworks/TermindPresentation` | Reusable SwiftUI content, forms, formatting, transcript policy, and terminal appearance. | Not a persistence or native-app owner; some shared views use conditional AppKit/UIKit for platform-specific rendering. |
| `TFM` / `TFI` | Native composition, interaction, navigation, adapters, and runtime lifetimes. | macOS windows and mobile scenes are deliberately different owners. |
| `Frameworks/Resources` | Shared bundle assets, localization, model catalogs, and privacy metadata. | A resource group, not a seventh framework. |
| `AgentKit` | Reference checkout of the separately versioned, host-neutral agent package. | Xcode consumes the resolved remote package, not this checkout. |
@@ -147,6 +149,21 @@ This split is also a placement rule: shared behavior belongs with its existing o
## Composition and state boundaries
The composition boundary is directional: app entrypoints choose concrete adapters and inject them into shared feature models; the resulting workspaces have a different owner on each platform. A scene or window route is not a durable store or a transport.
```mermaid
flowchart LR
DesktopEntry["TermindApp"] --> DesktopApp["AppModel and shared stores"]
DesktopEntry --> DesktopWindow["WindowModel per main window"]
DesktopWindow --> DesktopWorkspaces["Window workspaces"]
MobileEntry["TermindIOSApp"] --> MobileApp["MobileAppModel and live workspaces"]
MobileEntry --> MobileRoot["MobileRootView"]
MobileRoot --> MobileScene["MobileSceneModel per scene"]
MobileScene -->|"selects by ID"| MobileApp
```
Composition and navigation lifetimes: desktop windows own their workspace collection, while mobile scenes reference app-owned live workspaces.
`TFM/App/TermindApp.swift` is the desktop `@main` entrypoint. It opens the Persistence container, wires stores, Keychain-backed secrets, sync and connection coordinators into an app-wide `AppModel`, and injects that model and container into each `WindowGroup` root. Each main window receives its own `WindowModel`; a separate authentication window uses the shared app environment. A failed desktop database open ends launch with `fatalError`. On mobile, `TFI/App/TermindIOSApp.swift` is the actual `@main`, **not** `MobileAppModel.swift`: it chooses live versus test dependencies, creates one `MobileAppModel` and supplies its container to the scene root, or shows an unavailable-content view if initialization throws. `MobileAppModel` assembles SwiftData, Keychain or in-memory secrets, remote services, sync coordinators, Assistant and workspaces. In the in-memory/test path it disables live sync and Live Activities. `MobileSceneModel` resolves selected workspace IDs against app-owned live instances rather than owning connections itself.
- **Process-wide:** shared stores, service coordinators, and application models.
@@ -159,4 +176,4 @@ For lifetime diagrams, continue with [Native App Directory Responsibilities](nat
## Verifying a boundary change
`TFMTests/ArchitectureBoundaryTests.swift` checks import and ownership restrictions: Domain stays free of platform and transport libraries, Application cannot construct concrete implementations, Persistence cannot import Infrastructure or Remote Infrastructure, shared Presentation avoids app and storage dependencies, and native Features do not reach directly into storage or transports. It also checks that the forwarding benchmark is not pulled into apps or tests and that AgentKit-owned runtime types are not redefined in the app. These source-level guards complement rather than replace the Xcode target graph: when moving a capability, inspect both the destination target's dependency/package-product list and these tests. Use the pinned-resolution build/test commands in [Engineering Quickstart](../quickstart.md).
`TFMTests/ArchitectureBoundaryTests.swift` supplies **source-level** guards alongside the Xcode target graph, not a blanket ban on UI or platform APIs everywhere. Its import scan excludes `Termind` and `TermindIOS` plus AppKit, UIKit, IOKit, and ServiceManagement from Domain, Application, Infrastructure, Remote Infrastructure, and Persistence; the separate Presentation check excludes app imports, storage and implementation modules, StoreKit, AppKit, and UIKit. However, the import helper checks only exact `import Module` lines, and shared Presentation currently uses conditional AppKit/UIKit imports for rendering; treat those platform exclusions as test intentions, not proof that every shared view is platform-agnostic. Domain also excludes storage, transport, and UI libraries; Application excludes concrete implementation imports and selected construction tokens; Persistence excludes Infrastructure and Remote Infrastructure imports. Native UI and feature restrictions are scoped: mobile `Application` excludes UI and storage imports, mobile `UI` excludes storage and Remote Infrastructure imports, desktop `Features` excludes selected storage and transport imports, and feature directories are checked for specific direct construction/access tokens. This does **not** forbid all framework imports in every native feature. The test also rejects declarations of a named subset of AgentKit-owned runtime types in the desktop source tree, not every AgentKit-related type across the repository; Termind still owns host-specific tool registrations. Further checks protect SwiftData model/repository placement and the forwarding benchmark's independence from app/test targets. When moving a capability, inspect both target/package-product edges and the precise test scope. Use the pinned-resolution build/test commands in [Engineering Quickstart](../quickstart.md).
@@ -3,6 +3,9 @@ type: architecture directory guide
title: Native App Directory Responsibilities
description: Directory ownership in the macOS and iOS apps, including desktop window composition, MCP transfer policy, and mobile scene, sync, and background lifetimes.
tags: [architecture, directories, macos, ios, ipados, navigation, lifecycle]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-c4b6e224fdbea6dcd393344d
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift
@@ -74,6 +77,8 @@ sources:
resource: repo://TFM/Application/Serial/SerialPortService.swift
- id: openwiki-source-d35453512ef488d0cacdc06e
resource: repo://TFM/Features/Assistant/AssistantView.swift
- id: openwiki-source-391dd36408ff1c7fc7c1c335
resource: repo://TFM/Features/Settings/MCPSettings.swift
- id: openwiki-source-cfe2a6b22338023c37a5b503
resource: repo://TFM/Features/Settings/SettingsPageView.swift
- id: openwiki-source-a93c339a06b550013d027e29
@@ -108,12 +113,11 @@ sources:
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-47dc468698b2904f0004ee04
resource: repo://TFMTests/MCPUploadTests.swift
- id: openwiki-source-44cb7a6172854edbfc9b5ccb
resource: repo://TFMTests/SettingsNavigationTests.swift
- id: openwiki-source-ea148dc5de8cabfc00dc07ae
resource: repo://TFMTests/WindowSidebarTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Native App Directory Responsibilities
@@ -163,7 +167,7 @@ The app composition roots also adapt platform device naming into the shared devi
| `Transfers` | SFTP browser/channel state and remote-file operations, distinct from the process-wide transfer queue. |
| `Workspaces` | Persistable connection-intent descriptors and connection-history coordination, not live terminal surfaces. |
The mobile service contracts can mention remote types, but do not construct the live transport implementation. Architecture checks prohibit UI and persistence imports in app Application directories; they do not make every platform-local type a portable shared-framework type.
The mobile service contracts can mention remote types, but do not construct the live transport implementation. `ArchitectureBoundaryTests` checks different boundaries for the two app Application directories: both reject UI and concrete implementation access, but the mobile checks also reject SwiftData, GRDB and `TermindPersistence`, while the desktop checks prohibit AppKit, Security, Network and other concrete framework imports and scan for direct persistence/transport construction. Feature code is likewise checked for concrete construction; neither app-local Application directory is thereby a portable shared-framework layer. The same tests enforce that `@Model` schemas and `SwiftData*Repository` declarations stay in `TermindPersistence`, even though desktop `Infrastructure/Database` can provide convenience adapters over those repositories.
The desktop MCP split illustrates **placement versus lifetime**. `MCPServerController` in `App` owns the server configuration and coordinates start/stop, Pro gating, port changes, token rotation and transfer shutdown. Its `MCPServerTools` in `Application/MCPServer` owns the exported tool registry and upload/download coordinators; it wires authenticated SFTP operations from shared remote infrastructure. `Infrastructure/Networking` serves loopback HTTP bytes, `Infrastructure/MCP` handles protocol sessions, and `Infrastructure/Security` stores the server token. A tool call creates a run-bound upload ticket; the controller routes a `PUT /uploads/{id}` stream to `MCPUploadCoordinator.prepare`, which checks origin, bearer upload token, method, headers, remaining length and acknowledged resume offset **before** claiming capacity or starting audit/transfer work. A disconnect or recoverable transfer failure can pause a ticket for retry at its acknowledged offset; integrity failure, cancellation or expiry cannot be retried. Commit succeeds only after the remote streaming operation returns; session/host revocation and server stop cancel tickets and drain tasks. The transfer budget and audit belong to application operations, not the view that exposes settings. See [MCP Server and Bridge](../integrations/mcp-server-and-bridge.md) for the external protocol.
@@ -187,7 +191,7 @@ Every current immediate child of either `Features` directory is included here.
| `QuickOpen` | Keyboard-oriented quick navigation/connection surface. | Not present. |
| `SFTP` | Browser, channel model, file context menus, and Open With menu. | Browser, remote text editor, edit preview, and browsing/download history. |
| `SSHImport` | Desktop SSH-config/key import preview and selection UI. | Not present. |
| `Settings` | App/terminal/sync settings, AI providers/models/roles, skills, MCP client/server setup, web search, developer options, and log-file management. | App/terminal/SFTP/sync settings, AI providers/models, remote MCP configuration, skills, and logging. No desktop loopback MCP-server setup surface. |
| `Settings` | Window-local settings index and detail routes for app/startup, terminal, SSH/SFTP connections, AI providers/models/roles, skills, MCP client and local server, web search, sync, logging, and debug-only developer options. The pages edit app-owned models rather than own the sync or MCP server lifetime. | App/terminal/SFTP/sync settings, AI providers/models, remote MCP configuration, skills, and logging. No desktop loopback MCP-server setup surface. |
| `Shell` | Window destination/route and title values. | Mobile destination and navigation values. **Neither folder is the remote shell protocol implementation.** |
| `Sidebar` | One window-local column with Navigator, contextual Assistant, Snippets and focus-sensitive History modes; the window model owns mode and visibility. | Not present; mobile uses its registered tab/sidebar navigation shell. |
| `Snippets` | Snippet library and actions. | Mobile snippet library and actions. |
@@ -225,13 +229,17 @@ flowchart TD
Mobile navigation dispatches scene-local intent to app-owned data and runtime; the Vault file is not the lifetime boundary.
On macOS, `TermindApp` creates one `AppModel` and SwiftData container, but its `WindowGroup` creates a `WindowModel` for each `RootView`. `RootView` mounts `WindowSidebarView` in a `NavigationSplitView` beside a persistent detail deck. Sidebar mode and visibility are per-window: the rail chooses Navigator, compact Assistant, Snippets or History. History shows command history for a focused SSH pane, browse history for SFTP, or connection history otherwise; it is disabled for focused serial/Telnet panes, and an invalid current History mode falls back to Snippets. Clicking Assistant outside a workspace navigates to the full Assistant destination, while Navigator returns from it; assigning a mode for presentation alone is not the same as activating its navigation behavior. `TFMTests/WindowSidebarTests.swift` covers window isolation and the focused-serial fallback; `TFITests/MobileVaultFeatureTests.swift` covers host menu filtering, duplication, group deletion and proxy defaults, and `TFITests/MobileConnectionPickerTests.swift` covers History's limit and search.
On macOS, `TermindApp` creates one `AppModel` and SwiftData container, but its `WindowGroup` creates a `WindowModel` for each `RootView`, injecting the shared app and container. It also declares a separate external-authentication `Window` scene; the native `AppDelegate` manages activation, reopen, login-launch behavior and termination rather than making any Settings page an app lifecycle owner. In particular, quit first rechecks pending SFTP edits and may cancel termination; after consent it saves window size and starts app shutdown, replying once after cleanup or a three-second timeout. The app's database-open failure is fatal at composition time, not a Settings error.
`RootView` mounts `WindowSidebarView` in a `NavigationSplitView` beside a persistent workspace deck. Switching to Vault, Assistant, Metrics or Settings covers the deck without unmounting its workspace views and sessions. Sidebar mode and visibility are per-window: the rail chooses Navigator, compact Assistant, Snippets or History. History shows command history for a focused SSH pane, browse history for SFTP, or connection history otherwise; it is disabled for focused serial/Telnet panes, and an invalid current History mode falls back to Snippets. Clicking Assistant outside a workspace navigates to the full Assistant destination, while Navigator returns from it; assigning a mode for presentation alone is not the same as activating its navigation behavior.
Settings is a **window destination**, not a second app-wide scene. `RootView` displays `SettingsPageView` for `.settings`; `WindowModel.settingsRoute` records the index, category or detail route and remembers the destination Settings replaced. Back walks the route's parent before closing; closing resets to index and restores the previous destination, falling back to Vault if its workspace was removed. `SettingsPageView` assembles the category forms and detail editors, with remote MCP editor access guarded by Pro; its `MCPServerSettings` route edits the app's local server configuration, not the HTTP listener. Leaving provider, MCP server or skill editors discards qualifying empty drafts; nonempty skill drafts remain available and an MCP draft must lock a unique namespace. App preferences and service models remain app-owned, while only transient route and newly-created-provider UI state belong to the window/view. `TFMTests/SettingsNavigationTests.swift` covers back/return behavior, removed-workspace fallback and draft policy; `TFMTests/WindowSidebarTests.swift` covers window isolation and the focused-serial fallback. `TFITests/MobileVaultFeatureTests.swift` covers host menu filtering, duplication, group deletion and proxy defaults, and `TFITests/MobileConnectionPickerTests.swift` covers History's limit and search.
## Infrastructure subdirectories
| TFM directory | Responsibility |
| --- | --- |
| `Database` | App-facing SwiftData adapters and convenience wiring for history/audit models. It uses Persistence-owned entities; it does not define a second model schema. |
| `Database` | App-facing SwiftData convenience wiring for history models using repositories declared in `TermindPersistence`; it does not define a second model schema or repository implementation. |
| `Repositories` | Factories that connect feature/library models to persistent stores. |
| `MCP` | MCP protocol/session handling on top of the local HTTP transport. |
| `Networking` | Loopback HTTP listener and request/response transport. |
+19 -10
View File
@@ -3,6 +3,9 @@ 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-24T03:18:19.992Z
sources:
- id: openwiki-source-875da2c4f1040409e53757af
resource: repo://Frameworks/TermindApplication/Events/HostDeletionHandlers.swift
@@ -60,16 +63,17 @@ sources:
resource: repo://TFM/Platform/MainWindowCoordinator.swift
- id: openwiki-source-73c75477db0674192248aa00
resource: repo://TFMTests/AppTerminationTests.swift
- id: openwiki-source-39248df19c48bb72235c6e8d
resource: repo://TFMTests/AppTestHostTests.swift
- id: openwiki-source-d3d065330c730839f5cc6112
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-531f6567ecf96fd4b0c5e97a
resource: repo://TFMTests/ExternalConnectionURLTests.swift
- id: openwiki-source-32c251eb2f83ec0be2f1a0e8
resource: repo://TFMTests/RepositoryOutboxTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
- id: openwiki-source-a08489338be00125d646c77e
resource: repo://TFMTests/VisibleWindowTestTrait.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Platform Runtime, App Composition, and Lifetimes
@@ -100,7 +104,9 @@ A useful consequence is that sharing a desktop `AppModel` does **not** make its
## 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, the reusable device directory, and the common `RemoteConnectionCoordinator`. The directory uses the Vault journal's stable installation ID and `MacDeviceName.current`: the trimmed `kern.hostname`, falling back to DeviceKit's `Device.current.safeDescription` when unavailable or empty. Startup fails closed: an inability to open the local database calls `fatalError` rather than substituting an empty store.
`TermindApp.init()` is the desktop composition root. Before opening data it cleans previous context attachments, sets up the scrubber web client and chooses the stored launch language (or a screenshot-demo language). A normal launch constructs one on-disk SwiftData `ModelContainer`, prepares settings and metrics persistence, makes the Keychain-backed secret store, and assembles `AppModel` with repositories, sync coordinators, logging, histories, the device directory, and a common `RemoteConnectionCoordinator`. The directory uses the Vault journal's stable installation ID and `MacDeviceName.current`: the trimmed `kern.hostname`, falling back to DeviceKit's `Device.current.safeDescription` when unavailable or empty. Startup fails closed: an inability to open the local database calls `fatalError` rather than substituting an empty store.
**Debug test and screenshot launches still run the real app entrypoint, but not the normal disk-backed runtime.** XCTest detection uses `XCTestConfigurationFilePath` in DEBUG; it selects an in-memory container, a private metrics defaults suite, disabled file logging, unrestricted test Pro access, no Vault/Settings/Metrics cloud coordinators, no local host defaults or production memory store, and a window size store without persisted defaults. A screenshot-demo configuration also uses an in-memory container but returns early with demo hosts, AI, metrics and onboarding instead of constructing the normal production services. Neither path is a fallback for a failed production database open: construction errors still fail startup.
```mermaid
flowchart TD
@@ -131,7 +137,9 @@ This diagram shows the desktop composition root and the split between one app ru
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. A desktop deletion request first persists the repository marker/outbox jobs, clears local histories and projects the Host away; the registered outbox handlers close panes across windows, cancel transfers, stop forwarding and finalize repository cleanup. A failed request reports a storage error instead of projecting the removal. 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.
`TermindApp` creates a `WindowGroup(id: "main", for: UUID.self)`. Each scene receives a fresh `WindowModel` (except a request-less debug screenshot scene, which can receive demo window state), places it in `RootView`, and injects the same `AppModel` and SwiftData container through the SwiftUI environment. `RootView` retains that model in `@State`, registers it on appearance, and exposes it via the environment and focused scene value. The independent `Authentication Request` window shares app dependencies but is reserved for external authentication presentation; `.commandsRemoved()` prevents normal Window-menu creation.
**Scene policy is separate from store policy.** In DEBUG, a default XCTest host suppresses automatic launch of both the main and authentication scenes unless `TERMIND_WINDOW_TESTS=1` or screenshot-demo mode is active. Tests disable restoration for both scenes even when visible windows are opted in; screenshot mode disables main-scene restoration, while ordinary launches use automatic launch and restoration. The delegate also refuses Dock reopen while test-window suppression applies, refuses to quit the test host when its last fixture window closes, and skips starting metrics activity/menu in tests. Explicit window/focus tests use `.requiresVisibleWindow` and opt in with `TERMIND_WINDOW_TESTS=1` (or Xcode's `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` forwarding); suppression is not a ban on explicitly created offscreen test fixtures. The default test-host checks assert no visible windows and no reopen.
### Window-local desktop state
@@ -139,13 +147,13 @@ The model keeps only weak registrations for open `WindowModel`s. Registration in
A host-opening action is centralized in `AppModel`, which chooses the requested protocol, but it opens into the caller's `WindowModel`. That window assigns one connection-history event to each saved-host SSH, Telnet or SFTP pane. Closing the pane/workspace ends the event before disconnecting, while moving a live pane preserves it and reopening creates a new event. External temporary and Serial panes are not recorded; a crash may leave `endedAt` absent. 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.
`MainWindowCoordinator` binds native `NSWindow`s to `WindowModel`s. It processes new-window and workspace-move requests, preserves system-restored frames (a restored scene has no pending move request), saves normal window size only at appropriate boundaries, and unregisters then closes a model when its native window closes. Restoring a window thus does not replay a moved workspace or reopen its live connection. 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 both entitlement state and the current `DeviceRecord` display name from `MacDeviceName.current`; the synchronized directory can therefore update without rewriting connection events. TFI refreshes its name directly from DeviceKit's `Device.current.safeDescription` on active-scene transitions. On termination the desktop app first checks for pending external edits; after user confirmation, it saves window sizing and invokes `AppModel.shutdownForTermination()`.
The AppKit delegate starts native appearance/login handling and, outside tests, starts metrics activity and the metrics menu once `AppModel` is available. For quiet login launches it hides the normally constructed window rather than running window-less; a one-shot key-window observer and three-second disarm prevent a later user-opened window from being hidden. On app activation it refreshes both entitlement state and the current `DeviceRecord` display name from `MacDeviceName.current`; the synchronized directory can therefore update without rewriting connection events. TFI refreshes its name directly from DeviceKit's `Device.current.safeDescription` on active-scene transitions. On termination the desktop app 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 fences new assistant runs, cancels pending run preparation, stops all stored conversations and waits for their terminal saves; it also suspends memory and edit monitoring, stops metrics and speech, closes windows, and cancels SFTP work, external authentication, forwarding, and the outbox. It concurrently awaits MCP and SFTP cancellation, then closes agent background commands and connection pools **after** the assistant drains. The delegate replies to macOS when cleanup completes or after a three-second fallback; that bound applies to the quit reply, not a guarantee that every asynchronous drain finished. `applicationWillTerminate` repeats cleanup safely.
Shutdown is deliberately idempotent and bounded by the delegate. `applicationShouldTerminate` returns `.terminateLater` while it rechecks external SFTP edits; if pending changes exist and the user cancels the alert, it replies `false`, clears the pending-termination flag and does **not** start cleanup. An accepted quit saves the ordinary window size before cleanup. `shutdownForTermination()` immediately fences assistant admission, cancels pending run preparation, stops the app-wide conversation store (including conversations no longer shown in a registered window) and awaits terminal saves; it also suspends memory and edit monitoring, shuts down metrics and speech, closes registered windows, and cancels SFTP work, external authentication, forwarding and the outbox. It concurrently awaits MCP and SFTP cancellation, then closes agent background commands and connection pools **after** the assistant drains. Repeated calls return the same cleanup task. The delegate replies `true` to macOS when cleanup finishes or after a once-only three-second fallback; that bound applies to the quit reply, **not** a guarantee that every asynchronous drain finished. `applicationWillTerminate` repeats cleanup safely.
## Mobile composition
@@ -237,7 +245,8 @@ Tests exercise the lifetime contracts rather than merely constructing views:
- `MobileForwardingLifecycleTests` verifies all-scenes background is required before expiration, and expired forwarding/authentication does not revive merely on foreground.
- `MobileBackgroundControllerTests` covers stale callbacks, exactly-once task retirement, synchronous expiration during lease acquisition and invalid UIKit identifiers; `MobileAppTests` covers scene removal and quick versus expired foreground returns.
- `MobileHomeScreenQuickActionTests` covers recent-host shortcut selection, payload decoding and one-shot consumption by the scene delegate.
- `AppTerminationTests` verifies shutdown cancels stored and preparing assistant work, waits for terminal saves before closing agent resources, fences new work, and replies once even when the three-second fallback wins.
- `AppTestHostTests` checks default test-host window suppression, Dock-reopen refusal and survival after the last fixture window closes; `.requiresVisibleWindow` gates tests that actually show windows or take focus.
- `AppTerminationTests` verifies shutdown cancels stored and preparing assistant work, joins even an unstored captured failure before closing agent resources, fences new work, and replies once whether cleanup or the three-second fallback wins.
- `RepositoryOutboxTests` verifies a Host deletion request commits the hiding marker and complete outbox atomically.
- `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.
+28 -10
View File
@@ -3,6 +3,9 @@ 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-24T03:18:19.992Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
@@ -26,24 +29,27 @@ sources:
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift
- id: openwiki-source-d2d4c06f734241db3badc1f5
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift
- id: openwiki-source-27d6a8d3b199ecf35f59fafb
resource: repo://Scripts/swiftdata-repository-declarations.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-dc9295278cc250ed20567540
resource: repo://TFI/App/MobileAppDependencies.swift
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-6c9f797fc6a1e7ce639b72b8
resource: repo://TFI/App/TermindIOSApp.swift
- id: openwiki-source-c52cd56852d12b2dee153082
resource: repo://TFM/App/AppDependencies.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-68b5f4529ef349aac826b1d9
resource: repo://TFM/Platform/MacDeviceName.swift
- id: openwiki-source-d3d065330c730839f5cc6112
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# System Boundaries and Dependency Ownership
@@ -77,20 +83,32 @@ For a directory-oriented view, start with the [Module and Directory Architecture
| 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. |
| `TermindApplication` | Use cases, feature models, repository and service ports, connection/import policy, and cross-feature policy. | Platform UI, SwiftData/GRDB, transport imports, concrete infrastructure construction, and dependencies on Infrastructure or Persistence. |
| `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, `ModelContainer` factory, and GRDB-backed memory store. | 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. |
| `TermindPresentation` | Reusable SwiftUI presentation policy and content: formatting, forms, summaries, transcript/tool-card rendering, and terminal presentation helpers. | AppKit/UIKit, SwiftData/GRDB/Persistence, Infrastructure/Remote Infrastructure, StoreKit, 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 selected production Swift source roots rather than relying on conventions alone. Domain cannot import the listed platform/UI, storage, security, network, commerce, SSH, or terminal modules. Shared Application cannot import listed UI/storage/transport modules or construct selected concrete persistence, SSH/SFTP, and URL-session symbols; desktop `Application` gets the same construction guard, while desktop `Features` gets a storage/transport import and construction guard. Mobile `Application` and `UI` have separate import restrictions, and mobile `Features` get the construction guard. Presentation is separately prohibited from importing platform UI, persistence, or Remote Infrastructure. These are exact import-string and token scans, **not** a complete compiler-enforced architecture or ban on every concrete implementation: in particular, app composition roots intentionally import SwiftData and concrete frameworks.
`ArchitectureBoundaryTests` checks **specific forbidden import sets per root**, not a blanket prohibition on platform APIs or concrete dependencies. Its exact-line import scans currently enforce:
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.
| Scanned source root | Imports rejected by the test |
| --- | --- |
| Shared `TermindDomain` | `SwiftUI`, `AppKit`, `UIKit`, `SwiftData`, `GRDB`, `Security`, `Network`, `StoreKit`, `CloudKit`, `CSSH2`, `OpenSSL`, `GhosttyTerminal`, `GhosttyTheme`; also the shared non-presentation rule below. |
| Shared `TermindApplication` | `TermindInfrastructure`, `TermindPersistence`, `SwiftData`; also the shared non-presentation rule below. Unlike desktop `TFM/Application`, this root has no separate UI/transport import list, but does have the concrete-symbol guard. |
| Shared `TermindInfrastructure` and `TermindRemoteInfrastructure` | Only the shared non-presentation rule below; for example, Infrastructure can use StoreKit and Remote Infrastructure can use its transport libraries. |
| Shared `TermindPersistence` | `TermindInfrastructure`, `TermindRemoteInfrastructure`; also the shared non-presentation rule below. |
| **Shared `TermindPresentation`** | Its **separate** rule rejects `Termind`, `TermindIOS`, `UIKit`, `AppKit`, `SwiftData`, `GRDB`, `TermindPersistence`, `TermindRemoteInfrastructure`, `TermindInfrastructure`, `StoreKit`. It intentionally can import `SwiftUI`; it is not covered by the other five-framework rule. |
| Desktop `TFM/Application` | `SwiftUI`, `AppKit`, `UIKit`, `SwiftData`, `GRDB`, `Security`, `Network`, `CSSH2`, `OpenSSL`, `GhosttyTerminal`, `GhosttyTheme`, plus the concrete-symbol guard. |
| Desktop `TFM/Features` | `SwiftData`, `GRDB`, `Security`, `Network`, `CSSH2`, `OpenSSL`, plus the concrete-symbol guard. |
| Mobile `TFI/Application` | `SwiftUI`, `UIKit`, `SwiftData`, `GRDB`, `TermindPersistence`. |
| Mobile `TFI/UI` | `SwiftData`, `GRDB`, `TermindPersistence`, `TermindRemoteInfrastructure`. Mobile `TFI/Features` gets only the concrete-symbol guard. |
The shared non-presentation rule (Domain, Application, Infrastructure, Remote Infrastructure, Persistence) rejects `Termind`, `TermindIOS`, `AppKit`, `UIKit`, `IOKit`, and `ServiceManagement`. Separate tests reject app-local `AppStrings` definitions and constrain imports in Presentation's `Strings` directory. The concrete-symbol guard on shared Application, desktop Application/Features, and mobile Features looks for `ModelContext`, `FetchDescriptor`, `KeychainSecretStore`, `SFTPClient()`, `SSHConnection()`, and `URLSession(`; it does **not** run on mobile Application or UI. The import check matches literal `import Module` lines and the token check scans a fixed list after stripping `//` suffixes: these are regression checks, **not** proof of an exhaustive compiler-enforced boundary or a ban on all concrete code. Composition roots deliberately import SwiftData and concrete frameworks. Use injected ports across a boundary rather than a re-export, forwarding alias, generic “Core” module, or framework-to-app reference.
## Persistence is a single-owner boundary
@@ -98,13 +116,13 @@ The checks also prohibit all shared frameworks from importing `Termind` or `Term
Connection history follows the same boundary: Domain owns the portable event value, Application owns the observable model and repository protocol, and Persistence owns its SwiftData shape and Vault-journal transaction. The reusable ID-to-name mapping is deliberately separate: Domain owns `DeviceRecord`, Application owns `DeviceDirectoryModel` and `DeviceDirectoryRepository`, and Persistence owns `PersistentDeviceRecord` plus the SwiftData adapter. A history event merely references `sourceDeviceID`; it does not own or capture the device name. Platform apps inject connection lifecycles, acquire their native system display name, and choose local versus all-device presentation; they do not declare stored models.
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 in scanned desktop, mobile, Domain, Application, and Infrastructure roots and requires Persistence to contain Swift files; the scan does not currently include Remote Infrastructure or Presentation. A new persisted SwiftData entity therefore requires a Persistence schema/migration decision—not a model embedded in a feature, app, or general infrastructure module.
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 in scanned desktop, mobile, Domain, Application, and Infrastructure roots and requires Persistence to contain Swift files; the `@Model` scan does not currently include Remote Infrastructure or Presentation. A separate SwiftData-repository-declaration check covers those two roots as well as both apps, the other shared frameworks, bridge, benchmark, widget, and workspace-activity support targets; it uses a Swift declaration parser and requires at least one such declaration in Persistence. These checks still do not constitute an exhaustive ownership proof. A new persisted SwiftData entity therefore requires a Persistence schema/migration decision—not a model embedded in a feature, app, or general infrastructure module.
Desktop calls `TermindPersistence.makeContainer` with in-memory storage for tests and screenshot demos; an unavailable local database causes a startup `fatalError`, rather than silent replacement with an empty store. Mobile `MobileAppModel` uses an injected container when provided, otherwise calls the same factory with a file under Application Support for live storage or in-memory storage for tests/injected hosts. `TermindIOSApp` builds the model once 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 also supplies `MacDeviceName.current` to the shared device-directory port (trimmed `kern.hostname`, with DeviceKit's `Device.current.safeDescription` as fallback). 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`; the mobile composition uses DeviceKit's description directly for the device-directory port. This is where a concrete implementation or platform value becomes a port supplied to shared feature code.
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 also supplies `MacDeviceName.current` to the shared device-directory port (trimmed `kern.hostname`, with DeviceKit's `Device.current.safeDescription` as fallback). It injects the shared model and container into its window scenes. `AppDependencies` packages repository, connection, sync, logging, and optional shutdown services for the desktop model and provides an in-memory host repository for tests. On mobile, `MobileAppDependencies.live()` wires logging and one connection coordinator into workspace and metrics services; `testing()` defaults to in-memory storage and replaceable dependencies. `TermindIOSApp` selects one of these at startup, creates one `MobileAppModel`, and injects its container into the `WindowGroup`; the mobile composition uses DeviceKit's description directly for the device-directory port. This is where a concrete implementation or platform value becomes a port supplied to shared 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.
@@ -3,6 +3,9 @@ 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-24T03:18:19.992Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
@@ -18,6 +21,10 @@ sources:
resource: repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift
- id: openwiki-source-a298d9034d557f1b420cb306
resource: repo://Frameworks/TermindPresentation/ProOfferPresentation.swift
- id: openwiki-source-ff6aeac237822b937eb60926
resource: repo://Frameworks/TermindPresentation/ProPaywallContent.swift
- id: openwiki-source-f9f51dced2f50e794fadc9ab
resource: repo://Frameworks/TermindPresentation/ProPaywallPresentation.swift
- id: openwiki-source-2d3fd78e62a89dd2c0b202e6
resource: repo://Frameworks/TermindPresentation/Strings/AppStrings.swift
- id: openwiki-source-667f8dcadd921c1910c5026c
@@ -28,6 +35,10 @@ sources:
resource: repo://Frameworks/TermindPresentation/Strings/Presentation.swift
- id: openwiki-source-eae5d91412d0e2847dacd5b6
resource: repo://FrameworkTests/AppReviewControllerTests.swift
- id: openwiki-source-3b424584de88a1150af27f83
resource: repo://FrameworkTests/ProOfferPresentationTests.swift
- id: openwiki-source-925cc598397685e13fcf56c4
resource: repo://FrameworkTests/ProPaywallPresentationTests.swift
- id: openwiki-source-103853faf6b28763354a1c79
resource: repo://LandingPage/package.json
- id: openwiki-source-554fe71f1ba6efebee0d020c
@@ -38,6 +49,8 @@ sources:
resource: repo://Scripts/check-presentation-copy.swift
- id: openwiki-source-41a7ded3800c9422f058a3ef
resource: repo://Scripts/check-zh-localization.sh
- id: openwiki-source-de562e98d49cbf6502c23c13
resource: repo://Scripts/normalize-string-catalogs.py
- id: openwiki-source-60d4159ef162d09de4f4b469
resource: repo://Scripts/run-screenshot-demo.sh
- id: openwiki-source-9fc915d39c61b81a60426eb3
@@ -92,10 +105,7 @@ sources:
resource: repo://TFMTests/StoreKitTrialTests.swift
- id: openwiki-source-0f8d0f9d08d6674698dd054c
resource: repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift
generated: { by: "codex", at: "2026-09-23T14:32:50.942Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
## Scope and ownership
@@ -134,7 +144,25 @@ The gate set is intentionally narrower than the product’s general remote-works
### 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. `ProOfferPresentation` turns StoreKit price, billing period, free-offer duration, and eligibility into the localized button, badge, and renewal terms: it advertises a trial only when StoreKit reports an eligible free introductory offer, falls back to “Subscribe Annually” if the offer is missing or ineligible, and describes lifetime access without renewal. Both paywalls reload products when opened and disable a plan without an available validated product; the macOS paywall also exposes a price-reload action when either offer is missing.
Both platforms use `ProPaywallContent` for the same status card, feature list, annual/lifetime picker, offer terms, restore, price reload, legal links, Family Sharing disclosure, and separate AI-provider charges. Native wrappers supply platform colors, actions, and a `ProPaywallPresentation` snapshot built from the shared controller. Its `ProAccessPresentation` maps entitlement phase, ownership, expiry, renewal and verification failure to a shared localized label and date meaning; a canceled renewal shows **Access Ends** while the subscription still grants access. Only purchaser-owned subscriptions expose Manage Subscription, not family-shared subscriptions or lifetime access. The content shows the free Metrics limit when that feature triggered the paywall, and chooses the MCP feature label using `supportsMCPServer`: macOS advertises remote tools **and** the built-in MCP server; iOS advertises remote MCP tools only. Processing and errors remain visible even when access already exists, while purchase actions otherwise follow `status.canPurchase`. Missing prices offer reload on **both** platforms; a plan requires its validated product, non-missing price and purchase permission and is disabled during processing.
```mermaid
flowchart TD
Gate["Pro feature gate or open Pro"] --> Platform{"Platform"}
Platform -->|macOS| Mac["Main-window paywall owner"]
Platform -->|iOS| Mobile["Mobile root sheet"]
Mac --> Snapshot["Controller status and validated products"]
Mobile --> Snapshot
Snapshot --> Content["Shared paywall content and offer formatting"]
Content --> Purchase["Purchase or restore on controller"]
Content --> Manage{"Purchaser-owned subscription"}
Manage -->|macOS| Account["Apple account subscriptions URL"]
Manage -->|iOS| SystemSheet["System management sheet"]
```
The common paywall content consumes platform-owned presentation snapshots and delegates commerce actions back to the shared controller.
`ProPaywallPresenter` elects one macOS main-window sheet owner; `MobileRootView` binds the shared paywall flag to `MobileProView` as a native sheet. The macOS wrapper opens Apple’s subscriptions URL; iOS uses `.manageSubscriptionsSheet`. Both reload products on opening, default to annual and switch to lifetime when only that product loads, route annual/lifetime purchase and restore to the controller, and retain platform-owned close affordances. `ProOfferPresentation` formats StoreKit's annual price, billing period and eligible free introductory duration using the view locale and an explicit app-catalog localization callback. It converts `weekOfYear` trial durations into their full day count (for example two weeks becomes 14 days) because `DateComponentsFormatter` does not format StoreKit weeks; singular billing periods use localized year/month/week/day, and composite periods format one full unit. Eligibility chooses “Start Free Trial” versus “Subscribe Annually”; a missing duration suppresses the badge and trial-term detail rather than inventing a duration, even if the eligible title remains. Missing price or billing period suppresses annual detail. Lifetime copy always states one payment without renewal. The controller validates the annual product shape and free introductory offer before reporting eligibility; no hard-coded price or free-trial guarantee should replace these values.
## Review invitation policy
@@ -146,11 +174,11 @@ Eligibility requires at least seven days since first use, three distinct active
Define app-facing copy as semantic `LocalizedStringResource` entries in `Frameworks/TermindPresentation/Strings`, **including copy used on only one platform**. `AppStrings` groups navigation, feature and common wording for both TFM and TFI; share an entry for the same meaning and use explicit variants when the platform action or wording differs. Keep protocol values, identifiers, diagnostic codes and user-authored content with their existing owners rather than treating them as translatable UI literals. The `Strings` directory owns definitions and reusable formatting, not a shared native view or a separate resource bundle.
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.
User-facing app strings belong in `Frameworks/Resources/Localizable.xcstrings`, which is compiled into every app bundle; bundle metadata belongs in `Frameworks/Resources/InfoPlist.xcstrings`. **Both app catalogs are manual:** every entry must have `extractionState: "manual"`. Extraction by one target cannot see all shared and platform-specific usages, so a `stale` marker is not evidence that an entry can be removed; search TFM, TFI and shared modules first. Add keys and finished translations explicitly. After any catalog edit run `Scripts/normalize-string-catalogs.py --write` for canonical Xcode ordering and formatting without changing translations; `Scripts/check-zh-localization.sh` runs the read-only `--check` first. Do not run `jq -S` or a generic JSON formatter on the catalogs. Keep `STRING_CATALOG_GENERATE_SYMBOLS = NO` so generated names do not compete with `AppStrings`. The normalizer defaults to these two app catalogs and does not touch the separate AgentKit runtime catalog, `../AgentKit/Localizations/Localizable.xcstrings`; rebuild AgentKit localization with `../AgentKit/Scripts/build-localizations.sh` after its changes because a plain Swift build copies those resources rather than compiling them.
An `AppStrings` entry produces a resource on demand; resolve it at the display boundary rather than caching a translated `String` across language changes. SwiftUI can consume the resource directly, or use `swiftUIKey` where an API needs `LocalizedStringKey` (ordinary `String` conversion loses resource localization metadata). For imperative/native menus or count-dependent messages, `AppLocalization.resolve(_:locale:)` selects the requested locale from the app's main-bundle catalog and shared formatting selects appropriate singular/plural resources while preserving literal names and paths. `PresentationCopyTests` exercises English, `zh-Hans`, and `zh-Hant` resolution, nested menus, count messages, accessibility copy and the SwiftUI key bridge.
`AppLanguage` stores the explicit `en`, `zh-Hans`, or `zh-Hant` choice as `AppleLanguages`, removes that override for Follow System, and migrates legacy Simplified Chinese preference tags to `zh-Hans`; unsupported stored tags follow the system rather than being silently rewritten. `AppLocalization` selects the matching main-bundle localization for explicit and system locales (including regional Traditional Chinese) so imperative presentation can use the effective language. An `AppStrings` entry produces a resource on demand; resolve it at the display boundary rather than caching a translated `String` across language changes. SwiftUI can consume the resource directly, or use `swiftUIKey` where an API needs `LocalizedStringKey` (ordinary `String` conversion loses resource localization metadata). For imperative/native menus or count-dependent messages, `AppLocalization.resolve(_:locale:)` selects the requested locale from the app's main-bundle catalog and shared formatting selects appropriate singular/plural resources while preserving literal names and paths. `PresentationCopyTests` exercises English, `zh-Hans`, and `zh-Hant` resolution, nested menus, count messages, accessibility copy and the SwiftUI key bridge.
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. Shared commerce copy includes the annual/lifetime selection, trial and renewal disclosures, status/error messages, and the feature list in both native paywalls; `ProOfferPresentation` localizes interpolated StoreKit values with the chosen app locale. `AppLanguageTests` checks explicit-language Pro offers and both catalogs for finished Chinese string units. 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.
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. Shared commerce copy includes the annual/lifetime selection, trial and renewal disclosures, status/error messages, and the feature list in both native paywalls; `ProOfferPresentation` localizes interpolated StoreKit values with the chosen app locale. `AppLanguageTests` checks explicit-language Pro offers, preference migration, regional Traditional lookup, token terminology, placeholder ordering and selected plural structures. Catalog-wide completion and manual formatting are enforced by the shell check and normalizer, **not** by `AppLanguageTests`. 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.
`Scripts/check-presentation-copy.sh` runs a SwiftSyntax visitor across TFM/TFI and flags selected string literals used as first arguments or named copy arguments in UI APIs, as localized string declarations, or in localized return types. Its detection is deliberately narrower than “all app text”: it excludes macros and only recognizes specified call forms; review new copy ownership and semantic reuse even when the script passes. The script checks that `Strings/AppStrings.swift` exists. `ArchitectureBoundaryTests.presentationCopyHasOneSharedOwner` prevents an app-local `AppStrings` declaration and bans app, AppKit/UIKit, TermindInfrastructure and TermindPersistence imports in the Strings directory. Run the copy check alongside `Scripts/check-zh-localization.sh`; neither replaces language-aware rendering and behavior tests. See [Shared Framework Directory Responsibilities](/openwiki/architecture/shared-module-directories.md) for the ownership map.
@@ -158,9 +186,9 @@ Any new or changed English app string requires completed `zh-Hans` and `zh-Hant`
The shared catalog is also the contract for ordinary native product surfaces, not just Pro copy. On iOS, Vault and Vault search open the Snippets and Known Hosts destinations with an optional initial query. The Known Hosts page distinguishes an empty library (“No Known Hosts”) from a search with no matches, offers “Add Known Host” in the toolbar, and exposes Edit, Copy Fingerprint, and Delete on each card. Its editor chooses “Add Known Host” or “Edit Known Host” according to whether the entry exists. The macOS Known Hosts page uses the same add/edit labels, but its empty state also offers “Import Known Hosts” and describes manual fingerprint entry; bulk deletion uses a count-dependent confirmation and warns that the next connection will require server-key verification again. Keep the platform-specific actions and warnings aligned with their `Localizable.xcstrings` keys rather than assuming the two pages have identical UI.
The iOS Snippets page likewise differentiates an empty library from an unsuccessful search. Its add menu offers “New Snippet” and “New Package”; a package menu also offers “New Subpackage”, while deletion offers either removing the package and its snippets or keeping the snippets. The catalog carries these labels and the package-tree snippet-count message in both Chinese scripts. The known-host and snippet cards render their timestamps using the view's environment locale, so an explicit app language must be checked in the actual view as well as in string lookup tests. Do not translate user-authored hostnames, fingerprints, package paths, snippet titles, or scripts as interface copy.
The iOS Snippets page likewise differentiates an empty library from an unsuccessful search. Its add menu offers “New Snippet” and “New Package”; a package menu also offers “New Subpackage”, while deletion offers either removing the package and its snippets or keeping the snippets. The catalog carries these labels and the count-dependent package-deletion message in both Chinese scripts; the section header's count is rendered as a locale-formatted number, not a separate package-tree count sentence. The known-host and snippet cards render their timestamps using the view's environment locale, so an explicit app language must be checked in the actual view as well as in string lookup tests. Do not translate user-authored hostnames, fingerprints, package paths, snippet titles, or scripts as interface copy.
For focused validation, `AppLanguageTests` asserts explicit-language Pro offers, Chinese catalog completion in both `Localizable` and `InfoPlist`, and distinct Simplified/Traditional lookup; it also checks that assistant token counts use 词元/符元 without applying those terms to security-token labels. `MobileCardTests` checks the known-host editor's add/edit title selection; the opt-in `MobileCardRenderingTests` mounts the real Snippets, Known Hosts, and editor views in a UIKit window for `en`, `zh-Hans`, and `zh-Hant` (light/dark plus a large-type Known Hosts capture). When changing these labels, run the catalog check and language tests, then inspect affected on-device captures in each locale; unit-level catalog completion does not establish that search, menus, dialogs, or layouts still read correctly.
For focused validation, `AppLanguageTests` asserts explicit-language Pro offers and distinct Simplified/Traditional lookup; it also checks that assistant token counts use 词元/符元 without applying those terms to security-token labels, that forwarding templates preserve placeholder order, and that selected tool-count resources retain appropriate plural forms. Use `Scripts/check-zh-localization.sh` for full-catalog Chinese completion and normalization across `Localizable` and `InfoPlist`. `FrameworkTests/ProOfferPresentationTests.swift` covers weekly trial conversion across three locales, eligibility, missing duration or price and caller-supplied localization; `FrameworkTests/ProPaywallPresentationTests.swift` checks phase/date labels, family ownership and canceled renewal, unavailable plans, and processing/error visibility. `MobileCardTests` checks the known-host editor's add/edit title selection; the opt-in `MobileCardRenderingTests` mounts the real Snippets, Known Hosts, and editor views in a UIKit window for `en`, `zh-Hans`, and `zh-Hant` (light/dark plus a large-type Known Hosts capture). When changing these labels, run the catalog check and language tests, then inspect affected on-device captures in each locale; unit-level catalog completion does not establish that search, menus, dialogs, or layouts still read correctly.
## Mobile Live Activity and widget boundary
@@ -181,5 +209,5 @@ The public site is a separate Astro app in `LandingPage/`, with strict TypeScrip
- 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 (opt in with `TERMIND_STOREKIT_TESTS=1`, ideally restricting to `TFMTests/StoreKitTrialTests`): it covers trial metadata and restoration, lifetime precedence, cancellation and catalog network errors, pending Ask to Buy approval, unverified transactions, annual purchase without an introductory offer, invalid annual product shape, and empty restore. `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, define semantic resource entries under `TermindPresentation/Strings` and complete all three catalog languages. Run `Scripts/check-presentation-copy.sh` with `Scripts/check-zh-localization.sh`, then `PresentationCopyTests` and `AppLanguageTests` where applicable; inspect affected native screens in all three app languages and on both platforms as needed.
- For text or product-copy changes, define semantic resource entries under `TermindPresentation/Strings` and complete both Chinese translations in the manual catalogs. Run `Scripts/normalize-string-catalogs.py --write` after catalog edits, then `Scripts/check-presentation-copy.sh` with `Scripts/check-zh-localization.sh`, `PresentationCopyTests`, `AppLanguageTests`, `ProOfferPresentationTests` and `ProPaywallPresentationTests` where applicable; inspect affected native screens in all three app languages and on both platforms as needed.
- 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.
+18 -6
View File
@@ -3,6 +3,9 @@ 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-24T03:18:19.992Z
sources:
- id: openwiki-source-685b7f8e7dbcf91b4e2a50e2
resource: repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift
@@ -96,10 +99,7 @@ sources:
resource: repo://TFMTests/AgentPersistenceTests.swift
- id: openwiki-source-1d1efb20e239b1f2142f6cb7
resource: repo://TFMTests/SettingsSyncTests.swift
generated: { by: "codex", at: "2026-09-24T01:58:11.184Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Persistent Data, Migrations, and Secret Boundaries
@@ -128,7 +128,7 @@ This diagram distinguishes durable SwiftData and GRDB records from Keychain mate
`TermindPersistence.makeContainer(inMemory:url:)` is the single SwiftData entry point. It exposes the complete `TermindSchemaV34` 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 do not assemble a partial schema per feature or scene. Desktop services commonly share `container.mainContext`; mobile creates dedicated `ModelContext(container)` instances for several repositories while sharing a vault context among host, connection-history and device-directory services.
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 are not silently replaced with an empty database: the mobile initializer throws; desktop initialization catches and terminates with a fatal database-open error. Data availability is an explicit startup condition.
The desktop root opens the container during `TermindApp.init()`: normal launches use the factory's default file-backed configuration (no explicit URL), while DEBUG XCTest and screenshot demos select an in-memory container. It supplies `KeychainSecretStore` for the normal composition and passes the same container to SwiftUI's main and authentication-window scenes. A screenshot demo instead constructs demo models and returns before the live repository wiring; XCTest still uses the in-memory container but disables cloud coordinators. 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 are not silently replaced with an empty database: the mobile initializer throws; desktop initialization catches and terminates with a fatal database-open error. Data availability is an explicit startup condition.
### Repository projections and atomic mutation
@@ -160,6 +160,18 @@ Historical SwiftData model shapes are deliberately frozen. A `VersionedSchema` h
V28 is required for existing installed stores. Removing its endpoint made staged migration reject those stores with CoreData error `134504` (unknown model version). `TermindSchemaV28HostModels` restores the historical fields, defaults and model identity from the parent of `b0d35d24`; V30 retains its existing model types and order. Recovery uses the normal container factory and preserves the original database on an opening failure, rather than clearing or rebuilding it.
```mermaid
flowchart TD
Fixture["Historical V28 fixture store"] --> Factory["makeContainer with V34 and migration plan"]
Factory --> V28["Recognize frozen V28 endpoint"]
V28 --> V30["Lightweight V28 to V30"]
V30 --> V31["Lightweight V30 to V31"]
V31 --> V34["Custom V31 to V34 device backfill"]
V34 --> Reopen["Open same migrated path again"]
```
The fixture-based path tests endpoint recognition, successive migration and reopening of the same on-disk data.
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.
@@ -169,7 +181,7 @@ Examples show why this matters:
- V34 directly migrates released V31 stores to the Host/connection-history/device model types named V32 and the Identity type named V33, and adds workspace preferences. These type names do not imply intermediate released schema endpoints. Host and Identity replacements remove obsolete `lastUsedAt` columns. The custom migration preserves events, assigns the stable installation ID to their `sourceDeviceID`, and inserts a separate `DeviceRecord` for that installation. The event itself receives no hostname field, and the CloudKit envelope format remains V1.
- The V31→V34 compatibility test verifies retained Identity configuration and the independent Vault journal modification date, connection origin/backfill with no invented end time, and default workspace-preference journal bootstrap. Historical Host and Identity shapes retain the old columns solely for schema compatibility.
`PersistenceCompatibilityTests` opens original V1 and V14 fixture stores and a fixed historical V28 store. The V28 fixture was generated against the unmodified Persistence framework at `0dc173d4b1d190071d35bc66f80ebb767d8b950c`, not current models; `Scripts/generate-v28-fixture.swift` records its provenance and schema checksum. Migration and reopening preserve host settings, charset, identity/key references, ordered environment variables, snippets, Known Hosts and connection history, including the existing installation ID used for device backfill. `MobileAppTests` also constructs the app from the migrated disk container twice to cover startup and relaunch. The suite retains V27, V30, V31 and current V34 compatibility coverage, full-schema independent in-memory containers, and new-field defaults. Treat these compatibility fixtures as a release contract when changing entities, defaults, migration stages, or storage enum raw values.
`PersistenceCompatibilityTests` opens original V1 and V14 fixture stores and a fixed historical V28 store. The V28 fixture was generated against the unmodified Persistence framework at `0dc173d4b1d190071d35bc66f80ebb767d8b950c`, not current models; `Scripts/generate-v28-fixture.swift` records its provenance and expected checksum and explicitly stores synthetic references, not a password or private key. The fixture uses a V28 host with SSH port and charset, ordered environment-variable name/value arrays, snippet and group IDs, an identity pointing to an SSH key and a Keychain reference, a known-host mismatch flag, a connection event without a device ID, and a preexisting Vault installation ID. The V28→V30 model preserves the old `port`, `identityID` and `charset` property names as SSH fields and supplies Telnet defaults; V30 replaces the known-host type to discard only the obsolete mismatch flag. V31→V34 backfills event origin from the installation ID and inserts a separate device row without synthesizing an end time. The fixture test copies the original store to a temporary path and calls the normal factory twice on that same path: each open asserts projected host settings, charset, identity/key references, ordered environment variables, snippets, Known Hosts, history and the installation ID/device row, plus workspace defaults after `prepare()`. This tests migration **and subsequent reopening**, not a newly created V28 store using today's model declarations; it does not test recovery from a deliberately failed open. `MobileAppTests` also constructs the app from the migrated disk container twice to cover startup and relaunch, checking host/identity projections and event origin. The suite retains V27, V30, V31 and current V34 compatibility coverage, full-schema independent in-memory containers, and new-field defaults. Treat these compatibility fixtures as a release contract when changing entities, defaults, migration stages, or storage enum raw values.
### Synchronized connection events and device directory
+44 -6
View File
@@ -3,7 +3,12 @@ type: design guide
title: UI Design Principles and Shared Presentation Boundaries
description: "Source-backed UI principles for TFM and TFI: semantic visual systems, native interaction, shared forms and presentation values, stable rendering identity, accessibility, localization and safe extension boundaries."
tags: [ui, design-system, presentation, accessibility, localization, macos, ios]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-a51ca858a040a90d4ab9c1c4
resource: repo://Frameworks/TermindApplication/AppLanguage.swift
- id: openwiki-source-d1d534769c300d5fb8dbe9d7
resource: repo://Frameworks/TermindApplication/FeatureModels/HostCustomIdentityDraft.swift
- id: openwiki-source-4ae2a0061a7bd729d6e132b4
@@ -18,6 +23,10 @@ sources:
resource: repo://Frameworks/TermindPresentation/HostConnectionFields.swift
- id: openwiki-source-db3eac4d3fbf63570c0e0d56
resource: repo://Frameworks/TermindPresentation/SingleLineTextInput.swift
- id: openwiki-source-2d3fd78e62a89dd2c0b202e6
resource: repo://Frameworks/TermindPresentation/Strings/AppStrings.swift
- id: openwiki-source-667f8dcadd921c1910c5026c
resource: repo://Frameworks/TermindPresentation/Strings/LocalizedStringResource%2BPresentation.swift
- id: openwiki-source-8185a608f0b79f1af097efbd
resource: repo://Frameworks/TermindPresentation/Terminal/TerminalAppearance.swift
- id: openwiki-source-0689f4693840cd29f5ac352c
@@ -30,6 +39,8 @@ sources:
resource: repo://Frameworks/TermindPresentation/Terminal/TerminalThemePicker.swift
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-60d390fe6fbfea55a2a8230a
resource: repo://TFI/App/MobileFeatureRegistry.swift
- id: openwiki-source-c8d832474c03f5ebad7b0578
resource: repo://TFI/App/MobileRootView.swift
- id: openwiki-source-99e98ad50ba8a7c6df018977
@@ -44,6 +55,8 @@ sources:
resource: repo://TFI/Features/Metrics/MobileMetricsView.swift
- id: openwiki-source-5503f969776cb509a7d69160
resource: repo://TFI/Features/Ports/MobileForwardingView.swift
- id: openwiki-source-e21fae39ef7af76f86acbff6
resource: repo://TFI/Features/Settings/MobileSettingsView.swift
- id: openwiki-source-02810e1f8eac4d0983f8cd44
resource: repo://TFI/Features/Settings/MobileTerminalSettingsView.swift
- id: openwiki-source-db402cad9d68dd8e66bdd7ee
@@ -94,6 +107,8 @@ sources:
resource: repo://TFM/Features/Workspaces/PaneLayoutDropController.swift
- id: openwiki-source-ba160208435f3410138a3539
resource: repo://TFM/Features/Workspaces/PersistentWorkspaceDeckLayout.swift
- id: openwiki-source-22b9fca540c3029c5ace451e
resource: repo://TFM/Features/Workspaces/WindowModel.swift
- id: openwiki-source-931aff66b28d38cd69ce2324
resource: repo://TFM/Features/Workspaces/WorkspaceContentView.swift
- id: openwiki-source-7e364c6182a8339831ecab24
@@ -110,8 +125,12 @@ sources:
resource: repo://TFM/UI/Managed/ManagedCardPage.swift
- id: openwiki-source-d3d065330c730839f5cc6112
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-dc392b9979d99f5026bdeadf
resource: repo://TFMTests/PresentationCopyTests.swift
- id: openwiki-source-dceb8d7e7c5bb09359e70052
resource: repo://TFMTests/ResponsivePageLayoutTests.swift
- id: openwiki-source-44cb7a6172854edbfc9b5ccb
resource: repo://TFMTests/SettingsNavigationTests.swift
- id: openwiki-source-2891f940e682279163740c83
resource: repo://TFMTests/TerminalFontRenderingTests.swift
- id: openwiki-source-9442022b3dba1be62a55f0f0
@@ -120,10 +139,7 @@ sources:
resource: repo://TFMTests/WorkspaceLayoutDropTests.swift
- id: openwiki-source-a3093a0c1d98ecc1cdbc0279
resource: repo://TFMTests/WorkspaceNavigatorDropTests.swift
generated: { by: "codex", at: "2026-09-23T17:44:09.687Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-23T17:44:09.687Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# UI Design Principles and Shared Presentation Boundaries
@@ -153,11 +169,11 @@ flowchart TD
Mobile --> UIKit[UIKit terminal / list / input adapters]
```
The shared layer supplies values and fields; each app composes and owns its native shell.
The shared layer supplies values and fields; each app composes and owns its native shell. Shared presentation copy also lives here: `AppStrings` is a resource-backed semantic vocabulary divided into feature-specific extensions rather than a second app-local copy. Resources are created on demand; `AppLocalization.resolve` resolves against the selected locale and the app's main-bundle localization. Use `.swiftUIKey` for SwiftUI APIs requiring a `LocalizedStringKey`, preserving interpolation metadata; resolve to `String` at native menu boundaries. The copy-owner test rejects app-local `AppStrings` declarations, while presentation-copy tests check locale-specific menus, plural/interpolated messages and the SwiftUI bridge in English and both Chinese scripts. Keep platform-specific phrasing in explicit variants instead of making shared copy control platform behavior.
These arrows show conceptual dependencies and consumption, not an exhaustive target dependency graph. See [System Boundaries](/openwiki/architecture/system-boundaries.md) for the broader module structure.
`TermindPresentation` is allowed to contain SwiftUI views. It is **not** a transport-free name attached to an arbitrary bag of platform code: architecture tests forbid it from importing either app, AppKit, UIKit, SwiftData, GRDB, Persistence or RemoteInfrastructure. Native adapters remain app-owned. Shared non-presentation frameworks have their own boundaries; do not apply one blanket “no UI anywhere in Frameworks” rule.
`TermindPresentation` is allowed to contain SwiftUI views. The dedicated `sharedPresentationHasNoPlatformOrStorageDependency` architecture test forbids imports of either app (`Termind`, `TermindIOS`), AppKit, UIKit, SwiftData, GRDB, `TermindPersistence`, `TermindRemoteInfrastructure`, `TermindInfrastructure` and StoreKit. The separate `listViewKitIsLimitedToNativeListWorkloads` test limits `ListViewKit` importers to approved native-list workloads; it is not a blanket ban on SwiftUI in shared presentation. Native adapters remain app-owned. The other shared frameworks have different import rules, so do not generalize this test to every framework.
Useful shared pieces include:
@@ -168,6 +184,28 @@ Useful shared pieces include:
Not suitable for moving into a generic shared view are a window's selected pane, a scene's navigation stack, a native terminal owner, credential resolution, connection teardown or repository mutation. Sharing a form does not make its save, authorization or lifetime policy shared automatically.
### Settings navigation is app-owned
Desktop `RootView` mounts `SettingsPageView` when the window selects Settings. `WindowModel.openSettings(route:)` remembers the displaced destination; the page switches on the window's `settingsRoute` instead of pushing a shared navigation stack. The index offers App, Terminal, Connections, AI and Sync categories (Developer only in debug builds); Logging is a separate optional debug row, and Pro opens a paywall rather than becoming a category. AI has provider, model-list, MCP and skill detail routes; a terminal configuration detail belongs under Terminal. A category returns to the index, provider models return to their provider, AI details return to AI, terminal configuration returns to Terminal, and Logging returns to the index. The window toolbar Back calls `navigateBackInSettings`: it follows `SettingsRoute.parent` until the index, then closes Settings and restores the displaced destination, falling back to Vault if a remembered workspace has disappeared. Paywall presentation must not replace the route or consume this return destination.
```mermaid
flowchart TD
Previous["Window destination"] --> Open["Open Settings and remember destination"]
Open --> Index["Settings index"]
Index --> Category["Category page"]
Index --> Logging["Logging detail"]
Index --> Paywall["Pro paywall over Settings"]
Category --> Detail["AI or Terminal detail"]
Detail -->|Back to parent| Category
Logging -->|Back| Index
Category -->|Back| Index
Index -->|Back| Restore["Restore destination or Vault fallback"]
```
Desktop Settings routing and the toolbar Back action preserve the window's return destination; the paywall is independent of the Settings route.
`SettingsPageView` also cleans up provisional AI configuration on route changes or disappearance: an empty provider draft is discarded except when moving between that provider and its model list; a newly created MCP server is discarded if invalid or its namespace cannot be locked; a new skill with any useful name, summary or body survives as a draft. Do not move this cleanup into shared form fields. On mobile, the Settings feature is registered in `MobileFeatureRegistry`; `MobileRootView` gives each registered tab its own `NavigationStack`, and `MobileSettingsView` uses native `NavigationLink`s for categories and an app-owned paywall sheet. Sharing labels or fields does **not** imply sharing the desktop `SettingsRoute` hierarchy. `SettingsNavigationTests` checks parent routes, Back/restore/fallback and the independence of paywall navigation; `ArchitectureBoundaryTests` separately checks the shared presentation import boundary.
## 2. Use semantic visual roles, not per-feature themes
### Desktop vocabulary
+32 -6
View File
@@ -3,6 +3,9 @@ type: integration guide
title: MCP Server, Transfer APIs, and Stdio Bridge
description: How the desktop MCP listener and stdio bridge expose local host tools and scoped HTTP SFTP transfers, including ticket states and failure recovery. Distinguishes macOS server ownership from the iOS remote MCP client.
tags: [mcp, macos, loopback, authentication, sftp, bridge]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-1fc00d0407016efa5a0378eb
resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSSHTools.swift
@@ -16,8 +19,12 @@ sources:
resource: repo://TFM/App/AppModel.swift
- id: openwiki-source-b8fca76c89564e16eccfbb53
resource: repo://TFM/App/MCPServerController.swift
- id: openwiki-source-8a6e94328a445c3566ef9d57
resource: repo://TFM/Application/MCPServer/MCPDownloadCoordinator.swift
- id: openwiki-source-76b1cdca4a02038756187f92
resource: repo://TFM/Application/MCPServer/MCPServerTools.swift
- id: openwiki-source-396f97a332870d48c065d7e9
resource: repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift
- id: openwiki-source-d485ebb339c77875a3b2701e
resource: repo://TFM/Features/ExternalRequests/ExternalAuthCoordinator.swift
- id: openwiki-source-ef4c6426a19087a6c49e4841
@@ -44,10 +51,7 @@ sources:
resource: repo://TFMTests/MCPTransferTicketTests.swift
- id: openwiki-source-47dc468698b2904f0004ee04
resource: repo://TFMTests/MCPUploadTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-23T14:32:50.942Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# MCP Server, Transfer APIs, and Stdio Bridge
@@ -139,7 +143,29 @@ Tool audit records are registered per MCP session. The UI can show client, tool,
## 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.
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 validates the arguments and configured host and allocates a ticket through the normal tool executor; it does **not** open SSH, SFTP, a local file, or the remote source. The client owns its local file and sends or saves its bytes separately. Only a valid HTTP `PUT` or `GET` claims an active transfer slot and starts the dedicated SFTP operation. The byte route authenticates the ticket capability rather than a second MCP session header, but the server checks that the issuing run remains registered. Status lookup requires that same run ID; knowing another session's ticket ID is insufficient.
```mermaid
sequenceDiagram
participant Client
participant MCP as MCP protocol and tools
participant Tickets as Transfer coordinator
participant HTTP as Loopback byte route
participant SFTP as SSH authentication and SFTP
Client->>MCP: tools/call create upload or download ticket
MCP->>Tickets: validate host and allocate run bound ticket
Tickets-->>Client: URL and scoped Bearer capability
Client->>HTTP: PUT or GET with ticket capability
HTTP->>Tickets: validate capability and claim capacity
Tickets->>SFTP: open dedicated authenticated transfer
SFTP-->>HTTP: stream or commit bytes
HTTP-->>Client: byte response or transfer error
Client->>MCP: tools/call status with ticket ID
MCP->>Tickets: lookup for owning run
Tickets-->>Client: state and progress
```
Ticket creation and byte delivery are separate authorization and I/O phases; status remains tied to the originating MCP run.
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 **while the owning session still exists**. Host/session revocation, server stop, token rotation, or disabling the matching direction cancels/revokes work. Ticket creation only validates request/host and allocates a capability; the subsequent HTTP claim acquires a shared active slot (or returns `429` without consuming a waiting ticket). The session activity check covers live work, unexpired paused tickets, and recently audited completions so a long-running transfer and its status remain queryable past normal session idle expiry.
@@ -217,7 +243,7 @@ For direct HTTP clients, settings generates quoted setup commands for Claude Cod
* 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 all 18 exports, shared descriptor parity with the acting host subset, excluded tools, disabled invocation, 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.
* Test changes at the correct seam: `MCPServerSessionTests` exercises initialization, version/session requirements, tool discovery, legacy SSE, and deletion cancellation without session resurrection; `MCPServerToolsTests` verifies all 18 exports, shared descriptor parity with the acting host subset, excluded tools, disabled invocation, one-shot session-bound secrets, and upload/download ticket creation with connection openers that would fail if called. Its cross-run status lookups fail, and `endSession` removes ticket access and discards secrets/cancels prompts. `MCPUploadTests` and `MCPDownloadTests` cover resume, claim, digest, cancellation, status, and wire behavior; `MCPClientSetupCommandTests` checks exact, shell-safe client registration arguments.
## Related pages
+24 -11
View File
@@ -1,8 +1,11 @@
---
type: release operations
title: Build, Test, and Release
description: Targeted validation gates for Termind's resolved-package Xcode builds, opt-in UI and StoreKit tests, localization, screenshots, website, and AgentKit releases.
description: Operational validation gates for resolved-package Xcode builds, opt-in window and commerce tests, localization, screenshots, website builds, and AgentKit releases.
tags: [operations, build, testing, localization, release, agentkit, screenshots]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-ea70eb6c045047448e446296
resource: repo://.gitignore
@@ -10,12 +13,20 @@ sources:
resource: repo://.swift-format
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
- id: openwiki-source-2d3fd78e62a89dd2c0b202e6
resource: repo://Frameworks/TermindPresentation/Strings/AppStrings.swift
- id: openwiki-source-103853faf6b28763354a1c79
resource: repo://LandingPage/package.json
- id: openwiki-source-c76cbada020604024adadb22
resource: repo://LandingPage/README.md
- id: openwiki-source-aa9e36be30555d3a6c7a3f6a
resource: repo://Scripts/check-presentation-copy.sh
- id: openwiki-source-f6e4a8e5d7aef42804ab0509
resource: repo://Scripts/check-presentation-copy.swift
- id: openwiki-source-41a7ded3800c9422f058a3ef
resource: repo://Scripts/check-zh-localization.sh
- id: openwiki-source-de562e98d49cbf6502c23c13
resource: repo://Scripts/normalize-string-catalogs.py
- id: openwiki-source-6a4176e7d97bf05b3983882c
resource: repo://Scripts/run-mac-marketing-screenshots.sh
- id: openwiki-source-9621f35145a32a9f8391084b
@@ -38,16 +49,17 @@ sources:
resource: repo://TFITests/MobileHostIntegrationRenderingTests.swift
- id: openwiki-source-1068a19b8ad42f734f4b4bb6
resource: repo://TFITests/MobileSavedNameRenderingTests.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-793d7861000adc19f0c3df01
resource: repo://TFMTests/AppLanguageTests.swift
- id: openwiki-source-dc392b9979d99f5026bdeadf
resource: repo://TFMTests/PresentationCopyTests.swift
- id: openwiki-source-0dd012e3740bcc348fc36ccb
resource: repo://TFMTests/StoreKitTrialTests.swift
- id: openwiki-source-a08489338be00125d646c77e
resource: repo://TFMTests/VisibleWindowTestTrait.swift
generated: { by: "codex", at: "2026-09-24T01:58:11.184Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Build, Test, and Release
@@ -109,7 +121,7 @@ A companion change in AgentKit must also pass its equivalent command over `Sourc
## 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.
Most routine tests should remain headless. macOS tests that present windows or take focus—including Dock actions, external authentication and Launch Services alerts—must use `.requiresVisibleWindow` at the suite or test level. The trait skips them unless the test host sees `TERMIND_WINDOW_TESTS=1`; for command-line runs, Xcode forwards `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` into the test host. The two safeguards are complementary: gating a test alone cannot stop XCTest from launching the real app. In Debug test runs, `TermindApp` detects the XCTest configuration and suppresses automatic launch of both the main and external-auth scenes by default, with restoration disabled. Setting `TERMIND_WINDOW_TESTS=1` allows automatic launch again; an active screenshot demo also bypasses the default suppression. This host safeguard does **not** replace the trait on a window/focus test.
Opt in only for the named rendering/interaction suite being investigated:
@@ -117,7 +129,7 @@ Opt in only for the named rendering/interaction suite being investigated:
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.
In Xcode, set `TERMIND_WINDOW_TESTS=1` in the Test action environment. Run this on a machine with an appropriate display and keep the selection narrow; the opt-in also lifts the app host's automatic-window suppression. Existing screenshot tests may retain their own dedicated opt-in variables; offscreen layout and logic tests remain part of normal validation. Without the opt-in, routine runs neither execute gated focus-changing tests nor auto-open the test host's windows.
### Mobile key-window integration tests
@@ -162,15 +174,16 @@ The macOS script requires macOS 27.x, accepts constrained scene/locale environme
## 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.
Define user-facing copy as shared `LocalizedStringResource` entries under `Frameworks/TermindPresentation/Strings` (`AppStrings`), even for one-platform wording; the catalog compiled into each app bundle is `Frameworks/Resources/Localizable.xcstrings`, and bundle metadata belongs in `Frameworks/Resources/InfoPlist.xcstrings`. Keep identifiers and diagnostic codes with their existing owners. `STRING_CATALOG_GENERATE_SYMBOLS = NO` because `AppStrings` owns the Swift-facing API. Any new or changed English string must ship with finished `zh-Hans` and `zh-Hant` translations in the same commit. Preserve placeholders and Chinese punctuation conventions.
Run the catalog gate before committing; it requires `jq` and accepts an optional catalog path:
The two shared catalogs are manually maintained: keep `extractionState: "manual"`, add keys/translations explicitly, and verify use in both apps and shared code before deleting an entry. A single target's `stale` extraction flag does not establish that a shared key is unused. After a catalog edit run `Scripts/normalize-string-catalogs.py --write` for Xcode-compatible ordering and formatting; do not substitute `jq -S` or a generic JSON formatter. The normalizer leaves translations intact and does not touch AgentKit's catalog. Before committing, run both checks (the catalog check requires `jq` and optionally accepts a catalog path):
```sh
Scripts/check-presentation-copy.sh
Scripts/check-zh-localization.sh
```
The script first runs `normalize-string-catalogs.py --check`, then 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.
The presentation-copy check uses Xcode's Swift parser to scan `TFM` and `TFI` Swift literals at presentation API call sites and fails when app-facing copy is written directly instead of using shared resources; it distinguishes these from identifiers, URLs, comments, and interpolated expressions. The catalog check runs the normalizer in read-only `--check` mode, then validates JSON and, for each Chinese locale, rejects absent localization entries, string units not marked `translated`, empty values except for the empty key, and invalid Han/Latin or punctuation spacing. Fix the reported catalog or copy violation rather than bypassing the gate. Run `AppLanguageTests` when language behavior changes; for resource/formatting behavior also target `PresentationCopyTests`, which exercises multilingual resources, menus, plurals and SwiftUI resource bridging.
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:
@@ -221,7 +234,7 @@ Do not skip the release or resolve steps: a project-file bump alone does not est
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.
4. Run `Scripts/check-presentation-copy.sh` alongside `Scripts/check-zh-localization.sh` for every commit; complete both Chinese translations, normalize changed catalogs, and run `AppLanguageTests`/`PresentationCopyTests` when their behavior changes.
5. For landing-page changes, run `cd LandingPage && npm ci && npm run build` and inspect English/Chinese routes.
6. Keep visible-window, mobile key-window integration, and StoreKit authorization gates off in routine runs; when affected, opt in with the exact flags above and narrow the suite. Run the ungated adaptive-layout suite deliberately without parallel testing for adaptive UI changes.
7. Regenerate marketing captures only through their dedicated scripts when product imagery changes.
@@ -3,6 +3,9 @@ type: release-readiness
title: CloudKit Schema Deployment and Signed-Device Release Readiness
description: Production CloudKit schema, compatibility, and signed-device checks for Vault, Settings, SFTP preferences, Metrics, and Keychain-backed secrets.
tags: [cloudkit, sync, release, settings, vault, metrics, sftp]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-7ca30f0e781e8c2df826b47a
resource: repo://Frameworks/TermindApplication/HistoryLimits.swift
@@ -34,6 +37,12 @@ sources:
resource: repo://Frameworks/TermindPersistence/SwiftDataVaultJournal.swift
- id: openwiki-source-a0d614d618b11f103ec246ae
resource: repo://Frameworks/TermindPersistence/SwiftDataVaultStore.swift
- id: openwiki-source-7a9c6d90cba4ebd1d1398673
resource: repo://Frameworks/TermindPersistence/TermindPersistence.swift
- id: openwiki-source-79e0f2a939e874c6a6803c19
resource: repo://Frameworks/TermindPersistence/TermindSchemaV28HostModels.swift
- id: openwiki-source-8fda0c115d3df709fffe110c
resource: repo://Frameworks/TermindPersistence/TermindSchemaV29HostModels.swift
- id: openwiki-source-3cfc52217a7a6835b4bffac1
resource: repo://Frameworks/TermindPersistence/VaultSyncPersistence.swift
- id: openwiki-source-bf7a64e7c819eb9279e2f9e4
@@ -46,22 +55,25 @@ sources:
resource: repo://FrameworkTests/CloudSyncSafetyPersistenceTests.swift
- id: openwiki-source-eb9518e5c7eb3782fa0cccc0
resource: repo://FrameworkTests/CloudSyncSafetyTests.swift
- id: openwiki-source-8428b9f5de49b8a561d93fa5
resource: repo://FrameworkTests/PersistenceCompatibilityTests.swift
- id: openwiki-source-25a5163498969aef5057c698
resource: repo://FrameworkTests/SettingsPortTests.swift
- id: openwiki-source-fce837c614f18611765f3804
resource: repo://FrameworkTests/SFTPSettingsSyncTests.swift
- id: openwiki-source-a6f48b126bfcd6573fe06736
resource: repo://FrameworkTests/SFTPSettingsTests.swift
- id: openwiki-source-294dd6a8637abdafe40e9570
resource: repo://Scripts/generate-v28-fixture.swift
- id: openwiki-source-25a2df896b93f410289e8512
resource: repo://TFI/TFI.entitlements
- id: openwiki-source-b822b041afbf829d09a8555a
resource: repo://TFITests/MobileAppTests.swift
- id: openwiki-source-f5ab2303a67ae18cbe2f59f2
resource: repo://TFM/TFM.entitlements
- id: openwiki-source-960109cd5bc0de7a879c1e16
resource: repo://TFMTests/VaultSyncTests.swift
generated: { by: "codex", at: "2026-09-23T00:14:42.075Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# CloudKit Schema Deployment and Signed-Device Release Readiness
@@ -110,6 +122,22 @@ Current defaults are 30 global transfers, 10 per Host, and Smart topology. The a
For a release check, change 30/10 to 100/50, close Settings, and verify that another device adopts the new pair without interrupting active transfers. Repeat while offline and while the Settings category or master switch is paused, then resume. Include a device retaining 3/2 and, where compatibility testing is available, an older client that continues syncing the pre-existing record types while ignoring `SFTPPreferencesItem`.
## Installed V28 store upgrade gate
The local SwiftData migration is a separate release gate from CloudKit schema deployment. `TermindPersistence.makeContainer` opens file and in-memory stores with the shared V34 schema, `TermindMigrationPlan`, and `cloudKitDatabase: .none`; CloudKit transport is owned by the category coordinators instead of SwiftData mirroring. Keep the historical V28 endpoint: the plan takes V27→V28→V30→V31→V34, skipping V29, V32 and V33 as endpoints. V28 supplies the frozen Host shape (including `charset`), and V30 retains V28's `port`, `identityID` and `charset` column names as SSH values while introducing default-disabled Telnet fields. Do not rewrite shipped model shapes or replace the fixture with a store generated from current models just to make migration tests pass.
```mermaid
flowchart TD
Fixture["Historical V28 disk store"] --> Factory["Shared makeContainer"]
Factory --> Local["V28 to V30 to V31 to V34"]
Local --> Verify["Load Vault data and reopen store"]
Verify --> Device["Signed device upgrade and relaunch"]
Device --> Cloud["Independent CloudKit delivery checks"]
```
This is the evidence ladder for upgrading an installed store; each step establishes a different release property.
The checked-in `V28.store` was generated against the historical Persistence build with synthetic data and no passwords or private keys. `PersistenceCompatibilityTests.version28FixtureMigratesAndReopensWithoutLosingData` copies it to a temporary disk path, opens it through the normal factory twice, and checks the preserved SSH port/GB18030 charset, default-disabled Telnet, identity and key references, ordered environment variables, snippet, group and known host, history and installation ID, and workspace defaults. The V31→V34 migration backfills the history event's source device from the existing Vault installation ID and creates a device record, without fabricating an end time. `MobileAppTests.startupLoadsVersion28DataAfterMigrationAndRelaunch` also constructs the mobile app twice from the migrated disk container and checks the projected Host, identity reference and history. These in-process fixtures do **not** prove an on-device installed-app upgrade, process relaunch, Keychain secret availability, mixed-version CloudKit compatibility or Production delivery. Include an upgrade of an existing signed installation with actual credentials, then relaunch and sync on another signed device in the release matrix; a fixture credential reference is not a secret.
## First-stage mixed-version safety
Local schema V31 adds replica-scoped quarantine and recovery checkpoints. The current V34 schema retains that safety storage and adds the connection-history/device shapes through the direct V31→V34 migration. Those local changes do **not** add a Vault record type, change the existing zones, or raise the V1 envelope formats. Treat local database migration and cloud schema deployment as separate decisions; the distinct Settings record types in the inventory still require deployment before use.
@@ -139,11 +167,12 @@ The historical 2026-09-19 implementation record covered full TFI, focused iPad,
Release sign-off should record, separately:
1. the current pinned macOS and mobile build/test results;
2. successful Development validation and explicit Production deployment for every required zone and record type;
3. the signed multi-device/account-switch matrix, including offline and pause/resume behavior;
4. Keychain-delivery and migrated-token checks;
5. the SFTP preference and mixed-version safety matrices; and
6. the published privacy-policy version and effective date.
1. the current pinned macOS and mobile build/test results, including historical V28 fixture migration and reopening;
2. an installed signed-device V28 upgrade and relaunch with real credentials, separately from fixture results;
3. successful Development validation and explicit Production deployment for every required zone and record type;
4. the signed multi-device/account-switch matrix, including offline and pause/resume behavior;
5. Keychain-delivery and migrated-token checks;
6. the SFTP preference and mixed-version safety matrices; and
7. the published privacy-policy version and effective date.
See [Settings, Vault, Metrics, and Cloud Sync Workflow](/openwiki/workflows/settings-and-cloud-sync.md) for runtime lifecycle and journals, [Persistent Data, Migrations, and Secret Boundaries](/openwiki/concepts/persistence-and-secrets.md) for local stores and secret references, and [Build, Validation, Localization, and Dependency Release Operations](/openwiki/operations/build-test-and-release.md) for ordinary build gates.
+2 -2
View File
@@ -1,7 +1,7 @@
# Files
- [Build, Test, and Release](build-test-and-release.md) - Targeted validation gates for Termind's resolved-package Xcode builds, opt-in UI and StoreKit tests, localization, screenshots, website, and AgentKit releases.
- [Build, Test, and Release](build-test-and-release.md) - Operational validation gates for resolved-package Xcode builds, opt-in window and commerce tests, localization, screenshots, website builds, and AgentKit releases.
- [CloudKit Schema Deployment and Signed-Device Release Readiness](cloudkit-release-readiness.md) - Production CloudKit schema, compatibility, and signed-device checks for Vault, Settings, SFTP preferences, Metrics, and Keychain-backed secrets.
- [Marketing Assets, Screenshot Production, Figma Exports, and App Icons](marketing-assets-and-app-icons.md) - End-to-end rules for localized captures, device frames, website imagery, App Store boards, Figma exports, and layered app-icon sources.
- [Port Forwarding Benchmark Design, Results, and Reproduction](port-forwarding-benchmarks.md) - Historical forwarding measurements, workload semantics, retained transport decisions, comparison limits, and reproducible loopback commands.
- [App Store Commerce Configuration and Release Verification](storefront-commerce-release.md) - Product metadata, entitlement expectations, App Store Connect ownership, and Sandbox/cross-device checks for Termind Pro.
- [Storefront Commerce Release Checks](storefront-commerce-release.md) - Cross-platform checks for Termind Pro annual trials, lifetime purchases, localized paywalls, App Store metadata, and storefront imagery before release.
@@ -1,62 +1,106 @@
---
type: storefront-release-operations
title: App Store Commerce Configuration and Release Verification
description: Product metadata, entitlement expectations, App Store Connect ownership, and Sandbox/cross-device checks for Termind Pro.
tags: [app-store, storekit, commerce, subscriptions, release]
title: Storefront Commerce Release Checks
description: Cross-platform checks for Termind Pro annual trials, lifetime purchases, localized paywalls, App Store metadata, and storefront imagery before release.
tags: [app-store, storekit, commerce, subscriptions, localization, release]
verified:
- by: openwiki/0.5.2
at: 2026-09-23T10:08:51.776Z
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-a8a9aade8fbc89d5829a491e
resource: repo://Frameworks/Resources/Localizable.xcstrings
- 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-a298d9034d557f1b420cb306
resource: repo://Frameworks/TermindPresentation/ProOfferPresentation.swift
- id: openwiki-source-ff6aeac237822b937eb60926
resource: repo://Frameworks/TermindPresentation/ProPaywallContent.swift
- id: openwiki-source-f9f51dced2f50e794fadc9ab
resource: repo://Frameworks/TermindPresentation/ProPaywallPresentation.swift
- id: openwiki-source-3b424584de88a1150af27f83
resource: repo://FrameworkTests/ProOfferPresentationTests.swift
- id: openwiki-source-925cc598397685e13fcf56c4
resource: repo://FrameworkTests/ProPaywallPresentationTests.swift
- id: openwiki-source-ef9b991e118d6fe8b7fbee55
resource: repo://Marketing/AppStore/en/mac/01-three-screens.jpg
- id: openwiki-source-3882fc675d1b99ff0f2ba4c3
resource: repo://Marketing/AppStore/zh-hans/iphone-6.5/06-vault.jpg
- id: openwiki-source-b130fb70b5ba4d89364e1196
resource: repo://Marketing/AppStore/zh-hant/ipad-13/06-vault.jpg
- id: openwiki-source-446ef49ac8edac86b5511fe5
resource: repo://Marketing/README.md
- id: openwiki-source-9fc915d39c61b81a60426eb3
resource: repo://StoreKit/Termind.storekit
- id: openwiki-source-0ffab0ae6452f870ce4a0efe
resource: repo://TFI/Features/Commerce/MobileProView.swift
- id: openwiki-source-bc6023e93d60f0fac1bbea53
resource: repo://TFITests/ProPaywallRenderingTests.swift
- id: openwiki-source-766dc23f16ac26a41a5b5c22
resource: repo://TFM/Features/Commerce/ProPaywallView.swift
- id: openwiki-source-0da64bbb5811b467bbf89b7f
resource: repo://TFMTests/ProAccessTests.swift
- id: openwiki-source-8e854eded0d88c86c59da2e5
resource: repo://TFMTests/ProPaywallRenderingTests.swift
- id: openwiki-source-0dd012e3740bcc348fc36ccb
resource: repo://TFMTests/StoreKitTrialTests.swift
generated: { by: "codex", at: "2026-09-22T01:13:21.371Z" }
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# App Store Commerce Configuration and Release Verification
# Storefront Commerce Release Checks
App Store Connect is the production authority for products, offers, localized metadata, Family Sharing, grace period, and review behavior. `StoreKit/Termind.storekit` is a local development and test fixture; editing it does not update the storefront. Do not add a demo or App Review entitlement override. Exercise purchases with the local configuration, Sandbox, or Apple's review environment.
App Store Connect is the production authority for products, offers, localized metadata, Family Sharing, grace period, and review behavior. `StoreKit/Termind.storekit` is a **local development/test fixture**, not a storefront deployment. Keep the product IDs stable and test with the local configuration, Sandbox, and the review environment rather than granting demo or App Review entitlement overrides. Separate evidence for local behavior from evidence for the live storefront.
## Product matrix
## Product and offer matrix
| Field | Annual | Lifetime |
| --- | --- | --- |
| Product ID | `com.akinokaede.termind.pro.annual` | `com.akinokaede.termind.pro` |
| Reference / English name | Termind Pro Annual | Termind Pro Lifetime |
| US price and type | $3.99/year, auto-renewable | $9.99, non-consumable |
| Local US fixture price and type | $3.99/year, auto-renewable | $9.99, non-consumable |
| Simplified Chinese name | Termind Pro 年度订阅 | Termind Pro 永久版 |
| Traditional Chinese name | Termind Pro 年度訂閱 | Termind Pro 永久版 |
| English description | Annual AI, MCP & iCloud sync access. | Lifetime AI, MCP & iCloud sync access. |
| Simplified Chinese description | 按年使用AI、MCP与iCloud同步功能。 | 永久使用AI、MCP与iCloud同步功能。 |
| Traditional Chinese description | 按年使用AI、MCP與iCloud同步功能。 | 永久使用AI、MCP與iCloud同步功能。 |
Both products enable Family Sharing. The annual product belongs to one `Termind Pro` subscription group, bills yearly, and has a free introductory offer currently configured for two weeks. Production Billing Grace Period is an App Store Connect setting: retain the intended 16-day, paid-to-paid-only policy and verify it in Sandbox before relying on it. The app obtains price, billing period, introductory eligibility, duration, and subscription state from StoreKit; never hard-code storefront display values into access logic or UI.
The fixture marks both products Family Shareable; annual is in the `Termind Pro` subscription group with a one-year renewal and **one two-week free introductory period**. Verify the actual offer and eligibility with a fresh Sandbox account: prior use of an introductory offer can make the badge disappear without changing the configured offer. Billing Grace Period is controlled in App Store Connect, not represented by this fixture: confirm the intended 16-day, paid-to-paid-only production policy and exercise the actual grace state before relying on it. Do not treat fixture prices as a universal storefront price.
## Entitlement expectations
## Shared paywall contract
- A verified, non-revoked lifetime purchase wins over annual state.
- A verified annual introductory trial, subscribed period, or grace period grants Pro. Cancellation retains access through the verified expiration date.
- Billing retry without grace, expiration, upgrade-away, refund, revocation, or failed verification does not grant access.
- Product metadata/catalog failure must not remove already verified access. The controller refreshes entitlements independently, observes `Transaction.updates`, and handles deferred Ask to Buy completion.
- Protected features consult the current entitlement immediately. Free access still includes Mac Workspace composition, broadcast, batch opening, multi-Host snippets, and local templates; template iCloud synchronization remains Pro.
- Retired standalone trials are not an access source.
`ProAccessController` loads both products, accepts only a family-shareable non-consumable lifetime product and a family-shareable yearly auto-renewable annual product, and reports StoreKit display prices, billing period, free-intro duration, and intro eligibility. `canStartTrial` requires the purchasable annual product, an eligible account, and an actual zero-price free-trial offer; annual remains purchasable without an offer. The Mac `ProPaywallView` and iPhone/iPad `MobileProView` feed these values and their controller status into the same `ProPaywallContent` through `ProPaywallPresentation`. Both reload products on presentation and select lifetime if annual metadata is unavailable but lifetime metadata exists. Mac supports the built-in MCP server in feature copy and opens the App Store subscriptions URL; mobile advertises remote MCP only and opens the system manage-subscriptions sheet.
Keep runtime access behavior in the shared commerce controller and domain types. The local StoreKit file may mirror production configuration for testing, but it is not permission to infer the production state.
```mermaid
flowchart TD
Store["StoreKit products and verified transactions"] --> Controller["ProAccessController"]
Controller --> Metadata["Price and trial metadata"]
Controller --> Access["Entitlement status"]
Metadata --> Mac["Mac paywall adapter"]
Access --> Mac
Metadata --> Mobile["Mobile paywall adapter"]
Access --> Mobile
Mac --> Shared["ProPaywallContent and ProOfferPresentation"]
Mobile --> Shared
Shared --> Actions["Purchase restore reload or manage"]
Actions --> Controller
```
## Release verification
This is the release-facing boundary: platform adapters supply live commerce values and actions; shared presentation supplies the localized offer and status UI.
1. Run `StoreKitTrialTests` and the relevant `SKTestSession`/Pro access suites. Verify purchase, introductory trial, renewal, cancellation, restore, expiration, billing retry, paid-to-paid grace, refund, revocation, Ask to Buy, deferred completion, and transaction updates.
2. With a new Sandbox account, verify the localized annual and lifetime product names, descriptions, prices, annual period, introductory eligibility/duration, and Family Sharing. Existing accounts may already have consumed introductory eligibility.
3. Verify the same Apple-account entitlement on Mac, iPhone, and iPad, then verify Family Sharing separately. Confirm lifetime precedence and cancellation-through-expiry behavior.
4. Apply all English, Simplified Chinese, and Traditional Chinese metadata changes in App Store Connect. Coordinate storefront text with website and free-Workspace messaging while preserving the product IDs, prices, subscription group, offer, and grace policy.
5. Inspect native paywalls and subscription-management flows using StoreKit-provided metadata. Verify that metadata/network failure is recoverable and does not downgrade a verified user.
6. Record App Store Connect/Sandbox evidence independently from the local test result. Local tests cannot prove production metadata, review-environment behavior, cross-device delivery, or Family Sharing.
`ProOfferPresentation` formats the annual trial badge and the selected-plan detail in the effective locale. StoreKit's `weekOfYear` introductory period is converted to days before formatting, so the local two-week offer displays its full **14 days**, not a guessed duration. Eligible annual offers use **Start Free Trial** and “free, then [StoreKit price] per [billing unit]. Auto-renews until canceled.” Ineligible/no-offer annual purchases use **Subscribe Annually** and the price/renewal disclosure without a free claim. Lifetime uses **Buy Lifetime Access** and “One payment. No subscription or automatic renewal.” Missing annual price or billing period suppresses the annual detail; missing trial duration suppresses its badge, not the eligibility-based button title. `Frameworks/Resources/Localizable.xcstrings` contains the Simplified and Traditional Chinese offer strings; inspect the native resolved text rather than deriving it from the StoreKit product description. Do not hard-code fixture prices or the two-week duration into UI or access rules.
See [Commerce, Localization, and Product Surfaces](/openwiki/concepts/commerce-localization-and-product-surfaces.md) for runtime gating and paywall ownership, [Marketing Assets, Screenshot Production, Figma Exports, and App Icons](/openwiki/operations/marketing-assets-and-app-icons.md) for product imagery, and [Build, Validation, Localization, and Dependency Release Operations](/openwiki/operations/build-test-and-release.md) for ordinary validation.
The shared view presents access state and dates, plan cards, feature disclosure, restore, legal links, and recovery controls. Plan cards and purchase buttons are disabled when that plan is unavailable or a purchase is processing; a missing price offers **Reload App Store Prices**. Restore remains available even with existing access; manage subscription is offered only for an account-owned subscription, not Family Shared or lifetime access. Purchase actions stay visible for progress or errors but cannot initiate another purchase when access already exists. At accessibility text sizes, purchase controls move into the scroll content and plan cards stack vertically instead of relying on a cramped bottom inset. Verify the feature list and free/Pro boundary against [Commerce, Localization, and Product Surfaces](/openwiki/concepts/commerce-localization-and-product-surfaces.md): free Workspace composition is not a Pro benefit; paid gates include assistant, file upload, Metrics limits, remote MCP, Mac-only MCP server, and Vault iCloud sync.
## Entitlement and failure checks
- A verified, non-revoked lifetime entitlement wins over annual status. A verified annual introductory trial, active subscription, or grace period grants Pro; cancellation keeps access through verified expiry. Billing retry without grace, expiration, upgrade-away, revocation/refund, and unverified transactions must not unlock Pro. Retired standalone trials are not an access source.
- Entitlement refresh and product metadata fetch are independent. Catalog or network failure can clear available product prices and show recovery, but must **not** erase verified access. On launch the controller observes `Transaction.updates`; purchase and restore refresh status, finish verified transactions, and handle deferred Ask to Buy approval without duplicate requests.
- Product validation prevents a misconfigured annual period or non-family-shareable product from appearing purchasable. Recheck actual StoreKit and App Store Connect configuration when a plan unexpectedly vanishes instead of adding a UI fallback price. A local test-only unrestricted status is not a production entitlement override.
## Localized storefront and release gate
1. Reconcile the product matrix, trial, Family Sharing, and intended grace settings in **App Store Connect** for English, Simplified Chinese, and Traditional Chinese; compare the actual Sandbox display prices and subscription group, not only `StoreKit/Termind.storekit`. Verify new-account trial eligibility and used-offer ineligibility; trial-to-paid renewal, cancellation-through-expiry, billing retry/grace, refund/revocation, restore, Ask to Buy, and lifetime precedence on Mac, iPhone, and iPad. Verify the same Apple account across devices and Family Sharing with a separate family account.
2. Inspect both native paywalls with live StoreKit metadata: annual and lifetime selection, 14-day fixture trial disclosure when eligible, renewal/no-renewal language, status/date, restore/manage links, localized legal/disclosure text, disabled/missing-product and retry states, and readable layouts at accessibility sizes. Run `FrameworkTests/ProOfferPresentationTests.swift` and `FrameworkTests/ProPaywallPresentationTests.swift` for duration/locale/eligibility and status behavior; `TFMTests/ProPaywallRenderingTests.swift` and `TFITests/ProPaywallRenderingTests.swift` render en, zh-Hans, zh-Hant in regular and accessibility text, free and subscribed states. Mobile key-window rendering is opt-in via `TERMIND_MOBILE_UI_TESTS=1` with parallel testing disabled; the fixtures do not contact StoreKit or prove production pricing. Run the opt-in `TFMTests/StoreKitTrialTests.swift` with `TERMIND_STOREKIT_TESTS=1` for local purchase, trial, precedence, pending approval, invalid catalog, and metadata-failure behavior. See [Build, Validation, Localization, and Dependency Release Operations](/openwiki/operations/build-test-and-release.md) for the general test invocation playbook.
3. Confirm the final localized **storefront imagery**, separately from paywall screenshots: `Marketing/AppStore/en`, `Marketing/AppStore/zh-hans`, and `Marketing/AppStore/zh-hant` each have Mac, iPhone 6.5-inch, and iPad 13-inch sets of six JPG boards. Review language, device/platform sizing, readable native chrome, and offer/product messaging against the current storefront metadata before uploading to App Store Connect. These are final boards, not the capture or device-frame inputs used by the website. For the generation and review workflow see [Marketing Assets, Screenshot Production, Figma Exports, and App Icons](/openwiki/operations/marketing-assets-and-app-icons.md).
4. Record App Store Connect/Sandbox checks independently of local tests and artwork export checks. Local rendering and `SKTestSession` cannot establish production metadata, approval behavior, cross-device delivery, or Family Sharing. Coordinate any changes to marketing and free-Workspace copy without silently changing the product IDs, offer terms, group, or grace policy.
+18 -10
View File
@@ -3,6 +3,9 @@ type: engineering quickstart
title: Termind Engineering Quickstart
description: Task-oriented routes to Termind's owning layer, startup and shutdown lifetimes, focused tests, and build gates.
tags: [engineering, architecture, routing, testing, macos, ios]
verified:
- by: openwiki/0.5.2
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
@@ -18,10 +21,14 @@ sources:
resource: repo://TFI/App/MobileRootView.swift
- id: openwiki-source-6c9f797fc6a1e7ce639b72b8
resource: repo://TFI/App/TermindIOSApp.swift
- id: openwiki-source-fffc181d864b6caea779a6f5
resource: repo://TFITests/MobileAdaptiveLayoutTests.swift
- id: openwiki-source-7341d7b266d976d7aac5d161
resource: repo://TFITests/MobileEditorToolbarTests.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-22b9fca540c3029c5ace451e
@@ -32,10 +39,9 @@ sources:
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-0dd012e3740bcc348fc36ccb
resource: repo://TFMTests/StoreKitTrialTests.swift
generated: { by: "codex", at: "2026-09-23T17:55:27.475Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
- id: openwiki-source-a08489338be00125d646c77e
resource: repo://TFMTests/VisibleWindowTestTrait.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Termind Engineering Quickstart
@@ -57,18 +63,20 @@ Termind is one Xcode project with native `TFM` (macOS) and `TFI` (iPhone/iPad) p
| Terminal, metrics, forwards, shell hooks or forwarding pools | [Remote Services and Forwarding](/openwiki/concepts/remote-services-and-forwarding.md), [Shell Integration](/openwiki/concepts/shell-integration.md), [Port Forwarding Dispatch](/openwiki/workflows/port-forwarding-pool-and-dispatch.md); choose the matching service or pump tests. |
| SFTP browsing, transfer scheduling, external edit | [SFTP Transfer, Scheduling, and External Edit Workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md); select the transfer, conflict, or edit suite. |
| Assistant turns, approvals, host tools, skills, memory | [Assistant, Agent Runtime, Skills, and Memory](/openwiki/concepts/agent-runtime-and-assistant.md); target preparation, cancellation, persistence, tools, or memory tests. |
| SwiftData, secrets, migrations, CloudKit, settings | [Persistent Data, Migrations, and Secret Boundaries](/openwiki/concepts/persistence-and-secrets.md) and [Settings, Vault, Metrics, and Cloud Sync](/openwiki/workflows/settings-and-cloud-sync.md); select repository, migration, or sync lifecycle tests. |
| SwiftData, secrets, migrations, CloudKit, settings | [Persistent Data, Migrations, and Secret Boundaries](/openwiki/concepts/persistence-and-secrets.md), [Settings, Vault, Metrics, and Cloud Sync](/openwiki/workflows/settings-and-cloud-sync.md), and [CloudKit Schema Deployment and Signed-Device Release Readiness](/openwiki/operations/cloudkit-release-readiness.md); select repository, migration, or sync lifecycle tests. |
| MCP server, external upload/download, bridge | [MCP Server, Transfer APIs, and Stdio Bridge](/openwiki/integrations/mcp-server-and-bridge.md); run token, server-session, transfer, or bridge tests. |
| StoreKit, localized copy, widgets, screenshots, website | [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); use localization, app, screenshot, StoreKit, or website checks as appropriate. |
| StoreKit, localized copy, widgets, screenshots, website | [Commerce, Localization, and Product Surfaces](/openwiki/concepts/commerce-localization-and-product-surfaces.md), [Storefront Commerce Release Checks](/openwiki/operations/storefront-commerce-release.md), and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md); use localization, app, screenshot, StoreKit, or website checks as appropriate. |
| Picking a deterministic test seam | [Testing Strategy and Behavioral Boundaries](/openwiki/testing/behavioral-boundaries-and-fixtures.md); run the narrow behavioral test before the affected target suite. |
## Lifetime and change boundaries
`TermindDomain` defines portable rules; `TermindApplication` owns ports and use cases; Persistence owns SwiftData models and container construction; infrastructure implements services; apps assemble concrete dependencies and native UI. `ArchitectureBoundaryTests` rejects shared-layer app imports, forbidden platform/storage/transport imports, concrete implementations in feature/application layers, duplicated AgentKit runtime types, and SwiftData models outside Persistence. Fix an ownership violation rather than bypassing the test.
`TermindDomain` defines portable rules; `TermindApplication` owns ports and use cases; `TermindPersistence` owns SwiftData models, repositories and container construction; infrastructure implements services; `TermindPresentation` owns reusable SwiftUI content and copy; apps assemble concrete dependencies and native UI. `ArchitectureBoundaryTests` checks **specific** forbidden imports per root, not an all-UI-framework ban: its five-framework rule excludes Presentation and rejects app targets plus `AppKit`, `UIKit`, `IOKit` and `ServiceManagement`; the separate Presentation rule allows `SwiftUI` but rejects app targets, `AppKit`/`UIKit`, storage, concrete infrastructure and `StoreKit`. Shared Application cannot import Infrastructure, Persistence or SwiftData; desktop Application/Features and mobile layers have their own checks. The tests also guard concrete constructions in selected feature/application roots, AgentKit type duplication and SwiftData ownership. Fix an ownership violation rather than bypassing the test; see [System Boundaries](/openwiki/architecture/system-boundaries.md) for the precise scope.
`TermindApp` makes the macOS container and shared `AppModel` at launch; XCTest and debug screenshot demos use in-memory stores. If the local database cannot open, startup fails rather than replacing it with an empty store. Each `WindowGroup` instance gets its own `WindowModel` for selection and workspaces, while app services are shared. `TermindIOSApp` migrates language preferences and creates one live or testing `MobileAppModel`; successful scenes receive its container, and failure shows an unavailable-data view. Each `MobileRootView` makes a scene-local `MobileSceneModel`, but the mobile app model shares services and live workspaces across scenes. Restore workspace descriptors, not live transports or credentials. Desktop session/pane and mobile workspace owners end their own connection-history entries on close.
`TermindApp` makes the macOS container and shared `AppModel` at launch; XCTest and debug screenshot demos use in-memory stores. If the local database cannot open, startup fails rather than replacing it with an empty store. Each main `WindowGroup` instance gets its own `WindowModel` for selection and workspaces while app services are shared; `RootView` registers the window, installs its focused scene value and keeps mounted workspace views when switching destinations. `TermindIOSApp` migrates language preferences and creates one live or testing `MobileAppModel`; successful scenes receive its container, and failure shows an unavailable-data view. Each `MobileRootView` makes a scene-local `MobileSceneModel`, but the mobile app model shares services and live workspaces across scenes. Restore workspace descriptors, not live transports or credentials. Desktop session/pane and mobile workspace owners end their own connection-history entries on close.
Mobile phase changes are aggregated across scenes: background work is paused when *all* registered scenes are backgrounded; the expiration handler suspends workspaces, stops forwards, pauses transfers, and expires Assistant work. An active scene resumes monitoring, memory, workspaces, eligible sync, and metrics. On macOS, closing the last window does **not** always quit: the menu-bar metrics preference and running metrics decide. Quit first rechecks unuploaded SFTP edits and can be cancelled; confirmed termination fences new Assistant runs, drains cancellation/persistence, stops transfers and MCP, then closes agent resources. The delegate waits for cleanup or a three-second fallback before replying to AppKit. Use [Platform Runtime](/openwiki/architecture/platform-runtime.md) for the full sequence and ownership rules.
In Debug XCTest runs, the **real desktop app** still launches. By default it suppresses automatic launch of the main and external-auth scenes and disables main-scene restoration; an explicit `TERMIND_WINDOW_TESTS=1` lifts suppression, as does an active screenshot demo. This host-level safeguard complements, rather than replaces, `.requiresVisibleWindow` on any test that presents a window or takes focus. Screenshot demos also disable main-scene restoration. See [Testing Strategy](/openwiki/testing/behavioral-boundaries-and-fixtures.md) and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md).
Mobile phase changes are aggregated across scenes: background work is paused when *all* registered scenes are backgrounded; the expiration handler suspends workspaces, stops forwards, pauses transfers, and expires Assistant work. An active scene resumes monitoring, memory, workspaces, eligible sync, and metrics. On macOS, closing the last window does **not** always quit: during tests it never terminates the test host; otherwise the menu-bar metrics preference and running metrics decide. Quit first rechecks unuploaded SFTP edits and can be cancelled; confirmed termination fences new Assistant runs, drains cancellation/persistence, stops transfers and MCP, then closes agent resources. The delegate replies to AppKit only once, after cleanup or a three-second fallback. Use [Platform Runtime](/openwiki/architecture/platform-runtime.md) for the full sequence and ownership rules.
AgentKit is a separately versioned, host-neutral remote package for the agent loop, approvals, providers, MCP client and built-in tools; Termind owns SSH/SFTP tools and registers them additively. For a cross-repository change, release `../AgentKit`, then update `minimumVersion` in `Termind.xcodeproj/project.pbxproj` **and** `Package.resolved`; the sibling working tree does not affect Xcode's pinned build. Keep metadata in persistence and secret values behind Keychain references. Follow [System Boundaries and Dependency Ownership](/openwiki/architecture/system-boundaries.md) for imports and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md) for release steps.
@@ -84,6 +92,6 @@ xcrun swift-format lint --strict --recursive Frameworks TFM TFI FrameworkTests T
Scripts/check-zh-localization.sh
```
For `TFI` tests use an installed iPhone/iPad simulator. Visible-window macOS suites require `.requiresVisibleWindow` and explicit `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` (or `TERMIND_WINDOW_TESTS=1` in the Xcode test action), preferably with `-only-testing:TFMTests/<Suite>`. Mobile key-window integration suites require `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1`, `-parallel-testing-enabled NO`, and a narrow `-only-testing:TFITests/<Suite>`. StoreKit suites require manual authorization and `TERMIND_STOREKIT_TESTS=1`. Keep these gates off for routine checks; offscreen tests remain enabled. New app text needs completed `zh-Hans` and `zh-Hant` translations in `Frameworks/Resources/Localizable.xcstrings`; run the localization script (requires `jq`) even without intended copy changes, and `AppLanguageTests` for language behavior. For web changes run `cd LandingPage && npm ci && npm run build` and check English and `/zh/` routes.
For `TFI` tests use an installed iPhone/iPad simulator. Visible-window macOS suites require `.requiresVisibleWindow` and explicit `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` (or `TERMIND_WINDOW_TESTS=1` in the Xcode test action), preferably with `-only-testing:TFMTests/<Suite>`; the opt-in enables both the test and automatic app-host windows. Opt-in mobile key-window suites require `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1`, `-parallel-testing-enabled NO`, and a narrow `-only-testing:TFITests/<Suite>`; `MobileAdaptiveLayoutTests` is serialized but not gated by that variable. StoreKit suites require manual authorization and `TERMIND_STOREKIT_TESTS=1`. Keep these gates off for routine checks; offscreen tests remain enabled. Define app copy via shared `TermindPresentation/Strings` resources; new app text needs completed `zh-Hans` and `zh-Hant` translations in `Frameworks/Resources/Localizable.xcstrings`. Shared catalogs are manually managed: after catalog edits run `Scripts/normalize-string-catalogs.py --write`, then `Scripts/check-presentation-copy.sh` and `Scripts/check-zh-localization.sh` (requires `jq`); run the Chinese check even without intended copy changes, and `AppLanguageTests` for language behavior. For web changes run `cd LandingPage && npm ci && npm run build` and check English and `/zh/` routes.
Before submitting, inspect the diff for secrets, generated artifacts, cross-layer imports and accidental `Package.resolved` churn; use the routed operations pages for CloudKit deployment, StoreKit release, marketing assets, and forwarding benchmark measurement semantics.
@@ -3,11 +3,18 @@ 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-24T03:18:19.992Z
sources:
- id: openwiki-source-8037e2358a2c4f9b2c722a11
resource: repo://AGENTS.md
- id: openwiki-source-5f99e8af445e073ffe9bc257
resource: repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift
- id: openwiki-source-a298d9034d557f1b420cb306
resource: repo://Frameworks/TermindPresentation/ProOfferPresentation.swift
- id: openwiki-source-ff6aeac237822b937eb60926
resource: repo://Frameworks/TermindPresentation/ProPaywallContent.swift
- id: openwiki-source-b347308e8c5cc6c0b0d29b7d
resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift
- id: openwiki-source-017f5e2abe9b13df755a5322
@@ -26,12 +33,20 @@ sources:
resource: repo://FrameworkTests/CloudSyncSafetyTests.swift
- id: openwiki-source-8428b9f5de49b8a561d93fa5
resource: repo://FrameworkTests/PersistenceCompatibilityTests.swift
- id: openwiki-source-3b424584de88a1150af27f83
resource: repo://FrameworkTests/ProOfferPresentationTests.swift
- id: openwiki-source-925cc598397685e13fcf56c4
resource: repo://FrameworkTests/ProPaywallPresentationTests.swift
- id: openwiki-source-db40aa993661b07f1a9aff6d
resource: repo://FrameworkTests/SSHInteractionPolicyTests.swift
- id: openwiki-source-294dd6a8637abdafe40e9570
resource: repo://Scripts/generate-v28-fixture.swift
- id: openwiki-source-27d6a8d3b199ecf35f59fafb
resource: repo://Scripts/swiftdata-repository-declarations.sh
- id: openwiki-source-cd0be716a2446029f345525a
resource: repo://Termind.xcodeproj/project.pbxproj
- id: openwiki-source-0ffab0ae6452f870ce4a0efe
resource: repo://TFI/Features/Commerce/MobileProView.swift
- id: openwiki-source-350d4a794cfef67e406ddf9b
resource: repo://TFI/Infrastructure/MobileWorkspaceStore.swift
- id: openwiki-source-34542e0f07e1650e098824c7
@@ -52,6 +67,10 @@ sources:
resource: repo://TFITests/MobileEditorToolbarTests.swift
- id: openwiki-source-9b78a7e39bfa08bea5192722
resource: repo://TFITests/MobileWorkspaceStoreTests.swift
- id: openwiki-source-bc6023e93d60f0fac1bbea53
resource: repo://TFITests/ProPaywallRenderingTests.swift
- id: openwiki-source-766dc23f16ac26a41a5b5c22
resource: repo://TFM/Features/Commerce/ProPaywallView.swift
- id: openwiki-source-cfbc34def649c94f760c5695
resource: repo://TFMTests/AgentHostAuthenticationTests.swift
- id: openwiki-source-715de8d16be5a3d06ae915ad
@@ -62,20 +81,21 @@ sources:
resource: repo://TFMTests/ArchitectureBoundaryTests.swift
- id: openwiki-source-78797a18dd3153d23a2c42e2
resource: repo://TFMTests/ChatComposerStateTests.swift
- id: openwiki-source-1ec6004f796c8c008740f13b
resource: repo://TFMTests/ChooserInteractionTests.swift
- id: openwiki-source-c15cd5bef4646aaf64df407e
resource: repo://TFMTests/ConnectionHistoryTests.swift
- id: openwiki-source-47dc468698b2904f0004ee04
resource: repo://TFMTests/MCPUploadTests.swift
- id: openwiki-source-8e854eded0d88c86c59da2e5
resource: repo://TFMTests/ProPaywallRenderingTests.swift
- id: openwiki-source-53e2b2fd2e661123f63e69e1
resource: repo://TFMTests/SFTPTransferContextTests.swift
- id: openwiki-source-960109cd5bc0de7a879c1e16
resource: repo://TFMTests/VaultSyncTests.swift
- id: openwiki-source-a08489338be00125d646c77e
resource: repo://TFMTests/VisibleWindowTestTrait.swift
generated: { by: "codex", at: "2026-09-24T01:58:11.184Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-24T01:58:11.184Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Testing Strategy and Behavioral Boundaries
@@ -149,7 +169,9 @@ These tests do not prove unknown-field round trips through an actual historical
### 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. It also checks that all three CloudKit coordinators retain the shared batch/provider/quarantine gates and that the lifecycle itself does not acquire a SwiftData or Persistence import. These source checks complement, rather than replace, the runtime safety fixtures. Run it whenever moving code, changing framework dependencies, adding persistence types, or crossing the AgentKit boundary.
`TFMTests` owns desktop composition and native interaction seams. `ArchitectureBoundaryTests` is an executable source-boundary check, not a compiler-enforced dependency graph. Its restrictions are **per module**: Domain excludes platform UI, storage, networking, security and commerce imports; `TermindApplication` excludes implementation-framework imports, SwiftData and concrete I/O construction; macOS `Features` excludes persistence/transport imports and concrete constructors. Mobile `Application` excludes UI, SwiftData, GRDB and Persistence; mobile `UI` excludes Persistence and RemoteInfrastructure; mobile `Features` excludes concrete I/O construction. Shared frameworks cannot import app targets or platform-only APIs, `TermindPersistence` cannot import infrastructure, and `TermindPresentation` stays clear of platform, storage, StoreKit and implementation imports. Apply the corresponding rule when adding a module or relocating code, rather than assuming one blanket prohibition applies everywhere.
The suite additionally scans for `@Model` outside Persistence and uses the SwiftSyntax-backed `Scripts/swiftdata-repository-declarations.sh` parser to reject **declarations** of `SwiftData*Repository` elsewhere without mistaking references, strings or comments for ownership violations. It checks app-local `AppStrings` redeclarations and a bounded list of AgentKit-owned type names, limits `ListViewKit` imports to approved native-list workloads, and keeps the forwarding benchmark independent of the app/test target. It scans CloudKit delegate files for lifecycle batch/provider/quarantine/conflict calls, and checks that `CloudSyncLifecycle` keeps its 250-record boundary without SwiftData or Persistence imports. These are source-level guardrails (mostly literal import/token checks), not proof of runtime behavior: run the CloudKit safety and lifecycle fixtures for blocked uploads and recovery. Run this suite when moving code, changing dependencies or persistence ownership, or crossing AgentKit and CloudKit boundaries.
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.
@@ -192,7 +214,7 @@ External connection URLs are another ownership boundary: opening one creates an
## 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.
Offscreen layout and logic tests remain ordinary tests. A macOS test that **presents a window or takes application focus** (including Dock actions, external authentication and Launch Services alerts) must opt in with `.requiresVisibleWindow` on its suite or individual test. The trait is a Swift Testing `ConditionTrait`: it enables the test only when the test host sees `TERMIND_WINDOW_TESTS=1`; otherwise that test is skipped. For example, `ChooserInteractionTests` is gated as a suite because it makes its window key, whereas individual integration tests may carry the trait without skipping their offscreen neighbors. Do not mark all rendering tests as visible-window tests: `TFMTests/ProPaywallRenderingTests.swift` uses a borderless `NSWindow` and `NSHostingView` for **offscreen** layout and bitmap capture, without making it key or activating the app, so its serialized suite runs by default. Conversely, creating a key window or changing focus requires the gate even if the test does not save a screenshot.
Run a named visible-window suite only when its interaction contract changed, for example:
@@ -200,13 +222,20 @@ Run a named visible-window suite only when its interaction contract changed, for
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. Mobile key-window integration suites are also skipped by default because UIKit presentation is process-wide: opt in with `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1` (forwarded as `TERMIND_MOBILE_UI_TESTS=1`), `-parallel-testing-enabled NO`, and a narrow `-only-testing:TFITests/<Suite>` filter. StoreKit tests require separate manual authorization and remain skipped by default; run `TERMIND_STOREKIT_TESTS=1` with a narrow `-only-testing:TFMTests/StoreKitTrialTests` filter. A visual change still needs behavior-appropriate coverage: an offscreen test for state/policy, an opted-in window/key-window test for focus/presentation when applicable, and screenshot/marketing capture only where that workflow owns the deliverable.
In Xcode, set `TERMIND_WINDOW_TESTS=1` in the Test action environment. Existing screenshot suites can retain their dedicated gates. Mobile key-window integration suites are also skipped by default because UIKit presentation is process-wide: opt in with `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1` (forwarded as `TERMIND_MOBILE_UI_TESTS=1`), `-parallel-testing-enabled NO`, and a narrow `-only-testing:TFITests/<Suite>` filter. `TFITests/ProPaywallRenderingTests.swift` follows that policy: its serialized test mounts `ProPaywallContent` in a `UIHostingController`, makes a temporary `UIWindow` key, then hides it and restores the previous key window. StoreKit tests require separate manual authorization and remain skipped by default; run `TERMIND_STOREKIT_TESTS=1` with a narrow `-only-testing:TFMTests/StoreKitTrialTests` filter. A visual change still needs behavior-appropriate coverage: an offscreen test for state/policy, an opted-in window/key-window test for focus/presentation when applicable, and screenshot/marketing capture only where that workflow owns the deliverable.
### Pro paywall: separate commerce policy from rendering
Both apps feed StoreKit-derived status, prices, billing period and trial eligibility into shared `ProPaywallPresentation`, and supply platform colors and purchase/restore/reload/manage callbacks to shared `ProPaywallContent`; the desktop reports MCP server support, mobile does not. `FrameworkTests/ProPaywallPresentationTests.swift` checks access labels and date semantics across subscription phases, owned versus family-shared management, and the rule that missing prices or in-flight work disable purchases without hiding recovery. `ProOfferPresentationTests` uses a synthetic offer instead of contacting StoreKit: it checks plan/trial button copy, weekly StoreKit trial duration converted to full days, localized billing units and composed details for English and both Chinese locales, missing-product fields, and an injected localization callback. A locale supplied for duration formatting does not itself change the default localized label lookup; the platform view supplies its own locale-aware localization closure.
The platform rendering fixtures then test the **same shared content** rather than purchasing anything: free versus subscribed, `en`/`zh-Hans`/`zh-Hant`, regular versus accessibility text, and horizontal overflow/usable scroll space at the macOS sheet size or mobile phone/tablet sizes. They attach PNGs and write previews to a temporary directory for inspection. These assertions and screenshots are layout evidence, not proof of StoreKit transaction flow or of tapped-button behavior. Use `ProAccessTests` for the desktop feature gate and separately authorized StoreKit tests for actual commerce paths.
## 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. |
| Framework dependency or data-owner change | `ArchitectureBoundaryTests` plus affected framework suite | Respect each module's import/construction rules; no app import from shared code, local shadow of guarded AgentKit types, or SwiftData model/repository 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. |
| Assistant message-boundary edits or replacement provenance | Agent persistence/replay, conversation operations/controller, composer and mobile Assistant fixtures | Same-run prefix and graph survive, suffix backing is removed, staging adopts once, chronology remains stable, live/restore agree, and late retired writes cannot resurrect history. |
| CloudKit format, upload scheduling, conflict or recovery behavior | Shared lifecycle, coordinator-safety and on-disk safety fixtures | Unsupported IDs never upload, compatible peers progress, restrictions survive retry/reopen, and failed reconciliation cannot unblock data. |
@@ -216,7 +245,8 @@ In Xcode, set `TERMIND_WINDOW_TESTS=1` in the Test action environment. Existing
| Mobile cards or visual presentation | `MobileCardTests` for layout policy plus focused rendering/key-window suite if needed | Container width/accessibility layout and stable heights work offscreen; shared UIKit presentation is opted in and serialized. |
| Tool approval, transcript cards, or presenter metadata | `AgentToolPresentationTests` and affected platform rendering suites | Registry IDs stay unique, legacy/restored detail agrees, and structured detail, preview and copy behavior survive. |
| MCP upload ticket, stream, or HTTP route | `MCPUploadTests` plus affected server/session suite | Authenticated tickets remain scoped; offset/digest/commit and cancellation/cleanup state remain correct through loopback HTTP. |
| 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. |
| Pro paywall copy, eligibility or layout | `ProOfferPresentationTests`, `ProPaywallPresentationTests`, platform `ProPaywallRenderingTests` | Trial durations and labels, purchase availability and recovery stay correct without StoreKit; platform layouts fit across locales and accessibility sizes, with mobile key-window rendering opted in. |
| macOS rendering or focus behavior | Focused offscreen test plus `.requiresVisibleWindow` suite when needed | Offscreen rendering remains default; tests that present windows or take focus are explicitly opted in. |
## Execution strategy
+8 -4
View File
@@ -5,7 +5,7 @@ description: "Native drag sources, live drop routing, split previews, cancellati
tags: [macos, tfm, drag-and-drop, workspaces, panes, assistant, appkit, lifecycle, testing]
verified:
- by: openwiki/0.5.2
at: 2026-09-23T17:55:27.475Z
at: 2026-09-24T03:18:19.992Z
sources:
- id: openwiki-source-685b7f8e7dbcf91b4e2a50e2
resource: repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift
@@ -15,6 +15,8 @@ sources:
resource: repo://FrameworkTests/AssistantConversationOperationsTests.swift
- id: openwiki-source-4dbea0ff2808163cb4ecdd8f
resource: repo://TFM/App/AppModel.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-d35453512ef488d0cacdc06e
resource: repo://TFM/Features/Assistant/AssistantView.swift
- id: openwiki-source-564c1a0cc523e70840b9fc66
@@ -51,7 +53,7 @@ sources:
resource: repo://TFMTests/WorkspaceNavigatorDropTests.swift
- id: openwiki-source-a48980e81bab99fcd643df54
resource: repo://TFMTests/WorkspaceWindowMoveTests.swift
generated: { by: "codex", at: "2026-09-23T17:55:27.475Z" }
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# TFM Drag and Drop: Workspaces, Panes, and Assistant
@@ -190,6 +192,8 @@ sequenceDiagram
Coordinator->>Coordinator: Position and fit destination window
```
Live layout ownership changes only when the requested destination window registers.
The request stores a weak source, the move identity, ordinary source size and optional release point. Repeated requests for the same source and move reuse the pending request ID. If the scene factory is absent or the requested source/pane is invalid, no ownership mutation occurs.
Registration consumes the request once. A whole Workspace moves as the same object, including its complete split layout. A pane from a split workspace is extracted into a newly named workspace around the **same Pane object**; the remaining source tree repairs focus, group naming and broadcast eligibility through `Workspace.closePane`. A lone pane moves its original workspace, retaining its name and template identity.
@@ -227,7 +231,7 @@ Evidence: [active list routing](../../TFM/Features/Assistant/AssistantView.swift
| Ownership loss, reconnect, changed history or late request | `WorkspaceWindowMoveTests`: destination delay, duplicate requests, lone-pane identity, closed sources, reversed arrival order and window placement. |
| Assistant hidden receiver or active-row eligibility | `AssistantConversationListDropTests`; `AssistantConversationOperationsTests` covers persistence failure and preserved activity; `WindowStateTests` covers stable manual order. |
Run the relevant logic suites without visible-window opt-in first, keeping dependency resolution pinned:
Run the offscreen policy, geometry and lifecycle cases without visible-window opt-in first, keeping dependency resolution pinned. The suite selection below also includes three `WorkspaceNavigatorDropTests` mouse/session cases that will be skipped by default; an `NSWindow` fixture alone does not require the gate if it stays offscreen.
```sh
xcodebuild -quiet -project Termind.xcodeproj -scheme TFM \
@@ -241,7 +245,7 @@ xcodebuild -quiet -project Termind.xcodeproj -scheme TFM \
-only-testing:TFMTests/AssistantConversationListDropTests test
```
Real mouse/List interaction cases use `.requiresVisibleWindow`. Opt in narrowly; these tests can show windows and take focus. Keep parentheses in a Swift Testing single-test filter and verify that the result bundle contains the intended test rather than trusting a zero exit status alone:
The `WorkspaceNavigatorDropTests` single-click, native mouse-session and split-workspace tear-off cases use `.requiresVisibleWindow` because they call `makeKeyAndOrderFront` (the tear-off case also orders another window and activates the app). The trait skips these cases unless the **test host** sees `TERMIND_WINDOW_TESTS=1`; the Xcode command-line prefix `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` forwards that value. The Debug app also suppresses automatic test-window launch by default, but this does not replace the per-test gate. Opt in only when changing real mouse/List or focus behavior, with `-parallel-testing-enabled NO` and a narrow filter. In Xcode's Test action, set `TERMIND_WINDOW_TESTS=1` directly. Keep parentheses in a Swift Testing single-test filter and verify that the result bundle contains the intended test rather than trusting a zero exit status alone:
```sh
TEST_RUNNER_TERMIND_WINDOW_TESTS=1 xcodebuild -quiet \
+31 -11
View File
@@ -3,6 +3,9 @@ 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-24T03:18:19.992Z
sources:
- id: openwiki-source-dc7b363138921b0923d2dc2f
resource: repo://Frameworks/TermindApplication/FeatureModels/ConnectionHistoryModel.swift
@@ -10,6 +13,8 @@ sources:
resource: repo://Frameworks/TermindApplication/HistoryLimits.swift
- id: openwiki-source-9fbc733f79d51a7265ee9e4a
resource: repo://Frameworks/TermindApplication/SettingsKey.swift
- id: openwiki-source-9bd2b93db78747d6956c2405
resource: repo://Frameworks/TermindDomain/Hosts/Host.swift
- id: openwiki-source-1429ec01ac68a7770ce41977
resource: repo://Frameworks/TermindDomain/Vault/CloudSyncSafety.swift
- id: openwiki-source-a9afccb62e1c69e5a0fbf46c
@@ -26,6 +31,8 @@ sources:
resource: repo://Frameworks/TermindInfrastructure/Cloud/VaultSyncCoordinator.swift
- id: openwiki-source-1366e71322413c98e0ac1534
resource: repo://Frameworks/TermindPersistence/CloudSyncSafetyStore.swift
- id: openwiki-source-fe1dc993163bb9ff61397be7
resource: repo://Frameworks/TermindPersistence/HostPersistence.swift
- id: openwiki-source-07774a741f517493204edd63
resource: repo://Frameworks/TermindPersistence/MetricsSyncJournal.swift
- id: openwiki-source-65a2da12a42f42fb0850078e
@@ -46,6 +53,12 @@ sources:
resource: repo://Frameworks/TermindPersistence/SwiftDataVaultJournal.swift
- id: openwiki-source-a0d614d618b11f103ec246ae
resource: repo://Frameworks/TermindPersistence/SwiftDataVaultStore.swift
- id: openwiki-source-7a9c6d90cba4ebd1d1398673
resource: repo://Frameworks/TermindPersistence/TermindPersistence.swift
- id: openwiki-source-79e0f2a939e874c6a6803c19
resource: repo://Frameworks/TermindPersistence/TermindSchemaV28HostModels.swift
- id: openwiki-source-8fda0c115d3df709fffe110c
resource: repo://Frameworks/TermindPersistence/TermindSchemaV29HostModels.swift
- id: openwiki-source-15e5026028d13d2202844f68
resource: repo://Frameworks/TermindPersistence/TermindSchemaV33IdentityModels.swift
- id: openwiki-source-3cfc52217a7a6835b4bffac1
@@ -62,14 +75,17 @@ sources:
resource: repo://FrameworkTests/CloudSyncSafetyPersistenceTests.swift
- id: openwiki-source-eb9518e5c7eb3782fa0cccc0
resource: repo://FrameworkTests/CloudSyncSafetyTests.swift
- id: openwiki-source-8428b9f5de49b8a561d93fa5
resource: repo://FrameworkTests/PersistenceCompatibilityTests.swift
- id: openwiki-source-906678adb91c2fce2d3fcaed
resource: repo://TFI/App/MobileAppModel.swift
- id: openwiki-source-4dbea0ff2808163cb4ecdd8f
resource: repo://TFM/App/AppModel.swift
generated: { by: "codex", at: "2026-09-23T00:14:42.075Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-23T10:08:51.776Z
- id: openwiki-source-cfe2a6b22338023c37a5b503
resource: repo://TFM/Features/Settings/SettingsPageView.swift
- id: openwiki-source-0a0c39623be1c4e870d0f538
resource: repo://TFM/Features/Settings/SyncSettings.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# Settings, Vault, Metrics, and Cloud Sync Workflow
@@ -80,6 +96,8 @@ This workflow is CloudKit replication built around a SwiftData journal, not Swif
## Categories, switches, and runtime ownership
On desktop `SettingsPageView` routes the Sync category to `SyncSettings`. Its master switch checks the Pro capability, reconciles app-wide access, and, when enabled, attempts to move custom Host passwords into iCloud Keychain; Vault selection does the same migration. The category checkboxes change their own coordinator's enable state and show per-category status, retry, or account-merge confirmation. This UI is a control surface, not the store migration or CloudKit engine itself.
| Category | Coordinator and zone | Content boundary | Default control |
| --- | --- | --- | --- |
| Vault | `VaultSyncCoordinator`; `TermindVaultV1`; `VaultItem` | Hosts, identities, SSH-key references, known hosts, snippets, forwarding rules, workspace templates, connection-history events, and the reusable device directory | `vault.sync.enabled` plus `icloud.sync.enabled` |
@@ -94,19 +112,18 @@ All master and category switches default on. A category is enabled only when the
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, prepares scoped safety state, resets incompatible CloudKit metadata when needed, commits a recovery checkpoint, creates an engine, restores only uploadable 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.
<!-- openwiki: mermaid parse failed and this diagram was converted to a text fence so it does not break rendering. Fix the diagram source and restore the mermaid fence. Parser error: Heuristic: a semicolon inside a label breaks rendering; rephrase the label. -->
```text
```mermaid
flowchart TD
Enabled{"Master and category enabled?"} -->|No| Paused["Paused; retain local journal"]
Enabled{"Master and category enabled?"} -->|No| Paused["Paused and retain local journal"]
Enabled -->|Yes| Account{"Account available and binding accepted?"}
Account -->|No| Waiting["Wait for account or merge confirmation"]
Account -->|Yes| Prepare["Prepare scope and persist recovery checkpoint"]
Prepare --> Engine["Create engine; restore eligible queue; ensure zone"]
Prepare --> Engine["Create engine and restore eligible queue and ensure zone"]
Engine --> Fetch["Fetch with current engine"]
Fetch -->|Processing failure| Retired["Retire engine; retain recovery and local edits"]
Fetch -->|Processing failure| Retired["Retire engine and retain recovery and local edits"]
Fetch -->|Successful completion| Gate{"Pending record blocked in this scope?"}
Gate -->|Yes| Held["Retain local intent; exclude from uploads"]
Gate -->|No| Provider["Recheck engine, scope and journal in provider"]
Gate -->|Yes| Held["Retain local intent and exclude from uploads"]
Gate -->|No| Provider["Recheck engine and scope and journal in provider"]
Provider --> Send["Send eligible record"]
```
@@ -145,6 +162,8 @@ Merge is deterministic: newer versions win; an older remote value causes the loc
Vault projections deliberately remove device-local presentation metadata from envelopes: group and package expansion is normalized rather than synchronized. The live V33 Identity shape no longer contains `lastUsedAt` usage metadata. 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, SFTP and workspace preferences use distinct types in the Settings zone so older clients can ignore newer records before decoding.
**Host schema versus cloud wire format:** `TermindSchemaV28HostModels.PersistentHost` is a frozen *local* SwiftData shape with one SSH `port`, `identityID`, and `charset`; the V28→V30 migration keeps those stored property names in the successor Host model as SSH fields and defaults the new Telnet profile to disabled, port 23 and UTF-8. The live `PersistentHost` projection retains independent SSH and Telnet profiles. This migration does not create a Settings record or a new Vault zone: `HostPersistence` reads the migrated Host into a `VaultSnapshot`, bootstraps or diffs its Vault journal, and the existing `VaultItem` host envelope still uses format V1. `Host`'s Codable keys keep `port`, `identityID`, and `charset` for SSH, while new protocol flags and Telnet fields have backward-compatible decode defaults. Do not treat a successful V28 local-store reopen as proof of mixed-version CloudKit writes or account synchronization.
Connection history is an exception to “configuration-only Vault” by design: each event is an independent `connectionHistory` Vault key using the same `VaultItem` record type and V1 envelope. Existing local events bootstrap even after the original Vault bootstrap completed. Insert, end-time update, deletion and clear reconcile history rows with the journal in one transaction; logical deletions use ordinary envelope tombstones. Remote events may arrive before their referenced Host and remain stored but hidden until that Host exists. After local or remote merge, deterministic start-time/UUID ordering retains the newest 250 and journals tombstones for the overflow, allowing devices to converge. Launch-time pruning can discard overflow journal rows that never reached CloudKit; previously uploaded overflow receives tombstones. Platform views then choose a stable-source-device local projection or the complete synchronized event stream.
The reusable device directory is a separate replication stream in the same Vault category. Each `DeviceRecord` uses a `.device` payload keyed by the stable installation ID; its repository upsert and journal envelope commit together independently of the event repository. Platform activation refreshes the current system display name, and app models invalidate the directory cache when remote `.device` keys arrive. Device reconciliation creates or updates records but does not tombstone mappings merely because they are absent locally, and connection-event retention, per-Host deletion, or Clear History never removes them.
@@ -191,6 +210,7 @@ When evolving a record, retain decode compatibility and validation. Unsupported
## Focused verification
- `FrameworkTests/PersistenceCompatibilityTests.swift` opens a copied V28 store twice through `TermindPersistence.makeContainer`, checking the Host's legacy SSH port/identity/charset, disabled-default Telnet profile, associated Vault data and journal state, and default workspace preferences after Settings preparation; this is a local migration/reopen fixture, not a CloudKit sync test. `FrameworkTests/HostProtocolTests.swift` separately checks live Host protocol defaults and persistence projection.
- `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.
- `CloudSyncSafetyTests` runs all three real coordinators behind fake transport, checking actual batches/providers, conflict quarantine, compatible peers, tombstones/recreation, retry/restart, failed-unblock rollback and status hints.
+24 -13
View File
@@ -3,9 +3,14 @@ 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-24T03:18:19.992Z
sources:
- id: openwiki-source-cb178f0d078ab3218679c80e
resource: repo://Frameworks/TermindApplication/Connections/RemoteSessionConnectionController.swift
- id: openwiki-source-d69fe1c34dca9a13f42d2dbc
resource: repo://Frameworks/TermindApplication/Connections/RemoteSessionHostStore.swift
- id: openwiki-source-5aa101e9f8e2906832f58121
resource: repo://Frameworks/TermindApplication/Connections/SSHConnectionPreparation.swift
- id: openwiki-source-4f78037bc69b6dfc293aca3d
@@ -44,16 +49,15 @@ sources:
resource: repo://TFM/App/AppModel.swift
- id: openwiki-source-6570374eaac2e0278fa84640
resource: repo://TFM/App/TermindApp.swift
- id: openwiki-source-7e796927b780e67cc73f6a5b
resource: repo://TFM/Features/Terminal/SSHSessionModel.swift
- id: openwiki-source-22b9fca540c3029c5ace451e
resource: repo://TFM/Features/Workspaces/WindowModel.swift
- id: openwiki-source-cfbc34def649c94f760c5695
resource: repo://TFMTests/AgentHostAuthenticationTests.swift
- id: openwiki-source-85c3f954351f96433cb1fb4b
resource: repo://TFMTests/ConnectionJourneyTests.swift
generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" }
verified:
- by: openwiki/0.5.2
at: 2026-09-23T17:44:09.687Z
generated: { by: "openwiki/0.5.2", at: "2026-09-24T03:18:19.992Z" }
---
# SSH, Telnet, Trust, and Workspace Session Lifecycle
@@ -62,7 +66,7 @@ verified:
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, forwarding, or an Agent tool can share preparation and transport policy without sharing UI lifetime or an interactive prompt. On desktop, `TermindApp` builds one `AppModel` for shared host data and services, but `WindowGroup` constructs a separate `WindowModel` for each window's dynamic workspaces and selection. Agent SSH connections are **not** borrowed from those workspace sessions: `AppModel` constructs `AgentHostServices.live` with the shared coordinator and registers its resolver, authentication registry, connection pool, and background-command owner with Assistant and MCP. Agent sessions can therefore survive a window's workspace closure until their own pool eviction or app cleanup.
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, forwarding, or an Agent tool can share preparation and transport policy without sharing UI lifetime or an interactive prompt. On desktop, `TermindApp` builds one `AppModel` for shared host data and services, but `WindowGroup` constructs a separate `WindowModel` for each window's dynamic workspaces and selection. Agent SSH connections are **not** borrowed from those workspace sessions: `AppModel` constructs `AgentHostServices.live` with the shared coordinator and registers its resolver, authentication registry, connection pool, and background-command owner with Assistant and MCP. Agent sessions can therefore survive a window's workspace closure until their own pool eviction or app cleanup. A temporary pane-backed Agent target is different: the resolver rechecks that its pane still exists before reusing a pooled connection, and a vanished pane makes the target invalid.
```mermaid
sequenceDiagram
@@ -177,7 +181,7 @@ Authentication answers whether a transport may be installed. The next layer deci
`list_hosts` exposes public Vault host metadata and live temporary targets from desktop panes; it does not return credentials. Agent SSH and SFTP tools require an SSH-enabled target, and a closed temporary pane fails target resolution rather than legitimizing a lingering pooled connection. The desktop resolver obtains temporary SSH configuration from the pane when needed. Merely listing a connected pane does not give a tool its PTY: `ssh_exec` opens a dedicated non-PTY exec channel over an **Agent-owned** connection.
For an unpooled host, `AgentSSHAuthenticationRegistry` leases a per-host `AgentSSHAuthenticationContext` only while overlapping operations connect. The resolver requests missing proxy credentials, identity and protected-key passphrase in route order **before** opening the socket, then uses the attempt's callback to ask for host-key approval at handshake and literal keyboard-interactive answers during authentication. Saved Hosts can persist an explicitly saved identity or trust decision; Continue Once remains attempt-scoped, and temporary targets cannot persist trust from an Agent card. Concurrent exec and primary SFTP openings join one authentication prompt and one pending connection. Cancellation removes an individual waiter and cancels its prompt when no waiters remain; generation checks prevent old failures or late answers from overwriting newer attempts. A rejected credential can prompt again for the failing hop or proxy, but successful authentication consumes the submitted secrets. The registry drops the context after its last connecting lease: a later physical connection must resolve saved credentials or ask again, not reuse a previous Custom password.
For an unpooled host, `AgentSSHAuthenticationRegistry` leases a per-host `AgentSSHAuthenticationContext` only while overlapping operations connect. The resolver requests missing proxy credentials, identity and protected-key passphrase in route order **before** opening the socket, then uses the attempt's callback to ask for host-key approval at handshake and literal keyboard-interactive answers during authentication. Saved Hosts can persist an explicitly saved identity or trust decision; Continue Once remains attempt-scoped, and temporary targets cannot persist trust from an Agent card. Concurrent exec and primary SFTP openings join one authentication prompt and one pending connection. Cancellation removes an individual waiter and cancels its prompt when no waiters remain; generation checks prevent old failures or late answers from overwriting newer attempts. A rejected credential can prompt again for the failing hop or proxy, but successful authentication consumes the submitted secrets. For a proxy with an unavailable saved password, the prompt keeps `proxy.username` even if its selected password identity is missing; an unsaved answer overrides the proxy only for this attempt, while Save updates the Vault proxy identity and username. Identity and protected-key passphrase are separate prompts: entering a passphrase merges into the staged identity submission, retaining its password fallback. The registry drops the context after its last connecting lease: a later physical connection must resolve saved credentials or ask again, not reuse a previous Custom password.
`AgentConnectionPool` keys reusable authenticated connections by Host ID and an in-memory route fingerprint (route, identities, proxies, known-host keys and destination charset), not by run or window. Fingerprinting reads no Keychain secrets: changing a saved secret without changing identity affects the **next** connection, whereas changing route or trust invalidates reuse. Concurrent misses coalesce into one open; cancelled or superseded opens cannot publish late sockets. The primary SFTP subsystem and exec commands share the pooled transport; exclusive SFTP leases may use silent auxiliary connections or sibling channels as scheduling allows. Idle sweeping defaults to 180 seconds and spares active exec and SFTP leases; host deletion and app termination explicitly close the pool. This is distinct from the feature-owned terminal, SFTP, and forwarding lifetimes described in the linked pages.
@@ -191,13 +195,20 @@ sequenceDiagram
Tool->>Registry: connectionContext for host
Registry->>Pool: check pooled connection
alt no reusable connection
Registry->>Resolver: resolve route and local credentials
Registry->>Resolver: resolve proxy identity and passphrase in route order
Resolver-->>Registry: one attempt with trust callbacks
Registry->>Pool: open with attempt request
Pool->>Server: handshake and authorize host key
Pool->>Server: authenticate
Pool-->>Registry: pooled transport
Registry->>Registry: consume attempt secrets
alt credential rejected
Registry->>Resolver: retry failing hop or proxy with retained username
Resolver-->>Registry: new one shot attempt
Registry->>Pool: open replacement connection
Pool-->>Registry: authenticated transport
else authenticated
Pool-->>Registry: authenticated transport
end
Registry->>Registry: clear staged secrets
else reusable connection
Pool-->>Registry: pooled transport
end
@@ -223,7 +234,7 @@ The platform rules intentionally differ:
| Background/foreground | Closing a window tears down its workspace sessions, not app-wide Agent connections, transfers, or services. Quit checks pending external edits, then initiates shared shutdown (with a bounded termination reply) and closes every live window. | Only when all tracked scenes are backgrounded does a background task begin. Its expiration immediately requests workspace suspension, stops forwarding, pauses transfers and cancels Assistant runs; Assistant subsequently closes Agent background commands and pooled connections after conversation drains. Foreground ends the task and resumes workspaces that recorded foreground-resume intent. |
| 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. |
Desktop termination is idempotent: `AppModel.shutdownForTermination()` stops conversation runs, window workspaces, metrics, forwarding and other app services; it waits for Assistant/MCP and SFTP drains before closing background commands and the Agent pool. `AppDelegate` asks about pending edited-file uploads before starting cleanup, then replies to macOS when it completes or after the three-second fallback; `applicationWillTerminate` invokes the same shutdown path. No live workspace transport is reconstructed by native scene restoration.
Desktop termination is idempotent: `AppModel.shutdownForTermination()` stops conversation runs, window workspaces, metrics, forwarding and other app services; it waits for Assistant/MCP and SFTP drains before closing background commands and the Agent pool. `AppDelegate` rechecks pending edited-file uploads and can cancel quit before starting cleanup, then replies to macOS when it completes or after the three-second fallback; `applicationWillTerminate` invokes the same shutdown path. Closing the last window does not necessarily quit: the metrics menu setting or running metrics can keep the app and its app-owned Agent services alive. No live workspace transport is reconstructed by native scene restoration.
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.
@@ -233,13 +244,13 @@ stateDiagram-v2
prepared --> opening: connect
opening --> waitingTrust: unknown key
opening --> waitingCredentials: local or server challenge
waitingTrust --> opening: accept and retry attempt
waitingTrust --> opening: approve current handshake
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
authenticated --> retired: owner teardown or background expiry
waitingTrust --> retired: reject or disconnect
waitingCredentials --> retired: cancel or disconnect
failed --> opening: explicit retry
@@ -259,7 +270,7 @@ When changing connection code, preserve these boundaries:
- 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. Do not tie the Agent pool's life to a workspace, window, or Assistant turn.
- When changing Agent authentication, preserve the separation between temporary per-opening secrets and reusable route-fingerprinted transports; cancel the final prompt waiter, close late opens, and never replay a command after its channel started.
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. `AgentHostAuthenticationTests` exercise proxy and passphrase prompting, shared exec/SFTP opens, prompt-waiter cancellation, host-key decisions, stale generation failures, post-success secret consumption, and non-replayed SFTP failures. For mobile expiration, inspect `MobileBackgroundController`'s lease behavior as well: expiration calls cancellation synchronously, retires a valid UIKit task exactly once, and treats a failed or synchronous `beginBackgroundTask` as expiration rather than leaving work assumed protected.
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. `AgentHostAuthenticationTests` exercise proxy username retention with a missing password identity, password-plus-protected-key passphrase merging, shared exec/SFTP opens, prompt-waiter cancellation, host-key decisions, stale generation failures, post-success secret consumption, and non-replayed SFTP failures. For mobile expiration, inspect `MobileBackgroundController`'s lease behavior as well: expiration calls cancellation synchronously, retires a valid UIKit task exactly once, and treats a failed or synchronous `beginBackgroundTask` as expiration rather than leaving work assumed protected.
## Related pages