From 2b78eccec40d107b0134c811e752fb6597e08f01 Mon Sep 17 00:00:00 2001 From: Kaede Akino Date: Wed, 23 Sep 2026 20:00:20 +0800 Subject: [PATCH] update wiki --- openwiki/.claims/architecture/desktop-ui.json | 296 +++++++++++- .../architecture/engineering-invariants.json | 320 +++++++++++-- openwiki/.claims/architecture/mobile-ui.json | 290 +++++++++++- openwiki/.claims/architecture/module-map.json | 154 ++++++- .../architecture/native-app-directories.json | 256 ++++++++++- .../architecture/platform-runtime.json | 254 ++++++++++- .../shared-module-directories.json | 222 ++++++++- .../supporting-system-directories.json | 86 +++- .../architecture/system-boundaries.json | 104 ++++- .../concepts/agent-runtime-and-assistant.json | 430 +++++++++++------- ...rce-localization-and-product-surfaces.json | 256 ++++++++++- .../concepts/persistence-and-secrets.json | 172 ++++++- .../.claims/concepts/shell-integration.json | 120 ++++- .../ssh-multiplexing-and-scheduling.json | 142 +++++- .../concepts/ui-design-principles.json | 362 +++++++++++++-- .../integrations/mcp-server-and-bridge.json | 32 +- .../operations/build-test-and-release.json | 96 +++- openwiki/.claims/quickstart.json | 106 ++++- .../behavioral-boundaries-and-fixtures.json | 158 ++++++- .../sftp-transfer-and-external-edit.json | 166 ++++++- .../workflows/ssh-session-lifecycle.json | 152 ++++++- openwiki/.last-update.json | 6 +- openwiki/.page-manifest.json | 252 +++++----- openwiki/architecture/desktop-ui.md | 83 +++- .../architecture/engineering-invariants.md | 129 +++++- openwiki/architecture/index.md | 6 +- openwiki/architecture/mobile-ui.md | 73 ++- openwiki/architecture/module-map.md | 32 +- .../architecture/native-app-directories.md | 108 ++++- openwiki/architecture/platform-runtime.md | 68 ++- .../architecture/shared-module-directories.md | 75 ++- .../supporting-system-directories.md | 24 +- openwiki/architecture/system-boundaries.md | 57 +-- .../concepts/agent-runtime-and-assistant.md | 75 ++- ...merce-localization-and-product-surfaces.md | 46 +- openwiki/concepts/index.md | 2 +- openwiki/concepts/persistence-and-secrets.md | 43 +- openwiki/concepts/shell-integration.md | 47 +- .../ssh-multiplexing-and-scheduling.md | 45 +- openwiki/concepts/ui-design-principles.md | 103 ++++- openwiki/index.md | 2 +- openwiki/integrations/index.md | 2 +- .../integrations/mcp-server-and-bridge.md | 47 +- openwiki/operations/build-test-and-release.md | 59 ++- openwiki/operations/index.md | 2 +- openwiki/quickstart.md | 106 ++--- .../behavioral-boundaries-and-fixtures.md | 41 +- openwiki/workflows/index.md | 2 +- .../sftp-transfer-and-external-edit.md | 76 +++- openwiki/workflows/ssh-session-lifecycle.md | 75 ++- 50 files changed, 5034 insertions(+), 826 deletions(-) diff --git a/openwiki/.claims/architecture/desktop-ui.json b/openwiki/.claims/architecture/desktop-ui.json index 13b73a12..51c5bad8 100644 --- a/openwiki/.claims/architecture/desktop-ui.json +++ b/openwiki/.claims/architecture/desktop-ui.json @@ -1,18 +1,22 @@ { "schemaVersion": 1, - "pageVersion": "sha256:f63ee68a44535a16e3e9c2cbce555c36e71ccd6c531a5f2be1ba12c409df160e", + "pageVersion": "sha256:b9ac495e361094b701333dbc6741fb9eb235201a3428a88baa539e85b899368f", "claims": [ { "id": "claim_5a53c5a47b7445f7a7b6f8865297a805", - "statement": "TFM shares AppModel across main windows but creates per-window WindowModel state; RootView supplies that model through the environment and focused scene values, while external authentication uses a separate scene removed from ordinary scene-opening commands.", + "statement": "TermindApp shares its AppModel and persistence container across main WindowGroup scenes, constructing a fresh WindowModel per ordinary/restored scene (or a demo-configured model for a debug screenshot launch without a request ID); RootView holds the model in @State and provides it to environment and focused scene commands, while the external-authentication Window is excluded from ordinary scene-opening commands.", "evidence": [ { - "resource": "repo://TFM/App/RootView.swift#L189-L212", - "version": "repo-lines-v1:sha256:d71f166db375946ef90321a74b2b3943f9137b43d68003f6991b1c9c56dbc5e9:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBmNTg3OGE2YmZmYTQ4OTg5M2U1ZDljYjAzNjU1Y2QyMzBkNTNjODI1MzNlNmM1MzllNjcyMzVjN2ZhOTQ3NDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3NzRiNTdmMDI4YzVkNTlhYTZiNWJjMzJhN2Y3ODhiY2NlZTk3Y2QzYzRmNGJmZjJlNjRmNjI0MjVlMGYwYWYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQwODBmODZmZDI2OGM5MDgyMDQzM2EwYTU1Zjk5MWFhM2M3NWMyZmRmNjc0NTRkYzA0MDgwNzUwNjk0ZjM2MzkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVmZjY1OGMwNzA0YjlkODZkZWVjOTc1M2EyODI3YWM3YzJlYTE5ZmRjMGQwYWU5ZDBiM2YyMzdmMzZhN2M5ZWIifQ" + "resource": "repo://TFM/App/RootView.swift#L12-L27", + "version": "repo-lines-v1:sha256:83688e26829f58520c3a1708b0dba404afc769843fb45588034eaa933bd07381:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI0YTU0NzRjYTQyZGYyYjU5YWQ4MzRlZTEzYjFiNTczYTlhNzkxOWM1ODg1NDZjOTg4MWI5Nzc5MWMwZTliODEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ4ZjE0OGYxNWFlNTBkMmE3MjZlMGRhYmNhMWI2NWQ0NzVmNTYyYmI5YTlmZWMxZmVjMWEzM2EyYzdjZDIwYjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZkMjk5MDMyMTk5YjM3NTAwZDdiYmRhMTQ4OGI1N2YyNmFjYzUyYjgwZTA1MmQ2MzAzNmZkNmRiZGIyNzMyN2IifQ" }, { - "resource": "repo://TFM/App/TermindApp.swift#L150-L194", - "version": "repo-lines-v1:sha256:00c8269a3e30e0a6c21609b9611182d7db6ea597b5034e06084b9777a951d26b:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcwMWZjNjEwMWEwZjJiMGNiNmFkNTEyYzg2MzExYzEyNzllM2VlZjMwNWExMDQwMTc5MzUzMTQ4N2MxYTllNDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY2YzczNjhlYWI2MWJhOGIxYWJlYTEwZmIxMTE3OTIzZjk5ODA2NjU4ZDFiNjcyODkyMjU5ODAxOTIxYWI0N2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIwZTJhYTI2ZTg3N2YxZWE5MzA4NjE5NmU0Nzg2N2U5MGYzNTk4ODI2MDA0MmY2YTM1YzEzZTlkNDRlOTVhM2MifQ" + "resource": "repo://TFM/App/RootView.swift#L190-L209", + "version": "repo-lines-v1:sha256:f02230c1b5e2bf5f434b78334c147ac1c4d41d0886ec8c79fb3019e4d3ebeac2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBhZDFjODhkMzAwYTM1MWU4M2RhYTc0YzdkYmQ4NmNlMDk1NDNjYWM4YWNlOWE3OWNkZWE2NTA4YjAxNTc5MTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyN2Y2Nzg2ODRlNDYxODQyZThlMDcwNTdiNmFlMDg2N2NkYmEyMjkwZGViM2VkODk1YzIwNTAxNDZkMDhhYTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI4MGZkOThlZTkwNGMwZjRjZmRlN2EzZGNlOWQ3NDNiMzExOTAzMzhkNzFkMWRiMTdhMTg4NzlhM2QxMGFmYzIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlMzE1MGI0MzY3YWExZTg4ZDZlOTQxNmMzZGQ4NDRlOTc3MmMzMjhiNTljMjY3NjdmZGRkNDA4MGUwNjUwMWMifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L168-L212", + "version": "repo-lines-v1:sha256:eb20fcc10fa3cc0f5740fa0fbbf0746859c1e4b7b431188ee4e3672fc48bae73:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxMDk3ZDRjZTdkZDAyOWU5OGI2YWFkMjViMDFiYzEzNzhjOTdlMzA5YmRjMDY0YTM0ZTI2NTQ4MTFmMTgxYWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQwMmQ5OGU3M2M3ZmQxZDQ4ZjUzNjdjZmY5NGFlNGYzNDlhZTYzZmIyMWRiYzkwZmYxYjZhNDViYjNmOWQ5MzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjZGEyMmE4ZWYyODNjOGFmOTJjZDlmMmY2ZTA4MzdkODg4MjdjYjBkZGM2OWNlNDFkMTAwZDFiOTdjYWM5MmMifQ" } ] }, @@ -247,10 +251,288 @@ "version": "repo-lines-v1:sha256:7196e06e9dc8a27ab84f9e882ab334752ea92d105ede6662f4caa406f3348cb3:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBiZTY3NWZhODQwMDAyZjE2ODExNjhkODFkMWNhMTJjNDIzMmFjMzY2YzdjYTU1NThlNWNmOWUwMDVmOTQyY2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMzZmY0MjE3Yjc1YmQwYzMwZWVhZjlhN2NlMDczZTA3NWVmZTZlMWY2NWRhNzZkMzAzMmFmNmQ5Y2RhOGE4MDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYxY2U4ZjAyY2Y0NzE4ZTA4OTNkNzFlNTJmNzc1YjM2NDQ5OGJhMWYwNjkwMWQxOWE1MWE2NzllYmU2ZGFkYjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ" } ] + }, + { + "id": "claim_ece35ff164264d62aba803284a87b7b5", + "statement": "MainWindowCoordinator requests a UUID-valued main scene for moving a workspace and leaves the live workspace in the source until the native destination registers; registration takes and opens the same workspace in the destination model rather than closing and reopening its session.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L1333-L1347", + "version": "repo-lines-v1:sha256:da353e4f93aafdf617967c1f193fac28aa52e7c78a72a9496406e7cb28643add:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg1MGRmNGNiMDJlZjZmZmY0MGVjMDk1Y2RjMWRmZDQ0ODZhZmVkMTNkMWZlNTkyMTgwMzQ0NzUyMzBjNTk4Y2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA1YTkyZGE1ZDMxNjBmNGNhM2UxYTgxNzkxMzgwZGRmZWZjNzU0ZjQ0Mjg5YmNiYWMyZGI3MDczNzYwOGE1YjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFhNmQ4OWYyNDA1OGY0ZWVmNzExNzA4ZTc4ZTBkOTllZjZhY2RmM2RhYzVlZjJiYzdiYTcyMTlhZTk1NWQ1YTkifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L613-L618", + "version": "repo-lines-v1:sha256:eb93dac75da2ca026ed325b2ea360204f635a2f0bb96579dba65983ee5e01498:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTkwOWE1M2E2MThkMDI4ZTFkMzAwMGMwYTdhYmNlZWNiZTVmYjM3ZjRlNTExZWZlNDY2NDNmYWQ2ZTY2ODcyZiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzNiYjU5YTQ4ZDg3NjhlYjVmNWQ3ZTNiNTNiYTIzYjQ0OGQyMmUzNzNlMzNhMjViNWJmZjkzNjFhYTEzNDdhOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNGM0MmEwYTUwZjc0MWMxYmE3MDEzNDMyMzMwNzc1Njg3NDI1ODRlMTM4M2RmMWRjOGJlOGE4NjAyMGFjNGY5ZSJ9" + }, + { + "resource": "repo://TFM/Platform/MainWindowCoordinator.swift#L139-L197", + "version": "repo-lines-v1:sha256:19cdd2415ed0718be3cd7bddebdd4730f6e57c91d93dc56c7b0c5058e42236e8:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmNGVkYjE4NDBiNmE1NzQzNDljYjhiNGEyYTJjMGY3YTk1YjAwYzg1NDhiZDAxZDgwNjdhMjc0OGQwYjA5ZjQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgwODZmMjNhZmUyY2EzNDFlNmMxYzg0NmU5ZjVmMzk0Y2NlM2M2ZmU5OTcyMWRmNDU4MTEzNGE3OGIzNjRjOTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxZmMzMjQyOTY2NzdmNGE4OTRiNjM4ZWZmY2FkZDZmN2E2NzliODgzZjgyMGE3M2JlMTU3NzI4OWJjMDZkNGQifQ" + } + ] + }, + { + "id": "claim_f99fef09ac6c48ec820b02ce599f7871", + "statement": "Closing a registered main window unregisters its model and calls closeForWindow, which disconnects all workspaces and clears window-local reopen, drag, route and transcript cache state; a restored window without a pending request retains its system-restored frame.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L1349-L1364", + "version": "repo-lines-v1:sha256:71e9406f9869f56eb1c521ba6e327418432191e53cefdd968517dc3a0ee96204:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJjYWZjOTA3ODNhMmViZGYxZTVkMjA5ZWNiYTI5M2M2NWI5ZDBmYTY2ZmJjN2Y4M2VjM2M5YzJkNTVhMjUxNTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4NDg1NDZhYzY0MDljOTA2MmY1NmFhOTZjMjljMWMyZmJhMGQ0YmQ4NTZlOTkyOGNhZjgxNTcyNzk3NmRiNzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM2NTBhY2EyZjc3OGM3NDg3MGNiYTI2ODljZjFiODcwYWJjMmJhNGEyY2FkMDMzMzA5ZWQxNDk3ZWRiYTlhNGIifQ" + }, + { + "resource": "repo://TFM/Platform/MainWindowCoordinator.swift#L172-L197", + "version": "repo-lines-v1:sha256:89bd46b74788f6d720daaf656e778418e93cfc731a73cf27d8eb030e7d10a710:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVkMWQzZDYzMmM5MThkZmFiYzJkZmViZTQ0MmMxM2I3MDA2YTgxNzlmZjg5MDYyNDk5ZjBmZTMzNzRjYjFkZjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmNGVkYjE4NDBiNmE1NzQzNDljYjhiNGEyYTJjMGY3YTk1YjAwYzg1NDhiZDAxZDgwNjdhMjc0OGQwYjA5ZjQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMxNTFjMDIzNTg2OTk0MDFhZDg1ZTkxZjZjNGU1YWQzYWU3ZmU5NGE3YWNjOTc0YTg5MTQ4MzZlNzIzZDg3NDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxZmMzMjQyOTY2NzdmNGE4OTRiNjM4ZWZmY2FkZDZmN2E2NzliODgzZjgyMGE3M2JlMTU3NzI4OWJjMDZkNGQifQ" + }, + { + "resource": "repo://TFM/Platform/MainWindowCoordinator.swift#L232-L245", + "version": "repo-lines-v1:sha256:140731d265cec1f8c14e8955120f658c7f65e3f6fbc81de28c53187c387b21c1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg4MDA1ZTViMzQxMjg0NzIxNTA5NTE0ODRlN2VkYmNmNjhlYTUyYWE2NDkzYjAyMTdjYjA3OGZmOTdiNTllMDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM5ZjMyZjFiMjI2NTNjYTE3MDYzYTU4ODk0NTVkODQyODUyZDQwYjE1MDllZWQzOGE1YjI1YjBhMWJjNjE2YTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU1NGZlOWE1ZDY4ZmYzY2I3MWYwYjhmYzIxNmYwY2JlM2FjNjM2OThkYzkwOTZlOGI2YTA2NDgxMzJmOTQ0OTIifQ" + } + ] + }, + { + "id": "claim_66ad144a860c45d8b63e1ec8111e8dca", + "statement": "The Navigator's workspace inline rename starts with the full localized displayed title before the native field receives focus; commits delegate to WindowModel, which rejects unrenameable workspaces, trims names and stores split-workspace names on the group but single-pane names on the pane.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L1473-L1503", + "version": "repo-lines-v1:sha256:94d3d9aeab1a6c1adeb0bd781287fd4fc7d23300fd29af1bc8c061b11cf8ffc2:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI5ZWZlY2QzYTViODY5ZmZmYTZlMWZjODg1MTVjNzEwZjhiZTUwMGUxMTkwMzIyNTZmZjczMzdhMjgyMDU4MjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYwNWZlM2RmMTc2NjQ1NjYxYjk3MjBiMWFiMGM2OTgxOTJhN2IyOGRkNjJiMzA4OTA3NWVlNmViZjRjYzgyMzYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxY2VhN2JlYmU0Y2RkYzcxYWViY2NjZWNhYmFlOTRkZGM5NWYyMmY3NGVlZTYxMWIwMmNiNWUyYjJiZjg3NjgifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L337-L353", + "version": "repo-lines-v1:sha256:2a55777bcb0eec1c64042a775fbf26aa722956873948a19184682013f935954c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjYjRjMjQzNTM4YzI0ZmNjNGJlMmE2NGU3ZDEwYjc5MDZiODhlMjU5YjZjZmFhOWQyYTU2ZDFhN2Y5OGFmN2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk1MzI4MjRjNjkxYjc3YTQ1MDdhMjQ4ZDZlZjIzYzI0ZDc0ZGQyMDQ0NGEwNjc3NzgyN2E3MTU5Yzc2YWY1ZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBmYzVkOGVjN2Q1M2E5MTkzMzI1NjYzZGMwZTdjYmZiZDgzZTg3ZGY3N2UxYzk2NmI2NjU3ZmU2NTc4NDBlMGQifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L447-L455", + "version": "repo-lines-v1:sha256:9c46af93272d913c6a3a16e546e146a9242243a366ac0e48331482a97980e882:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNzZiZDExNjdmMmYzY2UwNTZmZDZmODc5YWIxMzMyNGI0Zjk4Nzc4M2RmOWJlY2Q5NGMwNDFiYjAwYzRjZmI5NCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYWY3MTQ0MTIwY2EwZWVkMzE0ZjA3NTIwODc4M2FjYWM1YjI3ODg3YmM3ZTEwYTE0MDNkMjlkYjExNzhmZGI5YyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMjYxY2Q4YzNiN2MxMWZiNmJkMjQyYTJhZTU0OTczOTI4NjBiODliY2MwOWJhYTdjZmJkNzc2Mzk0OGExMTY0OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMmI4YjBjNzlhOWNjYjEzZGEyYWI0ZGYyMmM4MjAzZTg3ZGMzNTNlOWVhYWMwYmIxOGI3ZDRhYzRlYmExODgxMSJ9" + }, + { + "resource": "repo://TFMTests/WorkspaceNavigatorRenameTests.swift#L89-L97", + "version": "repo-lines-v1:sha256:0fc39b77342c244e81470d358a1d67076f1f743003c383f218be0a3009aca381:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNGY4NjM4NTcwMzRlYzU0MTVmY2I3YzliMmM5ZDA4MzIwNjMyZjlhZjU5ODkwNjE0Mjc4Y2I5OTYyMzYwMWJhNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWFkMTU4MDNlYzMxYTU4ZTBkYmNmYTkzM2Y0ZGMyYzhlOTk5NmE5NDBhMTJkZDMxNWU1OTY1YmIzODJmOTI4YyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMzFjZWVjOWU1YmYzNGM0YzllNDljN2FiMzI0ODE0ODY4NTkxNGU4NWRiZjkzODIyMGY2YTMzN2U3N2FhOTQ0ZSJ9" + }, + { + "resource": "repo://TFMTests/WorkspaceNavigatorRenameTests.swift#L9-L32", + "version": "repo-lines-v1:sha256:cfbdccc4f0bd874f1bf5c03e0fe623bde5aadbc9aab80a5866685fa3e6ac2950:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU1Y2RiZGUzMzQyNDE0YzU2NjcyYTRmZjdlMDNmYjZkMmI4OTMzNjY1ODVhOGI2MGFjMTkyYjg5NDNhNjJlMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1NTJjOTcxMTBhMDM1ZjNkYjQ2MWIzM2VjZmQ1MzAwNzk5ODMxZWJlYjdlMmEzOThkMzJiY2ZmNTJlYjFlNWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ" + } + ] + }, + { + "id": "claim_4626c7d1805f4915acea9613715e344b", + "statement": "The Navigator overlays an AppKit-compatible workspace layout drop receiver above native List rows; it uses live window drag state and measured row frames to preview insertion, excluding the dragged workspace when calculating its mutation index, then reorders a workspace or detaches a pane only on a valid drop in Navigator mode.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L1154-L1166", + "version": "repo-lines-v1:sha256:9998c91d1d7004b0a89c1479e7e6be4e31c461f493bcfda14a15209746173e14:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYThhM2ExNzBiOWM2OWY1YmQ5NzQ5ZjA2MGYzODIwNTg0YmYxYWMzM2U0ODBlYzVkYTMzYzBmMzlmZmIzNGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0NDA0M2I2YTFjZjU1MzZhY2ExYjViMjg5NWY1ZWFiODUwYjg4NGU3YmJmYzBkNWMyZmViNzg2NDA4NzBiNjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlM2QzMjBjMjliMDA2NGVmN2U3NjA3NjY4N2RhNDhiZWZhZmE2YjdjOWY0ODRlYTc3MThkMjZjYTY5MTU4OTMifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L1460-L1471", + "version": "repo-lines-v1:sha256:6d208ced125d8ee92bede8c6cc1fc9d2e3a783390f397b9597820cb59d3e76e3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM1N2I3NDQ5YTRiYWMxMDJhNzc1ZDBmZDdhZTU4YTYyMGEwZmFmZGU1NTNlZDYyYjgzMTA5ZjQwMjNiZGYxYjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM2M2RiZDZjMDhiMTJhMTEzYTVjYzUyYTg2MmI4NzA4ZjVlZmI2ZmRhMWM1NTU2MzQ2MTBiMTBmOWM0NjI4MzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMwMGE5YjAwNjFiMzcxYjRmMzJiZThhYzI2NTQwNTJhMDI5NWZhYmM0MDgwNDk5ZDUwOGVhNjE4ZmFkNmUyNzkifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L215-L300", + "version": "repo-lines-v1:sha256:a093210dd716e3f4a599c63bbbf234847585ca0d26b8012f6c859beca609a506:eyJzZWxlY3RlZExpbmVDb3VudCI6ODYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU0NThmMzc1OWM3ZDY1YmMzZGE3ZDY1Y2I2NDc1ZGMxOTY2ZGE5N2YyYWMzYmQwMWU0MGIwNDhlMDFkMGRkZTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcwYzY4Yzg0YzZjNjNlMDQwY2E4NzRiMzkxN2JkMWQwNDY4ZTllMmU2NmNkYjNiZTZjZTBmMTEyYjlmZTc4MGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzNzVhMzVjMjgxM2Y4ZjgyY2JkYjQyMTdiOTZiZjdhYTJhM2RmNGMxMDMzMmY0NGM4YTkzMzJiZDY1YTk0N2UifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L23-L65", + "version": "repo-lines-v1:sha256:a7cbc6b0b6121f16bdecef2e8a1dcf8e3e91b079155aa73c3cb9c35e62024017:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNjYTMxYWJhNjZmMjJkMGM4YWViMDU5NDRjMzczMGI5M2NkNWE0NmJkNDU0NDBjZjI2OTU4ZTNjNzZhZTA5ZTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ0NGE3ZGE5ZWRkYjJiN2I0YjhkMGQ2NzZjNmI4ZDhjYjY1NjY2NmYzMmQ5MTZhMzU4ZDIwNTI1MTE2NDdlOTIifQ" + }, + { + "resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L210-L302", + "version": "repo-lines-v1:sha256:2b121eae49ca13c02687dcaa64b06609d3d014e1cc8db3514211dc6736ac99fa:eyJzZWxlY3RlZExpbmVDb3VudCI6OTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4ZmRiMWE0ZmJiNDNlODMyMWI3MmU0Y2Y1ZmI2MDViMzJjMGRhMDlmMDVjZjQ2NjRkOTk1ZWFhYWZmZjk3YjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmOWIwMzZlYTA1M2VjNTc3Mzg3MTM0NTM5YTAwNzQ3NWQ1NGE3MDgxZmQ3YTE3NGMxZTQ2MTljMGUwZmJiYWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM4NmI0NDc2YjRiY2U3YmU2YWFkOWRjZmNiMTEwMjZhNzY0OTQ3YmRmNGRjNzQ2NDk1ZmVjNDAyYjc4MDA4M2QifQ" + } + ] + }, + { + "id": "claim_a213393c73a04dfea82e7ee735e13d64", + "statement": "Workspace row drag state starts on macOS 26 only after the native List drag session becomes active, while older systems set it in onDrag; the model documents that an older release outside a destination can leave stale drag state until the next click/drag, so drop callbacks validate the pasteboard.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L131-L145", + "version": "repo-lines-v1:sha256:7c21e825ccb2d46d9b62ee16ebe2cc629c93733f11bb55257c09a2f6756bdec2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM1ODBhMGJjZjE3MGMxZTQzZmMyNTRiNzM5NDg1NmM5OWEzZGU5Zjk5Yjc2MTk5ODg0OTkwZTQ3YzEwYTM2NDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI2NzNmZjY5MjI3ODQ1M2RlYzI5MjcwMTAzMjM2NTRlZmY2ZGU1YzhiYjMzYzViYjc3YTcyOTZlMDk5MTVkNzkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzNmIyNjExNDViNTdjMmU0MjkzYjE2NDc2ZDQ5NzUxYWZhNjA0NzY4NjZkMThmMjYwNDY1ZGM2NGJhYmU5MmQifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L157-L175", + "version": "repo-lines-v1:sha256:64b52e8954a04de9a1f8e0e74ada88979d7a519013d4c1b104520480e097283c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiZmVmODg3ZmEzNjEwYjA4MDVkN2ZiNTA5Yjk0MjU5OGQ1ZDgyOGU5YmNhMTlhNjM0OWJiMDU4NzcwMzhhOTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhkYjMzOWMxN2Q0Y2M1NGU3MGM0ZmNmZWNiNjExYmI5ZTdkMzYzZjI1YjE4ZTA5MjNhMWQzMDZjYzk1OTI0ZTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ3YjlkM2E0MTIxZDAxNmY0NGIwZjBlMDY2NWFkMWQ3NzdjZTE3YzY3NmQ0YTM5MGRjOGI2MjVjMzM2MmRjNzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUyNDNkZjE5YzRkMGYyNGY0YjlmOTA5ODRkNTA5ODJkYzlmYzgxNzIwYWVhZjRmMzc5OWQzYzFhMDcwMThjYzUifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L357-L387", + "version": "repo-lines-v1:sha256:2b8da7491c350234c98084e27a32d120cc153957d6946872efc8e23e62b304d1:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiNTZlNzgzZGJiOTljZmRjNzEzYmEyZjlhMDkzZmQ0NTA0MDIxMTAxNDY2NzUyOGYzNzA3M2RmNDcxNWQxYWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmYzVkOGVjN2Q1M2E5MTkzMzI1NjYzZGMwZTdjYmZiZDgzZTg3ZGY3N2UxYzk2NmI2NjU3ZmU2NTc4NDBlMGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcwZjQyODcxNDFiZDhjZDQ2MmRjMGRhNzYwYzVjNTU4YzA4MGY4NjUwMTIzMTYxNGNlZWY5YjY4NTExYWU1YjkifQ" + }, + { + "resource": "repo://TFMTests/WorkspaceNavigatorDropTests.swift#L179-L208", + "version": "repo-lines-v1:sha256:0dfd53e2ba4742839ddb69d18d0dd3fb0d653757790284ecc2e96156f85c50f1:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ2MDMxMWIwZmM3ODkxY2Y3ZDVlNTY4ZDAxNzkzMDNlN2RmNjU3NTUwMmNlYWI3NzZlYjcxNTVjMjU4MTQ2YzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImViYWQyMmE0ZDU0ZmE4YmRiYjBjMTVjMTRlYjliYzdjM2IyZmZjODk0ZGEyZDg0OTlmYzIxZjBkMmIyZTc0ZGUifQ" + } + ] + }, + { + "id": "claim_4f3942ad7e0c48f7b513905bae30f802", + "statement": "Workspace Navigator expansion is a persisted presentation preference, independently of workspace ownership: selecting a Vault or workspace destination expands its section, and its row menu routes selection-sensitive pane actions through the window model.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L13-L21", + "version": "repo-lines-v1:sha256:0119f0738039c9a8de6bbd2fa113f0fae4f84a64d939206fbf56218631307858:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzM4ZDdjNzcyZTllNTA3YmFmZWQwYWNmMzk2NDlkMWUwNTAwNDdmNTdhYzZkYmI1NTE4ZDE5NGQ1ODljMWM0MiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDc3MDVlMWM0NjRjMDRmZDdjOGE0NTIxNTliNWUwMmMyMWNmYTRiMzI2OWQ4NzEwMTMxNTdmYTczZTU2MjkxNiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZGFkODQ0MzM5M2NhNjA2ZTFjNzRmZjhkNmUzOTRiMzhhNTVhNDAyYTk4NmE3N2I5ZjIxOTI4NWVlODBlYTc1ZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiODY5MTY4NmU1YmZjN2I1ZDg1NmI3NzAxM2Y2OTM1ZTA0YTJhN2EyYjU0NGY0NDcxMWJiNDA0YTEwNmVjYjgzMiJ9" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L521-L653", + "version": "repo-lines-v1:sha256:4b8c972e35e30d61882503efd4fb3130fb6fe606f8e72bf1f032227e07f44e12:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMzLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI4NTU1YzkxODExYmNmMGVlNjEyY2IyODI5ZDA4NTZmZjBlNTg4MzY5ZjM2NDFiM2Q2MTNiMGNkNDhlYjEzNzU2IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MSwiZm9sbG93aW5nQ29udGV4dEhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIn0" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L59-L67", + "version": "repo-lines-v1:sha256:f207ff2c8d5cfa18b88454ff571f6b743e835306445fd638cce7420dc2396dc3:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzU2NDUyNDhkODhiZGJlZDQyN2M2NGE1ZmEyMjFlNWI1YzcyOGFhYjA1NGJkOTMxMjI3MGQxMzc0Y2M4YmU3NyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNmMxM2E0NjEwM2VlMTJjNjQyMWZmMTEzYzVmMmVjOGQ3N2U5ZjA0NTVkZWYyODY4N2NjNzQzYTZkMTYxMzk0MyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNmUxYzM0ZjM2ZTliZWZlNmYzNTFkNTBjOWMzNzM4NDA3ZTk5YWUyNzYxYzRkZTc0ODBhOTFjY2U2YWM1NGUzZSJ9" + } + ] + }, + { + "id": "claim_f97512492f084fc79a3cb6957f1b47e8", + "statement": "The Snippets sidebar filters shared host-library snippets with a sidebar-local footer and can insert into a live focused SSH/Telnet terminal; executing a risk-classified snippet requires an additional confirmation. Its persisted package-folding state is distinct from the full Snippets page's expansion.", + "evidence": [ + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L197-L255", + "version": "repo-lines-v1:sha256:76b9b922cfec03a2fef27dcb44e80e758ee095eee0272311fe5fef4cbe41333c:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjczNzBhNmFmYzRjYjI5NGJlNWI4NTlhNTU3NGRhNDhkNGIyYzhmOTY3ZWI3NWNmYjE5ZjIyODYwNjA0MTdmMDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMyOGZhNTE0NGY3YjJhNDE3MjUzZTlmMTRlZDE3OTliYzliOTA4MGJkNDExNGU3OWViMjI2YmE0NmNjYTViNTcifQ" + }, + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L520-L693", + "version": "repo-lines-v1:sha256:7b0b4141e0cdfc83f2251f8e4e95ac566375022b9a5492a3c1f4ac360e638f09:eyJzZWxlY3RlZExpbmVDb3VudCI6MTc0LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJiNzE3YWY2MGVlZTU5YTJhOGJjMWE4N2RkNzlkMDM5ZmI4YjQzZGQ3Y2Q4YmJiYzVmM2IxODFmNDZlMDkwNjRmIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIwOWRkNGI3YjQ0YTg4NjQwZmVhYmIwMjk5NGFjYTg4ODM5ZDc2NmQ1M2JjYmJmZjQwNzQ0MTBjMDFiNTk1YjgzIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI0YmExNzE1ZTAyNDdiMmYxNzZkYzY1MTM5ZDFkNDQ5YWIwZmJmYzg0OTE0ZGVkZGViNDQ3NTczZTA1YzUwNmFiIn0" + } + ] + }, + { + "id": "claim_68e57ce6fc234414ae96c13d09756d0f", + "statement": "The History sidebar projects SSH command history, SFTP browse history, or connection history according to the selected workspace's focused pane, while Snippets and History use AppKit ListViewKit-backed rows with separate footer search and blank-area menus rather than changing the titlebar Find target.", + "evidence": [ + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L309-L431", + "version": "repo-lines-v1:sha256:d845dfbd8a915f9f2789556b59bd3df536b4ff664b82c9da52b26da1051a34d5:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIzLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIxNjhjMmU4N2Q4ZTEyMTA1YjZkNTFmZjdjMmQxNjUxYWFkZDcwMjY1ODIwNmQwZmUxMzNkZjM0ZDM1OWQ4ODY1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIxOWU3NjM1NWNmMTE5OTQ4MGMzZjk5ODM2YjE0ODZjODQxZDg5MWZhYWQ5MDRjNjA4ZTA5MzAyMmQzNzU3YWVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIyMjFhMzQ0MWM2MThlYTk1NWEzMjVhMmViNGFhMjEzNjk5Njg5MWJjMmI4YmM2M2M1MWEwYzliMDIwZWUwYTQyIn0" + }, + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L533-L567", + "version": "repo-lines-v1:sha256:ec0c5c55c65e3900b48f42d3a12737f488e6a620498034a28bf46b4d47d02a5f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg1NGE5NjIzNGFlNWVhYWRjNjkyMTlkOTQ2NzYxODI0MWRhZGRkMTgzZTdjMjM1ZDk4MzU4YTRmNDE0YjViMzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlOGQxZDVlNjk5YzI0ZjNhZTk0Yjk2MzZhZTk1MzE0Njc3Njc4Mjk1ZjQ0YTUxYmExNmZjMDhmNGE3MTViNjQifQ" + }, + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L768-L779", + "version": "repo-lines-v1:sha256:5d4ca3aa9b8065880638441e6fde5ad930ed84cd12cd2c2846958e5f3e54aabb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjNzI4NzFlZDg1YWRiY2U3NDE3ZWU4NzNmNDNkMDNhN2Y2MmE0N2ZlYjQ1YTgwODhkZDUzMGY0NTUxYTU0YjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkZGIxYmZhZGQ3YzM1MmU3NTYyYTQ2Y2Q0YjRlYTQzZGVhMjM0NWI4M2ZjM2YyZmM5MTU0OTY2MTNiM2JjYmIifQ" + }, + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L819-L867", + "version": "repo-lines-v1:sha256:499b81e496685ef41d3631bd61ea31504805447a4faf163e7dc65e259e66d8d0:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVhYzZkNDA4ZjA1NDA5NTFkYzZhOTc2MDU3ZTQxNDBmMTZlNDE2YzhmNTg1YzI3ZDYzMTY1YTRlODIxNDI3NGMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzNDhjMDVhZWRjMDRiN2QxYjc3Mjg4NjY2YTJkMDM1MWUyNTUwZDJmYmJjOWUxZmQwOGU5ZGExMzcxNzkxYWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ2YzEwMzVhZjA1NjA0MDliMGE1ZTE5NzE5Y2VmYzg3Nzk3ZDdlMmI4ODE5MDQ3MDBhYTc1YTkwNmRlYmE2ZmYifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L411-L439", + "version": "repo-lines-v1:sha256:eed3ad51297132b5578d6e00015c3c5f253c32323524b6e8f36154ac32cdf779:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg5Zjk5OWM1ZTg1NzJjYWI0ZDEwNGRlNjQ5MmE0OTVkZDA0ZTI2NDliZTUxMjczNTRmNzQzMDBjOTBhY2U1OTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZhOGYxZTlhYjU4NWQ0Zjg3ODkwNDAwZDRiZDJjZWY2MGMzMzhmYzlhNWFiMjQ5YjUwY2E4YTQzOGQ2NzllYzIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE0MmU2OWU3NjA1NDhhNjA2MzNhOWY0ODk3Mjg5N2Q3MDkyZjU4ZTg4Nzg0NTczNWVhMjEzYTI2YjA0MzIwYzgifQ" + } + ] + }, + { + "id": "claim_433e32067700414ebc56d58a3b49fb83", + "statement": "Toolbar creation actions derive from the foreground destination rather than the sidebar mode, while Vault Navigator row menus reuse per-page creation verbs even when that page is not in front.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L106-L125", + "version": "repo-lines-v1:sha256:ec41d820128a79e3ce0a4c46df499dc79b647fcc6731df5b4116d73fcfed6bdd:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI0M2U1ZGEyYzA1YWY5Njk2ZGRhODAyOGVmMzRiOWZmODNkNjY2MTcxNjM0MWJhM2UwYWRjOGNiNmFmODMyODYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhkYjMzOWMxN2Q0Y2M1NGU3MGM0ZmNmZWNiNjExYmI5ZTdkMzYzZjI1YjE4ZTA5MjNhMWQzMDZjYzk1OTI0ZTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZjZThkMTM3ZmE0NGFjNjY0OGIzYTRhNmY1NmY1MGJhYmE2NzczNDE0NWQwNDc0YTRlNTU1Njk3ZmQyNmJlYzgifQ" + }, + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift#L609-L668", + "version": "repo-lines-v1:sha256:19b5e0fa97c2f57e3a66eb966ce5153b68d7c77ffdde088afdc59505248c8538:eyJzZWxlY3RlZExpbmVDb3VudCI6NjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg0MjE4MDk4ZmNmOTI2YzdmZGNkZTk4YzEzZmY0NzliYTUyZmQ3NzAzMzIyZDRhN2ZjM2M0ZGU1OGIyNjlhZDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIxMDcyYmE1MTk1N2I0YTkwYzI2YjA3OWNiNzY1MzBlOTZiMDE3YWQ5MjAzMDI3MTM2Mzk0NDM3OWRmZWEyYmQifQ" + }, + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift#L700-L822", + "version": "repo-lines-v1:sha256:21098cd1daf2b3ea6d24dc402154d342313c63ebcebbb0fda0dfcef895c87666:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIzLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI1YzEwNTMxODk5MjIzNTgwZmVkNDc1NmRlNzM2ZmI1MGQwODRiOGI3N2M5MDMwOTMxZjMxMTFlNTI3NTI5YTZlIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI4ZDMwOWRjNjUwOWZhMjMyNDJmZGU2OWRhODA2NDhjZDFiNWYzOTRmYzU3OGQ2ZDFmMDBkOWJiNDE1ZTkyYWFlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwOTA1ZDdhM2IyNDViOTRhYmQ3NDY1M2RhZWM3MWIxMzI2YWM2ZTRjNjExZDEzNWY1Y2VkZTY3MjA3ZDI1ZTVkIn0" + }, + { + "resource": "repo://TFMTests/WindowToolbarFindTests.swift#L135-L153", + "version": "repo-lines-v1:sha256:7d37b7b61770aa9ea4aca8a2ea0dfc730f96a23a1de5b7d900f224bcbaa7be88:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYxNGE1YjAyY2Y2NDVhNzI1ZTI4MWQ0ODAxMjJjZmQyN2I4YWQ1ZTUzZDQwYjA1ZWFhNGFkZjUwZmYzYzc5NGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE2NWRjNGJlN2Y1ZTg4Zjk2ZjQyYmEwNDIxNTdlNjE3YzU0ZjY1ODlhZGU5Mzg5Mzk0MWFhNWZmMjIzZjhiODcifQ" + } + ] + }, + { + "id": "claim_42920ad7109749758fe31c53f2bff3ac", + "statement": "Window Find routing is chosen by the foreground destination and, within a workspace, its focused pane; page queries belong to their page state, Welcome uses its own content search, and a destination without a searchable target offers no toolbar Find.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L411-L447", + "version": "repo-lines-v1:sha256:56c13d35bdb50725a448abb44f68c1cdc3f54e4a1097299d0aee09dbbc7ab86f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg5Zjk5OWM1ZTg1NzJjYWI0ZDEwNGRlNjQ5MmE0OTVkZDA0ZTI2NDliZTUxMjczNTRmNzQzMDBjOTBhY2U1OTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg4NGYxYzk5MjE0YjlmY2EyMTFhYzcxOTcwZTM1MjYyZWRkZmU3M2JiZmFmYjlmODE0ZWExZjExNzdiNjFhODYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZhOGYxZTlhYjU4NWQ0Zjg3ODkwNDAwZDRiZDJjZWY2MGMzMzhmYzlhNWFiMjQ5YjUwY2E4YTQzOGQ2NzllYzIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiMGQyZjhjNDYyZjViZmU5MjVmM2VjMDU4YjMzODMzMGE1ZjFkNWU4ZTkzZTFmM2E1NDA2MWJkYzk4YjE1NDAifQ" + }, + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift#L824-L907", + "version": "repo-lines-v1:sha256:b2bc5730509ad7850d6d442650f2e527958daa363279c834da520e61a2f1b326:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0ZjViNWJkODA4YmMwZmQ0NmIxMjg3NjU1MzI3MzNkZTc3OTIyNzI3ZTgyZDAwNzYzOGRjNzIzMjA2YzQ1NTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUxY2ViNzRiYzA1Nzg0ZmI3ZDI4ZjU1NzU2NWQyNGU3N2Q4ZDBkMDBiZWZhNDZlNWQ0YTk5YzA1ZTEwMzhhYTkifQ" + }, + { + "resource": "repo://TFMTests/WindowToolbarFindTests.swift#L177-L193", + "version": "repo-lines-v1:sha256:87daeb11634e2605bb7747bb99bdf9db76a22f4ec4f9589471c510f272b5b590:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0NWJhYmQzZmRkOTJmNzkwZjc3MWViOGMwYTQyY2RjYTUzNzQ4ZGNlNTc4NzNlNzQ1OTMzZjUzOTMxMDA4ZWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMwYTI4NDk0MTEzN2NkM2Y0YWY2OWNiYjZmNzBmMmViMmU2OGFjNjIwOWRkODBmNDlkZjUyMGNjYjZiOTJmNzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIwNjg2NzljNDQ3M2NlMjg0OTNiY2EzMmZkOWE1MTQ0ODhhNWE5N2JiYTU5NDcxYjQxYjcxYTA4ZDFhOGRjNDcifQ" + }, + { + "resource": "repo://TFMTests/WindowToolbarFindTests.swift#L27-L104", + "version": "repo-lines-v1:sha256:9141bed7ee8e6a0771dc3c0b9589dec0bcab764b5b9f69d3d1ef939a50a5423c:eyJzZWxlY3RlZExpbmVDb3VudCI6NzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ2ZWEzOWJmZmFhODY5MzJlM2U1NGZmMDAwZmI1NGQzMmRiMDE3MGVkMjVhMmY3Yjg1MDIzMGI2NTU1ZjVmMGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiOWM2MDg4OTIyMzljMDkwNDA1MDYyZmMwOGYxNjE1NDc4MGRmZjM0N2RlOWE5YzVjNmUzOWQ4NzU3MTJmYzEifQ" + } + ] + }, + { + "id": "claim_0211cbb51b0240f99474a49d7381d168", + "statement": "Find commands target the focused window model, which suppresses pane keyboard claims before activating terminal search and focusing the toolbar control; Welcome redirects focus into its content field and unsearchable destinations do nothing. Toolbar focus ownership is released on explicit user exit so panes may reclaim the keyboard.", + "evidence": [ + { + "resource": "repo://TFM/App/TermindCommands.swift#L125-L125", + "version": "repo-lines-v1:sha256:38a484f4ed7c48f24c8ded5e0d28a17aedf0356fbc4137c45ff956fb4906cf93:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzhhNDg0ZjRlZDdjNDhmMjRjOGRlZDVlMGQyOGExN2FlZGYwMzU2ZmJjNDEzN2M0NWZmOTU2ZmI0OTA2Y2Y5MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzhhNDg0ZjRlZDdjNDhmMjRjOGRlZDVlMGQyOGExN2FlZGYwMzU2ZmJjNDEzN2M0NWZmOTU2ZmI0OTA2Y2Y5MyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmVkYjY1NmVhNzNmNDQ0MGY2OTAwNTg3OTM5YmMwNzk4OTQxMmNkYzAyYmZjOWIwMjE5MjRiODBhYjBkOWJkMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNWVlOTZjNzFlMjRiZmVmZjlmMGMwNTMzMDZiNDIxYTlmMzcxYWQyMzkyMmRmMzVmMmIyN2JkNzc1NTY5YzkzZiJ9" + }, + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L370-L473", + "version": "repo-lines-v1:sha256:8c5e4335ed75c5db166bd682da042bba99aa59fa2f9a8dc06d7ad37abda3bdd4:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA0LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI5MWFkN2M1ODNjNDVlZDZiMmUzMTk1OWRlMDRjOTg3ZTA5YTdkYTExZWMxOGM3YTlmZmFiNDY4MzYxMGZkYjViIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlODRmYmFmMjYzM2M4ZTg0MDkxNWY4YWVjMjZjNDMyMWY4NWRiNjg0MDA5YzJmOGRlMzgzNWZiNDU1MjBkY2M1IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI1OThiM2ZkYTVkMjcwZjY3MmVlOTM3NmJmN2RiOGZlZTJmNDhiZWEyN2FhNDliYjEzYzVhNmYyYTAzNjIzZjE3In0" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceContentView.swift#L555-L589", + "version": "repo-lines-v1:sha256:5b49bc13f4df56b004b908909ef82094b29f7cc275af61ae0fee28d5adaf467b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiZTM2MTE2NDk5NDM3MWMxOTlmNzg5NWQ2YjBjNTQ5NGU0ZTBkNDBmZjc0YzY1Zjc4Yjk0NGFhNjhjOWEwZGUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM4MDU1NTIyN2IxNGM1ZmEwYTQ0NTA1NjhmM2U0N2RmNzAxMDg1NjFlZDU4NjM3ZTZiODlkZDc5ZmVhOGE3NzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY4Zjg3NmQwODViMzQwNjE2MjkwNzMwZGIwNTNlYTJjM2M5NmVjNDQxOTFjOTk4NDc1NGI4MjFjOWU5OTNjYTQifQ" + }, + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift#L262-L351", + "version": "repo-lines-v1:sha256:5535bdd6a0c2aa10458639db09aff2e136fe57e90a36a884b905b6b6cc612eed:eyJzZWxlY3RlZExpbmVDb3VudCI6OTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MTUwYWRjYjYyYzQ2MTMxYzczYzdjODQ3MmI1ZDZiZWI0OGY0ZjRkZTAwNzUxMDk1MzQ2MzBmNWVmMDZmMjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRhOWY4NmQyOGU3ODRmOWZkMzFmYjcyZDE1ZjYwY2JjZWFhZmRkNjY5Y2JkNWI2ZGE3ODg4YTAyMzMyMWViYjkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlmMjk0Njk2OGZmNzUzZDk3ODM0ODZiODE4NzRmMzViMWRjNmFhNDM2MTc3ODVlNDZhNWVkMzlmNTU1OTQwODkifQ" + }, + { + "resource": "repo://TFMTests/WindowToolbarFindTests.swift#L106-L133", + "version": "repo-lines-v1:sha256:f5abcb028167903c4b022c1b67ec39b17b66210be38f18d8e5a3e3d56b91a574:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyMzkzODU4NjhhODkyNGFhMDc4Y2QyNDQyNGVhZmE1N2NkYTQ3OTZkMmRjOWFhOTY0NWJiZTVlZWI5MzJmNDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU1ZmNkYzA4MmRkZWRkMTFkNDhmNTI1ODdiMGI4MDFiOWI1NzBjYmFmNGU5ZDFhNzUzMWJlZTJmOTNhMzUxZDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjExOGNhYjZkNzgwMjk5ZWY5NzVkMjRhZTFjZGYyMzVkNTE5OGY1MzYyNjA3NWNkZGU0YjY5OGQ3MzE2MzlmMWEifQ" + }, + { + "resource": "repo://TFMTests/WindowToolbarFindTests.swift#L53-L67", + "version": "repo-lines-v1:sha256:239e773209810ab34d76ac380e7ea9db58844733b42bb7117103e750b82cd74e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU2Njc2MjJiODU3ZWI1ZDAyYTQzN2YwNGFkOWY0NDE3NTU3YjIxYTc2ZDZjNjA3NjNlNmRhODRlZmI2MzBkOGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcxNDVmZDFkMjk1OTMwMzE4YTI4MzA3YzU0ZDFjNzdkYjBjZTRlNGE4ZWFiMjZjMzZhMTU2ZjA5ZjcwNGFhMWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU1ZmNkYzA4MmRkZWRkMTFkNDhmNTI1ODdiMGI4MDFiOWI1NzBjYmFmNGU5ZDFhNzUzMWJlZTJmOTNhMzUxZDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ" + } + ] + }, + { + "id": "claim_49fcc268f3564138803dc0186748f685", + "statement": "On macOS 26+ a background search host contributes system searchable UI without rebuilding the persistent split-view branch; earlier macOS uses an explicit toolbar search field or compact Metrics popover, retaining native field identity and reserving toolbar height even when no Find is offered.", + "evidence": [ + { + "resource": "repo://TFM/App/RootView.swift#L70-L114", + "version": "repo-lines-v1:sha256:b75444b20f9972ed77527c11bc67da1e702630dcfd40325b2404ada9e632bb72:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY5MDFkZDM3NjU2Yzk2MTY4Yzk2ZTUxYzMyNTZiMDdhZWIxZGU0NzY0Yzk4N2VjNmQ3ZThmZTVjMmQ0NWNjZjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNlNzE0MzFmNGM5NzhiOWU2ZjQ4OTJiM2JjN2RiZGY4NTdjZjMwYTdiMzBkNmQwYzY1ZjNiZDE5MjQ4YjhkNjciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyZDc4OTQyMGU5ZjY2Y2MyNzdjZDliNTNjYTUxZDFhODgyNDA2MDAyNmVlZTU0NTgyNGJmNWQyNWQ2NDJjZjIifQ" + }, + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift#L421-L605", + "version": "repo-lines-v1:sha256:09502a00c98ff9986bd6a8459680229069daf2b7db8f0d2dc183e5e73f084108:eyJzZWxlY3RlZExpbmVDb3VudCI6MTg1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI4MDgzNDc1NTE1MTk2ZTVhMzRjODg1YmM2YTUxYmVhZTA2NTU2YWQ5MzIxMWQ1ZmVlZWM5MDFkMzNkYjFjZTAzIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiIxYWZlZTU1NmI0NjE5ZjBjMmIwY2NkMzU2YmQ4M2Y5YzVhN2UxMjU5MzhiYzcwOTUzODIyMzdlMWU3YmVmYjQ2IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIxOWU3NjM1NWNmMTE5OTQ4MGMzZjk5ODM2YjE0ODZjODQxZDg5MWZhYWQ5MDRjNjA4ZTA5MzAyMmQzNzU3YWVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIxOWU3NjM1NWNmMTE5OTQ4MGMzZjk5ODM2YjE0ODZjODQxZDg5MWZhYWQ5MDRjNjA4ZTA5MzAyMmQzNzU3YWVlIn0" + }, + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift#L43-L52", + "version": "repo-lines-v1:sha256:60e875315d65ba9344420d6e411894a420a10b0990d3f7c6aa57a984803bf20d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcxZGNkYzJiY2FlNmU5ZGMyNWNmNDExNmYyMGY1Y2M4MWEwMTY1MDdmYzc0MjY1YzFhYTJhN2MzMjZiMzFiY2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNjY2YwMzlhY2M0MmJlYzQ4ZTMxNzllMWU0N2ZkOWYzNjkzODgwM2EyMWFmZmQzZjlhZGRkMTM1NjU4ZjliM2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5YmZiYjUwZTliODgyOTI1ZDY4YzJmYTZhOGQ1NDBhY2Y2ZWM1YWRiOGU4NDk0MjEwODg4NGM5ZmNkZWRlZGQifQ" + } + ] + }, + { + "id": "claim_8e153c5f89214464a1e8d11df371eb60", + "statement": "A focused Telnet session resolves to terminal Find and can present search from the command, but the current toolbar findContext terminal branch only binds Serial and SSH sessions, so Telnet has no usable titlebar query binding through that path.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L423-L428", + "version": "repo-lines-v1:sha256:1d671a184e76194c338c714fb8b0e84f23ca184f68d84a7527682f616ad3c83a:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOWI1MWExNzQyM2VmM2VjYzBiOWZkZmVmNjcwNzlkZjA4NDU0NWFiYzlhOWI2YmM1YzRkZGM3YjAwMWY5ZGFiMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMmQ0NzkwYzFhNGYxMmNmZjI4NGYxZjk4ZDliMGYzMGZkYmM1ZjE2ZjI3MDNlNjk1M2YyN2Q1MDMyZjU0YmJlYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTM4ZDEwNmZiNTY3ZjViODk4NTNkNGQ1YWY3NmRkMjE4MzRlNTRmZTJjN2E0ZjBiM2E2NGM2MTkzOTQ3YzJlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZGY4ODJjMzk5NjNiZjdiNThiMzk3NTJkOGE1MTI3MmVjNTI1NTI4YTlhZDU1NDJiZmNiZjM3Yjg2ZGMxZjM4OCJ9" + }, + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L457-L473", + "version": "repo-lines-v1:sha256:9f65b5a24d048ffb22d191d72af2fd14cabccd3c0b01208f9b81d99a8316da4e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY4NTc4NjJlMDEyNWU3MTgzZWQ2NmRkYzUxN2RkNjg1NDIxNTE3NDFmZTY2YjM5NjhmYjYwNTgwMDdlOWEyMDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQwM2I4M2Y2NDA0YTkzMzMwNWJhYTdiNTUyMThkZTdhYzg1YWI1N2EzNDgyNTViZjQ0ZGM5YjgzYjlkY2NlMDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU5OGIzZmRhNWQyNzBmNjcyZWU5Mzc2YmY3ZGI4ZmVlMmY0OGJlYTI3YWE0OWJiMTNjNWE2ZjJhMDM2MjNmMTcifQ" + }, + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift#L875-L897", + "version": "repo-lines-v1:sha256:15ba3a426171e5ddb08798f6d2bbbe8ad97e0404d2c91d8bc63159844740cdcc:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJjYTY0NTkyNGIzZjY0ODMyMGFjMDkwYWRhYTVkNWFlODExZjRmMDcwMTNkNjU0MzFiYTgwMDM2MTU1ZGNiMWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE4YzFiMTVlODA1ZDNhMjM0NjU0NTAyYzY0NDcwYjhjNjcyZTc4NDg3MzgyYjhmOTdjN2I3OTE0YjhlY2NkMzYifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/engineering-invariants.json b/openwiki/.claims/architecture/engineering-invariants.json index 66b133d6..483ca292 100644 --- a/openwiki/.claims/architecture/engineering-invariants.json +++ b/openwiki/.claims/architecture/engineering-invariants.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:6c657e197430df2d01d976bdc75bfd503c6dbcfe5a6f9db0def86eeb8e459d1b", + "pageVersion": "sha256:b3cf2c3e75779877055fc98f5005afa3c2c3ca927da6b0232fbf035d108cfe52", "claims": [ { "id": "claim_72f9329a158e418cbf0fd6394f82815e", @@ -44,7 +44,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFI/App/MobileSceneModel.swift", @@ -52,7 +52,7 @@ }, { "resource": "repo://TFM/App/AppModel.swift", - "version": "repo-file-v1:sha256:5284fc38208bb02af017031469b91288fedd0383d59f391622aa4c32a8450f42" + "version": "repo-file-v1:sha256:0029784efe4588e87c3dc18317fdfaad46bed6b3a32bcf72dd0dd9b1c9da256e" }, { "resource": "repo://TFM/Features/Workspaces/WindowModel.swift", @@ -150,27 +150,27 @@ }, { "id": "claim_396197f6506e448888fc408eefe3eb04", - "statement": "Mobile workspace restoration persists connection-free descriptors rather than live sessions, reuses one live workspace across scenes, and closes runtime transports on background expiration without making foreground restoration an implicit approval or replay boundary.", + "statement": "Mobile stores ordered connection-free Workspace descriptors, cold-launches them as Recent without connecting, and publishes one live instance before its first on-demand connection across scenes; finite background expiration suspends live transports, and foreground reconnects only live Workspaces with resume intent, not unopened saved descriptors or prior commands.", "evidence": [ { - "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "resource": "repo://TFI/App/MobileAppModel.swift#L647-L697", + "version": "repo-lines-v1:sha256:21f59b12deb183823816db3e0f32890c5383be16343e6cc30957fb0e11101477:eyJzZWxlY3RlZExpbmVDb3VudCI6NTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZDY0ZTIzNWJjNzZlYTM1MDI3NmE4MGZlMGM1NjM0ZTYwZDFkZmUwN2FjYWQ4NTJlMTFhMWQ2MjkzM2ViMTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhkZjI2Yjc1ODA3NjRhMzA3MzcwNDAxZTZiZmI4NWVmMDBlMDFiOWY5MDA0M2RjNWIxY2I2ZDhkZGU1Y2Y2NzYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyMWFjNTE4NDc5MWIzNWNkZTM4MDkzNDU1MTVjMGFjMDEwZjA3MGVhZTAyMTRjZGY0MzIwZDE4NzI5N2M3MDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQwMTYwNjlmZDYzNTRiM2JjOWZiMDlmNTY3MzEzMDA5YmRmN2IxYmExNGZkNWFmMzBjYzU5NGYyN2M5YjJiNDUifQ" }, { - "resource": "repo://TFI/Features/Workspaces/MobileWorkspace.swift", - "version": "repo-file-v1:sha256:3aed203d6e01bca706733b899b9636aa4808717dea3a8f2d044fd01db08a33d5" + "resource": "repo://TFI/App/MobileAppModel.swift#L748-L767", + "version": "repo-lines-v1:sha256:009a2acb4cd53659b0f5811f41e299f4d746f4be8f1f4352ff30ad7118fd662b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxODI4YWZmNmM2MDJhZDBjNDkzM2FhYjA1ZmQzZTgzOTVmYmI4ZjY3NTI1OGU4NzBiMmE4MGY5MjhjYzhmZWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhNzhhMmQzMGFkYTcwNjU3OTM0MDdhOGM1ODY5NmMxMmM3NjAyZTc0OTVlM2IwZmE5MDRmMDE3NmI0YzY5NmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUxNmNkYmM5MDJkOTFjMzE5NWYwNWM4NzZmZjcyYmM3NTdiNDdlZGE3ZjYwNmU4NTRjNDMyNTgyOTRhMDk3MGIifQ" }, { - "resource": "repo://TFI/Infrastructure/MobileWorkspaceStore.swift", - "version": "repo-file-v1:sha256:ea46bc5d91b8f0cbbdf562a56e1383dc1d7732ba249b109dd676a54369acf9c6" + "resource": "repo://TFI/Features/Workspaces/MobileWorkspace.swift#L1097-L1101", + "version": "repo-lines-v1:sha256:a6a1d35a0ae426d90a8b6ecf552cd2c38bc70c537be939bbd2b6446fdc7d92be:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTJhNTAwYzZlZDg2ZWUwMTFjMTk4ZDc1NGFmNzI3NWM1MzEzMDUyZGZiOWNkYjIwM2E3NzEzYjllMzQ1ZDA5MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTZkYzM4MjAyM2ZkNDY0OGRiNDNmZmE2MWM1YmZiNDdmOWI5NmNlMjJmMWY0YjY4ZjFlNzNkZjc4OTE3ZWUwOSJ9" }, { - "resource": "repo://TFITests/MobileAppTests.swift", - "version": "repo-file-v1:sha256:d2466771edf0d6d85ccbd8d5c6a8a7cd05521af153016478430a466085380ba9" + "resource": "repo://TFI/Infrastructure/MobileWorkspaceStore.swift#L4-L67", + "version": "repo-lines-v1:sha256:b13777ca2b68bbd24b7633bb0fb32e6e884a5469c4b3d6eb06974d2561ece073:eyJzZWxlY3RlZExpbmVDb3VudCI6NjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxNDkxODZkNzI0Y2I5MzM5MjJhN2U0MTQwZTVkMzhiNGI5MGQ5YzQyZjQxZmY0NDIzMzZjNjVkNWNhMGRlZDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlkZWFmNWM3MTU4ODdiMWVlNmNjZTNjMzk3OTIyNTUxZWUwYjJjOTIxMjJiYmM2MmExZDMzYzE1M2JmMjBiNTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE1OGQ0YTkxMDc0MDU5ZjBjOGQyMTM2ZjliZjgwODM0NjE0OGZjOGNmYjM1NDNkZGNiYzc1MGU3NTc2ZTcyNjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ" }, { - "resource": "repo://TFITests/MobileWorkspaceStoreTests.swift", - "version": "repo-file-v1:sha256:9953e49389c0c2b390fe6bd51e467de56c31ec1556a13633ae239ac842c9241d" + "resource": "repo://TFITests/MobileAppTests.swift#L1532-L1601", + "version": "repo-lines-v1:sha256:95d9405507e382bde006ede06de795e41c83dcceaa0a8f55ce36fb006d9939f9:eyJzZWxlY3RlZExpbmVDb3VudCI6NzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVhZTdlMWFhMzAzZGM0N2UzZjM1M2VjODFhMGQyZTMyN2Y3ZDgwOTI2NzQxYmIyMzA5OWJhY2NjYzlmZDg3YjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRjMjM0YjM5MDZjN2Y1NTE2NzhhMmZkZjNkNzFjMjIzYjQ5Y2YwMWU1N2RkZjQyMjdjNjNiYWY1OTRjNjVjMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAwYTY3MGRlNmM5NGQ5N2RlODBkN2RmMjk5MWJjOWI5MTM2MDg4NWVhZjE4OTJkYTk2MzUxZTNmNjA3OWIwNWYifQ" } ] }, @@ -332,37 +332,41 @@ }, { "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L516-L630", - "version": "repo-lines-v1:sha256:b1882f48ba2a0c4f0faaa010c3ad73fbbfed243a2f0f51c0d883ed8058e5a3d3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIzN2U2Yzk0MTIwZGUzNjU0OGMxZjcwMTkzYzMxYzg0NTQ1ODI0OGQ0M2E4N2U2ZTU0MjY5MTBmY2VkYmJlOGJiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3NDhiNTNjYTI2MWZjOWVmMTVjMzg5YWVkYTA0Zjg2MTFjN2I0N2UxOGU2MjA5NWQxMWRmODkwYWNjMWQ4ZjRjIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwZWE5ZjA1OWViZGRiM2M1YTA1MTQwYTNhNTJjMTM2MmU4ZGVhZDhlNmU1MjllZWNhNWMyNjkxOGZhNTMyNTY1In0" + "version": "repo-lines-v1:sha256:6f0586148546ed005af984580253f2dc7d5de8689160a50bb5889c18111981cb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTI0LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIzN2U2Yzk0MTIwZGUzNjU0OGMxZjcwMTkzYzMxYzg0NTQ1ODI0OGQ0M2E4N2U2ZTU0MjY5MTBmY2VkYmJlOGJiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3NDhiNTNjYTI2MWZjOWVmMTVjMzg5YWVkYTA0Zjg2MTFjN2I0N2UxOGU2MjA5NWQxMWRmODkwYWNjMWQ4ZjRjIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwZWE5ZjA1OWViZGRiM2M1YTA1MTQwYTNhNTJjMTM2MmU4ZGVhZDhlNmU1MjllZWNhNWMyNjkxOGZhNTMyNTY1In0" } ] }, { "id": "claim_bbae8e4110c5473b83d5d2803745fea5", - "statement": "Preparation has a separate identity from streaming: cancellation invalidates it synchronously and joins tracked history/preparation work before interrupted persistence; stale edits are rejected, archive/delete cancel preparation, manual compaction refuses it, and changing selection alone does not cancel it.", + "statement": "While an Assistant capture is preparing, cancellation makes its identity noncurrent synchronously and joins tracked edit/history and preparation work before attempting an interrupted save; interruption is projected only on successful save, whereas stop alone does not await it. In the separate savingFailure phase cancellation joins the existing failed-snapshot save rather than replacing it with interruption; archive/delete wait, manual compaction refuses active preparation, and selection changes do not cancel it.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L231-L255", - "version": "repo-lines-v1:sha256:63509c11ab1c2718bead3930614de6427e1e6df47c0e787aeed401498661891c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY0YzVmZGJhOWRmZTUwNjMwNjlkYTdlN2RiZWVjM2QzZWRiNjE3YmUzMTQxYjBmNGEyYzY0OTEzNWI0N2M2ZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIyMzkzYWYzYmRiOTExYzA2ZWFmMjNkYjMxZTkyMmNkNGY3NDc2MmYzNGFmMTE1NTJkNDczYzc1ODhhZmFhZTkifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L233-L400", + "version": "repo-lines-v1:sha256:804456815453447a0a1d2f6b01d659757753754ad94479145a6399eaf8e23f34:eyJzZWxlY3RlZExpbmVDb3VudCI6MTY4LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0Y2YwOWViMGM1NzQ0ZmI5NzMzMWI5OGZmM2ZiZjA1YTYwMmJhM2Y3ZjY3ZTVkYTViZTkwOTUwMzNmNjI1ODI1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJiMjM5M2FmM2JkYjkxMWMwNmVhZjIzZGIzMWU5MjJjZDRmNzQ3NjJmMzRhZjExNTUyZDQ3M2M3NTg4YWZhYWU5In0" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift#L12-L21", - "version": "repo-lines-v1:sha256:e2ba6b40bc2c5a1843a0a570f28c471ba3a74682cf31c79865a8472029912a21:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkNWFkOTQ4ZjVhN2JlOWJlMTVkNTRhY2EwNzlmZWI4MDYwMjNlMjVjNjIzNmVmMWI0NTM0YzQ0NDA1ZTk1NDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI5NDU0MDY3MDk1MTM2ZmQyMDViNmNhM2JkMGFjYjk5N2M0MDg5M2JjNGI4OWFjMzMxN2YxZmNhYzFiMzc5ZmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU4ZGJjMzU4MWFjZTk4MTNjMmE3ZmQ5OWI2YjNmN2I2ZTBlNmE5ZjJiMGJlZDUzNmUwOTJiZjI2NWMzOWNmNGIifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L519-L540", + "version": "repo-lines-v1:sha256:86b94fd10a8c9d7ca8a12fd280f314f6ed57b669f92add6b32897973ab5fbe31:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUxNDk2NDE4YTVkMGU3OTIyYmYzZjczOGMzMzJmZmNhM2UxZGJlMjkwNmFiMWVhMzBkYmE1YjVmNzdiNGYzNDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBjOGE2MGMzNzZlZGJkOWFjYTMwZGY1NDgwMjUwOGVmMDcxYWU4YmYzN2VmZWE3ZjI3ZTkwOTk0Y2VhZTBhYjAifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift#L63-L75", - "version": "repo-lines-v1:sha256:c49e78dca59df1fa504084f70e5870b13c95199d99512f713215e4d963559c1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBlZGZjY2UzODdkY2Y5MTEzNWQ4YjcyMzViYjIzZGU4ZDM4OGVkOWY0YjU5MzhkODdlMTM1ZjA3OGU5MzBlNjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmNTU2NmQyMjg3Mjk1MmM0NDc3MmQ1NDEyZTgwZjE2MzI4ZWM1ZGM5YmIxM2YyNjVkODFmNTg0MGFhYWM1ZjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVmM2MyYmU5Yzg4ODZjMmM1YzI4MjYzOTk4MTBmZTYyMDY0YWZhZWEyN2RmMTNmNzQ5OGI4M2QyMmVlODBjODkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjZjMxNzMzMTFlZjYxMGRlNTllOTE2MjM5ZDBiZDQ3YjA5OTU3MTNjYThiYWY1NGZmYWVkY2Y2ZmJmZTQxZjUifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L89-L231", + "version": "repo-lines-v1:sha256:55ea4bfcd519dd09eee725c19c9392e357ef7c679007cf5830e28441f8dbfc43:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQzLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI2ODc2Yjk2OGUwYmE1M2U1NTE2ZDdkMjM4ODIwMjU2NTYzZDk1NTM0NzhlZmMxMDZhMWFhOTQ5ZTFjNGE5OTJmIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlOGVhZjNlMWRiMjg0ZjZhNmZkNGUwNjZhZTJmYjY1NGFlNjhmZGZjZjNlN2U0ZGNhNGMyZGQyMTRhNDliOWQwIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJmZDMzMGY5ZWQ5ZDY1MGE1YTA0ZTU5OGNmMTZhNjZmZDkzNzVmY2FiMTM4ZDJiYjZhNDFmMTUyY2M0YzIxMTQ0In0" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L241-L280", - "version": "repo-lines-v1:sha256:10dde8f96383fc4e7c331b4e927c1c5e61a7173356ef4b5b49d67c68ba29e2e3:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImExMGUxZDhkNTQ2OGFiNjQ4MzUxNzE3MWM1ZDQ0NzZiNjUzNjIwNDJlYzVlNzZhYjNlZWQ2NTM4YjhmZmRiN2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiZWNkMDQ0NWJmNGEzYTg5NTcwNTczNGE0YmEyYjFjYzQxMjRiNzM1NzYyYWY0ZWYxYzQyODcyNTkyMThlNzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBiNDkxY2E1OGFjYmFiYWNhOTBhZDBkYmQyNjgxODk3NzFhMjY2YTYyM2FhZmE3NzRhYzY1MTg5OTk3YjU1YWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift#L12-L26", + "version": "repo-lines-v1:sha256:287f28908d38a5334560a66a57519954c883a2b09e9a93068dadc3602d22feb1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkNWFkOTQ4ZjVhN2JlOWJlMTVkNTRhY2EwNzlmZWI4MDYwMjNlMjVjNjIzNmVmMWI0NTM0YzQ0NDA1ZTk1NDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU2ODM1MTRjZmQ4NDBjYjlhMjgwMzMyZjM1ZTk3OTMyYWQ4NjVhZGVmYzY0NzQ5MTkzNjQ2MThjY2RhMjViMGMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI5NDU0MDY3MDk1MTM2ZmQyMDViNmNhM2JkMGFjYjk5N2M0MDg5M2JjNGI4OWFjMzMxN2YxZmNhYzFiMzc5ZmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIxZTU1YWYyOWEyZjRkYjE0MjU2NjllNGRkZmYwOWFhYTA2MTNjMjBkNTZmNmQ4ZWE4YjhlNjVjNWY0NGM5ZWYifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L684-L762", - "version": "repo-lines-v1:sha256:7a08479880142384554fef4c4143ed597856d65be0c552a76400a967ada09df3:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxMGEwMjJhZTMxNzI3ZmIzMmUxNTFiMmY3NzA0ZmE4ODVkYTZjZTc0NTdhMjU1OTNiMWIxY2M3YTA3ZGY5NjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI5YWI2ZThkYTBmYzkwMDY0YjdjNGEzNTI3YTVlNWFiZDI1NWI2YjBmZTE3NTc5YWFiNDI1Nzg1YjA2NmZmNDUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdiZTFlNjJiNzdiZmE0MWYyZjNjYzlhMDU1MDI1MzY4MWI3Y2VhN2M2ZDZhMTk5MzljYjVkNTEyMGFjNTI4M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBkOTk4NGRkMWE0Y2M1Y2ZlMTkyYzE1NzRkZWMzYTk1MmFmZDgyMWVjNzZjMGJmZTAxM2Y3OWMzNjJmODlkODIifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift#L63-L74", + "version": "repo-lines-v1:sha256:57b82845f5eaff42dff5e7ad1ff5b51df73afb6149438dc92abac50a70963151:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBlZGZjY2UzODdkY2Y5MTEzNWQ4YjcyMzViYjIzZGU4ZDM4OGVkOWY0YjU5MzhkODdlMTM1ZjA3OGU5MzBlNjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjMjU4YjdiNGY1YjRhZjg4NjE4ZDI4NGJkODg1Y2VmYzNiMmQxOWRhMTk5OTlmN2ExNDI0YmQxMDliMjNjZjMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVmM2MyYmU5Yzg4ODZjMmM1YzI4MjYzOTk4MTBmZTYyMDY0YWZhZWEyN2RmMTNmNzQ5OGI4M2QyMmVlODBjODkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNhNDJjYTgxZmYyZDhkMzljZmVhNGFlMTA1MGFhNjhmNTRkZTgwNzZmOTY5MTE5YjY4NjRiODIxNmRlNDVlMzUifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L830-L839", - "version": "repo-lines-v1:sha256:ce3f227083ebc0587a705272d2c18cfa110d702714310ad736937b34384653a6:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNmNzA5MTI3NmEyNGM5MTU5YzRjZGUzZWZiY2RlYWM3YmQ4ZWM3ZjQxYzVkYjNhNmIyOWM3MTE1OGZkZDg5Y2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNlOGQzZmM2YzYwOTVmMmM4OTlhMmM0MTRlMTg4Zjg4MjY3MTA1ZjQ0ZTQ3ZTZhODQ4NjE3MTM1NGE1ZmYzYzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY5MTNmNzA3ZWY5NzdkM2FlMDUxOTgzMGM2YTc2NmYxYmI1OTdjZjJlMDgxOTQ3MDM0MzU0ZWU0MTQ1ZjA0NmUifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L680-L821", + "version": "repo-lines-v1:sha256:5be31ca8267fac7c7912ab1b0d461fface21b722bbdc22a0b34180d31b7e47f0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI1NWEyZmM4NWY3MmI1MzQ3MWY5OTcwOWRjM2ZlMzgyZDFiMDBmNTljMjVlYmU0MjNmOTNhYWI0ZTIxMzRmZjcxIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI5MTQ1ZjdlOTZhNDNmMmI3NzdkZTU2MDg5MDU1MDYyYWNiZTc5NTFkNTNhYmIxZDVkM2FiNDcyMTY3ZjgwZDM2In0" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2241-L2257", + "version": "repo-lines-v1:sha256:10265098d3b40def1fdadf83d0e0a2ecebe2e14e921219ac83bbeb31eae12afe:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmZmM0MzNjZDM1OTM3MTAxZjgyZTM2MzI0MGZiMDkzMWJlMjZkYTcwYjg1MjRlMDEwYjVjMzlkNzdkNWYyNjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM4MDU1NTIyN2IxNGM1ZmEwYTQ0NTA1NjhmM2U0N2RmNzAxMDg1NjFlZDU4NjM3ZTZiODlkZDc5ZmVhOGE3NzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5NGMwNjM0YWI1Nzk0YTg2OTJlN2U2ZDI0M2FhYzEyYmEyOTM2ZDc2ODY5NTdkZDcxYWI0NGUzNDYyNzc1OGUifQ" } ] }, @@ -386,33 +390,273 @@ }, { "id": "claim_fd359e43825344cb87abb3a4938e1663", - "statement": "An edited message first owns its same-ID staging run; the first real snapshot atomically reassigns only the staged row and removes staging, while live running/failed/interrupted adoption preserves provenance and chronology. Repository-instance retired IDs reject late saves/events; missing-model/credential failures still publish live before asynchronous save.", + "statement": "A successfully edited message starts in a same-message-ID staging run; the first real saved snapshot reassigns only that staged row and removes staging while preserving chronology and old replay ownership. Live running, interrupted, and failed-run adoption uses the same guarded provenance; missing-model/credential preparation failures hold the preparation until their asynchronous save commits before projecting failure, and failed saves report an error without adopting staging. Repository-instance retired IDs reject late writes.", "evidence": [ { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L719-L793", - "version": "repo-lines-v1:sha256:81156ef97d808d87d63a184f6020940cf4a5bbbdecd8dc55a2d3a3c7e7b0b60c:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2YjhlMjRkZDNlZmY5YzY3YTZiNzg3ZWMwMjA3ZmMxZTI0ZGMxZTcwZmRlZWViNmFjOTljOGFkNjA1Yzk3YmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2ODhmNzU3ODA1NDczNjk2N2U4NzY5MmJiYTg2YjI4MDhmMzI0MTk3NTQ0MDVlYmZkNmM0NWI3MTk4OWQ0NzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRhNzdhMDY4Y2ZiMmUwMWRiMDJlMTAyZDRiODhhOWMzYWRlOTU3YTNhMWMzYjczOGE3ZTBjMWNmMTc5MTUwMjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRjNmM3Y2RjOGM0ZWMwYmM5ZGU4ZTY5MThmYWUwYWE5ODQ0MTJiNDJjZTVjMzY5ZWExZTMzMjg0N2Y4ZjIyOWIifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L652-L746", + "version": "repo-lines-v1:sha256:eeb339ffaa2586b34a5e83768ce7d360446364a3f9a4b4dc2155f93e7c51d70b:eyJzZWxlY3RlZExpbmVDb3VudCI6OTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFhYTU4ZmU0MmEyZWE4ODVmNDg3OWQ3MzVlOGJkMzU2ZTczYmEwZDFkNjkxYzc5MWVmZmU5YmE5YzJjNDg5ZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIzOTgyN2Q5ZDE5OGE0ZTRkNmExZWNkZTFlMDVmZDAyZjY3MjdjNTBkZGNmZWY3ZTc1MThmMGRjYWEyMzE3MWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ4ODhhZDQ4NDdhZDZkMThmMGZlOWEwMWI5ZWYzNGM5ODZiZWFkZGMzNDQ5Mzk2ZWE1MGVjYjFiYzZkODM3ODYifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2040-L2092", - "version": "repo-lines-v1:sha256:d1a56a12b39372c0277e40115884e11b8c29d16d3df1e847c7407b89efbd1881:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVkOGQ3MGNkOTIxY2E1NTJmMGEwZWIxMGJhNzc3OWQ2OTk0M2RlZjUwY2NhNjQ5YjIyZTg2MzU3OTgyM2ExM2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3YzRmZjVmY2EyMGUzODk0Zjc3ZmY2NDk0Y2FmNmVkZDU2NzFiZjE3N2YyMmVmMDE3NDBlNzNhMTYwMTc3OWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlhZDUyYWNhNzhkODcxNDMzZjJhNzMzZGJmMDQ3MGNmYTZhNGEwZGQzM2IzY2IwYzgyMTJlODNkYTIxY2ExZmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiNTdmZTYwMTUxZDJlN2IwYWNlZTEzOTJhYzI5OGUxYzBjOGE2OWRiMzlkNWU4OTllYzNkMzdkMTM4Njc3ZjMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L738-L821", + "version": "repo-lines-v1:sha256:572c14aae2ce8defd734596e7ea69dd84e1525de9a6d92c91853c2f091d9f82c:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2YjhlMjRkZDNlZmY5YzY3YTZiNzg3ZWMwMjA3ZmMxZTI0ZGMxZTcwZmRlZWViNmFjOTljOGFkNjA1Yzk3YmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRhNzdhMDY4Y2ZiMmUwMWRiMDJlMTAyZDRiODhhOWMzYWRlOTU3YTNhMWMzYjczOGE3ZTBjMWNmMTc5MTUwMjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkxNDVmN2U5NmE0M2YyYjc3N2RlNTYwODkwNTUwNjJhY2JlNzk1MWQ1M2FiYjFkNWQzYWI0NzIxNjdmODBkMzYifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2625-L2646", - "version": "repo-lines-v1:sha256:078528287f4cac7401a61342ac1db3154e36f5566407f8bb9332cd63c543e273:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjZWUwZWU1M2M2NjUxODNlOTE0NjU5MDViZWY3ZDQyMTI0ZDRmM2JkYTJkNDg5MzlkNWIwNWQ1Yzc1MzIyODgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNmODMwOTk4YzhiZmMyY2EwMGQ0MGM5NDlmZTgxOTQ5ZmQwZDg4MTg1ZWUzOGNlMDNjMjAzNzg4MDZhZWQ4YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2YzUyZmU0ZTgxMjIzMWU2NGIyMGFmODc0MmI0ZGJjZWNhMjlkMDFjMTVjYzk1NDNjYzc0ZGFhNDAzNjlkZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJmZGI5NTg3M2IxNmNiMTEwMGJjNGVmMGZmYWFiMzZmODc1Y2EzYmVjODY2MmIwMDA5YzEwY2JlNWE2YWVjNTMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2183-L2239", + "version": "repo-lines-v1:sha256:d982f6091ccc1b135d96a1bc0e6f45ef79b9ff1032b27e788f11838ea0f7312f:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjNWM2ZTc0NjY1Nzk2NDMwMDgyYjI2NzM3NGZkODliZjYyYzQ3Y2ExZGI5N2Y5MjhkZTRjZjczMGJlYWNiMmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNlMzBjMDUxNzQ4NThmODEwNDM5MGM4Mjc1NDM0NjRhZDYyMDU1ZWIzYzIyOWEyN2ZiMWFjZTgyZDFjYTZiY2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAyMDJkMWVjMzI2MWJhMDI3M2Y4M2Y4NzVjZDYyMDE0NGVlYjdmNmE4OGQ3NjRjZjUwMDFkNGY3MzI2ZGE4ZjAifQ" }, { "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L156-L165", "version": "repo-lines-v1:sha256:c887b3a1878d05b6825a0061c2a4ac62fa358fae324872204ffb83d6b940c2ed:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyYmI2ZDU3ODMxMmY2MmZkZDc5Yzg4N2EwY2M2ZWQwNGNkOTA5NDBmMWFhYTdlOWE1MDIwZWY2OTI5MWE5NTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2MDIwMDcwNjJmOGU3MDc5ODNiZjBkYmI4ODMyMDYwMjZiMzM1ZGY5ODBmODNlZjQ0YWYzYjRjMWI3NDA0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcxMDIxY2E1Njc1M2E4ZWM0MDdkZjY5ZjhhNWM4ZGMwYmJiODEyOWE2MTQ1N2NjYWNhYTdjOGYwNzEyMWQ4NTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMwNzU5M2RmMjVjYjQxMmZiNWI3NWUwZWI3NWQ3NGM1ZWY0YjBhMzE1YmJlMWRmYjcwMTg4N2MwMjEyMGM1NjcifQ" }, { - "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L16-L121", - "version": "repo-lines-v1:sha256:c1a4a9f265c86d77937e83acae5e2b69a2523713431a89d470dad62099d6b376:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI3MmJiNmQ1NzgzMTJmNjJmZGQ3OWM4ODdhMGNjNmVkMDRjZDkwOTQwZjFhYWE3ZTlhNTAyMGVmNjkyOTFhOTU3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJkY2UzN2IzN2YwNGIxOGQwODk0NmFmYTY3M2UwYzIzNjcyMWEwMzkwNTQ2YjM4NTUyYzI0YWY3MDc4ZTdhYjMyIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlY2U5NjA2M2ViYmNhNjY1M2Q0YTYwYTViNjBjZWE4OTRkOTVmOWExNjQyZTQxNDEwMjFkNDZlNjQ4MjgyNGVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJmNTcxZWY2ZjVlOTYzMTE4ZDM3MTdiNGQ4MmI0YjBiOTliMmI0OTI3NjYzNGFjNWZiNmZhMGE3ZTVjNDBlZjhjIn0" + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L16-L117", + "version": "repo-lines-v1:sha256:b2ff4fa29463577fc96df58a7d6795d890ae5f393207d9a228faaf0c6ecee252:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI3MmJiNmQ1NzgzMTJmNjJmZGQ3OWM4ODdhMGNjNmVkMDRjZDkwOTQwZjFhYWE3ZTlhNTAyMGVmNjkyOTFhOTU3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlY2U5NjA2M2ViYmNhNjY1M2Q0YTYwYTViNjBjZWE4OTRkOTVmOWExNjQyZTQxNDEwMjFkNDZlNjQ4MjgyNGVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI5MDg2NTI3OTliNTFlNzllMWE4Nzk2ZWQzMzQzOWQ1ZjUxMDU2M2IwOTg2NWQ4MjhiY2ExYmQzMGE2NzE4ZmJhIn0" + } + ] + }, + { + "id": "claim_fed94eeb6f614c99a6adedd8c7b61d58", + "statement": "Saved-Host deletion commits a pending marker and ordered outbox jobs with the repository mutation before hiding the Host from snapshots; ordered cleanup closes runtime Workspaces, cancels transfers, stops forwarding, clears references/history and finally removes the Host and its owned Identities, while independent Known Hosts trust survives.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/Events/HostDeletionHandlers.swift#L44-L78", + "version": "repo-lines-v1:sha256:e9fa55078c8b9b4195f07979e7af9514ac57c4de9dcb0de0519438c170f72e88:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI2MzBkNDEzNGFkMTlkMGIzMzE2NGM0MWIwZTVjZjM1OGYzNzNkZjYwMTdkODUyNjNmNzgwNjg3N2MwZjU3ZTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://Frameworks/TermindDomain/Hosts/HostDeletion.swift#L25-L35", + "version": "repo-lines-v1:sha256:58d3fc9cb36ce1384c05252e74825f2174425ff6b76baa3a51ccd04355efc805:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBhNWU5MDlkNTdlZWJjMjI0NTczMWI3MjVjNGY2NzY0M2Y5N2QzZTU0OWE0ZDRiMmYwYTIyY2RhZTIwMTE4NDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFkZDI0NDU4MmI2ZmIwM2QyM2I4NDE1YWJlY2QzNDZiMGM5ZjQ2NmI2Zjc1MmIwNjgxODljZTdlOWEyZGMzNTAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmYzVkOGVjN2Q1M2E5MTkzMzI1NjYzZGMwZTdjYmZiZDgzZTg3ZGY3N2UxYzk2NmI2NjU3ZmU2NTc4NDBlMGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift#L18-L35", + "version": "repo-lines-v1:sha256:62b7cc87ba41bb8ebf35a8df0659dec7c681fde07799ece53845b344cd2dbc47:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkODJmMzBiNDgzNjViYzQzNDRlMzFmNmEzNTBiMWFkNjA5ZGNhODg0YjM1MjI2NWFlZGJmZWMyNzIzNjEyMjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY2MWNhYzQxODkwOWE1ZGMyZTkzMjg4MzVlOTYwZTc5NDIwMzc2NjNiNDMwZWUzYTQxMjQxMzcwZmE1NDY5MGMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVkYTY4ZDk0NmE3Y2M3Njc0NWQ4NDI4MjY4NWVjY2M3Y2I1YTJjNDZkN2M2ZmY3ZWRkNDRlZDMyNzBjZDFkZDIifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift#L75-L139", + "version": "repo-lines-v1:sha256:6a6921d601ac1bd9258f1a97ffd4615e3557900bc40e20bc841c3627b3ee43b9:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiZjZiOTc3YTk5YjNlYWI1NjczZTA2ZmRhZmEwYWMzOTUwYzMxNzE5ZDhlNzk0MDNmNTU4Y2QwYjcxNWNiMDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJjZTZiOWI4MGE1MGI4NzAzYmMzMjM1Y2U3OTY5NTNhNGZjYzA0NTAzYThhMGY0MmRhMDUzNDMwNDc5ZmZiNzEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZiZDFmNDA4NmI3M2JhYTgwMGUwYTg3Mzg1NDQzY2I0ZDdmMWYzODcyYzVhYjVmMjRiOTY0MjA2ZTJmNjYzOTIifQ" + }, + { + "resource": "repo://TFMTests/RepositoryOutboxTests.swift#L209-L250", + "version": "repo-lines-v1:sha256:de89e296420359694c7de67ceebc7744f1e7483764649ce63375cc765c330ed6:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyY2YyZTQ3MmZiYWFkOTc3MTc0NDAyMmVjMGZmZDg2ZWEzMzc5MGI4YTFmNjNiMDRiMDczODQyZTUyMmRmZTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcxZjc3ZDM3ZTI3YzA4NTdkZWQzMjI4NjBhYmVjYTFmNDJmYTNhOWYyMzE0MzE0ODk3M2I3ZDVjOGQ4NGUyMWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ" + }, + { + "resource": "repo://TFMTests/RepositoryOutboxTests.swift#L277-L294", + "version": "repo-lines-v1:sha256:f087a02884ada9dc399a8dc83a4f235647ade09cbe87a4d0cc03a109cef3bf9f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAzNGQ5MzY3Mjg5ODBiYTk0ZWIwMTgxOWMwYmZiMTRiN2FiMTU5MDdhNzVhNzY3YTVhMjUwYmVlOGI2YWMwY2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM3YjA2ODAyMzliZjEyMDc5ZTkyOWYzNmRjNmE4MWYzMjY0MjE4ZWIwMDVjZTg2NmNkYTM1MmVmMjE5ZTU5MGMifQ" + } + ] + }, + { + "id": "claim_a8b755d3fd2740118de7f7c4bf29ee75", + "statement": "On mobile local Host deletion proactively closes live and unopened Workspace descriptors and cancels associated Assistant, transfer, forwarding and Metrics runtime work before requesting durable deletion and starting the outbox; remote Vault removal separately closes saved descriptors and clears local history. Desktop requests durable deletion first and then projects the Host and clears local history, with registered outbox and Host callbacks handling runtime cleanup.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L289-L308", + "version": "repo-lines-v1:sha256:63e3cb34ad0a6d1c4cee4ed6e3ccf865545b2728b1f2395572d0b9dca0375631:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwM2M0NWRiMmQ0ZTMyMDIzOGNmOTkzMWJjMDJlMTg3NzZlMjVmNmNmNGZhY2MwZjcwYmE4M2Q3MzYxYmJmYzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg3MDAzMDk2ZDkzZTMyMmY3NDZlMWZhZjQxZjY1NTcyMWY3ZDc5MmRkYWM3NDIyNzA5ZTMwOTg2MTgzZDA4MWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3MWEwNzY5OGM3ZjA3ZjI0NTY0NjVmYjA3MDVhNWNjMTM4M2U1NGU4MDYyOWFjYjAxNGEyYzczNzg3MzA0OWYifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L501-L523", + "version": "repo-lines-v1:sha256:04d6de73c3e6546f20ba5a5e31b40a0c6a0f1c7a158074ac4ffe3145f6a7194a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYyYmY0MThkMjk2MDkwOWQ0M2E2OWUyNzZmNWRmODc3ZDhmM2QzNzIwYTYzNDUxOGE5NGViOWVhNDA5MzMyN2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlkYWU1NGY5ZjkwYWVmNTQ0ZjBhZTQ5MDAxZjQzMmY4NTUxYzZiZjU0OWZlMWYxM2E0YjEyYTQ1MDVhYzUzMmUifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L603-L634", + "version": "repo-lines-v1:sha256:2b17d09836cd982b03982416cec87456a70533270eee87d5a3e6d89488bea78f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNhMjA4N2I3YjllNTQ5ZjEyNjNhNmJiMWY3M2JmYzYxZGFlM2I2ZGIwODdjMWQwYjFhODk3MmIyYTVlNzNjOTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxNzMxNDIwMjQzNGQ0Yzg0MjI5MGRkYmY3M2RkNDg5ZTM2YmI4M2UzYTIyOTY2MmI2YjI3MWQxYmNiYWZjMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5ZDFkZGZkOTM3OWY5N2QyNTllNzJiNGU3YjNhMTMxYmNkN2U0NWNiMGVmZGVjMDA2NmRiMTc3MTdkMzYzYmIifQ" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift#L1763-L1788", + "version": "repo-lines-v1:sha256:6f98578160eea0b5dbcc04123f099deb6402e4b0826fc28180b04437bc74b82d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4ZmRiMWE0ZmJiNDNlODMyMWI3MmU0Y2Y1ZmI2MDViMzJjMGRhMDlmMDVjZjQ2NjRkOTk1ZWFhYWZmZjk3YjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjEyM2FiYjcxYzNjZDlkMzhjMzA1NjA1MTVhMmUwNGNkMmE0MzliNGFmMmViN2QwYjc4NWFmYzA5YjBkMmUzNzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY1YzMzOTk5MzgzYjY1ODI0YTVkNDZjZjVkODc4MzUyMDJkY2QyNTZkMGYxMjNjNWYxNjJjNzQ2ODBiYTg3ZmEifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L256-L318", + "version": "repo-lines-v1:sha256:bda235f6436ad7ec5a918c8ad516f292203a30ed2735e16ee07668141edfefd0:eyJzZWxlY3RlZExpbmVDb3VudCI6NjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4M2E2MjQ1ZDczOTAzYzVmOWVlNzdjNjFlMjllMGIzYmZiMzNmM2Y3MmVlZTIwNDVlMWI4MWE5MjZhMGYxYmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyZjg3YjNkNjcyYmM2ZTk0MTA1NDlkYTYzZDBjNmUzYjk4NDRkOTE2YTkyNDY3ODllNzdmOTg5Y2RkODMyZWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY5YTVjNDU4ZWJhZGU4ODY2N2VlMTE3OTczZTEyMWViMmM1YmExOGMxNTFlYWIyZGUzOTRmMzhhOGMzOWZkMGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJjZjk5NjAzYzM1OGMzN2Y2MjMyZDA0YzhmOWFlN2RkYzlkNzBlYWY4NGMwY2YyNjVkYzNkOWM1NTg1NzViNjcifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L363-L393", + "version": "repo-lines-v1:sha256:de71cfc5d70c8197e0411e417521d0834d1b984ab96a02fc0f982e4e9c3aa7ed:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1MGQxYmQzNDkyNzgxNDM5ZWJjMjVmNGNkYzI2NTE2Y2QyZTc4YWRkOWYyZWIxNWJhOWFjMjcwNjI2MDIxOGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM2YjU5ZDI0NTYzNmJhNDBhNjIyMGI5OThkN2I4ODg5NGFjMmYwOWRiMDUzYjIxNjkyMWY1NzAxNDE3ODViZGUifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L663-L678", + "version": "repo-lines-v1:sha256:6def89de94cd728ecd8c553c53f5fee8a40e237e9d24cccaa78514811e430795:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkxNjBkNTI5NzhjYzA0ZjJmODhjOTA2YjgzMTIyODQ0NDZlZWZmNDA4ODkyMmZmNDVlYTMzNDQxNzdhYmU0YjkifQ" + } + ] + }, + { + "id": "claim_873a6f3d96c24aa88501ebc880f288e5", + "statement": "On mobile all-scenes background pauses sync, Metrics and outbox before a finite background task; only expiration suspends Workspace transports, stops forwardings, pauses transfers and expires Assistant work. Foreground resumes eligible existing Workspaces and process services, while failed initial selection needs explicit retry.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L560-L592", + "version": "repo-lines-v1:sha256:700f9e73e6acd2438498dfbe1d19a5b2614ce217164c821896645f67673103ca:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ1MGZiNmUwZThhYmY3YmNiNjdkODIzMzJjMmVlOGZlNzY0NzYzZDFlZjA5ODc4NWM3ZmM4Y2Q1Zjk2ZmRkOGUifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L647-L663", + "version": "repo-lines-v1:sha256:be3d7ace4663375024627ad072542aab75a2ee635ebaf20ee80f0a63f51e0d0d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZDY0ZTIzNWJjNzZlYTM1MDI3NmE4MGZlMGM1NjM0ZTYwZDFkZmUwN2FjYWQ4NTJlMTFhMWQ2MjkzM2ViMTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhjYWNjN2E0NzlkMjI5N2FiYTI4NWJlYWFlMThhZmI4ZWE3YmQzODEwMTkxNTA3MTIwYmRhNzVjNjBhYTBhZTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyMWFjNTE4NDc5MWIzNWNkZTM4MDkzNDU1MTVjMGFjMDEwZjA3MGVhZTAyMTRjZGY0MzIwZDE4NzI5N2M3MDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5ZjIwMmJmNzJkZjZiODUwNjM5ZmNjZmRiZjY4ZDJhMDdmZWY0ZjMzYThlZjQ3MWM0OWUwMDEwY2Y0YmRhYWQifQ" + }, + { + "resource": "repo://TFI/Features/Workspaces/MobileWorkspace.swift#L1097-L1101", + "version": "repo-lines-v1:sha256:a6a1d35a0ae426d90a8b6ecf552cd2c38bc70c537be939bbd2b6446fdc7d92be:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTJhNTAwYzZlZDg2ZWUwMTFjMTk4ZDc1NGFmNzI3NWM1MzEzMDUyZGZiOWNkYjIwM2E3NzEzYjllMzQ1ZDA5MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTZkYzM4MjAyM2ZkNDY0OGRiNDNmZmE2MWM1YmZiNDdmOWI5NmNlMjJmMWY0YjY4ZjFlNzNkZjc4OTE3ZWUwOSJ9" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift#L1562-L1628", + "version": "repo-lines-v1:sha256:69d3ff0350b2b3a989bd3c438ad24cff72aebf9f136636fded05cfd3e45f4c14:eyJzZWxlY3RlZExpbmVDb3VudCI6NjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkyNjg1Mjg5MWQ1ZjVjNTVlNjY5YzQyNjRiNzc3NzAyOTVkMDcwYTY0YTVlZDAyZTc4ZmJiYTJhMTk5NGFkNDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjczNzhlZjkzMGE2OGVlNWNmZTg4Y2NlMTZlOWYzYjkwMzBhNjExMzYwNzg2OTI0ZDM4ZGU5MzJlZGM3NjI0NDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJlNDgxZmNmYjBiNDc2Yzc5NGI4MzUxYjZiMjc3MGViNDE2NDlkNzI2OTViMzY3ZTFhMWNmY2FiN2ZkYTEyMTQifQ" + } + ] + }, + { + "id": "claim_0bb36663909342939a70f3e208ac12c2", + "statement": "ArchitectureBoundaryTests fail closed when production Swift roots are absent or empty, restrict mobile feature layers from importing or constructing concrete storage/transport implementations, and require CloudKit sync delegates to use shared lifecycle upload/quarantine gates rather than ad hoc change batches; these source checks do not exercise runtime UI or sync behavior.", + "evidence": [ + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L191-L219", + "version": "repo-lines-v1:sha256:4cf75e45396d3ce40ad529d43b445aec7b3c1f608c7411eb91ecb928ae5538c2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM5YjJkYjM3YThjY2FiMDIzMTkyOGUwZGY0MzcxOTc3ZWQzYzQwNzBkYTlkMDUwMjEzMzQyYmMwMmQyOGE0YWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ3NDI5ODQ5YmU0MTZhMzMzMmY5NTcyYmY1NTM5ZDkzOTZjNDEzMjY1MWE4MzhiZGRhZGIzN2IwNzg1OWViMmUifQ" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L286-L300", + "version": "repo-lines-v1:sha256:dac9ad32a391d5c088eab604491f77d23f251f388f98f7600b3eacb0cc289ff9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUwM2NiZTY3MGI2ZWRmM2UyNGQ0NWM4OGI0MGNjOWMwNzY1Y2U3ZmFkZTVhMzY3ZTZjNjJkYjA0MGMyYWE0ZDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L65-L106", + "version": "repo-lines-v1:sha256:cccba101be353c92ea23d68341dedab8bfc267dc2bc40693662576447fa784e3:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwMGI5MTQwMWVjNTRhNzEyZjI4MDZlYzA0NjE0MWVhZDIwODZmMmMyMzUxMTIwOGQyYmVhOGVmOWFhZjIwZWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ" + } + ] + }, + { + "id": "claim_ee396548b2c34c02b954712e64d5c530", + "statement": "AgentToolPresentation creates an approval-only projection of in-memory original arguments without attaching it to durable cards; it can replace host_id with a resolved host name and use an injected presenter for the remaining reviewable arguments, keeping long argument values out of the short action title.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L31-L61", + "version": "repo-lines-v1:sha256:c3531adf2bf4595f35038023e3d1254c504766128563071c72d81a1fffd5891f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2M2U0NDQxODAyNzNiNmE0NmQ1ZTFmMDY4OWMxNGVhNWVkODE3M2RhNTRkZDdjNjk4ZThlOTc4NDBmNDkxM2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc1OTQ4N2MwMmVkYjdjMmJjYWJlYTI4Nzk3ZDk5MjQ5ZDg3MGU3YjFlZTQ2ODk3MjJmODg0ZjcxOWIyMzFiOTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE4NDYxZTE0OWUzMGJkZTI3N2ExZmRjN2E4M2IyZTQ2NmQzZmRjMTZjZTcxZGIyNTE1ZTZkNGRkNTU3ODk4NGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMzMjdiNTFiZTIyYjk1YTc1MjkxNDU5YjZhM2JlNThhN2UyMWQ5MDA1NjNiYTljNTkzMjhjOWI2MTFkZTY4NzQifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L402-L427", + "version": "repo-lines-v1:sha256:a5b39195bcac0abf3e575e5176a6f2f201f0e10fb851b22b4ba13897647f86ab:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM0YmMwYzJlYjMxMDVjZjBlNGMxZWYyYjJlNTdiYjViYzY0YWJlNWRmOGJmYWRiNDRkMmQyMzBiMzQ3ODZiMWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA2ZmZhNDcwNWU3ZWVlMmY1NjQ3ZDM4YjA2Yzg5YjI3MDM2MzEwMTE4YzFmMzc3MDIwMGFkNzg2M2MyOTE0ZmUifQ" + } + ] + }, + { + "id": "claim_ece93976c37a44359339e07fb010a4f4", + "statement": "AgentToolPresentation renders local built-in result detail through decoded JSON and an injectable presenter or generic formatter but retains MCP's remote-defined JSON presentation; unsuccessful knowledge results cannot select success detail, and duplicate denial reasons are suppressed from the result detail.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L267-L341", + "version": "repo-lines-v1:sha256:bba4e19903c791d3ec9216963c8cfb64461dce6524c8ed2acae33e08b1300f8e:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2NDczYmRlOGY2OTkyZGFkOGY5YzhmYTczN2QxOTAxZGM1ZGM0ODUxYTVkZjE2OWNmYzY1MWZiMmY4OWY1NTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVlOGQ2NGFjYmIyYjdhOTIyYWM5Yjg4MjdkMWZjYmNjZjc4ODE3MThhODliNjJmNDQ0ZDhhZGM3NGQ1MzJhMzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ4YjY4NjllOTQ2MmUxMDkwNmQ1ZDM2ODY3ZGU2N2M1NTY4ZGJiMWY5YWMzOTRjYmMzNDE4Yzg4Yjk0MGJlMWQifQ" + } + ] + }, + { + "id": "claim_e84d43c0d6214cd1ae1151cd9e93ea5f", + "statement": "Assistant tool batch summary groups calls by tool identity, terminal state and knowledge action so mixed failures remain visible; bounded head/tail previews limit rendered output to 8,192 characters and 120 lines by default while preserving the full transformed text for Copy.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AssistantTranscriptPresentationTests.swift#L112-L124", + "version": "repo-lines-v1:sha256:a3c7c65253a20454e4f79ef9a232f0dbba082cc0971547b2e0b065fc742ad242:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlmZDA3NDBhYjE0M2ZiNWE2MzUyZWRiZDE3NTYzMzYzMWUxNjYxNzIzMWFlYjU1YmJiZjBjZGFmZmUyNjM5Y2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNkYTExZDliYmRkNzdkYThjZmE2N2IzOTQ5YTgzNGQ4MDM2MGE0ODdkNDBhNjlhZjhjNDUwNDZmMGU2YzBkNTkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjViY2Y1NjRkYTM3MDZmNmY4ZWNhODIxOWI2Y2M2MGZhMDU2NDM3YTkzYWVhMWI2NWNiMDY3NWNjMmViN2E3ODMifQ" + }, + { + "resource": "repo://FrameworkTests/AssistantTranscriptPresentationTests.swift#L166-L182", + "version": "repo-lines-v1:sha256:d7cdde9ffa85322d661132846d2fe8915ce6410018a4c97020d81540325bb79c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiNmE3OGU1NGU4YTZhMDI1NGNkNDk4NTQ0ZDEyMjIwZjk1YjYwYjY5YzQxNjhiNTQ5MGUxZmNmM2U0ODM2YjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmYThkOWVjMTA4YTA4YTMwYjQ3NjAxMTg0ZTIxYzUzOTNlOTAyNjNkODRmOWY2Y2Q3MTJjMmI1ZWZhZDc3YWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM4YWJiYWQzYjdhYWJjM2RkMmRjZDE0NGNjYjI0NDFiNzdmNWE4OTQwMDM4MjMzZjg0NmUxOTExMjIzYTY5MTIifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L12-L20", + "version": "repo-lines-v1:sha256:54c618593559e6b7fc8b3c12aea290fda7f4c4a04f5d0bf4834330859848beac:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTZmMTRhZjJkNzZmZmFkZDlkNDVmNzkwNWI3N2MyMTQzZjkxYzYzYTFjOGQ0NDQyMTM2MjM3YTQwZDI4OGUwOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMGE0YTc1MjExODFhYWQzODM2MDNjNzE3MjIyYThjNzUyODk3ZTI0ZjhlYjEwZGRjODhlNzY1NTY0MTJjMjY2NCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDlhYzY4NjAwMGMyOGEzYzhjMDM3YmVjZWM2N2EzZGU1NzM4MDU4ZmMwZWEzOTg3NzYxZjY4YTViMmFhNzExZCJ9" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L229-L260", + "version": "repo-lines-v1:sha256:b379b203502a5e103476383a2047628807bcc01f4d709be5ba41e5cc7713897e:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJhNjVmNWY1MmNiY2Y0Y2E0MDgwOTVlMTQ5MDY5YzgwNjUyZGY2MDkxNzJhMDc3NTVkNGMwODE4MTVhYjU5MWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYyNDMyNDZjZjI4NDUzNGUyZDlhMjkyYjA5MzBhOTYxODAwZTU0MTFjZThiZDNlYjk0NDc1NGRkZDZjNjA0NDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIxYjAxZTg3NjMyNjRiNzg5ODdiYzcwMjFjYTE2ZTdiNTJhNjYxMmQyNzNjNjc2ZmMwMjY1MDNjZDA4ZjgwNGMifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L343-L400", + "version": "repo-lines-v1:sha256:22a57ee8264d0d99fa0a45fd797535de26c96dfbc092bf9b9114749dba0bba9f:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJjZDYyOGM2ODYxOWY0ZWYzNmE1YmI1ODU0OWMyOGRkNmY3NzlkZGI2ZmUxNDY0YTdjMDY2OGNmMzkxZDE2MDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFkNGI4ZDEwYWM1YjQ1ZmUwMjUzNjQyODVmYTM1NWZjN2IyYTQ2ZjE1NDA4ZTQwYzYwODVhOGVjZGI3MDk1NTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYyMmY3ZjljNDNmMjFhNzk0MDI2NjQzMmVmN2YwODBmNTA3MjI3ZWI0NDJhNWJiNTAyYWUxNzQ3ZTZhZDdlMzEifQ" + } + ] + }, + { + "id": "claim_de10bb5bd41f4da2bb769fe7b8bdf31e", + "statement": "MobileBackgroundController invokes UIKit expiration synchronously on the MainActor before retiring a finite background task lease; it ignores stale callbacks, ends valid leases at most once even if expiration reenters begin, and invokes expiration for an invalid returned task without ending that invalid identifier.", + "evidence": [ + { + "resource": "repo://TFI/Platform/MobileBackgroundController.swift#L15-L84", + "version": "repo-lines-v1:sha256:2dfe8707a9753adbf3a9bc7fca6838f1028692a488062d86262f2ece6aa16f4d:eyJzZWxlY3RlZExpbmVDb3VudCI6NzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU2YWU3ZWJjYzI0Y2E2NWE4MzA3NjJiNTYyOTZmYTg3MTI4ODg5MGQxOTIzZTlkYzM4Y2MzODU4NzJkNDI3NjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFITests/MobileBackgroundControllerTests.swift#L8-L66", + "version": "repo-lines-v1:sha256:6ae00f644f06d81a0eb43f3dd2bc57732de40ec02e521559d77f4f9a6af70321:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4YzgzZDk2MmE2NDhmZWZkZTJjMjEzZDVkYjQwNWM5MThmNmRiMWU5MzdkMGI4MTMwNmU1ZDY2ZjI2Y2JkMmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgyNmNkODQwNGM5Zjc1MjhkODk1MDg3MzBmMTczMjc1M2JhZWZiZWQxMWFmZmI5N2FkNmRiNTllOWQ4NmE4MzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ" + } + ] + }, + { + "id": "claim_f2d4a4d008b74e8f8d87db3ecf481c73", + "statement": "When the last mobile scene enters background MobileAppModel pauses sync, metrics, edits and outbox, then starts a background lease; expiration synchronously requests Workspace suspension, forwarding stop, transfer pause and Assistant expiration, without waiting for asynchronous Assistant persistence or transport drains.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L643-L664", + "version": "repo-lines-v1:sha256:285418211661a8f06599619d932cfd0edcbc363a0c46a27597147118b0ffc0fc:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY2MTg5YTNmOTZjYWI4YzM1ZjZkODNkMWQyMGE2N2U2MmUxOTJiZDgxMjQ5MjI5MjFjM2M4NTMyYzE2MjlmZGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxNzMxNDIwMjQzNGQ0Yzg0MjI5MGRkYmY3M2RkNDg5ZTM2YmI4M2UzYTIyOTY2MmI2YjI3MWQxYmNiYWZjMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM0Yjc0YmRmNzgxODA1OTJlM2YyOTM1YzcxMzhlZmU1MDA0NzZhNjFjOTllMGZiZTcxNDVjYmRlMDBkYTU5MmEifQ" + }, + { + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift#L141-L155", + "version": "repo-lines-v1:sha256:0780c8d87faf6cccd18d3e4cd58b9155c4fe4a4baa3a11ca128b29f5be4061f8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU2ZjMxZTAyNWIyZDQ2MGNjNGNjZGY5NTdkNjkzMGM4MTRiM2JlZGRlZGQ5MDVjMjNkOTg1MGIxMTNmNTFiMDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2NTdhYTY2MTFhOTk2ZTA3NjllNjNiN2VhYjJmMzIzYTEwZTA3YTAxMmViYjk1MTBjYTdhMTE4M2U1MzQ4ZDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzNjFmYmU2YTJkNzg3MDAzYjc5NDliMDY4NTFjOGJlNDczNTI3MDNiZjAwYmZkYjM5YTVlZmEwZDAxYTdkNmQifQ" + }, + { + "resource": "repo://TFI/Platform/MobileBackgroundController.swift#L45-L84", + "version": "repo-lines-v1:sha256:ea3406fa5773e70a02548ed6337f82053c4e9639713f34e7042ec70b11e2603d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIzMGE3YjMwNzMwMWQ5Yzk4MWZhNjFmMjJkNDhkMTE3NmQzMjBhZjdkYmM3MTJmOTk4NzM1ZDc1NGE2ZTJkN2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA0YmUwZTMwOGMxYjUwMzI5MGNmOGNkYjQwM2Q0ZTFmYzQwYzFmOTk0MzdjNmRmNTk4ZjZiYjlkOWYwYzMxYWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + } + ] + }, + { + "id": "claim_8ef489be4eb24176999faae50ce560f3", + "statement": "MobileAssistantModel expiration fences new Assistant work while suspending, requests cancellation of captured preparations and all stored conversations before awaiting any conversation drain, then closes background commands and Agent connections; focused tests cover blocked sends, edits, plan implementation and ordering against blocked saves.", + "evidence": [ + { + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift#L115-L137", + "version": "repo-lines-v1:sha256:d884494a35ff53875a54b449f399714b9593269893ee6b39224ad026690f757c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ3N2Q1YWM0NmZkNzdmMWZlYWMyMTM1ZTlmZDAxMGYyMzk4MWQxYzBhMzMzZWJkMTNlZjE2MmUyYzZiNTg0MDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMzZDE2ODk4MTU0MTExNzUyNDc4NGZlZWJjNTY5NzIzNmYyZDk2ZDI2YWJmYjA2ZTIxYmM2OWQ4MzIwODY0MTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA2NTdhYTY2MTFhOTk2ZTA3NjllNjNiN2VhYjJmMzIzYTEwZTA3YTAxMmViYjk1MTBjYTdhMTE4M2U1MzQ4ZDQifQ" + }, + { + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift#L141-L158", + "version": "repo-lines-v1:sha256:5d7b7b28f33ec3976e03d613ce0916ef4e6630ba495c329ffb3513f1cc077a17:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU2ZjMxZTAyNWIyZDQ2MGNjNGNjZGY5NTdkNjkzMGM4MTRiM2JlZGRlZGQ5MDVjMjNkOTg1MGIxMTNmNTFiMDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNkNGJhYjUyYTNjOGQ3ODAzMDA0ODIwNzhlNGZkYzZhNzE5OTczNDg0OGI3ZmQwYmUyM2NkMzc5ZjJmNWIwNDEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2NTdhYTY2MTFhOTk2ZTA3NjllNjNiN2VhYjJmMzIzYTEwZTA3YTAxMmViYjk1MTBjYTdhMTE4M2U1MzQ4ZDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhhYjY4NmNlMzk2MmRjNDVmMTEyMDEzZDgyNzY4YTZmYzY0YWNjZTFmZjY4N2NhOWI3MzI5YzhlMGU5YTQ2MWUifQ" + }, + { + "resource": "repo://TFITests/MobileAssistantTests.swift#L480-L637", + "version": "repo-lines-v1:sha256:2adcf866159c2cb3d2ca31f286ce8b4de0aaa34e83f730d90aa07c7ec9f40090:eyJzZWxlY3RlZExpbmVDb3VudCI6MTU4LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIxNDAxOTk4OTFjZmJjZjk0ZjZiMTllMGEwMWYzYmU2YTQyNDZmODM4NDU0YTNhNTZhNzdiNjQyNzQ0OWQ4MTNjIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI1M2VlMjUxY2RjZGNmZTUxZTRmNTNhOWRmYTI0MTIzOGRjZmRjYjZjYmE3YTQxMGQ3ZjliZDI2NzU4NGRhZWY3IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIwZDZkNWRlOTFlMzdjNjIzMDQyYTllMTVlNTcwNjk4MjkxMGE4ZDFhNDM0YjhhMzE5OTQ5OTAwZjc0OTRiYjFlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIzM2VhNzEzMDlkNWI0M2I2YmUyMmU0MmZiMjlhYjYwMGEyMWQ2NDg3MjllYzEyM2I5NDE1YzkwNjMyZTA0NzNmIn0" + } + ] + }, + { + "id": "claim_2d1af0011b7d4417a6745a61faa74bcf", + "statement": "At desktop termination the app rechecks unuploaded remote edits and lets the user cancel; accepted termination runs an idempotent shutdown that fences new Assistant admissions, cancels captured preparations and stops stored conversations before joining their drains, runs MCP/SFTP stops concurrently, and closes Agent background commands and connections after drains while retiring other app-wide services.", + "evidence": [ + { + "resource": "repo://TFM/App/AppModel.swift#L724-L778", + "version": "repo-lines-v1:sha256:4088a1395f839fa08e6e42d1dc28faa30416dc463f43b9354b941ebf4e582043:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiNmE1OWU3Nzg2NmU1MGRiZDYxZjA5ZmQ1YWM2MjQwN2Q0ZGVlNjdkNGIyNTJhNDExYzRhZTEwZWNmMWQwNmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzODNlN2M2MmI5ZmI0ZGU3YjNjNTc3ZmFkNjNiOTYxMGRlZTcyNmI4NzljYzZjN2M5ZjYzNTljOTU5YWEwODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzNmM5MGE0M2ZiOWQ0NDg2NzI0NmE0MzY5ODk4YWZkOTFiOWUyYjM0OTZmMjU3OTg1YTk0MDFhZjY4ZDI1YWYifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L383-L415", + "version": "repo-lines-v1:sha256:0b48fe4bc83deb8ff877360273e4f5a25c243a95938f6b0edd9a23f7dcdeab91:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliOGJlZDVmYjA1YjU1Mzk2MGFiMDVlYTU4ZjI2ZDA5MGQ2MDY1NTE5ODkzZGNmOTllZmQ5ZTc1NGQ3Y2VhOGMifQ" + }, + { + "resource": "repo://TFMTests/AppTerminationTests.swift#L13-L160", + "version": "repo-lines-v1:sha256:5c3808df71f1f1675477a2e643e235ae655add9ac160ca922e25ae5ae9db2c16:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQ4LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJiYTY1OTc3NGZkY2U5ZGY1ZmRhZDNkNjAwOTNhZWY2NGY2ZjlhOGNiNTIyNDdkNjUyN2Y5N2IxZTYwOWJkNWM2IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ZDJkYjMzNzM2OTA5ZDMxM2M0MTE0NGE0Mzc2Y2U0MDk0YjJhZmU0OGI2MmI3NTY0NDEwMDNhNjUzZjgzNzNiIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlODdhMWNiNGE5NjU0YWJiMDdkY2I3OTE3NDgxZjZkMGEyODgyMzZlY2JhZWU2ZWIwY2Y4NDBmYzQzZDM3ZTc2IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlOGVhZjNlMWRiMjg0ZjZhNmZkNGUwNjZhZTJmYjY1NGFlNjhmZGZjZjNlN2U0ZGNhNGMyZGQyMTRhNDliOWQwIn0" + } + ] + }, + { + "id": "claim_a793871a225a43f9aa0901f559e00cdc", + "statement": "The macOS termination delegate replies exactly once after either asynchronous app cleanup completes or a three-second fallback timeout; the timeout limits the quit wait rather than guaranteeing completion of persistence.", + "evidence": [ + { + "resource": "repo://TFM/App/TermindApp.swift#L215-L241", + "version": "repo-lines-v1:sha256:b6a884010a3a8be3a6f465af0a85d69ba9541866b9e1ff17aab730481c270ef4:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZkNjgzYjc5NGVkOWI1NjQ2Y2Q2ZTZjMGEyYmMzYTk4YTFjN2NiYmMzMDUxZWZiN2E0NWQzYWI5MWI0MDRhZmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxYmJkYmE3MTE3NjI3OTU5NzBjZWQxMDc4MzhjY2EyMGY2OGJkYmM0OWFiODdiNTE5YzcwZmEwOTdiZGU0OWIifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L409-L415", + "version": "repo-lines-v1:sha256:da0dbd9ed3dbdbb6fb68c253c08ff49d722493631a12e7346149a8d0cf5efad9:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZTM3MDQyNjgyNDFmY2E3ZTJhMGM3YWYwZWIxYmViMTAwNGJkYmYyZmM4ZDE0YzM1M2YzZDlkY2U3YjdjMDhjMSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZjY0ODRlOWE3YWJkMGFiMjA3NTgyNzIzYzk5MjM5MzEyYjI3NDY2YTczNzg1ZDFkOGE3YzlkOThmOWUyZTc0OSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOWI4YmVkNWZiMDViNTUzOTYwYWIwNWVhNThmMjZkMDkwZDYwNjU1MTk4OTNkY2Y5OWVmZDllNzU0ZDdjZWE4YyJ9" + }, + { + "resource": "repo://TFMTests/AppTerminationTests.swift#L163-L200", + "version": "repo-lines-v1:sha256:23741adb64c4324b01aab2e7b6c1ff5b763b7be042588dafeb2e55ddb2254e05:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzYjI4MzBlZWZiNWU4Y2YwOGEyZmUwM2FiY2M3MjE4NTI1MDljMzkxNWI2MDEyNGQ1YWQxZGQ2ZTA4MTUyOGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwMWUwZTUzYzVjZjJmYjM3M2ZhNjdiZGYxZWIxODUzZmI5ZWUyMmVkOWUwZWQwZTdiMWQwNDFiOGYwN2Y2ZjcifQ" } ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/mobile-ui.json b/openwiki/.claims/architecture/mobile-ui.json index 4af9086a..c7fb633e 100644 --- a/openwiki/.claims/architecture/mobile-ui.json +++ b/openwiki/.claims/architecture/mobile-ui.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:5a57c9f6cd1214629ea2a75c3ba60386a70d5c2170cdb552f4dea473f0dde193", + "pageVersion": "sha256:1804e1b56dad3aff397363c08ac6c2af77f136d8fee3b4d6e8a2b80fa040f948", "claims": [ { "id": "claim_fbb919f62a2d4ab88aafcc4c1186731b", @@ -40,7 +40,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFI/App/MobileSceneModel.swift", @@ -160,7 +160,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift#L512-L544", - "version": "repo-lines-v1:sha256:b41d3de43fde9c50d0b478946d6263804791efe4519784713c872a1679a205dc:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" + "version": "repo-lines-v1:sha256:b0fa484bcb19ae7f887f203d3b438c9bccc7b5936706cd85d285e53c0f9b31d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" }, { "resource": "repo://TFI/App/MobileRootView.swift#L49-L74", @@ -174,7 +174,7 @@ "evidence": [ { "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L9-L180", - "version": "repo-lines-v1:sha256:fd1dfb3439ec991b16afb53f24aebc218d39fe34cb89144a79d75a4fa14cad8c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI2MTcxN2I0ZjY1MWU3NTQ5ZTUzN2QxZDg3ZGNmODNhNWRiYjkxODAzNmJjZDExMDRkYWM4M2QxMmNkNzZlNTYzIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJhMGE4ODZkMjJlMjhmYThjZmFkMzg2ZTUzMzlmN2JhNGFmNDEzM2U4NGRmMjU5YTYwNTNjNjJiMzI4ZjQ2Y2U3IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJiY2JlNmZkZjFkNDEyOTVmNjUwMmJhODFjNWQyYjdmZTdkOWZhMDFmZTU0NWQ3ZTZhMmFiY2M5YmUzMjRiOGI0IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJjMTNhOTQ2OThjNjNhZjM5MmJkMWI0YTZkZWIwZWI5ZjdmYzFlNWVjZTQ0MGM1OTU3MTdkYmEyYjM2ZGJjYTU4In0" + "version": "repo-lines-v1:sha256:81dac028bbcfd23568873033feb932627182fdd7dba20e6b887a28fc7cbd83ca:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI2MTcxN2I0ZjY1MWU3NTQ5ZTUzN2QxZDg3ZGNmODNhNWRiYjkxODAzNmJjZDExMDRkYWM4M2QxMmNkNzZlNTYzIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJhMGE4ODZkMjJlMjhmYThjZmFkMzg2ZTUzMzlmN2JhNGFmNDEzM2U4NGRmMjU5YTYwNTNjNjJiMzI4ZjQ2Y2U3IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJiY2JlNmZkZjFkNDEyOTVmNjUwMmJhODFjNWQyYjdmZTdkOWZhMDFmZTU0NWQ3ZTZhMmFiY2M5YmUzMjRiOGI0IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJjMTNhOTQ2OThjNjNhZjM5MmJkMWI0YTZkZWIwZWI5ZjdmYzFlNWVjZTQ0MGM1OTU3MTdkYmEyYjM2ZGJjYTU4In0" } ] }, @@ -198,7 +198,7 @@ "evidence": [ { "resource": "repo://TFI/Features/Vault/MobileVaultView.swift", - "version": "repo-file-v1:sha256:ccb0a1c9c7db91c0e853149a638c43c633f8a0fe41fca90a0e39e3566df7bce8" + "version": "repo-file-v1:sha256:ae5726d2034f41e3797ec0cd94009bac394fe28681d3b939aa0ba8dda3d8dd28" }, { "resource": "repo://TFI/Features/Workspaces/MobileWorkspaceListView.swift", @@ -248,21 +248,293 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift", - "version": "repo-file-v1:sha256:6062bded1a57eef49e3f62a7e11af7921c06564a64b679eb0347da7f09237aeb" + "version": "repo-file-v1:sha256:e9acaf0cde5c2fc6c94b78739cfcdd483f74e97266a4a750b1743e93b05de665" }, { "resource": "repo://TFITests/MobileAppTests.swift", - "version": "repo-file-v1:sha256:d2466771edf0d6d85ccbd8d5c6a8a7cd05521af153016478430a466085380ba9" + "version": "repo-file-v1:sha256:b2c528520ad5272155355404f91af52e490c6f17780a845d9e8a596c523484ef" + } + ] + }, + { + "id": "claim_948b20af62154ae88c06035a979951fb", + "statement": "Vault Host deletion delegates to MobileAppModel, which disconnects Assistant Host connections, closes matching saved and live workspace descriptors, invalidates edits and transfers, stops/removes forwarding rules, removes Metrics selection, requests repository deletion, projects the Host out of the library and starts outbox processing; an error reports failure without rolling back already performed cleanup.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L501-L523", + "version": "repo-lines-v1:sha256:04d6de73c3e6546f20ba5a5e31b40a0c6a0f1c7a158074ac4ffe3145f6a7194a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYyYmY0MThkMjk2MDkwOWQ0M2E2OWUyNzZmNWRmODc3ZDhmM2QzNzIwYTYzNDUxOGE5NGViOWVhNDA5MzMyN2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlkYWU1NGY5ZjkwYWVmNTQ0ZjBhZTQ5MDAxZjQzMmY4NTUxYzZiZjU0OWZlMWYxM2E0YjEyYTQ1MDVhYzUzMmUifQ" + }, + { + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift#L33-L41", + "version": "repo-lines-v1:sha256:29fe38e80d38f839f9350f937690a306a9c071692df9534840c43900050d0303:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYWE2NDM4MjE0NDZmM2M1YjM4ZTFkNWVlODg4ZDYyMGRhYzIzMzJlNjRkYjFkZDg1NjRmZTA2YjJhOGYwOWUxNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDJjYTExYmUzMjE5YjM1YTE0NGUzYzI0MmVmN2VmYTg3NzhiOTY2ZjdmZmExMTYzNzJmODJjMmUwOTAwZThkMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZDg2OWE2YjcxYTU5MDY3NjgxZmQ5MTllYmU1OGRmYzM4NmQzMjdhNGE2YmUwMWIwYjRhZjBiYWQyZWJhZjczNyJ9" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L487-L497", + "version": "repo-lines-v1:sha256:3de511e40bf5994c7b503811d139b77afba88252dd203b9b4ecbe93d69823f14:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiYTYzZDkzNmVmZmQxZTZiYjIxMjI0YjA1NmFmNjdiM2Y2MjNiNzNkNDVhZjhkN2FjZjc2NWM0Nzg1YmVhNjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkzNGY1ZjMxOWNhZjRjY2NlOWJkZGFiZTgzY2UzODFlZmQzYTE5YmVlNDFmY2I4MGM0MGQ4ODU4ZDM0OTI0OGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMwM2U1ZDFjM2QxMzE5ZGQ4Y2IwMjY5YThiODk2NGQ2NzE2MjI2MWM5MzFhOGQ2NWU0NzczYjNlNTFmM2RiOWEifQ" + } + ] + }, + { + "id": "claim_e30e975a20384af5bf5fa454ef4ed102", + "statement": "Host deletion cleanup also runs in registered outbox handlers; group deletion without keeping Hosts calls the per-Host path, while remotely removed Hosts close saved workspace descriptors and clear Host histories and Metrics selection.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L289-L308", + "version": "repo-lines-v1:sha256:63e3cb34ad0a6d1c4cee4ed6e3ccf865545b2728b1f2395572d0b9dca0375631:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwM2M0NWRiMmQ0ZTMyMDIzOGNmOTkzMWJjMDJlMTg3NzZlMjVmNmNmNGZhY2MwZjcwYmE4M2Q3MzYxYmJmYzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg3MDAzMDk2ZDkzZTMyMmY3NDZlMWZhZjQxZjY1NTcyMWY3ZDc5MmRkYWM3NDIyNzA5ZTMwOTg2MTgzZDA4MWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3MWEwNzY5OGM3ZjA3ZjI0NTY0NjVmYjA3MDVhNWNjMTM4M2U1NGU4MDYyOWFjYjAxNGEyYzczNzg3MzA0OWYifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L525-L532", + "version": "repo-lines-v1:sha256:846f167cc88f879c3f24575b32488276b1c6993d16e5adfee0a9cedc112cce7f:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYjQzY2Y5ZDU4Yjc4MDU3YzEwOTg5MmVjNDFjNTYzNDY5NTE4ZjE1NGEzNzM5MzBmOTJlMmRmZjlhODNmMDdjNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYzJjMDFiYmMwOTgxYzlkMjJkNzM1MmU4NjIxZTg2YTg0ODg5NTQ1Mzk3YzJmMjg2NGZiZmZhYzQ5ZTc3ZTY1ZiJ9" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L603-L634", + "version": "repo-lines-v1:sha256:2b17d09836cd982b03982416cec87456a70533270eee87d5a3e6d89488bea78f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNhMjA4N2I3YjllNTQ5ZjEyNjNhNmJiMWY3M2JmYzYxZGFlM2I2ZGIwODdjMWQwYjFhODk3MmIyYTVlNzNjOTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxNzMxNDIwMjQzNGQ0Yzg0MjI5MGRkYmY3M2RkNDg5ZTM2YmI4M2UzYTIyOTY2MmI2YjI3MWQxYmNiYWZjMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5ZDFkZGZkOTM3OWY5N2QyNTllNzJiNGU3YjNhMTMxYmNkN2U0NWNiMGVmZGVjMDA2NmRiMTc3MTdkMzYzYmIifQ" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift#L1763-L1787", + "version": "repo-lines-v1:sha256:c0fbcf17b1adca98ce3c7dccb8a75f0785243a7566f85815aa0f1feb7088c62a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4ZmRiMWE0ZmJiNDNlODMyMWI3MmU0Y2Y1ZmI2MDViMzJjMGRhMDlmMDVjZjQ2NjRkOTk1ZWFhYWZmZjk3YjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5ZjIyMjVkNWRjMWRlOWYyNzFmZWVmYWU5ODc2MTIyYmQ2MDY3YjVmOWUxMTlkN2U5ZGJiOGJiOTAyOTRmNTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjEyM2FiYjcxYzNjZDlkMzhjMzA1NjA1MTVhMmUwNGNkMmE0MzliNGFmMmViN2QwYjc4NWFmYzA5YjBkMmUzNzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg4ZmVkMDVhNzZjZTkzMTcxNDhiNGQ5YzE2NDM0MDhmNjI3ZjhjMGFiYTgxNTM1OWU2MjU0ZTliYTUzODU3OTcifQ" + } + ] + }, + { + "id": "claim_00e737b06ba042fc8535dd51256eac5f", + "statement": "The adaptive UIKit-hosted layout tests additionally verify native tab controller identity and compact label visibility, retained navigation and edit sheets across width changes, independent scene presentations, adaptive switchers, and save-in-flight feedback, while workspace restoration tests verify only a selected dormant row connects without reordering.", + "evidence": [ + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L131-L176", + "version": "repo-lines-v1:sha256:9ff692e72ae5bc6ec980c25f35b1b34b7926bd49ab3afaf1930f3316bdd7bf13:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRlYmZhYTQxMjcwNWM3ZGQ3NTg2ZTI4MjcwZTJiZmJiODBmMzNlZDMzMjRkMWVkYzZhZGVlMmZhYmY1OTc2MDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2ODYwN2ZkMGY0M2NjZDAzZDU2MzZhMWFlOWJiNWVmMTEwM2YyNmQzZDQ0OWI1NGMwNTEyOTk2NGQ3NjYxMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmNzU0NTFmY2MwMTA4Y2RmYjZjY2U0NGMxNDAzMTExOWRkNjdlODYzYmUyY2ZiZGY5MTA4M2UzZTc2MTQ4NGYifQ" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L198-L219", + "version": "repo-lines-v1:sha256:8b80778c5f0eff74192081d12cf4e08094098adf923c131b216d1a4c6879fd54:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM0MjY3MmI1N2QzZjFiNTFmNmQ4NTE4YThlNjZhYzYzYmNjZmI3OWNlYTFiMTViMjgwN2YzY2RkY2MwYjAxMzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVlNDYxMGU5MWNiYWJmNjg2YTcyNzRlMWZjMjk4MTM4OWE5ZDJlNTc5ODU1YzVhOTUyYjQ1OWJkODBmMjFkMTQifQ" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L449-L489", + "version": "repo-lines-v1:sha256:3653575cd1c4b5aa50cbfac98c46c62e83243f634a3e1139ac6c2732c2c81f14:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEyMTM5N2FmYjVlMzRhNWM1YzEzY2M4ZGYzMmMxZjViMTI2MzQ0YTVhMDlkZTMwZDhjOGRkM2I0MTQzN2YyYWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM3YzkzZDdiYzZjODdiNGViZjQ0ZmM3Y2E3ZjE5MGM3ZWI4ZGUxODg3NDFjZWNlNmI2MTU4ZjNhOGFkMTNlZTYifQ" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L532-L667", + "version": "repo-lines-v1:sha256:6f641a3f72f015787c8cf8e792ec1be9bec1a50ad88a88ffc91da19e065dc895:eyJzZWxlY3RlZExpbmVDb3VudCI6MTM2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI5MzU1OWE0ZjYyNWUwMzMxZmExMTQzZjAwYWRlMGZkOTk3YTg1MWU1MzhkOTU5ZGE0YTE1NTk1NzQwNjllMTVjIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIyYzY2ZGM4M2UwMzhiOWM2Y2QyMGE3ZWFjOTAwM2I5YTg0ZGMxOTc4Mzk2NjAyZTc4YmY4ZmU3YTk3Y2I0NTdmIn0" + } + ] + }, + { + "id": "claim_c9d6611b694d4c57a35c783d694f7014", + "statement": "Vault owns navigation into Keychain, Port Forwarding, Snippets, Known Hosts and History; Vault search builds cross-feature links with forwarded query for item matches and routes Metrics matches to its separate top-level tab.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileFeatureRegistry.swift#L50-L81", + "version": "repo-lines-v1:sha256:f4396e91b9ec448a100b829e1d4f124c4355e45bc4aef3218ce17c504cb804ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI0ZjYyOTRkZWVmNTliYzUwMTMwOWMzOTRiMWYwOWU4ZGM4NzRiNmM0ZTRjOWJkNmNmM2ZhYTY5OGQzNjQ2OTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIxOWQ3N2VhMjJkZjJjNzYyMWE2YTE0NWQ0NjhiYmFiZmE5MThjNjdiY2YzMGNmNTFiZTBkZjk4YWUxYzcwMDkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNhNGZkNGYwNDcxM2MyYWU1MzMxMjc5ZWVhNjRkYWNlMDg0NmRlZDU0MzRhMGJmMWU2M2YzYWFjZDUyZmZkYzAifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L314-L439", + "version": "repo-lines-v1:sha256:d9df5125147b279f04dbd4788a152eec8eb3f0d19132d19b6127c50af7825fcb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTI2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJhYWU3OTg2N2ExOGI4OTY0YmQ1ZTU4YTE1NWQzYjBkNDM0MTY3ZThkMmY1OWM2NTBiZjgwYWNlNzAxNjk2NjI4IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJjNTkxYzhlZDM5MGUxMDJjMGQ0Y2UxNDAyMzVhOTc1OTc3ZmNiNTUyZjZjZmIyYTk3MjNkMzE3M2EyYzM4NGQzIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJmMDMxMzUzMjFjY2YwZGNlNWYyZTA5OTlmYmJjNGI1NGQwNGZhM2I3NTBiNjY1YzVlZjhmMTkyMTY2NTkzYzFkIn0" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L516-L660", + "version": "repo-lines-v1:sha256:5715a91baaefebff6fe4cd93266c94265f6901d5636ece2f16d5b6954ff3bbce:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQ1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJmMDIwNDMyZGM0NzRhZjdlZmNjZWJjMGU0NWQwM2MyMWJjNzk2NGVjM2VmOTQxNmY4OTZkZTA1ZTZjNDgwMzM0IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIzN2E4OTVkMjFhNTdjNzI0NDg3ZDk1YTRkMzg2MDkxZjE3NGIwYWRhNGIwZTBmMWYxMjNiY2E4YTM1ZmUxNTQyIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIxMTA3YTA2NGVkYjM0ZDZhOTA1YTk2ZGI4YTM1MGQ4MmM5MDcyMzAwZmM2YjFlZDU1MWU2ZDQ5MDU4YzFkNmY0In0" + } + ] + }, + { + "id": "claim_795d34f15c0e4ded99e27d18e824b11f", + "statement": "Vault History list actions belong to MobileConnectionHistoryView rather than the Vault landing page: it projects all-device events with a 50 matching-row cap and device-name search, shows disabled-protocol events without opening them, deletes individual events, and clears the entire history after confirmation.", + "evidence": [ + { + "resource": "repo://TFI/Application/Workspaces/MobileConnectionHistory.swift#L76-L123", + "version": "repo-lines-v1:sha256:488a1079cc7f87c309ff776b53cc6443379f5af2e3f68dd3a2baf012bb1aba22:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU0YzlhNWMxNWQyOTA0NDZiOWM0N2Y0OThmZTUwY2NiYWY5NWExYzBkOTNlZjAxOTgxYzZiZDEzOGM5NjU0MDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhN2JkMmM0MWNhNzg3NjBjYzJjNDM4Y2QwNWIxMGZjMjZjNWJmZDYxZmQ4YTYwNGJmNjQ3YjgxZTY1ZmMxMTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L46-L140", + "version": "repo-lines-v1:sha256:e71709eafcf3da8bdbde97098cae7414aeae3a7d48267bf33ed9c64c1f755de2:eyJzZWxlY3RlZExpbmVDb3VudCI6OTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNmODhhMjRjZmVkZmU1ZTIzYTM1MDVjYTU4MDZhNDdlNDJjOTViMmZjNDQzMTRhMjA1NTcwMjkzNDE5YjQ4YWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJhMTQ0YTlmNjlkODllZjM2OTRlMzRlNDhkMzFkMDQ4MDJiMzYxMzRkMTk0MjI3NzFkMjc2ZjgwMThiMGQ4ZWQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ" + }, + { + "resource": "repo://TFITests/MobileConnectionPickerTests.swift#L124-L174", + "version": "repo-lines-v1:sha256:d9cdd264b984c5fa6dda30359ada80013c32b668389d0afea21a127bf4881313:eyJzZWxlY3RlZExpbmVDb3VudCI6NTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY1ZjUyOGNlZDhiOWZkYzBkMjg2MjZlYjJkYjQ3ZWI2NDg1NjQ2YWRhNzUwYjhkZmJjNDc2ZmY1NjQ4NmE3NjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMzNzMzNmYzZDQ2ZGE1MDU1MWJmN2IzNjRlOWU5MDc1NGYzMTFiZTQ1NDU3MWVhOWUzOGEyZTdmZDlhMDYyODkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhiYzk4MzRkMzRiMDNlOGQyMTNkMDBhYjdkMTE4N2JmYTNhMjljZmY1ZjdjZGI5ZGQwOWRiZmZjYTkwMzI5ZTYifQ" + } + ] + }, + { + "id": "claim_7561c7d7c2ae434081a61bd80351e950", + "statement": "Vault Host cards activate the scene's preferred terminal workspace on primary tap, while a capability-filtered context menu provides explicit protocol connections and separate edit, duplicate and deletion actions; new Host/editor presentation is scene-bound.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileFeatureRegistry.swift#L50-L71", + "version": "repo-lines-v1:sha256:c9ceba61fc95d5c217de3f2bade1d1eb111799bc7d8f430bd74dddaddd99d0c3:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI0ZjYyOTRkZWVmNTliYzUwMTMwOWMzOTRiMWYwOWU4ZGM4NzRiNmM0ZTRjOWJkNmNmM2ZhYTY5OGQzNjQ2OTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIxOWQ3N2VhMjJkZjJjNzYyMWE2YTE0NWQ0NjhiYmFiZmE5MThjNjdiY2YzMGNmNTFiZTBkZjk4YWUxYzcwMDkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdiMDA3YzAzODVlMDEzMmNkOTJmNjRmZDAxODg4MjZkMDFmMzc4MWNjNjU3N2I1NWZiMTY3YTQyMzZhYjg0NTcifQ" + }, + { + "resource": "repo://TFI/App/MobileSceneModel.swift#L78-L81", + "version": "repo-lines-v1:sha256:72699cc8d65faa86d18075b1f1cd656984a00050309defa8987bd8d9c33a61bf:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2M4ZDg4OGJmZjUzZTYwYjQxNmE2ZGYxOGRhYWIzNmYwM2UzOWQ4OWJhYWIwOTkwM2Q4OGVhYWZmZjc1NGRkZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiODM4ZGEwOTQ3NGI4NTc4N2I3ZmJjMmViMWY0NTNmN2UwYThkMzJhZWE1MWRhNmFiZTlhZjZjMjgzYjJlZDYxYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDQ5MTdhZjFhZWVhNTY2YzIxOWQ2OGY2OWM2OGEzODIzNTdhMDgyMDI1ZGM5MWQ3YWY3Yzk3OWQ0Zjc0MjAwOCJ9" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L16-L44", + "version": "repo-lines-v1:sha256:3fadb0523a363711191ac025b2a2be70dca696c5d1189ef587e89c1687da7ecb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZkZmUzZTM2OTM5MTg5ZDg3NGU0NzlhZjFlYjJhNjg1OTY4Y2M1MDg0YTM2MDYwMTcwM2E3NjU2ZmZmYTdjYWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNhMGQ4NTMzZDViNDMxOTM5YTVlZGI0MzY3N2Q3NjYyYTU0NWM2MWIxNjNlOWI4MzFjZWI3ZGZhZGRmYzVkYzYifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L767-L834", + "version": "repo-lines-v1:sha256:a07e0e245c8f4f406d84b4fef5566cdc859fd6f1122354eb1b71ee859d8c361c:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyMTExNDcyZWQ0MmE0NDkxZjc5OTQ0MzNjMTM5ZTBlY2M3ZTczZmZhZjI4ZTZlYzIzZDI3OGIyMmRjZmYyMTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkzOTgxNDU1ZTQyYTZiNzRiOWU5N2ZiYTY0MjM2NTQxM2Q4YTNlOTJkY2JlNjU5NjY1ZDUyODA0OGExZmU0MjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzYzUyYWM5YmUwN2MwNzljNTRhZDgwOGMzNDEzNDMwMjFmYmM4M2NiZDVmZDk2ZGNlZTk4MGY4YTI2ZTU4YzMifQ" + }, + { + "resource": "repo://TFITests/MobileVaultFeatureTests.swift#L33-L68", + "version": "repo-lines-v1:sha256:1ea05d84f5bbde850a612da2de508f4c2c278de3fd5ce0ee1710e12e4ecfa25d:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgwNzEyOWY5ZDgxMzg1NTc0NWI4NDZhM2Y5MDNhZDRlOTk2MmIwMTJiMGVmZjdhNGM1MjI0ZTAyNzVhZDBjYjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI3OTE4NTE4YmYyODg1NTFhYWVkOGRlMzU5YTQ1NTQwNWUxOGMxYmRjMjEyNDgzMGI5NjA4ZmJjMjU0MGI2MWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE0YWIwODlkMDRjOTQxYmEzYTg2NGI0ZjEzODE5NDM5ZmNhZjk1MTgyNjk5MjdlZTZkYjQ3Mzg5OTNjNDc2ZWQifQ" + } + ] + }, + { + "id": "claim_598502d30fb9447fb9eafb18fa90335d", + "statement": "Vault Host sections preserve nested and empty groups and persist collapse state in the library while search still finds Hosts in collapsed groups; group deletion can either ungroup retained Hosts or delete the tree's Hosts through the app deletion path.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L525-L532", + "version": "repo-lines-v1:sha256:846f167cc88f879c3f24575b32488276b1c6993d16e5adfee0a9cedc112cce7f:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYjQzY2Y5ZDU4Yjc4MDU3YzEwOTg5MmVjNDFjNTYzNDY5NTE4ZjE1NGEzNzM5MzBmOTJlMmRmZjlhODNmMDdjNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYzJjMDFiYmMwOTgxYzlkMjJkNzM1MmU4NjIxZTg2YTg0ODg5NTQ1Mzk3YzJmMjg2NGZiZmZhYzQ5ZTc3ZTY1ZiJ9" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L441-L513", + "version": "repo-lines-v1:sha256:456cfc3a140a45f1536ca95bdf7f347179c129b50a48912515b2528bd411b911:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRlZjlmZDM3NWY1ODkxYTc2YTE5Mzc2YzI0NTZiNGYyMzM4MmVjODJkNWJiNTkzMDEyZTNmOWZkZDNhY2YzYTYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJjZmUyOTY2MGQwMWI1MTk0ODgzMDkwNWE3ZDQ1ZGQ0NDUzMGNmMWMyNGE0ZTk2NWI0OGMwMDY1OGQzODBmYTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiODlkNTljMjE3MGEwZWFmOWY0NDc2YmVjMjRjOThlYjdlYTRiMWNlYTY4ZDQ5MmQ2OGNkNzAzOGZkNDE0YmQifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L663-L760", + "version": "repo-lines-v1:sha256:0a7beae712af175e3c91d44d76c441c66a033e3dd2e46f0923329b0aa7773cf9:eyJzZWxlY3RlZExpbmVDb3VudCI6OTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhZWI3OGJkZmVlNGM0NWMxNGZhYmIyNGE5ZjI4MDhjMGZjMDlmNDdiNjc2YjZhODJmMWM4MjBhYWFlNWJjZjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcwN2QxMWQxNmI4Zjk3OTFiZWRkYmI4ZjYxMDhhMjE1N2Y2YmZhMzUxMzhhMjZiZDUzODQ5ZThhYmU4NjkyMTIifQ" + }, + { + "resource": "repo://TFITests/MobileCardTests.swift#L113-L148", + "version": "repo-lines-v1:sha256:780d54c2aa93b53dd841b7eaa1bf2ef298287443ecf655933e16024be9a46172:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiMjBmMWIwYTE1MjBlYjU0OWM1ZTQxM2NjYmQ3ZjRkZmViYjAwOWQzNDNhZDM1MDM3ZGUwMzBhMDgzNDlmMjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVlMjAwZTI0ZDg0M2FjMzhiYjkyMTc2ZjRlMzZlOWEzOTNkOTM4ZjJlNGFhYjU0ODFhMzAzYWU2YzQ4YjQwYjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU3MjBjMTRlZjEyZDI5MGRlYmExYzJlYjkyYzYwOTYzMzBjNzkzZDcyOWJmNzRjOTRhNzUwNDY4MzU4NGNmOGIifQ" + }, + { + "resource": "repo://TFITests/MobileVaultFeatureTests.swift#L101-L134", + "version": "repo-lines-v1:sha256:6768055581f07f3dec6f401580626fe226d088bd5546fcd882b3e72d40b26c20:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmZmYyODVjMjI3N2YyNTA4NWMwMGJmOTc3OGQ0OTgzMjdiZDFhMDBjM2NiOTM0NmU3YzBkZDliZTNmZDE5NWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA4NTc1ZWNhZWViZWYyZTk4MzQ1MTBhMjE3NmE1OTBkNWU1ZGZjZWFiZjE3NThjNzBmNzg1N2UyNTA1YTQxZWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY5ZjNiNTgzMTZkZmQxZDVkMDg5ZGVlM2EyY2Q5ZDEzMjFiNGJlZWJmNmEwNGJmY2E1MWQwMjViYWMyM2E4ZmIifQ" + } + ] + }, + { + "id": "claim_557f948137274e30b94ce749a4581d84", + "statement": "MobileActionCard gives the entire shared minimum-height card surface the primary button action and puts secondary actions in its context menu; mobile card surfaces adapt glass or solid styling to iOS availability and transparency/contrast accessibility settings.", + "evidence": [ + { + "resource": "repo://TFI/Design/MobileDesignTokens.swift#L3-L15", + "version": "repo-lines-v1:sha256:9f66d7f273710c4d50f062728e5df6c899c58d89f5d9ddd241c7c92f90e87a40:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc2M2E0MDYxMjcxNjkxZGY5ZTZlNzNhNDc2ZjY2MGZiNDAzZmE3OGYwNDBjNDVjZTBhMmUzM2ViZmFlYmNlMjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmODVkNWEwZjU0NTg4ZWEyNzdkOTIyZjAwMzZjOGFiYjMxNDg0YzQ4Y2UwNzY0MjZjMjdjMTA5NWVmZDE4OTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFI/UI/Managed/MobileCards.swift#L58-L157", + "version": "repo-lines-v1:sha256:2cf99d837b00ff9aba65d956325ef8f04eed66070070cc7089c591356a29cacb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAwLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIxNDI2MzcyZTIyMDBmY2RiODYzZDZlZDgyMzkzMzc1YmI2YzEzNDdmOTgyZTdiNzhmOWFhZmUyZmE4M2VhN2U3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIxOWU3NjM1NWNmMTE5OTQ4MGMzZjk5ODM2YjE0ODZjODQxZDg5MWZhYWQ5MDRjNjA4ZTA5MzAyMmQzNzU3YWVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJmNmY0ODkyZTI3MzAwZDVkYjkzYTg4MzM1Nzk2MDEzYWM1ZjgzNjY5NWE4NWJmYmZjNzY1NGMwNmIzYTA5ZjllIn0" + } + ] + }, + { + "id": "claim_349600096eb247f68a37cca1e4894a89", + "statement": "Mobile Host cards display at most two tags without changing standard card height; card and forwarding-card layout behavior is covered by measured-height tests.", + "evidence": [ + { + "resource": "repo://TFI/Design/MobileDesignTokens.swift#L3-L15", + "version": "repo-lines-v1:sha256:9f66d7f273710c4d50f062728e5df6c899c58d89f5d9ddd241c7c92f90e87a40:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc2M2E0MDYxMjcxNjkxZGY5ZTZlNzNhNDc2ZjY2MGZiNDAzZmE3OGYwNDBjNDVjZTBhMmUzM2ViZmFlYmNlMjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmODVkNWEwZjU0NTg4ZWEyNzdkOTIyZjAwMzZjOGFiYjMxNDg0YzQ4Y2UwNzY0MjZjMjdjMTA5NWVmZDE4OTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L776-L805", + "version": "repo-lines-v1:sha256:b450a12dafd975a16cff62a0e87313c4ed0135ae1696c5bf1946ec4099b4af1b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzMzhmZDQxYzFmNWI5ZWQyYmY4YTQ3N2QxNWQ3ODYyNjVmODE4MmZiOTA3N2QxMzM3Yzc5NzM4ODU5M2I2YzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY2NjgzMDMxZjE3ODk4NTBhNmU4M2UwNmEyMGM5YzFhZDNmNzM5ZjcwYWRjYTZlODQxM2M3YzBmMTgzYmJmNmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ4ZTM2YTk5OTllOTZjN2FmZjllMDIxNmRiZDcwMGIxMGNmZDVlYjM0ZmIwZGMyNjI4OWRkZmIxZjIxYTk4NzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE0NDVhM2ZjOTQwNWI1YWZlMmU3N2IwZTQ4MzJkZTQ1NjY5ODM0YjRkYzA2ODBhMGZiZTBiNWY1YzM5MjQ4MmYifQ" + }, + { + "resource": "repo://TFITests/MobileCardTests.swift#L49-L85", + "version": "repo-lines-v1:sha256:7992d7f52bb45d306c7c6d3e7005c7ee0c6505ae4280e37208e49b027818dae9:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY0YWEzZWRjOTBjNjc4ZmVhNTgwNTlmMTExODRhMzk0Nzk0NTc5ODNlZmE1OWMwZmUxNGQwMzM0YTc3ODBkMjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBjMjI2NjIwNTE5ZDBhODVkM2NkOTQ3Y2M2YTc1ZTY5ZWEwZTVmZTNkYjY4MTBhN2Y1MTI0OWNhMWE2Y2VlODkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNkNmNlNjA2NDBhNzAyZjg1YjM4MzgxZTc0OWQzMjc3ZWJiNTdjYTVhNGMxMDNhZTYzNGFmM2UxYTE2ZTU4M2QifQ" + } + ] + }, + { + "id": "claim_b09a9485e6b24bf194f6e22600204788", + "statement": "MobileHostEditor keeps a Host and Host-custom credential draft local to the sheet, uses shared presentation sections with SSH/Telnet-specific controls, validates host, enabled protocols, ports, identities, proxies and environment before Save, and delegates durable Host and custom identity persistence to HostCustomIdentityDraft via the library.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/HostCustomIdentityDraft.swift#L229-L289", + "version": "repo-lines-v1:sha256:f4da79b6a808be0ecc0884ee5fed0550c9f7505698591cd214d062e4e35c818f:eyJzZWxlY3RlZExpbmVDb3VudCI6NjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlMGY0M2FlNGYyYzcwMDNjZDk1ZTc3ZDc0NmQ1YjNhMDE2M2U2MTVlMzVhODEzODI3Mzg0NGRhM2VkM2ZjOWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ2ZjM4Y2E4YzJjOGYzMGZmYjkzOTZkYWZmMzdhMGM1YmNmYzI3NjcxMmI1YjM3NzM0NzM0YTg2MTNlZTEzMDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/HostCustomIdentityDraft.swift#L6-L10", + "version": "repo-lines-v1:sha256:7dbe0b61f6e150c1022868b905224e61ced4ad7f0749a5e41252fc1bcae14b9a:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2I3ZmZhNTU1MWMwZjNjNTUwZmE4MjkzODNhNmI1MzI2MWM2NmI5MGQ5NTU3ZTNkZDg0NzFhYzMzZDk3NzcwYSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDQ3NTE0MGUyNmU5YzVhMTcxMWQ2NDQ1YTE4YjdmNGFlMjAyMmY5OTNlZjYyODQwNzU1NDMwMWI5NmUwZGMyMCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiY2RhMzEyZmUxNTU3MDQzOTMzNGJjOTAwZGI0NDI5NTM2MmYzODlmNWM2ZWQ4ZTQxNWI4MjJjMGY3ZjA0MmM0OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMmNiMGE2MTZmN2FjODVkMDRhNjg3ZjFjYTM1YjM1MGIyNWRiYzg2Y2JjMWVjMGQ1ODUwOTliMjliOWU0ZDlkYSJ9" + }, + { + "resource": "repo://Frameworks/TermindPresentation/HostConnectionFields.swift#L6-L110", + "version": "repo-lines-v1:sha256:29c7efc3b61247d2d68e1e17d4db6c249d314d57e82f21af61c33b1061cd21c9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJkZGRiMTRiMzgzMzAzNjRhZDk3YmViODY5NWVmYzMyYTFjMjkwZmUyYzk3Y2EwNjAxZmYzY2QzNzhjYTVmMTI5IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJjZGEzMTJmZTE1NTcwNDM5MzM0YmM5MDBkYjQ0Mjk1MzYyZjM4OWY1YzZlZDhlNDE1YjgyMmMwZjdmMDQyYzQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MSwiZm9sbG93aW5nQ29udGV4dEhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIn0" + }, + { + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift#L27-L85", + "version": "repo-lines-v1:sha256:a6e29baaf15f74202edf721730ed24039c57ae6838fe140b2b4e362d091ee07e:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZlMzA0ODhhNDJjZmI4Y2M1YTgzMjM2YjRjNmM0YmE4NTg3YTY1ZDlmNWZhNDUyZGE4ZjY2MzhkMjhjNDZlYmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkNmFlZmJiYzE2NGE0NjBmMTYyMDM3M2FmODUzYWI0Y2I3ODUwNTk3YjY5Y2UxNWQ0NGI1NjI4NjdjNDhmMGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAxZGQ3YmJmYzM4MTU4YTI1YWNiMmUzMWU5NWZjYjdkYjFlMDRiYTA4ODg3ZDBhZWM2ODVkMzNhNDQ2Y2E0OWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM2YWU5ZDE5OTIwZjMyYWQ5Yjk0ZWI3ZmYzNDk4ZWM5ZWY4ODBlMDEwYjZkNWUyZDgxNGQ5ZWQ0NmNiZTdmN2MifQ" + }, + { + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift#L85-L268", + "version": "repo-lines-v1:sha256:1791485dbc760b6a70abc050298fbc5fe8fc27cba0b5980e353fa9e6c1bbf1c2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTg0LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIwZDZhZWZiYmMxNjRhNDYwZjE2MjAzNzNhZjg1M2FiNGNiNzg1MDU5N2I2OWNlMTVkNDRiNTYyODY3YzQ4ZjBhIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI4MWE4OWExMWNlN2ExOWFjNDBlZmU5NjNiMzFlY2FlYjkwZmNlYmYwNzczZGRiNDdlZmYxNTg1YmViNGI0MjU2IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI2MjNhYmZhNzc3ODY2M2M0YTg3NzkxY2QxZmE0MTk5YzlhNTNiNWMwZDI4NTYzZWJkMDQyNjU0OGRkNzZjOTM4In0" + } + ] + }, + { + "id": "claim_20dc21354719402395bad742e0b3bfdc", + "statement": "MobileEditorSheet owns dirty-discard confirmation, async save progress, error feedback, interactive-dismiss prevention and in-flight task cancellation on disappearance rather than allowing a failed save to silently close the editor.", + "evidence": [ + { + "resource": "repo://TFI/UI/Components/MobileEditorSheet.swift#L13-L108", + "version": "repo-lines-v1:sha256:538f0ee547a19e0e7559fb08ac488e9345fab5ce2baad4deae9c274fab19f0d3:eyJzZWxlY3RlZExpbmVDb3VudCI6OTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBhN2M5YTk5NTdiOThhZWU4MWNlMmQ1NDhkOTI3ZTk3ZjFjZTE2OTllYjAwMGE5ZjY5Mzc0OGY5ZGExMTYyZDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJiZmVkZWI1YzcxOGQ0Y2VlZjQxMzViMDE2NDNlYWM3ZDUzMTY4YzRkZTc3MDJmMjZiZmQwMTQ1NjNhNTUzYWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + } + ] + }, + { + "id": "claim_e8683bb3d0df4a429b9b4fd078d0689e", + "statement": "Vault's Known Hosts is a separate card editor for SSH host-key entries: card tap edits, a secondary action copies the fingerprint, confirmed deletion uses the known-host store, and saving validates through app.knownHosts; hashed entries do not expose a recoverable port field.", + "evidence": [ + { + "resource": "repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift#L6-L86", + "version": "repo-lines-v1:sha256:c95a7ee49b5428df46595142db320a1c9b94635eb0003029a58ed9d7e75aba82:eyJzZWxlY3RlZExpbmVDb3VudCI6ODEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3NzM1ZGU2NzdlNWVmZTVkYTI5NWUyMGYzNzk0Y2M2MDM0YTI4YjJlZGJiODc1ZDZiMGRiZmQwZTMxNTNhZGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNmYTE5ZjJhYWYyNmU2MjE5ZGY4MmM0M2QxOGI1MmU5OWI3MzhlNTIyNDJiMjE4Y2VhZmEzMjg1NThkNGNjZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFkZTY3ZmY5NzJiMWUxZDk5Njc0OGE1ZTczYjM2NmY5MzU4NzZiMDE4MGU5NmFlYzI4YWJjM2UyZGVmZGQ1OWMifQ" + }, + { + "resource": "repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift#L89-L154", + "version": "repo-lines-v1:sha256:ba61694ac7cb6511e2145c7bb97834acf099353fe88d3e6df2569e52e66faa65:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3OTJkZjUxMDBhY2FmNGJjZWI1YWMxNDljZDI5ODEwYzFhNTc5YmU1OWIxNjIzMWVhMjA0NDgwY2M2Mjg5OTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L585-L594", + "version": "repo-lines-v1:sha256:61a53c7427686f015a2a0e178754b73c6cace5d3a8f133c0ec322a0f059d97ae:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVkODVlZGRlZTIzMDBkZGNjMTY1NGI5MzE3OWQ1M2Q0YzExYTZjMTZhYThlZmFjN2IxYjcxYmEwMDRhZTg5MWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVkNmEwYWJkNWM1MDRmMzM0OTMxZWY0ZTY3YTAzMzBiZWIyYWFmYTNmM2UxZWNkYjhmYmRiNDYxODhkZmMwMmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ" + } + ] + }, + { + "id": "claim_e4fabb6e59b94e1d849094e9db9fe01d", + "statement": "Host duplication creates an independent Host ID/name while removing references to Host-custom identities, so duplicate actions do not share Host-specific secrets.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L534-L549", + "version": "repo-lines-v1:sha256:0d01fc0bc960d8e9ede9793b66394cce8ffdd3aa5d778fa6d9b366973c979fa2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImEyZjRlZTNjMTI5MGIyZDBiYjE4YmFlZDJmNDE0ZGJjOTk1ZDExNDE3ZTYzYWFkZGNhN2MzOTFiNjMyZjA1ZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFkYjQ1OWJiNzNkN2U1ZTQ2Y2YzZjg4ZmQ1NGFhNjQ2N2E5OGI0Njc5YzU4MGFhZDc5MTdmZTFlOGUxZjcwMDUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3NzRiNTU3ZTIwZjFhNzM4OTJjMTc2YjJhYzQwODlmY2I4Mzc1MjY1ZDgyNjQwM2Y4Nzc1ZTQxMjYzNzZhYmIifQ" + }, + { + "resource": "repo://TFITests/MobileVaultFeatureTests.swift#L70-L99", + "version": "repo-lines-v1:sha256:7f1eee07fcdb08cacdb0aee8ead03028da5d588ec619947fbd773d04a13b5e10:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI2OTllNGJmZDIyN2YxOTYwZWI1MWY3ZTlmMTU4NTFmMWMwOWQ4NWNjNDkzZWJjN2E1MDRmMGQxZTY2NmQ0ZDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM5YjJkYjM3YThjY2FiMDIzMTkyOGUwZGY0MzcxOTc3ZWQzYzQwNzBkYTlkMDUwMjEzMzQyYmMwMmQyOGE0YWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2N2IyNmY2YWVhZGY4N2Q2NWViMTgzOTUyZGY5OWRmYzcyZjc2YzI1ZDFlYzI0ZDg3OWNjNWFkNmVmOTkxMDMifQ" + } + ] + }, + { + "id": "claim_94adfa83eff944aeb787b40bd5c0e375", + "statement": "Workspaces Recents filters local events into a maximum of five distinct Hosts only when no saved or live Workspace is listed, while quick actions publish up to three openable Hosts from the same local projection and re-resolve terminal capability on activation.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileSceneModel.swift#L88-L105", + "version": "repo-lines-v1:sha256:14eed48b39ce10f59fee0068214b04db5f0f481e900b4ed0a90dfc1d866798a3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ0OGI4ZWMyMjc0MGQ4ZDA4YjAzNDZlMmE1OGE3ZTMwYTEyNTMzMDNmZTU5ZTJjNWE4MzE4NjY0Mzg1NTI0M2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNmODZjOGRkOGIwOGUxYmE0MWEwYzhiN2Y0NmQxMTBmYzFhZTk3YzRiMzk2ZDNlNTk3YThiMjk1Mzg2NDFlMWQifQ" + }, + { + "resource": "repo://TFI/Features/Workspaces/MobileWorkspaceListView.swift#L183-L190", + "version": "repo-lines-v1:sha256:aa1856158ce2fbaea83b75c9e7e49f3c80ccec56b7b0b041591862872beaf4d7:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDc3Y2I1ZjRhYmRiZjgxNWE0YTZiMzUxOWE5ZTNlNmIxM2Y0Nzc4NTg0MmFlNjQ2ZDEyZWQ0NGQzOWU0ZjY5ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYjQxZjVkZjVhNDQyZGQwN2Q1ZWVjMWZiOTQ2ODMwMWMzZjQ3YzRlNzIyNGI0YTU0OWJhYzMxMmEwMmQwYmUwOCJ9" + }, + { + "resource": "repo://TFI/Features/Workspaces/MobileWorkspaceListView.swift#L37-L53", + "version": "repo-lines-v1:sha256:5610fadbc23981d1bcdcb4c387bfddac5cbe7d4071c26c5c3089adcddcad8ebe:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwOGZmYzFmMDllNWEzZmNhMmI0MDE5OTIzNjY1Y2I0NjBhODA2NjIwZWNlYWJmODRiN2IwNDYyZGYyYmM3MGYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIwZjFmN2Q2YjE4ZDNiZjJmMTM2ZjgzZWQ5ODhmZDc4MmE1NzgzMWQ2MGZiYWU3NDY1MjBlNDM2MGViMjQzMjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkMjAyNDczN2I3NzRiZGVhNWE4MTA1OWI5MzQ1YjhiMWJlMDUxMzg3MWYyNzUxNWFhNGQzNTFiMDJkMjU4YzMifQ" + }, + { + "resource": "repo://TFI/Platform/MobileHomeScreenQuickActions.swift#L68-L85", + "version": "repo-lines-v1:sha256:5182cc7b295da108c285936161ef8d3a015b3bfa4f8278b2cc65c2ccffb6a220:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY0YzRiMWQxNGU2YTFjNTc2ODk0ZDhkYWUyMmViNTQ1YWFkYjY0NDU2Mjg2NGE1ZmVhMWQwZjU4MDYxNmIxNzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ" } ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T02:40:53.789Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/module-map.json b/openwiki/.claims/architecture/module-map.json index c81cc27b..54626cf0 100644 --- a/openwiki/.claims/architecture/module-map.json +++ b/openwiki/.claims/architecture/module-map.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:e3b8050ae27e288e93f95da211d5b461d2d1fae6ba7afce02d15c9a8937a9b24", + "pageVersion": "sha256:bca96ac65afae5b3c664cba51d37fdd56b978934b1d494d475e95d057226bf98", "claims": [ { "id": "claim_34230e88036241baad093fb8de5bac8e", @@ -8,7 +8,7 @@ "evidence": [ { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" } ] }, @@ -32,7 +32,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFI/App/MobileSceneModel.swift", @@ -40,7 +40,7 @@ }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" }, { "resource": "repo://TFM/Features/Workspaces/WindowModel.swift", @@ -62,7 +62,7 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" }, { "resource": "repo://TermindMCPBridge/main.swift#L4-L87", @@ -92,7 +92,7 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" } ] }, @@ -140,17 +140,153 @@ }, { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" + } + ] + }, + { + "id": "claim_6120a1245337428e9dfca940e2d22e54", + "statement": "TermindIOSApp is the mobile @main entrypoint, which selects live or test dependencies and creates a MobileAppModel for the scene; failure to initialize displays an unavailable-content view, while desktop TermindApp creates app-wide composition for each WindowGroup and terminates launch on database initialization failure.", + "evidence": [ + { + "resource": "repo://TFI/App/TermindIOSApp.swift#L5-L33", + "version": "repo-lines-v1:sha256:1574c44f26f386fca5834af375adbea23b9471aaca384b9aa647006e94caec2e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0MDI1ZTA5ZDBlYTM3ZDMyNTYyMDVjODkwYTg5YjU0NmE0MDcwNTg4MDJmZWUyZDY1N2Q2ZjJmODg5MzllMTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwOWRlZDA1YTMwZTBiMDk1ZjI3NWRkNTcwMzRmNzU2NTgzNjBjOWQ4ZWIyNTg3NjNjNGI0MDMwYmM5ZGRjYjEifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L13-L21", + "version": "repo-lines-v1:sha256:06b626892110f9744884986c24067cdd36319b7ecbff0b8e399689be24a91fe3:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNWNmYmRiYjUwMTZhYzdkZWVhNTZlODkwYWU5M2FkNzczNjVjYjRkOGEwZDg2OGIyZTZjOWJlM2NjMTFjNDY0ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOGJjYzYxMWFmMjNhOTFjM2I3MjdkMGFjZTRkZTIyMjQyZmM0OTA2YzcxOTRhNjM0OTE5YjY1ZDcwM2RkMDBiMCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNWEyZGI2NmY0YTUzMjU3NWRjNTBmYmM5MWNmNGJjYThiMTVkN2U4ZDJiZTlmNWNjMThlMDY2MjY1OWMwYTVmOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYTljYTJjYThlNGZlMzI2MzgzMzdkNzZmYjI2NzI0NDRmZGNjMTI3MjU0OTQ4YWE3YWMzODZlMzhiY2JiYTY5MSJ9" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L137-L212", + "version": "repo-lines-v1:sha256:11dfd817e23e7a83d0ba2e12fd400fa125b0db9a3f60b67d7cd8192803616199:eyJzZWxlY3RlZExpbmVDb3VudCI6NzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhMGFmZmI5M2JmYmI4NjViODQ1NDU5NDY0ZGIzNmVmNDdkN2QwOTgyYzBjMGJlMzI1ODI1M2NhYzcwNTQxNjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVmNzY0ZGRiYmJlYTkxMTUyN2U4MTdhODBmNmZiOGExMmU4NDE3MzE3ZWY2ODEyY2Y5YTgxZjc5MDgxOTkwNjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjZGEyMmE4ZWYyODNjOGFmOTJjZDlmMmY2ZTA4MzdkODg4MjdjYjBkZGM2OWNlNDFkMTAwZDFiOTdjYWM5MmMifQ" + } + ] + }, + { + "id": "claim_6082f0f53bc94c899659425a2e4a67b7", + "statement": "The mobile app model assembles persistence, connection and sync services, agent host services and workspaces; its in-memory/test configuration disables live sync and Live Activities while the scene model looks up selected live workspaces from the app.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppDependencies.swift#L23-L61", + "version": "repo-lines-v1:sha256:9e38fcb9869533680eb4e62cec63f8d3e82213ab0e4ac8cc1da5cd3ae8ba606b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiMjNlZTJkYjBjMTU5OWVkNmI2NGMyM2QyNWFlNTU2MTY0MDMyNjIzYzFjOGU2YjJlODhjYzJlN2NmOTUxZDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRlODFhMzRiMzdmMjJjNTdjOWI3MjE2NDVlZTRjYWUwYjhkYmU3MDA0YTY3MjUzNzNhODM4YmQ0MmVhNjhiMjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L142-L170", + "version": "repo-lines-v1:sha256:663a6ccff640b2ca0aee6da8bd6f832dcc34fa8efbe9a442ff15f92b6a6c4f75:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlMWUwYThkMGE4OWM0NGE0MjQyMzhiOTQ4NWM5YmZkZWUyMGQ3M2M1ODFiYTEzOWMxODNiMTEwYzU4N2FjYjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFmYmVjNWY5MzkxMTMzY2U2NjY1NzgyNzMxZWExZmE0N2MzYWY2NDE3ZDdmZjI0YjNlNjVkZjQ3Yjc0ZjUxM2QiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNiYjUzMTU2YTNkYjA5MDdmY2I4NDEwNjJjNjc5NjdiMzMwY2I5NTk1ZjViNWEzM2I4ZWVmNTZjZTVlMzczZjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZkZTRmMzcxNjA0NDFkN2Y0MmQ1YjBlN2U5MjIzNzQ4OTI0ZmNkOWRmNTBiYzQ3OTYyYzg1YzQxMWRiYWM5MjMifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L201-L261", + "version": "repo-lines-v1:sha256:c51bd9620b015b21ffc4bb7aab7f3be9e4ae9eec95a90668b46269b5cd28bcdc:eyJzZWxlY3RlZExpbmVDb3VudCI6NjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk1MDE4Y2FmY2ViNTI1ZTZhZjQzN2JjZTEwMzI3OTQ2YWM0MzFhMDI3YjI3MjQ2NDE4NjBmZTc1MTBhZTMyMDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQyNmNhYmY0NDRhNjE0ZGZhYmY3NjdkM2Y0MTc1NWEwNDMxZGU1MmQ4ODU3NDg2NjY3OWE5Zjk3OWY5MzhiYTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVmNmY0MTY5ODIxNTkwZjRmMGJjZDljNTYzYTc3NzVhNjM1N2JlZDc5ZjM0NWVmNWVmOWUxNTY2MDdlYmNkM2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJlMzdlZGUxZTdmMTk1YWNmYTdiNWJlYjVkZDkxNGUzZTAyNmQ1ZDM5YzE1YjUwYzQxZjVjYTJjMmNlZGRkOTAifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L331-L332", + "version": "repo-lines-v1:sha256:abecd7a101a262aca6c56ec6b7ef713991d01ec5fd138a80e5e0f5b9bbe42d19:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjU4Zjk2YWRiZTFhNWJjMDVjZTVkMjIwMjMzMjY1NDBiNWNmNjcwOWM2MDdhZjM2MWJmYzExZDM1NTQyNDRiMSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOGFiZWZhNWM3ZGIyMjBiNTJmMTVkNzkyZDhhOTY1ZDNkZDQ1OGE3OTkxMWM0ZDJkMWZhZDVhZDU4NDdjMzIyYyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYmFhMDIyNWY0MWUxMTU1NWMzNDUxMTVhMDdiMzY0YjBiZjc0ZjQyNDMwYWZiZjQ3OTM1Y2M1NjY1ZjU1OWIwMiJ9" + }, + { + "resource": "repo://TFI/App/MobileSceneModel.swift#L32-L44", + "version": "repo-lines-v1:sha256:04248219d08461a2e9328bf6fd603cef8404c7adba60e83702f97fa5314381cc:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNiOGVhMmUxY2I3ZDY2M2Q1MjNhNzNmYWZmZjI2ZmNhNGNiZjhlY2I5ZmE4ZDRmMGE5ZjI1MDU1ZTUwMDRkZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM3NWVmNjM1NjYyN2ZiMjE3MTdmYjM1YTNiNjI1OWVmOWNjZjg4MmIxYWVlMzAyZmU3ZjMyY2Y3MjRmMmMyYTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM2OTdkODFmMjgwMmI4ZWQxZWI0ZjE1ZGYwNjA4Y2NhYjFhYzcyN2Q2MWI2MWMzODNmMjFhMTM3Yjk4YjhhN2UifQ" + } + ] + }, + { + "id": "claim_0d9152b054784557ac356322612a7708", + "statement": "The Xcode project declares remote AgentKit starting at 0.14.0 and the resolved file pins revision ffc4aa41c8854142aa47c35231e57f56f961ba9f; edits in the AgentKit checkout or sibling working tree alone do not alter the Xcode dependency.", + "evidence": [ + { + "resource": "repo://.gitmodules#L1-L3", + "version": "repo-lines-v1:sha256:d44aba833f5460dbae6fe83e58327069b8ca0528c32f0bd299bf7d56e1acb99c:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZmU0MjljMjJjMWYxZWM0YzE3YTg2ZjkzYWI3ZjcyNDdlODQxMDAwNjlkNWUxZTM4N2VlNjczOWMxN2Y1ZjFjMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYzY3Njg4YWQ1NzBiZjg1NTkxZGIzZjg1MTI2ODJhZjlmMjViYjY2MWQ1NDM0YzMyMWEyYjA2NzA0YzExYjQ2MyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjAsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjAsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZTNiMGM0NDI5OGZjMWMxNDlhZmJmNGM4OTk2ZmI5MjQyN2FlNDFlNDY0OWI5MzRjYTQ5NTk5MWI3ODUyYjg1NSJ9" + }, + { + "resource": "repo://AGENTS.md#L16-L18", + "version": "repo-lines-v1:sha256:79d9222951afd1cde2967f4987b4aa7b4347f1510f1fc4d1141010690b9c8bff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGI2ZWFiNGFjNWIwNmRiMjY5NmQ0ZDUzZTJlN2YwZDE3MzhmMWI3NTAyY2UyZWY1YjcwMzIzZjg3NjdjYTllNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRkZTk1MTMwNGUxYWVlNjRiM2IyYmY3NWZkMzI2YjAyZGM0OTE5YjlhODM4MGZjZTY1YTAyY2VjOTE3MzdjMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWM1NjRmZjMwNzY2N2QwZTgzMGJkYjkxYmY1MDYwY2FlODNhMjc2NzRkNTU5NWNiYTU0ZGMwNmQzNmE2NWMzYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTVkOTdmMmUwNzM5MTAzZjc1MTA1MjljNjA1Zjg0OTIzMTdkNDJmNDA5NzEwNGFmMmRkMjBiOGUyNmZhMmNmNyJ9" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L2852-L2859", + "version": "repo-lines-v1:sha256:444f908545e708b1d395265e4292e5529193fc19d4f609c8b5e06f6d68e13abe:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDhlMTQzODY5ZWI0MzVjMzZmNTljZTI5N2IxYWYxNzc3NThjMzVhNzFlNzJiMDQ2MTY2ZjkzNTNkODcxM2E3MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzYwYjg4YTA1ZDViNTM4NDc2MDIyOWJlNjA1NzJmZTYyYjFjMjljZGM1N2VkYjVlNjk1MWRhYTRmZDQ2YzgwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzExMTg1YzI4MDExZTZiNWFiYjU1YzRlOTQ5MjMyMTkwMzE1YWFmNGZhYzU4MzhhMDFjMWZmNTQyMjgwZmFiOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2M5YzA1MzMwYWQ3YTFmNDVhMmI2NDU2MTQ4OGZmY2NjZGY5Yjc3YzZmMDA0ZjBkYzRmNTBiOWRhZWFiYjdmNyJ9" + }, + { + "resource": "repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved#L4-L12", + "version": "repo-lines-v1:sha256:7eb86daf3bd5704e40a1831553c670c00afaaaaf5be6d7769f1a27c5a7b8b605:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjljYTg5MWJmZjdhYzFmN2NlYWFlNDBlZjA1MTA2NmJlOWVmZTQ3YjRlNDI4MWU4NmMzMTliZTJjNTVlYmNlNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMWYwY2RiOTcyYTdiZmI3ZWQyNDZmOWZmNjcyMzg1ZTU1ZjQ5NjhmYzExMDQzZGM1YjY4NGQ1MWRmYTMxZGJjYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNWZmNzZlNDczNTc5ZjY2ZjA4ZDYwNzE5YWQ5ZWI0MGZhZGRhN2M5ZTE2NjFlZjY4MzM5MzAyZDYwNDI3ZDFhZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjY5NDc0MjNlZmI2YjU1MDBhNGNkODk0MzY1ZTM4ZTJkYjBiZDY0MDQyMmJlYWUyNDEwOWNjY2Q5YjhmMDE1MSJ9" + } + ] + }, + { + "id": "claim_073ebd2722e443499d8a7746d340ac91", + "statement": "The Xcode target membership compiles WorkspaceActivitySupport source into TFI, TermindWidgets and TFITests; TFI embeds the widget extension, which directly depends on TermindPresentation, while TFM embeds the separate MCP bridge tool.", + "evidence": [ + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1037-L1059", + "version": "repo-lines-v1:sha256:2dbe5a26628d4c42a81936919a40d28732563faf8206ab1cf409e06465d95232:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUxZTk1MzFiZDY5NjA2MWVhMTllMGRjYjNlOGZjNjZiZTNlY2UwYzgyYzAyMmY0ZTZiOThiNTEwMTIyZTQ4YWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MGQzMTQyYmYzM2UwNjczOTk4ZWExNDA0OWRjNTY2YTFiMTE1OWM3ZDNkZjBjYzY0YzIwOTFiODgxY2I5MDgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFiY2UzNDJhOGZjYTAwMWM1MDBlYThlYjA4N2Y1ZjRhYWFhOGI2ZTk5ZGYwMTQyODllZTlmYzNkZmJmYTYxOWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVhODMyYWM4YWNjMzJiYzNjNmYwZjY2YmVhMTI1NmE0YjAwMjZjYTc5NzI4NDJjYWY2M2Y0ODc4MDk1MzYzODcifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1138-L1159", + "version": "repo-lines-v1:sha256:f58ff171cc36cbf55693e395eb39ed3922dce37762772834709d1d09eb1b11e7:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRlOWRjNjE2MGJmMDAyNGNhNzFjZDJlM2MwZTVmM2E1NTZhYzc4YzY2ZjA3ZWViOTM4MDc5ZGRjY2U5NTZhMDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBlNTIzOWY5M2QyMzljODdkYTIyMjEzMWY4Yjc2YzBhMTA5ZDBiYjY5ZDU2YTAxZTcwYWJjOGMwYjQwODQyMTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjczOTBjNzY0M2M4NWVmNmZkY2M1ZjgyNzA5YTRkNWQyNmYwMDU3ZWUzYjJkYjU5MzcwMWIxNWQ4ZTc0YzkxZmQifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1171-L1194", + "version": "repo-lines-v1:sha256:2036aa6e61474748b664b83552a3661d0d65fc735737e391926849ce81f90253:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNlZDFmYTFkMmM5ZWNlYjY4OWU2N2ZhNzg4NGFjMTI4ODc4NjIwNzczODc2NzdmNWMwZmMwM2FlMmYzNTNiNTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU2MGI5MjNjYjkxMDkxM2QwZjMzZDc5NmU3NTEyYTMxNGIyZjllYWY5NzQzYzg1MGQ5NWQ0OTRmMjliMGNlMDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNkNjM3NTM3Yjk0YzZjZDdjYjQxNDY2Mzc2ZjhiMzk5ZDNhZjA3ZGM4OWVmNTlkMTI3MmIzM2I1ZjA3M2I0ZWEifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1656-L1679", + "version": "repo-lines-v1:sha256:44c2a628f074f0ff548419c916e5230842be36f27fecb5530d71afbf6ef6d86a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM5ZjdiNDk0Y2M0NjU0ZmM3NjA4NDAxOTUwODAyMDFjYWRjMTQ3YmViODI3OWJhNjEyYTQ1ODI5ZGFlNzhjYTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxNWY3NTY0YmQ2MTFiMjk3NGEzZWQxYzE1OGFkODI2MGZlMjFmZDAzYzQzOWQ5NTE3MzgwMTE1OTI5ZDAyNmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmZTE2Zjc4YWM4MTAyMjhhYjM4OGY4OTljNmJjODU3NTRlZjgxOTk1OWQ1NjYyOThhMTZjM2RkZTFjODcyNGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYxM2VmOTZlMGJlMmZkOGY5NGM4NTNmMjQ2ZjA0OTA5OTIyMGM2Zjk3ZjU2NTk0YTcwZjllY2Y0OWI2NDQ1MDIifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L859-L883", + "version": "repo-lines-v1:sha256:083ada686c7445442054245a730f23d361b8256e82648ba1dcfddaf506d31c11:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY4OTFkMmE5MWQ5N2Q2NTQxODU0ZDdiMDQ1MGVhNmQwOTQ2OTA5ZTA5MWExZTQyOWQwY2FlYzhmZmY2ZDNiNTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdiNzdiODlmYzMxMTdkMDBhNTcyMWU0Y2ViYTY5ZTE3MWQxYzUyN2Q2M2U1NDVjYWRiMTUwZTAxMDg2MDYyNTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM2NTE0Y2FhNGMzOTc3OWQzZDIwZjIzNzVhZDc0MDQ3Mjk2NTgzYTE1NDBiZWFlZTllYTQ4N2Q5ODlmZGMxNTUifQ" + } + ] + }, + { + "id": "claim_49f0afaee7e041a581273eddd29956b2", + "statement": "ArchitectureBoundaryTests enforce source-level dependency and ownership restrictions across shared frameworks and native features, independently of Xcode target edges, and guard the forwarding benchmark against becoming an app or test dependency.", + "evidence": [ + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L137-L189", + "version": "repo-lines-v1:sha256:5e582ad2f3ec4728109feafbf32361c1b58e79da16cc678a79d1606293005434:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjOWJmNjE2ZGNmNTM5YTBkNTRhMTM2YzY2NGM1M2EyNTllZmFkOWNmNWFmYTY5MDY5ZmEzOGI1MzE5OTQ0YzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0N2NhYjY3NzUxMmRjZWQ0YTIyMGVkZGQ4NjNlZDFlNDM1OTM0NmRiYTk4ZDljYjkwZDBmZjk2MjhjM2IzNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3ZGE0ZTRmODRkMjdmYjAxMTA1N2E3YjdmMzE0ODI3NmQyOWUyOTUyNDU3ZWE4ZTYyMmUzMmU4MWU4NTVlYmMifQ" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L221-L236", + "version": "repo-lines-v1:sha256:f8c236519e8486d9e23370a1125780885a560563104317d8b0667fde12b5c048:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyMzk2YTZjMGFlNGEyMDI0YjE2OWE0NWY3MjdmZjYwNWE4NDI4NjdkODJlYjJjOTNkYmNkNmVlNDg4YmExYWEifQ" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L4-L21", + "version": "repo-lines-v1:sha256:5d744dd3a04aa52af14b4dd6198dd44bf394cb500c3a31ee4dc57da5babf2b34:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJhM2Q2ZGI3NWZmMTQxZTlhNTA5NTRkYzMzMDFmOWE4NzEzOWFkZjlhM2MyNjY3NDViYzg3MGQ1ZTk2Y2VjZGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjczZDkzNjkxMWM2OTMxOTkwMThhZjEyOWUwNzY4NmI2OTY4MjA2ZjI5NDJmNmRlYjc3ZDViYzJkNDBiNWUyYTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMyNTMyNzdkNWRjOTAyZTI1OGVlNmZmMmY0MzA4YjRkYTQ2ZGJmM2Y3NmI1N2Q4MzQ1NWU5OGMyMTg3OGU5NTgifQ" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L65-L106", + "version": "repo-lines-v1:sha256:cccba101be353c92ea23d68341dedab8bfc267dc2bc40693662576447fa784e3:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwMGI5MTQwMWVjNTRhNzEyZjI4MDZlYzA0NjE0MWVhZDIwODZmMmMyMzUxMTIwOGQyYmVhOGVmOWFhZjIwZWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ" + } + ] + }, + { + "id": "claim_19165192a0694b01bb3a9bb5aa6f255d", + "statement": "FrameworkTests directly depends on all six shared frameworks; the platform test targets depend on their app and selected shared frameworks rather than the standalone port-forwarding benchmark.", + "evidence": [ + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L7-L20", + "version": "repo-lines-v1:sha256:ec49e742f75508008bc31f786cda52fe80643449016a57594742c8720299edf5:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiMGE3YWFlYWQzYmVhYTg2NGM2ZTA0YTAzNTJhZjk1NDMwZWQ4NzM3YWY5MTZkNGMyN2VhNDAwZjFiYTI3ODUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkxZjMwNWE0ZWI4MzZhY2NkYzA1MDBhNDQzNDg5NzljMjcyZDYzODg1YzkzZTFiY2M2Y2Q2YmY4OWJhYTE2NWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1138-L1159", + "version": "repo-lines-v1:sha256:f58ff171cc36cbf55693e395eb39ed3922dce37762772834709d1d09eb1b11e7:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRlOWRjNjE2MGJmMDAyNGNhNzFjZDJlM2MwZTVmM2E1NTZhYzc4YzY2ZjA3ZWViOTM4MDc5ZGRjY2U5NTZhMDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBlNTIzOWY5M2QyMzljODdkYTIyMjEzMWY4Yjc2YzBhMTA5ZDBiYjY5ZDU2YTAxZTcwYWJjOGMwYjQwODQyMTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjczOTBjNzY0M2M4NWVmNmZkY2M1ZjgyNzA5YTRkNWQyNmYwMDU3ZWUzYjJkYjU5MzcwMWIxNWQ4ZTc0YzkxZmQifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1214-L1233", + "version": "repo-lines-v1:sha256:b6fa3f7d3d875af3d0ce34729545d95918a4f939571017b2a305bda40d579dce:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwZDc4MDI2ZGJkOTdhYWMwNmVkNDBkYmFlMzg5YmViNjBlNzRhYzBkOTVlYjg0Y2Q5OTkyNTA2NDRmNzcxMDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFmMDYzODdkODk0NGYzODFhMDc0M2Y3ZWM0NGY0NTQyNDA5ZDc2MTUxY2M3YWRiYjZiYWI4YTE4NWNjMDg1NmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc2NmM1MDA0NGFlMjRlZTAyMTRlMzFlMTNkY2M3YjQzMGNhZWZiNDAyNzM4YTlkODEzYmYwODc1MTZkMTlhYmIifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L901-L918", + "version": "repo-lines-v1:sha256:c0afba6920715469b1143421a486cab4c58af4d861f4f079b3c67a50a57cc3c9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIxNTg2NDk5Mjk3MTM5ZTRkMWUwMTM1MTU3MDkyNGM1Nzk5MTUyOTI3ZGJiMDM0MDI5MzljNDhkY2RlZjczYWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk2YzJjMzg2MTg1ZDA1MGMyNzY2Y2RkNDZjZDM3OTg2ZTY3NmRhYmU1ZmEwNDk2MTE1ZGQ0M2U5M2ZkNjYxMTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVjMDlmOGY2NDVmNjBmNGRjZGE1MGIxY2IxMzBmMDJmZGY5M2E4YTRkYjY4OWI2ZjBhZGNmYjBkMmQyNDRhYTEifQ" } ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/native-app-directories.json b/openwiki/.claims/architecture/native-app-directories.json index f28b1935..474b5d8d 100644 --- a/openwiki/.claims/architecture/native-app-directories.json +++ b/openwiki/.claims/architecture/native-app-directories.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:576b2a04372cf81fcde6d2915f6e8b918efb29ed6cb739e33ee70fb76991d17e", + "pageVersion": "sha256:6fcee3a37158ff40799ce0b4dc356338d80ec4b9e1bc658f5d856c466618b2fe", "claims": [ { "id": "claim_8e9cf2adb50847f98fcd4516cb0ed521", @@ -16,7 +16,7 @@ }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" }, { "resource": "repo://TFM/Features/Workspaces/WindowModel.swift", @@ -60,7 +60,7 @@ }, { "resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift", - "version": "repo-file-v1:sha256:303d0a53d1bfa67f4ce602a193bc9c1e917b9f2075f5654acf19e9166dee9f1f" + "version": "repo-file-v1:sha256:d4b9205cc908ce2c38eb1e82ca1ea0a84a45794fa0613b0e794177ae9e48a48a" }, { "resource": "repo://TFM/Infrastructure/MCP/MCPServerSession.swift", @@ -160,7 +160,7 @@ }, { "resource": "repo://TFI/Features/Vault/MobileVaultView.swift", - "version": "repo-file-v1:sha256:ccb0a1c9c7db91c0e853149a638c43c633f8a0fe41fca90a0e39e3566df7bce8" + "version": "repo-file-v1:sha256:ae5726d2034f41e3797ec0cd94009bac394fe28681d3b939aa0ba8dda3d8dd28" }, { "resource": "repo://TFM/Features/SFTP/SFTPChannelModel.swift", @@ -182,7 +182,7 @@ "evidence": [ { "resource": "repo://TFI/Platform/MobileBackgroundController.swift", - "version": "repo-file-v1:sha256:0fbc54522867c50f4c6ddff1294d936dd65a21acf6dbdec239bb78866166e525" + "version": "repo-file-v1:sha256:75c3d7bda5bf9ce83518666d5801cf3e01f9bbc82ed5acdc557bf17c2c6d4efc" }, { "resource": "repo://TFI/Platform/MobileLiveActivityController.swift", @@ -206,7 +206,7 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" } ] }, @@ -215,22 +215,252 @@ "statement": "Native app composition adapts platform device naming into the shared device directory: TFM uses the trimmed kern.hostname with DeviceKit fallback and refreshes on application activation; TFI uses DeviceKit's Device.current.safeDescription and refreshes on active scene transitions.", "evidence": [ { - "resource": "repo://TFI/App/MobileAppModel.swift#L580-L589", - "version": "repo-lines-v1:sha256:71bcd9d234f4fe43fb8074f23095acbfa238266403359ce6f85621ad7d170c6d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc1Nzg1MjI2MjQyOTAxY2NkOTlmMTgzNjZjYTdhOGNhOGEwNTc1YTA0OGNkOGU3NTZlZmI2ZmRmMjc5MTFiNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQzZGFiZTIzNDEzOTNjYzU1NWUzZjI0MzRlOTFlZTZjYjVjZTNhYTgwNWEwOWVhNjA2YTY1MDI3YzNlZWUzY2UiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMzNDVkYzM2OGMxODNiMzEwOTZlMDYwYWFiODA1NzE2MTY3YTYyNDQ5MTgzMTM1NjJlMTgzNmQ1NDk0ZjIwMWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY4ZWY4Mjc0MmI5NzUwODBiMTdhNDZjZjVjMDYzOGM0MmY1ZGYxNjE3NTBjM2U0OTY1MGRhYTc1OTQzNjJmMWIifQ" + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { - "resource": "repo://TFM/App/TermindApp.swift#L285-L294", - "version": "repo-lines-v1:sha256:4f92aff6ab1ede611953c68748bb9269d0f87191ba08801a24ee1e1968e1fe94:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2Y2JmMWEzM2ZlOWQ1MWIwZWY0MDc2MzM5Y2MxMDBhZTIwZThhYmM5Njk2ZTM5ODYwYWNiZjZlNWFkNmU0OGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYwYTMzOTQyMzQ4NzRjMmRkNjYwMzEwZTMxZjZiNDAyYmY4NjM1ZDAwZmI4OWVmN2E1M2VmOTAwZmEwNDlhYjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVhZmNhZTk2NzVmZWU3ZDkxZTJlODNmYmY5MjI4MGQ1NmFjZGQ5MWFjMzFlODg1MzA3YTNhMTcyM2MwYzFjOTkifQ" + "resource": "repo://TFM/App/TermindApp.swift", + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" }, { - "resource": "repo://TFM/Platform/MacDeviceName.swift#L5-L29", - "version": "repo-lines-v1:sha256:2e3a802d84fd2b017f0074f76c3ef896d3127453e0142f3a054521e823ba686f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzZWIyNmFmMDY4MGI1ZTY3MGVmYjZkZGRhNjRmNGEyMzVmNDhmNTE2N2NlMWY4OTYwMDQ0MDU0MGE1OWRkMzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVlNGQzYWNkOTllYjdjOGNhNzFkNzZjODJjMTIxOTcxNzU5YjBlOTFmODVlNzhhNWQ1NDJlOWUzNWQ4ODFhODUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + "resource": "repo://TFM/Platform/MacDeviceName.swift", + "version": "repo-file-v1:sha256:d884719f29fe1d5e7a8e980adcc5205737202a72bcb9e839ba39c34f0dcb414b" + } + ] + }, + { + "id": "claim_66d56131f7cf483b9a9eecb7bf7ce47d", + "statement": "The desktop app creates one shared AppModel and SwiftData container while its WindowGroup constructs a separate WindowModel per window; the AppDelegate handles native application activation, reopen, and termination, including confirmation of outstanding SFTP edits.", + "evidence": [ + { + "resource": "repo://TFM/App/TermindApp.swift", + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" + } + ] + }, + { + "id": "claim_a771d620e2544e5d82a72c78bc0ab51f", + "statement": "MCPServerController owns server configuration and lifecycle, binds loopback HTTP streaming requests to application upload/download coordinators and protocol requests to MCPServerProtocol, and stops transfers when the server stops or its token rotates.", + "evidence": [ + { + "resource": "repo://TFM/App/MCPServerController.swift", + "version": "repo-file-v1:sha256:7374829e1807503b67c654c88edc8dba34bbd50a8499c6beec23170a73745c99" + } + ] + }, + { + "id": "claim_8c472aba264a4c74b5c13a414684f22b", + "statement": "MCPUploadCoordinator validates run-bound upload tickets and incoming PUT authorization, origin, headers, length and acknowledged resume offset before allocating capacity; interrupted or recoverable failures can pause for offset-based retry, while integrity failures or cancellations cannot, and successful state follows remote transfer completion.", + "evidence": [ + { + "resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift", + "version": "repo-file-v1:sha256:d4b9205cc908ce2c38eb1e82ca1ea0a84a45794fa0613b0e794177ae9e48a48a" + }, + { + "resource": "repo://TFMTests/MCPUploadTests.swift", + "version": "repo-file-v1:sha256:20a1aa368466f1b01198ac0b2b96b0d3e66589e42679ad3a1bf086ac4d2966d6" + } + ] + }, + { + "id": "claim_966f61495f4c4cc5a075bbeec6a94be3", + "statement": "MobileRootView retains scene-local navigation and reports phase, removal and Pro changes to the app-wide MobileAppModel; the app publishes a restored workspace before connecting so multiple scenes share one live runtime rather than initiating duplicate connections.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift", + "version": "repo-file-v1:sha256:5391ee5b542127ba539cac32e1f3d49c335e78f9c09aa06499c6c61fd00e42fa" + }, + { + "resource": "repo://TFI/App/TermindIOSApp.swift", + "version": "repo-file-v1:sha256:9daf1c0933fdbcff826165a8edc171876c54faa343a184348284e63f736e86bf" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift", + "version": "repo-file-v1:sha256:b2c528520ad5272155355404f91af52e490c6f17780a845d9e8a596c523484ef" + } + ] + }, + { + "id": "claim_4b1bafeb03c74e7dbec2139a65e9457c", + "statement": "MobileAppModel.reconcileSync starts vault, metrics and settings sync only if a tracked scene is active and Pro allows vault sync, and otherwise pauses all three; it runs on foreground entry, scene removal, sync setting changes and Pro entitlement changes, while in-memory composition has no cloud coordinators.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift", + "version": "repo-file-v1:sha256:5391ee5b542127ba539cac32e1f3d49c335e78f9c09aa06499c6c61fd00e42fa" + }, + { + "resource": "repo://TFITests/MobileSettingsPortTests.swift", + "version": "repo-file-v1:sha256:02e61b9d136c84002e35854cf33f1eab0751a685f2c5d9e27acb05a44ff10a57" + } + ] + }, + { + "id": "claim_5db49dd0db5c475fbd5ea87a7d7a11e8", + "statement": "When all registered mobile scenes first become backgrounded, MobileAppModel pauses app-wide services and begins a UIKit background-task lease without immediately disconnecting healthy workspaces; expiration suspends sessions, forwarding, transfers and Assistant work, and active reentry finishes the lease and resumes affected workspaces and services.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift", + "version": "repo-file-v1:sha256:b2c528520ad5272155355404f91af52e490c6f17780a845d9e8a596c523484ef" + } + ] + }, + { + "id": "claim_86f156b5ab4447759ac53e099b95a5c0", + "statement": "MobileBackgroundController owns an at-most-once UIKit background-task lease: it ignores stale expiration callbacks, retires a returned identifier even if expiration occurred synchronously during begin, and does not end an invalid task.", + "evidence": [ + { + "resource": "repo://TFI/Platform/MobileBackgroundController.swift", + "version": "repo-file-v1:sha256:75c3d7bda5bf9ce83518666d5801cf3e01f9bbc82ed5acdc557bf17c2c6d4efc" + }, + { + "resource": "repo://TFITests/MobileBackgroundControllerTests.swift", + "version": "repo-file-v1:sha256:1226ebbfffd760d8d288d9208938faeb797aa2fecef504092e45ad7965ed97e2" + } + ] + }, + { + "id": "claim_f66918c39d834e18acd207900b826930", + "statement": "MobileAppModel.setSyncEnabled requires Pro permission to enable synchronization, persists the preference, attempts custom-password migration when enabling iCloud or vault sync, and then reconciles the app-level sync lifecycle.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" + } + ] + }, + { + "id": "claim_84739cc6b5964a3ab3635eed6c05f98c", + "statement": "MobileFeatureRegistry registers top-level destinations and MobileRootView mounts each in a NavigationStack backed by a scene-local MobileSceneModel; the Vault registration passes scene callbacks for opening/activating hosts, executing snippets, switching to Metrics and presenting a host editor.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileFeatureRegistry.swift#L33-L116", + "version": "repo-lines-v1:sha256:95b16864445cf19cf8b5ffa9ac1006beb70a9a8fb97a1def2f928a0f0df56446:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyYzBhYjFhNzUwMDZhMDA3NTE5YjhmZTgyNGQzOTVlNGVjM2JkNWJhMjY1MDNjZjA5ZTJkZGY5ZWMxYTI0MTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYyNjg3ZWVjNDdjMDhjYTllNWRhZmJiNGE3ZTEwNGMyZmJiMGU1MmYzNmMxY2ZkOGJjMzhlZjE4OTE5OWQzMWEifQ" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift#L14-L39", + "version": "repo-lines-v1:sha256:15879a1e881b04625ba69f98737d9205e03d7fbd868ce4c2799bcd7bb4faaaac:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyODgwNTA4Y2FkZTAwMmU3ZWE3Y2MxZGNkMmEzZjgxNTJkMWViMDlkMTU4MmU1ZmFiNjc0YzY5NzkyZDk3NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkOTY4MDU1YmE3YjlkNGU0YzBkYmMzMDczNjYzZDM0M2U5MTg2ODliZWRlZjc3MTI0NDRmYTc4YzNjNGJiODMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMxNjI0NDQ0NWQ0ZTY5YjU4NjI3NmU3OGQ0MDAyOWU1OWQ1NjRiNjQ0YjhlMTRmNDI0N2U2MWI1YmI5ZWZlMDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI2MjIzODhlOTUxYjRjY2JlM2I1ZWVmOGMxMTg0MDA0MjFkNzJhNjg5Y2EyZDFiZTUwNDFmNTExNDA1N2YyN2IifQ" + }, + { + "resource": "repo://TFI/App/MobileSceneModel.swift#L15-L43", + "version": "repo-lines-v1:sha256:a9c891c91552cb57bb16304a1daea60106c1c74497e2801a6b9715779a2f31fb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFhMDBhYzk5ZDQ4ZmUzMzU5Nzc0MzkyMmI2MzU0NDkxMGZiOWZkMDdlMTAxNjNkZTc0NTM4ODBjZjEwOTU0NjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRhOTU5YTBkOTA2MmZjOGQxMWNiNmJhYTkxZDA4NjFjN2NiM2JlNTE3ODFhYjFlNDM2YzY4NzNjMzliZmU5YTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg1NGI5NTkyZTNiZmY1MGMzYTczMjA4Mjk4ZDQ3ZDdkNTQ0Yzk2NzNjNDczNDA1MjdlM2M2YzA5MjIxMDg0Y2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2YzU5MWQyZDA2ODBjN2Y1NTkzZDVkZmRiMWJiZDdmYzJjNTA3NWMzZDMzNzQ5MTZkMDdhZDk1YzExMzRkYTEifQ" + } + ] + }, + { + "id": "claim_934ebc213cdd4841b2798e17a0edbeaa", + "statement": "Mobile Vault renders grouped host cards and resource links; tapping a host selects or opens a preferred terminal workspace through the scene, explicit SSH/Telnet/SFTP menu actions open connections, and local edit/group/deletion presentation does not own the app's session or host-deletion lifecycle.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L501-L532", + "version": "repo-lines-v1:sha256:272653e3fcc219bb95f099a32ccd67ffda852cbf012cc914bcaec085d7edefdb:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYyYmY0MThkMjk2MDkwOWQ0M2E2OWUyNzZmNWRmODc3ZDhmM2QzNzIwYTYzNDUxOGE5NGViOWVhNDA5MzMyN2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMyYzAxYmJjMDk4MWM5ZDIyZDczNTJlODYyMWU4NmE4NDg4OTU0NTM5N2MyZjI4NjRmYmZmYWM0OWU3N2U2NWYifQ" + }, + { + "resource": "repo://TFI/App/MobileSceneModel.swift#L83-L131", + "version": "repo-lines-v1:sha256:44ed638316c70669b5ef692ac635ac86469aabb3dd4c6ec1a008643ec9218ca5:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwOTA1MzRlNGFlMDdmZThiMGM5MTk4MWE3MGY1ZDFjMmM4ZWE1YzMzZmY5OWEzZGQ2YTBjMWQwNWM3NzBmNjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjYzk0ZjdiZjEyMjBmOTFjNDQxODMzYjYxMGRjZGQ1MGM1N2ViNjc1YzNiYzY0YmY3Y2EyZThlYzkxNzBhYmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ4MTBlMzEzNDk5YzU3NjYzMzUxMTFjODI1Yzg4MWEyYjhhNWJiMjBkN2ZiNTgwNDQ0MzAyNjk0OGI2MTU3YjgifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L441-L513", + "version": "repo-lines-v1:sha256:456cfc3a140a45f1536ca95bdf7f347179c129b50a48912515b2528bd411b911:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRlZjlmZDM3NWY1ODkxYTc2YTE5Mzc2YzI0NTZiNGYyMzM4MmVjODJkNWJiNTkzMDEyZTNmOWZkZDNhY2YzYTYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJjZmUyOTY2MGQwMWI1MTk0ODgzMDkwNWE3ZDQ1ZGQ0NDUzMGNmMWMyNGE0ZTk2NWI0OGMwMDY1OGQzODBmYTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiODlkNTljMjE3MGEwZWFmOWY0NDc2YmVjMjRjOThlYjdlYTRiMWNlYTY4ZDQ5MmQ2OGNkNzAzOGZkNDE0YmQifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L767-L834", + "version": "repo-lines-v1:sha256:a07e0e245c8f4f406d84b4fef5566cdc859fd6f1122354eb1b71ee859d8c361c:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyMTExNDcyZWQ0MmE0NDkxZjc5OTQ0MzNjMTM5ZTBlY2M3ZTczZmZhZjI4ZTZlYzIzZDI3OGIyMmRjZmYyMTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkzOTgxNDU1ZTQyYTZiNzRiOWU5N2ZiYTY0MjM2NTQxM2Q4YTNlOTJkY2JlNjU5NjY1ZDUyODA0OGExZmU0MjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzYzUyYWM5YmUwN2MwNzljNTRhZDgwOGMzNDEzNDMwMjFmYmM4M2NiZDVmZDk2ZGNlZTk4MGY4YTI2ZTU4YzMifQ" + } + ] + }, + { + "id": "claim_9dd19b3f4f36491895e7c994060850a1", + "statement": "Mobile Vault search forwards matching resource queries to dedicated pushed screens and switches the top-level destination for Metrics results; History presentation lives in the Vault file but filters host/device-backed app connection events through Application/Workspaces policy, caps results at 50 and only opens enabled protocols, with delete/clear operations delegated to app.connectionHistory.", + "evidence": [ + { + "resource": "repo://TFI/Application/Workspaces/MobileConnectionHistory.swift#L26-L124", + "version": "repo-lines-v1:sha256:0a30a7cb5bd5c6e983aff721f11dfe9a9e88b0b0bfe5529ad89ba0a0c479f37f:eyJzZWxlY3RlZExpbmVDb3VudCI6OTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiYjcyYjBmNTVlMWRhMWMzOWE4MGY1NjI1YWQ3YmY3ZjMzNDBkZTk0NzVlYzYxYTIzMThkZDRjOGJkNzBmNjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxMzVmNzBlZTdjOGYyNDQ4ZTgwYjQ3MjQ5ZDI0NGJlZGU4ZmIzNmIxYTVlNjZlZWE0YTQ4NzFkYmI4MWMxZjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L398-L438", + "version": "repo-lines-v1:sha256:6426680101ae11723a8187b37964aaf570488070e8a8d58c4a53f0cd80b90998:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM0OTFkYTIwY2NkNDBlY2I1NzJlNjg0NDUyNDk1N2NlMGVkMjk4ZDE4OTYyZmE5MWRkMDNjMmQxZjc3YTQ5OTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMzMDJiOGY2NTU3MTc0YzMzZDgwMmE5N2IwZTk3M2U0MzU4NjI3ZTA1MGI5MDNlN2M2MWE5OGQ1MWM4MDNiOGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjliYjI1MGMxMWI4ZWVlZDllMDA0ODIxOGFlMDBmMmEzM2E3ODAyZmEzMDY2ZTA0MWMzY2RiNzI0MGYzMzVjMjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhiOWRiYzFmMDQ5YTIwNDhlYWE2NmU3OTVjNDkzODkzYjg2ZDNjZDI5NTEzM2E5ODQwMzRmNjM5MzI2ODMwNjUifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L46-L127", + "version": "repo-lines-v1:sha256:515f44848c6cf09add98e47c05ba8dd7a1bffdcf0238619cd7754c00258112fe:eyJzZWxlY3RlZExpbmVDb3VudCI6ODIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNmODhhMjRjZmVkZmU1ZTIzYTM1MDVjYTU4MDZhNDdlNDJjOTViMmZjNDQzMTRhMjA1NTcwMjkzNDE5YjQ4YWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU2ODYxZmNhNzI0NTBkYWZmMGJlNjNjNTM1MWU2ZjllMDUyNDg1Yzg2MTI4NGI3MWI1NTk5NzhkMjVlMDJkYTgifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L568-L661", + "version": "repo-lines-v1:sha256:a8dde1065aaa091734bb471cbb4e28413f294c2fa7e9d846b08d81943a72a5ce:eyJzZWxlY3RlZExpbmVDb3VudCI6OTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlODY2ODIwYzYxZTkzNTc2ODNmMTE1NzA0OWQxMDRkMjlkMjE2ODg5NWNiM2RhMDg2NGZhZDVlNTYwNTc3NGYifQ" + }, + { + "resource": "repo://TFITests/MobileConnectionPickerTests.swift#L148-L173", + "version": "repo-lines-v1:sha256:c41e543bd8025d0fe331b673e3d89151282497571cfe21fbb403e4db7fe28cf1:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkOWVjNjFiMTUzMGUxMmU5MWQzNjU4YmY5YzhmYmExZWU5MDk5YjZhY2ZjNmE5NTdhZTkyOThlNGYwOWMzOWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ0YjQ2NzVjMjMxNmI4M2Q0MTI1ODRiZmE0ZGNiZWM2OGQ5OWM4ODM1N2QwOWMzNGY4OTdkZGU4OWM5MjA2MmMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0OGI4M2Y2NDVjYjJmZTI5N2YzMzkwYzliODMzZjdmZWVjMDk0ZWMyNGNkYjA4ZGQ1ZjI3Y2JlNzNjZDM2YjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5YjliYmYwYzQ2ZWVjYTY5NjFkM2E0NmEyNTJjYTRjZWU5M2UzMWQzNTNmOWYyZjIwMWJjYmZkOGRkYTk0YWUifQ" + } + ] + }, + { + "id": "claim_c9d328984b1145879989b7ad8778ff26", + "statement": "MobileHostEditor holds host and custom-identity drafts in a sheet, gates save on protocol/port/authentication/environment validation and saves identity changes through the host library; the separate Known Hosts screen edits validated trust entries via app.knownHosts and reports storage failures.", + "evidence": [ + { + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift#L208-L269", + "version": "repo-lines-v1:sha256:f9642a68da4f4e7a085ca7ff63ad77a0ad5992c82d14a3ba0055300c7a7bc272:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg4M2IwNmQ1MmQ3ZWY4NGJlZDBjMzVlNzVjNWQyODg4N2Y0MzZmOGE5ZjM1MjBmZTRhMzFhZWY1ZWZlZmM2MGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY5NjQ4YzE1MjRiOWVmNDk4ZDBhNzgzNTI1OGYzNGIxOTZhOTdlODg0YTUxOGM0MzY3YTE2MzQ5ZjcxMjVlMWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZjOWNiMzdiYjEwMzg5MDAyMmY2ZmYyYTg4YTdiMWJhODlkYjg1NWU2OGRhODAwNDE4ZWRkNmE0OWY3YzE1YjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWY0ZWJlMWUyOWMzZTllZWQ2MGVhMTUwMzUxMzQwMTUzYzllMWI5YWY5NTBiMTdhZWU3NGQwOWQ0NzVlYjkifQ" + }, + { + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift#L27-L69", + "version": "repo-lines-v1:sha256:02754b0a1bbd6555d1c8c5586c972850b8ea563b4ccd6bb577ea81b06d927ff2:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZlMzA0ODhhNDJjZmI4Y2M1YTgzMjM2YjRjNmM0YmE4NTg3YTY1ZDlmNWZhNDUyZGE4ZjY2MzhkMjhjNDZlYmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3ZWExNTk4ZmY2N2M3ZGM0NmE5Y2IwMmE2MjhlMWQ0MzZlMjdlMmU4YmNhZTFkMDllOTAwNGU4NzcwNTMxNGMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAxZGQ3YmJmYzM4MTU4YTI1YWNiMmUzMWU5NWZjYjdkYjFlMDRiYTA4ODg3ZDBhZWM2ODVkMzNhNDQ2Y2E0OWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkwMmUwMTg2MjNlMTg3ODVlNjQ5ODlhZTEzYzIzMjgyMDE0OGE3Mjk0YTZkZWNhMjQ5MjExNjFjMWFiNDY4ZGEifQ" + }, + { + "resource": "repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift#L6-L86", + "version": "repo-lines-v1:sha256:c95a7ee49b5428df46595142db320a1c9b94635eb0003029a58ed9d7e75aba82:eyJzZWxlY3RlZExpbmVDb3VudCI6ODEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3NzM1ZGU2NzdlNWVmZTVkYTI5NWUyMGYzNzk0Y2M2MDM0YTI4YjJlZGJiODc1ZDZiMGRiZmQwZTMxNTNhZGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNmYTE5ZjJhYWYyNmU2MjE5ZGY4MmM0M2QxOGI1MmU5OWI3MzhlNTIyNDJiMjE4Y2VhZmEzMjg1NThkNGNjZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFkZTY3ZmY5NzJiMWUxZDk5Njc0OGE1ZTczYjM2NmY5MzU4NzZiMDE4MGU5NmFlYzI4YWJjM2UyZGVmZGQ1OWMifQ" + }, + { + "resource": "repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift#L89-L153", + "version": "repo-lines-v1:sha256:ac254b0b4597be75de10b8c7596fe613d94b2e76dfa17bfe5e41947933915602:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3OTJkZjUxMDBhY2FmNGJjZWI1YWMxNDljZDI5ODEwYzFhNTc5YmU1OWIxNjIzMWVhMjA0NDgwY2M2Mjg5OTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + } + ] + }, + { + "id": "claim_eaf0bc4181fa4863a0e0486bc6ce5f0a", + "statement": "Desktop RootView mounts one WindowSidebarView alongside persistent detail per WindowModel; the sidebar selects Navigator, compact Assistant, Snippets or focus-sensitive History, whose source depends on the focused SSH/SFTP pane and is disabled for serial/Telnet panes with a Snippets fallback; activating Assistant or Navigator can also change top-level destination.", + "evidence": [ + { + "resource": "repo://TFM/App/RootView.swift#L6-L49", + "version": "repo-lines-v1:sha256:86a5698ef6059244332c78ef1e569c473d56b5ba3d767b7c9b61b0c838083495:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4NjljNDYwYmI1YjgzNGM4Zjc4YzhjMjEzMjAyNThiZWZjMGVmZGEzMTZmZTE2MzY0ODY1NzNhZDkyMGJmNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhhMDZmOGRiMGExNTBhMGZkOWRiZjE5ODI2ZjliODBlNTY0MDA5MGIzYWNlZGU5OTQyZWJhMjViZWE3OWVjMTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU3MWRhNzQzNDU3YzAzYTI0MDQ0YTE5NzU0NjBhNmM0ODk5ZTgwYjc1MjhlMzA0ZDMxNGQ2N2ZlNTVhNDE2MDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc0YTk1MzE4NmM4MTFmNGJhMjcxODk0MDUxMGNkYmI0NGUwNjIzNmMzZTViNTcwZjI4MzhkYzk0YzYyMTRhMTYifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L168-L196", + "version": "repo-lines-v1:sha256:fab8ec5c2615e2059937c1874b34f91fa78e407a9c91834fd5a9e2bae6bef536:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxMDk3ZDRjZTdkZDAyOWU5OGI2YWFkMjViMDFiYzEzNzhjOTdlMzA5YmRjMDY0YTM0ZTI2NTQ4MTFmMTgxYWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZThjZDVkNTA2ZmYwYjY4ODQ3MTFjMmMxNTI1YjdiY2UwMmY0NDMxMDU2YTk3Y2E0ZDQ1NWY3N2Y5MTg4MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQwMmQ5OGU3M2M3ZmQxZDQ4ZjUzNjdjZmY5NGFlNGYzNDlhZTYzZmIyMWRiYzkwZmYxYjZhNDViYjNmOWQ5MzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNjZmM1ZDE4YjJmZGJhYzRlZDQ1NGFjODhhZjc1YzI4NGNjYTNjZDlmMzZjMmQwZDhmNzUyNGVmNjc2ZTA0NWQifQ" + }, + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L20-L109", + "version": "repo-lines-v1:sha256:453efb359ee33d9200b73cdd0c8e381ef22355605ada3c2999e958efa5d020ae:eyJzZWxlY3RlZExpbmVDb3VudCI6OTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNkNjE5MmFmNWU2MTFjZTc2MGJiMTdiYjIxY2RmMzVlNGRjMzE5YWM0ODIxMjc3NmE3MTY1YTdhNGVkYmE3NDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA0ODM5Y2YzNTY3NmU3MWJkMjNjZjQ1MWRjMjU0ZTI1MmZlZWQ0YjI4MWVlZGYyY2M5NGIwOTg5OWUwZDQzOGYifQ" + }, + { + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L768-L779", + "version": "repo-lines-v1:sha256:5d4ca3aa9b8065880638441e6fde5ad930ed84cd12cd2c2846958e5f3e54aabb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjNzI4NzFlZDg1YWRiY2U3NDE3ZWU4NzNmNDNkMDNhN2Y2MmE0N2ZlYjQ1YTgwODhkZDUzMGY0NTUxYTU0YjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkZGIxYmZhZGQ3YzM1MmU3NTYyYTQ2Y2Q0YjRlYTQzZGVhMjM0NWI4M2ZjM2YyZmM5MTU0OTY2MTNiM2JjYmIifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L198-L260", + "version": "repo-lines-v1:sha256:c369d3ccb9cff0a5a11f9565fd9a2687419334e5e2e6d40108edb3142bac2c57:eyJzZWxlY3RlZExpbmVDb3VudCI6NjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4MGVlMGVlNzM2N2FmM2ZmOWFiODcxYWUwMTI2YjQ2MDY1MThiNGYzNjM5N2Q5Njc1ZjE5ZjQ1NTExMDJmYWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM5ZWRmZjJhNDQxOGNlM2EzZGE4MmM0ZTVmMWFkYjNiNmI3ODExYTU3ZGUwOWEzZDJiOWRlM2I2NmIyYzdhNTgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE4NTUxZjM3NmYwYzQzZTZmYjczNDI2YTFhOTA1NzhiOTM0ZjBhNjY2NjM3NTA4N2RkZmY4NTVlZGJiYWM5ZTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNlN2FjNWYwMTAzZjFkMDlmOGNhMTAxODgyMDU5NzM4ODY4NzdjMmM1NTRkOWI3MzU0MmFlZWFmYjAyNDc4NjYifQ" + }, + { + "resource": "repo://TFMTests/WindowSidebarTests.swift#L46-L124", + "version": "repo-lines-v1:sha256:4a7890314d8b06976cb8c0138504e183510892cf9e9556c2d8dee49174149176:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg4YmZlZDBhOWM3NzUyOTQ4ZWY4ZjRlYmRhZTcxMDM3YjYxZTQ1ZDk0MDFiNGFlOWU3YmZkYzI3ZmI5OGQyZTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYxNzBjNDZlM2Q5OTBjMDNiYmM1ZjBmY2JlZjA2Zjc4ZmVmMTA5MjRkNjZhMjAyY2Y4N2EwZjIyZmU3MDcyNzUifQ" } ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/platform-runtime.json b/openwiki/.claims/architecture/platform-runtime.json index ce386b2c..47014ece 100644 --- a/openwiki/.claims/architecture/platform-runtime.json +++ b/openwiki/.claims/architecture/platform-runtime.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:d3cd20c0a6365a0e940e562495075e28f5f59946fe18b68e5c8b459e02b4571f", + "pageVersion": "sha256:b2e31af1e23b8eb56a0e9eaabf4e5a5b0a0ad90c94c725aa451f629dbe390f3f", "claims": [ { "id": "claim_bd9f5ddda6b6466eb79c622b02fd73f2", @@ -20,7 +20,7 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" } ] }, @@ -30,7 +30,7 @@ "evidence": [ { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" } ] }, @@ -40,7 +40,7 @@ "evidence": [ { "resource": "repo://TFM/App/AppModel.swift", - "version": "repo-file-v1:sha256:5284fc38208bb02af017031469b91288fedd0383d59f391622aa4c32a8450f42" + "version": "repo-file-v1:sha256:0029784efe4588e87c3dc18317fdfaad46bed6b3a32bcf72dd0dd9b1c9da256e" }, { "resource": "repo://TFM/App/RootView.swift", @@ -82,11 +82,11 @@ "evidence": [ { "resource": "repo://TFM/App/AppModel.swift#L669-L693", - "version": "repo-lines-v1:sha256:3fdd3e3a61b4f0fac27a94144beb60ee81bea2eb973de02975ed94e17607bcf9:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiNmE1OWU3Nzg2NmU1MGRiZDYxZjA5ZmQ1YWM2MjQwN2Q0ZGVlNjdkNGIyNTJhNDExYzRhZTEwZWNmMWQwNmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzODNlN2M2MmI5ZmI0ZGU3YjNjNTc3ZmFkNjNiOTYxMGRlZTcyNmI4NzljYzZjN2M5ZjYzNTljOTU5YWEwODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzNmM5MGE0M2ZiOWQ0NDg2NzI0NmE0MzY5ODk4YWZkOTFiOWUyYjM0OTZmMjU3OTg1YTk0MDFhZjY4ZDI1YWYifQ" + "version": "repo-lines-v1:sha256:4088a1395f839fa08e6e42d1dc28faa30416dc463f43b9354b941ebf4e582043:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiNmE1OWU3Nzg2NmU1MGRiZDYxZjA5ZmQ1YWM2MjQwN2Q0ZGVlNjdkNGIyNTJhNDExYzRhZTEwZWNmMWQwNmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzODNlN2M2MmI5ZmI0ZGU3YjNjNTc3ZmFkNjNiOTYxMGRlZTcyNmI4NzljYzZjN2M5ZjYzNTljOTU5YWEwODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzNmM5MGE0M2ZiOWQ0NDg2NzI0NmE0MzY5ODk4YWZkOTFiOWUyYjM0OTZmMjU3OTg1YTk0MDFhZjY4ZDI1YWYifQ" }, { "resource": "repo://TFM/App/TermindApp.swift#L331-L380", - "version": "repo-lines-v1:sha256:dba035b03cf3758c5dd56a198c82d72e009987583daf5432a41a80018be9c9f2:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg2MmZlMmQ0YmFjM2JhZjAxN2NiYmY5MmFiMTcwZTQ0NWExMWQxNzYyODBkZDEyOTdjZmM2ZDQxZjI2Y2NlMGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdlMjAyMDc0MmMzM2IxYjkxZWIyMjYxNmJmYTg4NWMxNjQ2NThlM2Y5YzAzZDNkODZhYzllMjgwMGRkYmNhMzcifQ" + "version": "repo-lines-v1:sha256:af7cb9bc2d40d80d6078769faf6bbf1fe1a5b20164b5d9d6f3c4f6ff36236ea9:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg2MmZlMmQ0YmFjM2JhZjAxN2NiYmY5MmFiMTcwZTQ0NWExMWQxNzYyODBkZDEyOTdjZmM2ZDQxZjI2Y2NlMGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdlMjAyMDc0MmMzM2IxYjkxZWIyMjYxNmJmYTg4NWMxNjQ2NThlM2Y5YzAzZDNkODZhYzllMjgwMGRkYmNhMzcifQ" } ] }, @@ -116,7 +116,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" } ] }, @@ -144,7 +144,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFI/App/MobileSceneModel.swift", @@ -152,7 +152,7 @@ }, { "resource": "repo://TFITests/MobileAppTests.swift", - "version": "repo-file-v1:sha256:d2466771edf0d6d85ccbd8d5c6a8a7cd05521af153016478430a466085380ba9" + "version": "repo-file-v1:sha256:b2c528520ad5272155355404f91af52e490c6f17780a845d9e8a596c523484ef" } ] }, @@ -180,7 +180,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift#L512-L544", - "version": "repo-lines-v1:sha256:b41d3de43fde9c50d0b478946d6263804791efe4519784713c872a1679a205dc:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" + "version": "repo-lines-v1:sha256:b0fa484bcb19ae7f887f203d3b438c9bccc7b5936706cd85d285e53c0f9b31d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" }, { "resource": "repo://TFI/App/MobileRootView.swift#L49-L51", @@ -216,7 +216,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFM/Features/Workspaces/Pane.swift", @@ -233,30 +233,244 @@ "statement": "Both app composition roots create an app-wide DeviceDirectoryModel with the Vault installation ID. macOS names it from trimmed kern.hostname with a DeviceKit fallback; iOS uses Device.current.safeDescription directly. Foreground activation refreshes the directory record without rewriting connection events.", "evidence": [ { - "resource": "repo://TFI/App/MobileAppModel.swift#L204-L207", - "version": "repo-lines-v1:sha256:e4c05ddc982049c744719ce0e23ec5e9583f75ad8cdf645293c1d455c1430051:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiY2M3ZjhiYzVmMjYwMjJmY2QyMGMzM2QzN2EyMTA3MTc5ZWNiYTMzNTAzMzgyNzAxZDg3YTM0MmVjMDQzZjNjNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYmU1NDFmMThiZTNlOTczZTBjY2Y3YzQ1ZjljOWRhMmE3ODU2ODYxMDk2NDA3M2EyNGFhOTg0Zjk2MDVmYjJiZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNmE5OTJjNGI5YTNmYzZiMzgwNDU3ZDAyZGU5N2I3ZjJjYTg2NmE4MmEwZjdlNzg2OTc5NzhmZmRkOTExOTgxMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTYyMmI4OWNhYjU0MGMxM2UwNjFiNTdjNjQ5ZDY3ZWMyMTZhNjY0YmJmZGZjNDg3YTAyM2JkZGIxMTYxMGU0MSJ9" + "resource": "repo://TFI/App/MobileAppModel.swift#L201-L210", + "version": "repo-lines-v1:sha256:4f516b911b69847058eaab07c798fe64dfeafa277166dba252d21c44e382448b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk1MDE4Y2FmY2ViNTI1ZTZhZjQzN2JjZTEwMzI3OTQ2YWM0MzFhMDI3YjI3MjQ2NDE4NjBmZTc1MTBhZTMyMDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJlODRkMTQ0ZGU1YjZlY2NlODY0MWZmMDQxODBmOWEwZWQ3MjkwYTRiOTU3ZWZhNDVlM2U1YzkzNGI5ZWU3YWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVmNmY0MTY5ODIxNTkwZjRmMGJjZDljNTYzYTc3NzVhNjM1N2JlZDc5ZjM0NWVmNWVmOWUxNTY2MDdlYmNkM2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE1MDNhZTlmZWY1YTRiZjM5ZDIzZmQ0MDRmYWFiYTkyMDY2MmY0ZmEzODUzMjkxOGVlMGI2MmE0OWNhY2EwZjIifQ" }, { - "resource": "repo://TFI/App/MobileAppModel.swift#L580-L589", - "version": "repo-lines-v1:sha256:71bcd9d234f4fe43fb8074f23095acbfa238266403359ce6f85621ad7d170c6d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc1Nzg1MjI2MjQyOTAxY2NkOTlmMTgzNjZjYTdhOGNhOGEwNTc1YTA0OGNkOGU3NTZlZmI2ZmRmMjc5MTFiNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQzZGFiZTIzNDEzOTNjYzU1NWUzZjI0MzRlOTFlZTZjYjVjZTNhYTgwNWEwOWVhNjA2YTY1MDI3YzNlZWUzY2UiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMzNDVkYzM2OGMxODNiMzEwOTZlMDYwYWFiODA1NzE2MTY3YTYyNDQ5MTgzMTM1NjJlMTgzNmQ1NDk0ZjIwMWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY4ZWY4Mjc0MmI5NzUwODBiMTdhNDZjZjVjMDYzOGM0MmY1ZGYxNjE3NTBjM2U0OTY1MGRhYTc1OTQzNjJmMWIifQ" + "resource": "repo://TFI/App/MobileAppModel.swift#L560-L578", + "version": "repo-lines-v1:sha256:b0fa484bcb19ae7f887f203d3b438c9bccc7b5936706cd85d285e53c0f9b31d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" }, { - "resource": "repo://TFM/App/TermindApp.swift#L285-L294", - "version": "repo-lines-v1:sha256:4f92aff6ab1ede611953c68748bb9269d0f87191ba08801a24ee1e1968e1fe94:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2Y2JmMWEzM2ZlOWQ1MWIwZWY0MDc2MzM5Y2MxMDBhZTIwZThhYmM5Njk2ZTM5ODYwYWNiZjZlNWFkNmU0OGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYwYTMzOTQyMzQ4NzRjMmRkNjYwMzEwZTMxZjZiNDAyYmY4NjM1ZDAwZmI4OWVmN2E1M2VmOTAwZmEwNDlhYjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVhZmNhZTk2NzVmZWU3ZDkxZTJlODNmYmY5MjI4MGQ1NmFjZGQ5MWFjMzFlODg1MzA3YTNhMTcyM2MwYzFjOTkifQ" + "resource": "repo://TFM/App/TermindApp.swift#L317-L320", + "version": "repo-lines-v1:sha256:1ee408a9a5507918379d16437b19820e165a6ac4f23f4bb06987770b0e8aa179:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNDU5MDRhNmM4Yzk5NmRhZmEwYmM3Mzc4YTJhNDQ4YjM2MTNhODQzNDgzNGYxYjdmMGU5MTMxMzc5MGU0ZmJmOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMGZiMTRiOTAyOWQ0OTg1MmNiYWU1ZDNkMjc3M2I2NTA1NGFjYTU0NWI2NDI5MmZjNWY5MWEyYjU2MGQ5MDU2OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZThmZTBiYmI5NDc2N2JkNzQwZWYwN2NlMDI5NTc3MzZhYTBjNDE2YjMxODIxMTZhOTAwNDhmNTUyOTJhNDg3MCJ9" }, { - "resource": "repo://TFM/App/TermindApp.swift#L90-L100", - "version": "repo-lines-v1:sha256:99c03b236bf8dffd11d7dc7a6c3ebbae74a50a0d5ef1bc523799c17d53c040fd:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUyM2I4NzQyMzJhYmM3NDhjNTI1NDkzNjk2MmQ0MjliMjM3ZmEwYWFiN2VkZDUzZDY5MzY1NWJhZGZmNzFjY2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZhYWU3ZDJkZDk1OTRkNmMzYmViZjE3Y2FlZTgzOTllYWIyMTNlMjM3NGQ2MWZhYjY3MDc5YmVjMTYwMjg2MTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI2NGY1MjY1NmMwMzEyZGY4Y2IzZDcyN2JiYWFiMTVlZWM4NmE1ZDcwYjJiNGMxNjNkNWM3Zjc1YTNiNTdlZjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY1MDFlN2VkMjlmY2YzZTZlMmE3MDI0NDZhNzQzZWRmMWE3ZGQ3MGVlOWY4ODg4ZWYwOGI4NTFjMTc2Yzc4YzQifQ" + "resource": "repo://TFM/App/TermindApp.swift#L84-L100", + "version": "repo-lines-v1:sha256:01cc489e7587e0656b402cdd3bfe9f089758ba5d920b6bb9a538388f4d0f4727:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0YzA4NGU4NjI3OTA4ODY3YzIxYzc0MWVlZGQ0NzlhM2ExMGE5MDk4NzQ2NTZmM2E1N2YyZDU1Y2MyMWExYTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZhYWU3ZDJkZDk1OTRkNmMzYmViZjE3Y2FlZTgzOTllYWIyMTNlMjM3NGQ2MWZhYjY3MDc5YmVjMTYwMjg2MTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFjYTEyOWUyMWU4M2NhYmM5MjYxNTk2OWFmYjUzYWM4NGEzNjlkMGNjNzU5NTAwYTMyOGZkY2Y0NWE2Y2ZhOTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY1MDFlN2VkMjlmY2YzZTZlMmE3MDI0NDZhNzQzZWRmMWE3ZGQ3MGVlOWY4ODg4ZWYwOGI4NTFjMTc2Yzc4YzQifQ" }, { "resource": "repo://TFM/Platform/MacDeviceName.swift#L5-L29", "version": "repo-lines-v1:sha256:2e3a802d84fd2b017f0074f76c3ef896d3127453e0142f3a054521e823ba686f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzZWIyNmFmMDY4MGI1ZTY3MGVmYjZkZGRhNjRmNGEyMzVmNDhmNTE2N2NlMWY4OTYwMDQ0MDU0MGE1OWRkMzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVlNGQzYWNkOTllYjdjOGNhNzFkNzZjODJjMTIxOTcxNzU5YjBlOTFmODVlNzhhNWQ1NDJlOWUzNWQ4ODFhODUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" } ] + }, + { + "id": "claim_8458fd10112344259c4df10ea229d356", + "statement": "On mobile, reconcileSync starts all three optional sync coordinators only when a tracked scene is active and Pro allows Vault sync; otherwise it pauses all three. The coordinators separately check global iCloud and category-specific enabled preferences before syncing, and mobile sync-setting changes trigger reconciliation.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L148-L170", + "version": "repo-lines-v1:sha256:459356fe969639fa153e66541bd0fa25df2bc3e30fd3ebad13d65d21541398ae:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiMzk4YmYyMmYxODdkM2JhNDcxZjBlOGUwZTgzZGMzMzkwMjAxMjM5YjgwYWI5NGY3ZmQ2MDUxZTI0NzVhZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5MzczZTY2MjhlM2ZjOGE5Y2VhMWM0ZTFiOTMxZTA5N2UwYWI0NGNlOTgxNzI4MjBiZDk0ZTdhMTU0YTQzY2MiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1N2M3Y2Q2OTJmNjFlNGIzMzVlYjhiNWRlOGYwNDQ3YTVjYTljZmQ0NDhmZjE5MmE1ODE5MjUzYzIzMTRkMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlZjg1NWY0ZjEzZTAxM2EyYWMwOWYwN2EyYmFiOGMxMWYwNGFjMjU3YTBiZjNmZjcxZDgxZWIyZmJhMzJlZWYifQ" + }, + { + "resource": "repo://Frameworks/TermindInfrastructure/Cloud/MetricsSyncCoordinator.swift#L104-L108", + "version": "repo-lines-v1:sha256:4fee0282690c2b28c7290c5554b58bb24f3a74d17070899bd96a1946507763d0:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTdiNTE4YjI1MGMzYzk0YTNjNjkzNWQ4N2EwOGM3ZGFlMWViYmY4MTQ2YzgwYTMzYjdiNjc4ZWUyYjg0MzQwNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNWU5MWE1YjE3NDdiNmU5OTlkNmU0ODQ3NTA1MzgyZjRiNmM0MzNjMTM0MTQ0YjE5NDliMjUyY2NhYTAwYTZkMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZjMzMDMyZTUwOTQzNGUwZjliNjg0MzMxODdmYTM2ODEyOTZlZjQ2NGJiMThkOWM1NGM1Mzk3NjNkNGE5MDNjYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDA1ZDViNzNhN2ZlYWIxZGM3ZTQwOGNhOGU5ZTkzZjFiN2MzY2IwZWFlZTA3YzY0YmNlYTJlYTEyNzlmYmMyNCJ9" + }, + { + "resource": "repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift#L114-L120", + "version": "repo-lines-v1:sha256:70bcf5ece01007fbddd3f9e4f01e5a9f305a75e591a6a5ae9f24e2407252ee13:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTdiNTE4YjI1MGMzYzk0YTNjNjkzNWQ4N2EwOGM3ZGFlMWViYmY4MTQ2YzgwYTMzYjdiNjc4ZWUyYjg0MzQwNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYTcwZGU4MGYxMTg3ZWU2YjIzNjJiYTkyM2JlZjhlMTUzYzcxMjllMjE4YzA2ZTJjM2M3NGFlNDk4NTFlNzg1ZiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZjMzMDMyZTUwOTQzNGUwZjliNjg0MzMxODdmYTM2ODEyOTZlZjQ2NGJiMThkOWM1NGM1Mzk3NjNkNGE5MDNjYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZDRiMjEwZWQxYjBiZWQzYTk5MTRhNTBiYWNmMzZkNWVmZDIwMWZiMWQwMDY5M2I5YTMzOThiYjI0NWYyZjRiMSJ9" + }, + { + "resource": "repo://Frameworks/TermindInfrastructure/Cloud/VaultSyncCoordinator.swift#L103-L108", + "version": "repo-lines-v1:sha256:29594bc1782932dab0cecfcfd0731971be0407378ca539c5a47b75072f2f9ce5:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYTdiNTE4YjI1MGMzYzk0YTNjNjkzNWQ4N2EwOGM3ZGFlMWViYmY4MTQ2YzgwYTMzYjdiNjc4ZWUyYjg0MzQwNSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYzZlYjU3YjAwZjk2YWQwZDRmMTc4N2Q5ZjlhNDY4ZGVhMzUwZTFjZTVkYWQxMGZjZjA1OWI4NTlkMzdmZDg4NyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZjMzMDMyZTUwOTQzNGUwZjliNjg0MzMxODdmYTM2ODEyOTZlZjQ2NGJiMThkOWM1NGM1Mzk3NjNkNGE5MDNjYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDA1ZDViNzNhN2ZlYWIxZGM3ZTQwOGNhOGU5ZTkzZjFiN2MzY2IwZWFlZTA3YzY0YmNlYTJlYTEyNzlmYmMyNCJ9" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L560-L601", + "version": "repo-lines-v1:sha256:e4d71366b6436398ee043c247f55f33d49a7e76e504b4fe8e18f86aa0bfd3f46:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3YzFlN2NkMjk4NDdjY2ExY2U2MjE4ZWQ4ZGRlMDJkYzFiMTIzMmFiNWE0OGZlYzVjNGU5NGIxOWYzYThlMzkifQ" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift#L66-L70", + "version": "repo-lines-v1:sha256:79b409add9ae91fe33cfece07140957972cc7fbc90784c9ed0fa6f6074cfdb8e:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjJiM2E2MGVmNjIyMmQ0ZmQzYTA3NTg1ZDY2MTIzZDRiZTdiZWQxNTljYjljMmMzNzE1MmE3N2U0MDU2Y2M3YiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNjI3NWQ4N2JkZGJlMzU5NmYyMmI5MDQ2ZDI0ODY1NDEzZDBjNDY3MTk3NWVkNTBhMGVkMjNlZjE2MTU4MWZhNSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZWJhY2RhMGQ2YTI1NzMzOWRjODc1YjBhODhhOTAzZjBkOGRjMzYyNjQ5YWJmNDBlMmM4Yjg0ZTc4OGI5MjM1MCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNGIyMTExZDRjODA0YTYwN2Y2YzdhNTc1OTZmODc1ZGVhNzdmNTc1NjU4NzYyNGY3NzFmYjY0ZTdjMjg3OTVlOCJ9" + } + ] + }, + { + "id": "claim_2b1d956abd384217af29c7ce6f50a159", + "statement": "Desktop AppModel starts and reconciles Vault, Metrics and Settings sync according to Pro access without a scene-phase gate, but each coordinator retains its own global and category-specific sync enabled checks.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift#L148-L170", + "version": "repo-lines-v1:sha256:459356fe969639fa153e66541bd0fa25df2bc3e30fd3ebad13d65d21541398ae:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiMzk4YmYyMmYxODdkM2JhNDcxZjBlOGUwZTgzZGMzMzkwMjAxMjM5YjgwYWI5NGY3ZmQ2MDUxZTI0NzVhZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5MzczZTY2MjhlM2ZjOGE5Y2VhMWM0ZTFiOTMxZTA5N2UwYWI0NGNlOTgxNzI4MjBiZDk0ZTdhMTU0YTQzY2MiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1N2M3Y2Q2OTJmNjFlNGIzMzVlYjhiNWRlOGYwNDQ3YTVjYTljZmQ0NDhmZjE5MmE1ODE5MjUzYzIzMTRkMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlZjg1NWY0ZjEzZTAxM2EyYWMwOWYwN2EyYmFiOGMxMWYwNGFjMjU3YTBiZjNmZjcxZDgxZWIyZmJhMzJlZWYifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L340-L361", + "version": "repo-lines-v1:sha256:582650738d34923d769f4519bc488d4dd520015e975720cfc61641e73097da72:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY3MDMyZjUzOTcxNDA0YjMxMjM2MmZkYmQ5MzlmOGRlNjYzMGRiNGVhNTQ1Mjk5MTUxNDVlMjNmY2RjNTc0MGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdhNmVkNDJiNDliZDBjNGNkMDNiZmMwMzRkNzZiMzI2NjliZmYwOGYwOTE5OTRkMDUyNTIwODllYmEyNTEwNWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU4NTUwNThkODhkZWZkMWYxYzM1MDQ2OTE1ZjQzYzc3MmUyYTVjMWI2NTRmYThhYmIwNmE1NjA5YjM3OGViMWMifQ" + } + ] + }, + { + "id": "claim_0622c71c72294d5fa2b9954b3b43e13c", + "statement": "A local mobile Host deletion closes associated saved and live workspaces, retires runtime dependencies, requests durable repository deletion, projects removal and starts the outbox; a failed request reports an error. Remote removal also prunes opened and unopened workspace descriptors, while route changes disconnect affected sessions without removing descriptors.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L488-L523", + "version": "repo-lines-v1:sha256:fe29c1aa8634b5d3b7e41f762b60c7d82e05751fa29720ce5c638a4c69453919:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMyMzMyZThhNDhhYmJlNGM3OTVhY2U4ZmFjM2RjM2M2OGRmOTAxMGU5YTEzYzIyYzkxZjE3MjIyYTlhODg4OGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRlMGMwYzg3ZjJiZjhhNjVmNDIwYmY3ZjkzMWVhMmZmOWZiZmRjNmI4ZTlmNDg0YTdmNTgzNjhkMmRmYjE0NjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlkYWU1NGY5ZjkwYWVmNTQ0ZjBhZTQ5MDAxZjQzMmY4NTUxYzZiZjU0OWZlMWYxM2E0YjEyYTQ1MDVhYzUzMmUifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L603-L634", + "version": "repo-lines-v1:sha256:2b17d09836cd982b03982416cec87456a70533270eee87d5a3e6d89488bea78f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNhMjA4N2I3YjllNTQ5ZjEyNjNhNmJiMWY3M2JmYzYxZGFlM2I2ZGIwODdjMWQwYjFhODk3MmIyYTVlNzNjOTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxNzMxNDIwMjQzNGQ0Yzg0MjI5MGRkYmY3M2RkNDg5ZTM2YmI4M2UzYTIyOTY2MmI2YjI3MWQxYmNiYWZjMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5ZDFkZGZkOTM3OWY5N2QyNTllNzJiNGU3YjNhMTMxYmNkN2U0NWNiMGVmZGVjMDA2NmRiMTc3MTdkMzYzYmIifQ" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift#L1763-L1787", + "version": "repo-lines-v1:sha256:c0fbcf17b1adca98ce3c7dccb8a75f0785243a7566f85815aa0f1feb7088c62a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4ZmRiMWE0ZmJiNDNlODMyMWI3MmU0Y2Y1ZmI2MDViMzJjMGRhMDlmMDVjZjQ2NjRkOTk1ZWFhYWZmZjk3YjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5ZjIyMjVkNWRjMWRlOWYyNzFmZWVmYWU5ODc2MTIyYmQ2MDY3YjVmOWUxMTlkN2U5ZGJiOGJiOTAyOTRmNTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjEyM2FiYjcxYzNjZDlkMzhjMzA1NjA1MTVhMmUwNGNkMmE0MzliNGFmMmViN2QwYjc4NWFmYzA5YjBkMmUzNzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg4ZmVkMDVhNzZjZTkzMTcxNDhiNGQ5YzE2NDM0MDhmNjI3ZjhjMGFiYTgxNTM1OWU2MjU0ZTliYTUzODU3OTcifQ" + } + ] + }, + { + "id": "claim_60b90acf3e6544f0924c0a007e6a8f91", + "statement": "A desktop Host deletion request persists the repository deletion before projecting removal and clearing histories; outbox handlers coordinate closing window-owned workspaces, canceling transfers and forwarding, clearing references and final removal. The SwiftData deletion marker and all outbox jobs are committed atomically for crash recovery.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/Events/HostDeletionHandlers.swift#L44-L79", + "version": "repo-lines-v1:sha256:af38596b23d9dca49bbb77bee2bcb0592407a5409219e643324eef08fa9e850c:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI2MzBkNDEzNGFkMTlkMGIzMzE2NGM0MWIwZTVjZjM1OGYzNzNkZjYwMTdkODUyNjNmNzgwNjg3N2MwZjU3ZTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift#L75-L105", + "version": "repo-lines-v1:sha256:f7e780781ac32ec01ee8af20f96c6d3e6d4680cf07cd2f2d36b5e040350b3e73:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiZjZiOTc3YTk5YjNlYWI1NjczZTA2ZmRhZmEwYWMzOTUwYzMxNzE5ZDhlNzk0MDNmNTU4Y2QwYjcxNWNiMDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE1NWYzY2JlMGM5ZmYwOWNhYzIzODllMDdhZjJhYjRjODY0YzMzNWZmNTdhOTlkMDNjYWZkNjdlODBhMjU3MTYifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L299-L319", + "version": "repo-lines-v1:sha256:c4ab6396c4fe7d94f9e848fa79ab48ef918b8e6edab3d487203835cb5f3dff2c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxOWE1ZTNjMDdkMWZiODZlNzgzODQzYjBjOTc0M2UxYzkwYzg1NGQ0Yzk0NjFjOGYyMmExNmUyNTBhMDkyNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAwZGFiZWIzYjE0Y2NiNGI4NzQyMTc1M2EzOTFmMTA3OGE0N2RkODYxNGVjNGY4ZDU5YzY5ODJkNDM4NmExODYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ0MWI1MmU1NGU3ZTNiZmRhOTZkNGZhZWU2MjE4NTg3NmQ2MDliZjQzMDQwMmU4NmU2MDExOTlmYjE1MjRiNTEifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L663-L693", + "version": "repo-lines-v1:sha256:ea8d5864bc88f5669e2845844bbef5319000ff729dc380fe611b2785a616cd6a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3MjIzZDg2ZTU1MjY1MTNlYWFhNzdlYmJkNDM0YWViY2RkNzViYWM4MDViYWFmZTQ5YWFmOWNjZjdiMjgyNTkifQ" + }, + { + "resource": "repo://TFMTests/RepositoryOutboxTests.swift#L171-L225", + "version": "repo-lines-v1:sha256:ad9c22e52d711d38cc42f14895e71362ff34e0a9b026c077ad70076535a8a300:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVlMTdkMGM4ZGNmYzQ1YTllYzVlMDExZDhmMWQwYzk1NGJlNTcwNDg5NDk5ZjQ2MzFiOWRmZjMzMmJjMzFlODMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY0MTdjMzdkZTI4YmZkZDBkNDA4OWI1ZDBjYzdiNzE5NmJiMjI5NGYzNDAxMmI5NmFjY2NjYWYzNjRhNDQ0YjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmZDJiODY5NDJhMDYwZWZjOTk1YzQ2NDFhZjQ2NDZjNDEyNTA2Y2EyM2RlMjZiOGUwYzY2MWEwODhkNGMzNjgifQ" + } + ] + }, + { + "id": "claim_0f846fc667814b1dba324b10557a622f", + "statement": "Desktop shutdown fences new assistant runs, cancels run preparations, stops stored conversations and waits for their terminal persistence before closing agent background commands and connection pools; repeated calls share one cleanup task, while the AppKit termination reply has a once-only three-second fallback that does not guarantee cleanup completed.", + "evidence": [ + { + "resource": "repo://TFM/App/AppModel.swift#L724-L778", + "version": "repo-lines-v1:sha256:4088a1395f839fa08e6e42d1dc28faa30416dc463f43b9354b941ebf4e582043:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRiNmE1OWU3Nzg2NmU1MGRiZDYxZjA5ZmQ1YWM2MjQwN2Q0ZGVlNjdkNGIyNTJhNDExYzRhZTEwZWNmMWQwNmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzODNlN2M2MmI5ZmI0ZGU3YjNjNTc3ZmFkNjNiOTYxMGRlZTcyNmI4NzljYzZjN2M5ZjYzNTljOTU5YWEwODQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzNmM5MGE0M2ZiOWQ0NDg2NzI0NmE0MzY5ODk4YWZkOTFiOWUyYjM0OTZmMjU3OTg1YTk0MDFhZjY4ZDI1YWYifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L217-L241", + "version": "repo-lines-v1:sha256:850e12a59f116f944049eaf0226a5d7979e0610d2e89b9adf9e7b220b02dc96c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMzNzRjMTE1MjIyZjljYzUwMWEyMjliZmUyMDk1YTNkZWZmMTFiMDg2MjFmOGFiMmI5MzgwZWEzMjQ1ZWM5MmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhMTE1ZmUxY2Q2ZDFkNTg2ZTIzYWM3NTJkODUyNzQwZWQ2YmE5ODNlZmU2NDg0NTMwNDM0YmM4MTBiOGQ5ZGUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxYmJkYmE3MTE3NjI3OTU5NzBjZWQxMDc4MzhjY2EyMGY2OGJkYmM0OWFiODdiNTE5YzcwZmEwOTdiZGU0OWIifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L383-L422", + "version": "repo-lines-v1:sha256:3584a07a98a3152e8413b2ca3dab7ec5452440020bc87aa0c1a67dad6ee6df69:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMmJlMTBlOWQxYjNjMGE2OTYxNzZmMGYyMDQ3MGVhODMzN2FmYzI4MWZmMTIzYmNmMmRmMjkzMTNkMDIwMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4NWYxZjhkMWY1ODkwZmNjMTE1ZWMwNWRlNGU3NzA1ODdiOWRjNDlkZDhlM2IxNTViYmUwYzI4NWI2ZWQyYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhiMTg2M2Q4Njg3OTcxYTY0ZjViOTdkMmI1YTMzNmYyYWE0NTIzYWU3MjU2MDIxOTg2YTQ2MjdlY2ViMTUxMzEifQ" + }, + { + "resource": "repo://TFMTests/AppTerminationTests.swift#L12-L66", + "version": "repo-lines-v1:sha256:6ad8d7bcd045badb3fc0b39ec827c2092c78053e237fee649338c10c207fe520:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk2NjIzZDExNWQwMWY2ZjNiNWJhZDE5NTgwODNkYmY0Y2U0OWVhNDIxZTY2ODZmNThlODQ5ZmU5NThiNzhmYmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMxNTg4YmUwOTg1YmY0YjM2ZTM2ODU2NmViNjlmMjI3NGVkN2UyOTIwOWFmYTJjYTYxNjFjYWU2OTFiODA0YjYifQ" + }, + { + "resource": "repo://TFMTests/AppTerminationTests.swift#L163-L200", + "version": "repo-lines-v1:sha256:23741adb64c4324b01aab2e7b6c1ff5b763b7be042588dafeb2e55ddb2254e05:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzYjI4MzBlZWZiNWU4Y2YwOGEyZmUwM2FiY2M3MjE4NTI1MDljMzkxNWI2MDEyNGQ1YWQxZGQ2ZTA4MTUyOGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwMWUwZTUzYzVjZjJmYjM3M2ZhNjdiZGYxZWIxODUzZmI5ZWUyMmVkOWUwZWQwZTdiMWQwNDFiOGYwN2Y2ZjcifQ" + } + ] + }, + { + "id": "claim_f5a139ba25c14953b8da0eb26bbf5034", + "statement": "MobileBackgroundController owns one finite UIKit background-task lease at a time, retires a previous lease before beginning another, ignores stale expiration callbacks and retires the lease after expiration or foreground finish; an invalid task identifier triggers immediate expiration.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L647-L664", + "version": "repo-lines-v1:sha256:8613dda7483542917c347fbb037141f5d2ec700d16c61b5ae233ade853ad9dc3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZDY0ZTIzNWJjNzZlYTM1MDI3NmE4MGZlMGM1NjM0ZTYwZDFkZmUwN2FjYWQ4NTJlMTFhMWQ2MjkzM2ViMTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyMWFjNTE4NDc5MWIzNWNkZTM4MDkzNDU1MTVjMGFjMDEwZjA3MGVhZTAyMTRjZGY0MzIwZDE4NzI5N2M3MDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM0Yjc0YmRmNzgxODA1OTJlM2YyOTM1YzcxMzhlZmU1MDA0NzZhNjFjOTllMGZiZTcxNDVjYmRlMDBkYTU5MmEifQ" + }, + { + "resource": "repo://TFI/Platform/MobileBackgroundController.swift#L27-L84", + "version": "repo-lines-v1:sha256:b633f63ef830e7665dc60afef2702d82bfbfd1cac1b84192699778c674465a93:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + } + ] + }, + { + "id": "claim_a6a08ce71d4e4c03b800d416e2640b89", + "statement": "UIKit Home Screen quick actions are staged per MobileSceneDelegate and consumed once by the scene's MobileRootView; MobileSceneModel routes connect to the picker and recent-host actions through the Host's current preferred connection kind, reporting unavailable hosts rather than restoring a stale session.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileRootView.swift#L62-L65", + "version": "repo-lines-v1:sha256:a3aafc560b106a51680e89e13e2e2ba7b5bfb1dea6e9edd0457e661480a68197:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTYwNmQ4ZWZjMGM3NmEyMmU0ZTA1MmRlMDcwMDAxNmUxMmRlZDdiYjQ5ODlkNzU3NmJiNWUxYmIxOGE5YmJlMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNTUyZGI3ZjY2NDBmYWRlNDY4NDM0OWUzZTc5YWRkYjRhYmY2NThlYzEzMWU1ZDZlYWE0YzM1NTE5ZjliMjc5NCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZjFiOWI3MTNiNDM4OTk2NjZjYzFhZTUwMTg1MTEyNzdjZWY4ZTRmZmRjYmY1NTgyYjNiYTc3OWFkYmVlYzE5ZiJ9" + }, + { + "resource": "repo://TFI/App/MobileSceneModel.swift#L88-L105", + "version": "repo-lines-v1:sha256:14eed48b39ce10f59fee0068214b04db5f0f481e900b4ed0a90dfc1d866798a3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ0OGI4ZWMyMjc0MGQ4ZDA4YjAzNDZlMmE1OGE3ZTMwYTEyNTMzMDNmZTU5ZTJjNWE4MzE4NjY0Mzg1NTI0M2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNmODZjOGRkOGIwOGUxYmE0MWEwYzhiN2Y0NmQxMTBmYzFhZTk3YzRiMzk2ZDNlNTk3YThiMjk1Mzg2NDFlMWQifQ" + }, + { + "resource": "repo://TFI/App/TermindIOSApp.swift#L36-L46", + "version": "repo-lines-v1:sha256:0681b01e675cd4f53716b1814ac976c4a7a3277abd25b7af14727d9e840c549d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4MDEwNDA4MDFjM2I5OGI0ODY2MDQ5MmRjYzkzZGFkYWMyMjlmYjk2M2JkZTYyYzk5M2VkNTkzYjdlNDUyY2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFI/Platform/MobileHomeScreenQuickActions.swift#L88-L119", + "version": "repo-lines-v1:sha256:754b3c470d8bf48e70d8bf829bbb1c312cda69c36379bcd1e3d53b48d96123d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + } + ] + }, + { + "id": "claim_091fa53c71a34d739f389a438041eb83", + "statement": "Mobile Home Screen recent-host shortcut items are refreshed from local connection history when scene phase, history or host configuration changes and are limited to three openable recent Hosts; unknown and malformed shortcut payloads are rejected.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileRootView.swift#L49-L61", + "version": "repo-lines-v1:sha256:249ac9c410d430a05c01d60a3f50dad3ec3d6f422327fd2c794d220961356430:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwNmIyOTNhY2FiZjI2YWJjZmZmNDhiYzNlZmVkZTIzZmEyMDFiYjA3MDMzMDMxYzcwOWVkZDc2NmQ1YjQ2NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5MzEyMzk0OTNhNjBlYTFkOTllZWQyZjE3MTljZjEyNjZmMThlNTE5ZDQxZTZmODNiMjYwNjg3ZjUxZTA3OWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVhODJkMzE1MjUzMGQ4NzVhM2U0ZTA1ODYyMDQzNTI2Zjg4YWY3ZGVkNzkxNjk0ZjdjZWZkNTQ0OGQ5ZTY3MGIifQ" + }, + { + "resource": "repo://TFI/Platform/MobileHomeScreenQuickActions.swift#L53-L85", + "version": "repo-lines-v1:sha256:d61cefed43f210f7ad7e714850a75960082d617c06fad5bbba053929b04142de:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYwMjEyZWU1ODM0MGZjYzliNzkxNTZlZDdiYjIwNjQ0YjJjODJhYzM2MGMzZDdhYWU0YTZhZWQzZjg3ZGVmZWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ" + }, + { + "resource": "repo://TFITests/MobileHomeScreenQuickActionTests.swift#L13-L99", + "version": "repo-lines-v1:sha256:e64ef71db78459dd5c501551f9cf9bb8e02172db307bc2ed4feca0700a0baca5:eyJzZWxlY3RlZExpbmVDb3VudCI6ODcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRhNWQ1NzkwYTUwMTk1OWQ5MzcyNDJjODJlYTQzMTdlZjI4MjA1ZDUyYTY1NzVkNGFlZjRiNDA1ODE1NTRmNzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlmZTI4YTNjYTA5YWVkYTRiNDFlMzhhNzU1OGZlNTAxMWJlNGNmYTIwMTk5NzZlZDgxNjM3MTFiNmVmNDgwMzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk0ZGY1MjYyMGJkMmEzZTcxYjhhOWUxMTdlZmRmZTQ0MDQwOWNlM2ZiMmJmZTYxNGJmZThmNWJjZjNjZWRkMTkifQ" + } + ] + }, + { + "id": "claim_be15153e110246e9b60bc280b72fa06f", + "statement": "Removing a mobile scene triggers the all-scenes-background transition only if other tracked scenes remain and are all backgrounded; removing the last tracked scene or a backgrounded scene with another visible scene does not start a background lease.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L636-L645", + "version": "repo-lines-v1:sha256:c9f231d0f50e2dfd316c0107b142236456918cbfe57327652e97026f92e822af:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwZjQ1ZWEzZDVjMjljYjRiOTAxNThmOTJlOGNiYzk4OGFjZjMyNGYzYzlhMTQ0NDExNmE3NjkyYmZjYmM2MDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRlMGMwYzg3ZjJiZjhhNjVmNDIwYmY3ZjkzMWVhMmZmOWZiZmRjNmI4ZTlmNDg0YTdmNTgzNjhkMmRmYjE0NjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjljMWM2OTIzNTgyZWI5MGYwNWVjMTRhZGI3ZTAxYjhlMjIxZjFhOTU0MWU5ZDZhYTVmOGJiZGFjM2RhZTMyYTIifQ" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift#L414-L456", + "version": "repo-lines-v1:sha256:7ac411824f719e24e6e0cda56955a37a844d064068f309fb91775181b944ce8a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlkYTNhNzE1Yjk4OTMwNDAxMTQ2YWIyMDUzNDU4NDEzNDQxZDdiNGJmZGUwODA4ZGE5Zjg0NGJjZTk1MjJhZjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE1ZjViMjM1OTRhZDZjOGZmM2FmYzE5NjgyZjhiMDE1ZTAwMGI1YTY2MTJkMTFkYzg3MjUwNjNmYzMxZGNmODAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY3MDZkM2ZiZjk0Mzg2YjgxNDE2MTkwYzhkNzNjMGNkMmM1NGQxZDhkNzM4YTRkNDBmMWEwNjA2M2FiNDQ3YWYifQ" + } + ] + }, + { + "id": "claim_6041ba61effc47da9ebd7e37bcf94447", + "statement": "MobileBackgroundController invokes its expiry callback synchronously before retiring a valid UIKit task, including when expiration occurs during begin; it safely retires the returned identifier without disturbing a replacement lease, while asynchronous cleanup initiated by expiration is best effort.", + "evidence": [ + { + "resource": "repo://TFI/Platform/MobileBackgroundController.swift#L45-L84", + "version": "repo-lines-v1:sha256:ea3406fa5773e70a02548ed6337f82053c4e9639713f34e7042ec70b11e2603d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIzMGE3YjMwNzMwMWQ5Yzk4MWZhNjFmMjJkNDhkMTE3NmQzMjBhZjdkYmM3MTJmOTk4NzM1ZDc1NGE2ZTJkN2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA0YmUwZTMwOGMxYjUwMzI5MGNmOGNkYjQwM2Q0ZTFmYzQwYzFmOTk0MzdjNmRmNTk4ZjZiYjlkOWYwYzMxYWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFITests/MobileBackgroundControllerTests.swift#L8-L66", + "version": "repo-lines-v1:sha256:6ae00f644f06d81a0eb43f3dd2bc57732de40ec02e521559d77f4f9a6af70321:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4YzgzZDk2MmE2NDhmZWZkZTJjMjEzZDVkYjQwNWM5MThmNmRiMWU5MzdkMGI4MTMwNmU1ZDY2ZjI2Y2JkMmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgyNmNkODQwNGM5Zjc1MjhkODk1MDg3MzBmMTczMjc1M2JhZWZiZWQxMWFmZmI5N2FkNmRiNTllOWQ4NmE4MzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZjNGY2MWQ0YWEzNzkxMTQ4YTUyNGZmNzA2YWE5YTg2MjQwMDZkNGNhMTIzZWM3NWU4YjQzOTRlYmZkYjdhOWUifQ" + } + ] + }, + { + "id": "claim_a7d51b7744ed4480ba4a18ffc6d23f03", + "statement": "On mobile background-task expiry, active workspaces detach transports, clear pending interactive authentication and set a foreground reconnect intent; foreground resume reconnects only workspaces carrying that intent, so returning before expiry preserves a healthy connection.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L560-L578", + "version": "repo-lines-v1:sha256:b0fa484bcb19ae7f887f203d3b438c9bccc7b5936706cd85d285e53c0f9b31d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" + }, + { + "resource": "repo://TFI/Features/Workspaces/MobileWorkspace.swift#L1056-L1101", + "version": "repo-lines-v1:sha256:0a7ae642dd083c84f164b264fee0281ba51d48288dcddb66d8c2e9912a631140:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjljN2Y4NWI1NDQ5YmI0MTM0YjhmMTAzN2M1ZDkwNjU4ZDNiMjU4YWIxMDZlNWZmNjEzNTBiZjg2MzlmYzY4ODQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2ZGMzODIwMjNmZDQ2NDhkYjQzZmZhNjFjNWJmYjQ3ZjliOTZjZTIyZjFmNGI2OGYxZTczZGY3ODkxN2VlMDkifQ" + }, + { + "resource": "repo://TFITests/MobileAppTests.swift#L364-L412", + "version": "repo-lines-v1:sha256:4b42b940eee336d4e9dba5d37b9cd3b61c253847a1e50c87f2a735a301852750:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiZDFmNThmMjIzZDQ1NjI2YzYyY2U4NDc3Nzg4MjI0OWNkMDdjMzM4MzQyYTE0MWRhYWRhMzkzMjUwNGY5NTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzY2QxZDE2MWMyZWJmNTNmZjg1NjNmM2Q5MDdiMmM5MDJiYzVmZWE1MThmMDcyY2UwNmU2MjI2NTQwMGIyMmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjczNDUwNzJhNjRjMWI2Y2UxMWFmZmZmNGZjNTM1ZTk1YmYwZGMwYmQ2MDhhYTQ4NzMzMWI5NzYxYzI3MjdhY2YifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/shared-module-directories.json b/openwiki/.claims/architecture/shared-module-directories.json index 11fbc64e..2d0fcab0 100644 --- a/openwiki/.claims/architecture/shared-module-directories.json +++ b/openwiki/.claims/architecture/shared-module-directories.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:e8da1978ed97e3c4dc6008ad373801967126a936955746a9426ecf5cea2fcae9", + "pageVersion": "sha256:1d94baed34a4a63a7a933c51f451945882a2778972ab6bd10350dbd195285613", "claims": [ { "id": "claim_6e30bc8cde134c23815d274543d0786c", @@ -262,7 +262,7 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" } ] }, @@ -287,10 +287,226 @@ "version": "repo-file-v1:sha256:9a3e7296fd09c4b397c90c7b15c20775a0950a145ec1c506ac431c04fc5ea020" } ] + }, + { + "id": "claim_4d3ad7ad0e694d31a52ef3a4a5fd8cef", + "statement": "Xcode file-system-synchronized framework root groups are owned by their corresponding framework targets, while Frameworks/Resources is included by TFM, TFI, TermindWidgets and FrameworkTests rather than by the six shared framework targets; consumers of shared data must not assume it is in their framework bundle.", + "evidence": [ + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1047-L1054", + "version": "repo-lines-v1:sha256:4e86a43e410e278253aef653d2796c9f32c2b951cfb8144e1321d6e14f4c33cb:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDk4YTI5ZmE4ZWJiMWU4MTA1MDk5MjlhMDhiYjE2YTI1ZDFhM2RiMjk2ZjQxNzhhZjNhMDY2ZjI4MTZkNWRlNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOGZhZDEyMWZkZGVkZGY0ZTQ3MmZjNTJkODE0NTdjZWYxOGNiZTZkODQzM2IyNDRjY2YyZjEyNjI2ZGY2NzljNyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTAyMjJiNGU4Yjg3NDVjN2YwODM4ZDcyNzQ5MWZiY2Q1NTA5ZGJjMzA4YmUxMWZhMDQyODU3NjBlYTAxMGFkOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYjJhMDcxMjI4Zjc3YjQ0YjA0NTgyMDhhZTdkNDU4OTc4MDgwN2IyZDE4ZmI3Zjk0NTBlNmM3YjE5ZjllMDAxMSJ9" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1190-L1194", + "version": "repo-lines-v1:sha256:0047e83d5500a91f47288d1b4936f8bfffc2bcead414db3bf56ef2d92dc49daf:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGZhZDEyMWZkZGVkZGY0ZTQ3MmZjNTJkODE0NTdjZWYxOGNiZTZkODQzM2IyNDRjY2YyZjEyNjI2ZGY2NzljNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOGZhZDEyMWZkZGVkZGY0ZTQ3MmZjNTJkODE0NTdjZWYxOGNiZTZkODQzM2IyNDRjY2YyZjEyNjI2ZGY2NzljNyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZWU5ZTEwMDM1ZjZhYWFhNTA4MzYxNjhiOWExYzYwMjBmMTU1ZmNiZDdiMzFhMWQzNzFiMGNmM2E1YWI0Y2VjYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiM2Q2Mzc1MzdiOTRjNmNkN2NiNDE0NjYzNzZmOGIzOTlkM2FmMDdkYzg5ZWY1OWQxMjcyYjMzYjVmMDczYjRlYSJ9" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L504-L565", + "version": "repo-lines-v1:sha256:eef5ebb60f3f4e85c13c7cb14a016a8fa32183228d7b958036783b33f6111b1f:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE5MTMzZDNlNWNkZmM4MDk1NzlhNGU4NzQ0ZjNjNTRmMjExOTc5OGE4NWUxMWE2MzMxMzMxMjdjNWQxYzg3N2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2MGI4OGEwNWQ1YjUzODQ3NjAyMjliZTYwNTcyZmU2MmIxYzI5Y2RjNTdlZGI1ZTY5NTFkYWE0ZmQ0NmM4MDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQwYWY2MzkwNDY3NDBhMTY0YjQyMzk5YzcwZGIzM2M3OTZlNGIwMDAxNzQ5M2VkNjAwZTI3MDhlODZlYTI1ODIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNjMWFmMGNlNmUwYTQ0YmY3MjRmN2Q3MzI3Y2E4MjEzOTZlNGFmZThiMWQxNzYxOWEwZDFmNGJhZThhYjVmNWIifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L879-L950", + "version": "repo-lines-v1:sha256:42ccc7d1fb1ed5a6905b34fc9008c21d5305ae0884588f293817b564dd3fb480:eyJzZWxlY3RlZExpbmVDb3VudCI6NzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3ZjA0ODAwYTVlMDQ3MGRiZGIyZGIwNDY3YWMzNDc5ZGVmN2YyYWM0YjlkZDNhZTFhODg5ZmMxNGYxNDI4ZWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhmYWQxMjFmZGRlZGRmNGU0NzJmYzUyZDgxNDU3Y2VmMThjYmU2ZDg0MzNiMjQ0Y2NmMmYxMjYyNmRmNjc5YzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFkNjU4YjcwNzMzMTRmMWQxM2I2ZGRmY2NkYjhhZTdkNTE5ZDhkNzA0YjE4YzRkZmY2YTBlZTVmOTBlZDcyYjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg1ODZiYzAxZmY5MDc0ZTExMTQyY2M5YmEzZDI3NDg2MTg3YTRkNDM0ZGI4MzMwNGI4NzBlMTM2N2NhMmYwNWIifQ" + } + ] + }, + { + "id": "claim_3ddc074e7774454a878306869ad2ac67", + "statement": "AssistantExecutionController freezes selected model/secret, permission mode, skills, tool registry and context at submission before optional asynchronous memory and compaction preparation, preventing later UI configuration changes from changing a captured turn.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L11-L64", + "version": "repo-lines-v1:sha256:604bddad4b166bc47c4f5294d8ea8330d5a1d422fa5e15965e92bdbedfac6ec0:eyJzZWxlY3RlZExpbmVDb3VudCI6NTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRmYzYyNDcwNjBjMjNlMzFmOGY5ZTYxM2U1NDNiNjYxNGI4ZjcxYWRkMmUyMmQ1OTI0M2YwMzllZTYyMmQ5NTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM1NzkxNjVmNDIzODA0ZjA4NDFhOGQxY2JlY2MzYzBlMTY0YjA5NjI0MDY5YjE2MzY2OTc3ZGRmZTNjMTlhZWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU3OTNhMzE5Mjc3YmQ1ZmMzM2E1YzI5NzRiZTQyN2IzMzlkZWJiMGVjNjJkNWYyZmMzZmU4YWQxNWM0ZjUyNzIifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L523-L646", + "version": "repo-lines-v1:sha256:6f0586148546ed005af984580253f2dc7d5de8689160a50bb5889c18111981cb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTI0LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIzN2U2Yzk0MTIwZGUzNjU0OGMxZjcwMTkzYzMxYzg0NTQ1ODI0OGQ0M2E4N2U2ZTU0MjY5MTBmY2VkYmJlOGJiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3NDhiNTNjYTI2MWZjOWVmMTVjMzg5YWVkYTA0Zjg2MTFjN2I0N2UxOGU2MjA5NWQxMWRmODkwYWNjMWQ4ZjRjIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwZWE5ZjA1OWViZGRiM2M1YTA1MTQwYTNhNTJjMTM2MmU4ZGVhZDhlNmU1MjllZWNhNWMyNjkxOGZhNTMyNTY1In0" + } + ] + }, + { + "id": "claim_4299a58f184d44f2b62d6607712b1420", + "statement": "Application tracks one cancellable agent preparation per conversation, prevents overlapping runs, persists missing-model or missing-credential failures before projecting them to conversation state, and can record interruptions on cancellation; injected AgentRunPersisting keeps SwiftData out of this coordination layer.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L88-L132", + "version": "repo-lines-v1:sha256:57e069f8af0094156607711530491f45d2aee8ec3c938ef45d84cf4d5eb380a1:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE5N2Y5MTA0Y2I3MTFhZmVjOWQwNDhkNmU3MDg5ZThjMWQxMjMzNGI3ZjRiMDY4NDMzYmM2OTFkNmZlNTFiYjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjljZjkxNGIzYjNlNjQwOGIwNTE5MGVjY2ExZjdkMzE4YjZjNzhmMmNmMGY2ODg5ZjQ1YjdlY2NiNmM4ZDJlMzEifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L351-L385", + "version": "repo-lines-v1:sha256:637ec0d996f7024c7ce72cb572d39f084ebea1a8e395d3c2099a4c32dcc7f4c6:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIwYzRmYjc2MWFjNmVmZDQ0YzY2Zjc1ZjMyZmJlMmI2MDBlZWMyYzdmMGQwYjBmMGZhM2JjYmFlMzY5MWQzZjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAwYWFhOGQ2YTcxZmY4OTIyNzczMzM4NDIxMWM5MTJjZmVlYTY1MGJmYTExODgzNGUzNjAxZDgxM2M4YmQxOGUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJjMTVlZjIzNWZiOTJkMWRiZDA1NGNlOWYxMWJlNGYzMDQ1NWRiZGMyZTczOTA0ZjQwNjNjMDYzYzlmMzkzMjYifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L518-L520", + "version": "repo-lines-v1:sha256:131d110d466be3f6969aedb536bc3688bdd631b1ff862d2f62ec4de6b36828b8:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTYwZTRkNzE4YzNlNmMzMWQ1MGY1YmVmZWQ5ZjIzYWQ4MmI0YTA2Y2Q2NDY0ZGFmMTM2NWE3ZjU0YzE1OWU5YiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzE0NWJhOTBhNTBlOWYxMmNjODViNDEyOTYyZWUyYmE5YzE1YTQwMGY5ZDI4NDY2OGU3MWRiZWY0ODYwN2Q0NSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzhjZGJjM2M3NGQwOGY1MzM4ZDkwMDRiYzBhYmVjZmZlY2IxNmUwMmYwZGQzYjBkZDBiNmIyODRhM2Y3MmY3YyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDE4NzQ2ZjYwOGM3YjI5ZTcyZmUwODUwMGM5ZjdmZDAwMjUzMDcyZTFhYWEyNTNiNDUyOGZlNjdiODIzNjVjNCJ9" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L680-L821", + "version": "repo-lines-v1:sha256:5be31ca8267fac7c7912ab1b0d461fface21b722bbdc22a0b34180d31b7e47f0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI1NWEyZmM4NWY3MmI1MzQ3MWY5OTcwOWRjM2ZlMzgyZDFiMDBmNTljMjVlYmU0MjNmOTNhYWI0ZTIxMzRmZjcxIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI5MTQ1ZjdlOTZhNDNmMmI3NzdkZTU2MDg5MDU1MDYyYWNiZTc5NTFkNTNhYmIxZDVkM2FiNDcyMTY3ZjgwZDM2In0" + } + ] + }, + { + "id": "claim_fce7aa182d414292b07a64689273c287", + "statement": "The controller composes AgentKit runtime with injected host-tool registry, eligible skill/memory tools, an ordered event channel, and weak conversation approval interaction that denies when closed; compaction is persisted before changing the observable transcript.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L392-L507", + "version": "repo-lines-v1:sha256:8163d3bcf773ab3ce1a46efe6d771e1b678414bea3238aa8bd8fb108ea9b64d5:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJmMWYxNDNiYjJhZWRlMDIzMjViZmQwMTJlMWI5MTg1MDU0ZjUyYmMzMDY2NzJjNTFkMjAxNTBkNDMzOWJmZTVmIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI1OTA5YTUzYTYxOGQwMjhlMWQzMDAwYzBhN2FiY2VlY2JlNWZiMzdmNGU1MTFlZmU0NjY0M2ZhZDZlNjY4NzJmIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlMTFmZmZmZGE4NDM0YWY0YmM1MzQ1NTNmZTFjMWNjNzcwZGVkMTQ5NDM5YjE2MzAwZWQzNGFkNjRmOTU4Yjg0IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlZWMwMmIwMGE3NjI5NDE0ODA2ZDEyMjI3NjliODBlMGY2YjFjNTFmZmE0MGM1OWMxMTI5YjJmNDE4Y2EzZWM2In0" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L910-L919", + "version": "repo-lines-v1:sha256:7c9756ce11f5a802355fdf037aff24ef90f81e71df715249370eef766c0a4ab0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2MTZmMWZiZWQwMTYzZTEyMTU4OGUxOTZkMjA3Zjk1ZWYwNTFmMGZiMDEwN2YyNDI4OTA1MzAyOTEyYTVhNmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJlMGJhYWZiMDE3NmFmY2M1Yzg3NzI0MTkzYmY4ZmM2NWU4MzgwNGUyYWUwYzk5YjZkODViZjViMmY2ZWFmODEifQ" + } + ] + }, + { + "id": "claim_72a4effdbd6c4615b9408a74fa878c58", + "statement": "SwiftDataAgentRunRepository deduplicates history by message ID across successive run snapshots and stores frozen replay/context backing separately from ordinary messages; it restores transcripts in run order with compaction projection and recovers recorded tool results absent from a later transcript snapshot.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AgentReplayPersistenceTests.swift#L11-L69", + "version": "repo-lines-v1:sha256:fc914331358f0eb37c941ef368ea3ac9e12c64e15621e16c9f49bd358319814f:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgwODVhYzhjNzMzZTQ1ZGUyZmFjMTcyZjlmMjgzNmVkNzVlMDE4NzgzZTM2ZTMyZjI2NGE2ZWEyMTI0NzRkMWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3MzgwYmYzNGNkYmJjNGVmODdiMWZhMTc2NWNiYTY1OTFiZGJmODk4ZDAzOGNkNmY2MDg5YTAxYzUxNGU3MzEifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L217-L308", + "version": "repo-lines-v1:sha256:14e13f896c7d35cb4652edd53a498d51f91d07a12bde67be4a94c68b1d11f738:eyJzZWxlY3RlZExpbmVDb3VudCI6OTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzYWRhOWMyODlmYTIzOTFmMWNjZWQ4MzlmMTQyOGIxZjNhZmZkMjYwMmYxY2E5MmE5NTk0ZTk5OTNjMzUzYWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA3OTA3YmVlNWRiMjNhMzUxNDcyODQxNzBkZjBmMjBhMDU3NzRhYjRjNDEwYWFlNDI1M2JjNmNhNzI0NzAzM2MiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE3OTRhODhlYWRmMDM1Zjc2MDFjNWRhODBiNzE2ODYwNzQ3NTMwNzg4ZjViYjc1OWU4NDE1ODIwNTRlZTE1M2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2YmI4ZTFhZWZjZDg0ZTUwYjYzZmQwOTRkODA2MzRjZTVlM2RiODg5OWQ0Y2E5NmFjYjcxYTQzMTA3MzZiNGMifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L61-L110", + "version": "repo-lines-v1:sha256:c6e106f0aa7272cd0ab8a752acef1b13c5254bbcd31ee78bea0e362f314f6bde:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc4NjA2MDBjMWQxYTVmOGE3NjdmZTM0MTA1NDNhY2E0NjA0NDAwZmFmODhmNjQyNjczNTZmOGJkMjBiZGQ4ZWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY5NjBjMTViNmMwNDcwNTc1MmY5M2NjMDRhNjdjMzUyNDdlNDI5MDhiNGQxYzFkN2RmMjFmNTY2YzNmMzdlYTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5MGRiOWU4MzA3ZGQzZTk3Y2VmYWY3ODk0NDJiMDc2MWM0YWQxOTAwNDNlNGMzYWRhM2ExMmRhNzk0YTk0ZGUifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L732-L786", + "version": "repo-lines-v1:sha256:d7c559067250de1bae8e0749bea447f411c8fe95dd7f7ee569b3c8010463a382:eyJzZWxlY3RlZExpbmVDb3VudCI6NTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzNzE0ODNiZmQ5OGM1MGM5NDg5ODlmOWEwNTJjMzI1MGUzNzMyYTczYTc2MGY1ZDJhN2I2MjFhNTJhNmUzYjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjljMjdkYzQ2OTBhZmJjZmM5NjgxOGIyYWZkNDY4ZjkwOGUyNDBhYTgwZWEzZWYwZjcyYjM2ZjNhOThjYTUyNjgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNiYjUzMTU2YTNkYjA5MDdmY2I4NDEwNjJjNjc5NjdiMzMwY2I5NTk1ZjViNWEzM2I4ZWVmNTZjZTVlMzczZjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZTE1OGU4OWZkYzM4OTc0NzZhMGZmYTc2NjE0MmUxNGNkYjIyMTNjYjIzMmQwYTEzMGU3NTlhNWM3ZDllNGUifQ" + } + ] + }, + { + "id": "claim_0f6882b385b8491e91ef8e79ec902839", + "statement": "Agent persistence marks unfinished runs interrupted on repository initialization; editing truncates a conversation suffix and stages a replacement user run that a real run later adopts without duplicating the message, while conversation deletion removes its related tool and message backing and tombstones prevent late saves.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AgentReplayPersistenceTests.swift#L71-L112", + "version": "repo-lines-v1:sha256:081bbe5beeb6834585986890a850825852d4c0e5010dcce28caea70d9a958c8d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkyMmZhOTY2Mzk0NWFiMDAxZWNjMWQ4NDY0NzE4OGYwZmZkZDlhNjM3MGEzMWEyOTBiMDlhYWI1NzcxNmY4YWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE3YTJiYWYxMjA1ZDE2OTUzOGVjMWE5MTljMTg2NTc2N2M4YzJkMDg1NmQzOTJlM2RmZDhhNjIwYjQ0OTdjNGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OTYzZTM0ZjIyODQxNmRhYjU1MWM5ZjY1MTE1ZGZhNjc0OTk5MDAyYzRkMDc4NjZkMjY1Yjk2MzRhZGEzNDIifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L11-L22", + "version": "repo-lines-v1:sha256:033269572b41ca861d3a6ce484743be4c29f9165f69a1d846eaece9d62041c0f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNiZTcyZjM3MzE0MmEyYTAxODNlOWI1MmMxODkzMWQ5MDUyOWVhYzhkMGZiYWNhZTJlNzY3NTE2YzE1ZWZiM2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg4ODhlZWJhMjA0NjZiOGEzOWE4YzkyNDllMzMyNmIwNmM3N2U1Njk2ZmQ4OTQ4OWI3ZDlhOTM1NzUwNWM1M2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI2ZWM4ZTI1YTE5ODBkNGJlZjQ0ZmM5NWNiZWEwMzZkYmYzNjg0NjFlNWE1NzZkYTYwNjEzYWMxYWJhYzg5NTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYwYWI0NzFiMmUxNjQ0NDdhYTc5NTA1MmQ1YzFkYmMwYjZiYzNjZTRiNDIxOTExMDdmOGZhNDUwZjM4Y2NkMmUifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L403-L508", + "version": "repo-lines-v1:sha256:2fb2ffccbd32b1e2d0d66f4bf68a6aa39fc5538e9d4c11b046730255c496a118:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI3MmJiNmQ1NzgzMTJmNjJmZGQ3OWM4ODdhMGNjNmVkMDRjZDkwOTQwZjFhYWE3ZTlhNTAyMGVmNjkyOTFhOTU3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3MTAyMWNhNTY3NTNhOGVjNDA3ZGY2OWY4YTVjOGRjMGJiYjgxMjlhNjE0NTdjY2FjYWE3YzhmMDcxMjFkODUyIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI1ZmI4NGY5MTE3YTNlMmZjM2FjZDgwMjk5YmU1OGZjYTlhNjNjMDEzMTNmNzM3ZjRjNGQ0MWE1MzA2MjQyZDUwIn0" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L596-L640", + "version": "repo-lines-v1:sha256:c4d558fab47145fdbc751c39c1334d02d4799494b9373e84a0c1c31c280b4aab:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyYmI2ZDU3ODMxMmY2MmZkZDc5Yzg4N2EwY2M2ZWQwNGNkOTA5NDBmMWFhYTdlOWE1MDIwZWY2OTI5MWE5NTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM1ZDk2YjE2NmNlZjIzZWQ4YTNlNzhjZjg0ZDBkNzAwY2UyMmFhODJlMGQ2ZmJjNzJiNTkyYTAzMTQyNGE5YTEifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L72-L93", + "version": "repo-lines-v1:sha256:2d8abe733aa2173eaabf948e48201c13df9dbe8b0352316e29776c31d570a225:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiZjZkZjJkMGNlZDk2OGNiMDU4ZWNlMDY1ZGU1YmI2ODUyNjNiYjE2YWIyOWEyMTFmZjIxOGU3N2Q2ZjkxMjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEzY2UzMTZkNDcyNGJjZjY2NmZjZjJmMmIyMWEwN2M1NzBkMzM0NzUxZTA2NjYwNjcwNDgzMWY4ODAwNzRiMTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE0OWMyZGIzZjU5ZDNlNGJiZTk2MzcwMmYzN2MxZmQ0NGJmM2M1NWUwY2ZhNDY5MmEwODA4MTE4NmIwOTJhMjYifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift#L853-L865", + "version": "repo-lines-v1:sha256:f142043bb1b01de9a0458b3995239712303b9ee5f7cd1bc4531d3ee6da2913f1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ5NGQ4ZDkyN2FkMTU0ZTM2ZmFhZjZiMmI2MjMxZDllN2Q2MzRiY2IzZTliMjI2MzA4ZmJhMGVkOWQ3MDY0NjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + } + ] + }, + { + "id": "claim_fb12be44f0e64c5c9acd3f5967038319", + "statement": "RemoteCharsetStreamConverter performs strict outgoing iconv encoding and stateful streaming decoding, buffering incomplete multibyte input while passing malformed received bytes through rather than failing the stream; normal encoding throws on unrepresentable text and optional invalid-input recovery reports rejection.", + "evidence": [ + { + "resource": "repo://FrameworkTests/RemoteCharsetTests.swift#L26-L67", + "version": "repo-lines-v1:sha256:e26eabcaac0395551641ec9be367ea064eff06db917c89c2ac5dcf5011273d8a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI2MmYxZjhlNzYyMmY5NjRjMDE0ZTU3YmM0NzQ0NDRjZGQ5YzI4OTcyZTcxMmNiYTJkZGI5ZWZlMmJjODIzNTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgwYTg5ZTQ0Yjk3NTMzNThhNzRkZjI3ZjgxNjE5Y2RhY2YzNmVjNTJiOTNlNzcxOGUyNDE3YzYxYTQzNGI4OTEifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift#L145-L223", + "version": "repo-lines-v1:sha256:f8892502d88bbe21dd53f7d2f5feb868e83104b38e739700e675dd7cf2a539d2:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyOWQwZGQ3Njg3MTU3NzZkZDE5NTU1ZmI3MzU1ZDZmOTE1ZjI4NDM2ZjhmYmIxMTQ3Y2Y5MTUwMThkMjgwM2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVlMmY4NzI4MWVkYjU0NmViNTIzNGRiNjk4ZWYyZGJkM2Y1NWM3YjNmZjgxMDQ0YzVhZWJlMTdmMTdiODhiNjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMzOGRkMWQ4Zjk2ZGNhNzFiZWE3ZTUyMmU0NDgxNDBhNjc5ODRmYTRlY2Y5ZTJiMzgzYmRmYTNhYmYxZGJmM2YifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift#L41-L139", + "version": "repo-lines-v1:sha256:fb2a42a6ccccf45a6ea6fb302bc378c0e36219610401cfc86b3ef3ac773934ab:eyJzZWxlY3RlZExpbmVDb3VudCI6OTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ4MGQ2NzYyOGE1ZDQyMmQzMzNkMDY0MjNlNDRiNDQ5NWRjZjIwODZiMjQ0NzZmZjY4MjZhNGExZmQwMTM1NDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE1M2M1MTkzMmRhMWMyNmI0NDkzMTIxNmUyMDRhYjZjYzUwNzE4OTE1MzEwZDZjYmUwNGJhNWY0ZDRlYTVhYTcifQ" + } + ] + }, + { + "id": "claim_8b84218e3a83494ab419f06bbb0b0224", + "statement": "The remote charset adapter is applied at SSH exec, PTY and SFTP boundaries and also in Telnet; the SSH PTY OSC 7 filter rewrites charset-encoded working-directory paths into percent-encoded UTF-8 for Ghostty, buffering fragmented frames and bounding incomplete payloads.", + "evidence": [ + { + "resource": "repo://FrameworkTests/RemoteCharsetTests.swift#L88-L105", + "version": "repo-lines-v1:sha256:d993b57e4ee07fe64963235749b3d1da91c896eb37a806687ec3a4924fae8690:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBjYzBiNjNlMjc4YjhiYWZjNThhZjEyZWU1NDUxOGMxZTEzZjEzYThkNmY4N2JmNDlhNzJiYjEzYjc5MTQ3ZGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift#L225-L272", + "version": "repo-lines-v1:sha256:097eb2230f29b0b7ba234ed63cc74a0020b8455dd74b27ae1372400534c80237:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM0NGY1M2U3ODIwY2I2ZGVlMjBjYzI3YzUzNzI1NzQxNTVhMjUyNzZhOGZmNjI3ODViYzcyZTBmYzM5N2ZjZWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk1NDE0NWZjOGQ2NDEyNjYzYzIzNTA5MDgxOTIwOTcwNzViNmI4N2JlY2Q1NTMxZDk3MzZjZmI3MmNkNGUxZWIifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L1050-L1059", + "version": "repo-lines-v1:sha256:1658b6df3d87086511f52ca5558ba653833f3c8661c53141329dbcc7b1dcfbdf:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg3MTQ1YjAxZjU4OGNhYjg3MzZiNzcxNDJlNjMwNGM3YmQwMmFhOTY5ZWU4ZjJkYjA0ZmQ4ZDNhZmMzODI2ZGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNhZTk2NmQ4YzVmOWI5MmMxMGRjYTQ2MDRkMGQ4OTAwOTIwZTNkYmNmODY3ZTUxNjZmNGU1ZmM1NzJjYTRmODgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3MGIyM2M1ZWE2MTUwNDFjMWM1NmE4NWFmYzNiYTNmM2M2YjBhNjFhZGY0ZmRkOTQ4M2M3Mjg3NzY1Y2IzOTQifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnection.swift#L28-L60", + "version": "repo-lines-v1:sha256:22a22a2b497829248ab3e5880daf830512f03dd4a317771d2541f86155b98c15:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImEyYmU2NzBmYzQyNzBiMzQzOTg5M2I1Y2Q3MDMyODQ0MDZmYmZlNjRhNzg4MmUwMzVjOTE4MTRlYjBkZjRkNzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnectionWorker.swift#L60-L85", + "version": "repo-lines-v1:sha256:9fb1b85b1ac40b091bec6ae0b36debc5978c2c029f69f90944402912907d2a75:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1YmEzZWNhZDAwNzM4MGU4ZGI2NjcwNDhkNmFjOTA5YjRiMTcxNjIyNzBmYTU1ZjQ1MDEzNTViMmMwMDhiZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjllN2NkODRiNzY3MWNiOWFlZmQ1NzkyOTZiNzYzODA1NjM2YzllOWYwZWQ4ZDRlMjU0MTMyMTI0OWMxZTgxYmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExZmE0OGJmNmI0MTZiYmVkOTA0YmRmMTk2ODZmN2I5OTViOTcyNjRkNTlkMDVkZTEwYWQzYTkxMjY5OGM3ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM2Nzg4MjlhNTVkNTI4NGQ1MjQ2N2I3MjcxM2VlN2E0MjYxM2UzOTdjODRkNzE4YmJhM2I5N2IwOTY3NDExODIifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L1097-L1125", + "version": "repo-lines-v1:sha256:18b6ec795aa4c05d1e4b820fa966bdcd93eac5d15b1643bf22c9159acd84a950:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxMDI0YTNlZDg5OGNiZTliOTI3MDY1OTc4NjFmMjBjZmFkMTY4MTY2OTY5Y2FjNjQzNjI2OWE2MzRmOWU1ODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzNGYyOTRiYzljYWNmMTVjZjM2Y2I1NDIwYmVjOThmNTBmY2Q2ZWIyNmJhYjc1ZmU2NjMwMzMxYjc5ZGFmYmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIwYzFhMDM5NmZhNTI4ODRjN2JkNTAyMGI0YjMyN2IxMzc3NjNkYmQ0NWE5NjFmZDI5ZTczZGEzYzU4MGY5OWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2MzkwMzNmODAyZDEwMDE1YmFkZDExMDc4YzFiZjg5YjljODhhMzc2ZjhjMzlkN2Q0MTZkODk1OTc1MWUyZGEifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L100-L110", + "version": "repo-lines-v1:sha256:5ec85b0929ba0a2bfd2b1302882875ba5d00ca0589bb2c9c1b17ff05f5cdd9ec:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFlMzE4Y2U5MDUyNmI0NDBlMGQ2YTJjNzAxZjNiNzA5MzIzNzk2ZTE2ZDcxYmQzNjY0ZWE2OTFmMGRlNjhjZjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE0MDQwNzcyMjI1MTA4MGEyNWE4Zjk3OTczZmRjZjY3MTBkYTY3YmM1MGUyNjhmNDYxZGFmMjFiODk2MmJiMzgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNlODliZWQ5YjAxNWE5MzY2NDk3MjgxN2EwM2Q4MDMwMjZmOGYwMzY0NDNiODYwYjc4ODljMjM1MzU4ZWE3NjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY1ODgwYzBiN2JmNWVjZWM3MTcxNmM2NDhmNDM3NWJiMmU2MTZiZjIzNDE5YjAzOWE4MmQ4ODQ5Yjk3NGRjOWYifQ" + } + ] + }, + { + "id": "claim_9e16ea19ab4845b794c9ba18577ed800", + "statement": "The presentation icon catalog loads a main-bundle JSON index, resolves detected Linux distribution by exact or like ID and returns no entry if unavailable, while AgentKit searches main/package bundles for the Pi model catalog and optional overrides.", + "evidence": [ + { + "resource": "repo://AgentKit/Sources/AgentKit/Providers/ModelCapabilityResolver.swift#L312-L326", + "version": "repo-lines-v1:sha256:9a8722c8684ebfdfe69f4ae13be901046add0711f63bd690c0fb4bd89e86ad8d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmMmY0NDcxNWIwNTQ5NmZkZWFlM2I3NGIyOTIwZDI1ZDMzMTE3YTYzOGI5NDUwMzllMjM2MDE2MjQxZjg2ZDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU4NDAzZTc3NjQ4NGVjMWNjYmYyY2UyZjE5YTZiNmFkZjg4MjVhMGVlM2NjNTllYTdjOGE4Y2E2ZGMwZjJkYWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkZDRlYmNjYjZmY2IzZGEwNWFhM2M5ZWMxNWI3ZDJlODI0ZjJiYzFhMGJjMGZmNDFlNWJhZDMzNmI3Yjc1ODAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJhNmY4NjA3ZDllOTg3ZDAyNjlmYWFlMGRjNWI2YWRiNjUwMTNjOTBhZDUxZWYxNjg4ODYwNjE5NTRiY2RlYzkifQ" + }, + { + "resource": "repo://AgentKit/Sources/AgentKit/Providers/ModelCapabilityResolver.swift#L345-L363", + "version": "repo-lines-v1:sha256:4485a67c4288263bb970e1ff9beabb21e116c7a48080e895888686dc3c02fe32:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3OWM2MGRiNjBhNTMzYmRhMWM5NTllMmMxYzIyZWMxOWZlZjllYjIyNGU2YjI4MTkxMGVlMjBkMWUyNTlhYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNmODEyMDFlYmJkMDBiMTA2OWFhOTcyZjRiMDc4ZTEwYTlmN2ZjNGQ1NjYzODU2NGUxYTQzZWUwNzkwYzM1NGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE3YTYyMTA4ODIzZWZkM2E3MTI2NDMwMzQzNDI4YTM3YTc1NGRiNDNhMjA0YWVhMmQ0NTBmZDNlNDA1YjBlODUifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/LinuxDistributionIconCatalog.swift#L11-L35", + "version": "repo-lines-v1:sha256:ac25a50716070642dd63d4d60e39cc2f9e20c6f65f4b56c2109fc96aea6d3d85:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2MGNlZjlmMmI2YTlhNTY4OTMzNWQzNmM4YmUyMDAzM2QzMWY3ZWZiYzNkYjZkZDZlOGE5Yzg1Njc0MmVjY2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgzNDlmYjQ2ZDM2OWY3YTIwZTU5YzdkOTZjOWU5Yzg2NzE2MzNmOWU2NTgyOGUxMWE1NGMwYjQ2YTQwZmE3YzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + } + ] + }, + { + "id": "claim_492758d43985458487245bc23a82b179", + "statement": "Shared application strings and bundle metadata have separate string catalogs from AgentKit text, and the repository localization check requires completed zh-Hans and zh-Hant translations; Linux distribution assets, catalog and licensing are regenerated together from a pinned Simple Icons version rather than fetched during app use.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L48-L50", + "version": "repo-lines-v1:sha256:5e69d5ddf8b0181f834edfe8f463b1ddc71ce0c0c26beaa6f4dc0cb63b7f1c67:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiN2ViNmVkNjM3YmU2ODNjNzYxMmY2NzdlYTllMWE1NmI5NjU5OWU3NzJmNmQ3NjkwYjQyMzc0MGNkMTRhZmZmNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODQ1MThlZDQyNWZhZWNhNTgxNGExYzEwMTU0ZjEzMjgxOGViM2VjMGI2ZTgzOThkZjQ5NGI4YWRmN2MzYTI0NiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTg2ZjBmYzI2Yzg1ZWJjYjA4ODA0ODE3YmIwZDNkYmQ3YTA5YTYxYTU3ZGE5YTA1OTdhYWM5ZTc1ZDBkNzQ5MiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMGVkYzQzMzI5OGFkNTgxMjllZTBhODg1MmMxM2Y1MjkyMGRhYWY5NGE4YzY0YTQ4NzFlZWVmNDZlMTMxNWVkMiJ9" + }, + { + "resource": "repo://Frameworks/TermindPresentation/LinuxDistributionIconCatalog.swift#L14-L25", + "version": "repo-lines-v1:sha256:46220a6c0c2862ec48861323b92cc21d9e565259e819e8ffe2ba105ebe7b0e83:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkwNWQ3NGUyZmQzYTU0ZWQ2OWIyZTlkNGFjNjQ5MGQzNmZhNmQ1YjlkZTM1NWIyZjdkMDdlZTMzNTVjM2UwNjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI1ZDUyOTJkOWFiYWZmMDkzNjg4NjdlZDJjZTZlYmQxZTBhYmZlZDBiMzIzY2M0NDVhNjJkOTY3OGU2YTM4ZmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNlYWNmMmU1NWZhZTY3MzJhMzgxNmUzMWRkYWM5MTNjNjY5NDk0YjYzNGVhYmJmMjJhOTc1NWI1YjgyMWJiM2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRhOGI1ZDNiNGU0ZmFlNTYzM2NjMjY2MmU4NWI4ZjM0YzNlYWU0MzVlMjBiMzM2Y2VmMWZmYzI5YmRmZGQwYTMifQ" + }, + { + "resource": "repo://Scripts/check-zh-localization.sh#L5-L38", + "version": "repo-lines-v1:sha256:b0e73658713e0bef0ac9fac43dd6d0773ad289fc23ff261a3048e2b0c041518b:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiM2ZjMjU5YmQyZWU2NDYyYzExYjZkOGUxNjZkMjU4MTVlMjNjNjkzZTA0ODRjOGZiZWQ3OTRmOTJmODI3ZDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMxY2M5NTJiNzdlY2RhOWVjMDJhODQxMDRjMDZhOWI3YjBlM2YyM2UzMjczMmQ0ZjIwNmU0NTYxYWI4Nzk0OTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImExOTg0ZjI4NTg4NzhjMzQwMjJjYzU0NDQ0NjVjNGY1NjczYTE0ZGVhNGE1N2E1NmRiZTdmOTA2M2E2ODQwYzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk4M2RmNGEzNjk4MThjNzczM2Q2ZWJmOTdmNTg3YWIyMzg1M2ExMTc1YzA0YzUxODYxNjg4MTljZmEwYjMxMmUifQ" + }, + { + "resource": "repo://Scripts/update-linux-distribution-icons.sh#L4-L27", + "version": "repo-lines-v1:sha256:e49bb42925da6bf075fa72a0630d566b825cb7bb54f427a17350ff9475ae4f9b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI5N2RhYmY0NzI0YThlZTU1ZjY3MDIzZjRiZmQ4MjI1YzE3NDEzNDQ4ZjBmZmM0ZDk5MjI2NGVlZjU1MmQzYTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiMzk3NDE3YWZhZmJmZDk3NWNiNzE2ZjkwNDM1NDc3MDVjMjkwM2NjMTc5NDRhM2U4NTcyNTgwNTYwZmMzZDAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjMyNzE5ZjUyMDk2ZmMwMTY1NzlhZWE0OTY5NmVmYTgyOWNmYzg4N2E5YzI5YWY1ODQyYTVlNGIxYjVhOGNhN2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUyZjMzYjM5MGE0NmE1YzJkZjkwOGIwOGM4NjNlMGEyNmJiY2M1YzQ4MDJkZGUxNjA2ZWNlZGIzNjBmM2EyNzAifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/supporting-system-directories.json b/openwiki/.claims/architecture/supporting-system-directories.json index 637966bb..5c25664d 100644 --- a/openwiki/.claims/architecture/supporting-system-directories.json +++ b/openwiki/.claims/architecture/supporting-system-directories.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:7128b59755ba977881cdcb66403f656aca8e06a74e8217aae2fc581cd6b07aa9", + "pageVersion": "sha256:28aa0deba6ac872df151035ac04d0aba9eb9619b16b76c706ecd36c2dbe08425", "claims": [ { "id": "claim_8809151c43594803b83cf0451d849112", @@ -12,7 +12,7 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" }, { "resource": "repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved", @@ -100,7 +100,7 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" }, { "resource": "repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift", @@ -226,17 +226,93 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" }, { "resource": "repo://Termind.xcodeproj/xcshareddata/xcschemes/TFM.xcscheme", "version": "repo-file-v1:sha256:6215ae5d2e32c9f76d70d6401196b14937f7be4b1e06b67db2297f3b81d86aa4" } ] + }, + { + "id": "claim_23ecd208184940d5b7f7bfabf565ce28", + "statement": "Cross-repository AgentKit changes require testing and releasing the separate package before updating Xcode's minimum version and resolved revision together; architecture tests reject app-local redefinitions of package-owned runtime types.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L16-L18", + "version": "repo-lines-v1:sha256:79d9222951afd1cde2967f4987b4aa7b4347f1510f1fc4d1141010690b9c8bff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGI2ZWFiNGFjNWIwNmRiMjY5NmQ0ZDUzZTJlN2YwZDE3MzhmMWI3NTAyY2UyZWY1YjcwMzIzZjg3NjdjYTllNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRkZTk1MTMwNGUxYWVlNjRiM2IyYmY3NWZkMzI2YjAyZGM0OTE5YjlhODM4MGZjZTY1YTAyY2VjOTE3MzdjMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWM1NjRmZjMwNzY2N2QwZTgzMGJkYjkxYmY1MDYwY2FlODNhMjc2NzRkNTU5NWNiYTU0ZGMwNmQzNmE2NWMzYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTVkOTdmMmUwNzM5MTAzZjc1MTA1MjljNjA1Zjg0OTIzMTdkNDJmNDA5NzEwNGFmMmRkMjBiOGUyNmZhMmNmNyJ9" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L137-L161", + "version": "repo-lines-v1:sha256:7cdee90b6c957a9b654ad149c681648048b6f866215d776195dcdc82e9e60f1c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjOWJmNjE2ZGNmNTM5YTBkNTRhMTM2YzY2NGM1M2EyNTllZmFkOWNmNWFmYTY5MDY5ZmEzOGI1MzE5OTQ0YzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE0N2NhYjY3NzUxMmRjZWQ0YTIyMGVkZGQ4NjNlZDFlNDM1OTM0NmRiYTk4ZDljYjkwZDBmZjk2MjhjM2IzNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwOTFiNTFiYWM3YThlN2Y5MGRlY2E4MWMzMTYyZTdhYjY4ZmViOWIzZTViMDk3ZDZhMTliNTg0OGJkODZmNjEifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L2852-L2859", + "version": "repo-lines-v1:sha256:444f908545e708b1d395265e4292e5529193fc19d4f609c8b5e06f6d68e13abe:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDhlMTQzODY5ZWI0MzVjMzZmNTljZTI5N2IxYWYxNzc3NThjMzVhNzFlNzJiMDQ2MTY2ZjkzNTNkODcxM2E3MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzYwYjg4YTA1ZDViNTM4NDc2MDIyOWJlNjA1NzJmZTYyYjFjMjljZGM1N2VkYjVlNjk1MWRhYTRmZDQ2YzgwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzExMTg1YzI4MDExZTZiNWFiYjU1YzRlOTQ5MjMyMTkwMzE1YWFmNGZhYzU4MzhhMDFjMWZmNTQyMjgwZmFiOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2M5YzA1MzMwYWQ3YTFmNDVhMmI2NDU2MTQ4OGZmY2NjZGY5Yjc3YzZmMDA0ZjBkYzRmNTBiOWRhZWFiYjdmNyJ9" + } + ] + }, + { + "id": "claim_f14815c519a24573871b358a9b99cb67", + "statement": "The MCP bridge defaults to a loopback URL, accepts URL/token from environment or command line, refuses invalid URL or missing token, skips malformed stdin, emits JSON-RPC errors for failed requests with IDs, and best-effort deletes its session at EOF.", + "evidence": [ + { + "resource": "repo://TermindMCPBridge/main.swift#L109-L130", + "version": "repo-lines-v1:sha256:4b0af7bee6f0f7d20c1f50e99d9ff54805bf9306b28f10aee8ee646a4a2209d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIyMjM0MWZjYTQzNTFmOTBiYzJlZTdlMDU0M2FiY2NmOGMyNmQyNDQ4ZjM2NjJhMTMzNjkyZjE4ZTM4NTkxNTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdiYzA0MzAyOWJiOTU2MjMyYzRhNmEyNDc3OGZlYTY1ZjhlYzBmYWUwZWI5MzkxM2U5OTM2YjBjZjU1NWEwMzkifQ" + }, + { + "resource": "repo://TermindMCPBridge/main.swift#L37-L88", + "version": "repo-lines-v1:sha256:5660a52ceb6e4e997c228d62cc5f9e79b588dcf8ba41819a12f42d6c185e3586:eyJzZWxlY3RlZExpbmVDb3VudCI6NTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYzUzMDFiNzY2N2NjNmE5MGQzNzIxMjI5NWE0YmE5NTM3MTM3NDAwNjhjMzA2NmExYTYwOGUwNzg5ZTlkMDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMzNzE2Y2U1YjJlZjU4ZDU0MThmMzM1MDRlMjgxZTZmMjcyZmYzMWVlOGQwNTYxMmQzMzI1YmRjZDQ2YWYzNzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVmZmU0MzJlNTVmYzJhYzRiMzc3NmIwZjI1NjhhNTVlOTE0OGQwZDNiOTExOWVlYTE4YTZhNjE4YzMwYjgzM2EifQ" + }, + { + "resource": "repo://TermindMCPBridge/main.swift#L4-L23", + "version": "repo-lines-v1:sha256:07a524e72460f12d0c060f2965197b7edf17b3f39e8e68ff604727503d88bed5:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0ODcxYWY5NDg1Yzg3ZThjMGM0ZGNhN2IyYTI3MThiOWY5YTJmN2QxM2RlYWM1Y2MyYTY5YzgyNWVhY2ViZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUwMTlmZWVlZjY3OTE3NjQ5MTAwM2ZlNmE0MTcxNWZjMzFjODI0ZGYxOWNkMzdiYzhhZGI1ZTZiZDRjYTk4MDcifQ" + } + ] + }, + { + "id": "claim_5533ba3f491248e08bc6d4210fca6ea2", + "statement": "The mobile Live Activity controller restores one active or stale activity and ends duplicates; it serializes updates and retirement, ends on empty workspace state, and requires explicit start intent and start permission before recreating a missing activity.", + "evidence": [ + { + "resource": "repo://TFI/Platform/MobileLiveActivityController.swift#L16-L29", + "version": "repo-lines-v1:sha256:3bea0397adae7574719a1651c9f1141456f8bed411e39d4f981d518268dd9b26:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM1ZmViNmNmYmY2MzE0YTE1MTk1OGVjOGJmMTdkOWQxYzQ0ZjAxNzE0ZmE4YzMyMDI5MGVhMjZkYjk3MDU4YjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ3MWQyNTBlMDQ0MWQ4NDYxNDAyYzc1YmY2YTNiNTdhNjFlYTRlMjU5YzhjMjY4Y2EwODJmNzU3MzkxNGVkOTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMxMjBkOWZhNzhlY2NmOTY4MWYwMGEzOTdjNGM4NGViOGNjMmRhMmJkNWYwYjA4MWRjMDUwYTU2YzEyOGQ1MmEifQ" + }, + { + "resource": "repo://TFI/Platform/MobileLiveActivityController.swift#L38-L70", + "version": "repo-lines-v1:sha256:25904d437e3d846013d0a6d6d0b7fe72ced259ca15d37ea18710b89263f59a87:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM5YzBjNjcwMzUxMjRmMzhiYmZmMTRmZDhlODIxYzJhYWUzNzg1MDc3ODJiMGZjODY1NmQ2YjVjZWU5ZDEwNmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRiOWM4ZGJlZGQ0ZTBjNDJlMzUzMmI2ZDM0YjZhZmIxMDAzN2I3MDY0NzRmM2MwNTExNmJkNWFlOWE3MWQ3MzEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ" + } + ] + }, + { + "id": "claim_85382a4e74594dffb2d36a8002fa0a4f", + "statement": "The standalone forwarding benchmark consumes fixture metadata and validates connection limits; the Python benchmark runner builds its dedicated Release scheme with pinned dependencies and collects metric records, while architecture tests ensure it is not an app dependency or test-host workload.", + "evidence": [ + { + "resource": "repo://Benchmarks/PortForwarding/main.swift#L7-L59", + "version": "repo-lines-v1:sha256:f51c7cc6683f5e4f441bf17b4a651aa9a86700c2794e6e0a13dc9b935c590180:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcwNzA1ZGJmYWE0ZjAyNDYwNTA2ZWM2OTJkOTZmMzUzMzg2ZDVlMzkxYTE0MzQzMjZmNDY3NTk2ODNmZDg5YzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNiZWMwNGMyODI2NGU3MWI2MjIwMTQ3M2MwOTMyMDVlMGIwZGUyZjQyNDM1NGMwMmQ4ZDljMmE4Zjg1MjI4OTQifQ" + }, + { + "resource": "repo://Scripts/benchmark-port-forwarding.py#L14-L16", + "version": "repo-lines-v1:sha256:f710759d9d1d258e530899145cf791513f7286ea85c3c68c5c1fb64bcec056ae:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzA1ZDAxODViN2FiYWU1ZTkxMTYyMjgwZWE1MWIxNmRjYjI3Yjg0NTJjNzc1ODkzZjM2N2NiNzc3MDM1Yzc5MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOTA3MDEyMzE1YjMzZDcxMTgzMmMwMmM5ZWI1ZTI0MWQ1NGFjNGMxMTVmZGY0OWFiMTc2MDJhYjlkYmFiMTA4OCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYjZmNTkxOTA2ZDYyZmZjYzQyOWViYjQ4ZmRiNzlkMzkzZjM5ZDJmMzg1NzViODlmYjQyMWRkNmI0OWE4YTIwYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWRiMmE5N2Y0MjAxNGQyMWYwNzYwMTUzNjcwMTlhMmNlZTc0MzM2NzE3ZDJmZDMxNWE4NjNiMTM2YjdiNGFmYiJ9" + }, + { + "resource": "repo://Scripts/benchmark-port-forwarding.py#L33-L105", + "version": "repo-lines-v1:sha256:80f1083f560e7db60c3a66c32f7a6a0b53936734805c987d01e6bcc4a9d18099:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgwMmNhZjkyMDVhNDc5OWI1Y2RjODU0MDE0NmU0YWI0NGRjZDY2ODJhMTk1ZWUxYjg3NDRlYzg5MzUxODZlMzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQwMDZiOWNkODI3NzY5ODM0MmJiYmQ2YjU1NjZkYWE3NThiMWExMjBlYTRlN2U5YzJmNDFjZTAxODMxNDZkZDAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImExYTRmMDVmZjRkNDhiNzRkNGMzNjU1MGNkYmUwYjhjN2UzZWVkYzM3MmEyNDdmMTI1NjY2YjFmNmUzMTljYzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzMTEwOTA0YTFlMDRkYzYxYjA0NjIxY2RhMDM5YzExMjFkNDVjZWVmZjNmN2I4ZmRiNDgzOTM0MDE4OTVkOGMifQ" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L5-L21", + "version": "repo-lines-v1:sha256:98306357e42814b24b1aa8f79d3e9d07347124bc26ff146d80b8ed5d90d4ef9f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2ZGQ1ZmEyNWE4NWIwYTBhODU3MDBkOTk2ZTIxMzgyMWEwZjk2MmU0NmVkNGU5NDY5ZDVlYzNkYmI2YmM4ZmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNkMTZmOTdkOTZhZjllZjZjYjY3NGUyNzIxZTU3MmQ2YTFlNWRkOTY4MDJmOGIwZmIxM2RhZGVkNGI3NjYwNGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMyNTMyNzdkNWRjOTAyZTI1OGVlNmZmMmY0MzA4YjRkYTQ2ZGJmM2Y3NmI1N2Q4MzQ1NWU5OGMyMTg3OGU5NTgifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1091-L1111", + "version": "repo-lines-v1:sha256:90c928ad9e8328b3f2fd4f0325c470b6bfee84f729fdaab7df4dc416481f2c8c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImViNGJkM2U1MzkyMzUwMzkzYmQxYmQyYjI0MjdmNjMwZGU2OTUzNjFkNjY2ODMzYzE5ZTE2NzEzYTRiMWZkNWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2MGI4OGEwNWQ1YjUzODQ3NjAyMjliZTYwNTcyZmU2MmIxYzI5Y2RjNTdlZGI1ZTY5NTFkYWE0ZmQ0NmM4MDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRiOWFlYjQyMDRmZmM1Nzc0MjY2NGY2NDQ3NjcyZWRjZmIyM2IzNDAwYzhhODkwNmFiNmMyODhkZTg5OGVjMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM0NDNjODdmOTI5NmQwY2E5YTZhZTg3MzFlYWVkMjVjYWJhMmZiOTcyOTAzMjQxNWQwMzc4M2M4NjQzZjQ2NmMifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/architecture/system-boundaries.json b/openwiki/.claims/architecture/system-boundaries.json index a4e20548..b62747d3 100644 --- a/openwiki/.claims/architecture/system-boundaries.json +++ b/openwiki/.claims/architecture/system-boundaries.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:f3b4a0dcddee51aa391d389de1ab210d6dc3216ee5664dfe83429fa642a50edb", + "pageVersion": "sha256:a6f8d86c38688d119e171586b5b7c1c46a68416470c47cda9fbe3cbee3d02f9a", "claims": [ { "id": "claim_085ce722f39f48eea75366ec3b3f7554", @@ -16,43 +16,47 @@ }, { "resource": "repo://Termind.xcodeproj/project.pbxproj", - "version": "repo-file-v1:sha256:a6aef8eda8e5dc79dd30cec5bd6695dfc39d8c06958c49b6d29ec60c3ef1398b" + "version": "repo-file-v1:sha256:f54f1c1bc5f44d2793a5b079b18cf8043d2b1d75455f8130d7a7e237602d3796" } ] }, { "id": "claim_07d6c15b703242fa94b68c4f347d23a1", - "statement": "ArchitectureBoundaryTests enforce dependency direction: Domain cannot import platform, UI, storage, security, network, commerce, SSH, or terminal frameworks; Application cannot import UI, persistence, or implementation frameworks or construct selected concrete infrastructure symbols; Presentation cannot import platform UI, persistence, or Remote Infrastructure.", + "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.", "evidence": [ { "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L163-L189", - "version": "repo-lines-v1:sha256:0d3b3a4cd81181b5228a2cfa0b6a89f30ffcaa8a77112e9c8ed819cc29a59663:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ3NDI5ODQ5YmU0MTZhMzMzMmY5NTcyYmY1NTM5ZDkzOTZjNDEzMjY1MWE4MzhiZGRhZGIzN2IwNzg1OWViMmUifQ" + "version": "repo-lines-v1:sha256:0d3b3a4cd81181b5228a2cfa0b6a89f30ffcaa8a77112e9c8ed819cc29a59663:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3ZGE0ZTRmODRkMjdmYjAxMTA1N2E3YjdmMzE0ODI3NmQyOWUyOTUyNDU3ZWE4ZTYyMmUzMmU4MWU4NTVlYmMifQ" }, { - "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L75-L106", - "version": "repo-lines-v1:sha256:11f74fcd104993cd2feab9af4770f39538b63efcdefeeb85a9faf48e46c50f74:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk2ZThiMDFjOTI0YTg1OTFkMDY1YTNiZWE5M2Y5Yjg3MTA1N2MzZmE2NzRiYzk5N2JmMWU1ZGExYjRlNzU2MWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiZDllMTYwYTMyNWIzNzgxZTQ5M2JlYjYxM2EzZjhjZWMyZTNkZDQ1OTVjODgzMDg2MTQzMTVkODZhYjdjYTgifQ" + "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" } ] }, { "id": "claim_04df7977ba1a43bfba0b2585bc5f185a", - "statement": "Persistence exclusively owns SwiftData models, versioned schemas, migrations, and ModelContainer construction; its current container uses TermindSchemaV34 and architecture tests reject @Model declarations outside TermindPersistence.", + "statement": "Persistence owns the SwiftData model set, historical schemas, migration plan, and ModelContainer factory using TermindSchemaV34; architecture tests reject @Model declarations in scanned desktop, mobile, Domain, Application and Infrastructure roots, but do not scan Remote Infrastructure or Presentation for @Model.", "evidence": [ { - "resource": "repo://AGENTS.md", - "version": "repo-file-v1:sha256:7cd9b9e940106ce07b1fc987586fc9c6ca1c4f9489cabb02791b627a05a1eedb" + "resource": "repo://AGENTS.md#L5-L11", + "version": "repo-lines-v1:sha256:d662a510b30f190ca7401445bf0ed33d43981f48b53c5a81081bca176aaf60e8:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjM4YmQ4MDg4Y2Q5OGMyYTJiZjdjZWUwMjg2NjU0OTRlOTA0MGI0YmIzNTBhYjMwY2VjOThmMmZmNDlkMjUyMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYjEzMjhkOGFmMzQ1YjI3MzczOTBkZjBlMWYwN2I1ZmZlYmE3Y2IyZWIyNzZmZDBiMDk1NTg5ZmVkZjgwOGE2NiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMmQ1ZDk4ZDMyNTIxNzM5OGEyYzA4Mzg5YzFlMjg1MDQyMTA2MDQ2OGUzYzI5ODdhODRiMDFjNDM0ZWU2ZDcyZiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMmM0MzRhZjQzYmUwYTA3MjE2NzE5ZjBkMjg5MjdhNjkzMzNhYmJlZDhiY2U0MWZmOTA4ODM2ZDIxNDk3NmFjNyJ9" }, { - "resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift", - "version": "repo-file-v1:sha256:2decf5319e2a1302f86a30e9dd9066658885034b8edd637368d1a3e2f8025682" + "resource": "repo://Frameworks/TermindPersistence/HostPersistence.swift#L776-L806", + "version": "repo-lines-v1:sha256:921208bc56423c098837786a9c40583ac0131d031db0843b5e545675eba1b171:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcxZjM2MjEyMzM2MGM4MDkzODU4YzIyN2I3ZTEyYmUyMDk1ZWQyODBkZmJkNzdlMDljYTMyMzJmMzlkYmRjZTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMyNzEzMGYzYzFhZWM1ZDRiODIxZjcwODBmYzFkZDUyNzRmNWQ4M2VjYzdmMWRlZjJlNzU2Y2Y5MTIwZDIxN2UiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5NTg0Njc2ZWZjMGU1YjI4MWYyNzViYTgwNjYwMzY0ZTRlMTI1MjkzOGZjMGRiMjZiMzVhNjE4MDgzMjM4ZDcifQ" }, { - "resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift", - "version": "repo-file-v1:sha256:ad0b99e06c0a0817f6980a6a682f016a27d45d86fd8c378ab1036ae910712cd4" + "resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L4-L22", + "version": "repo-lines-v1:sha256:b674d7c2d231d5b2d374e10cd417076ab8795bb2bc586fc20b530a68b283e3ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzMzA4NTlkNjgzODAyNWFiM2Y2NjIxNTU5NWM4N2JiZWI1ZDVlMDlmNTIxMjk3YmY2MzI3NTUwYzgxYzBjYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4OTUxYTVlMDA0MTE2ZjBmM2Y1MzVjODgxOTBiNmUwNmU3NGFmZGZlYjU2MTc0MTA0YTIzYzQyZjJiYTNlZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" }, { - "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift", - "version": "repo-file-v1:sha256:ca356c025f911101bbaf63a9a34b72736291043ed0fc0daa8dbedec972eac6b1" + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L221-L236", + "version": "repo-lines-v1:sha256:f8c236519e8486d9e23370a1125780885a560563104317d8b0667fde12b5c048:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyMzk2YTZjMGFlNGEyMDI0YjE2OWE0NWY3MjdmZjYwNWE4NDI4NjdkODJlYjJjOTNkYmNkNmVlNDg4YmExYWEifQ" } ] }, @@ -66,7 +70,7 @@ }, { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFI/App/TermindIOSApp.swift", @@ -74,7 +78,7 @@ }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" } ] }, @@ -176,21 +180,81 @@ }, { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" }, { "resource": "repo://TFM/Platform/MacDeviceName.swift#L5-L29", "version": "repo-lines-v1:sha256:2e3a802d84fd2b017f0074f76c3ef896d3127453e0142f3a054521e823ba686f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzZWIyNmFmMDY4MGI1ZTY3MGVmYjZkZGRhNjRmNGEyMzVmNDhmNTE2N2NlMWY4OTYwMDQ0MDU0MGE1OWRkMzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVlNGQzYWNkOTllYjdjOGNhNzFkNzZjODJjMTIxOTcxNzU5YjBlOTFmODVlNzhhNWQ1NDJlOWUzNWQ4ODFhODUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" } ] + }, + { + "id": "claim_7b91156dd01d4ba58713d5c46aa56683", + "statement": "The actual shared-framework Xcode target graph is consumer-to-dependency: Presentation depends on Application and Domain; Remote Infrastructure on Infrastructure, Application and Domain; Infrastructure on Persistence, Application and Domain; Persistence on Application and Domain; Application on Domain. Both apps depend on all six frameworks.", + "evidence": [ + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L1171-L1213", + "version": "repo-lines-v1:sha256:569b92e136ade5b983eb70625dc8ce2f1aa3f1b162bf69ff24ae18a3059ce813:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNlZDFmYTFkMmM5ZWNlYjY4OWU2N2ZhNzg4NGFjMTI4ODc4NjIwNzczODc2NzdmNWMwZmMwM2FlMmYzNTNiNTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2MGI4OGEwNWQ1YjUzODQ3NjAyMjliZTYwNTcyZmU2MmIxYzI5Y2RjNTdlZGI1ZTY5NTFkYWE0ZmQ0NmM4MDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU2MGI5MjNjYjkxMDkxM2QwZjMzZDc5NmU3NTEyYTMxNGIyZjllYWY5NzQzYzg1MGQ5NWQ0OTRmMjliMGNlMDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY0MTMzZmI4MjlhZGJmMWU4NWFiN2ZhNjgwYWMxMTY4NGEwZGNmZWRmMDY4ZTMyOGFlZTA0ZTA1OTg2YjA4ZjMifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L858-L899", + "version": "repo-lines-v1:sha256:a8f0ff3082a8bdced7d7813e2cdff3b064d2a3e5a6f654ae3a3070a126629d42:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRlZjFiZTMyODgzY2VlM2M4NGQ0NzZmZWNlNTMwYmJhOTBhMGIzNzNiNTE1MjkzOTY1OGQwODE5OGI4YjM1OWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiNTk4OTQ0NWRhZGE0MGYyYzkzYjZmN2JiMTBjOWQ5MTg0ZTI1ODczMDRjMjExNmVhNTIyMTZhODk0YzAzNmEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZhMzcxNmY2ZDJiYzhlNjIxMDBlNjhjMTEyNjk0NzJiMmE1ZGVhNTM0YTFiZDk2NmQ5NmUzNmQzN2JmNzg4MjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNjYjU0Nzk3YmMwZWYzZTM2MzU0NGU4N2E0NWNlNWI4ZjVhMDA3Y2U0YzI3MTE4YzVkNmRkMDAyYmUwYmY1NzYifQ" + }, + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L934-L1136", + "version": "repo-lines-v1:sha256:443e3c17cdb912366c7c5ec8a7c6b02fb60fded0938a6b48e70a48a27dfe4ec9:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAzLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0YjI1MmM0OTA4MWRmODIzZDdiMTIzMDgxZjVhODQxMTE3YTYwYzJmZGYxNzVkYjA0NTk4NjE2N2RlMGUyYzMxIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0YmI3N2E0MmRjZDlhNWUzNjdmNWUzYzhjNTI5NmNhNGM0OWI2ZTljOTExZDI1NDIwZjEyOTEwZTU1ZTY0MjkzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5NDU2MmVkZDViMGMyYTY0MTAxOGYzZGU4Yjg0MDY0ZmJjMWE3ZTEwMDM5ZDQzNmUyNzU0NmJlNDc3MjJlOGVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJiYmEzYjA4MGUzZjYyNDc1MTJhMmRjNzlkMzhkNDUwNzY0MWE1NTc3YzU2OTUzMDgxNTBhNTQwZTVlMWNkOTM3In0" + } + ] + }, + { + "id": "claim_8818e8f10d9942a185664769568eae34", + "statement": "Mobile composition accepts an injected container for testing, otherwise chooses a file-backed Application Support store for live operation or an in-memory store for tests and injected hosts; it constructs the shared Persistence container rather than the schema.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindPersistence/TermindPersistence.swift#L4-L22", + "version": "repo-lines-v1:sha256:b674d7c2d231d5b2d374e10cd417076ab8795bb2bc586fc20b530a68b283e3ac:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzMzA4NTlkNjgzODAyNWFiM2Y2NjIxNTU5NWM4N2JiZWI1ZDVlMDlmNTIxMjk3YmY2MzI3NTUwYzgxYzBjYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4OTUxYTVlMDA0MTE2ZjBmM2Y1MzVjODgxOTBiNmUwNmU3NGFmZGZlYjU2MTc0MTA0YTIzYzQyZjJiYTNlZTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L124-L167", + "version": "repo-lines-v1:sha256:c76c6c2207553af62caf65ca65361b2badf606be6df2057ab8fbe33207391368:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiNGE1MzM5ZTM3NWY0MTI1OWIyOWE3ZGRiOGE2MDhlMGY5OWVkYTEwOWQ4MDRkOTE1YjJmYjRkM2VlOTU5OWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJmZTc3ZTdjMGNmZWIyYjQ5ZDBjYTIzOGExMThkOTk0YTFkYWYyNjAwNWEyZDYxMGI3YmRkZWRkYzc3YjM1YTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxZTgyZThiYjBhZTE4ODAyMWE3YzViMGE1NmM4MWUzZWZmMzczMGZmZTYzMmE0NWEyM2UwN2JiNDgwYzk2NzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA3YzFiNmI0YjE0NDZiZDA4NTAwNzg4ZTk4YmJhOWQ1NjVlYmJlNjJmMTE3ZTRlZTc0MjlkYzUxNmY4MjQ4NjYifQ" + } + ] + }, + { + "id": "claim_5a69ab99b9f846db8487614c0a4757ae", + "statement": "The architecture tests' @Model guard only scans the desktop and mobile app roots plus Domain, Application, and Infrastructure; import scans are exact import-line checks and concrete-symbol checks only look for a fixed list, so tests do not prove all intended ownership boundaries exhaustively.", + "evidence": [ + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L221-L236", + "version": "repo-lines-v1:sha256:f8c236519e8486d9e23370a1125780885a560563104317d8b0667fde12b5c048:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyMzk2YTZjMGFlNGEyMDI0YjE2OWE0NWY3MjdmZjYwNWE4NDI4NjdkODJlYjJjOTNkYmNkNmVlNDg4YmExYWEifQ" + }, + { + "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L245-L300", + "version": "repo-lines-v1:sha256:97554b0b6762f85b0f292940aa809315e0f8c641560cdb8ca2cdf8fbec334748:eyJzZWxlY3RlZExpbmVDb3VudCI6NTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwODJlYzhiMDRiNTlhNjdhZWFhYmYxOTVkNWE5Y2I4YWJkMGE3NjBjZDc4YjE1MTNhNzg3MTA0MGE3N2Y0Y2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM0ODVjOTkxNGE0ZTFmMmY4YzUzZGM1MzYyODQ3NjI5MGQwZDAxYmFkZTA0NzQzYjVlNjczOGYyNTk4Y2M0YTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + } + ] + }, + { + "id": "claim_f21f9c91a31f4ea782f02018361ebdb0", + "statement": "The project specifies a remote AgentKit package with up-to-next-major requirement starting at 0.14.0; the resolved build pins release 0.14.0 at revision ffc4aa41c8854142aa47c35231e57f56f961ba9f.", + "evidence": [ + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L2852-L2859", + "version": "repo-lines-v1:sha256:444f908545e708b1d395265e4292e5529193fc19d4f609c8b5e06f6d68e13abe:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDhlMTQzODY5ZWI0MzVjMzZmNTljZTI5N2IxYWYxNzc3NThjMzVhNzFlNzJiMDQ2MTY2ZjkzNTNkODcxM2E3MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzYwYjg4YTA1ZDViNTM4NDc2MDIyOWJlNjA1NzJmZTYyYjFjMjljZGM1N2VkYjVlNjk1MWRhYTRmZDQ2YzgwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzExMTg1YzI4MDExZTZiNWFiYjU1YzRlOTQ5MjMyMTkwMzE1YWFmNGZhYzU4MzhhMDFjMWZmNTQyMjgwZmFiOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2M5YzA1MzMwYWQ3YTFmNDVhMmI2NDU2MTQ4OGZmY2NjZGY5Yjc3YzZmMDA0ZjBkYzRmNTBiOWRhZWFiYjdmNyJ9" + }, + { + "resource": "repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved#L4-L11", + "version": "repo-lines-v1:sha256:fca958a7ad62418ce0a9e8b6086dc052497d2a11aba31a72de600c9fb3446d61:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjljYTg5MWJmZjdhYzFmN2NlYWFlNDBlZjA1MTA2NmJlOWVmZTQ3YjRlNDI4MWU4NmMzMTliZTJjNTVlYmNlNCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOWI2MmY2MGQ4NTkwYTU3OWNmNDZmOGQ2NzM3OGM0YzU3MmI5NjJjZWNjZGI5MGM3YTVmN2I0MmI5NjA3ODJhNCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNWZmNzZlNDczNTc5ZjY2ZjA4ZDYwNzE5YWQ5ZWI0MGZhZGRhN2M5ZTE2NjFlZjY4MzM5MzAyZDYwNDI3ZDFhZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNjdlNmMwMmJkYjc5NzI3MjI1ZDU2Y2UwOThlNjgyNWQ4MTFiZWFkOGRlMDcyYTEyOTA4NTllNWE5NmNmODQ0NiJ9" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/concepts/agent-runtime-and-assistant.json b/openwiki/.claims/concepts/agent-runtime-and-assistant.json index 033e4fcc..27090ad0 100644 --- a/openwiki/.claims/concepts/agent-runtime-and-assistant.json +++ b/openwiki/.claims/concepts/agent-runtime-and-assistant.json @@ -1,22 +1,22 @@ { "schemaVersion": 1, - "pageVersion": "sha256:88227616aa0b14b25c451de0e54bf45792788cfeaa77194995405b81c344be9a", + "pageVersion": "sha256:40e0ea051b8758c505d4264ef66de5fe3e767ee52a8afa2858337c6827d609d1", "claims": [ { "id": "claim_981f16f030e9469588af705aa377161e", "statement": "AgentKit owns the host-neutral agent loop, provider-facing runtime, approval handling, MCP and generic tool catalog, while Termind assembles host-specific SSH/SFTP tools, policy, persistence, and UI around it.", "evidence": [ { - "resource": "repo://AGENTS.md#L16-L18", - "version": "repo-lines-v1:sha256:79d9222951afd1cde2967f4987b4aa7b4347f1510f1fc4d1141010690b9c8bff:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGI2ZWFiNGFjNWIwNmRiMjY5NmQ0ZDUzZTJlN2YwZDE3MzhmMWI3NTAyY2UyZWY1YjcwMzIzZjg3NjdjYTllNiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZGRkZTk1MTMwNGUxYWVlNjRiM2IyYmY3NWZkMzI2YjAyZGM0OTE5YjlhODM4MGZjZTY1YTAyY2VjOTE3MzdjMiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYWM1NjRmZjMwNzY2N2QwZTgzMGJkYjkxYmY1MDYwY2FlODNhMjc2NzRkNTU5NWNiYTU0ZGMwNmQzNmE2NWMzYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMTVkOTdmMmUwNzM5MTAzZjc1MTA1MjljNjA1Zjg0OTIzMTdkNDJmNDA5NzEwNGFmMmRkMjBiOGUyNmZhMmNmNyJ9" + "resource": "repo://AGENTS.md", + "version": "repo-file-v1:sha256:7c19a99ec73d4473ac94bb134b62a1306c62d1285e5b8af26430f1d466de35a7" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L385-L501", - "version": "repo-lines-v1:sha256:261028a999073e8a0cb935c25c5226d7e3ccbb616cdf003ce8ba9d54ffb92c31:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE3LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJlYzFiOGExODllNmEyYWM4ZTM1MmJlMDMxYmIzYWY0NTI2MjM2NDU0MDI2NzIwODY5NzZkNWVhNTQyYjk5MDQ0IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiIyZDVmMTIyNGM2ZDQyZTY1YWVjMzZmNmRjYjBiMTc2Y2FkMGJjYjU0M2U1ZjM3MDMzOGQ4ZjYzZjk0ZGEwZWM3IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIyYzE1ZWYyMzVmYjkyZDFkYmQwNTRjZTlmMTFiZTRmMzA0NTVkYmRjMmU3MzkwNGY0MDYzYzA2M2M5ZjM5MzI2IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlZWMwMmIwMGE3NjI5NDE0ODA2ZDEyMjI3NjliODBlMGY2YjFjNTFmZmE0MGM1OWMxMTI5YjJmNDE4Y2EzZWM2In0" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" }, { - "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift#L42-L68", - "version": "repo-lines-v1:sha256:1be121a99f843d9d127884deb2bf2d9aeb076f899bc7dd89017d85db3359e991:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdkOGI0OTE4MTMwMjdmMDQxMDIyZDAyZWNmZjI4YzIxYjYyZWMwMjZlYzE0MmJiZDE2MTU5MTYzYmY0YjFjYmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFhOWIyYjIzNmEwNjJlM2M5NDU0NDlhNjdjMGE4ZWZiNGU4NGM4Y2UwNDI0Y2YzNzZjZmY4MWE1NGRiMjIwYjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AssistantToolRegistry.swift", + "version": "repo-file-v1:sha256:8ccfafe881aacc3f7232d30cef9c97588787771dd925d726b5591efa15c92021" } ] }, @@ -25,24 +25,12 @@ "statement": "An accepted Termind submission synchronously captures composed content, context, model/provider/credential, reasoning, permissions, search, skills/registry, Guardian and preparation settings before compaction or memory awaits; a fresh runtime consumes that capture and persists a running snapshot before model work and transcript snapshots around tool-result rounds.", "evidence": [ { - "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L213-L274", - "version": "repo-lines-v1:sha256:0dfd924390c397077812263deb5dd48a301f249f10478b62641a686cfd342a4c:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiY2NmYjg3NmVhNWUyNGFhMjgxNzFhOTdlM2NlNDFhYjIyNjE1N2VlZjcyMzhjNDMxMmVkOGQ3NmJjOGEwODUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkNGFlYTM3NDhjNzUxOGU3Zjk1MWMzNGM0MTQ5M2FlYjY4OTgxYTg1YzBiY2UwYTk5ZTZmOWY1MTQ2OGQ1NWQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAzNDE3M2M2NjQ2NDEzMTc3YjQ1NmZmZjdiM2MxY2Y4Y2Q3Mjg1Y2IzMzAxYzI0ZDM3MGU4YmZiNzNiZWVmOTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI3ZTA4ZDYzNDU5ZjAxMzEzODQ4MDgxMGIwZmI3ZjBiYTJhYWY3MmM5MzhkZGViZDEyYzRhZWZiNTEyZDQxMzYifQ" + "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift", + "version": "repo-file-v1:sha256:dd5e6ea3dd365910d2a30a88da9029bd972a547b511503e9665857da494271c3" }, { - "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L303-L318", - "version": "repo-lines-v1:sha256:fd811671f5fdc47d264e5c3d26b3fb815385a39f5747a7d460403896bb8c0081:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBlMmZjMTRlMmFjYmU5MjgxYmI5OTRmZjQ1NGUyNDAyMTE3MDQ1OWI5ODJjM2ExNTlkOGJlODM5NWI2NmJkNzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkNGFlYTM3NDhjNzUxOGU3Zjk1MWMzNGM0MTQ5M2FlYjY4OTgxYTg1YzBiY2UwYTk5ZTZmOWY1MTQ2OGQ1NWQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVkN2RhMWFmYjFkMTc3MmUwNTY5YmU0MWZkOGQ0YTA4OTczNWNlMzczNDExNGU3OWZkYjJmMGJiMDdmN2ZmODkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2ZGI3YjgwZDA1MzcwODYxOGIzZTUzNTJmYWM1YWE3NTUxN2M5OGE4OWVjNGNkYzU0MWUzZjE4YTgxMjY1ZGEifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L284-L304", - "version": "repo-lines-v1:sha256:de29dc974cbd2c72ac1a59847fd02fc322550b4b15d0016d4ac1a76e768f07f8:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZhNWZmOTFkNGU1OWMxMDhlZWFkYjMzYzhiYzk3NTk1NGM4MjM1MDQ2YTcxNDRhNDFmMTBlMmI5NzgyYTc2ZDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ1MGE4MTlhNjgyMGMwMzcxODE2OWM0YjllYmQ3ZThkODI1NDlmMTgzZDE2ZjkxYjM4YWY5MGZkNTM4ZmQ5YTkifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L474-L501", - "version": "repo-lines-v1:sha256:810bdc77e6681b23d6f9936b515073efa39a5f809eefcc66b0f6c79e571bec35:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4MzNjZDg0MjZlZTc3ZDg3ZTk4YTlkYjY4YmMyNDVhYmEwYjYxYzY4NGNkZjJiZDhlNTJlY2ViYTA4YTliNzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJkNWYxMjI0YzZkNDJlNjVhZWMzNmY2ZGNiMGIxNzZjYWQwYmNiNTQzZTVmMzcwMzM4ZDhmNjNmOTRkYTBlYzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzODdlODkwYzgzZWE5ZTZkY2U1MzZhMTBhM2Q5MjBiODQzNTk3ZDMwMTQ4YjY1ZjYyYzYyMzk2OGMyM2RhYzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVlYzAyYjAwYTc2Mjk0MTQ4MDZkMTIyMjc2OWI4MGUwZjZiMWM1MWZmYTQwYzU5YzExMjliMmY0MThjYTNlYzYifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L516-L630", - "version": "repo-lines-v1:sha256:b1882f48ba2a0c4f0faaa010c3ad73fbbfed243a2f0f51c0d883ed8058e5a3d3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIzN2U2Yzk0MTIwZGUzNjU0OGMxZjcwMTkzYzMxYzg0NTQ1ODI0OGQ0M2E4N2U2ZTU0MjY5MTBmY2VkYmJlOGJiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3NDhiNTNjYTI2MWZjOWVmMTVjMzg5YWVkYTA0Zjg2MTFjN2I0N2UxOGU2MjA5NWQxMWRmODkwYWNjMWQ4ZjRjIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwZWE5ZjA1OWViZGRiM2M1YTA1MTQwYTNhNTJjMTM2MmU4ZGVhZDhlNmU1MjllZWNhNWMyNjkxOGZhNTMyNTY1In0" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" } ] }, @@ -51,12 +39,8 @@ "statement": "ConversationModel keeps a display projection separate from the authoritative transcript because replaying display messages would lose tool calls and results; it owns the active runtime and consumes its ordered event stream.", "evidence": [ { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1907-L1935", - "version": "repo-lines-v1:sha256:29086746228df689c5ee73c74a8f470141cf46d41005fdc2804d4ee9d81f9759:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVlY2VjZjZjNTcwM2QwMzM4NThjMTkzNjQyMTc5NGFhNmExYzY1MjAyMWM1ZjQzNTI4YTk1MTlkMDE3NzliYzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAzYjU4ZTRmZmFjNDQ4ZTc3NTVkYTFlNTM3ZjU5ODgxMWFjYzY1MTAyODBjMmUyMjA1YTk5M2JhNjI2MWEwOWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRiOWM2YjNmMTRkNjAwZjcxY2Y5YzBmZDdkOThiMTljZjQ1MzMxOWYzYWQyMzFhMmIxNDA4YjRjZmQ2NTNjNDkifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L785-L803", - "version": "repo-lines-v1:sha256:6f128436b4d34e1d8dff80a345e8abc178fb1737285d7cbee881bece263cf02a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjljZjIxYjFiNzJjNDQxMzg5ZmYyMzE1NjcxOTNiOTgyNWY3ZjQ0YWY1MTI4YmVjNjlkNjVjNmUzOGI5NWQ0YTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA1ZjhjNjMxNWJmY2Y3MzE1OTUzYTJkYTBkZDM0ODVhNTkwMjk0OTExMzVlMGViZmFjYmI0MTkxZmE1OWVjYWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdhZjhmZjY1NDM5MTMxODVjM2UyNWNhNWQ5M2U3NjhlY2NjZTI4ZmRmNzZmN2Q1NTA2ZjRkMmViNzJiMzYwMDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdhZjMzNTQyNTM4N2U2ZjRiZTIxOTVkODMxM2YxMzhjMTM4MDk2YmYzOWIwNzE0Y2NiZDA2ZWI3NzhmZGFkOWUifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" } ] }, @@ -119,20 +103,12 @@ "statement": "Steering messages queue for an active runtime and become transcript history at its next model boundary; stopping requests runtime/task cancellation and secret disposal and returns undeliverable steering to the composer.", "evidence": [ { - "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L139-L165", - "version": "repo-lines-v1:sha256:1893129dd01a1c8a79a01cdf4625cb226ff4ebca0b1b11cdfc4a9827340a17ca:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4N2Q1NGYyZWZiNDBlN2ZjNDdkYmUzNjJmOTgzNzNmYzJkZmI3NDM3Yzc1NTlkMzEzYWFmNzAyMWZjMDkyNGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFhYmQ3YjdjN2RkYTI0MTcyNTJhMDY3ZmY2YjU5NWQyMDllNGI5OTc1ZGRhYmJkODc2M2ZkYzFkOWQyMDQ0ZDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjEyZmQ2NTFmYjQ2OWY4YjVmMTQ0NjRiY2M2ZGMwZDZhYjJkZTM1Njg4MDhhZDcyNzYxYjhiMGNlNTFlNDZjNjgifQ" + "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift", + "version": "repo-file-v1:sha256:dd5e6ea3dd365910d2a30a88da9029bd972a547b511503e9665857da494271c3" }, { - "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L249-L265", - "version": "repo-lines-v1:sha256:dd7262281b0133a9a56570381c1b52df5dededbbb751d9e81871e8fd08bb10b4:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjMjU4YjdiNGY1YjRhZjg4NjE4ZDI4NGJkODg1Y2VmYzNiMmQxOWRhMTk5OTlmN2ExNDI0YmQxMDliMjNjZjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmMGE5Mjg5N2Q0YzU4ODhhNzJmMDY5NDJjNmZkYmViM2NiNDAyMzBlY2U1ZmZjMThiNWJhYzU2ZTM0Mjk1YzYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRlOWQ2MDRlNmM4MjFhMGNkZDdjNjhjMGQ5MjM2ZGYzNGQzYWY1NjM5ZDI2YzAxNDRiMDQ5MDQzZTgxMjBmZWMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY1N2YwZDhiZTM1MGE0NGY1YjRhYjlmZmE1MDUyMjc5NTBjODk3YmI4MGVhZjI3NzNkMTAxODNkZTljNjE1ZWQifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1956-L2040", - "version": "repo-lines-v1:sha256:f0190ce17ccd16ba2db4de8b4ee133516fd1cbf030f89f914b0643ab0477deb4:eyJzZWxlY3RlZExpbmVDb3VudCI6ODUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmZmM0MzNjZDM1OTM3MTAxZjgyZTM2MzI0MGZiMDkzMWJlMjZkYTcwYjg1MjRlMDEwYjVjMzlkNzdkNWYyNjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVkYjZjMmYzYTBiZWM4ZmU1ZTRlYjY3M2NlODAwMmMwODM0YWJiYTU1ZDM2MjhkOTMzNzUxYzA3MmUwYTc4NGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmMThmMGI1OGIyNjAwNzUwYzBkMjdlZDlmMDA2ZGRhNjZiMjBmYWM4NDg1NzFlYTVlODUwOWFlZDQ3NWJmNjkifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2556-L2581", - "version": "repo-lines-v1:sha256:bda10632960326b0f4e14ddac898407fdd0f3a8325eb63e712a04206f75ef600:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4MDc5OTUxYmYwMGZiMjNmYzBkZDhiMGIxMDk4NzFmMzQ5MzJiYjNmZTEyZTA4ZWZhZDdkYjllMzQwMjY2NDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjViMTQxZjY1OGUxNDM2ZWUwZGNkY2I1NDRhYzllNGQ5ZTZhZjI4ZmYxODdlNTkwZTRhODljYjA3NGEzMzY1ZjkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRiMTZkMmIxYWNkOWMwZTFiMzVhZmMwMzVhZWM4YmRkZjMyODcyZWJkNWQ1YzM2OGNiNDI5MGI3ZDU3MGJlMGMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFiYWFiMmE0NTg0NWUzZDAyOWM1NDI0ODBmMGY4NThiZDMwMmU3OTdmNjNkZjFjNzIzNzMzYmFjZGY1YTgwYTMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" } ] }, @@ -199,16 +175,12 @@ "statement": "Skills are app-managed packages whose enabled catalog and inventory are captured at submission before preparation; only SKILL.md is procedural instruction, and a skill does not authorize commands, writes, or transfers outside the normal approval policy.", "evidence": [ { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L394-L404", - "version": "repo-lines-v1:sha256:3bcf15a3ce14b9ed88dd81ab4acccf0d8910eee98b7e5e350a7647991cea8ba8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4YjYyNmIxMGUzNGMyYmYxMTE1OTg5NGYyYjA1MTU4Y2I0NzVjYjJmODYyMjRiNjg2NjA2Nzk5M2JjNGEyZmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA5MDJhM2QzZDU4YjYwMmY0YjZlNjhkMTAxMjRjZjE1YThmMTMwOGYyYThlMzdhY2RhNzQ1NDkzOWEyOTllOWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc0MDU4ZjhjMjAyYjNmM2Q5YTEzOGY2ZTMxOTAwZjc1YTVlZmM4N2Y3OWM1OGZmMzQ4Mzc2ODJkNzkyMTVkYmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRjNGM2YzQwNjcxOGIzOWFjYzE3Zjk5ZGE2NDhjZWJkNmRmODZiZWUwMmFkZjAzNDUxZTQ5YTRkZDExYmIwZjUifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L532-L566", - "version": "repo-lines-v1:sha256:1436f7c04f746958de27f6bda7b04d27675582b1bb906c9d464b4d2c9b7494ec:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2ZTY3YmE5OTE0YTMzNWE1NTMwYTQwZWE1NDBjMzc2Y2E0MjM5MGNkZmFmMmVkMzgyYzM3YTFkZmQ3MzcyYWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmMjIwYzhiMTI3ODQ1YTBiNDdlOGI4ZDY5OWQ0YTZhZmQ1OTVjNmQwOWFjYjVmODliNzI2N2Y4MmQzMDc2ZTkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI1ZmNhMDUzYmQ4NzkwZTZmOGI0N2ZiZTAzMWZhNzk4OWFhOGNkY2EzYWZiYzI1MTRjOWI5MjkwNWJjOGJjMmUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIzZjQ3NzRkYmY1NmE0MTNhNmY3ZTUzNWRlYzdhYTU1NjRjZjcxNDIyZTJhMGI4ZjU5YWQ2NWMzYWZlYzE5MTUifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/TermindAgentPolicy.swift#L46-L49", - "version": "repo-lines-v1:sha256:81359ab87f7ba9a790818b6e8d31c3a5fbc50e1fb4e4b2cead9f1a7ca42567cb:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMTZiY2U2NDRlZDg2MDdlNTRjMWExZjU1Njk3M2VkZGFkY2ZiNWE4NGIxYWE4MTRhNDMyYmYyNGU2ZWZjMGMxMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMTNjODMxYmFjNTNlN2E1NDdiNjZlYTk0YzNlMjJkYjY4ODMwMWYzYjc1NTkzYTBjZDA5ZTNjNmEyNzBhMDg0ZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZjM0MzUyNGVhMWRhYjc3YzE0YjM5MGJmM2I3OTE2MmMwOGZjNTg3Yjc2OGRkMDQ1ZTQxYmY0MjI1NTdjMmEyYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZDQ2MzU1NzZhMjE4ODFiOGFiZjIyYmY2ODJhOGEyNDUyY2NjMmJjZGE5YWFmYTY5ZmFlMDNmZGI4Y2YzY2JmMSJ9" + "resource": "repo://Frameworks/TermindApplication/Agent/TermindAgentPolicy.swift", + "version": "repo-file-v1:sha256:e2480863994a403ef1a84e771fc16cb9729c43a1de3a64d96806f099125d1b0f" }, { "resource": "repo://TFMTests/AgentSkillTests.swift", @@ -222,37 +194,25 @@ "evidence": [ { "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift", - "version": "repo-file-v1:sha256:3a875082b9ca385a928fcf0e8bda396e66be74ac882859697c6ccf5423058df7" + "version": "repo-file-v1:sha256:53303b99278ef87af5bc0365c6546c10de8ea4cc6462f0bc9e1d39ba048515a7" }, { - "resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L123-L224", - "version": "repo-lines-v1:sha256:4db4ea2d811f10d0fb1345147f521e5a493179ad7661195ed552ca2d61cc58f0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJiNGNhOWU1NTU5YmY4NzhmYTExNTgzNzMwNDE0Nzg0YzFmMDk1NTY0ZmRmNzA2MDI2MzY3MjliYWQ2YjMwMDA2IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIyYjI5OThkODI0ZTVjZDc3MjNiZWY5MWI5MWE2MDE0YzEwMzMzMWNjMTY5M2Q0NDQyYThmMzFlOGZjOTEzNTYwIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJiZTQ4YWE5NDM3ZTU2OWExZGIwMWFiOGY5ODQ0YjM5MGE0MDQwOTkyMTdiMmQyMThhNTRhNDM0NmRiOTk1NjQwIn0" - }, - { - "resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L6-L45", - "version": "repo-lines-v1:sha256:8365553c7428472ce048f7d8c2fe2b1bed26640a0e82a3b015acbeb3d131ee0a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2ZTgzNWJiMzkzNjdhODBkMDdiMDkxZDJmZGIwODFhZGM0YThkYTg0NmQ4MjhjYjM1YzUzY2IwYzUyMjc4MDIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiNTk0OGZjNGE2MTllOTBjZDM5Yzk1YzdmNjdlZGJhOWU2OTdhZGJlN2YxNmFmMjY5NmM1ZGRlNDMzMTgyODciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNiZWFjYTU1MGI4N2Y4MTM4MGM0NDM2MDc1YTA3MDQ0NGJkMTRhYWQ4MzMwNTZmNjE0MmYyMDdiNzlhNjdkMDUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5ODg4MmQ2NWE4M2YwNjEyNzFiMTQ0MmNjMWRhOTIzNzZlM2E5MDg5NzczZjMyNzg5ODQ2NTFmNGZmZjQzNDQifQ" - }, - { - "resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L94-L105", - "version": "repo-lines-v1:sha256:7062dea6d750d5f5844cdd575659ace68dc528cbe06fd4c3500d4c6a4bd7db2d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyNDE1ZGFjYWRjY2RiMTk4ZDJkYmQ4OTI0NDA2Zjc2ZjE5NTFmNDBkNTYzNGVmNDRjNDYyMTdhNTQ5MmMwNTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExNGJhMjZkMGQ0OWIyMzAyZjU5YmRhY2U4Y2IzNDE5N2YxZTI1YmZiYTZiMzdkOTVmYjAxMjNjNjU1NDg4NmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFlYmUzM2VkMWNmMmIyN2FiY2ViMTU1MjJiMGE2ZThhM2M1NTZmZTA5NTYxOTY1NWIwNmU2NjJmZDYxOGRlYWEifQ" + "resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift", + "version": "repo-file-v1:sha256:5d148d9b678c6512cdf58a6803d31d360869a54ecf3c7cd1176abd1126ed2bb6" } ] }, { "id": "claim_a3ad24a30cc74874af7e95eba686afbc", - "statement": "Disabling Hermes memory invalidates contexts and cancels indexing/reviews while retaining storage, whereas destroy persists disabled state, joins work, and removes the owned database directory; stale accesses are rejected by generation checks.", + "statement": "Disabling Hermes memory invalidates contexts and cancels indexing/reviews while retaining storage; destroy persists disabled state, joins work and removes the owned directory. Generation checks reject stale access and UI publication, without rolling back a storage write already committed in flight.", "evidence": [ { - "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L232-L255", - "version": "repo-lines-v1:sha256:1f1936e4e3cbc44909d06cc25a5f18b6c26588b7ff8596107fe54c2e1c9e1a5c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhlNzEwNmQ4YmYxZmZiMTA5ZGJhZjNlNzU3ZDYyMzA0NGEyYTE4YTZhODg4ZmU1YzllZGFiNjFjMWQ1NjBkMjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjYThiNmYwOTgwNzYzZjgwY2I3Mjk4ODliYzM3MTdlMTQ1MjBiOTkxZGVkODdhZDNhNWZmOGUxY2FmYTJjMzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MjgxMjhkMDk1ODYwMmUyNTRkNmFlNmVhOTBjZjM0NzA0OWYzNjdhMDE3MDEwMjJmNTI4ZGRhNDkzMDU5OTgifQ" + "resource": "repo://FrameworkTests/HermesMemoryTests.swift", + "version": "repo-file-v1:sha256:71e95fb6c946bc98afa02a8b141769b9c8aef0e8fe8572b48080a0047a5becf6" }, { - "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L52-L76", - "version": "repo-lines-v1:sha256:63ceffb701cb214698f1c57e2105b4dc02d7d20d26ec8b71c4eb50058a6e8aed:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYzVkNTIyNmFhZThmY2Y0MzhjMzM0OTQ3MWY0M2JlYWU3ZjkzYjAwMTlmOWY3MTIxOWQyMzhhNTY3MWU0YWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmMjE1Y2QxMWU4MjNlM2M0M2IxYWY0OGI2MDBmNDQ1ZTY5MDA4OTZmNmU1MmFlN2U1ZGI3M2FmYjFkNjMwMmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU5NzJkNjIzZGZjOTFjMGU2YzQ4MDU1YzY3NzhlYThmNWUxZGQxOTYyZGNlYmY3YjY1NDQ4M2NlZGUzZGY0OGEifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L98-L140", - "version": "repo-lines-v1:sha256:63a4e0832eb58af19f1014b010116530bd83aa6cfe5c62c9e3643d154d77383e:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk5MmZkOWM4MzE1NGM3OTBiNGI3MDUyY2ViZTk3ZWI5ZjVjZjYyNjZhOGFkNGY2ZWMyOGY4NjY5MjU4NWNhMmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc3MmY5Njk1Yzc0NjdjNzQ3NzNjOWNlN2ZjNDI5YzVkMGQwZTQ4N2YzYzUxZDE1ZDY2NjhhM2QyNDA3MmJiOTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFiYzgyYTk3NzE1YzQ3N2I3MzM1MWJkN2M4NGVkYWRjNTdmMTlhM2QzOTIyYjE2NjRjZTlmOGZlNTdkNzU3ODIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQyNWZmZTlhNjZiY2Q1Y2QwNWE0NDhhYjFlYmQ1NmVjMTJkNTg1ZjYyN2RhOGM5YmI2ZjYxYTVhNWUzOWU2YzcifQ" + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift", + "version": "repo-file-v1:sha256:53303b99278ef87af5bc0365c6546c10de8ea4cc6462f0bc9e1d39ba048515a7" } ] }, @@ -331,16 +291,12 @@ "statement": "Conversation steering changes the sending session and only the terminal_suggest availability key, preserves other overrides and skill/plan/memory context, leaves a legacy absent snapshot unknown, and updates activeContextSnapshot only when delivery occurs.", "evidence": [ { - "resource": "repo://FrameworkTests/AgentSteeringTests.swift#L187-L233", - "version": "repo-lines-v1:sha256:c063ee9ee073185632ec59778a870a9595ae3c988770a96bd2dfee10f2ba5338:eyJzZWxlY3RlZExpbmVDb3VudCI6NDcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxYmE0NzE5YzgwYjZmZTkxMWIwOTFhN2MwNTEyNGI2NGVlZWNlOTY0ZTA5YzA1OGVmOGY5ODA1ZGFjYTU0NmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUyNTlmOTQwOWQzOTg3ODRhY2EzOWEzMGU1M2VmY2E0MjlkZDdhNzExZWY1NTZhMzhmYTZlNGRlY2VmYzIwNjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAxZjljNDg3Y2RiYjcyYTAyZDg2OWMyNmNmMGM5ZDYwYTdmZDg4ZTBkMjcxYzM1MGM5MTgyNDM4YjYzY2E3YmIifQ" + "resource": "repo://FrameworkTests/AgentSteeringTests.swift", + "version": "repo-file-v1:sha256:5f5c5a357ce9559972f5f71fe4ce5834006fabc14ffa157d906996254e29fd12" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2010-L2027", - "version": "repo-lines-v1:sha256:458a3fd6f7bd7ffcce08a4a412975c949076d429ce17f65d44c3c2ccb774bcb2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI5MzFhZDdmZGZiNjJkOTVjY2U1NTA2NDE1NmIxYmM1Nzg5ZTU3ZjhiZDc5MDQ4OGM3MzU1ZWM4MDhkZTJlNzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE3YjgzYmUzYzE2ZmJiMzE3MTQ1NzRmYjUyZDFhYjU4MWI3YTFiZmI2MTI2ZTI5YmI5ZjkxMWUxMzNiN2QzZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlhMjk1ZTVhYjdlZTNmODg1ZDE5YjdlYzE0ODJlOTI2NjJmZDcxZDdjZWM0MWZlMzUyYzE4MGFlNWRmZjFlZmUifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2556-L2581", - "version": "repo-lines-v1:sha256:bda10632960326b0f4e14ddac898407fdd0f3a8325eb63e712a04206f75ef600:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4MDc5OTUxYmYwMGZiMjNmYzBkZDhiMGIxMDk4NzFmMzQ5MzJiYjNmZTEyZTA4ZWZhZDdkYjllMzQwMjY2NDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjViMTQxZjY1OGUxNDM2ZWUwZGNkY2I1NDRhYzllNGQ5ZTZhZjI4ZmYxODdlNTkwZTRhODljYjA3NGEzMzY1ZjkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRiMTZkMmIxYWNkOWMwZTFiMzVhZmMwMzVhZWM4YmRkZjMyODcyZWJkNWQ1YzM2OGNiNDI5MGI3ZDU3MGJlMGMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFiYWFiMmE0NTg0NWUzZDAyOWM1NDI0ODBmMGY4NThiZDMwMmU3OTdmNjNkZjFjNzIzNzMzYmFjZGY1YTgwYTMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" } ] }, @@ -457,28 +413,28 @@ "statement": "Desktop and mobile prepare edits synchronously before creating a UI task, preserving original attachment payload/suffix but capturing fresh submission context; performAgentEdit checks identity before tracked persistence and again before runtime preparation, and failed persistence does not apply the live edit.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L450-L503", - "version": "repo-lines-v1:sha256:1c6b9ba0438e47aa7828a8f0a41cdc7625ac586fd9baee676a531b04a954769a:eyJzZWxlY3RlZExpbmVDb3VudCI6NTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZkYTc3OGQ5NDJjNzRkNGFjOGYzMmM1MTgyMDg2MGFlOGE2MDQ5YWE1NDUwYTE5NjMzMTM4MmNmNWVmNWU1MGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJhOTU4ZTIzMDAzNTJiNWU3NmQ0YzYyZWM3ODUyYjY4NjViZTQ4ZDgxODg3NDg2Nzk2ZTkyMTI2MmZkNGRmNTcifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift", + "version": "repo-file-v1:sha256:40ea45f2c9460238030ad6c00ed2f9ac58ffdfbefbe7500d752238d97379a217" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift#L129-L147", - "version": "repo-lines-v1:sha256:45383d212fb6991f01b24f3ea84538b0f619b50ed950673b4c79037e4de1652d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU3ODhmN2QzZWVhNGY0NTY0NzdmM2QwMjliNTAzZDI5YmU4YjExOTNiNjJjZTZlOWMzZTk5ZDQ1NDczMjViNDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4MzBkMzQxYjc5NmIyZjQyNTk4YTk3M2UwMTJkOGIyZTZjNTE2MDkwYzliMDQ0YWMwZDhkYTIyZjU2MzI4MzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift", + "version": "repo-file-v1:sha256:4db42452efcdb40e5be1e5de14d1faaaccf41d15fbea9978ab160016d3abfe95" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L216-L281", - "version": "repo-lines-v1:sha256:0b8c25408aec78da9722af3b9358ea9a949a5bf115e9d69ec12834362b0fbdee:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk3MTI1MTA3NjE5NmE2NjI3OWU2MDFjYjExNTRjYjNkYTQyNmM0NmUxYzVkMjBmZDJiYmYyMWM3Yjg2MzE5MDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM4MDU1NTIyN2IxNGM1ZmEwYTQ0NTA1NjhmM2U0N2RmNzAxMDg1NjFlZDU4NjM3ZTZiODlkZDc5ZmVhOGE3NzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAwNDYxNmUzZjI2ZjhhZWRkMzU4YmNjODQ3OTZkZDA1MThhOTIzOWYxODRhMTAyMTY2ZDFkZTRmOGRmOTRmODIifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1054-L1067", - "version": "repo-lines-v1:sha256:4f484d7cfc22662766e35da9dbd2bbae1e661c48fb02f3e454ed67e39e0efe50:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZkNDEwYjZlNzRkZThiNjdmYWNlOGI5MDE5M2EzYWNiMzg2Y2U2OTk1YjQzMGUwZTVlNThhZmFiZWE0NDFmYTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNmOWI5MjU0ZmFlZTRiMGFkZWU1YmRlMDZjYjY3MjI2ZGI3MDQ2NzUwYjU3NDVkZWQxNzI4YjQ2OTMyODEwZjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImMxODE2NWIyNGI3ZDdhMjdiNTZlZTIxZDVmNzk5NTFmODRkNTk5MDY1YmY3YzZlMzZkYzE5ZjBkZjM2ZWYyZGMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" }, { - "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift#L215-L227", - "version": "repo-lines-v1:sha256:cd20a3869cf3d54e2dba2169f1e5d4a254f24780ec533eae7cebbc62715da7e2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU5ZjlhOGZjNjI0YTNlM2JjNjU0ZjJiMGJjYTRhYjk4ZDgzNGJiZmY0M2Q2MTI2ZGNiYzg3OThhODE4Njg0MzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImVmMzBhYTA1MGU1ZjU1NjUzODUyZDU3YzU5ZDBmZWFhMWUxZTJkNmJlYzc3Mjk1NTQ4ZjFlNjExZWZmNzc0OTEifQ" + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift", + "version": "repo-file-v1:sha256:8a9a00fed4426631856719583ac4fe07542c1b12d159913a3936b39342dcee8e" }, { - "resource": "repo://TFM/App/AppModel.swift#L638-L654", - "version": "repo-lines-v1:sha256:52f1ee86dd5715fa752288f82f000ad9f5df3df9a8b00a1cd9ca301d14921032:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFjNDJhZWNiYjEyMjRmOWZlOGI3NjQwMDJhOTcyYzgwMzBiNDNiZjY5NGI2MDdjZmIzNTFlM2QwYzFmZmJhMzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFlZWMxYmQwNjQ0MjU2MWMzNjBkM2Q1MzgzZmQ3MTQwMjEwNzMwMWI2NWQ5NGYyZjk1YWI1MDIwYmRiYjdkOWMifQ" + "resource": "repo://TFM/App/AppModel.swift", + "version": "repo-file-v1:sha256:0029784efe4588e87c3dc18317fdfaad46bed6b3a32bcf72dd0dd9b1c9da256e" } ] }, @@ -487,32 +443,20 @@ "statement": "Preparation is separate from streaming, with combined activity guards; stop, global cancellation and mobile background expiration synchronously invalidate preparation identity, cancel and join tracked history/preparation work, and recheck identity after the interrupted save so stale work cannot retire a newer capture.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L88-L228", - "version": "repo-lines-v1:sha256:26af95b584c6f8c1e65cebc40fade84fabaed69fc999ad156818375892763d7e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQxLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJjYjA4ZDM4ZjgxOTRlMTEyMGIyOTYzN2Q4MmZhM2QzNzc3MTk5ODlhNWQwODc4MWI5ZTQyY2I4NjgwNDYyZTczIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlOGVhZjNlMWRiMjg0ZjZhNmZkNGUwNjZhZTJmYjY1NGFlNjhmZGZjZjNlN2U0ZGNhNGMyZGQyMTRhNDliOWQwIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI0MTUxMDgxNzdlYjA0YjhkYjk2YTZiNGFhNGEzNzE2YjAwZGRmNjYxZmNhZDlmODcwOWI3NDdkNmI2MTBlZWM2In0" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift", + "version": "repo-file-v1:sha256:40ea45f2c9460238030ad6c00ed2f9ac58ffdfbefbe7500d752238d97379a217" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L684-L760", - "version": "repo-lines-v1:sha256:7a08479880142384554fef4c4143ed597856d65be0c552a76400a967ada09df3:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxMGEwMjJhZTMxNzI3ZmIzMmUxNTFiMmY3NzA0ZmE4ODVkYTZjZTc0NTdhMjU1OTNiMWIxY2M3YTA3ZGY5NjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI5YWI2ZThkYTBmYzkwMDY0YjdjNGEzNTI3YTVlNWFiZDI1NWI2YjBmZTE3NTc5YWFiNDI1Nzg1YjA2NmZmNDUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdiZTFlNjJiNzdiZmE0MWYyZjNjYzlhMDU1MDI1MzY4MWI3Y2VhN2M2ZDZhMTk5MzljYjVkNTEyMGFjNTI4M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBkOTk4NGRkMWE0Y2M1Y2ZlMTkyYzE1NzRkZWMzYTk1MmFmZDgyMWVjNzZjMGJmZTAxM2Y3OWMzNjJmODlkODIifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L69-L83", - "version": "repo-lines-v1:sha256:0d5f7cf554fd4cb9799565481fd35f87cf6deabc07509813f9f40d913426acea:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY3MzJiN2I3NTFlYmQ1MmM4OWQxOGYwNzU4M2EwYjQ1MDY4OWNlMjkyYTIyNzJmNDVlNGZkNTY5ZGZhYjg1YmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImExMjMyNjI1MGIyOGY3Yzg0NmRmODVkODZhMWM1MmM1MjBhNjM1Y2Y5ZGIzMTY3MjFhNTE1MDdjY2E2NjE4NGYifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1872-L1905", - "version": "repo-lines-v1:sha256:6a975f7fa61da5d616fc6f10e1f9423d2116389da4c055f19e477ed0fc6ab95f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFkNDg1YmY3ZTFmMTQ5NDczNzFiZDY3NGZiMzAzMTJmNmNhOGU2YjU1MThjOTliNGI1YzRhMmE1NWYyOGI2OGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0YzBjNjJkMDZjYTNlYmQ3NDRjZGU2YmE0M2M5Njc2ZmIwYzQ2ZjdmZmNhZDZkNzRjZTFjN2M5NGNjYmI4YWYifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1956-L2000", - "version": "repo-lines-v1:sha256:def37b6b9d6634fc8205db0d3ab3eb671124b0e95c4e482e65b1b0ec66ce731a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmZmM0MzNjZDM1OTM3MTAxZjgyZTM2MzI0MGZiMDkzMWJlMjZkYTcwYjg1MjRlMDEwYjVjMzlkNzdkNWYyNjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVkYjZjMmYzYTBiZWM4ZmU1ZTRlYjY3M2NlODAwMmMwODM0YWJiYTU1ZDM2MjhkOTMzNzUxYzA3MmUwYTc4NGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNmNGE5Mjc1NzY2ZjZmOWRlODJkNTdmOTM5ZDg3YTk5ZDhhYmNjYWYxMWI1ZTczNDhiOTA2M2FkZmM5YmFiYWMifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L843-L848", - "version": "repo-lines-v1:sha256:69c8d0eebc87d56ae3c9b142d02d0db22d37583c5461baed4ef0bcc384c91037:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjIzNTI1YTY4OWNjZTMxOGNjNWYyYmRmNzM5YmEzY2JhN2UzZjk3MDlkZGJjMmM0ZDVmZTU2M2RhZmMxNDcwZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZjE5YjZmYmIyYWMxYzk2NmFiYjNiNDcyYzQzYjI5NmEwN2JiOTU3ZDY0OWY0NTU2MDYzMzVjY2M3MDE3OTUzZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmFiMWFiMzA0Mzk4NjMzMmYyMWM2MTUyNWUyNjI4YzE2NGU1ZWRlMzYwMzhjNGMxYmM0MjgyYTVkMGZmMGFkNiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNmFlNWQ4OWJmZGUxNzU1ZTZmMDE4MTkzYzdlYzQ1YzMzZDkwNTgyOTI3MWIzZmI5N2QwYzk4YTUzNzI3NjFmNCJ9" - }, - { - "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift#L141-L153", - "version": "repo-lines-v1:sha256:a447b5e91a0ff06e0586ba98bce9ea20c40d2acd56bae2b931f831e2e81f8b7c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU2ZjMxZTAyNWIyZDQ2MGNjNGNjZGY5NTdkNjkzMGM4MTRiM2JlZGRlZGQ5MDVjMjNkOTg1MGIxMTNmNTFiMDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2NTdhYTY2MTFhOTk2ZTA3NjllNjNiN2VhYjJmMzIzYTEwZTA3YTAxMmViYjk1MTBjYTdhMTE4M2U1MzQ4ZDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzNjFmYmU2YTJkNzg3MDAzYjc5NDliMDY4NTFjOGJlNDczNTI3MDNiZjAwYmZkYjM5YTVlZmEwZDAxYTdkNmQifQ" + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift", + "version": "repo-file-v1:sha256:8a9a00fed4426631856719583ac4fe07542c1b12d159913a3936b39342dcee8e" } ] }, @@ -548,27 +492,15 @@ }, { "id": "claim_c32cd0e1ce114b36bb3a375a2f210902", - "statement": "Preparation cancellation does not guarantee durability across the separate queued-runtime handoff: ConversationModel.start defers AgentRuntime.start to its event task, and immediate stop can cancel that task before runtime snapshot persistence begins; the immediate-stop operations test checks model calls, not persistence.", + "statement": "ConversationModel owns a queued runtime before starting its event consumer; stopping while queued constructs a cancelled snapshot from the captured request, saves it in a separate task, and stopAndWait joins that save via the consumer, without needing a running snapshot or model call. Presentation can cancel before save completes and queued-save errors are swallowed.", "evidence": [ { - "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L123-L136", - "version": "repo-lines-v1:sha256:4d5a3a936c8b5150faef581457b3b776c9d18f4efe621f40a45a72c60ef2a59a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI3MGM4YmE2NzBjNmVkZmMzYjk4N2VhOTcyODM5OGY5ZDI5MTQ1NTUzODA1ZDQwZDVjZGNmZGE1YTk1ODk2MWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjYzFjNmE0OTAwMzg1NzI5Mzc4YTYwZDdhNWJjMjU2MDdhZGMzMDBjNDFlYjg1NTBlYmQ0MjYyMDdiYmViNWYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQxZmIwZDU5NGEyZGZmNmM5M2FlMmNkNDZkMjg0MGJhZTRkOWFlOTJlM2JkNzMwNGQ0YzYxMjY2OTQwOWRhYWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIzYzg1YTk5NjdhZTQwM2JlODJjYTg1Nzg2NTUxMTVlYTkzNjIxZDRkM2I1MTVkODcxYTljNTc1MGU2NjczMDMifQ" + "resource": "repo://FrameworkTests/AssistantConversationOperationsTests.swift", + "version": "repo-file-v1:sha256:c8c60326b63af7ffe172997d099fdce4259f5b89b94be163f2e95bce2827eea8" }, { - "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift#L220-L226", - "version": "repo-lines-v1:sha256:cc952d0f1cbf33f306da48d33bcf8bf2242b55cfca2867498da7ce2a4f243d56:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYjU3NDBkMDVhYjczOTc0NDVlYWU1ZWRhYWY5YTVjODk4NDQwMDk0NzUyYjRkY2Q3ZjI4MjFmNTQ2ZTliNTNjNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzllZjY4ZTg0MTUzNDc2MTZmMDcwYTU2MjhjYWQ0MmYzMDZmNTRjNjE4MjA0OGU2YmU1ZDgyNjI4YzZhYjU1YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYjMxZWUwZWMyMTRhNDZmZTcyZmQzNWNjOTEzODUxNjVkODAwNGIzNzc4MDI1NDRmOWIwODY5MzE1MTQ5MmU3MiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTE2ZTU4Y2JiMDlkYmM1NTdlMTAwOGU2M2U2YTU3NjU3N2Y0MTFiYWM5NmRlMmFhYjVhODJhYzcyNzNlMzUzYyJ9" - }, - { - "resource": "repo://FrameworkTests/AssistantConversationOperationsTests.swift#L205-L220", - "version": "repo-lines-v1:sha256:774f5d0ae6842b8664276641f46b6f253e19709bd44872b96739c6326b567f6b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY3ZmIyNGM5NGIzYjY1ZDg2Y2I5MmE2YmI3NGNhZjg3OTA1Y2U1OThjZDMwOGUxYTg0ZWQ1Y2ExMDU1MDdiYWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJjYWRiMjlmOGU4MGU2MDkwOGNiNTczMGFhZmVkYmIwNjI1MzkxOTYyMjYyMWVmNDI4MDM5ZDQ3MTc1ODU4NTAifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1907-L1935", - "version": "repo-lines-v1:sha256:29086746228df689c5ee73c74a8f470141cf46d41005fdc2804d4ee9d81f9759:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVlY2VjZjZjNTcwM2QwMzM4NThjMTkzNjQyMTc5NGFhNmExYzY1MjAyMWM1ZjQzNTI4YTk1MTlkMDE3NzliYzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAzYjU4ZTRmZmFjNDQ4ZTc3NTVkYTFlNTM3ZjU5ODgxMWFjYzY1MTAyODBjMmUyMjA1YTk5M2JhNjI2MWEwOWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRiOWM2YjNmMTRkNjAwZjcxY2Y5YzBmZDdkOThiMTljZjQ1MzMxOWYzYWQyMzFhMmIxNDA4YjRjZmQ2NTNjNDkifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1956-L2000", - "version": "repo-lines-v1:sha256:def37b6b9d6634fc8205db0d3ab3eb671124b0e95c4e482e65b1b0ec66ce731a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmZmM0MzNjZDM1OTM3MTAxZjgyZTM2MzI0MGZiMDkzMWJlMjZkYTcwYjg1MjRlMDEwYjVjMzlkNzdkNWYyNjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVkYjZjMmYzYTBiZWM4ZmU1ZTRlYjY3M2NlODAwMmMwODM0YWJiYTU1ZDM2MjhkOTMzNzUxYzA3MmUwYTc4NGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNmNGE5Mjc1NzY2ZjZmOWRlODJkNTdmOTM5ZDg3YTk5ZDhhYmNjYWYxMWI1ZTczNDhiOTA2M2FkZmM5YmFiYWMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" } ] }, @@ -577,20 +509,20 @@ "statement": "Implementing a pending plan captures a new acting submission with planContract cleared before resolving the plan, folds composer attachments and armed skill once, and leaves the pending plan and composer payloads untouched when refused.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L324-L370", - "version": "repo-lines-v1:sha256:ad9eaf7b1dc87c1e840daa96a98450465bda4c91dc8e5fb16f1c3d665084f121:eyJzZWxlY3RlZExpbmVDb3VudCI6NDcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzYzdiMTYwOTA4ZTYxYWIxZThjNTM0ZTY4ZjU2Mjk0OTc0ZDNiYzI5M2EyZGFlNmU2OGY2NjJiMmU2ZWMyNjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlmOGIzMTVhNmQ3Y2JlZGQzOGVlZmUzMjBiZmRhZjdjMDI2ZGQ4YWRlMGNlNGE1NWY0OTExMjZiODA5YmJiNDYifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift", + "version": "repo-file-v1:sha256:40ea45f2c9460238030ad6c00ed2f9ac58ffdfbefbe7500d752238d97379a217" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L185-L213", - "version": "repo-lines-v1:sha256:a30ec2eddcb339c146e32da1428a8f2381c02b6515aadcf05f27b41d4b6410bf:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU0NWZhOWExYTg0YWM0MzAwODViZTIxMDNkZmRlMTA5OTQ5ZTQ4OGY0NjA3YzRmYjM1ZWQ4Yjc2MjUyOTAwYzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3YzRmZjVmY2EyMGUzODk0Zjc3ZmY2NDk0Y2FmNmVkZDU2NzFiZjE3N2YyMmVmMDE3NDBlNzNhMTYwMTc3OWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVmM2MyYmU5Yzg4ODZjMmM1YzI4MjYzOTk4MTBmZTYyMDY0YWZhZWEyN2RmMTNmNzQ5OGI4M2QyMmVlODBjODkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkM2NkNTgwOGZiNWY1MTI3NWEyY2IzNTQ3ZDcxYWJhZjJmYmYyMjlkYzFkNTkxOGU5MjNlYzNkN2FhNTRhY2QifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L1613-L1632", - "version": "repo-lines-v1:sha256:1bb7fc88e5f9e73eeaea78d36f1655d94dba673f8fe9bf6b08652e7e18fd45a5:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUyNjc3YmY3OTBlMWIzMDZhMTY1MWNlOGJjMTliM2JjYmU5NGQ3NDk4MjlhYThiNDcwNGZjYjRjYjkyYTc4MTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlkNmE1NzQxNTViMDMyNWQ5ZTA3YzA5MmNhMWJhNDAwMDBhYWNmN2FlYzMzZmNkOTMwZTA2NDg2YjVjYjY5YTEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5NzkxODQ1NWVkODQyNThjMThkMDBmYmM2OTkwNGYyZWNkNWJjMmFlODVlMTY4MjlmYzY4YWEzNDhmZTI0YzMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" }, { - "resource": "repo://TFITests/MobileAssistantTests.swift#L215-L240", - "version": "repo-lines-v1:sha256:198760cf2a134c8b7734e21e1666526e81539cda162f86a0c718c9af531b0643:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjMjY5OTU5MDM0ZmNmMTk1NzhiYTA5MTVkMTUyNTUzNzQ0Y2FjMTQ4NTIyM2M2YzI3MDY1ZTc4NzRhMzYwZDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImViMmY3NTYyYjc4YzhiNGIxMTdjZDY1ZDFlZTg4NmQzN2E4NGQyYTA1Yzg1YzY0MzA4Yzk4MmFiYzU4M2JlMDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJmZWEwZWQ4NzRhMWQyZmU0MmUxZmUwOTBkNGYwOTFjOTdlMGYwYzRjZjJmZDdhNDFkNTg5Y2ZlZWVjMzVhMWUifQ" + "resource": "repo://TFITests/MobileAssistantTests.swift", + "version": "repo-file-v1:sha256:5ecfc54b7addd6380a9d6c18571dc487085f2b995cbc5ab1ed3ef190f571fd08" } ] }, @@ -629,42 +561,30 @@ "statement": "A missing model or credential at capture stays a failed submission even if configuration is supplied during preparation.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L66-L85", - "version": "repo-lines-v1:sha256:80d25cc0451a928bc50f91e07a28b411b83c0d7299889938c179b8d5e96fb33b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY1OGZlNzcyYzJiNDExMGEyYzJhOWQxYTk5MjI3OGY4ZTNmZDg5YzMzNzJlZjZmYjE0Y2NjYmU1NDU3MmQyMWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZkMzMwZjllZDlkNjUwYTVhMDRlNTk4Y2YxNmE2NmZkOTM3NWZjYWIxMzhkMmJiNmE0MWYxNTJjYzRjMjExNDQifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift", + "version": "repo-file-v1:sha256:40ea45f2c9460238030ad6c00ed2f9ac58ffdfbefbe7500d752238d97379a217" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L348-L379", - "version": "repo-lines-v1:sha256:6eaf43bb757978c5badc8b8bc08b8d551439733c979c24ef1a948607211463ce:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNmE0YjUxN2VkYTk2ZmVhODI1MDU2NzdjMGJlNmY0NTYzM2E1NTVjNzg3MTM4OTkxOTcxN2M4YWY2ZTY3MzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk3MWE2YmMwYjNlZDNlZmEzMmI4NjkzYmQxYTljOTg4NjZhYjU5YjM1NjlmMTMxYmNjOWU1YjBkNDE1MGJkYzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRiYTg0YTA3Nzk4ZjI3OTg2OWI0MzVlN2JkZTYyZmRjODZkNGFmOTM3MmRhNzIyZjk1YzYyNjlhMmFiOTAzZTcifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L523-L525", - "version": "repo-lines-v1:sha256:3cad3b5cb26d6fd2806c7989d5cd8b766f0080b717490e9a6998983f8650f32b:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNDcwYjdhMjk5OTAzODQzNTQ2ZDM5YmFkZDg5NzQ4YmNjMTUzZTQ0NmZkZWY5OGQwZWQ1ZGZmZWI3MWZlMjYwZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjFiNmJkZjk5Njg4ZWIwNmJkNWI1YjVhOGI4ZDZhODg2NzExYjVkMzY2YTY2Mjg1YWQ2YjAwOTU1YjRlZmQ1MSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiM2RkZmFhMDUwMzQ3NzIxMThiMjE4ZWU1MWZjZjMyN2U5ZGMwYjUwNTRjYjE5OGFmOTcwMGI4MzM5YTJhZTkzNSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTEzM2Q3NzZkZWFkNDA1ZTEyOTNiZWRiMzdkZGRmMmFjNDA0OTJhNGE1NDRjYjhjZTQxZDQ4Y2JhMmQ3ZTBlMyJ9" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" } ] }, { "id": "claim_1b7003b57ebd41dfbc14412d029a7f28", - "statement": "New submissions capture memory-session eligibility before preparation; later enabling does not add a session to the turn, while disabling revokes existing contexts and rejects late loads from the prior generation.", + "statement": "New submissions capture memory-session eligibility before preparation; enabling later does not add a session, while disabling revokes existing contexts and rejects late snapshot loads from the prior generation, so captured eligibility does not ensure availability.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L395-L428", - "version": "repo-lines-v1:sha256:a08af3f8158f08c746947fff72a037f53c6abcef3acc5a298d04c24e3a817d93:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFmODg2Mjk4OTI2YzJmYTAwODkxNDQ4MzdhZjIyYzFmOThlNWRiNTlhZDJiNDI3MDFlMWY4OWYwOTZlNjNiZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFkZWFjMjgxZjBmYTk0OTMzODI3YzJlYzFlNGFmMThiZTk0Yjk0NjRmMzMyNDIyYzUxMzNiZDNmYThkODg0YmMifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift", + "version": "repo-file-v1:sha256:40ea45f2c9460238030ad6c00ed2f9ac58ffdfbefbe7500d752238d97379a217" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L611-L619", - "version": "repo-lines-v1:sha256:04ba197fac5b56c77ec0c0f30bbd76411d9455f58e9d396d84d2b36c9e6967c8:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzFmOWYwZmE1Mjg2ZTNjNWNjODQyMGM4OTlhNDllOWE4MDg5YzdlODFmNDM4MjhkM2ZmODE1YWZkNjhhYmU1NiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZjJhYjU2YWMwYTg2OWJmODA5ZWVlMWJkZGNlMzg4YWYwNzdjOWZiMzY3MjUyMWRjN2ZjOTVlMjA5YTExNzdjYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMDY0NzlmM2RlOGUxNmNkMWJkMjcxMjk5YzlhYTY3MTBiOWFkMjU0Yzk5NTBmNGRiYjZkZjFmMDAyYzYwMjBiMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNzY0ZTM0ZWNiZjkzMjgzZDEzYTVlN2UyNGY0MTAxZTg2NzQ1YzI2NjZjMmNiOGEwNGY3YmE0N2QwM2Y5MTkyMiJ9" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L794-L809", - "version": "repo-lines-v1:sha256:f5bad0e8ec4b31fdac4505332e2c746548c179c72239909f782501aec3db7129:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRjYTA3Y2I3YmYxMDg4OGZkZDFlMmMwMDMzYzI4MDIzMGVkMTRkNjkzNGY0NjFiNTZhNTg3NDllNmRjOTUyNWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjViOGQzYzU0YjEwNzZiYmJmNTcwMmQyMTc3NDA0NmFlZDI3ZmNlYzVhM2JiNzYzNzQ0NjNlN2RlYTEwNGMwMmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcwYmFhMzUxMmU3OGFiOGM2NzBiZWU2NWVlNDQ4MzQ4ZTNjODVkNWZkYTFmM2JmYmYzYWRlMzI3MGIyNDY3MDgifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L52-L76", - "version": "repo-lines-v1:sha256:63ceffb701cb214698f1c57e2105b4dc02d7d20d26ec8b71c4eb50058a6e8aed:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwYzVkNTIyNmFhZThmY2Y0MzhjMzM0OTQ3MWY0M2JlYWU3ZjkzYjAwMTlmOWY3MTIxOWQyMzhhNTY3MWU0YWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmMjE1Y2QxMWU4MjNlM2M0M2IxYWY0OGI2MDBmNDQ1ZTY5MDA4OTZmNmU1MmFlN2U1ZGI3M2FmYjFkNjMwMmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU5NzJkNjIzZGZjOTFjMGU2YzQ4MDU1YzY3NzhlYThmNWUxZGQxOTYyZGNlYmY3YjY1NDQ4M2NlZGUzZGY0OGEifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L98-L116", - "version": "repo-lines-v1:sha256:ae20e9db15b84f07e0787f36390d963dfb0425b2ba7f5a5cec258e46ddc6598f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk5MmZkOWM4MzE1NGM3OTBiNGI3MDUyY2ViZTk3ZWI5ZjVjZjYyNjZhOGFkNGY2ZWMyOGY4NjY5MjU4NWNhMmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFiYzgyYTk3NzE1YzQ3N2I3MzM1MWJkN2M4NGVkYWRjNTdmMTlhM2QzOTIyYjE2NjRjZTlmOGZlNTdkNzU3ODIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRjZmQ4ZjZmYzk3NjQ5MmIzNjQ2MmQ4NmUyNjVhODNkNGRjYzlhN2YwMDViYmZjYmI1NjYwZThkOGM0NmQ1MzkifQ" + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift", + "version": "repo-file-v1:sha256:53303b99278ef87af5bc0365c6546c10de8ea4cc6462f0bc9e1d39ba048515a7" } ] }, @@ -758,23 +678,19 @@ }, { "id": "claim_eb12b2d099c145dba48004e4797b19a7", - "statement": "Live run-started, captured-failure and preparation-interrupted paths adopt the staged replacement's real run provenance and chronology. Cancellation awaits save before adopting after an identity check, whereas missing-model/credential failure projects live before asynchronous save, so the end of preparation is not a durability barrier.", + "statement": "Live run-started, successfully saved captured-failure and preparation-interrupted paths adopt a staged edit's real run provenance and chronology; queued prestart cancellation also projects adoption. Preparation interruption saves before adoption and checks identity, while captured missing-model/credential failure keeps preparation owned until its save finishes, adopting only on success and leaving staging intact on failure.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L476-L534", - "version": "repo-lines-v1:sha256:435b7b43d6dfe28c7d197656e31af82f72b308168427674bccfeb12777d04735:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYwZWU0MDJjOGFkMzY5M2YwZjFjNzY1MzZlZTk5OTVmZWMxYjkzNTBkNzU5YTVkOGUyMDY0YmRhYjRlN2Y1MzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk1NTUyNmNmOWEwOGQ4Yzc1ZTA5ZThhMWZhMTIwODkxZmQ3MWEwMDNhMjkwY2U5ZTEzY2YwOWQ5NjRmYjkxYWUifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift", + "version": "repo-file-v1:sha256:40ea45f2c9460238030ad6c00ed2f9ac58ffdfbefbe7500d752238d97379a217" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L719-L793", - "version": "repo-lines-v1:sha256:81156ef97d808d87d63a184f6020940cf4a5bbbdecd8dc55a2d3a3c7e7b0b60c:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2YjhlMjRkZDNlZmY5YzY3YTZiNzg3ZWMwMjA3ZmMxZTI0ZGMxZTcwZmRlZWViNmFjOTljOGFkNjA1Yzk3YmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2ODhmNzU3ODA1NDczNjk2N2U4NzY5MmJiYTg2YjI4MDhmMzI0MTk3NTQ0MDVlYmZkNmM0NWI3MTk4OWQ0NzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRhNzdhMDY4Y2ZiMmUwMWRiMDJlMTAyZDRiODhhOWMzYWRlOTU3YTNhMWMzYjczOGE3ZTBjMWNmMTc5MTUwMjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRjNmM3Y2RjOGM0ZWMwYmM5ZGU4ZTY5MThmYWUwYWE5ODQ0MTJiNDJjZTVjMzY5ZWExZTMzMjg0N2Y4ZjIyOWIifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift", + "version": "repo-file-v1:sha256:5d0e5c2bd75be53d73649916974145d847e8ffdd944a4f096192052d7a2b8078" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2040-L2092", - "version": "repo-lines-v1:sha256:d1a56a12b39372c0277e40115884e11b8c29d16d3df1e847c7407b89efbd1881:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVkOGQ3MGNkOTIxY2E1NTJmMGEwZWIxMGJhNzc3OWQ2OTk0M2RlZjUwY2NhNjQ5YjIyZTg2MzU3OTgyM2ExM2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3YzRmZjVmY2EyMGUzODk0Zjc3ZmY2NDk0Y2FmNmVkZDU2NzFiZjE3N2YyMmVmMDE3NDBlNzNhMTYwMTc3OWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlhZDUyYWNhNzhkODcxNDMzZjJhNzMzZGJmMDQ3MGNmYTZhNGEwZGQzM2IzY2IwYzgyMTJlODNkYTIxY2ExZmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiNTdmZTYwMTUxZDJlN2IwYWNlZTEzOTJhYzI5OGUxYzBjOGE2OWRiMzlkNWU4OTllYzNkMzdkMTM4Njc3ZjMifQ" - }, - { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2625-L2646", - "version": "repo-lines-v1:sha256:078528287f4cac7401a61342ac1db3154e36f5566407f8bb9332cd63c543e273:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjZWUwZWU1M2M2NjUxODNlOTE0NjU5MDViZWY3ZDQyMTI0ZDRmM2JkYTJkNDg5MzlkNWIwNWQ1Yzc1MzIyODgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNmODMwOTk4YzhiZmMyY2EwMGQ0MGM5NDlmZTgxOTQ5ZmQwZDg4MTg1ZWUzOGNlMDNjMjAzNzg4MDZhZWQ4YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2YzUyZmU0ZTgxMjIzMWU2NGIyMGFmODc0MmI0ZGJjZWNhMjlkMDFjMTVjYzk1NDNjYzc0ZGFhNDAzNjlkZGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJmZGI5NTg3M2IxNmNiMTEwMGJjNGVmMGZmYWFiMzZmODc1Y2EzYmVjODY2MmIwMDA5YzEwY2JlNWE2YWVjNTMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" } ] }, @@ -799,10 +715,186 @@ "version": "repo-lines-v1:sha256:f5fa05397f6c5f103da1b22e51552d54d9f197d9f1cd73b34142a57e11b9d9cd:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYxZjE3YzM4MDE4ZjhkMDliMDEwMWYzMDI4ZTlmZDk1MGJmZWVhMjljYjAzMTkxYWVlNDNlNzBmODU2MTViMTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZhZGUyYTZhM2JkNmI1M2Q1MWI3ZGZjMzk1MjQ2MDBiM2I0ZDQ2OGMzMWM1Y2ZjNWM5MThiNjgyMDExOGY0ZjkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM0Y2FmM2FiYTk4ODdmMWYwNWQ0OTgyM2ViOGQwNWE3YjhhMDkwMzhlNDQxNWE2ZmYzMDg3ZDQxZWRhOTQ2YWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI2ZjkxNzkxMGMyOWI0MDdmMThlZjI1MDJiNmU1NWE5NDc1M2NlYjVhNDIyMzY0NDUwODgyODBiZjg2M2E1YzUifQ" } ] + }, + { + "id": "claim_e5a37af3b7524a02bdde9be5632be193", + "statement": "A submitted user turn separates authoredText used for visible bubble and editing from model-facing text with attachment blocks and an armed skill directive; structured images and context attachments travel with the turn, and pendingPriorMessages excludes the last user turn so the runtime adds it only once.", + "evidence": [ + { + "resource": "repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift", + "version": "repo-file-v1:sha256:dd5e6ea3dd365910d2a30a88da9029bd972a547b511503e9665857da494271c3" + }, + { + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift", + "version": "repo-file-v1:sha256:40ea45f2c9460238030ad6c00ed2f9ac58ffdfbefbe7500d752238d97379a217" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift", + "version": "repo-file-v1:sha256:68355854cdc17712a285fe01fd836c11ddc8321954037db18cbd738e3b5d85de" + } + ] + }, + { + "id": "claim_9a6447324e834e179d7a7576a682c71f", + "statement": "The Xcode project resolves AgentKit from a remote Swift package reference with minimum version 0.14.0, not from the sibling AgentKit checkout used for inspecting runtime contracts.", + "evidence": [ + { + "resource": "repo://Termind.xcodeproj/project.pbxproj#L2852-L2859", + "version": "repo-lines-v1:sha256:444f908545e708b1d395265e4292e5529193fc19d4f609c8b5e06f6d68e13abe:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZDhlMTQzODY5ZWI0MzVjMzZmNTljZTI5N2IxYWYxNzc3NThjMzVhNzFlNzJiMDQ2MTY2ZjkzNTNkODcxM2E3MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMzYwYjg4YTA1ZDViNTM4NDc2MDIyOWJlNjA1NzJmZTYyYjFjMjljZGM1N2VkYjVlNjk1MWRhYTRmZDQ2YzgwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzExMTg1YzI4MDExZTZiNWFiYjU1YzRlOTQ5MjMyMTkwMzE1YWFmNGZhYzU4MzhhMDFjMWZmNTQyMjgwZmFiOSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiN2M5YzA1MzMwYWQ3YTFmNDVhMmI2NDU2MTQ4OGZmY2NjZGY5Yjc3YzZmMDA0ZjBkYzRmNTBiOWRhZWFiYjdmNyJ9" + } + ] + }, + { + "id": "claim_2ed4f993cae84003afa836dcc6177352", + "statement": "ConversationModel serializes user-input requests by creation time, starts a request's timeout only while it is the visible head, and clears drafts on cancellation or timeout; changing question steps does not reset that deadline.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AgentUserInputTests.swift#L550-L635", + "version": "repo-lines-v1:sha256:b053494013fc58511669baa9d5fb076972a83b9c5e82c312c89b75c14f305b99:eyJzZWxlY3RlZExpbmVDb3VudCI6ODYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZhNTQ3YmRhMzJjYTJhZjNlYzYxYTg3ZGVhOGNkMTU0MTkyNjYyY2JhZjFkNDkzNThkNjFlNDMyMzIxODRkMWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIyZWMwZDNhZTJkZGU2OGU4YjU5YmQ4ODg0NmFhMmVlYWUzYmU1ZWEwNTllM2RkZjc2NThhMzg3MjkzMzY1OTMifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2528-L2539", + "version": "repo-lines-v1:sha256:e89752873cdffa42470a3e8e5f35a41eb1ad3de2e5091d9310ff12ce1c6c34f1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzZWFiNTQxZmUxMzFlYmZlZTMyYWQ1YjBjMDk3MDcyZTYyOWE0NDFlMjkyZDg2NzBkNTA1MGRhNDYxOWJjNWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJhMzVlYmI4ZjliMDUwMTY2MjRjMjYzZTM0ZDRmY2M4MjFiNzMxMzBmYzExM2I4NGRhZDk0YmRmMGU2ZDQwZjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ2ODE3NGJiN2E0NjhiZTAyZTNkOTExYTVhZDNlOGFhNTZiZDA5NDM5MDlhMzM4MGY1N2FmYWMwNTRmZjM1NDEifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2701-L2757", + "version": "repo-lines-v1:sha256:bf16b951021a86c889916c6ab69a11734867d745628cbb970b189c32ad4d97ca:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlkNDYzNTIwN2RjZWU1MzYwODlmYjRlNzBlYjBiMjA3ZGQ1MTA2Nzc0MzdkMzYxYjEwNzYxOGU5OTAzMWVjOWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIyMjkxYjE2NzIxMjcwYTMzN2M3ZmNiYTk4ZTQ1ZGExY2Q5NmZkNjE3ZTljNTM1NTdhODE3ZDE0OGIxNjE2MDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEwZjFkMmE2YjczMWYyMjBkYjJkYWU5YWY4MjQzZTk1NzE5NDNmZmRiNDEyNjNjMzI1MmJhZTdiZTZmZGU4OGYifQ" + } + ] + }, + { + "id": "claim_8fae898df1d6472db063b154cb5390ef", + "statement": "AgentKit user-input tools accept an optional 1–1800 second timeout defaulting to five minutes and validate at most three questions; Termind requires each question to be answered or explicitly skipped to advance, does not allow skipping secrets, and keeps secret answers in a separate cleared draft.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AgentUserInputTests.swift#L17-L100", + "version": "repo-lines-v1:sha256:fc8ba7ef902a01f4e404a73e042a84db3adf075e36caf6445809b66e5e8751de:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI0M2Q2ZDI4MzVlNzI2N2FjYjQ2ODBlYWRjMGNlODcwYWI4MDM5Zjg3NzljY2JhYjgxZWZhZGU1ZDE4NjE4ZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgxZWI3OTFjZjc0NDVkNGRlZWRjN2NmY2JkYTYzOTI4Zjc0NGZmNDE3N2ZlZTA4MTIwMDE0OWI3ZTZiYWI0YmQifQ" + }, + { + "resource": "repo://FrameworkTests/AgentUserInputTests.swift#L200-L213", + "version": "repo-lines-v1:sha256:d0c08e45ef96010507a5f98c0abc0d37d09c3de3184b995e60de6beec3906cd0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIwZDhlODgxOTVmMjU5MjExOGM5MTJlYzdjZjY3MDJiMjkzMTRhN2U3ZmIxYzlmY2NhOTZkMTJkZTFlYjY5MjYifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2542-L2582", + "version": "repo-lines-v1:sha256:73a9fadd27e6313e00dfb2e760c0482e78f6608cffbea2173275fe1261684573:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJjMWRiOGU5ZmVjNDE4OWU5ZjIxN2MxODc2MjUwNWJjMWZlZTZhYTYyOTE0YWM0NTYyMjA2MjMzZDYzYzRhYzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI1MzRjYjRlZmZjNzE2YWM5ZDUwODFhM2EzYjg0ZTBmMTZmNTRhZDVlNWYzNmIyYzM0YmFmMjk2NTg5NThiZTYifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2638-L2690", + "version": "repo-lines-v1:sha256:22f3d589947e66de8e6b6bf87c5b8f2fdc58432f251d0d955b1f04323416fe97:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNkYzZmZTQ1NzM1MmM1OWNkNjc0YmQyNjRmNDY3NzU0ODJlZGZkOWZkOWE2NTc5MzY4MzUxM2FlNjQ4OGZmOGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5MjFkNTY0NTkxMDhlOGRmYjliYWIzMDI0ZjM1MDYzZjA0NWI2NzQ1MGE3YTBkOTU0NTdlZjYxZmU4YTRkYjYifQ" + } + ] + }, + { + "id": "claim_efcc9360fe184e419e692d56a9257eb1", + "statement": "Skipping a user-input question omits it from the interaction response but the model-facing request_user_input result reports the question with a null answer; cancelling or timing out returns a distinct outcome without partial answers.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AgentUserInputTests.swift#L442-L475", + "version": "repo-lines-v1:sha256:c0a3ec3f66ccaecb4079e80ea8eaffdc7ef99bdb3c4324a8e03fd70c07cbc671:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExNGNmN2U1YjVhNWQ3MmJiMDIzYTAxODRjMDM5ZDIwMWQzMGY1ZmEwNTZlZWEwZTNmYTI0Y2NiMzAwNmU4Y2IiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdmMGFlYmYxODIyYjM1NGM2MTMyMDYxMzc0YzU2ZTY0YWUzYzJhMTk0OTBmOTAyZTk0MTk4MDIyNWMwYWNlYzgifQ" + }, + { + "resource": "repo://FrameworkTests/AgentUserInputTests.swift#L536-L568", + "version": "repo-lines-v1:sha256:cfb246dfb0275d99720b4e579e5bb905977c2cc6122e2c7659dc46538fa67c48:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmZTAzMzU1YzdhOTE0Y2ViNDE1OTBmODVhY2Q4OTM1NDcwNTc0NjY0ZWZhZjlkNmU3ZTgzMjI3MTJjNTFjMzgifQ" + }, + { + "resource": "repo://FrameworkTests/AgentUserInputTests.swift#L752-L784", + "version": "repo-lines-v1:sha256:2c64bc886b979dd14796063e246001eee78ada27da547a6c800437adf00218fe:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYyNjA3NTU2MTFiODQ5NzdmYmJlMWVmZDljNzVjM2ZkZDEyZTVmYjU2OTZiMTNmNmYxZmY0ZmQwNjM3ZmJhYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY5OTZmZWRkNDYzYmYzMWVjYTk4M2FkNjEzNTBiOTg0NmUzYzNjZmYyODkzYThlOGQ1OGFmOTUxMmFjM2ViMGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU2Yzk2ZjQwMWUwMDM4ODZiMTAwZjM0YTg4MDdhNjg0MDE2MzU1YjBmOTc4ZWE2ZDFjNDZlYzU0YmQ1MzAwOWUifQ" + } + ] + }, + { + "id": "claim_56a9b9f295694e6289580ef6ed03bdf6", + "statement": "ConversationModel queues manual approvals by creation time and only accepts an answer for the head; direct approval stages a tool card before channel events drain, and late approval notifications do not overwrite terminal denials.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AssistantTranscriptPresentationTests.swift#L127-L164", + "version": "repo-lines-v1:sha256:38fe1e9a61e603b506dc1a1e4e88f70fa344aa0fac39b7fa9e62678158e05fad:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZjNzU4ZTRlNjEyZDFiZmRjZDJlYWYyYzUyNGZhNzk3MmQyZjZmYTYyZTY2NjQ5ZDAzOGZhYjQwNmQzMjUzZjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdlMDNmOTA3OWQ3NTcxMDI4OGEzYTNhZmEwNjc5ZWJmYTAzMTQxMjQ4Y2FhOThiZGRkYzQwYzZkMjc4NGZkYTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY1YWRmODQ1NmU2ZGY4MTAxMWQ4YmIxZTg2ZWMwMmY0YTNlMThiNzQ4MjBiZDg4OTQ2M2RlNjQ5ZTE4ZTA0ODAifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2374-L2435", + "version": "repo-lines-v1:sha256:77668d68a961f9ab30b548321f29c83d849c528027934cf8a78e687f48e34bb4:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc0NzRjZjQyMmE2ODUzOGNmNDI2MDdkYjViMDRiMzIwNmNlNGU4MWM2ZmRjMjM1NTc2YmZiM2U2MGNiYzBhZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZkYmEyNTM5NGIyNjJlOTYxOThlNWI3Mjc0ZDVmZGJiZjQxMmIxZWQxOWI1NmVjMTAxYTE4Yjk0MDkyY2ZhMzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY3YmFiNWY4ODhhMmUyYTg0ZjgxNmYyNjYyZGVkNmFkNTdkMjkyZDc0NTA2MmM4NDMyYjZmOTljZDkyMzQ1ZTkifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L3000-L3007", + "version": "repo-lines-v1:sha256:123b759b0fbc80688ec4cfb0b8a1e4785aac7544f5e56e57a1986a2a2d8a999d:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNmYyNzNkNmQxZDVkOWZiODdiOWE4NTkzNzQ4NDI5Nzg1Y2Y4NmJlZGY2MjI4ZTY2YmZmMGU5ZGUzNmI0NjE2ZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTUyMmM0MmNkMTljNmQwM2Q4MDhjNDUyNzIwNTUyODI1YjdlYTFjNWI0OTFiMjE4NTExY2FjNzQxNWNmOWQ5YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNTFkNTFhZjJhNmNkMjUxOWMzOGJlNGU4ZGU3ZmFlZGViMzA2ZDVjNzk3NDFkYzIzYjJlYzNiYjg1ZWZhNmU5YiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiM2YzNzAwYWRjZGMwMjkyZGVlYjA1ZmUyNzEyN2Y3MWYwNjg4ZWM2MGE3YjNlZDA2Y2M5YWIwNGFjODAzOTE3ZSJ9" + } + ] + }, + { + "id": "claim_b13dacae7f2f40f38238d00735614941", + "statement": "Live approval presentation uses unredacted in-memory arguments for the user to review without appending that projection to durable cards or model transcript; normal tool detail presentation instead projects structured built-in JSON through presenters with a generic fallback, while MCP output retains its remote JSON form.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L283-L340", + "version": "repo-lines-v1:sha256:5e56d25a1e8069fbae6e7beee9d1dc6a247e7faab8ed0932bbf40a3e421d8a9d:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIzZTEyMGRlODYzNWZlY2VkNWMxYTA4YTc2YzAzODhhNjAyYzRlNWViZDYyNWU5NGVmYTNjZjk4M2QwODRkM2QiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ4ZjUyMWRiYzdkNDdlMDdjOWJhYzQ3OTA1YjA2M2U3NTE0YThhZTU5NDYxZWJlMmZiMmYxZDRlYmE3MWViMjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY4YWNlOWI3NWYyZWQ5ZTRiMDk4NTZlNGJjYjFhMDJiMzVjNzY1MzRjNzhiZjM0MjZlYjllYWQxNWM2YmUyYTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZmM2ZiNTg1NmE1ZDNhOTVjOWI2MDk2OWQ3ZmE0YTJkMTZmMGFkMmM2OTg0MjAwOGI5NDBhODEzZDA4YjdiZWIifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L31-L56", + "version": "repo-lines-v1:sha256:f3371795f66380cfe85f58101e64fd10829766f329547b3e37e7f2a2759aa7cb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2M2U0NDQxODAyNzNiNmE0NmQ1ZTFmMDY4OWMxNGVhNWVkODE3M2RhNTRkZDdjNjk4ZThlOTc4NDBmNDkxM2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE4NDYxZTE0OWUzMGJkZTI3N2ExZmRjN2E4M2IyZTQ2NmQzZmRjMTZjZTcxZGIyNTE1ZTZkNGRkNTU3ODk4NGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5YjMxZmE4YTM3OTdhNDY4MTZiMzU3YWUxOGFhN2ExZWJmNDQ5MjY2MGY4ZmU4NzA3Y2U4MDBlZTMwZTY1MjgifQ" + } + ] + }, + { + "id": "claim_52cb1f85ed3443748ee9169225c4ef91", + "statement": "Tool presentation groups summaries by qualified tool, terminal state and knowledge action so mixed failures are not shown as successes, and bounds displayed output previews to 8192 characters and 120 lines while preserving full transformed output for copying.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AssistantTranscriptPresentationTests.swift#L112-L125", + "version": "repo-lines-v1:sha256:8f92b27419a2874c9307bfc8ae8af05227ae92d294bd3ab9f51bad119d7619f9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlmZDA3NDBhYjE0M2ZiNWE2MzUyZWRiZDE3NTYzMzYzMWUxNjYxNzIzMWFlYjU1YmJiZjBjZGFmZmUyNjM5Y2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY1ZjhmYzQ1OWY4NzYxMWJmMDZjYTNhZTE4N2U5MzgwNTM5NGNlODBlOTQ1ZDM3YmExNTE5MTU0NTYwZDE2NmEifQ" + }, + { + "resource": "repo://FrameworkTests/AssistantTranscriptPresentationTests.swift#L166-L182", + "version": "repo-lines-v1:sha256:d7cdde9ffa85322d661132846d2fe8915ce6410018a4c97020d81540325bb79c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiNmE3OGU1NGU4YTZhMDI1NGNkNDk4NTQ0ZDEyMjIwZjk1YjYwYjY5YzQxNjhiNTQ5MGUxZmNmM2U0ODM2YjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBmYThkOWVjMTA4YTA4YTMwYjQ3NjAxMTg0ZTIxYzUzOTNlOTAyNjNkODRmOWY2Y2Q3MTJjMmI1ZWZhZDc3YWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM4YWJiYWQzYjdhYWJjM2RkMmRjZDE0NGNjYjI0NDFiNzdmNWE4OTQwMDM4MjMzZjg0NmUxOTExMjIzYTY5MTIifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L12-L20", + "version": "repo-lines-v1:sha256:54c618593559e6b7fc8b3c12aea290fda7f4c4a04f5d0bf4834330859848beac:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNTZmMTRhZjJkNzZmZmFkZDlkNDVmNzkwNWI3N2MyMTQzZjkxYzYzYTFjOGQ0NDQyMTM2MjM3YTQwZDI4OGUwOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMGE0YTc1MjExODFhYWQzODM2MDNjNzE3MjIyYThjNzUyODk3ZTI0ZjhlYjEwZGRjODhlNzY1NTY0MTJjMjY2NCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDlhYzY4NjAwMGMyOGEzYzhjMDM3YmVjZWM2N2EzZGU1NzM4MDU4ZmMwZWEzOTg3NzYxZjY4YTViMmFhNzExZCJ9" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L229-L264", + "version": "repo-lines-v1:sha256:a68c35194fc0e7827843f64afff8a8ce5459352bd185eefecf29784e24136545:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJhNjVmNWY1MmNiY2Y0Y2E0MDgwOTVlMTQ5MDY5YzgwNjUyZGY2MDkxNzJhMDc3NTVkNGMwODE4MTVhYjU5MWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE1ZTJjNWRlZjlhYWUxYzk2MWRlNWVlNTY2ZjIyNmFiYjFkOTRkOTY4NTFhN2RiMDA0NzI5OGU0YzZkN2IyMzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjYyNDMyNDZjZjI4NDUzNGUyZDlhMjkyYjA5MzBhOTYxODAwZTU0MTFjZThiZDNlYjk0NDc1NGRkZDZjNjA0NDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAwMWQ0NmYzN2NlOGVhNjUzNjdkOTM3MDdhZDIwOTI2NmUyMmRhYWE4ZjcxNjI1ZTMzN2QxOTBiNjQ4NjU4NTQifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift#L343-L400", + "version": "repo-lines-v1:sha256:22a57ee8264d0d99fa0a45fd797535de26c96dfbc092bf9b9114749dba0bba9f:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJjZDYyOGM2ODYxOWY0ZWYzNmE1YmI1ODU0OWMyOGRkNmY3NzlkZGI2ZmUxNDY0YTdjMDY2OGNmMzkxZDE2MDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImFkNGI4ZDEwYWM1YjQ1ZmUwMjUzNjQyODVmYTM1NWZjN2IyYTQ2ZjE1NDA4ZTQwYzYwODVhOGVjZGI3MDk1NTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYyMmY3ZjljNDNmMjFhNzk0MDI2NjQzMmVmN2YwODBmNTA3MjI3ZWI0NDJhNWJiNTAyYWUxNzQ3ZTZhZDdlMzEifQ" + } + ] + }, + { + "id": "claim_21839365d98e4ad6ae8ea000051bf327", + "statement": "Mobile app backgrounding suspends Hermes memory, and background expiration separately cancels pending Assistant preparations and active runs before draining run work and closing host connections; desktop termination also suspends Hermes memory.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L647-L663", + "version": "repo-lines-v1:sha256:be3d7ace4663375024627ad072542aab75a2ee635ebaf20ee80f0a63f51e0d0d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZDY0ZTIzNWJjNzZlYTM1MDI3NmE4MGZlMGM1NjM0ZTYwZDFkZmUwN2FjYWQ4NTJlMTFhMWQ2MjkzM2ViMTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhjYWNjN2E0NzlkMjI5N2FiYTI4NWJlYWFlMThhZmI4ZWE3YmQzODEwMTkxNTA3MTIwYmRhNzVjNjBhYTBhZTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyMWFjNTE4NDc5MWIzNWNkZTM4MDkzNDU1MTVjMGFjMDEwZjA3MGVhZTAyMTRjZGY0MzIwZDE4NzI5N2M3MDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5ZjIwMmJmNzJkZjZiODUwNjM5ZmNjZmRiZjY4ZDJhMDdmZWY0ZjMzYThlZjQ3MWM0OWUwMDEwY2Y0YmRhYWQifQ" + }, + { + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift#L141-L155", + "version": "repo-lines-v1:sha256:0780c8d87faf6cccd18d3e4cd58b9155c4fe4a4baa3a11ca128b29f5be4061f8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU2ZjMxZTAyNWIyZDQ2MGNjNGNjZGY5NTdkNjkzMGM4MTRiM2JlZGRlZGQ5MDVjMjNkOTg1MGIxMTNmNTFiMDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2NTdhYTY2MTFhOTk2ZTA3NjllNjNiN2VhYjJmMzIzYTEwZTA3YTAxMmViYjk1MTBjYTdhMTE4M2U1MzQ4ZDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzNjFmYmU2YTJkNzg3MDAzYjc5NDliMDY4NTFjOGJlNDczNTI3MDNiZjAwYmZkYjM5YTVlZmEwZDAxYTdkNmQifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L745-L766", + "version": "repo-lines-v1:sha256:857daee44a3ff3ba905934c89b3e51232c4ed4e0a6dcefd1fb68cd2a1b0ba829:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc4Y2YxMzBiYzQ5ZmEyZTk4MjVlMzhmNDdmYTJjN2UxNWIyZjFjMTYwMzNmMDM4MTc2YzkyNjM0YzMxMjRmNDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI3ZDcwNjRjNDA1MGRmMjJiOWM0NWMzZDIyZDMwMGVjMTRkNDJlZjZlZjQ3ODMxZmJlMDJjODAzNDU3NzBkOTgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM0MjE0OWM0MGFmNDRiZjAxOWQ5MDBkYzkyOGIzNWEyMThmNTI0NWY0NjllYWY3M2IwZTAzMDgxYjc1MjgzYzMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5OGY2OWM0ZGU2YmEyMjkzMGEwNGUzOWNmZmM5NTFkOTkzMDE1MTc5ZWM3MjM5MWMyMDI0MjNjNTE3MzY0MDcifQ" + } + ] + }, + { + "id": "claim_547bede8d9804a89875e8daab02119d2", + "statement": "Suspending Hermes memory revokes existing sessions and access without deleting stored memory; resume reloads state and schedules history indexing, but an old access handle remains invalid even after resume.", + "evidence": [ + { + "resource": "repo://FrameworkTests/HermesMemoryTests.swift#L116-L155", + "version": "repo-lines-v1:sha256:fbf0ad89f09481ea1d06caafe7c2bdec8f64ba44652eb26db599c9f707c2a332:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3MjA1MzIyZDIyNTY5NmVkODY4OGRlYzk5N2NjNGMyMzZlN2M4ZDVhMDY4ZjBmOGEwNzg0NWJkYzk4NWJhYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFkMmZlMGM5ZTQ2MGJjYjM4YTQ0YzY4YTY2OWNlZWY3NDA4YWExNjcxMmUwMjZlMmFmZGI0Yzk4NTc5YzlmMjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIwMzc4NmU1YTkyNTJmMjA0ZmVhZmM3YjhiOTEyYTgzMjEzZWI0ZjRjMmIyMjM4Mzk3NTM0MDY2YmVkZWIwMDEifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L274-L284", + "version": "repo-lines-v1:sha256:c6bd184fd629fc2765d33f8ae15143e6791863bd814b8356a2ceefdd5dcfe82e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY1NTllZmFkMzI1Mzk5YmFjYjUwOThiZDZkMjAxYzAxMjg0NTI4YjMxZDIwYTAzZDMyNGNjZjlkNjdiMWE5ZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ4MzU0ZmU3NWE1Y2JjM2M1YmJlZWE3ZDU4ZDJlMjBmODAyZmE4MmJjZTllZDk0YTMyYzg5Yzk5MzMzNTFmYmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MjgxMjhkMDk1ODYwMmUyNTRkNmFlNmVhOTBjZjM0NzA0OWYzNjdhMDE3MDEwMjJmNTI4ZGRhNDkzMDU5OTgifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/concepts/commerce-localization-and-product-surfaces.json b/openwiki/.claims/concepts/commerce-localization-and-product-surfaces.json index 6a2fe69f..2bff8948 100644 --- a/openwiki/.claims/concepts/commerce-localization-and-product-surfaces.json +++ b/openwiki/.claims/concepts/commerce-localization-and-product-surfaces.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:bd337640d19689b0a49ced6065a75468c6db642b74b0fa43ef460aff4ebc1cf3", + "pageVersion": "sha256:c9bc2c85241afa99871ff2b9d281f17d45acb8c76ef353b5c20844561140d378", "claims": [ { "id": "claim_70c5c3da992944188e719c65adc9b06c", @@ -233,10 +233,262 @@ "version": "repo-file-v1:sha256:97866af84c8b01df60e0e125b61a85836eaa9156052aeac3c3ddb0c234cad81f" } ] + }, + { + "id": "claim_837e0ba5adf646f3b5788f840548601c", + "statement": "While subscription access is granted, `ProAccessController` schedules an entitlement recheck at expiration or within 60 seconds; both app targets additionally refresh StoreKit access on activation.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L422-L439", + "version": "repo-lines-v1:sha256:54566fe52fb9870a16b613f372aaa4ba69b65a70a12b18768a9a782b9f3fc3e9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkNjZlMzE4NTZlZTEyNThkNmVlOGY3YmZhMTFlYTI2MGY0YTI0NTY5ODcwNWY2NGUxODNjNGJlMDVhNTQxZmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA3MWYzYTI5NWQ1NjE5YjQwMGY5MDkwNWJiYTVhMzg3NmIzYTVlZmJjYWNiMzkxNmNjZmYxYmQ0NWIzZmMxZjAifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L560-L575", + "version": "repo-lines-v1:sha256:fcabea91d2fdb5f05f50a9cd08386114389bf2c5a32d9fcb27c47552ae337b35:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQzZGFiZTIzNDEzOTNjYzU1NWUzZjI0MzRlOTFlZTZjYjVjZTNhYTgwNWEwOWVhNjA2YTY1MDI3YzNlZWUzY2UiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY4ZWY4Mjc0MmI5NzUwODBiMTdhNDZjZjVjMDYzOGM0MmY1ZGYxNjE3NTBjM2U0OTY1MGRhYTc1OTQzNjJmMWIifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L317-L320", + "version": "repo-lines-v1:sha256:1ee408a9a5507918379d16437b19820e165a6ac4f23f4bb06987770b0e8aa179:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNDU5MDRhNmM4Yzk5NmRhZmEwYmM3Mzc4YTJhNDQ4YjM2MTNhODQzNDgzNGYxYjdmMGU5MTMxMzc5MGU0ZmJmOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMGZiMTRiOTAyOWQ0OTg1MmNiYWU1ZDNkMjc3M2I2NTA1NGFjYTU0NWI2NDI5MmZjNWY5MWEyYjU2MGQ5MDU2OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZThmZTBiYmI5NDc2N2JkNzQwZWYwN2NlMDI5NTc3MzZhYTBjNDE2YjMxODIxMTZhOTAwNDhmNTUyOTJhNDg3MCJ9" + } + ] + }, + { + "id": "claim_712f102d74174c1caa103f2bb461ec8c", + "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#L560-L600", + "version": "repo-lines-v1:sha256:9b75da6c368a22be4ea7671f9bee2c752a26e2c6242a6736aaf264cbbaeeec23:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA1NmJiMzc2MzhmOTFkYjA1YTlmNzMzNDYwZTdkZDk3OWI1ZDkzZjk1NDM1ZmRkMWU1ODVkM2VjZTcxOWE1MWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhjYjZjMGI5MTEwNmU0NmYwYTNkNTc5ZmYxN2E2MGM3OTg5OGNiMjdlYmJhYWQwZTE2OWY4ZTg3NDNmMzQ5NTIifQ" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift#L41-L66", + "version": "repo-lines-v1:sha256:768d045bd06100e92eed2837742f40428687f24feb6964bcca513f99f29eef4b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUwNTI0MTczZmExMGJlZTU3OGQ2ZmJhZTBiMGMxNWFlYzNjYmExOTFhZjM1OTczNDU0MTY0Yzc4YThhY2I2ZTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYyYjNhNjBlZjYyMjJkNGZkM2EwNzU4NWQ2NjEyM2Q0YmU3YmVkMTU5Y2I5YzJjMzcxNTJhNzdlNDA1NmNjN2IiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZlNGY3Yjc2ZDBlODI4YjNlZmNjMTE0OTYxMGQ5NDczZWU3NWMzN2RlYTg0NDc3M2VkYmRmMzhmYjZkMjU2M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRhYTA1ZWU2ODZmZjc3MmYxNjNhNTA3YTEwMmZiMTlmMzM0MzVlMjAxZWU1YjZhYzlmMDI0Y2QwYTNjMTRhNDYifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L347-L360", + "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/TermindApp.swift#L103-L106", + "version": "repo-lines-v1:sha256:d7a35235421f01a6dbee1cfc2c3f3947990480cc7da3f8b1eeb7d4eadf443a0b:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDhlNjgyZDk4YTk0YjFlMTg2YTg3Y2Y2NGVmYWUxOWJjMjBjZWM0MDBkNTdlZWNkMjcwZjM0ZTc3OWMyNDliMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODc1YTE5OTFkY2Q5ZWFkYjc1NGE1NGY4NjUzYzllNWFjMzU3ZTI5ZmQyZmU3MGFlODlkZTFkMWEyYTk0MjMyYSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTJhMjBiZDdhZmI2MWE5NzFiMDc4OWQ4Mjc2MjYzMmQxNmEzYjc2ZTkxN2I1MDBiYmM3ZTE0N2ZlZmI5MWE4YiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYWU1ODNlNGYzYmVkNjE2Zjk5MjAyZTU3NzEzNmNkZTdhMzdkOWIwMGFjZTQzOWJmZGUwYWRhNzNlMGMzMTBiNSJ9" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L24-L50", + "version": "repo-lines-v1:sha256:c0fcdf8d21b0f802f826a33abe78870a19d40443c08b8f5640fa5d1e10b247d5:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIzYTI4ZTc0YzkwYzJlOGQ0YWIyYzUyZmI5NGE0NGI0OGY2MDc3YzFjZGU3YzJlZDNkYzljYjkwOTY5YjNiZmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIwMzE5MmFhZThlNmRiM2Y5NzNjMjI2Mjg0MjQ3YzliNjg4MWFjMTUxMjhlMzhkNzdiYzZjMjQ0NzI4ODVmZWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5MGYxODJjOGI0OTgyMDk3OTA2NTZlNmY3YzcyNGVmMTM4YzcxMjBlY2NhMDU4ZDczMmU2ZjU5NTc1ZDQwZWEifQ" + } + ] + }, + { + "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.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L233-L276", + "version": "repo-lines-v1:sha256:f66e990185bf8759d93b651499e5d173859cc340e345e6edba3abbf5715ed941:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJkODA2NTg5YjQ0MDNmNDUzMTEzMDVhZjY5MzQzMGUzMzk3NTE2NWViNDc0NjM0YzA0YmE4YThmNTJkZThiNGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNlZTUwNDAxNGQ1NjFjNDYxYTNmZTgyNzUxNTY1YTI2N2Q1ODIwZTczOWRjZmY3YTVhNDdiMGEyMDJiYjM4MmIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlYmRkM2IwMzE3YzAzODcyNTJiZjc4ZjcwOGU1ZjVlOWQwMWEyOGI0YzE3MjhiNWVlZTM0Nzk3ZDkzYmRiZTYifQ" + }, + { + "resource": "repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift#L32-L47", + "version": "repo-lines-v1:sha256:703045e28f12924d2dc7b05569bdc9b0d47d35be6264aabdd3c835f4113f6f0e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ1YjQ0OTYxYmNlNmI5Y2E5MGRhYjNmNzU5OTM3ZGM2ZTU2YmIyZTkxNmZiNWU4NmJmZjc1ZWY3YzllMzRkZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBjOTkxNTM4NTA2Y2ZmYWNhM2MzZTliYjhjNThkY2Y0NTBjMzFmOGZlN2FiN2ZmZTUwNjk1MTBiNjA0NjMwNDQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ0MTQ4Yzg4MjUxYTUzM2M3MjFmNDYxOTI1YjIzMjNhOWI2N2QxMTcxZDNkY2M0NTBhN2NjYWM5ZTA3YmEzNzIifQ" + }, + { + "resource": "repo://Frameworks/TermindPresentation/ProOfferPresentation.swift#L10-L55", + "version": "repo-lines-v1:sha256:899c660fb5a61583fb1427a0c77b7674254d09aca6aa063583409d537e7a1d1d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVjYjc4YTBhYmU3YWE5YTA1YmY5NDJhYWZhMmQ0Y2Y5NjQ0ZTVlZDc4MjAwYTcyZTYxY2EzMDM1YmU5ZTc2ODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYxOTc0YjQyZmE3YTA0M2Q0Y2Q0NTIxYzg3ODYwMDhkMDM2YWIxNjY3MjkwODUwODYzZDdhNDFjNmRjNTc0NzMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQxMzhhY2VhNDZjMjMzMjEzZjFiZDc5MWEzMWQ5YTFmODMzOWE2N2RmOTIwMjQ0YWYxNjhlMWRlMmI2NzQyMjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3OTRkMDJhODEyMTk0NGQxNzZkMjY1ZTliYjljYzU5ZjZhYjg5MGJjYWRmOGFlZmRlYmRiYmI0ZjJlYTg0NDQifQ" + }, + { + "resource": "repo://TFI/Features/Commerce/MobileProView.swift#L97-L123", + "version": "repo-lines-v1:sha256:f09e3dd33e7d34d5a2f33e09661df8d00f274a5d285fa2b3a6ffef78fddced25:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1N2U2YzM3M2E4NmNiYzcyYmVjNTMzYTNlMjUyZDk5MDQyYmU0ZWMzOTc0NzdhMTg2YTkxOTQ1MzVkOWJiYzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVlZTdmOGE2YTdhYjFlZGQ1ZWE0NTczZWYwM2E4MTk4NmNhZmM0YzBmZTgyODM5NWM5N2VhYzAwZjA2YmRiM2MifQ" + }, + { + "resource": "repo://TFM/Features/Commerce/ProPaywallView.swift#L52-L90", + "version": "repo-lines-v1:sha256:3ba4af54585a578373c1b087486e1df70cd0a464318cf188121413a68b428513:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiYTU2MzIzNTNhZmQyYzk1NDZlODZjNGE0ZjRiNzhlMWNjOThkZjJlN2Y0OWY2OTBjNTQ1M2ZlOWE4NzRjNWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdhNzIwYjc4NDFiMTViNWM3NWZmN2MzZmJhYTBiMDg1NjhhYTUzYjMzNmEzYjUzMjkzMjQ5ZjZiZWZmMmRiMjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYwNThmNmQ1NWJjNWQ5OGMzYWQxMTA3ZTQ4ZmQyMGMwNDdlYTVlZjA1OThjNjYxZWEwZmEzZmE4MDhjMDU5M2QiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE2MTkyOWE2N2QyZWVmNzM1Y2UxYzFmZjQ5MzcxMWY0OThiN2FiYzE5NjI5MTVhNjhhZDI2ZmJlNGM4N2YyMTcifQ" + } + ] + }, + { + "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.", + "evidence": [ + { + "resource": "repo://Frameworks/Resources/Localizable.xcstrings#L4880-L4894", + "version": "repo-lines-v1:sha256:ae374ff3abb4f81ab4bbdd99d2d00beafd5474c4d23499eb6ffc2eb68398e534:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIxMTc0NjExZWI2OGY2MTg0OWYyMGMwZWY3ZjJlYzBjMzhmNThiYTM3YmFlZTdjZjY2ZDA1MWMxNDdjNTE0ZDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg4MDA1ZDU3MTA2YTM2MmViMDAwZGFmM2RhNDY3NGM4MmI1MThmZjVhMmUyZjY3ZWU4ZTc1N2EzMzNjMmFmNjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJkODA0ODIyZGE3ZmE1MTJlNmJiYzJmOTgzYjFhNmQ3NTM1YzMxMGMzMmJkYjg4MmYxYmFkOGQ5NDI2NWE0MmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFlZGIxM2I1Yjg2YjY1ODI3ZDczMDA1ZWZlZjJiOGFhMzVjYWQwZWEwMjU5YzQxYjgyODcyNDNjYzBkYjEyZDIifQ" + }, + { + "resource": "repo://TFMTests/AppLanguageTests.swift#L102-L121", + "version": "repo-lines-v1:sha256:fae989108063e22cf05ff8739ed2a75708aa77e9a3638b94c4c539f908658bcc:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMzZDliM2RlM2MzNjAyMmZlNmI5YmE5NTM4Y2I3ZGVkZGY1NTkzNmEwMTE2Yjg1ZTZhZjA4ODFjNmE0NjA3MjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBjNTEzMGE3ZDBkNzM0Mjk0Mjk0ODhkNmUzZDE2N2ZmMzkyNjE3Y2ZhYTYzZjliMTk2MTUwMDEwYWE2M2MxZjcifQ" + }, + { + "resource": "repo://TFMTests/AppLanguageTests.swift#L136-L161", + "version": "repo-lines-v1:sha256:751ad8bf416d907a0bf5b4b4fecfbf6ae46b94ec1a2caa251ebcffcc1defdc48:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVmNTdiNzcxZmRhMjU1Y2ZkNDE4NTkxNDQxMzhjNWU4NDg1Njc4YmMxZDFhZGMxNjdhZDMyZmE3OTEwM2NhNmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ" + } + ] + }, + { + "id": "claim_f08b1d7d873d4e038880cb8b0fc33df2", + "statement": "StoreKit trial integration tests are manually opted in via `TERMIND_STOREKIT_TESTS=1` and use `SKTestSession` to verify trial and restore behavior, lifetime precedence, pending approval, failed verification, missing introductory offers, invalid annual products, and an empty restore.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L42-L45", + "version": "repo-lines-v1:sha256:62f0e471d906c7900219f000f39fb8ab034dfd8cadaee4b26bc84116b48a8976:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMTczYTI2N2E2ZGNmZTczN2MyODUyYjY2OTkyNTViNWZlMWViYjYzMzVlZmZiYzgwZjA3ZWE0ZWExZTBhNzdlOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMjRlZjRiM2VmMTA0OTMzZWQwM2RlNzdmNjEyNTY1MDc5OTNiMzY2YjY0NjYzMWIzODZjYjVmMmVkNThlZTA1NSJ9" + }, + { + "resource": "repo://TFMTests/StoreKitTrialTests.swift#L14-L175", + "version": "repo-lines-v1:sha256:2bd56e96e0ea4d9824ebefbe29fb4ab1ee4ce34289270e5ec725ebbc4afc043b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJjMTgwMjUwNGYyNWJhM2NkMGI4ZmYxMDBiOTRiZWI1MjZkNWVlMjU0MWMyZDg5MGQ4MWYzYTQ5NjYzYjEyMWMwIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI3NTUyYzk3MTEwYTAzNWYzZGI0NjFiMzNlY2ZkNTMwMDc5OTgzMWViZWI3ZTJhMzk4ZDMyYmNmZjUyZWIxZTVlIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI3YTM1NmNjMGQwZDg1YzZlMGE3N2M0MGU5NDIyNWQ2N2QwNmM2MDhlNmQwZmI5MjI2OGFkNWM2OTA4ZGRkMGY5In0" + }, + { + "resource": "repo://TFMTests/StoreKitTrialTests.swift#L177-L245", + "version": "repo-lines-v1:sha256:37e100d42a523a4a7a4c1c18ff7395b7c73277abf9151e5f4e6795859ca154a7:eyJzZWxlY3RlZExpbmVDb3VudCI6NjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQyOGY3YjBiMjZlNGFjYmE0NTJiYTk4OTYwNWU4MGVjYjI2MTJhMjRiNjJhMzc0ZjE0NWQ0ZWMzODNkYTVlN2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI1OWU1MzhlMTZhYzBmYTBiMzZhMDY5ZjQwZmFlMDliODFhNGFjZGU3OGY4MWY1YWZhNTEyNmY5NDcwNzQ4MGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + } + ] + }, + { + "id": "claim_1ac7683478c24c55b9bc9ec419e712bf", + "statement": "On iOS, Vault and Vault search open Snippets and Known Hosts with optional initial queries; Known Hosts distinguishes empty library from empty search results, offers add from the toolbar and edit/copy-fingerprint/delete per card, and selects add versus edit editor title based on whether the entry already exists.", + "evidence": [ + { + "resource": "repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift#L14-L86", + "version": "repo-lines-v1:sha256:eb63aa1a7b1b6940a0cbc90635756972afe9cfa93891c545fdd63dfc21405ac1:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIyZjZjMmM2NWMyNjM0NDUyZTNiM2Y1MjZhZGY2OGYzY2NlNDU0ZmQ3Yjc3ZjBlOGMxMjQyNWQyOGM2YjRkZDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU2MDdhYjM5N2ViZDE3NzRiY2NmZjJhYjgyZmEyMGFhMzVmYTExNTNiMjE4ZDJiODZiYWJkMzQ5M2ZjZjZjYjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFkZTY3ZmY5NzJiMWUxZDk5Njc0OGE1ZTczYjM2NmY5MzU4NzZiMDE4MGU5NmFlYzI4YWJjM2UyZGVmZGQ1OWMifQ" + }, + { + "resource": "repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift#L89-L115", + "version": "repo-lines-v1:sha256:d1a44a27ac3797ad7fcffda5b84ea41d412fab02a18098a95f6fb13c8f4f0180:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM3OTJkZjUxMDBhY2FmNGJjZWI1YWMxNDljZDI5ODEwYzFhNTc5YmU1OWIxNjIzMWVhMjA0NDgwY2M2Mjg5OTQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwOTNkY2UwMmZhM2U1YzBiOGMxYzg2YWM2N2U4NzYzZTNhMjQ5YWFhZDAxZjlhOGVkZTJkNjcyNzE1MGJkNzgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5ZWNmZTM4ZjNhZTg0NDhkNTg1NTZhZDEyNmQyN2ZjOTUzZDcxM2I1ODRlY2Y1OGQ3NzAxMWNmYzE1N2QxNDYifQ" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L580-L588", + "version": "repo-lines-v1:sha256:5f46640a1644ee65ad1f1cf34d92c291010f3d3e3686c3c6fc942d9de4d44975:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNWQ4NWVkZGVlMjMwMGRkY2MxNjU0YjkzMTc5ZDUzZDRjMTFhNmMxNmFhOGVmYWM3YjFiNzFiYTAwNGFlODkxYiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMmFhMTU5ZDBiMjYyNTI3OGFmODE1M2NkZGI5YTVlMWJmOWY4ZWZmOWNlMGZhMzBjZGNkMTAxOTQ2NDBhMWZjOCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiM2I5MDRkNGQwMTQyMzEwYTYyMzU4MDA1Y2M5NTk2MzM4ZjIxOTk3Y2MxNDQ4ZGIxNGU5NTdjYzlmNzAwM2IwYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNTBmOWQzNWY3MTAxOTgxMTA4YWVjMTg0MDU2YTBkYTE5YWU3N2M1NDA1ZDMyZGJmMTUwODE5ZWU5ODZhOTAyMCJ9" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L636-L652", + "version": "repo-lines-v1:sha256:30dfd942b6f2dcce677637aee4f43978ed7679dbe0396f106be48f5eed004b1a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImViN2FlZjQ3MDkxZDE0ZmY5MTVhZDFmMGM3MGY5MDYyMmE3ZDYwYTk1YzQ2MjFlNDVjZGQ2NzhlY2Q1ZDE1YzgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJmODgyYWVkYTYxNWI3OTQ4OWEyNDNhZjgwY2Q0NzkxYjU2NzViOGY3MTE1YjIyNGJlYjg2MDIxNjIzMTUwYzcifQ" + } + ] + }, + { + "id": "claim_5f8a347dd90c4515a3d176eb1c22cdd8", + "statement": "On macOS, the Known Hosts empty state offers import or manual add; deletion has singular/plural localized confirmation text and warns that deleting trust means verifying the server key on the next connection, while editor labels distinguish adding and editing.", + "evidence": [ + { + "resource": "repo://Frameworks/Resources/Localizable.xcstrings#L8325-L8339", + "version": "repo-lines-v1:sha256:b30193645f18967afc32bbb2dc3133b4d865901edf8c6f708341182649ecfd81:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2ZmY2N2Q0OGI2N2YyYWI0ZWZjY2RmZWMzZjU2N2Q2NzkxZDdhZDNkYmY1NjA1YjQxMGJkYjBiZjk4YTFiNjQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjliNjJmNjBkODU5MGE1NzljZjQ2ZjhkNjczNzhjNGM1NzJiOTYyY2VjY2RiOTBjN2E1ZjdiNDJiOTYwNzgyYTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYyNjIwN2UxOGU0ZTczYmIxZmFiZDUyZTFkZDAyM2E0MGM0YmY2ZTBkNjE4MDZjYzhiYWIwYjcyNmVmZTU4ZDQifQ" + }, + { + "resource": "repo://TFM/Features/KnownHosts/KnownHostsPageView.swift#L189-L213", + "version": "repo-lines-v1:sha256:dd117dbfada691588176c2a6ee440f3424f636b99349917d8c59d9c6be29e9bf:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJiMjRjYjUxYmRmZDdmYjhlM2RiNzJlZjkzY2NiYWU1NWYzZTAxYzMzY2ZiZjNiZjNmMzczNmMyZGU1ODI4NTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUwZGM5ZjIxZmI0Y2NlZGJlNDE4ZTlhNWQ1ZmZlZmI5ODdlYWMzZGEyNTE0NDE2NzFmMTQyMGU5NmNmYjRiZWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFhNTlmYjgzOGViZWJhYmZkOTU4NmMzMTljNzVhYTgyNjhmYmEzM2M2YWU0MWY0YzkyNWY2OTA1MTIwZDA5YmMifQ" + }, + { + "resource": "repo://TFM/Features/KnownHosts/KnownHostsPageView.swift#L243-L248", + "version": "repo-lines-v1:sha256:06c814d48d9c01b1cd4170904b441be3f9a491ac981a87268280015ebc26e195:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZjQ2M2M0ODc1MWI5MzQ3NDUzMjU5Y2ExYjFjMjViYTUyNWViNjdhYTJkZjUzMGRiZjM3NTI0ZmYzNjMxNTMzZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNDJlOTEzMjAwYjAyYTY1NWY0YjJmODk0NDk2ZWUxN2IwMTUyMzYwMjQzYTRjYjk5ZTE1NmI0MGUzMWExZjhiMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMDRjNTgwNTczMmNmMzAwYWI0NmM4YzRkNDBlYzZlMzU2OTAwMmMwODI1ZTEyNzhhZmVmZmNhMjg5ZDIzNDg2MSJ9" + }, + { + "resource": "repo://TFM/Features/KnownHosts/KnownHostsPageView.swift#L72-L100", + "version": "repo-lines-v1:sha256:367f80786d8d99e5269edfef2faf2bf1d55e0f022a710ff27bb7cd6e9aa717a1:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwZWMzNzc0MTEzOWVjOTg2Y2Y0MjMzYjE5MDJkOWU1M2YzNDU1OTI0YTBiY2E5ZTk1MGFiZDFiMjEwMGEyYzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAzYjQyMWI4ZTA2OTJiZTMwYzUyYjQ3ZTJhODAxMzNhYzMwNGFkYzY2MDlmYzM1ZDJkOGRhN2U4MzlkY2JjYzkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI5ODEyN2E5ZjRkMGJiNTQ5MDAzNDI0ZTBlZGQ3MmNkYzQ5ZThhNzY0NjU0N2MzY2VlNjZhOWYxMzU2NGM2M2EifQ" + } + ] + }, + { + "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.", + "evidence": [ + { + "resource": "repo://Frameworks/Resources/Localizable.xcstrings#L16421-L16434", + "version": "repo-lines-v1:sha256:6c40e495346a66850cf16d9f6728aa2b30697fd84d10005cd0eeac4a01bf8539:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgwZWJjYWM1YTliOTE3ZGY2YTgwODk4NDQ2YTljMmU1ZjA3NmZlY2Y5YjNkNzUzYjkwMzhmODczMTE0YzRmYjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU4NzI5MzE0ZmQ4YTM4YmM0NjE2OTExMDkzMDg5NjlhZDY0NjQzMzE0YjJlZDcxZWEzNmQ5MGE3NmNkN2Y4NDQifQ" + }, + { + "resource": "repo://Frameworks/Resources/Localizable.xcstrings#L16454-L16499", + "version": "repo-lines-v1:sha256:b2c36993f1d06bf6c488b1f9ae21c6eea09333828d29121dd249d7728eb48f2f:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI0ODNmODJkZDkyYzE1ZDZkZjUwYzU2NWJlNWU0NWQ1ZGMwMzc3ZGM1ZjRlMDYxOTlhZGQyYjU3NjA5MGVhMjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJiZGU0YzcwMDcxNmJmYjliMmNiY2NiNGFjOTMxMGE1OTk0MmI3Zjg5ODcyMzlmZDA3NWJiYjQ0MTRmMmYyMDMifQ" + }, + { + "resource": "repo://Frameworks/Resources/Localizable.xcstrings#L28997-L29011", + "version": "repo-lines-v1:sha256:7380e8f467909347288c95b4b0428ee86bb44554ab0b381cb57af255d4a7c2da:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkxYjIwYmU0YjA5ZWEwMDI4NWQ4ODBjZWVlYmQ0YTNhODFlZTM5OGVjNmNkNjI3NDliMjA0YjQxMWQ4Y2E2YjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjliNjJmNjBkODU5MGE1NzljZjQ2ZjhkNjczNzhjNGM1NzJiOTYyY2VjY2RiOTBjN2E1ZjdiNDJiOTYwNzgyYTQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg0NmVkNmFjZjVmNjkxZGFlZGJmMTc2ZDMyZTAyZjhiNTIyNjgxZmYxN2M5ZDY3MDk4MzY1YTMxNzUyNmY1NjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2YzkxOWZmNGY2OTk1OGVjOWMxOGI0NjE3ZTAxYmFhMDg3NDhkOTRjZjkxMTI1ZmZmOGMyOGE4YWQzMDViMmMifQ" + }, + { + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L141-L155", + "version": "repo-lines-v1:sha256:2e52362dcab9a2f7b6a44b0fc9291918703c3409cc2e6e2e391dcd47490a860b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZiYTYzZDkzNmVmZmQxZTZiYjIxMjI0YjA1NmFmNjdiM2Y2MjNiNzNkNDVhZjhkN2FjZjc2NWM0Nzg1YmVhNjIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE4OTU1YWEzMWRhMmQwNDYyNjIzZjZjOWVhNzFiZDc2ZWE1NmQxYWE2MTViZGRhMmFlZmQ3YzA1N2VhNTIwOTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRlOGQxZDVlNjk5YzI0ZjNhZTk0Yjk2MzZhZTk1MzE0Njc3Njc4Mjk1ZjQ0YTUxYmExNmZjMDhmNGE3MTViNjQifQ" + }, + { + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L180-L195", + "version": "repo-lines-v1:sha256:8ccf0dc95c02f78777ed9a12826a9b0b973f8951771e734bac70783c8bad0b46:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjNTUwNmNjYzg2NzY3ZDM1ZjBjMjk4YzdlMzkyMjU3MjhiYjg4NmJmMjYxN2Q4ZmUzNzQ5NmNlNjI4OWYzNjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMxYzUzZDM1YTgzMzNhMjMwNDFhNjQzMjJmYWYwNmU3NGZmODBlYzYyYmQ1OGEyOGI1NjZjZDMwM2RmYTBjYzYifQ" + }, + { + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L219-L235", + "version": "repo-lines-v1:sha256:2e54cffa1cbb29b3d600ea9dbb7dd005fac89c99463a853a21e41db1e09202b1:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU0NzJhOGE4MDI3MDRhZmNhMDFkMzA2ZmJjYzkwMWJhMWQzMzAzMTQ0OGIyMDg1YWEwY2E1ZjkzZTY5NmU2MmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM1ZjZjMmI0YzNlZmI4YTUxZGVhNjYzZGVlMmQ0ZTczNGI4MTk2M2Q0ODkyMDdhMjU1YjZhYmU2YTA2ZWM1ZDUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRjOTEyNDk4N2JmNmNlNjY1M2EwNjkzYWY2MzFkOWRmYmVhYWQxNjFiMDE0NWUyNzU4ZmViMTNmNDdiMGE1ZmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY4YThhYjM5M2JmYjY5M2NiYzAxMDAwNDdhZjUzYWY3YWY0YjMxNzg1ODZmOWEwZDZhNjBjMDNmYjQwYjg5MjEifQ" + }, + { + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L337-L349", + "version": "repo-lines-v1:sha256:0eabe1eeca028a6aa8fcf1e46bb7c7790202725a9c9b6cd84c74491f5b4b573a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZmMDgwNDY4M2FiNDA4MWU4ZjVlODhmNDJhZGVmNGYwY2UxMGRjOGRjOTUwY2JkOTQ4NGQ3OTdkNGZjYWE2YmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE4Zjg1NDZlNDMzZDc4NjQzODA2NmJjNjllMDg1MGZlNWIyNjU3MDBmYzBlNDM4ZGU4MWRiM2ZjMTJiOWM0ZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBkYTg5MjlkNTc5MzFjYmIzOTNlNzNlNGYxNjM5ZjQ0NTg4MjUwYTFlMmM4ZDI3NzY2N2UwYmUxMDdmZTdmMGUifQ" + }, + { + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L59-L95", + "version": "repo-lines-v1:sha256:905b85c88fbc967381dd93d5491254ae70939a1009566d440f798976b5d13b99:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVkOGZmZjY4MDgwNGJkZDg1NjgzYWU5MTc5YzNlNTdjOGUyOTdlNjM2YjI0MjAzNTJlMWQ3YWJlOTc0OWVkOGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkyN2FlYWRlOTVkYmRmZDdkM2NhZWVhZTc5MmUwZWMzMjQxNTE3YjA2MjYyNjA4M2ZlMzYyMzRiOTQzNjg2YTYifQ" + } + ] + }, + { + "id": "claim_4681abcae844435993790b38d7610694", + "statement": "Known-host and snippet card relative timestamps use the SwiftUI environment locale, while host titles, package paths, snippet titles, and script bodies are record content displayed directly instead of localized catalog keys.", + "evidence": [ + { + "resource": "repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift#L35-L50", + "version": "repo-lines-v1:sha256:8772c331061a6f33903a40129bf721838ddcd5f2faff405df623fe2923d0db6d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA0Y2IzN2Q5YTZiMmI1NTViYjllYzgxNzQyYTRkMjVhY2QyZmM3ZTFlOTgwYjM4NmU3NjQ4ZDllNTFkY2JhYzgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmZjdiMzliNGJkMzBmM2VkMWYzYjVhNDhhMjg2ZjYwNDBhZTc0OGNkNDA1MzlmNDJhNDZhZjA4ZjA0OGU5MTIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU2YzdjNjA3MmM5M2I2Yjk5MGEyMzAxNTRmNGUwZjU1NDJlZDBiMzAwZDEzNWQ3Yzk1NGZlOWViMDgzMmM5ZGUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJhZmQ0YTBiMDUxZWYxNTAwOTM1Zjg1MWUwZTE3MTRmOTBmMzFjMzM3NWU0OWYzNThmNDlmZDhiZjFiYTFlOTQifQ" + }, + { + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L260-L289", + "version": "repo-lines-v1:sha256:9db559e516085882cb823c6deb04a05c7edd1478eb836537803c730e09861a38:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUxYzA2NjM4NWQ2MDI0ZTE0MDZmZDQ5MTg4NDBlZDI0Yjg2NTQxZjZmNDQzMmVhNjk3MDRkYzQ5NWRjMjA0ZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIxOGYzNWVkYWFmMjQwYzE2NzUzM2NlMjAzYWNhODFkNjdjNWVlZTkxODYwNWU1OTJkMmU1MzAwOGViMTZiYzMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIxNDNkYTgyZTA0MDMyODVmMDg0OGQzMjA2ZTllNmUwOTU0OWYzM2NmNmY4OWRiZDJkYzEzNmZjZDQwMzNmMTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE1ZDk2Y2U1OWQxNDY0MDczZGNkNGIyOWE0MmRlOTFkYzQ1ZDdkYTc4YzNmMmFmZmQ3ZDNiMTlmYjA1ODA2MTMifQ" + }, + { + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L443-L450", + "version": "repo-lines-v1:sha256:d780e5cb62d4d18cc459ebdb88e119f5cdab79ffb2de53c9a6df112c1af3b427:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2JhNDEyODJiOTI3ZjUzNTc4OGMzMGY5ZWE3NjJhY2RmNDRjNDBiZjk4YzljNTk5ZWI5YjY3MmY4ODM2NjUxYSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNzVlNTIwOWUwYjg2MGYwODBmZTdmYzk2YjAxOTFlMWRhYjFmNTdmMjA5MjcxYjcxMDY0MzEzYjg3NzhhYWJiMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNTZjNDkxOWExZTkyMjkzMjdhNTNlNTJmZmEzMTgxNmZkYjRiMDEyZDhmMmY2MWQ4YTY0ZjIwYTA1NTNjZTk3YSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOTJmMmI5MWZmYzJkMmJhYzk0MWE4YmNkZmVkMTFmZGZjNGI1OWI4MzYzYmM1YTFkMDA3N2E0N2M3N2Q4ZWU4NSJ9" + }, + { + "resource": "repo://TFM/Features/KnownHosts/KnownHostsPageView.swift#L132-L163", + "version": "repo-lines-v1:sha256:f1abf0deec8bb39d80bbdbc6b1fc2ee8552a2edbf7ca07df64fa6f0d92ec86ab:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgxOGQ3M2EzZWQ1MWViNThlZDk4ZDEwM2Q0Nzg3NjgwMjk0Yzc1YjQwMDQ0YWI5MzRiMzIxMTNkN2I4MjU5OGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjYzNmI5MTA1ZDM4ZTViYmYxOTgxZWMyMjkzY2FmNjc0Y2ZjZjVjYjdjZDFlZDYwODYyODNlNGQ4ODhjMjRmNDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ" + } + ] + }, + { + "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.", + "evidence": [ + { + "resource": "repo://TFITests/MobileCardRenderingTests.swift#L10-L14", + "version": "repo-lines-v1:sha256:d52cb8c19a0b35bc44e205f0d5a12a698279206b2b4cdca80299321eedfac17a:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOWI3Yzc2ZTYwMzQwZWUxMGNhZGFjMDI0YThjNmFhYjJjYTg4NjRmNjdlOWI2ODlhMTFhODc0OTMyY2E1OTdlZSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiY2UyYTAyZDNkMmE3NzVlODIyMGJlMjk4NmQxMzNlOTliYjk1ZTA2ZDAwYmY0MTcyNjRmYzg3NTYxMGY5MDhhZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNmYyZDFhZjdhMmQ0MzFiZWJjNzgxMGZiMzgzNDlhZGYwMDhlZTNmOTA4ZGQ1ZjliNGZlMWY3ZGY1NDNlYzEzYyJ9" + }, + { + "resource": "repo://TFITests/MobileCardRenderingTests.swift#L155-L164", + "version": "repo-lines-v1:sha256:610fa0923a9b91c0d3e38f5a0bba02cdff0fec73b2980fe48b0c43000d6a1e74:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhkNDZkN2NhZDAyNTllY2U2OGJiYWY0YTYxMzAzYzQwMWY1Mzk1NDk4MWRmMWQ2MGZjZjIxN2YwNmZjMDc1ZmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZiNDEyNDY5YzBiOTkyZGFhZTI4YjYxNTBlZTZjNmVjZWM2MjAyZDM3ZDYzNTZmZDA1YzNlOTdjZmFhY2IyNjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM5MDEyYTIzNDBlMjRkNjE1MThjMmNmMWMyNGJkODRmYmU5YjVmN2RlOWM5MDYwMTk1MTJkYjNhYzA5Nzk1YTQifQ" + }, + { + "resource": "repo://TFITests/MobileCardRenderingTests.swift#L191-L205", + "version": "repo-lines-v1:sha256:d8f1d524946591de67b55a6cace633ee83c0efb92726ebb923e628b8805a9156:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjNmQ3OWVjZmFmY2M2MmIyNWJiN2U3MjI5OTI2NDY3ODU1ZGE1ZmJkYjMwYjlmY2M5OGQxY2MxZWZjZGVmMTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmZmMxMTlmYTk1Yjc1YThiYmQzMTQ5NjgzNzcyNmZmODU0NzQ4NDdkMWFlZTg3ZDIzMzBiODIwZDQwYTUzNDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE3OGI1MWU1NTllZDE3MTczNzgzZmQwOGIxYzI2M2U5ZDYwNTM1MTdiYjEzOGExNmFkN2RkZmM3NzM2ODZhZjYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIxNDU5MTM0MmRhNWEzNzJmYTk3NDFiNWE3ZTRiMjllNTk3MjNiNDBiZGVkN2QyZWNiOWQzZTkwMWNhMTAyZmUifQ" + }, + { + "resource": "repo://TFITests/MobileCardRenderingTests.swift#L95-L120", + "version": "repo-lines-v1:sha256:47605538f582da0dc698387e62dda4f4b71da6767d599dcbc17b8838ab509b08:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxM2Y0MmNjNDk2ZDAyYTU4ZmIxZGQ4NmM4MWQxN2NjZjY5NTQ5ODk2NjM5NTQ1MWRiNTkzMTg2YmZhMGNhNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MWU0YjJhNjU0NWVhMjMyNmYxOTY3ZjhhYmIyMjkyN2YzNTRhZjk0N2Y3NjE4NjkyNWI1NzgzMGI3NThjOTciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxMjRiZTQyNDU3MTA0MzVjMmE5OGM0NTZjMzNkNjJiMWI5YmRiNjVlYTMwMDRkNjZmZjcxNWU4MmZkM2ZjZDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE5Zjc5ZDYyMWI4NWIzYWY4NjEyYjAyZjlkMGNlOGRmMzYyZTkxOTNkMDllMTJjNjA0ZTQ5MDVjYjgwOTU1ZmQifQ" + }, + { + "resource": "repo://TFITests/MobileCardTests.swift#L99-L111", + "version": "repo-lines-v1:sha256:fae41ec0748177a9faa7e94da51b5caf99ed1557fe9c3a42e708424d06a3f5b3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIyMWQ0OWUzM2I1N2QxNGY1YjE4NDA2OWM5MGQ1N2M3NDg2NmM0Nzc1MzY2Y2JmZTdhYTg3ZjY2MmE0NWU4ZmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQyMDU3MzU2Y2FkZDUwNjg3Y2QxOGYyNzQyNDE2NzNkMjY5ZGM4NjMyYmVlMjhkNTUwNDE0MjJjZTFlYzI2ZmYifQ" + }, + { + "resource": "repo://TFMTests/AppLanguageTests.swift#L136-L162", + "version": "repo-lines-v1:sha256:4bc853acf8bb94e47d893ef308d5747f764c247379a23ac7b3a62ae7e4c29b95:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVmNTdiNzcxZmRhMjU1Y2ZkNDE4NTkxNDQxMzhjNWU4NDg1Njc4YmMxZDFhZGMxNjdhZDMyZmE3OTEwM2NhNmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzNTFjNDM0MmE4MjllMmYzYThkYjZjZjhlNzA5MjcyY2I3ZGNlNjdiNTVjNTA3NGE3MzJlNzNjMDUxYTc4MjMifQ" + }, + { + "resource": "repo://TFMTests/AppLanguageTests.swift#L80-L121", + "version": "repo-lines-v1:sha256:f5f37d324d7719c4bd8c418534ca4f5ff7de8d6cbebca019d3fc5559b925374e:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUzZGM3YjkyZTE3YmQ1OWUyMjQ4M2RjMDdlZWM5NWUxMTIxYmU5Y2ZjYmJkNzU5ZWRmOGVhYzc2NGEwYTlkMjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY0MTJmYmM2NGI2MzE3YTMwMmRiODZiZTI1ZjFhYjU1M2Q5NTk2ZjM5M2FhODM2OWJlYzFkZTU4NmRjMTE1OTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBjNTEzMGE3ZDBkNzM0Mjk0Mjk0ODhkNmUzZDE2N2ZmMzkyNjE3Y2ZhYTYzZjliMTk2MTUwMDEwYWE2M2MxZjcifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/concepts/persistence-and-secrets.json b/openwiki/.claims/concepts/persistence-and-secrets.json index 740ba86f..6bfa8792 100644 --- a/openwiki/.claims/concepts/persistence-and-secrets.json +++ b/openwiki/.claims/concepts/persistence-and-secrets.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:511be363c8934aa5a750eaa3c71e72cfbeaff50c5ebb0f8b6c5ec09e6892eb72", + "pageVersion": "sha256:1faf5315736b44da4aab78615dbdfeb81fd8888d3b52b10b884f9ac33af15aa6", "claims": [ { "id": "claim_e50b505da2214c6781fa8eb1a146dacf", @@ -12,11 +12,11 @@ }, { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" } ] }, @@ -26,11 +26,11 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:fc361c911553c831e066539b9f2c0df902eb588f71f3bac8606c0a48048a196e" }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:721bea277227a69f102c1b505cf41245ddf5d568b96d6ff229cb440e53106ac0" } ] }, @@ -412,25 +412,175 @@ }, { "id": "claim_b0b5b4708fda4de6bcc5775728746d34", - "statement": "Application history mutation publishes only after truncation commits, but captured missing-model/credential failure still projects live before a separate asynchronous save; live failed/interrupted adoption therefore does not turn preparation completion into a universal persistence barrier.", + "statement": "Assistant history edits publish after truncation commits; captured missing-model/credential failure and preparation interruption also save a terminal snapshot before live adoption, with save failure leaving adoption unprojected. Queued-before-start runtime cancellation is distinct: it projects cancellation when launching a best-effort save, so stop-and-wait does not guarantee a successful durable snapshot.", "evidence": [ { "resource": "repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift#L129-L147", "version": "repo-lines-v1:sha256:45383d212fb6991f01b24f3ea84538b0f619b50ed950673b4c79037e4de1652d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU3ODhmN2QzZWVhNGY0NTY0NzdmM2QwMjliNTAzZDI5YmU4YjExOTNiNjJjZTZlOWMzZTk5ZDQ1NDczMjViNDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc4MzBkMzQxYjc5NmIyZjQyNTk4YTk3M2UwMTJkOGIyZTZjNTE2MDkwYzliMDQ0YWMwZDhkYTIyZjU2MzI4MzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L719-L793", - "version": "repo-lines-v1:sha256:81156ef97d808d87d63a184f6020940cf4a5bbbdecd8dc55a2d3a3c7e7b0b60c:eyJzZWxlY3RlZExpbmVDb3VudCI6NzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2YjhlMjRkZDNlZmY5YzY3YTZiNzg3ZWMwMjA3ZmMxZTI0ZGMxZTcwZmRlZWViNmFjOTljOGFkNjA1Yzk3YmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2ODhmNzU3ODA1NDczNjk2N2U4NzY5MmJiYTg2YjI4MDhmMzI0MTk3NTQ0MDVlYmZkNmM0NWI3MTk4OWQ0NzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRhNzdhMDY4Y2ZiMmUwMWRiMDJlMTAyZDRiODhhOWMzYWRlOTU3YTNhMWMzYjczOGE3ZTBjMWNmMTc5MTUwMjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRjNmM3Y2RjOGM0ZWMwYmM5ZGU4ZTY5MThmYWUwYWE5ODQ0MTJiNDJjZTVjMzY5ZWExZTMzMjg0N2Y4ZjIyOWIifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L738-L821", + "version": "repo-lines-v1:sha256:572c14aae2ce8defd734596e7ea69dd84e1525de9a6d92c91853c2f091d9f82c:eyJzZWxlY3RlZExpbmVDb3VudCI6ODQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2YjhlMjRkZDNlZmY5YzY3YTZiNzg3ZWMwMjA3ZmMxZTI0ZGMxZTcwZmRlZWViNmFjOTljOGFkNjA1Yzk3YmMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRhNzdhMDY4Y2ZiMmUwMWRiMDJlMTAyZDRiODhhOWMzYWRlOTU3YTNhMWMzYjczOGE3ZTBjMWNmMTc5MTUwMjgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkxNDVmN2U5NmE0M2YyYjc3N2RlNTYwODkwNTUwNjJhY2JlNzk1MWQ1M2FiYjFkNWQzYWI0NzIxNjdmODBkMzYifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2040-L2092", - "version": "repo-lines-v1:sha256:d1a56a12b39372c0277e40115884e11b8c29d16d3df1e847c7407b89efbd1881:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVkOGQ3MGNkOTIxY2E1NTJmMGEwZWIxMGJhNzc3OWQ2OTk0M2RlZjUwY2NhNjQ5YjIyZTg2MzU3OTgyM2ExM2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU3YzRmZjVmY2EyMGUzODk0Zjc3ZmY2NDk0Y2FmNmVkZDU2NzFiZjE3N2YyMmVmMDE3NDBlNzNhMTYwMTc3OWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlhZDUyYWNhNzhkODcxNDMzZjJhNzMzZGJmMDQ3MGNmYTZhNGEwZGQzM2IzY2IwYzgyMTJlODNkYTIxY2ExZmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiNTdmZTYwMTUxZDJlN2IwYWNlZTEzOTJhYzI5OGUxYzBjOGE2OWRiMzlkNWU4OTllYzNkMzdkMTM4Njc3ZjMifQ" + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2148-L2158", + "version": "repo-lines-v1:sha256:0d402f7bc9263922ff162bdaf324f7e872edec5da836fac2270db712da2a5624:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjMjc4YzRhNGM4Mzc4MTY2NDI1ZTg2MjZmOTMyODgwZTBmMjkwNmFmODU2OWM0NWExYjNmYWY2MWVjNmNmZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk3MTRjN2YwYmY1ZWJiYTg0MmI2Yjg3MjlkYTI2MTliNzQyODMxZmMzY2I1NWQxNjUxOGE0NTY4NDJkNTkxNjgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJhNjkzYWFiOTVkZDE1YTNmMTQxY2ZhOWE2YjczZjgyNjlmOGM1MjNlOWFhMWZiYmQ4NDJlMmViMTQzYTU5YzAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5OTRjYWQ2MGQ4ZGM0ZTFlYWE2OTkwYzBjOGM1OWRiNTE5M2EyZWU3YTM0ZDQxNWMwZjEwOTdiMWNmNTJjOWYifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/ConversationModel.swift#L2241-L2256", + "version": "repo-lines-v1:sha256:687448483f885eab66762ecd1a5336e7e44e5df4db6a99fb3f9065b9e40b1cc3:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNmZmM0MzNjZDM1OTM3MTAxZjgyZTM2MzI0MGZiMDkzMWJlMjZkYTcwYjg1MjRlMDEwYjVjMzlkNzdkNWYyNjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE0NjVmODNlNjM1MzFmM2JjZGNmZTU5ZmE0MmE5Y2M1ZGIyMzI4MWFmNzAxM2NkZGNiMjY3YzUzZjM5MWRlY2MiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM4MDU1NTIyN2IxNGM1ZmEwYTQ0NTA1NjhmM2U0N2RmNzAxMDg1NjFlZDU4NjM3ZTZiODlkZDc5ZmVhOGE3NzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ5MmYyYmQzZTc3MWViYmIyMDI4ZjY2NzQzMWI5ZGMyZjEwMWJjNTUyYWU3OWU4ZTJlOTcyN2Y5YTcwMTViMWMifQ" + } + ] + }, + { + "id": "claim_30bc7a3d2da840be8666df0a9e19888f", + "statement": "Desktop host deletion requests the durable deletion before clearing command, SFTP and connection History and projecting the host out; mobile performs live-workspace, assistant, transfer and forwarding cleanup before requesting deletion and leaves its three History clears to the registered outbox handler, which can resume after startup.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L289-L308", + "version": "repo-lines-v1:sha256:63e3cb34ad0a6d1c4cee4ed6e3ccf865545b2728b1f2395572d0b9dca0375631:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEwM2M0NWRiMmQ0ZTMyMDIzOGNmOTkzMWJjMDJlMTg3NzZlMjVmNmNmNGZhY2MwZjcwYmE4M2Q3MzYxYmJmYzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijg3MDAzMDk2ZDkzZTMyMmY3NDZlMWZhZjQxZjY1NTcyMWY3ZDc5MmRkYWM3NDIyNzA5ZTMwOTg2MTgzZDA4MWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3MWEwNzY5OGM3ZjA3ZjI0NTY0NjVmYjA3MDVhNWNjMTM4M2U1NGU4MDYyOWFjYjAxNGEyYzczNzg3MzA0OWYifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L505-L523", + "version": "repo-lines-v1:sha256:241e56c8bf8a114c77e4c53dc1d887e431323f0516d50e525fd03a643d8026ca:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE5YjBiODUwMjBmNzZhMjllYzJmODA2NDBlYWZjNDE0ZTI0MTI5NjJjY2QzZmVjODEwMGQzNTYzZDcxZDc5M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlkYWU1NGY5ZjkwYWVmNTQ0ZjBhZTQ5MDAxZjQzMmY4NTUxYzZiZjU0OWZlMWYxM2E0YjEyYTQ1MDVhYzUzMmUifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L299-L318", + "version": "repo-lines-v1:sha256:4db583fd926f9bf6c9449799b090ae08c99037925ddb73c5c3f03d7f991de88a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxOWE1ZTNjMDdkMWZiODZlNzgzODQzYjBjOTc0M2UxYzkwYzg1NGQ0Yzk0NjFjOGYyMmExNmUyNTBhMDkyNTkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyZjg3YjNkNjcyYmM2ZTk0MTA1NDlkYTYzZDBjNmUzYjk4NDRkOTE2YTkyNDY3ODllNzdmOTg5Y2RkODMyZWMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAwZGFiZWIzYjE0Y2NiNGI4NzQyMTc1M2EzOTFmMTA3OGE0N2RkODYxNGVjNGY4ZDU5YzY5ODJkNDM4NmExODYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJjZjk5NjAzYzM1OGMzN2Y2MjMyZDA0YzhmOWFlN2RkYzlkNzBlYWY4NGMwY2YyNjVkYzNkOWM1NTg1NzViNjcifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L663-L677", + "version": "repo-lines-v1:sha256:7164a92c8128acec20df7975538475b412e572c6dfff408097f529a8537e3975:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhZDUzYmFhYzE4Nzg1MmI0MzFjMjMyZTA1MTYwNjFkNDk2ZjdhMjE1NmVlNGJmN2RlYTY0N2ZjNjY0OTg2NmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE5YWMyNWY4NzcwNGU3NjVlZTQxMjFkOTEyZTNhZmUwODY4YzIwZDdlYWM4ZTQ1YmJiZThkODUwMjBhYTRkNDcifQ" + } + ] + }, + { + "id": "claim_aed4501475d34b428b6ad2388faf953f", + "statement": "Desktop SwiftData composition shares the container main context among many persistence services and terminates on database-open failure; mobile composition creates separate contexts for several services, shares a vault context among host and history/device repositories, and throws on container-open failure rather than replacing the store.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L156-L174", + "version": "repo-lines-v1:sha256:779278cd462129371aead29c558c4ae4d7dedbb05b46408597b27fd46cecf78c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwMDc4NTkwOGZlY2YyODUxNWNhMDMxOGZkYjI4ODhhNjU4ZTQyMjVkZWZjMTAxNWExYWFmNzUxZGQ3OTUwNTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk0ZTZmZGNjYzBhNzIxZmJlNDcyNjI3NzQ0NmUwMGMyYmI2OTVmNzIzZGNiNDgyZTE0OWRkZDE0YTVmMjBhYzEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjlmN2M4NjBjOTAzOGM2ODEzOWVjMTYzOGNiZThkNDYzNzYxMDYyOGY0NGU4MTk1OThjYmY2YjA0Y2MzOWIzNWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVkMjhkMzExMmIzOGJkMjVhZmU4NTEwNzVkM2ZiNzZhY2VlNGRkNGMzZGZlNWVhM2M3Y2U1YzAzMTYyYWJiN2QifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L197-L209", + "version": "repo-lines-v1:sha256:e4e1f694ff1402e5530b483678d54581a8a277ae2f051fa9e89e851ab837f003:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMxMTc3MjU3ZmRlMGJiNjYxNmY4ODcwNTE1ZjNlNTVjOWZhOTdmMWNkMGI5YjFlZTIyM2VhYmIxZGU5MTNkNGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRlOTE2ZTI2YWM0ZmMyMmFhZDc3MWFlYzYzMzdmM2I0NzM5NWUzMzJlNjExMzFhYWFiN2E2MDM4ZGMyNTJiNmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUwMTNjNjUxZTFjODc3NGU1NWNlOWVmZmFjNmFkN2U5MTk5YmY3ZDAwYjgwZDMyOTE3NWNmMTc4M2U3MWMxNDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUwNzFjNjI4NTE3NzA4MGZlNTFjOWJhOTMwM2E3MjE3OTA3MTk1ZTM5NzE3OGZkNjkyMGVkNWE3OWNiNTVhZDUifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L137-L156", + "version": "repo-lines-v1:sha256:3a0dc8b68d20f1f1557e27aad0d3941552d5dfdf8039409571be2b632db4fc39:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhMGFmZmI5M2JmYmI4NjViODQ1NDU5NDY0ZGIzNmVmNDdkN2QwOTgyYzBjMGJlMzI1ODI1M2NhYzcwNTQxNjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFjZTZlNGYzYTNiZjViNjhmZDQ5M2UyOTA0ZGU1M2IyY2ZhMzI0MzEwNjIwN2E4MDFiOGZkZTc0M2RmYWIzZTciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVmNzY0ZGRiYmJlYTkxMTUyN2U4MTdhODBmNmZiOGExMmU4NDE3MzE3ZWY2ODEyY2Y5YTgxZjc5MDgxOTkwNjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L30-L38", + "version": "repo-lines-v1:sha256:4b22e5f4357b3b75549a2df873a4f7396eeff7b7c727404bdc8196d0f05c7011:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMWMyNThiN2I0ZjViNGFmODg2MThkMjg0YmQ4ODVjZWZjM2IyZDE5ZGExOTk5OWY3YTE0MjRiZDEwOWIyM2NmMyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiY2MxODM1YzBhNmE5ODhkMzM1NTZmZDE1OGYwZWU0MDA3MzZhNTQxOTkyNGVkNjQxYjY4ODlmYWEwMGZlMjE0MCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNGEzNjUzODgxZjg5MjNkYTJhYmYzYmFkM2YyYmFiM2JkYjhhMzY2OTViNjkyZjliOWY2YTExYjc1ZDgyOTBmMCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWNhM2IwMGJkMGIxZDUzOTAxMTYzODJjYWZjNWRlZWVlNGRkYjY3M2VjNTUxZWU0OGY1ZGRhOGJmMjBjNjMwNyJ9" + }, + { + "resource": "repo://TFM/App/TermindApp.swift#L57-L88", + "version": "repo-lines-v1:sha256:0a26a39b097512fd905a0379aa0e730a880dd82ead13c0c028d8128ec9868577:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyNzlkY2I2NTU2MzE1MmY1YTdkZDIwNDYxMTk2MmVkZTJiODAzNWVhNTRhOGMyN2M5ZTZlMGJhMTU2NTJlYTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk5NDk4ZjAyNGRkN2E3ZDM4MjBlZWMxOTFkYzY1YTliMjM0NzQ0OWVhMDViNTE0YjdiMzk0MmFmMGY0ODIxMTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkyZGFhZGJiZmE1NzAwNjhiNDYxYWY1MDJjOTQ3MDEwZTc2MDEwYjI5Mjc1MmM3OTU1MjBjYTMyMjNlOTg1NmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAwNDM1MDQ5Y2VlYWNhNTcxZGI3YTNhMmU1NDA4M2YyMzI0MjgzZmQ5YWM2ODhhYjNkMDc3OThlMjEyMzkyZjcifQ" + } + ] + }, + { + "id": "claim_21c2b51c5447462eb184133736b3f3c4", + "statement": "MemoryIndexedAgentRepository keeps SwiftData-backed agent conversations authoritative and schedules the separate GRDB history index only after successful terminal saves, creation, title changes, truncation, or deletion; MemoryModel loads that history through AgentRunPersisting when enabled and unsuspended, coalesces index requests, and waits for indexing before search.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/Agent/MemoryIndexedAgentRepository.swift#L4-L46", + "version": "repo-lines-v1:sha256:966e8a3e2d8ff0a267c9e01cb4ad301d729c79749b9f7fd46209c38f2105b5d4:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFmZDE3MzY0OGRhMWM0MjBkNDkwMzY5OWYwM2Y1MWUyOWMwYTQyMTNhZTRhZGNiMmI1ZDE5ZThhNGZlOGFjYWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc0NWExOGI2NjVjOTRlNzFjOWQ5Y2VmOWQ3YTU5NmZmMzQ2ZmY0Y2FkM2E2ODU2YjNjZGNkZGNiZjY0MTI3YzYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L147-L205", + "version": "repo-lines-v1:sha256:91fb555442f8760f4919f5361cb063ce2dcfdc6a2f6e87b9f27e34236786b4b5:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdkMmQ3NzA1ZTI5NDkzNmI1MjNmNjU2YWM1ZDZlNjU1NjI5ZGUxZmU3OTI3ZTY4NmMwNzFiMDAwM2M5NDYzNDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJmM2UzN2Y2NzljZDY2NzAyYjcxZjNmOThkN2IyYjYyZTAwMGEzM2FkYjQ4OTE1NDdjNjZhOTJkNDEyNGIxNzkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYyY2Y5YjAwMTJjOTMxOTUxZjM3YjliMWEzMzI4OTNhOTZlNDhkMTA5MzZkZWE2OGMyZThkZjMzMGZmNDgzOWEifQ" + } + ] + }, + { + "id": "claim_3dc0382c802944e78da580ebd0a7d007", + "statement": "GRDB memory history replacement compares redacted message IDs and content rather than timestamps alone, so edited turns with retained timestamps still refresh the derived searchable index.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L123-L170", + "version": "repo-lines-v1:sha256:4e602f79b32185971553efebed6d474ec0e4bb06041a7ebe3b10951fe2d1fc56:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI0Y2E5ZTU1NTliZjg3OGZhMTE1ODM3MzA0MTQ3ODRjMWYwOTU1NjRmZGY3MDYwMjYzNjcyOWJhZDZiMzAwMDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJiMjk5OGQ4MjRlNWNkNzcyM2JlZjkxYjkxYTYwMTRjMTAzMzMxY2MxNjkzZDQ0NDJhOGYzMWU4ZmM5MTM1NjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUyMGU0OWU1NGVlNTBkZTBlYmIzMjhmYTc3NTdjOGVkOWMwZTU4MjUwZTJmMzhkNWQ5MGVmNGUyMTliZDgzNGYifQ" + } + ] + }, + { + "id": "claim_701d905e143b438da6a889edb9f81f05", + "statement": "Memory suspension invalidates generation-bound session contexts and access, cancels indexing and reviews, and stops new work without deleting storage; mobile invokes it on background and resumes on active scene, while desktop invokes it during termination.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L274-L284", + "version": "repo-lines-v1:sha256:c6bd184fd629fc2765d33f8ae15143e6791863bd814b8356a2ceefdd5dcfe82e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY1NTllZmFkMzI1Mzk5YmFjYjUwOThiZDZkMjAxYzAxMjg0NTI4YjMxZDIwYTAzZDMyNGNjZjlkNjdiMWE5ZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ4MzU0ZmU3NWE1Y2JjM2M1YmJlZWE3ZDU4ZDJlMjBmODAyZmE4MmJjZTllZDk0YTMyYzg5Yzk5MzMzNTFmYmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MjgxMjhkMDk1ODYwMmUyNTRkNmFlNmVhOTBjZjM0NzA0OWYzNjdhMDE3MDEwMjJmNTI4ZGRhNDkzMDU5OTgifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L53-L60", + "version": "repo-lines-v1:sha256:937d61b838c65a7db5c31fcd120333916523ea157190fc1b778940c13cbeb5f9:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMzBjNWQ1MjI2YWFlOGZjZjQzOGMzMzQ5NDcxZjQzYmVhZTdmOTNiMDAxOWY5ZjcxMjE5ZDIzOGE1NjcxZTRhYiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmYyMTVjZDExZTgyM2UzYzQzYjFhZjQ4YjYwMGY0NDVlNjkwMDg5NmY2ZTUyYWU3ZTVkYjczYWZiMWQ2MzAyYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNGRkYWE4OTRmN2RjNDlmM2E0ZjMyYzY2ZjVmZGFiYzNhOGI5MThjZmVkOWI5YWQ4MjY3MTJlMDMyZmZiNGNmZCJ9" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L560-L579", + "version": "repo-lines-v1:sha256:0569dc2b10c701c3b0c48b14a14a2521ba0f40ec2645f7220d7e5a61e98501d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYwZTJhMWYwNzIwY2I4YWNhODQ4ZjIzNzM0N2E4YjUzNGY2YTEzZDVhZTBmMTQ3MDE4ODQ5ZmZjYjkxOTRlZWMifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L643-L655", + "version": "repo-lines-v1:sha256:43d95b2e4ccfc8c2aa01837f710eadece46b36937524129578251e56b261a7cb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY2MTg5YTNmOTZjYWI4YzM1ZjZkODNkMWQyMGE2N2U2MmUxOTJiZDgxMjQ5MjI5MjFjM2M4NTMyYzE2MjlmZGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY3YWZhNzJlNzZkZGRiNzBhMTgzZGJmY2NkOGRhYzM4NmFhYjEzY2I5NDIyMDdhNTExNmU5ZjE1NWRjNDdmMjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxNzMxNDIwMjQzNGQ0Yzg0MjI5MGRkYmY3M2RkNDg5ZTM2YmI4M2UzYTIyOTY2MmI2YjI3MWQxYmNiYWZjMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3YjBkNThmZmVlMDkwZWM2MDA0ZWFhZDExZjllMDYzYzEzYzc5ZjgxYjk4ZDdmNWNhZGFmNzIxNzk0ZGYxNmQifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L765-L767", + "version": "repo-lines-v1:sha256:c2e9a4e4dd46b3051a8098f210c618cc626d12bef02cf5253de620c52fccc5c5:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGVjMGNmZTMzNmJhNWE4OThhMmVhZWIzNjkxYTVkNWIzMjkwNjA2NGVmMDNlM2ZlYzFjMzM3NGZlOTE3MDE4ZiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODQxMTYyNzU5MmIxODU2M2JlMTNmOWI4MGNhYWI2NmYxNDUyMzYyOGQwODA2YzliMmI4ZDYwNDE5YTE0NmI1ZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZGM2M2IyNGQ4MjQ2MmY4ZGE5YThkYjUwODE2OWU4MzYwMDM1NTUxYTJhNTEzYWE4NWZlMjFiOTg2Y2QzYjQ5YSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDNhNjczOTg3ODQ4ZTI4NGI0ZDVjNGU5MTc3ZmI0ZDI5NWE2ZmRkZjg2YzJmZjJhNDUyNDFmY2MyNDE4MGJmMiJ9" + } + ] + }, + { + "id": "claim_f2855fe56b1c41108ac4f551ae3e0b48", + "statement": "After a memory write commits across a suspension, its old-generation caller is cancelled instead of publishing stale state and the active generation reloads the committed value; index changes deferred by suspension are refreshed on resume and stale pre-suspension reviews cannot apply.", + "evidence": [ + { + "resource": "repo://FrameworkTests/HermesMemoryTests.swift#L116-L201", + "version": "repo-lines-v1:sha256:112f27e178d238c67bdc2b780cd5d11302d23654deceab547853d69c7267fb87:eyJzZWxlY3RlZExpbmVDb3VudCI6ODYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3MjA1MzIyZDIyNTY5NmVkODY4OGRlYzk5N2NjNGMyMzZlN2M4ZDVhMDY4ZjBmOGEwNzg0NWJkYzk4NWJhYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFkMmZlMGM5ZTQ2MGJjYjM4YTQ0YzY4YTY2OWNlZWY3NDA4YWExNjcxMmUwMjZlMmFmZGI0Yzk4NTc5YzlmMjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc2ZGVkYmIyNmVhODk3NmRjMWEwNTQ0NmIyNDlkY2E1OWVmZGM2OWEyYzllYjEyMzk1OTQxNTNjNjIxOTJmZDQifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L117-L155", + "version": "repo-lines-v1:sha256:4ecfcaf691a0da872f534c3400b2ac256de8b03372b807020ffcc66fa58e6bf9:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyN2NiYTUzMDYwNWJkMDZiMGMxNGIyYTlmODM1MWJlMWU2YmJiY2JiNjE1YjVhNjFlOGE3NWE5NzZjNDJlZjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI5YjUxMTAxN2UwNjI2MThiNWYzMTA2M2ZlYzM4ZjhiZjQwNTI3MTFhZTI3MDIxMzkxYzQ3YjVkM2U2ZDM5NGIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM5ZTMwZjVhZTBjZjk4MWY4ZGJhOTlmOTMwYWVlY2RjYTlkMjRjNzI0NTQyZTc2MjRjOTRiOGMyNzcwMzU1MDkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcyOGNiMjBhNjliOTMzZDZmNmQ5YThjMDA5NDg3OWNkMDM0YTI5ODIwMzkyNjZjMDljYzA0NTNkOTA1MzY3MzMifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L177-L253", + "version": "repo-lines-v1:sha256:1079bf8c6034f2329567a14d9ff97aec13f6e760e3edeb9c79570862ef236f8d:eyJzZWxlY3RlZExpbmVDb3VudCI6NzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIxNjhmZjRmY2M1OGUzOTQxNjdmNmMwYTkwOGZiMzIzZDJmZmM3YWRmYWEzMTNjZjk3MDhhOTNmMGM2MmFjYjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxZmEwZGY2ODA4NTZlYTA3YTNlMmVkNzkxODJmYjA4YWQwMzE1NTQ1NjM0NzgzMDAxM2E1Yjc0MzBkMDMwNzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhMTc5NmZiOTc5MjY1ODlhZjExYTQ5ZGNhMjViNTgwMDlkYjVhZjhhMWQ3Y2UwMjhjZmYxNDBjYzJhNWEwNjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEzNzA1MWM2ZjA2MGQ0YTI1ZWI4NTNhYzNjY2ZjNDgzM2I3MDRhYTI2YjdlZjFhNTgxNzIzM2ZmM2U2NmRmODEifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L274-L284", + "version": "repo-lines-v1:sha256:c6bd184fd629fc2765d33f8ae15143e6791863bd814b8356a2ceefdd5dcfe82e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY1NTllZmFkMzI1Mzk5YmFjYjUwOThiZDZkMjAxYzAxMjg0NTI4YjMxZDIwYTAzZDMyNGNjZjlkNjdiMWE5ZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ4MzU0ZmU3NWE1Y2JjM2M1YmJlZWE3ZDU4ZDJlMjBmODAyZmE4MmJjZTllZDk0YTMyYzg5Yzk5MzMzNTFmYmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg2MjgxMjhkMDk1ODYwMmUyNTRkNmFlNmVhOTBjZjM0NzA0OWYzNjdhMDE3MDEwMjJmNTI4ZGRhNDkzMDU5OTgifQ" + } + ] + }, + { + "id": "claim_9fee3534891a491c914082772bbb7e37", + "statement": "Disabling Hermes memory closes its GRDB store without deletion; destroy disables access, joins cancelled work, removes the dedicated directory, and records a pending-destroy preference that prevents reenable and retries cleanup on next startup after a failure; surviving agent history can be indexed again after successful destroy.", + "evidence": [ + { + "resource": "repo://FrameworkTests/HermesMemoryTests.swift#L247-L270", + "version": "repo-lines-v1:sha256:52393b0714d677cf5bb3b87ae38b38016ea63f6af1e3086a91db18098e3f2506:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUxNTlkY2U2MjQxZGRhYzhmODgzNGVkYjM2ODgwZmJiMDdhZGMyOTI0MjQ3M2VlMTViZWRjYjgyNGM3MjZmYjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE2NzRiNjdiYWYyYmMwZDEwOGJmMWJkZjIwMDVkZWVjNjM3NThlNDVjNGJiMTE2ODk3ZjliZGM2YjhkMGQ0OTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzMDY1OWNhOWM1NTcwNzQzYjU2ODQzY2RkYWQ3MTRjMDc5YWNmMWMzN2YyZjA4YWFhZGM4MTdkMTAzMjRhMzIifQ" + }, + { + "resource": "repo://FrameworkTests/HermesMemoryTests.swift#L86-L114", + "version": "repo-lines-v1:sha256:19c73e094ae211d6a2a810ff0b0d71e58cf8109074bdfe50f02f8c137a2d75eb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMzNTBkZTA5MTUxMGViYjBlZDdlM2E5OTNkOGEzYjAyM2QxODg1MGUwMzA0NTQ2Y2U4NDIyYzRkMzM2MzZkNmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY1YjQ3MzcxOWMxOWFiZjk3YzY4Y2Y2ZTAwMzU2YTMyMDE0OGE3OGYzY2JlZDRiMGFmNGRjYzQ1YTFjY2YzODIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkN2NiOGVkNTMyMDUzNmZmNzAxNDhmZWVhNDgxMWFmNDhhOTg1ZjhkMjY5YWVjNGY0YTkyYjA1YTEwZDAzNDgifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L255-L273", + "version": "repo-lines-v1:sha256:ce2a99dde1ff37657b472fa1eefa8a209fa22fb9f6e72e7b4359b5d5cafb3362:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhlNzEwNmQ4YmYxZmZiMTA5ZGJhZjNlNzU3ZDYyMzA0NGEyYTE4YTZhODg4ZmU1YzllZGFiNjFjMWQ1NjBkMjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjhjYThiNmYwOTgwNzYzZjgwY2I3Mjk4ODliYzM3MTdlMTQ1MjBiOTkxZGVkODdhZDNhNWZmOGUxY2FmYTJjMzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU4OWJlZDcyZTZhZjY4N2ZmYjAxODUyN2Y2NmFhNWZhMDBhOWY5ZTI3MmE0NWVjNjZjZDZjOTJkMTQ0Y2Y2NGUifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift#L38-L76", + "version": "repo-lines-v1:sha256:d9b0f863ef7ee1ca7e70d0204b06a8b79e625efdf0bb4b8d4eb390e05b73ec97:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJjMTYzNTAxNzBmNjExMjhiMjk4MWZjYjIzYjU5YzM5ZmI4NmRlNTMwMGUyN2FlZjU1MWQwYzM2MTU0N2Q3ZTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZmZWNjOTI3NDViZjE3YmEyOGU5N2Y3ZDM3ZDUwNjExYzQ4NmU2ZmYwMDFmZGM3NDBmZTVlN2YyMDYxMTYwNDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjIxMTExMTYzYzE2OWUxMmNiNWQ5MWM1ODYxOWI5MDY1ZDZjZjkyNGJhZDg4MWE1MTJhMzdlZmI1NzhhYzMyZjUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkNWI4OTE4YjQ5NWU5NDY3NjA4OWMyMjY0MTAxNGY4ODFiZTJmODg2N2QwOWRkOTdjNDNhZDk2YTBiMjAxZjcifQ" + }, + { + "resource": "repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift#L226-L233", + "version": "repo-lines-v1:sha256:aeb4eb621e2238597be72c2efc2f258c606a2af7d9e22bc52285db04273eaefd:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjZiNjgyYjliNDhmMjg3Mjc4NzU4NjJkNWQ5ZjYyNzNkZTExMzEwN2FkYzQyNGY1MTMzZDA4NjAyZGNjYjI3OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTAxNDZkYzE0MTU1NWYyN2I3MGU2NTY2NTUzMTQwZTNmMTdjNGU4YWU5OTgzYWQ5OWYxZmNkYTE0ODgzZjdkMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9" } ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/concepts/shell-integration.json b/openwiki/.claims/concepts/shell-integration.json index 47fe1f84..1c2784e0 100644 --- a/openwiki/.claims/concepts/shell-integration.json +++ b/openwiki/.claims/concepts/shell-integration.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:93690003b8bab2fac2e0b4471cb3dc74e4b046473b3cce51e0a3e0d4e5f8f6b2", + "pageVersion": "sha256:ae4a3bccb3836edf9362314d853ddc4634ebac972ee4c7f16eaf1c9c77c95123", "claims": [ { "id": "claim_bc1531cd55cc445cbd6964ff7331b6c1", @@ -149,10 +149,126 @@ "version": "repo-lines-v1:sha256:52d47a062877d79081bd70483a65e58330e9eb7d6c24da4edd0c1d1c3bc7f9b6:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMWQwOTQ0ZmE4OTNhMGM5N2ZhODNhZmRiNjYxMDEwNmMzZDcwOWNhMzc2ZmE5NDFlNWRhOTlmODU0NzFhNDY5NSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTUyMmM0MmNkMTljNmQwM2Q4MDhjNDUyNzIwNTUyODI1YjdlYTFjNWI0OTFiMjE4NTExY2FjNzQxNWNmOWQ5YiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMDhkY2E2MGVmOWY4NTBmNGQyOThkNGNmZTQzOTZkYzBjNmNkM2M4NzQ4NGY4ZjczYzE1YmNhMWVjYzkxNmEwOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiODkxMzBhZmY4ZGI2NTMyODFiMmFkZDA1YmQ3ZDg2MmI2NTM1Nzk4YmE4Y2FmNzc5MGExYjk4YmM0OTU3MzQ5NyJ9" } ] + }, + { + "id": "claim_0117cea52f0d4ae69af02a6d7f2770a9", + "statement": "Shell command and draft OSC payloads are percent-unescaped and decoded with the configured remote charset into Swift strings, as is HOME metadata; raw SHELL and SYSTEM fields also use that charset. A failed conversion falls back to lossy UTF-8, and malformed UTF-8 bytes in a command can become replacement characters rather than round-tripping as raw bytes.", + "evidence": [ + { + "resource": "repo://FrameworkTests/RemoteCharsetTests.swift#L69-L86", + "version": "repo-lines-v1:sha256:682fc1771173cf86b22386ecb13cf4f6fdf0121be404c3b9da8a9321a33da29e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI3YjczNGE1Y2ZhYTI2NmZlODgwODVmZjZkMTM0NWM1MTM5YzdlMGU2NjRiNGNiNjVmNGI3NTgxMzA0ZWQ3ZmYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY3NGNjNmFlNzExODExMzg5ZTVlNzJhYzhhNzRkMmUzMWIyMzM5YTQwMzA4ODIxZDBhYjRjN2ZmM2UxM2M5YjgifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L197-L201", + "version": "repo-lines-v1:sha256:b85e28331cc97e6841c53ebbdc4e6b8ffc34d2f836697898f9a95f8a8a60dc58:eyJzZWxlY3RlZExpbmVDb3VudCI6NSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjAwM2JlMWZkODllM2QyODY3ZDA0NDBkMWIyZTk2NDAwZGFlNDRkNTgzYmI4NWM5NGVkNDU5NDk5MzkwYTM0NyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNjI2NTBmOTJmNGU5NTg1YzkxMTA5YzZkYWYzYmVkMDNhMjk3NzNhNzgwM2ZjYTkzM2Y1OGY5YTA0NmE0YjQ0ZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYjBlZDBhMzAzZWRhN2ViNjA2N2YwNWM4MGYyNTVkNTRmZDJhM2ZlMDBjNzU2NTQxNjNhMzNiMDg4ZTc2NzAyMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWUxZTljZTgwZDJmOWI2NmMzMzk5NWNmYWU4YTA2MmJlNGQwZTlhNDVkYmE2YmI2ZDJjODAxMzAwODA0ZmFjYyJ9" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L256-L288", + "version": "repo-lines-v1:sha256:6fa9b9e5ec6d89be04013de8295273409b36440d41f7b763f87d7954be9d741f:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjMDU5N2M3YWRmYjk2YjIzNGVlZjdkNmU0ODIyYTIyZjE1NGY2YjllZWFhNjNjMWVhZWI5NDBjZDFjN2U1MDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTdjNjc4MDQ0MGNlOWE4YWMwNGE3MDg5ZTU0NzA2MzJkMTFkMTE5ODUwZTBiNWI2M2QxNTU3NjA5ZGI2NzEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQ3YjY5NDk1MDQzYTMzYzMzMTZkMWI2ZjAwYmFkZGFhNDU1N2Q5YjM3ODgyZTQxYTI4NTNhZDc3MDJlZjE1ZTIifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L543-L565", + "version": "repo-lines-v1:sha256:e0fb88f4862196c1af7373f2defde926f9b478da5cccd145bb6bf083d5461c34:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1MWFmOTgzNjEwZjY3NjhkNzBlZThmYWNkYTVjZWE1NmRmY2NjNTUzNmNhNjJiZTg4ZWE2OTU3YzEwNTVkYjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjMjZiODNmZjI0NzRkNDBjNGM0ODYxMzBiZTFmMDNlMDJhMzhmZjE5MTNlY2IyMDg5Yjg5ZTk3MTkwZmFlMDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNlN2Q2NWE0NDYzYjM1MTNmZGZmZjUzOWQ2Y2JiZDBmY2VlNGE0MmVkYTdhNzYxZjU0Y2M2M2ZhYzNkOWZmZjciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA5OGMyYmVjZGI1YzgxMDU4NTg3Y2RmZTViMmQyYmRiMGFkNWE5MGNmZjI5ZGI1OWI2YjNkMWM5MzUzODUzOGIifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L604-L623", + "version": "repo-lines-v1:sha256:8d0803aa4a42b30a41d018fc29e047944d7476e4f4e33e09d2ae4518692f5f9d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQzY2IyY2U5NmMzNzY4MzljOTc3MjUwOTgwMTQwNzlmNTA5YmViYzBlNzJhNzFlMjBmM2ZjYWYzYTkzZjdjN2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZjMjYxMGM5ZDRlZGY2ZjBjYTk4ZGRlOGE3NDg0NTIyYTU2N2QyOGE0NTlmZmIxNDgyOGZjYTFkMmVjMTgxYjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3MzJhMDM2OWQ4ZjMxNmYwOTcyNzVhYWQ5YzA0MzFhYjI3YWZjZDVlOGE5NDAxNTk3MDU1NjE3MTI4ZjNjZDAifQ" + } + ] + }, + { + "id": "claim_c141ef1c567443e391cd8e3370196e85", + "statement": "The OSC 7 cwd filter buffers split `file://localhost` frames, decodes percent-unescaped remote-charset path bytes and rewrites them as percent-encoded UTF-8 for terminal parsing; malformed UTF-8 path bytes are rewritten lossily, while oversized unterminated frames pass through rather than remaining buffered.", + "evidence": [ + { + "resource": "repo://FrameworkTests/RemoteCharsetTests.swift#L88-L105", + "version": "repo-lines-v1:sha256:d993b57e4ee07fe64963235749b3d1da91c896eb37a806687ec3a4924fae8690:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBjYzBiNjNlMjc4YjhiYWZjNThhZjEyZWU1NDUxOGMxZTEzZjEzYThkNmY4N2JmNDlhNzJiYjEzYjc5MTQ3ZGQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift#L225-L315", + "version": "repo-lines-v1:sha256:154252fa67e4aa6bc5030188590b02acc141d0e793335df9f6d8f5be22e10850:eyJzZWxlY3RlZExpbmVDb3VudCI6OTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM0NGY1M2U3ODIwY2I2ZGVlMjBjYzI3YzUzNzI1NzQxNTVhMjUyNzZhOGZmNjI3ODViYzcyZTBmYzM5N2ZjZWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIwZTQxZGRjNzZkNWU0NWE0Yzc2MWIwZjY1ZTI3NjI0YTQyMjkyNWUzMzg2MTAyZjNlMzZjMzA3M2EzMTIyNjgifQ" + } + ] + }, + { + "id": "claim_a5a43368c5e94d96a085aa6f79eabbcf", + "statement": "RemoteCharsetStreamConverter has strict default outgoing UTF-8-to-remote encoding, but incoming UTF-8 decoding bypasses bytes unchanged and legacy decoding converts valid sequences while bypassing malformed bytes and flushing incomplete trailing bytes verbatim; string materialization can still be lossy.", + "evidence": [ + { + "resource": "repo://FrameworkTests/RemoteCharsetTests.swift#L26-L67", + "version": "repo-lines-v1:sha256:e26eabcaac0395551641ec9be367ea064eff06db917c89c2ac5dcf5011273d8a:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI2MmYxZjhlNzYyMmY5NjRjMDE0ZTU3YmM0NzQ0NDRjZGQ5YzI4OTcyZTcxMmNiYTJkZGI5ZWZlMmJjODIzNTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgwYTg5ZTQ0Yjk3NTMzNThhNzRkZjI3ZjgxNjE5Y2RhY2YzNmVjNTJiOTNlNzcxOGUyNDE3YzYxYTQzNGI4OTEifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift#L145-L223", + "version": "repo-lines-v1:sha256:f8892502d88bbe21dd53f7d2f5feb868e83104b38e739700e675dd7cf2a539d2:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjcyOWQwZGQ3Njg3MTU3NzZkZDE5NTU1ZmI3MzU1ZDZmOTE1ZjI4NDM2ZjhmYmIxMTQ3Y2Y5MTUwMThkMjgwM2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVlMmY4NzI4MWVkYjU0NmViNTIzNGRiNjk4ZWYyZGJkM2Y1NWM3YjNmZjgxMDQ0YzVhZWJlMTdmMTdiODhiNjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjMzOGRkMWQ4Zjk2ZGNhNzFiZWE3ZTUyMmU0NDgxNDBhNjc5ODRmYTRlY2Y5ZTJiMzgzYmRmYTNhYmYxZGJmM2YifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift#L41-L139", + "version": "repo-lines-v1:sha256:fb2a42a6ccccf45a6ea6fb302bc378c0e36219610401cfc86b3ef3ac773934ab:eyJzZWxlY3RlZExpbmVDb3VudCI6OTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ4MGQ2NzYyOGE1ZDQyMmQzMzNkMDY0MjNlNDRiNDQ5NWRjZjIwODZiMjQ0NzZmZjY4MjZhNGExZmQwMTM1NDciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE1M2M1MTkzMmRhMWMyNmI0NDkzMTIxNmUyMDRhYjZjYzUwNzE4OTE1MzEwZDZjYmUwNGJhNWY0ZDRlYTVhYTcifQ" + } + ] + }, + { + "id": "claim_463f22cff8384e89af53a9f0640de4fe", + "statement": "SSH PTY configures separate input/output charset converters and strictly encodes environment requests and user input, reporting failed user writes via a charset callback while preserving any bracketed-paste delimiters; OSC 7 rewriting runs even without shell integration, and PTY closure flushes cwd-filter and decoder tails before clearing them.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L1097-L1125", + "version": "repo-lines-v1:sha256:18b6ec795aa4c05d1e4b820fa966bdcd93eac5d15b1643bf22c9159acd84a950:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxMDI0YTNlZDg5OGNiZTliOTI3MDY1OTc4NjFmMjBjZmFkMTY4MTY2OTY5Y2FjNjQzNjI2OWE2MzRmOWU1ODAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzNGYyOTRiYzljYWNmMTVjZjM2Y2I1NDIwYmVjOThmNTBmY2Q2ZWIyNmJhYjc1ZmU2NjMwMzMxYjc5ZGFmYmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIwYzFhMDM5NmZhNTI4ODRjN2JkNTAyMGI0YjMyN2IxMzc3NjNkYmQ0NWE5NjFmZDI5ZTczZGEzYzU4MGY5OWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY2MzkwMzNmODAyZDEwMDE1YmFkZDExMDc4YzFiZjg5YjljODhhMzc2ZjhjMzlkN2Q0MTZkODk1OTc1MWUyZGEifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L1170-L1215", + "version": "repo-lines-v1:sha256:9ef763280ccf3dab12b1f4ea633744134103d81635f0b148b92ddc2d7c9849cc:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQzOGUwMDcwMDY1ZDYwOWQyNmQ0NTgzY2ViYmRhMzExYjhkYmI2NWJkY2VlODI0NGM0YjVjYjFkMWE1YzQ1MTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA1ZWMyMjIxNGI5M2JhY2MwNmJhNjhlOWY3NTc0MjU4YmJlMjNiOTIwNzYzMjk2MTU4OTBmZjQ1N2QxNDlkNDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxZDZmMzdjZGY1ZDg5OThlNmZhMjNhNGQyYjg0NjFiYzJiOWYyM2VmZmU5MjRhOTcxZmNhOTM4ZjY3ODU4MWQifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift#L1587-L1652", + "version": "repo-lines-v1:sha256:34d886a2ed1087143b81e0d9e03f2dee31d2d1d370340807b199379809bfd4c5:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRkZjQ0NWVmZGNjZmVlM2IxZjc3OGJjOGU3N2M3NjE2MWUxMGM4ZTE2NjkzNDU4OTllZjgxMWVmNzNlM2MwN2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjYmU4MjRjOWY2YTZmZDQ1ODEwMGI3NGExNzVhZjZlZGY3M2Q2YjNmODg5Y2E4MDUxZGIzYTcwOThhYmQ0MGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUwOWQwMDFkMzcyYzAwZTM2MzA1NmIyOTg5MjNhN2Y0ZmUwNTljNTliODRhYjU2MzQzMjlmZjgxOWVhYjIzNDcifQ" + } + ] + }, + { + "id": "claim_633ec495a548432785993802eafa37c2", + "statement": "Telnet direct and proxied connections configure charset encoders/decoders independently of SSH hooks; Telnet protocol and NVT parsing precede application-data decoding, and outbound text encoding precedes NVT formatting and IAC escaping. Decoder exceptions display raw application bytes, while outgoing encoding errors do not send the failed write.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L151-L177", + "version": "repo-lines-v1:sha256:83eb90aa5f275ba324f4283b41250aeeaf8a0ab789ad8555825a797afb9cc6b4:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI1NzA0M2EzYmQxMzJiYzI1MGJlMmZhMzZiODg4NzQyYTkxYWJlMzg1ZGQ2NjdlYmE0ZGJlN2U0Yjc3YTlkZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiOTE0NGMxOTM1YWY4MGU1MDM2OTI5ZjVlNTBlMWQwZWNkNDdkZDFjMjdhMmMyNTA1OWZiMzk3Yjg1OTc1OTkiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0YTEwMTVjYmY4M2Y5NTgxM2NlODUzZWU2OTFkZDIyNmJkMWM0MWMxZTYzYjcwZDJhMDA0MjYzMTg5Y2VjYWIifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L235-L245", + "version": "repo-lines-v1:sha256:db41403872122c2a4dd9a2f6952d26d7f0136af5e5d6a11194d794d8d177c426:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1OGQyZTEwZTZkYjY1ZmMzMTA3NmRmY2Y5ZmQwOTY2MGY5Y2E2Mjc0Zjc0YjYzNDBhYTZjOGUxZjFiNmI3MzMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQwZGVhNTU1YjQ0YWQ4YTAyY2U3M2NkMjNmZjAwZTU5NDYwYjZjYzJlYzAxMTEzOGU3ODlhNTJiYWI5NjcxZGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZhMmQ0NTQyNGYyODIxYzIxNmQwZWRlMTM1ZjE1ZjRjNjEwYmFjYTA2YTg4YjUzNTgwMTA1NDcyOWMyYjU2YjcifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L298-L315", + "version": "repo-lines-v1:sha256:2a866f959ab9446ea82d4f1cc2aeda49a0938bfdc66084fd5778c78ce6cdc4f6:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNjYjgyNzgxMTg2ZGExMDJhZTNlYjFjMjY4Zjg3MTIwNjYxNTZlNDk0Y2FkNTk2Mzc2OGZkZWU5OTY0Y2M5Y2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFjYmNlMGQ0NmNiZGYzODAyOWE5MGExZDBhODdkOTk0NGZjYmVkNjg2NjEwZGJmZWRkMmY1MWFmZDljN2I0NTQifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L397-L405", + "version": "repo-lines-v1:sha256:93aba1c315acc3116ca75c4a017b85685d7946c01cc5584478caa0298e808ff0:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiN2U3ZmM0YzM2YzEzMzA1MDVmMzhmZTFhNmY0NWFhZjdjMjZjNjdkOWE3MGNlNjFlMzdhZGM2ZWE0MWZhMzUwYiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYzVhMWM4YzZkYzliZjBlNGFkOTcyZjdmOTQzZDA2YTQ0ZjhmMmFhOTA5ZGNhNmNmYjQxODQyMWEwMjc4ODBmZCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOGVhZmFkNWRiNGQ2ZmIyNjE2MjIxN2JiMTk3Zjk2ZGQ5MzJlZTE1NjQ3MjEwMTA0NTBiNjM0OGEzMTE4M2ZhNyJ9" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L94-L120", + "version": "repo-lines-v1:sha256:2b3aa7a52e252877039238e3788fced33f9841467c65382082b805a90732665c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJlMmQzNmE5NmE0MzNkMjM5Mzg5NTg5NzdiOGJiYzA2NGRmODM1ZjVhMTI3NWZmOTkwMmFlOWNhNWUzZWY5MzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyMjY2M2FlMDBiMDc3MGIwMWNjYTljYzRlZTdmNDUzNWI4ZTQxZDBjYmViNjk1YTNiYWI3NjE4YTgwMTgyZGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRiYTg0YTA3Nzk4ZjI3OTg2OWI0MzVlN2JkZTYyZmRjODZkNGFmOTM3MmRhNzIyZjk1YzYyNjlhMmFiOTAzZTciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk1ZWI3YTc3YTMyZGJhZWIzMmI4NjUxMDM5Y2ZkY2M3ZTYzZTU1NGMzYTcxNjViMTUxYzkzNDY3NjFjYWY3YTIifQ" + } + ] + }, + { + "id": "claim_6ec240e9f8f24da786e3697463377799", + "statement": "Telnet automatic login strictly encodes username/password; an encoding failure clears secrets, reports a charset error and continues manually, while cleanup flushes decoded output and clears converter and prompt state.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L318-L395", + "version": "repo-lines-v1:sha256:4dc2ebee2e7b4d237580c96c8c6e766f0f1fa5de7381f375a9ff5549e1f15cfe:eyJzZWxlY3RlZExpbmVDb3VudCI6NzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM2MWQxODI3ZTg0Zjg4MTFjMGJjNWJmNGRjZTcxNTIyZDhiOGQzNDA1NTI1NjE3YTRmMWNmYTcyOGE5MzdiODMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI5OGViOTg0ZDg2NjM3YzAxOWE5ZTQ3OWM0YTYyNzkyNTZmMzJlYzZjYmExODUzZTgwN2FkZmMzNGQ1MGNjMGMifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift#L450-L473", + "version": "repo-lines-v1:sha256:965c06543dbae50ff67119b30ae542d45f4e5160e0f2e816d608c8fef3f5c68e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI4MTVhZjQ0Y2NjYmY3M2ZiOGFlYTRkMmE1ZWUwNTFkMTllMmUyMDMzMWQ3ODVlY2MzOThmMjBlMzgwZDk5ZDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRmMTIwMTgxYmY2YWI3MWJiMmYxYWZhODE1ZTllZjMwZDIyMTkyZDI2ODhhOTRiYzRiZjQxMDFkMjUxMTI3OWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImJiOTg0MmMxZjExMTk5ZmUyZDVhZjJmNzhkOTdiZjQ2NDc5ZjA0NTQ0NzQ5ZmZhNGJjMWQxMGUxMDhjMTUyMTIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/concepts/ssh-multiplexing-and-scheduling.json b/openwiki/.claims/concepts/ssh-multiplexing-and-scheduling.json index b1cf8ca2..8a5a15ca 100644 --- a/openwiki/.claims/concepts/ssh-multiplexing-and-scheduling.json +++ b/openwiki/.claims/concepts/ssh-multiplexing-and-scheduling.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:34fdcb119f481b5907ac4263413fb8b395af7b5c2200b99ae878bcf2fa78a269", + "pageVersion": "sha256:ff1be2ef80ee4380d12600b617927c4a697e8a40d38e6b740cde639c9f25cc8d", "claims": [ { "id": "claim_c56b98e3167443d9a8aa8d3405b35eca", @@ -130,19 +130,27 @@ }, { "id": "claim_1fd2c2f8970047b8bf324a93ca5f2650", - "statement": "AgentConnectionPool reuses Host/fingerprint keyed connections and primary SFTP across runs, joins in-flight opens and protects active exec/SFTP leases from its default 180-second idle retirement; replacement exec retry is limited to connectionUnavailable.", + "statement": "AgentConnectionPool reuses Host/route-fingerprint keyed primary SSH and SFTP across tool calls and runs, joins concurrent opens, protects active exec/SFTP operation leases from default 180-second whole-host idle retirement, and retries exec once only for connectionUnavailable before channel start.", "evidence": [ { - "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1051-L1093", - "version": "repo-lines-v1:sha256:2f42e9d3dec1ae9ef7bebbca339793f38e26964a5da29fdac17952be06061ded:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk0ZTQ2MDk3Yzg0MjkwZmY4YjdmOWNmOWUwMmYxMTRlZWU5N2VhYmM2MDZiZTdjZmJhMjI3ZjEzNjFhYzNiZjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE0MGVhYTUxNDQzMTlkMjQ4ZmM1MGEyMGY3M2VmYmM4ZGIxZmQwYjIzZmRhNjVkYTM1MDU2YjhmM2I3YTNkNWYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUxMDE0Mzc2ZTEyOWYzZjE2ZjM3ZWQ3ZDUxMTQ0YzY1YjAyYzlkMGViN2Y1MzNkNjg0NDZkOGI4N2Q4OTJhODIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE2OWMzZTIxNmM4N2M1YmU4MjdlNzM0M2IxZGEwNDM0MGY3NjMzMzJmYTc0ZTNjNzZkNWY4MDgwN2ZkNDRiODEifQ" + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1131-L1157", + "version": "repo-lines-v1:sha256:bddcad45319856a93c70ef5595e2b6580b4ee360079d7bb414cec957a0eb4567:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0NDg1ZjFmZDlkYmM3NDQyYjlmYTA5MTYzMzc3YTVlNmY2NTMxYWZjZGVkYWExZmY0YWQ5ODkyYzRhMzAwM2UiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZmOTZjMTljNDU3MDU5N2NlNjg1YjBhZDYwYTYxM2NlZmZlZjAzZjkyMTk0NGQ2OTBmNmJkMWU5ZmMyZTM5YmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVmYWEzMTI2ZDYyNTRmOTVmMGIzYzFlOTgyMmIwNDZiNjI5YTFkODQ5YzFlYmYxMzQxNTlkMTIyZTk3YzVjYmMifQ" }, { - "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1318-L1432", - "version": "repo-lines-v1:sha256:707e4db604c194ca27b91f7ad568cca6fc34450bb25dcc1a35ea700157cc5e6f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJiMjdlNTE3ZjU0YWJjYmJhZjMxMzRlZWE1YmZlYjQzNjBkYTQ3ZWIyN2Q2NWZjMWEzMGM5N2RlMWY1YmI1MjQ1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlMzIwZmNkZDBjNmFkNDQ0ZDIzM2Y3M2Q3ODIyMTY2MDcyZTEwYWJlOGZkZmRmNzgyYWNjMWVlODNmZjU2Y2Y1IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI2YTBmYmI0NWVjZWU3ZmMwMWY3NDZiZGU2ODJlMTE0YjkyYzU1OTlkZDllMDUxNmQyMmQzYzMyNWVkMDM3NDZmIn0" + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1407-L1454", + "version": "repo-lines-v1:sha256:66049789595c8c8c7db3d3f9619f475f72d0d99139ad0fa4947109c842101755:eyJzZWxlY3RlZExpbmVDb3VudCI6NDgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxYmNmZDM0ZjcxYzZmNmZlNGJhYTJmODZhYjkzNzBiMDkzMWVhY2M2NDU4ZWEwZWYxMDMyYTdhZDJlM2NkMTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjFiOGJiNzE0Y2EwMmYzNDA5YzcwOTkxNzM1NTIxODE5YzQ3NmFlOWIzYmM4MzM3ZjhhZDZmNThmNGE0Njg4ZGMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZiZTg2ZWRkZDdiNDlhMjJmZjE0ZWI3NjMxM2FkNjU4OWQ5YWM0MTVlMmFiMmZmNTM3MjBjZTlhZGFmMTE5NGMifQ" }, { - "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1469-L1584", - "version": "repo-lines-v1:sha256:aba7ec5c1e1cccd658c5215426672c337e11ebdcdc7d2878000d06641ed5a32f:eyJzZWxlY3RlZExpbmVDb3VudCI6MTE2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIzOTA2Y2EyOWJlYzI3YTBkMzUxYjRlY2RlYzE4NGFkMjZmNzgzOTgzNDFiMmIzODljYTM1MTM3MGEwM2QyNzRkIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIxNTA1OTA1MDFhOGI1YWM0OWJiZDk3OTc2Y2UyZGE5NTA0YTQ0MzcxNmZjYzY4M2E5ZTRkN2M0MmRmOWRhODE5IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwOTIwZjM4ZTMwOGI1NDBkZDU2YzQxZDUyN2NkNjQyYTZkNmQyOTNhZTNmMzkyNGY4NGVlNjNkZTUxZWQyYzBkIn0" + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1462-L1520", + "version": "repo-lines-v1:sha256:5953c37fda6efd1474b16d4f92c03d76a9fff159389a741f0763cfb59a16a10e:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiODUzNWJjMWVmM2IxNjU3NDVmZjk4Nzg5ZDA2YzcyMWU5OWE5YjM2MTc1YmJmM2YxMDg4OTY2N2JlMDYyNjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI1MzIzMGVlMTk4N2U2MjEwMzQ5ZGQ4ZWNiM2M0MDM0YWYwNzQ4MThiNmFjOTVkYWFmNzI1MjY1MjJmYzRlZGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNkM2FiNmRiZjc3NDE0ZjNhMzBlMzBiYjBkMGMyYzY0YTdkOGVhMzk2MTk3ODMzMjE0MmU4NjQ4YWE3MWZhZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc0NDkyZDMwNDk2M2RjMjA1MWY1Zjg5NTEyMGU1ZTNiNjJlMGE5NGZkMzI3ZjZmNDY1ZTkwY2JkNDZiYzA4N2EifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1564-L1595", + "version": "repo-lines-v1:sha256:3a9acd4c8114408922da435777791b50ceee74096f97e7bd23054a9d5189cf9e:eyJzZWxlY3RlZExpbmVDb3VudCI6MzIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM5MDZjYTI5YmVjMjdhMGQzNTFiNGVjZGVjMTg0YWQyNmY3ODM5ODM0MWIyYjM4OWNhMzUxMzcwYTAzZDI3NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE3NjU3YjNhNDRiZjMxYzhkNDI1MWIzZWI5NWYwYWRhOTUxYTViNTA1Yjk5Mjk5ODhiMmI2MTFlM2FiNjI3OGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE1MDU5MDUwMWE4YjVhYzQ5YmJkOTc5NzZjZTJkYTk1MDRhNDQzNzE2ZmNjNjgzYTllNGQ3YzQyZGY5ZGE4MTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg3YWMyMGYzMTBiNjNkMjM4MzNmYWZmMDk2ODM3MWM1MzhjY2MyZmYwNzc1MTVkNzI5MGNmM2JmZGQ2OWY1MjYifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnectionWorker.swift#L205-L233", + "version": "repo-lines-v1:sha256:f4f271ef818d072a5e1b5018cb4ad88a62ce5a913f4be8d09a61607eb2db0875:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI5ZDUwOTk3MDg4MTZlOWY3YjVlMTczZGI0OGIwMTQxMzczYWMxMzE0MzI1NGIxMDk4NzkxYzU1ZDM4NGJmYTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI5NTYxNTMyMDFhMTE1MjFkZGJkNmMwMDI5ZTY3ZTRhMDNmNjJkMzYzNGY3MTg1YzlhMmU3OWJlNGEwZmIyZTciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE5ZDQ3NTBhNTdmMzIyOTQ4OTIzMzE0ZmJmZGQwOGYyZDU1M2Y2YWM3ZWY0NzI1ZGNmOTgxMzYzN2U2Zjc1MzUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM3MGViZTllOWRiZmY4OGU2NmVjMTI0OTU0ZGU3YWM1MjFiZTM1OTg1YzAxMjUwMjU5YjAxNzE1OWU5NmI3NTcifQ" } ] }, @@ -155,10 +163,126 @@ "version": "repo-lines-v1:sha256:ef2acbffed6b7a7fd6955d7fa3a6f0c7c93e6cca2ed82d431dbc1a64ff794d6d:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk0OWUxM2UyOGRlY2Q3Y2U5NDdmMjMzNzM5NGQ2MWQ5Y2I1MGIzZGI1OGJlYjUzM2M1Zjg1NjVmNGUwNzdiYzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjoyLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExOGJmY2MwNWRhNWVkOWI1NWRjNTcyNWE0ZmNkYWVjNWMyNTc1ZmRmNGNlMjJhMTk5MDliMWIzZjRkZTgxZmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" } ] + }, + { + "id": "claim_201189494d684e719ccb436531f19a6f", + "statement": "AgentSSHAuthenticationRegistry shares a per-host temporary authentication context among overlapping operations but releases it with the final caller; authentication configuration attempts join by generation and cancelling the last waiter cancels the shared attempt, while successful authentication consumes staged one-shot secrets.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1096-L1128", + "version": "repo-lines-v1:sha256:7e96eecabc99cce936e042cf9da0183852804b4d365a9940b8dd0e0faae9ca3e:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZhMDRjYWY1ODdlNTA1YTczYTYxZmM5YjUyYTFlODBhZjRmNDU3YjUxOTZjOGZmODRkNjQyNTZlZTI4N2RmMzciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkYTc3YzM5ZTVlMTNkZjhjMzU5Y2VkYzUwY2JkZmRjMzZkMTBmOThiN2MwOGIyZmYxMDRkMDkyMjlkNzdkOTcifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L601-L698", + "version": "repo-lines-v1:sha256:8ab6fac9f35b7fa93b0f19b53e092d085c65fe2aa202936fb0e75fedfb51fb07:eyJzZWxlY3RlZExpbmVDb3VudCI6OTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdjOWRhNzhjOTJlMzEzNzI1OGY0NzA5MGQ1MjM5OTY2ZWEyYWQ4MTczYzRiZGZkMTQyMzhjYjE2NzcxZjM1MTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZmNGQxOGNmNDZiOWM5ZmQ0MDViYmVkZjlhZDc5ZmVmMGNhNGYzYjI4NTdmYWQ5MDA0NDI5MGJkNWM0NTVkMGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA1YzBjMTU2OWU3MmQ3ZDA5MTFmMmQ0M2FiMjcxZmI4NGE0ZGIxZjEzMDkwM2NhYjExM2Y1MjRlNWU1ZDA1ODgifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L700-L775", + "version": "repo-lines-v1:sha256:489267b842488f2d2de0ba85096718984af9bbf086b182cc1bf69647f5d6dbad:eyJzZWxlY3RlZExpbmVDb3VudCI6NzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwMzg4ZDNjZDU0YTVlOGYxZmVkZjlmOGY0ZjYxYTBiYWNkMDI1YWU0NGE1MDUzMDMxYjExNzU1YTQ5MmI1NzUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImNhNzc4Yjc5MjgwMzkyYWQyMjYzNjJmYzk5OGQwNGJhNzdhZjU4ZmYzYWQ2MWYyZjc2NzA0ZWZjMjNkNWU2YzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjczMWU4NTBjY2NiNjllNWEwNTEyNDA3ZTY5NjQ0ZWIyZjJiNWQyOGI5MmIwMTRmNzZlZWVhNjE5NTFmNDYxYzgifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L912-L937", + "version": "repo-lines-v1:sha256:e50095ddead1c2f5f643866cde79c57d6b3147dd4248b8e358ce65f4b3924d91:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFjYjRhNmQ0MzczYWNjNTgxNWU5OGI2ZWMzNDMzZDg1ZTBmNjU1YjU5NWVjMThlODUzNGJmMWVlYzk3MDIwYWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ" + } + ] + }, + { + "id": "claim_9d81b367737d41fba09d5681f7121e91", + "statement": "Agent connection acquisition retries rejected authentication by evicting a pooled connection for normal opens and advancing only the failed authentication generation; SFTP lease acquisition does not evict on this path, while local credential requirements re-resolve configuration without a rejected-auth reset and cancellation or unrelated errors do not enter this retry loop.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/SSHConnectionTypes.swift#L512-L540", + "version": "repo-lines-v1:sha256:82a166a31eadfa8380f6239d59b8e28d02e7def785902ee95451e088bf15a2d1:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlNDkyYzMzYTYzNDYwM2NhNmQxYjkzOTUzNGViYmMzOGExNWEyODI1ZmNlZmEyNjQ0MjlkMGJlMmQ2ZTIwZDEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU2ZDU4ODZkMWFjYWM0YjE1OTJiZWJjMjE3NjdlZDkwZjMxMzlkMmZmZDQ5MTM0NGY5ZGEzY2VmMzU0Mjg1YjAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM5NGJhYzg1ZDY2ZDNiYWJlMzFkMWYxMzYyMzdlNTgzMjcyZDIzOTgyZjQ2ZjRiNTRhZmJlZGQyNDhiMDAyZDQifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1015-L1034", + "version": "repo-lines-v1:sha256:25ef929025f156ccdd05a3e8bbc807366f84a4ba1209e7f1fc4af20b57c84203:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxNzcwYWFjOWViMmRlMjllMDJkMzcyNzQyNTFmNWExMzFjZWFmOGJlZGYzNzZjYTQxYTFhODBjODMwMjE0MzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU4NDBlMGRkYjQ0MThlMzE5OTYxZmQ2MTk3ZTA5NTNiZDI0MTJhNTMxN2JlMWEyOWIxNThjMDNhMGI2ZmU5ZDMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVjNjNhNDkzMmJkZmNjNmQxMGQyYTQxYTI1NThjYjNmN2Q0MmRlODk2OGYxZTBmMDM1NzlmMTJmZTVmOGYwZDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU4NjVmMDIyYmYyMTc3NTQ1MDBiNDQ2NmVmMjIxYmU1MmE0ZTY5MzQ4NmU1NDk0YzUzMjc2MmU5NjA4NTMxNWYifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1059-L1094", + "version": "repo-lines-v1:sha256:6c24b56ec94eab214ff12c22007c715ada6c634f4e23ae654fa3cc0ba2e93101:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2M2E1N2M2NDE3Y2NlY2M1YWYzMmNiNjNmMWNlNzBkZThjMTQ4ZDI0YjViMTVjOTk1NzA1MmZkOTY1MGUwYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjI1OTIyODZkMmYwMmNjY2M1ZjA3YTkzNWVmYjNhNTc2ZmMzNWM2NTkxYTBhYjcxZThjMDhmNzYwODg5NzRiNTcifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L672-L698", + "version": "repo-lines-v1:sha256:53131f2332c025cbcfe7341d6231ad3f3493513e688baec873fceccf1f155ed7:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA0NTYzMGI4ODI1MTZkNWZlMTMyZmQ3ODkwNDRkZTRlYThiNzEwZjM2Njg4MzY1ODRlMTI2ZjRkZWNlYjlmNzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRmMWJjYjU0ZmEwMTdhODlkN2U2MTVjNmIwNDE5NjljZjYzOWVmNzhiMGE0NmViMDk0ZDllZTA3NTIwNWM1YjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjA1YzBjMTU2OWU3MmQ3ZDA5MTFmMmQ0M2FiMjcxZmI4NGE0ZGIxZjEzMDkwM2NhYjExM2Y1MjRlNWU1ZDA1ODgifQ" + } + ] + }, + { + "id": "claim_a9ca0a1b28f9474ea7132144f1c19553", + "statement": "Agent route resolution prompts for local proxy/identity/passphrase requirements before network opening; attempts carry host-key and keyboard-interactive callbacks, with failing route-node authentication re-prompted without allowing old-generation failures to erase new credentials.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L213-L348", + "version": "repo-lines-v1:sha256:809a4b5397b625b90478396a97b00f44407800ee21d94acd13822d20b08baa76:eyJzZWxlY3RlZExpbmVDb3VudCI6MTM2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIwYzRiMmIzMzJiZGFmODlhYzdjMDM3MzI0M2M1Zjk2M2FjZjFmNjRkMWY1ZGIzOTY1MTk0ODRkMDU1MTgwMWYzIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiIwYThmMDNhZjNmZTdkZmIwNmRkYjFkYWE3ZWQ1ZDlhNGRiYjc3YmY3MDI2OWIxZmFhY2ZkYjIxYWJhYzk2NzcwIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIyY2Y3YTM1YTkyNzg0NGVmZDQ0MDM1Mzg0OTBkYTI5ZmE2MjkyYWI4YTI5ZThlODNlOWQwN2I2NmJiZmFiNTY5IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJmZjBkNzU5NTBkZjBmZjlhM2VlOTY2MzlkY2M4ZmY1ZWFlZGI0MGQ2ODJiZWE5MjYyMmI1MjBkZDg4N2Q5M2U5In0" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L672-L689", + "version": "repo-lines-v1:sha256:7eaa2dbdf324b2b6111287321ab64852d12d3afb3710e5093b4f0d6cd22016a6:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA0NTYzMGI4ODI1MTZkNWZlMTMyZmQ3ODkwNDRkZTRlYThiNzEwZjM2Njg4MzY1ODRlMTI2ZjRkZWNlYjlmNzkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRmMWJjYjU0ZmEwMTdhODlkN2U2MTVjNmIwNDE5NjljZjYzOWVmNzhiMGE0NmViMDk0ZDllZTA3NTIwNWM1YjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU3MjhjOGIyOGIzZGQ3MjY2YTNkNTM5NDM0ZmE1ZjBhYjc2MWZjZjNiN2IyYTY2NzBmN2I3YzBiNTA2Nzg5ZTMifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L778-L869", + "version": "repo-lines-v1:sha256:72b3460f2be94c1da99cbe52d15170ebdc000f536832a8d7f51af1679d4b93a9:eyJzZWxlY3RlZExpbmVDb3VudCI6OTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQwYzJjMmRhNTA0NWRjNzA2ZTQ5YTM5MjlmNDEyYmIxZGZhYjA0YTRiOTBhNWU1MWJmMjc0NDlmMzQ3NDA5MmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkNjVhMjIwZDUwYThhYjY0NzIwZjU3ZmI1ZjhhMDI1NDQ3YzFmNjQ0ODFhZTcyZWEwZDYyOTEwNGI0YzdkZjMifQ" + }, + { + "resource": "repo://TFMTests/AgentHostAuthenticationTests.swift#L616-L659", + "version": "repo-lines-v1:sha256:cb344ebd3cff539f706d2afb07762a1cc55c195c62e09fa4de7a408cecd43e39:eyJzZWxlY3RlZExpbmVDb3VudCI6NDQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA4Zjg5NDBiZDZmM2MzMjMwOTJmYmEwYzgzOGJhMDA0Y2VjNmZmZTdkNjYwNzY4ZWIxOTU0OGQ1NWE0ZDA4ZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUyY2RjNWI5MDZhNWE0YWY5NTZlZDU0MzEzYjdhMmEwYmY5MDkxODUxMjQxMjgyYmY4ZmE2YjE4YTI2NjRhOWIifQ" + } + ] + }, + { + "id": "claim_5cd9c6800b6a416c95a74e332ac5630b", + "statement": "Agent pool connection-opening waiters cancel independently: the last waiter cancels the shared open, late successful opens are disconnected, and disconnect cancels pending opens; a committed connection uses the post-authentication route fingerprint so identity saves during prompting remain reusable.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1638-L1774", + "version": "repo-lines-v1:sha256:23aaca80cf4e2215a2f75373a0dcf3b4d6ee051aa3b90f8a3ad089893590f8a8:eyJzZWxlY3RlZExpbmVDb3VudCI6MTM3LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJhZTE1M2Y3ZDQ0ZmFiNGE1NDY3NzdmOTE0YjZkZDBlMDIyMjEwNGYzOTk2NDk3YTA2MzQyZmExYmVlM2FlNTVmIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJkNmMyYzFhM2IyZWMzOGYxOTBiZDc5ZTNjNjczYjhjZDVhOTFjMmRhMmE4ZDgzODM3ZWY4MzRlYTc1N2Y2YjA3IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI3NDcyMmRmYjk2MDYxMDVlNTFhZjZkZDllYzI0YjNjZGE4ZDQ1MDU0NzA1YzUxN2UwNGU4OTJlM2U1YzQ2MjZhIn0" + }, + { + "resource": "repo://TFMTests/AgentConnectionPoolTests.swift#L81-L136", + "version": "repo-lines-v1:sha256:d95648ff624d1d27ac3b91f3160d9838f89a87415238b4b0cb01adfe233f5c30:eyJzZWxlY3RlZExpbmVDb3VudCI6NTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBkYjQ3M2ZjZDlkMDk4NWVmMjIzOTYzMjlkMjQyMjU2OTNiZjkwNzllNDMyODg1M2NlZTRhMzhlZWZhZjQ5YzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkM2E2ODhlNGZhYzk1MGJkNTg3MDgzYzY4YmQ5MGIyODM3ZDY1MDlhNTEzNWUyYTk0ZTAwOWZiMGFkM2RmNjgifQ" + } + ] + }, + { + "id": "claim_acf0fb213c4a4450b2f12237615a82b8", + "statement": "Agent pool route changes or missing targets invalidate primary SSH and SFTP reuse; idle sweeping separately retires unused auxiliary SFTP connections and only closes the primary when no active exec or SFTP lease remains, while its connection count includes auxiliary sockets but not sibling subsystem channels.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1529-L1605", + "version": "repo-lines-v1:sha256:a482f8c9c2b03d8f0fb9ac7c58d33b6b066d244fd930e833ba3ce323c898af92:eyJzZWxlY3RlZExpbmVDb3VudCI6NzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQwNGM2YTlkZDY3YzA4MTliYTRkZGE5YTBhYWYzYTc1ZGU2OTYyZGQ4MDVjZTJjMjYwNDY5NjY1MDI2ZjEzZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2OTFiYmExNWI2Zjg2ZjVjOGZlNDNjY2ZjNTBmNmY5MjcyYTVmMWMxYWNiYWFhNjcyZjU5YmM1ZmNhYzE3MDgifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1607-L1635", + "version": "repo-lines-v1:sha256:568cb2a46d89fa8d7c5f2691e4a096038f7c096aa72887ce91eb25f6ea52238f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmMWZmZmIwODk3NWE2MWVlOThkY2NhMTQxODE5YjZiZjJhZTA2MjdiZmM1OThlYTBhZmVkOWI1NGQ2ZmJlMzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0MWZlNzViNTUyMjBiMTk1ZDE3ZDQ4NGNlY2Y2ZDEzZjZjOTgzOThiY2RmOWQ5N2UyNDA0ZDk3YTAzMGFlMTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzZTZlMjQ4MzhhNTIxMzQxNzA1OTIxOGEwN2UzNWUyZjFjNmNkZTk0Mjg3NDZhZGNlOWVhNmI4ZTFmN2Y2M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc4MWUzMzFkZmNmYTQyZTgxMzlhMWZjYjQ1NTZhODhlZWRiYjQzZGMzNjg3NGVkNDViOTA0ZjliZWNlZjE1YjgifQ" + }, + { + "resource": "repo://TFMTests/AgentConnectionPoolTests.swift#L200-L285", + "version": "repo-lines-v1:sha256:980a1a913322687c00ec014f1e375647f0e8af48ce3b51f765e39a36bf620085:eyJzZWxlY3RlZExpbmVDb3VudCI6ODYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY4YjY1MjMwYmYzNjA1MThkZjUyZTNjOGM5NDBkNWMyMmY1MzIwN2RmMGE5NGRlNWQ3N2FhMzIwNjAzNmIxOWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVmNDEyNDY2Y2JiOTMwZGQ5OGQ1ZDYzY2I5N2Q5ZWM0MTI0M2NlMTNhYmUyYWEyNjU2MjlmYTFiMGNlODhjNTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAifQ" + } + ] + }, + { + "id": "claim_a627b349747c4cb2964afe91f22ee676", + "statement": "Agent SFTP operations take exclusive channel leases, use optional file scheduler permits and may acquire auxiliary connections or sibling channels for overlap; acquisition can retry authentication but an already-started operation is not replayed and connection-loss SFTP errors evict the host.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1234-L1386", + "version": "repo-lines-v1:sha256:0d522e13e574b8ef5c00ed8f3dbd3f78e3e82f87134aea5b234da0050fc24c8a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUzLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJmMmFmYWUxNGQzNWFkOTMyNDZlYmI2NGJlZjM4YzQzMDk2ODk5NzlkMWY0MTU3OTU2NDc1Y2E2ZTYxNDNkNDlmIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJhMjcyMThhY2IyOTllMWRhMDk5OTEyZWE4ZTdhOTA3ZjY4NjI3MDMzZmI1MGUyZjgxODA2MWJlYWI5YmFkMjcwIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlZTJhMGYyYzdiNWQwYWYzNmM0ZDZjODU5YzM4NWQ5OWYyOTdiOWZjYzg0NDE2NGE1MDBkNWE3NjI5YTgzNDRmIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJhMTIzMjYyNTBiMjhmN2M4NDZkZjg1ZDg2YTFjNTJjNTIwYTYzNWNmOWRiMzE2NzIxYTUxNTA3Y2NhNjYxODRmIn0" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L989-L1056", + "version": "repo-lines-v1:sha256:4764e52cb2e683023092ba7f5d9c94da56dfb4f16f1ff142e91032ba5797e27a:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUwYTE1ZjYyYjQ4YzU3NTI4ZjAxMThiMzcwZGJlZDA4ODAyNDBlNTk3MzM0ZDk3ZWFhZWM4ZTExM2NjYzdjOTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjU5MThkNTljN2Q1YmU1MTgzZTMyNDhiNjhiNzhiNzdkM2JlMzkxNWEwMGVhNjA4YjIxNmY5ZjEzYjRkMWM5MDAifQ" + }, + { + "resource": "repo://TFMTests/AgentHostAuthenticationTests.swift#L701-L753", + "version": "repo-lines-v1:sha256:4dd9039bd21715f37990fd518ca73cb901c0ad62ec4f732409137e701b3123ef:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUzMDM3YWQ2ZjQ0NmMwNGMxMzUzZjE1MDM3OGQ5OTEwMmRmZjkyZmRmMmNlN2JmZmRiMTdkMjRiNjI0NGRjMjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNjMTRkOGZmOGYyYTBlY2IyOTMxZTY2NjQ5NmJlNGNjMmJhOTIzYmY3NWM5OWJiMzQ3MDc2MzBkYTY0M2I0NTAifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/concepts/ui-design-principles.json b/openwiki/.claims/concepts/ui-design-principles.json index dbaa7b60..8ed54c2a 100644 --- a/openwiki/.claims/concepts/ui-design-principles.json +++ b/openwiki/.claims/concepts/ui-design-principles.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:92110e4a68f9373b2a5339feea69ea1a11bb1fe73727dd0e4709661aa7cb595a", + "pageVersion": "sha256:0abbaadf6ae386fe26eba5e0ce8010dfc8cd8a5eba91e389977e9d5ee6c76fb4", "claims": [ { "id": "claim_3a403468456840acbfe0a524b90d5717", @@ -8,7 +8,7 @@ "evidence": [ { "resource": "repo://Frameworks/TermindPresentation/HostConnectionFields.swift#L1-L111", - "version": "repo-lines-v1:sha256:cfc4b5c8a77e75a4ebb7d6dff1d9dbc696b1f54b5191c44f27ec387a151614b6:eyJzZWxlY3RlZExpbmVDb3VudCI6MTExLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI5ZThiYWYzZWNjYWU4YmFhMzJlODZlNDBmOTIxZDI2YTEzMGJhNzRjMjNmMDIxOWE3ZDI2ZWRmNzdjMmQ1YWEwIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MCwicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlM2IwYzQ0Mjk4ZmMxYzE0OWFmYmY0Yzg5OTZmYjkyNDI3YWU0MWU0NjQ5YjkzNGNhNDk1OTkxYjc4NTJiODU1IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MCwiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlM2IwYzQ0Mjk4ZmMxYzE0OWFmYmY0Yzg5OTZmYjkyNDI3YWU0MWU0NjQ5YjkzNGNhNDk1OTkxYjc4NTJiODU1In0" + "version": "repo-lines-v1:sha256:c8f3f7ce1f96c10a867138614a48a5bfccede52e85b3a3d71bb485b3d2d1dd16:eyJzZWxlY3RlZExpbmVDb3VudCI6MTExLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI5ZThiYWYzZWNjYWU4YmFhMzJlODZlNDBmOTIxZDI2YTEzMGJhNzRjMjNmMDIxOWE3ZDI2ZWRmNzdjMmQ1YWEwIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MCwicHJlY2VkaW5nQ29udGV4dEhhc2giOiJlM2IwYzQ0Mjk4ZmMxYzE0OWFmYmY0Yzg5OTZmYjkyNDI3YWU0MWU0NjQ5YjkzNGNhNDk1OTkxYjc4NTJiODU1IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MCwiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlM2IwYzQ0Mjk4ZmMxYzE0OWFmYmY0Yzg5OTZmYjkyNDI3YWU0MWU0NjQ5YjkzNGNhNDk1OTkxYjc4NTJiODU1In0" }, { "resource": "repo://TFMTests/ArchitectureBoundaryTests.swift#L109-L136", @@ -94,19 +94,19 @@ }, { "id": "claim_46e2a269c939465d9438906f630d5ee3", - "statement": "Shared Host organization/profile/connection fields bind to each platform's local draft; desktop nested edits stay in the Vault work column while mobile uses an editor sheet with its own dirty-state, validity and save policy.", + "statement": "Shared Host organization, protocol-profile and connection fields bind to platform-owned Host drafts; desktop keeps nested editing in the Vault work column, while mobile presents a draft-backed editor sheet with its own route, dirty-state and save gate.", "evidence": [ { - "resource": "repo://Frameworks/TermindPresentation/HostConnectionFields.swift#L6-L111", - "version": "repo-lines-v1:sha256:21e2c33e64294fedef351ebc371d67340cab0362a768accf66778255d01645fb:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJkZGRiMTRiMzgzMzAzNjRhZDk3YmViODY5NWVmYzMyYTFjMjkwZmUyYzk3Y2EwNjAxZmYzY2QzNzhjYTVmMTI5IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0MTJjYTM0NWNjZjc1YmY5YzA4MDZiY2U2OTViZThkZTgwOGI3OTk4NDI1MWE3YTU0ZDIwMmNmNjEwMWRkNDUxIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJjZGEzMTJmZTE1NTcwNDM5MzM0YmM5MDBkYjQ0Mjk1MzYyZjM4OWY1YzZlZDhlNDE1YjgyMmMwZjdmMDQyYzQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MCwiZm9sbG93aW5nQ29udGV4dEhhc2giOiJlM2IwYzQ0Mjk4ZmMxYzE0OWFmYmY0Yzg5OTZmYjkyNDI3YWU0MWU0NjQ5YjkzNGNhNDk1OTkxYjc4NTJiODU1In0" + "resource": "repo://Frameworks/TermindPresentation/HostConnectionFields.swift", + "version": "repo-file-v1:sha256:c8f3f7ce1f96c10a867138614a48a5bfccede52e85b3a3d71bb485b3d2d1dd16" }, { - "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift#L27-L79", - "version": "repo-lines-v1:sha256:989c495bfd26d21f97f26434e923b8a5d77420e8b42a8e631b0c6d640d69fea6:eyJzZWxlY3RlZExpbmVDb3VudCI6NTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZlMzA0ODhhNDJjZmI4Y2M1YTgzMjM2YjRjNmM0YmE4NTg3YTY1ZDlmNWZhNDUyZGE4ZjY2MzhkMjhjNDZlYmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBkNmFlZmJiYzE2NGE0NjBmMTYyMDM3M2FmODUzYWI0Y2I3ODUwNTk3YjY5Y2UxNWQ0NGI1NjI4NjdjNDhmMGEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjAxZGQ3YmJmYzM4MTU4YTI1YWNiMmUzMWU5NWZjYjdkYjFlMDRiYTA4ODg3ZDBhZWM2ODVkMzNhNDQ2Y2E0OWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImM2YWU5ZDE5OTIwZjMyYWQ5Yjk0ZWI3ZmYzNDk4ZWM5ZWY4ODBlMDEwYjZkNWUyZDgxNGQ5ZWQ0NmNiZTdmN2MifQ" + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift", + "version": "repo-file-v1:sha256:d2792158c62c3eecca3fef18c90e4eb26e3c51ec782431baa50bf2277e7f3e27" }, { - "resource": "repo://TFM/Features/HostEditor/HostEditorView.swift#L8-L100", - "version": "repo-lines-v1:sha256:49673a299a1dad2236e522503b138500311be62416728477bb1efaf1b282477d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQ3LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI5N2NkOTg0OGYyZGNmNDNlY2ZkNDBlZTg2MWQzY2UyNTllOTY0MTAwMWQ3ZTYyMDQ5NjdmMDMxNDA2NjU2NjQ3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiIwODg3NTE1ZTM4MDRiZTNkYmRlN2IyMzZjYjFhNjdmYTg4NzEzZGFjMjUzNzhlODY3MDdmMjRlZjA4NTA0NDc0IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJjZGEzMTJmZTE1NTcwNDM5MzM0YmM5MDBkYjQ0Mjk1MzYyZjM4OWY1YzZlZDhlNDE1YjgyMmMwZjdmMDQyYzQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIyYzUzNDhhNzI5ZjIzZjhjNTExZWYxM2FiODU5OGI4YzFmZmJmMzk2ODA4ZTY5OGFhMzkxZDk4ZWJlMjA0NzhjIn0" + "resource": "repo://TFM/Features/HostEditor/HostEditorView.swift", + "version": "repo-file-v1:sha256:a71a870383335276f0190eb1f90be657a7ce100f5ad68ec0fb6bb067fbbcd499" } ] }, @@ -160,7 +160,7 @@ }, { "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L75-L180", - "version": "repo-lines-v1:sha256:7029c2d16c93e885407ee0ac5dcf872a2cf816cf64cf5a6e1c2f1468bc6a7609:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIwMWJhNDcxOWM4MGI2ZmU5MTFiMDkxYTdjMDUxMjRiNjRlZWVjZTk2NGUwOWMwNThlZjhmOTgwNWRhY2E1NDZiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJhMGE4ODZkMjJlMjhmYThjZmFkMzg2ZTUzMzlmN2JhNGFmNDEzM2U4NGRmMjU5YTYwNTNjNjJiMzI4ZjQ2Y2U3IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5M2IxZTE2YzVlMWYyNGI4Njc3YzQzYjI2ZmYyMGI3ZDM3MGE2OGIyMWIwY2ZlZTA3NmQ4OWNlNmNjYmEwMmFmIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJjMTNhOTQ2OThjNjNhZjM5MmJkMWI0YTZkZWIwZWI5ZjdmYzFlNWVjZTQ0MGM1OTU3MTdkYmEyYjM2ZGJjYTU4In0" + "version": "repo-lines-v1:sha256:183c09e20a2fe787af9ee1eb4e3bcc40d84b9789653fde93b7209b166ef6cc10:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA2LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIwMWJhNDcxOWM4MGI2ZmU5MTFiMDkxYTdjMDUxMjRiNjRlZWVjZTk2NGUwOWMwNThlZjhmOTgwNWRhY2E1NDZiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJhMGE4ODZkMjJlMjhmYThjZmFkMzg2ZTUzMzlmN2JhNGFmNDEzM2U4NGRmMjU5YTYwNTNjNjJiMzI4ZjQ2Y2U3IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5M2IxZTE2YzVlMWYyNGI4Njc3YzQzYjI2ZmYyMGI3ZDM3MGE2OGIyMWIwY2ZlZTA3NmQ4OWNlNmNjYmEwMmFmIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJjMTNhOTQ2OThjNjNhZjM5MmJkMWI0YTZkZWIwZWI5ZjdmYzFlNWVjZTQ0MGM1OTU3MTdkYmEyYjM2ZGJjYTU4In0" }, { "resource": "repo://TFM/App/RootView.swift#L342-L351", @@ -182,7 +182,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift#L512-L544", - "version": "repo-lines-v1:sha256:b41d3de43fde9c50d0b478946d6263804791efe4519784713c872a1679a205dc:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" + "version": "repo-lines-v1:sha256:b0fa484bcb19ae7f887f203d3b438c9bccc7b5936706cd85d285e53c0f9b31d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0NTg0ZDFiMmZhZDA3YjA0ZTIwZTVjOGE2MTM3OGEzNDFjZGJlN2E4ZDgwMzAwZDQ2NzJlNjhhYjcxZTFjZjMifQ" }, { "resource": "repo://TFI/DesignSystem/MobileContentRegions.swift#L138-L163", @@ -208,7 +208,7 @@ }, { "resource": "repo://Frameworks/TermindPresentation/Terminal/TerminalFontFields.swift", - "version": "repo-file-v1:sha256:c119424e412062df06cd4a3ca4acfe9f5825e21f042ae615f7c62979f24ddb8e" + "version": "repo-file-v1:sha256:fe42abfe804da005ade77a8873f0196fc7c539b34d6397fcc1f1b71766d11749" }, { "resource": "repo://Frameworks/TermindPresentation/Terminal/TerminalFontPicker.swift", @@ -216,7 +216,7 @@ }, { "resource": "repo://TFI/Features/Settings/MobileTerminalSettingsView.swift#L6-L27", - "version": "repo-lines-v1:sha256:db0f6ac319ebe6e659670cb3fd3961daab53fc6bb6cca98bd301196b4a94cb2c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlZWQ0ODIzYWM5OWFkMjBjNDQ4YTY5NTNiZDAxMDI0ZjhmZTNiZGE5YWE4Nzk4NTI3Yzk3MmVmN2I2NzRiNGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdmODMzMmZhOTk2MTExMDJiYjgyOTEzYTZjMDFlYWU5N2Q3OTMyN2JlNTViZTY1ODYxMDM3Y2Y0OGRmYWQ5MjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjODk1ZjdlZDQ0MWRhOTBjNGEwMzliZjFkNzg2YWYzMjg2YmY2YmZjMjgxZjM3ODQ5MzIzNTczNjk4M2YzYjMifQ" + "version": "repo-lines-v1:sha256:f318db7e58e16b49c51697738acb5c9f01dd3ed4b82431898a5ff6ccbd86e50c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFlZWQ0ODIzYWM5OWFkMjBjNDQ4YTY5NTNiZDAxMDI0ZjhmZTNiZGE5YWE4Nzk4NTI3Yzk3MmVmN2I2NzRiNGEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdmODMzMmZhOTk2MTExMDJiYjgyOTEzYTZjMDFlYWU5N2Q3OTMyN2JlNTViZTY1ODYxMDM3Y2Y0OGRmYWQ5MjIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdjODk1ZjdlZDQ0MWRhOTBjNGEwMzliZjFkNzg2YWYzMjg2YmY2YmZjMjgxZjM3ODQ5MzIzNTczNjk4M2YzYjMifQ" }, { "resource": "repo://TFI/Platform/TerminalFontCatalog.swift", @@ -224,7 +224,7 @@ }, { "resource": "repo://TFM/Features/Settings/SettingsPageView.swift", - "version": "repo-file-v1:sha256:0c4e6f0881eead2da90bc782396a7c7c069a85a6ede7f2f4fdd23bc6233ecb1a" + "version": "repo-file-v1:sha256:5758c713210354b4146d35075de36a9650a9acd0025e9fbdfefbc5e2db82d3ed" }, { "resource": "repo://TFM/Platform/TerminalFontCatalog.swift", @@ -255,24 +255,24 @@ "statement": "TerminalThemePicker retains missing, empty or wrong-appearance selection values with a localized hint while the renderer chooses an appearance-specific fallback without writing preferences. Rendering applies base theme, custom overlay and local typography in order; the base picker remains editable with overlays. Desktop custom editing autosaves and imports files, while mobile explicitly saves a draft sheet.", "evidence": [ { - "resource": "repo://Frameworks/TermindPresentation/Terminal/TerminalAppearance.swift#L60-L96", - "version": "repo-lines-v1:sha256:4913d1b987cc2081c776971d909d256779a51d26723c42bad5ae9e09e5a30e02:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwNTEyZTQ4YzcxZWY3NmY3NDdmZGQxYThmYzZiMjlkMTQxZWM0NTA5ZTllNzMzMmQ4MzNjYjdmOGU5MzIzZjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkxMjg4YmU0Y2U3ZTdmMDAyNTdiODBlMmY2NGI1NGY3MjNiODBjZGYwNmFkZThmYmQ1ODhmYTg0NjkzYjc4ODEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRmYzUzMjljZTc1ZGEyMmZhOWIzODhiMDVmZmQ5NjhhZTg5YmQ1MzRiOTg1ODFlOTFlOTg1OWUyYTE1OTAyZTEifQ" + "resource": "repo://Frameworks/TermindPresentation/Terminal/TerminalAppearance.swift", + "version": "repo-file-v1:sha256:c2028ccf99f366328201299e762fa706e35c04c72aa8434b6bb44608e0761ca9" }, { "resource": "repo://Frameworks/TermindPresentation/Terminal/TerminalThemePicker.swift", - "version": "repo-file-v1:sha256:1531a49920dd29ec27794a8c0113cd62601cb025e9263e1714942238c2dc106c" + "version": "repo-file-v1:sha256:c176d88acd7707b28fc4a829b43c3cf6d21f5a8409f25d781577cf6c539c82cd" }, { "resource": "repo://TFI/Features/Settings/MobileTerminalSettingsView.swift", - "version": "repo-file-v1:sha256:47527034489c9cedc0dc531e2524553e5e6f4bcfaae73233f3ca5833d5299180" + "version": "repo-file-v1:sha256:697847e04d47b8b2778aefe44d33faf3b45719383c7bf550bbb68d3255c91b1a" }, { - "resource": "repo://TFM/Features/Settings/SettingsPageView.swift#L680-L726", - "version": "repo-lines-v1:sha256:49d4b62cae29977d89d76b80a4c2a92de212e127217474382144e30452d744bc:eyJzZWxlY3RlZExpbmVDb3VudCI6NDcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQyZWYyOGVjNTZhMzkyZGI1NDEzNGI2YzBmYzVlN2QyM2QzMDNlNjIxMzFmMDA0ODMzNWE2ZmE0M2JkZTUwYmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwZjY1YWFhMDIxZWI3NTc1YjZmNWIzYjc0OWM1ZTk2N2FlNTFkNDZlOGQ1YjYwN2FlNDJmZTdiZTkyYmMzMjgiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjljZWYwZTgzNDcyNDgwMWQwN2I4N2YzZmY3YmYwNTAzZjBmZGRmODlmZTQwNGMxNTUwMGM4MWY0ZGRmOTI1NjIifQ" + "resource": "repo://TFM/Features/Settings/SettingsPageView.swift", + "version": "repo-file-v1:sha256:5758c713210354b4146d35075de36a9650a9acd0025e9fbdfefbc5e2db82d3ed" }, { - "resource": "repo://TFM/Features/Settings/TerminalCustomConfigurationEditorSheet.swift#L88-L149", - "version": "repo-lines-v1:sha256:a9895ec2bcad6c2f2ae96c2e28c6012a07a88f8c59aa87e94762f84f17277032:eyJzZWxlY3RlZExpbmVDb3VudCI6NjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY5NjY2OGNjZjFjZDBlYzYwYjE1YjY2MDEwZTBjZDJiZjJiNjgzNjA4NmFiYzM3MDgyNzY2YTU4NzdkMWM5NDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc5NmRiNmJiZmE2NTc0MWZjMjUzNGZhNWE4NzAyM2JhZTY1NTY1M2NmZGQyYzdmM2Q1YzRkMmU2MTYxYjA2MjkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + "resource": "repo://TFM/Features/Settings/TerminalCustomConfigurationEditorSheet.swift", + "version": "repo-file-v1:sha256:81c17619a61afda1bce2d52d47ca85416b0ecb9af055a8e591b5593a8738aa71" } ] }, @@ -299,12 +299,12 @@ "statement": "The Sidebar mode rail shares one glass capsule with neutral animated selection, explicit selected accessibility traits, Reduce Motion handling and key-window focus outline; the Assistant footer groups interactive New Chat/Archive glass controls on macOS 26+, using neutral Archive selection and a semibold primary glyph.", "evidence": [ { - "resource": "repo://TFM/Features/Assistant/AssistantView.swift#L81-L130", - "version": "repo-lines-v1:sha256:851c5a4704e41df47e9500fba2300c125f45b4e02dfb2939f29148a6e857e26f:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMjA0MzJkYzQ3NGFmN2VmY2NlYmMwZTQ1ZDAzYzIxYmM3OTY0ZWMzZWY5NDE2Zjg5NmRlMDVlNmM0ODAzMzQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhhZjI4MmYyMDg2ZWI4ZTZmYTJiMDdmMGY3NzBmYmE2M2UzZWFmOTY2YzE0Mjk1NDg0NWFhYmQzODMxYTRiMDAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImI0YTM2NWE5MGVjMTFlOTA0MzI3NTJjZjkzNzZlYzVlZDM2YjgwYmE1ZThlNjg1NGZjZjk4OTcwZDMwNDQ0NjkifQ" + "resource": "repo://TFM/Features/Assistant/AssistantView.swift", + "version": "repo-file-v1:sha256:b5f2848d1ec5b805462acf73134e0af907ae7845501b70c3f11761a32cfb0553" }, { - "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift#L38-L94", - "version": "repo-lines-v1:sha256:cfbd8237ba2ca4f4797b4bba5216aced08897e568ba2875816a470bcd4ae3da3:eyJzZWxlY3RlZExpbmVDb3VudCI6NTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZjNzM1YTQ1NTZjMmZkNjgzMmVlZTgyY2Q4Y2MyYzM5MzA0YTAxNjdmNWZkMTVlNTgwYWI1MzRiNzQxMmUyZDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjFlNThhYjBjNDdiN2Y5OWVkOGM1OGM1Yjg2Njc2NWU3MDQ4YTZlZWI2YmJhODExYzRmNzcxMDk1ODZlMzQ2MWUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEwYmUyNzE1MDFmNzVhZWZlNjgxNzFmMTU5MjZlMGUzOWFkYjM4NmQyZjMxNjU2YzM0N2UzOGJlNDhiMDY4YTMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJiODlkNTljMjE3MGEwZWFmOWY0NDc2YmVjMjRjOThlYjdlYTRiMWNlYTY4ZDQ5MmQ2OGNkNzAzOGZkNDE0YmQifQ" + "resource": "repo://TFM/Features/Sidebar/WindowSidebarView.swift", + "version": "repo-file-v1:sha256:6c3b55dff7d302c6c87b804a2dde9aaf9de4941747f65049ddbc6d1ba6e8d672" } ] }, @@ -313,12 +313,12 @@ "statement": "Desktop single-rule forwarding menus group Address and SSH Command in a Copy submenu, while mobile exposes flat copy actions before Edit/Duplicate; both use native pasteboards, disable unavailable SSH-command copying and leave forwarding execution to separate actions.", "evidence": [ { - "resource": "repo://TFI/Features/Ports/MobileForwardingView.swift#L80-L96", - "version": "repo-lines-v1:sha256:eb7629f74c17d9c10936b2914f483e553754a07ac0ca69a9bcd6e00ef110c801:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY2NjgzMDMxZjE3ODk4NTBhNmU4M2UwNmEyMGM5YzFhZDNmNzM5ZjcwYWRjYTZlODQxM2M3YzBmMTgzYmJmNmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNDRlMGU1NmVjNzE0ZmQzMmY3M2M0MTYyMjg4ZjY5YmMzYzc4MGIzZGM5Yzk4MGExMTUxZDBlN2M5YzEyYjQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI5ODI0MWFjMGE4M2I1NDZmM2Y0Y2M0YjdmZTE5NDJlMjM4MzdlNDIwNjM1MGEyMDAzNDM5YWUzNzg2YWM2YWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE1YzhkZmE3ZjFlMGI4MTkyZGRlNmVlODc4NDc3NmFhZjYyNzk2YWI5MjM5OTU5YTE3ODE2YzQwOGE3NmM4MTgifQ" + "resource": "repo://TFI/Features/Ports/MobileForwardingView.swift", + "version": "repo-file-v1:sha256:95018dc2360759c42e609df416a46361413accd1818726e824ec1a3e736b2aad" }, { - "resource": "repo://TFM/Features/Ports/PortForwardingView.swift#L59-L80", - "version": "repo-lines-v1:sha256:0bf89175a0a781274cada4a8fa227ae456a38774c7d7ee3701e1e9513e081cf6:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIwMDIyNWJmYTIwMTYwY2UyNDE2ZDJjNzU0NmZiZTFkOTNmYzJmZTM2YjUyYmNhMWIxYTBhMDg0YzhkY2VhOTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYyNmE1N2EzYzNkOGJiYmJmYWJlMzkzMjJkOWM2ZWM2OTkyMmU2MTNlMWM1YThiMTY3NTFmYWZkYWZhNmU4MDQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA0ZmNmNDBlNzlkNDZkMTFjYjJkYmJkNjVjMzczZGQzYTFlODFkYTI1NjI4NTJhNDAxYmZiZDNlODNkN2ZkNWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFjMTgxMmU5ZmQwYWY4ZTMwMWVlMTYwYTNjOTJiOTUwYzQxMDE4YjVlYjA0ZDkyMTdjYWI2MzU1OTQ2Y2I3MGQifQ" + "resource": "repo://TFM/Features/Ports/PortForwardingView.swift", + "version": "repo-file-v1:sha256:d7b009e88acd4d7cbb688a5baf212f85632617d62863ce909c860da83125024e" } ] }, @@ -327,26 +327,310 @@ "statement": "Desktop and mobile Snippet cards expose one Run action instead of a separate Execute on Hosts override affordance; target selection and destructive-script confirmation remain owner-controlled, with desktop filling missing targets and mobile choosing hosts when no valid targets remain.", "evidence": [ { - "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L290-L303", - "version": "repo-lines-v1:sha256:82d7c71fd2cd54e76ebcee778a9240568dfb90e96a4e2a3af555591257aefe56:eyJzZWxlY3RlZExpbmVDb3VudCI6MTQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY2NjgzMDMxZjE3ODk4NTBhNmU4M2UwNmEyMGM5YzFhZDNmNzM5ZjcwYWRjYTZlODQxM2M3YzBmMTgzYmJmNmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZGJmOWM0NWEwODdiYTA3ZDkwODE5OTFlNGY5ZTNmYWU3ZWZlMjM5Yjk0NGViYWQwYWNlODc1MGE2NmEyYzciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgifQ" + "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift", + "version": "repo-file-v1:sha256:877ba966713da9e0c3d45559ccd607112baff1aecefa4d9e50440b33e90c4cc1" }, { - "resource": "repo://TFI/Features/Snippets/MobileSnippetsView.swift#L356-L380", - "version": "repo-lines-v1:sha256:a275fa91f09b523b4aafa93db152698586c8b779785492b6f16cabf5626e666a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE3ZTg5NDNmOTczODlhYjlhNjEwODVlYjRmNTEyNmFkMWFmNjQ0YTcxM2M0YzQ2MWU3ZDEyNDZiYmFjNjEwMGIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiOGUzOTMxYjNlNWEyZjhmNGU2NWM4NTk2YWQzMzYxNDc3NjY0YjAyYzM1MzFiYzg5NjQ3NGE3YWYxYjdjZTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE4Zjg1NDZlNDMzZDc4NjQzODA2NmJjNjllMDg1MGZlNWIyNjU3MDBmYzBlNDM4ZGU4MWRiM2ZjMTJiOWM0ZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjM4MmVhMGU5N2Q0OTc1NzRlNWI1ZmQ5ODQ1NDU1YWRjNTVhYWE0MWQxMGI4MzMzNGNmNGJmMjk5YjdhYTY1NzgifQ" + "resource": "repo://TFM/Features/Snippets/SnippetsPageView.swift", + "version": "repo-file-v1:sha256:8d4e7573123311fc852fedc7357d0ed3a74a2b55cd642c1476bb4d019640d8e9" + } + ] + }, + { + "id": "claim_ab4d8bbea4064122a957904114cad55f", + "statement": "Mobile Host cards activate through scene routing on tap, while their context menu groups protocol-filtered SSH/Telnet/SFTP connection actions separately from Edit/Duplicate and destructive Delete; even a Host with no enabled protocol retains editing and deletion actions.", + "evidence": [ + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L16-L44", + "version": "repo-lines-v1:sha256:3fadb0523a363711191ac025b2a2be70dca696c5d1189ef587e89c1687da7ecb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZkZmUzZTM2OTM5MTg5ZDg3NGU0NzlhZjFlYjJhNjg1OTY4Y2M1MDg0YTM2MDYwMTcwM2E3NjU2ZmZmYTdjYWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNhMGQ4NTMzZDViNDMxOTM5YTVlZGI0MzY3N2Q3NjYyYTU0NWM2MWIxNjNlOWI4MzFjZWI3ZGZhZGRmYzVkYzYifQ" }, { - "resource": "repo://TFM/Features/Snippets/SnippetsPageView.swift#L302-L326", - "version": "repo-lines-v1:sha256:6a4e35d060bf8c3af98a6bcafa7f2c3af3d2919dc77bbf40cddfec56f83474eb:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImYwMDE2OGQ4OTkwNWRjZWRlZDQ4OGFjOWE3OTg3ODA5NjMyYTMzZWZmYzE3MmZmM2UzMDQ2OTkwNmJmNDRlZTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImJhMDZhM2U3N2M4MzgzZTk4YmE3YTVkZDUzN2I1Mzg4MTdhMDFkNDZlOTAxMGUyNzEyNTgxZGFmZmFlZjYwOGIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjU5M2IzNWRiMDFmMTgyYjgzY2VkZWQ0MzM1ZTY4OGZhZmVhMzAxZjBhNzJlNGIxZGYyNmMwZDU0YjU5MThkMjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNkODg0YTQxZDNiYmZhN2E0MzAxZjdjMzExZGE3OWE4YThjNmU1YmI3ZTljYWFlNjc3M2RiOTM4OTMxMjg4NWIifQ" + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift#L767-L834", + "version": "repo-lines-v1:sha256:76b7cb173f7633d307e7f14d3725dbcd4d31003375122a62624beac5ae94cd9c:eyJzZWxlY3RlZExpbmVDb3VudCI6NjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyMTExNDcyZWQ0MmE0NDkxZjc5OTQ0MzNjMTM5ZTBlY2M3ZTczZmZhZjI4ZTZlYzIzZDI3OGIyMmRjZmYyMTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjkzOTgxNDU1ZTQyYTZiNzRiOWU5N2ZiYTY0MjM2NTQxM2Q4YTNlOTJkY2JlNjU5NjY1ZDUyODA0OGExZmU0MjEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYzYzUyYWM5YmUwN2MwNzljNTRhZDgwOGMzNDEzNDMwMjFmYmM4M2NiZDVmZDk2ZGNlZTk4MGY4YTI2ZTU4YzMifQ" }, { - "resource": "repo://TFM/Features/Snippets/SnippetsPageView.swift#L458-L466", - "version": "repo-lines-v1:sha256:9601001fe4af32f37a89a620b06175d054106430cb8d592abab3542ee6f56bc8:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiY2IzZWIyODgwNTgxMGU0OTgwMjE3ZGJmMmJkMjNhOWM5M2Y4ZTFiZjAyMDdkZGVlOThmZDlhNTQ1ZTYxMGRjOCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMTkxMmRjZmY4ZDViM2RiNmEyNjY0NGE1ZTVlMTA0MzBmNDhkNTBmYmM0Y2U2MDYyZjEwNDY2MjQyMDEyOWMyMSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZWUwY2ViM2FjNjViZDYzZTdiNTI4NjE1YzM5YzMxMTNlMTUyNWY2MzY0YjliMjg2ZGNiYjI3YjI4MWZjMzdkMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNzE1MWE5ZGJhY2E5NmQxYjg4NjU2ZTM0YTgzMjVkNDRhNjAzZjhkYThlNjE3ZjNiZjdmNDMxMTY2YjZhMzIwNSJ9" + "resource": "repo://TFITests/MobileVaultFeatureTests.swift#L33-L68", + "version": "repo-lines-v1:sha256:1ea05d84f5bbde850a612da2de508f4c2c278de3fd5ce0ee1710e12e4ecfa25d:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgwNzEyOWY5ZDgxMzg1NTc0NWI4NDZhM2Y5MDNhZDRlOTk2MmIwMTJiMGVmZjdhNGM1MjI0ZTAyNzVhZDBjYjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI3OTE4NTE4YmYyODg1NTFhYWVkOGRlMzU5YTQ1NTQwNWUxOGMxYmRjMjEyNDgzMGI5NjA4ZmJjMjU0MGI2MWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE0YWIwODlkMDRjOTQxYmEzYTg2NGI0ZjEzODE5NDM5ZmNhZjk1MTgyNjk5MjdlZTZkYjQ3Mzg5OTNjNDc2ZWQifQ" + } + ] + }, + { + "id": "claim_8a3f0b8c06d3430e91e49ebc6ef5862a", + "statement": "Host menu operations remain platform-owned: the mobile card delegates connections to its scene callback, edits to an editor draft, deletion to confirmation and duplication to MobileAppModel, which assigns a fresh ID and strips Host-custom identity references; desktop HostContextMenu has separate Quick Connect, Connect and Copy SSH Command actions.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:846cccb0bc643b8f8c6c54dc70c1928a29218a885598274f1ef689e239b1aa80" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift", + "version": "repo-file-v1:sha256:19fc7789a96e909c77b51a2b1149d8ce29449c22068fd0084b19e8a286a64d06" + }, + { + "resource": "repo://TFM/Features/Hosts/HostActions.swift", + "version": "repo-file-v1:sha256:91019e1a233737662d6cc3576b3ad19c075827060cd9e3c5e798f38aada6f64b" + } + ] + }, + { + "id": "claim_c2ee425a34ea40289406fca0d3b64f0a", + "statement": "MobileRootView binds the selected destination to a scene model and preserves one NavigationStack per registered feature inside a sidebar-adaptable TabView; adaptive tests assert the same native tab controller, five available tabs and scene/native selection with visible titles across compact and regular sizes and language/Dynamic Type variants.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileRootView.swift#L110-L118", + "version": "repo-lines-v1:sha256:b041a5d2b709e696a2ca470b6ad5af3b2ae30da547be4fc0b5cbb2e206bcfaac:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1ZWU4NTA4ODhhMjdhODRlNTc1ZTBiMGIzN2Q3YWI5ZGFjMmE0ZGQ3YTE2ZWE1ZWM5NTkyNTdlNDRmMTJiNyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTYzYWE0YWM3N2U2Y2I1YWNlMjZmOTZjNjA1NGRmMmFiOTc1OGU4YzY3NDNmNjU2MjQyNzI1ZTNhMjRkZjQ0YyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjEsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiNDEyY2EzNDVjY2Y3NWJmOWMwODA2YmNlNjk1YmU4ZGU4MDhiNzk5ODQyNTFhN2E1NGQyMDJjZjYxMDFkZDQ1MSJ9" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift#L28-L40", + "version": "repo-lines-v1:sha256:c77852cad0f3f351d8578c25f73cc6b2f69300d496c4c48d8d3b58b497fda049:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc4MGM2OTYyYmY5ZDg3ZWFlM2QzNDZiYWE1NGNlYmJkOTc5ZjBhN2RjNmIxYWUwMjk5ZDZkNTlkNzNjYzZhYjEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ0ZDhiNmFhZTdkZTg4YjQ5MzJhMjFhNWVmMTMzMmFiYTEyZmNhYTA2NWM3OWQ1OTJkYjczY2JhNTU4MGNkMGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBmYWJhZWJmNDA0MWQyNTAwY2U2MDZkNmFlZjI0NDdiZTFiMjg3MWIyMmQ5NjExOGFhY2ExYWIwMjkzMGU0M2EifQ" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L131-L176", + "version": "repo-lines-v1:sha256:9ff692e72ae5bc6ec980c25f35b1b34b7926bd49ab3afaf1930f3316bdd7bf13:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRlYmZhYTQxMjcwNWM3ZGQ3NTg2ZTI4MjcwZTJiZmJiODBmMzNlZDMzMjRkMWVkYzZhZGVlMmZhYmY1OTc2MDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2ODYwN2ZkMGY0M2NjZDAzZDU2MzZhMWFlOWJiNWVmMTEwM2YyNmQzZDQ0OWI1NGMwNTEyOTk2NGQ3NjYxMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmNzU0NTFmY2MwMTA4Y2RmYjZjY2U0NGMxNDAzMTExOWRkNjdlODYzYmUyY2ZiZGY5MTA4M2UzZTc2MTQ4NGYifQ" + } + ] + }, + { + "id": "claim_3fa9e5047d7e442dae2a3803e6d5e384", + "statement": "MobileContentRegions subtracts active obstacles and uses a usable division only when both regions fit; MobilePaneLayout retains the same native children and last usable size while Assistant and Metrics gate obscured panels' hit testing and accessibility along with visibility.", + "evidence": [ + { + "resource": "repo://TFI/DesignSystem/MobileContentRegions.swift#L140-L163", + "version": "repo-lines-v1:sha256:6c7bfff69a0f5f05b3085739d58b417da13a30af67c07362d355324d216ce450:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAzOWVmOTE2NmEzODI3Yjk1NThkNGRkZjczNjJiZDZiYTZhMjdiZDdlOGJmNzBmYTUxMWQ5YmRjZWEzODNhNTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + }, + { + "resource": "repo://TFI/DesignSystem/MobileContentRegions.swift#L21-L50", + "version": "repo-lines-v1:sha256:394d11666b5b3ae81204b86b43f4abccca062ae9169db4c326a327cd145cd15a:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVjYjEyZjVhYWMxZGFkMTVjZmQ2ZGQ5NmJhOTM0YTg1NjgzN2M2Mzk4N2MzYjBmYWZhMmM3NzU5Yjg5N2QwNDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM4OTVjMjI5MWNjNjQwODQ3NDc4ZjI2OTI0YjMyMjEzOTJlN2E1ZDc2ZmI0ZDRjNGRjMDMzNTEyMGU0MDU2N2YiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE3MzVlMmQwZjUwMzIyYjhjZTMxZGUxYjAyNzVjNDI0NmY3ZWYyMThhOWE2YzMyZjdkOWJhMWRlNjRlNWZlOTcifQ" + }, + { + "resource": "repo://TFI/DesignSystem/MobileContentRegions.swift#L93-L105", + "version": "repo-lines-v1:sha256:f26bb0948378327d38f13fb61f4f464c5c7b3f972c66cddd9a47bb1a49b20e3c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA3YjcxYjVlODAyNjcyYTA5ZTY0MGRlY2JiZTg0YzU1YTQ5ZTc0ZjRhZjMwOWNhZjFkMGIyN2U3NzdlYTc3OWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE3OGM3Yjk1Y2ZmNWI1ZWQ3NTEzYTkxYTMwNjZjZjI5ZTkzZDZkMzhlNDE3MWExZTIwMTczN2U2NzNjNzI4YmMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImYyMjUyZWUxMGNiOTI5NmYzNmQ5YWJkZDg0YzBjNGM2ZTQ5ZTE1NzM3MzM1N2ExYTA1YTZmYmQ0Y2MzNmUxYzEifQ" + }, + { + "resource": "repo://TFI/Features/AI/MobileAssistantConversation.swift#L470-L511", + "version": "repo-lines-v1:sha256:9866105509e309d9b6680eef99546a827a3050856da5d6fda59968a68500da0f:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc1OTA0ODUyMzg4MjVlMWRlYTYyMjQxNmU1M2Y4ZGFiOWVkODQ0NTAxMDc4Yzg2MmRiMjU2OTAzNTY5YmNhNjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MjJjNDJjZDE5YzZkMDNkODA4YzQ1MjcyMDU1MjgyNWI3ZWExYzViNDkxYjIxODUxMWNhYzc0MTVjZjlkOWIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk0ZTFlNWJhMDRiZDMwZjMwMDA3ZjY1MTJkNWM2MzRhOGNiMDRjMzJiYzFkM2EyYTY3ODM0YjY5ZTJiY2Q5NGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjllMDM4ZjMyM2U0NzlmYzZiOTU5MjM5MjY4ZTQ0NTFkY2ExYjA4MzA4NzQ3YTU4ZmQ0N2Y2Nzc4ODM3ZjY2NWUifQ" + }, + { + "resource": "repo://TFI/Features/Metrics/MobileMetricsView.swift#L106-L120", + "version": "repo-lines-v1:sha256:61c6af742805e51a8094f6052f8e29319e9971aab24d664ef139a75a2aeafe75:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NjY4Y2Y2Nzg3N2Y3NmJjZTA1NTBmZjNkY2ZkZDFmNTIxZmZlMDJkODQxY2QwOTM1M2U5ZjAyYzc5MTk3MDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQxY2NiOWNjZDY3Nzk3NzMyYjFmMmI1MzU2OWJiY2ZkMDBjZjFiNzNiYmUzYzgwMDI0YTMyMDY3MGM0MDU0ZDIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ1ZTY0NmYwYjUzYzFmMjg5YjI3NTMyZTA0OTY0MDliYzg2NTUyNWYzOGJkYzYzYzlkZDQ3ODZkNGY0ZGJmZTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZjZThkMTM3ZmE0NGFjNjY0OGIzYTRhNmY1NmY1MGJhYmE2NzczNDE0NWQwNDc0YTRlNTU1Njk3ZmQyNmJlYzgifQ" + } + ] + }, + { + "id": "claim_e58a3c28e3d34e9c9cd8309816ca6579", + "statement": "Adaptive mobile tests check native continuity, not just displayed text: Metrics list identity, offset and selected page survive folds and vertical-menu transitions; Assistant transcript, composer focus and marked text survive divisions/occlusion, and search, editor drafts and in-flight save feedback survive width changes.", + "evidence": [ + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L12-L113", + "version": "repo-lines-v1:sha256:562405259f47a1b1e23a9f9339e97729854a2cb3658363c7a787c217db2f2630:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0YzkwYTI0NTY5MDhkZmI0OTM0YzE5MzMzMWU3OWE2ZGE1Mzc5NzhjNGViZDM2NDcwMGM1NWE4MDNmNWU0MTU3IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJhOGNhYTE2NTAxNjE4NWE1ZDE2MDlmNDAwYmQ2MzIzNDI2ZDllNjQ4NjY1MTBiMjQ2NWY1Yzc3MTdmMWIzYzQ5IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIxNzU5YzJiZWIwYWJmMDQ3MDNjMTc0OTExZjkyYzNjMjU4ZGYxOGZkNTkxYzYyMWM4ZDc0NzRlZjJiYzU3NmYxIn0" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L449-L607", + "version": "repo-lines-v1:sha256:2522b7741b6de9f7e63a84e33fd8772741f6891f9adaa024ed92d247971b0f9c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTU5LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIxMjEzOTdhZmI1ZTM0YTVjNWMxM2NjOGRmMzJjMWY1YjEyNjM0NGE1YTA5ZGUzMGQ4YzhkZDNiNDE0MzdmMmFmIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI4MTdjZDE3MTU3ZTk4MDkyM2Q0MWRiNzBhYWM3YTJkMjdkZDQ0NmU0NGViOTI3NDEzZDc1NGFjYTY2N2IwMTY4In0" + } + ] + }, + { + "id": "claim_098389d50b3446068e0371aa0de6df82", + "statement": "MobileAppModel stores recent workspace descriptors apart from connected workspaces; a restored selection publishes a shared live workspace before connecting, while cold launch does not reconnect all descriptors, explicit close disconnects/removes them, and background expiration suspends live work until scene activity resumes it.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L431-L446", + "version": "repo-lines-v1:sha256:cd1f7502bc33ef6ea75833837ae3b8bab7622950871f307371b2e0e00dad750b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjMwMjY2NWE4ODQwY2FlOTY3MWE1NmZmM2IyMzk3Mzg2MGU1YmI0NDVmYmM0YTE5OGQ5NzlkYTk0YmNjMmU0MjYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImM4MDU1NTIyN2IxNGM1ZmEwYTQ0NTA1NjhmM2U0N2RmNzAxMDg1NjFlZDU4NjM3ZTZiODlkZDc5ZmVhOGE3NzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk0ZGZkNDg3YzJhZjFmZDE5NTFlOWE5OTUwNzRlYWM1NjM5M2ZmNjZlOGRkM2UwYmUyYjhjOWQ5YjUyYTM0MDgifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L560-L579", + "version": "repo-lines-v1:sha256:0569dc2b10c701c3b0c48b14a14a2521ba0f40ec2645f7220d7e5a61e98501d2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjExYjYwOWM3ODJiMmM2NDVhM2M2ZDFmOWMyMDA3YzdjMGVlMWI5MTI1YjJjOGIxOTU0YTFlMTVjY2UxM2VkYjMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjExMGVhYzUyYWE2NjM0MDczNjQ0MjU1MTg2YTc5NGIxMjdmYzQ5MTA2NTRmYTNhMjBiOTgzMjMxOTIxZWU2ZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjYwZTJhMWYwNzIwY2I4YWNhODQ4ZjIzNzM0N2E4YjUzNGY2YTEzZDVhZTBmMTQ3MDE4ODQ5ZmZjYjkxOTRlZWMifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L643-L698", + "version": "repo-lines-v1:sha256:4c247980d6a2ceef0cb2a5e32f83942cb2ef6fdfb7d9e498c6dbdebe7c110d51:eyJzZWxlY3RlZExpbmVDb3VudCI6NTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY2MTg5YTNmOTZjYWI4YzM1ZjZkODNkMWQyMGE2N2U2MmUxOTJiZDgxMjQ5MjI5MjFjM2M4NTMyYzE2MjlmZGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYxNzMxNDIwMjQzNGQ0Yzg0MjI5MGRkYmY3M2RkNDg5ZTM2YmI4M2UzYTIyOTY2MmI2YjI3MWQxYmNiYWZjMDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE5MDlmNTg5MzgzODA2NjM1OTVhOTFhNDhlYjQzNWFhNjI1OGNiZWVlZDc1MjAzMDUxODZiYjBiMGI4MTZjMDIifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L748-L767", + "version": "repo-lines-v1:sha256:009a2acb4cd53659b0f5811f41e299f4d746f4be8f1f4352ff30ad7118fd662b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImUxODI4YWZmNmM2MDJhZDBjNDkzM2FhYjA1ZmQzZTgzOTVmYmI4ZjY3NTI1OGU4NzBiMmE4MGY5MjhjYzhmZWIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjVhNzhhMmQzMGFkYTcwNjU3OTM0MDdhOGM1ODY5NmMxMmM3NjAyZTc0OTVlM2IwZmE5MDRmMDE3NmI0YzY5NmEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUxNmNkYmM5MDJkOTFjMzE5NWYwNWM4NzZmZjcyYmM3NTdiNDdlZGE3ZjYwNmU4NTRjNDMyNTgyOTRhMDk3MGIifQ" + }, + { + "resource": "repo://TFI/App/MobileAppModel.swift#L94-L119", + "version": "repo-lines-v1:sha256:e6e303e3b91444e7690cc8aa70d6e6eea8ec2eb542e89cca79f46e6fc0192ab2:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk0NWQzYzBlZDI0Zjk2MWU0ODEzNTI0YzRkNjM4NWVkMTZhNzNiMTMwOTA2YzBjOTcyMjg2ZTRmMzU3OTg5Y2IiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBkZjUxODQwNmQxYWNhOTYzYTJlMjBjZmFhMzViZWMzZjdlMDg0MTNjZWU1MDkxNTAyYjIzODhjNjYxZDk1NDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmNTM5ZTRiNDZhNWI3NzZlYjg3ZDY5NDIwOGFhZGU1MjczNjY2NDA1MWIyOWEwZmFiZGMwYmZiNTIwZmNkZGEifQ" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L609-L668", + "version": "repo-lines-v1:sha256:4c7184dd57b66ea0769dc47d28d7535c98477ead53bbed893ca94b4a0999da70:eyJzZWxlY3RlZExpbmVDb3VudCI6NjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmY2U1Njg1OTU0NTBiZWM0OTYwNjlmOTQxMmI1MDE1OWRlNjIyNTI4MDA2NTlkZWIwYTMwMDgxYzRiYjdmNWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIzYTVhMzJkOGE2M2M0ZTY5MGYyMGE2ZTFkOTVlMWIxYzk0YWM4YjNkMTZhYmM1OWQyYmQxYzAzYWE1Mjg3ZTEifQ" + } + ] + }, + { + "id": "claim_5b76f1e2ffcb43beb377d11d06f829d9", + "statement": "Desktop workspace layout drag retains the native source pane mounted but omits it from temporary geometry; a pre-mounted native receiver checks current displayed workspace and matching pasteboard identity before preview/drop, splitting occupied pane edges or replacing empty slots, and rejects hidden destinations and unrelated drags.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/PaneLayoutDropController.swift#L12-L76", + "version": "repo-lines-v1:sha256:450d924604a213e6c80984476d75057910731264b4fc4f718dfdcb872d8cc98f:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImY5MzUwMjNmMTY5ZWJiMDA1YTMzNDU4ZTM0YjljNzI1MzMzYjEzNjE5NGQ5Y2JhMjhiODk1NThhODdlYjYzMTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQyZmU2MmNmNjRmOTJhNzEzYWU1M2YxZTNjMjA4ZmU2ZWYwZTYzNGFmNjlmZDczZDllZTU4YTJmNWQ5YjdhOGYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRmY2E4ZWZhYjEzM2U1ODQ5NjIyZDliOTAyYmEyYWFkM2M4YTc0NTI5MTk3ZDYwMjgxMzNkMjBjNzFjOTExNzcifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceContentView.swift#L191-L209", + "version": "repo-lines-v1:sha256:01874908a5c92a0ef2908dd9b2bb9b43d6333cc57ca3a8a2320586e492979ad4:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYTQxMjgyYjkyN2Y1MzU3ODhjMzBmOWVhNzYyYWNkZjQ0YzQwYmY5OGM5YzU5OWViOWI2NzJmODgzNjY1MWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk2YjUyOGUyY2Y4NWU1NjdjNDIzNzk3ZjI4ODViYTFhZWRjZThlNmU2MWM1Y2NmZjBiNGFiZTNlYWIzMzUwZmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRkN2Q3ODI0ZGMxZjYwYTdiY2VlYjc4OWJkMzI0ODk4ZTRkNjgzNDM4YzFmZTM4NzQ3MjJmOGY4Yjg5MTFjYjIifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceContentView.swift#L99-L116", + "version": "repo-lines-v1:sha256:01b2449e675f9ac1efc718a165f9c2594abbbc460cbf529e3aac8383ad5f2b4d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFiM2Y5OTE2NTU5YmM4Mjc2ZDI1YTRiN2RjMTkyNWNiZjcxYzI1NTQ0ZDY0MzI5N2I4MzNkOGM1MTc5OTE3NzAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY5Mzc5Yzg0N2Q1YWE4ZTg0ZjYwN2JmMGQ0NzI3YWE5YWJlYjg4NDkyNTQzZDk5NjhjOGJmOWEwNWQ2ZmNiZWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEwZmQwNTk4NzdkYjNiNmYzNDYzYjBhOTlhZmNlYTY1YzY0NWJjYTFjYzE4MjYwNDVjYzc5YzBhYzJhZDFiMDIifQ" + }, + { + "resource": "repo://TFM/UI/Components/WorkspaceLayoutDropTarget.swift#L137-L153", + "version": "repo-lines-v1:sha256:957e547a267885cfffe10d90649156d31b1864311bc60e7efe769a1c55def8ef:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ5NGI1NjAzNjdmN2MyMGM2MDZlODI4MzUzYWIxZTQ2NWYwNGZjYWVmZTFiOTY2NDBiMDYyN2JhMDg5ZWZmZjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE3ZWE2YzE0ZTRlN2NkMzhkOTMzODkxOWViMDY2OWFlZDNlYjUyNjlhMzE3ZDU3ZjViMzE5YTBiNTZiZTU1YjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZmZTVhMmMxZjdlYjI4YTVkYzU4MjA3NGQ3MTJmMzk3YTY4ZjI3MDFkYjU0NjM5MTFlMzExYzc4ZTlkY2UxNjQifQ" + }, + { + "resource": "repo://TFM/UI/Components/WorkspaceLayoutDropTarget.swift#L43-L50", + "version": "repo-lines-v1:sha256:6278cfde832f103367568d013c49dcfff60208e0cc9eaf12a3043d988972b567:eyJzZWxlY3RlZExpbmVDb3VudCI6OCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMDFiYTQ3MTljODBiNmZlOTExYjA5MWE3YzA1MTI0YjY0ZWVlY2U5NjRlMDljMDU4ZWY4Zjk4MDVkYWNhNTQ2YiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYTc1ZjM3N2FmNWM5MGNlODEwN2ZjM2Y3Nzk5NmY1MTBlMTI5MjMxZDFlNzFlNDI3NzAyMjMyZDUzM2Y1MGQyZiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiY2U3NGU5NTYzMDRiODEyZmY3ODg5NjUyMWMxMDkzZDEyZjQ5NmMyODQ2MTdmMzgxNTMxMWVkOTlmNWRiYzQ2NyIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiYmFjMzg1N2VjMDcxZmU4NmVkOWFjMWIwNDk5YjdjZjNiOTY4YWRiYWU0MTYwNTRiYTNiMWY4YzA5ZDlhZDdlNSJ9" + }, + { + "resource": "repo://TFM/UI/Components/WorkspaceLayoutDropTarget.swift#L97-L113", + "version": "repo-lines-v1:sha256:ca79992303a0f088045106232ef7f197d5e93b391277f409db20e468e3cf70b9:eyJzZWxlY3RlZExpbmVDb3VudCI6MTcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI2MTNmMzllOWIxOWQ4YWU4Y2NiZjY2OWI5OTA3NDQ2OTA0ZDJlODIwYmI2ZTNlYTQ1MzkzZGUxYjcxYjRhOTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImRjMTk4ZTNjNWZhNTc2NTQ2MTEwMWFiODJjZTkyYjkzN2UxOGFhOTBkNTI2NWUwN2U1OGNlZjYxMjU3ODFlNDYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlNGIyNzRhMGRjZWMxNDU3MDc1MWFhZjRkNzUzZTM1OGQyMzQ5NmIyMjhjZDQzOTI1ZjY3N2VhMzQ1OGVmMWYifQ" + }, + { + "resource": "repo://TFMTests/WorkspaceLayoutDropTests.swift#L202-L274", + "version": "repo-lines-v1:sha256:41d784bab7ed526b91ca210272b443fd41c0e1d0637745574f51062fbcc834a0:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjIzYzkyNzMyZjVhYzgwNjljMDMwMGRiZTVkYjFkYjFkMzI1OGU0N2I5NWUzZWIwZTk4YTJlZjkwOTJjYWRjZjEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQxZjJiMmZhOGVkYWJiOWViOGVjMGVjZWVjNTBkOGQyMTBhMWEyNDBmOTJmODA5MTQ2YmQwOGMzZDMzYjZhNDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRmZDQ2MDJhYmEyZDQ1OWI1MDc1ZWU2ZjA3MTk2ZTQ1NTg4MWY3OWZiOTA4YzBlYzUxZTZmNDEyMGNlYjU1ZDgifQ" + }, + { + "resource": "repo://TFMTests/WorkspaceLayoutDropTests.swift#L36-L135", + "version": "repo-lines-v1:sha256:9dfb5603ee28a45fa0f937601c0556797f647a216329ffc296930752c76ccd83:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAwLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiIwYzJhNWQxN2Q3NzZhNmE2M2I2NGUzY2I1MGFmOGVkZTI1Zjg1YmM0YTk5NjMwMzcwODI2OGU1N2NlNWE2NWUzIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiJiNTk2M2Y3ODQwMmVjNWFlZmM5NWY3OWM4MzNmNmFhMjEwYjU0YzE4M2NmNWU5NWI2ZWM2M2IxOGFiODkzNjA2IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwZGIyYjA1ZTg2MTQ3ZDg3MjY2ZTc3YzNiODI3YTQ1MGI0ZTE0OGE0OWE2NmM2OWYyYTZmYzRkNmZlM2YyYjFkIn0" + } + ] + }, + { + "id": "claim_b1bab73f1fbb49d88d75c22640fb2702", + "statement": "Desktop Navigator workspace drops use a native overlay on the List and measured row frames to show an insertion boundary while computing the move index without the dragged row; drops detach panes or reorder workspaces only inside the workspace section.", + "evidence": [ + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L144-L209", + "version": "repo-lines-v1:sha256:4736d054e0b253e867e3b433eea2420794c77dcadf7e8ba7bcbcd21c803fdc34:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmMWZiMDUyYzFiMmM1Y2YwYTFkYmExNWNiODM1MjE5ZGE5NTVkNDBmMzM5M2E1YzJiZDg4ODNjNzllYTE3OTIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJjOTk5ZGJkMGY3MDRlZjZiOTljMmE2Zjg2NDFmYjcwNjI2YjZlMDNmMjM1OGMyNTI1ODg0MmY4NTdiY2Q5OGUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZmMDY3MmE0MDRhM2Q1MGRjYWYyMWQ2ZjgxNGNmOGViODQwODAyYTc4YjQ1NDJiMzc1YjRhYjFkOTQ1ZDU2ZDEifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L215-L301", + "version": "repo-lines-v1:sha256:db133ba93e0ef74d84a3c80e3353e783a3de2fa1d58044be861a7eacd7ac769a:eyJzZWxlY3RlZExpbmVDb3VudCI6ODcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU0NThmMzc1OWM3ZDY1YmMzZGE3ZDY1Y2I2NDc1ZGMxOTY2ZGE5N2YyYWMzYmQwMWU0MGIwNDhlMDFkMGRkZTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcwYzY4Yzg0YzZjNjNlMDQwY2E4NzRiMzkxN2JkMWQwNDY4ZTllMmU2NmNkYjNiZTZjZTBmMTEyYjlmZTc4MGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc3MTJmY2NjOWY2YTFmZGU3MmQ3YTQ2NGMzYmMyNmUyYzUyYjgwNjBjMzlmODZiNDQxMzg0NDRlOTZkNGQ4ZjYifQ" + }, + { + "resource": "repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift#L389-L415", + "version": "repo-lines-v1:sha256:f1528f5a42351f4b9b0f50ae64a5a34cfd7409ee9cae6e8a8a68e2be016a6884:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMzZDlkYjVhNWRkZDU4N2IyMmYyMTE3OGNhMDk1NzA1N2NiNWI0ZmI5MWQ3NDlhOWMzODA2ZjQ0NDU0MDU1NDgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZiODU1NjQyYzRlNzU5YzA3ZmI2ODI3YTUyYWQ4ODBjM2U2MjYxNzQ4ODhhNWNjM2Q0YTY0MjI4YzVlNTE3NDQifQ" + }, + { + "resource": "repo://TFMTests/PersistentWorkspaceDeckLayoutTests.swift#L16-L73", + "version": "repo-lines-v1:sha256:416d896921af35bcc580f0aa68bc3489a3576e6664e4aac3ba89f6945fb7692a:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwNDU1YWQ1ZGVkMTQyYzVhNWY3NDA3NGE2MmM2YzhmY2FhM2Q4Mzg1MjgzNzBiNDI2ODgwMDBkNTlmMDk5YWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA0ZDY2Nzg1NzQzNDllZjRkMzljYzQ4YzJmZWUwOWU4ZGFhZDFhZDE3Y2ZkYzg5ZTIzN2FmMzIwMjhhN2M5NzgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJkOTNkYjZhYjc4NWQxYWRlNDI1MzhmMGE3NjM2MGMwNzIyNGRhMmIyMGZiMzdlM2I3MTM1ZDM3YTA1ODIzMWIifQ" + } + ] + }, + { + "id": "claim_b4fc8a2cee5145ebaa9b384e0b6d0ca4", + "statement": "Vault presents MobileHostEditor as an item-based sheet for new or existing Hosts; the editor seeds a local Host draft and uses the shared profile and connection fields while each platform supplies its own group and tag controls.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindPresentation/HostConnectionFields.swift", + "version": "repo-file-v1:sha256:c8f3f7ce1f96c10a867138614a48a5bfccede52e85b3a3d71bb485b3d2d1dd16" + }, + { + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift", + "version": "repo-file-v1:sha256:d2792158c62c3eecca3fef18c90e4eb26e3c51ec782431baa50bf2277e7f3e27" + }, + { + "resource": "repo://TFI/Features/Vault/MobileVaultView.swift", + "version": "repo-file-v1:sha256:19fc7789a96e909c77b51a2b1149d8ce29449c22068fd0084b19e8a286a64d06" + } + ] + }, + { + "id": "claim_f5d668a0329a497aa495860481b68637", + "statement": "Mobile Host Save eligibility requires a nonblank address, an enabled terminal protocol, valid enabled ports, valid custom identity/proxy configurations and valid SSH environment variables; desktop additionally checks SFTP initial path and validated SSH route in its own policy.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/HostCustomIdentityDraft.swift", + "version": "repo-file-v1:sha256:072f2ec5b033ad57fa92e1ea95df08044cf9e91329e1337d9351c606187ea444" + }, + { + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift", + "version": "repo-file-v1:sha256:d2792158c62c3eecca3fef18c90e4eb26e3c51ec782431baa50bf2277e7f3e27" + }, + { + "resource": "repo://TFM/Features/HostEditor/HostEditorView.swift", + "version": "repo-file-v1:sha256:a71a870383335276f0190eb1f90be657a7ce100f5ad68ec0fb6bb067fbbcd499" + } + ] + }, + { + "id": "claim_9a485da9d27e4473b7b8de52717114c1", + "statement": "The mobile Host's separate temporary custom-identity draft loads once when the editor appears; saving uses the Host library to persist custom identities and the Host, whereas child identity, group and environment-variable sheets feed selections or values back into the parent draft.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindApplication/FeatureModels/HostCustomIdentityDraft.swift", + "version": "repo-file-v1:sha256:072f2ec5b033ad57fa92e1ea95df08044cf9e91329e1337d9351c606187ea444" + }, + { + "resource": "repo://TFI/Features/HostEditor/MobileHostEditor.swift", + "version": "repo-file-v1:sha256:d2792158c62c3eecca3fef18c90e4eb26e3c51ec782431baa50bf2277e7f3e27" + } + ] + }, + { + "id": "claim_fa62b5b94b28437faa7eed5089ee91b9", + "statement": "MobileEditorSheet owns mobile form navigation and save lifecycle: dirty Cancel confirms discard, an in-flight save disables editing and interactive dismissal, success dismisses, and failure displays an error without dismissing.", + "evidence": [ + { + "resource": "repo://TFI/UI/Components/MobileEditorSheet.swift", + "version": "repo-file-v1:sha256:f45f9043646b512f8fa210254172e922b2f2322339321d45b65b5e7f810095a6" + }, + { + "resource": "repo://TFITests/MobileEditorToolbarTests.swift", + "version": "repo-file-v1:sha256:b7bdc9c7e0f80d81f6610283c947786cfc0f0d13dc06ddd683a4240e1236b38a" + } + ] + }, + { + "id": "claim_50a47b66aa664c19922d1eb3f61792b0", + "statement": "Desktop titlebar Find resolves the foreground destination's query from WindowModel; its native search-field owner and direct focus handler preserve keyboard intent during SwiftUI toolbar replacement, while terminal contexts also provide find navigation and cancellation.", + "evidence": [ + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift", + "version": "repo-file-v1:sha256:2bc72f38966ee4942aff636233d023f6fd7899afa834a4c6d3899e56e382e7d1" + } + ] + }, + { + "id": "claim_5d432d6b33424594b31dbdcf952f1360", + "statement": "Desktop toolbar creation actions depend on the foreground destination rather than sidebar mode, and the same page-specific verbs can be offered by a Navigator row without first switching to that page.", + "evidence": [ + { + "resource": "repo://TFM/UI/Components/WindowToolbar.swift", + "version": "repo-file-v1:sha256:2bc72f38966ee4942aff636233d023f6fd7899afa834a4c6d3899e56e382e7d1" + } + ] + }, + { + "id": "claim_f8e11156b4024feea9bd224c69a504eb", + "statement": "AgentToolPresentation projects human-readable tool summaries and details without changing execution/replay data: live approval arguments come from the in-memory request, MCP output retains remote-defined presentation, failed results avoid knowledge success presenters, and a bounded preview retains the full text for Copy.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindPresentation/AgentToolPresentation.swift", + "version": "repo-file-v1:sha256:51672921c0a7180ee5ebe102540f2ea500e272801e87c31ed9fc83ad3640b91d" + } + ] + }, + { + "id": "claim_aaf091c40c4343e7a12df62c0dfd52f1", + "statement": "Mobile card tests verify measured card-height stability across tag counts, width-dependent columns and accessibility one-column layout; opt-in serialized mobile toolbar tests verify save, failure and cancel behavior across localized labels.", + "evidence": [ + { + "resource": "repo://TFITests/MobileCardTests.swift", + "version": "repo-file-v1:sha256:45c1ade664772060183a9c8babc283fd04b1698c2e7ec6879724c5373b657622" + }, + { + "resource": "repo://TFITests/MobileEditorToolbarTests.swift", + "version": "repo-file-v1:sha256:b7bdc9c7e0f80d81f6610283c947786cfc0f0d13dc06ddd683a4240e1236b38a" } ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T05:17:08.701Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/integrations/mcp-server-and-bridge.json b/openwiki/.claims/integrations/mcp-server-and-bridge.json index 92f6fabe..aa24814a 100644 --- a/openwiki/.claims/integrations/mcp-server-and-bridge.json +++ b/openwiki/.claims/integrations/mcp-server-and-bridge.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:8813e9d352ffc558ec59d677d22b494424eb3bb01bc65a25060eb3b812791721", + "pageVersion": "sha256:d346d4ae2b393ff1fa231f3fdb05e737eded8665a2627acc44df7c382333a96c", "claims": [ { "id": "claim_b47979774aa94e7dae517a6894c508d4", @@ -8,7 +8,7 @@ "evidence": [ { "resource": "repo://TFI/App/MobileAppModel.swift", - "version": "repo-file-v1:sha256:72bc88a9f06e31aca2ec86d3b13ba58773798d2a53742e63a0287edf971c7f25" + "version": "repo-file-v1:sha256:846cccb0bc643b8f8c6c54dc70c1928a29218a885598274f1ef689e239b1aa80" }, { "resource": "repo://TFM/App/MCPServerController.swift", @@ -315,10 +315,36 @@ "version": "repo-lines-v1:sha256:bbe609256f29f5d3f57df07fd079fd2175c599b92d24faf60060b97a17b592d7:eyJzZWxlY3RlZExpbmVDb3VudCI6NDEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA0MWJjMzU3ZWE2YzA2MmNiNjE1MGRiZmIwY2Q3YTBhZTM4ZTA3MTllYzU1Y2QwOWY0OGY3Y2U4MGVjOTcyZmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhjYzgwYmFjZGQ0ZWUwOTdkYmRlMzFjZTEzNGIzM2YyODlhMzVhMWM1ZTBmZjNhYmFhZWI3YTVhNmY5ZmVmNDEifQ" } ] + }, + { + "id": "claim_73da5137b6dd4ad8aa2e4dc90ee05765", + "statement": "The macOS AppModel supplies shared AgentHostServices resolver, connection pool, authentication registry, and background commands to its MCPServerController, which owns the external upload/download ticket coordinators and ties them to MCP sessions; iOS instead supplies AgentHostServices to MobileAssistantModel and constructs a separate ordinary SFTPTransferCoordinator, without constructing an inbound MCP listener or its transfer routes.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift#L241-L275", + "version": "repo-lines-v1:sha256:8d4d911d90dc89b12dd420b04b12d69b911218a6bac19b511a4ccbc2f51a8860:eyJzZWxlY3RlZExpbmVDb3VudCI6MzUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjJhNmVkZjNhNmY4NThlYTM3YTZmMDZiY2ZhNWFlY2Y4YmU4NzczNzJiYjhiYzA5ZmUwZjE3NmY5OGE1MTczZDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRmYWQ3ODk2ZGU0ODk4MzU0ODAyMGEwYzY5YmQxNDVjN2VjMTlhOTBkZTRhMGYxMjQyZWIwMWE3ZjMzZDVjOGIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjBiZDMxMGQwMTYwM2I3NmY0OWFhMjIzZjEzNzVlNjViYWQ5Zjc5Njk3ZWJlZmIzM2RiMTQ1OGUwZjMwMzE3Y2QiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIyNmQyZWJjNGFjZWE5ZDk0YWMyOGU0ZWJhMmQwNzA2MDQzODU2Y2Q4YmFmZTk4YzdmYzQ3NGJmYTdhYTk5N2QifQ" + }, + { + "resource": "repo://TFM/App/AppModel.swift#L201-L250", + "version": "repo-lines-v1:sha256:58b3f0c53db979ac8364ed09b8217835556719ff0162914f35e84ed27019f574:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhhZWVjYjk1YTc2M2FhZDQ5NjhiOWYxYWYyMDU2MjVmMTgxOTAyOGRmMWZkMGFkM2RiNmViMzQxZWE4NzJlY2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU5MDlhNTNhNjE4ZDAyOGUxZDMwMDBjMGE3YWJjZWVjYmU1ZmIzN2Y0ZTUxMWVmZTQ2NjQzZmFkNmU2Njg3MmYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJlYWMyMWIyNGJkYThiN2QwM2M1NTkzYzE3YjZkNDkxZGVhODk0NjVjYTIzYWI3MmY0NjQ2MGI0NjA4MGIzODgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjcwZGEyY2NmZmZiOWM0ZWM4NTIzMGU5NDMzZGVmMDFlNDIxYWI4MjJkN2I5ZWQwYTA4Y2QzMGIwODg4YWJkNTAifQ" + }, + { + "resource": "repo://TFM/App/MCPServerController.swift#L172-L200", + "version": "repo-lines-v1:sha256:8d50f6892bee3ab850c9f1ec6d76c62d981a96772a0785561c58917ea0df154a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc4OTI3ZjY5ZjRiN2JiZGM0NjNiYjZiOWJiNjkxZDQ5NzBkNjg3YjI5YzAzZDc2NTIxMDI0NWI3Mzk4OTg4MTciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY3ZWNmYTNkYjMwOTFjM2RhODgxZjZjODVlYmU3MjBlYmIxOTg1MDY3Zjg3M2Q5NWJmOWY2MDM3MWFiNTFiZDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFmN2E0YTAxMTI5YjdiNDlmYjA0NzYzMWRhNzM3MjBjYTMwM2EzMWIzNjcyYWNkN2RlZjg4NWM4MzdhZGM4ZjcifQ" + }, + { + "resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L114-L180", + "version": "repo-lines-v1:sha256:7429e23cc5acfb0c4d8c8db35b4f475f89eaca6cfc7509c889df129bd5960b36:eyJzZWxlY3RlZExpbmVDb3VudCI6NjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMwNWYxMzcwN2U0OTQ2YWY4NjE2MjcxZjhlOTc3MmFlMTllODM0MDNlOWI1OTE2OWQ0ZjU1MmYzYzg2ZDRjZGUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjgzNzhkOGYxZTk3NDg0M2I4M2U0MDFhYjcxZDExZGZkYTAzZjE0OWJkYjIyZGFhOTVjMDYwMjQzYmVmODZmOGYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjY1YmRiYjExOTcyMzQ2MWM4NTBiZWFlMzNiMjdlZGZkMmFlZTY4YWM1ODc2ZTU2ZTc0MmZhMzRjOTg5YTcwZmEifQ" + }, + { + "resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L24-L82", + "version": "repo-lines-v1:sha256:7e49cb710fe6531fd703953ff8e825394d457513e3338f6f31ef36dc2d21c462:eyJzZWxlY3RlZExpbmVDb3VudCI6NTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyODgwNTA4Y2FkZTAwMmU3ZWE3Y2MxZGNkMmEzZjgxNTJkMWViMDlkMTU4MmU1ZmFiNjc0YzY5NzkyZDk3NWMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZmYTk0OWU0N2NlZTA3MjhmODU0YWI1YjAwNDFkMDc3OWM0NjQ4NzEwOWMwNzM3ZTE5OTRhYmIzMzMxMzAxNmQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZkZDgxODQxYzE0YTcxYzljODI3ZmQ0NjRhZjU2MTYxMDVlYTBhZGVmZjVjZjZjM2E4NDc5YjE1MmI3Y2FhMGUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5MzU3YjJhYjcyNTNjYzgzZjIxNTAxMzlhZTI2NmU0NTZiNjMzMjA2YjJjYWFlNjlkOWY5ODYyNmFlNjkxYjkifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/operations/build-test-and-release.json b/openwiki/.claims/operations/build-test-and-release.json index 1d330cf2..6d6afa3a 100644 --- a/openwiki/.claims/operations/build-test-and-release.json +++ b/openwiki/.claims/operations/build-test-and-release.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:bb9dbed6786dee54c410e058f3e9ef6f001e35e72cd4845bec4d80a4b56f9e46", + "pageVersion": "sha256:18c4ab0086670df59a492485fb84903a16daf0e41e8c32cff217d1330fd49d7d", "claims": [ { "id": "claim_d34d7b16495a44a4a946d3dc9e0456f4", @@ -197,10 +197,102 @@ "version": "repo-lines-v1:sha256:c11f26108030abfcf1f2cdd98655ff0116e1d44180c4d5eec36e9b6bb15895e9:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjRjMjMzMjczNTc4NTMyYWE3NWIxM2ZiMzRjYzkwYjdkMDIwYWVkNDhmNjY1YTE4MjYxNjdiOTAwMjljN2MzYSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNTAzYWFlMjllMDYzMTZkNmRhNmY4YzJhOTFmNmU0NGE2MTJmYWJkNzkzYWQxZjVhMWZjYTUyMDZiY2VkYTQ3YyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMjE3MWVmNzc1NWEyMTNkNzkwZTA1OTU2ZGNhOTRiZjE5Nzk4YmYwNGZhOTNhOGE3MjE0OTgyNTczMDdiM2UwYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWIxYmM1YmM0YTIzN2Y1NzhlNmFmNGE0MTVkMDY0N2Y5OTEwYjAzYjM2NGUxZTI3YzFmMWRiYWE3NDNkMDNiYSJ9" } ] + }, + { + "id": "claim_3a425fb15df94283a88712a4a1684cff", + "statement": "The `TFM` scheme test action includes `TFMTests` and `FrameworkTests`, while `TFI` includes `TFITests` and `FrameworkTests`; a successful default run does not imply an opt-in suite executed.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L38-L46", + "version": "repo-lines-v1:sha256:070213e98b52cec4fdee409349c32e94d42a6a1c41a2f6b5e43523d08e46b11b:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTdmYzk4NmVmMDFlZTVmNThjNmYxZmEyNjViOGE2NDEzMTE2OGY4YWE1OTkzZDc4ODZkOTZjNmUxODk4OTQzMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDFkYTg3Nzk4Y2M5NTc1N2I3NzQ0NThlYzQ5Yjg0MWRjYWMzODA1MWQ5MjljZGI5ODE5MGJiMTdiMjdkZmQ4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9" + }, + { + "resource": "repo://Termind.xcodeproj/xcshareddata/xcschemes/TFI.xcscheme#L25-L52", + "version": "repo-lines-v1:sha256:df271653446a88ce49df6c4f146b94acea68146f3d12fbf80e894e3e2f694fce:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNhMzMxZTFiY2RkOThjODFhN2FhZDMzZDZkOGMwOTNlMTE1NzYyODE5MGM2ZjQzNDUyZGJhNDBhYjI0YjczZmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU5YTdhNzM3ZGMxMzZkMzFkNzUyYjFjY2U0N2VhNTBkMWQ1OWUwODIxZWQyYTU0ZTc5MmUxMWI2M2QxNzU0ZjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzZGFjYjcyYzhjZmVjMjI2MmMxNGI1ZmEwNWQ0YmI4OWU5MTk1ZjAwZTBlNjA5NWJkMDM2YTU3MjBjOTU5OWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJlYWMxYzY4YzUwNDExNWM3OGZmOWM3NGY4NTdiZGI1ODJlNjNkMmFkMjk4ZTM3ZDRjMmI3M2U4YjY1MmJmNTMifQ" + }, + { + "resource": "repo://Termind.xcodeproj/xcshareddata/xcschemes/TFM.xcscheme#L53-L80", + "version": "repo-lines-v1:sha256:52623979e6d63854abaace47c93b1410d3f8b46613aa84d866b9c843bc87384a:eyJzZWxlY3RlZExpbmVDb3VudCI6MjgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNhMzMxZTFiY2RkOThjODFhN2FhZDMzZDZkOGMwOTNlMTE1NzYyODE5MGM2ZjQzNDUyZGJhNDBhYjI0YjczZmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU5YTdhNzM3ZGMxMzZkMzFkNzUyYjFjY2U0N2VhNTBkMWQ1OWUwODIxZWQyYTU0ZTc5MmUxMWI2M2QxNzU0ZjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjUzZGFjYjcyYzhjZmVjMjI2MmMxNGI1ZmEwNWQ0YmI4OWU5MTk1ZjAwZTBlNjA5NWJkMDM2YTU3MjBjOTU5OWIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJlYWMxYzY4YzUwNDExNWM3OGZmOWM3NGY4NTdiZGI1ODJlNjNkMmFkMjk4ZTM3ZDRjMmI3M2U4YjY1MmJmNTMifQ" + } + ] + }, + { + "id": "claim_c27820eab70a46a5919312d53abaf3d8", + "statement": "Mobile key-window integration suites such as editor toolbar, forwarding rendering, host integration rendering, and saved-name rendering are serialized and disabled unless the test host has `TERMIND_MOBILE_UI_TESTS=1`; command-line runs use `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1`, disable parallel testing, and narrow the TFI suite selection because UIKit presentation state is process-wide.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L44-L46", + "version": "repo-lines-v1:sha256:a0ee5a32ecdb2ce8f5dc8df2134d5fc548dc5c470380c3085abc02cde4861345:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGUwNDgwMzIwNDhlODdiMGE2MWE3ZjMwMTU4YTE3YTZlODA1MWI0YzQ4ZDUwZTE0YjJmYjY3NmI4MDBlYTJjYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjZhNzFhZDgxY2FlOGI3MGJiZDYwMzkxNzllYTExZmU0OGExODY0YzdmMDcwNzU2MDQwYWJlOTYxNmVhNmMyYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9" + }, + { + "resource": "repo://TFITests/MobileEditorToolbarTests.swift#L8-L14", + "version": "repo-lines-v1:sha256:9840e4f16e3feb35c895f5df5137cf37c074d60727cd0f68497f1620f220baa8:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzE4MDI1MDRmMjViYTNjZDBiOGZmMTAwYjk0YmViNTI2ZDVlZTI1NDFjMmQ4OTBkODFmM2E0OTY2M2IxMjFjMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZWY5MjllMmY3NmM4ZjhlNDUyZWZlMTVlMGUzNzY4ODVlYTEyMmY2NzA3ZmRiZjk0NmQzNDZhNmI3MGZkMzVkNyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiM2U1NmQ3MWMzNzQ3MjBmMjJhNGUwZDViNzVhNWY2YTZjYzEzMWQ2YWM5ODA2N2QwZWYwNjc3NzVkOTNmMmMzYyJ9" + }, + { + "resource": "repo://TFITests/MobileForwardingRenderingTests.swift#L10-L16", + "version": "repo-lines-v1:sha256:19b48e1a53736cd071b682a614adbdfe1ceff866fd66e652b1fab40c88b9d60e:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzE4MDI1MDRmMjViYTNjZDBiOGZmMTAwYjk0YmViNTI2ZDVlZTI1NDFjMmQ4OTBkODFmM2E0OTY2M2IxMjFjMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYzdjY2RkNDgzM2Y0MTk4NDJjM2FlMDc3YmViM2I3ZTEwNjMxZGUxMzAyOTFiNDRjNzgyM2UzZTU1N2FiZjAzOSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZWNkODkwMTAyYTJiZWIxM2VjZTg1OGM5YWYzNWMxMmVkOGUwNWZkMzFjNjE5NjZjNjNjZGEwYWY1ODkwZTI0YSJ9" + }, + { + "resource": "repo://TFITests/MobileHostIntegrationRenderingTests.swift#L11-L17", + "version": "repo-lines-v1:sha256:7f8bcb821b064323f4d73aa3f02d4ffed62856965bdb74cb6ae481ea7842dd4b:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzE4MDI1MDRmMjViYTNjZDBiOGZmMTAwYjk0YmViNTI2ZDVlZTI1NDFjMmQ4OTBkODFmM2E0OTY2M2IxMjFjMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYTE1YWJlODY1YzIwMGNmZDI0YmNiOTNhNGQ2MzY2MTg2Zjg5ZDY2MDg3MGYyZjU5MDVmYzVmYTIzZmJhZmQwMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiODNhMjk2MTM0NWUyZGE3MDg0Y2NkZjQ1OWI4NDZjOWViZGYwNDUwZWYxYmE4MmY1YjhmNmNmN2QzN2YwMTUxNCJ9" + }, + { + "resource": "repo://TFITests/MobileSavedNameRenderingTests.swift#L12-L18", + "version": "repo-lines-v1:sha256:f4e5f08698e65c5ef38d27102f2f413dcfbce41d7705dbeefed58fdaaa4ded90:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzE4MDI1MDRmMjViYTNjZDBiOGZmMTAwYjk0YmViNTI2ZDVlZTI1NDFjMmQ4OTBkODFmM2E0OTY2M2IxMjFjMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTJkOWNmNzI4MTc1YzliN2MzOGExM2E2NjUxOThjYTQ0YzhkZDE1YjdmYTUwYWVjYzAyZmI5YTU0NGQzYjdmYiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOTJiOTM2YWEzNDk1NmQ3ZDM5ZDViMDdjNzdhNjRkNjhlNmMzYmJjMjkwOTVlMDJlZjMzYzQ2MWIyOGYyMDQ2NiJ9" + } + ] + }, + { + "id": "claim_6587ad212d9d46ffb28294b05d9c63f6", + "statement": "`MobileAdaptiveLayoutTests` is serialized but has no mobile-UI opt-in condition: it temporarily makes a UIKit window key, restores the previous key window afterward, and tests adaptive tab/navigation state and UI continuity across widths and locales; focused nonparallel execution avoids competing process-wide window state.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L46-L46", + "version": "repo-lines-v1:sha256:20f70f81c29f72ceb3b8c0d0ed710e433bbc08043f50f8fa17d7544dbd06708d:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjc0N2NkNGE1NTI3OTAxN2Q1ODYxMzE3ZjlhZDcwZWY0ODIwZTFiOTAxYzI4MDFhYjE1MTdjZGI5NjhiZjliYiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L10-L11", + "version": "repo-lines-v1:sha256:29fd225b0e3fa2e46da661ee74241fa80baa5d50e1ada6d94078881997a81812:eyJzZWxlY3RlZExpbmVDb3VudCI6MiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiNjE3MTdiNGY2NTFlNzU0OWU1MzdkMWQ4N2RjZjgzYTVkYmI5MTgwMzZiY2QxMTA0ZGFjODNkMTJjZDc2ZTU2MyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiYWM5MmM3OGJmMWQyNTVjY2M1ODhmM2ViYzY4ODk2NDg2ZWQwZjE2MzA0MDNhYmZkOThlNDA5ZGVkOTY2ZjNmZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMjI2NmRkNDI0NTFiZTYwZmI1ODc0ZWMzZmU3ODRlM2EzOGI3ZjBmYzZmNGFiYjg5NzI4NzAwODcyZGY2NGI3YiJ9" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L131-L176", + "version": "repo-lines-v1:sha256:9ff692e72ae5bc6ec980c25f35b1b34b7926bd49ab3afaf1930f3316bdd7bf13:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRlYmZhYTQxMjcwNWM3ZGQ3NTg2ZTI4MjcwZTJiZmJiODBmMzNlZDMzMjRkMWVkYzZhZGVlMmZhYmY1OTc2MDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA2ODYwN2ZkMGY0M2NjZDAzZDU2MzZhMWFlOWJiNWVmMTEwM2YyNmQzZDQ0OWI1NGMwNTEyOTk2NGQ3NjYxMGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmNzU0NTFmY2MwMTA4Y2RmYjZjY2U0NGMxNDAzMTExOWRkNjdlODYzYmUyY2ZiZGY5MTA4M2UzZTc2MTQ4NGYifQ" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L683-L725", + "version": "repo-lines-v1:sha256:28259f5267d5e31e47bf18179d541ec09b629419cec56a6234328d010a73c22d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAyNTY0MjI2YzMyNGE5Yzg2OTgzYjIyMjAwNjFlYzU4N2U4M2Y1YmNjZDY2MmU3Y2U4MzViYWVhY2JhYjQ0ZjkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjZhZmE0MzQyY2M2NjdmYTAxYWRhYWI3M2FmZjE1ODJkMDM0YWQ0M2Y5Y2U1ZGZkNzg3ZjA2MGM5MjFkN2MwNzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk4OTI4ZWRkM2U5OWIyZDljMTZlNmU1OWI3MzJjNjhjMDFkM2Q1OTNiZmFkYzMyODBmMmM3NmYxMzBkYTEyMjcifQ" + }, + { + "resource": "repo://TFITests/MobileAdaptiveLayoutTests.swift#L77-L113", + "version": "repo-lines-v1:sha256:10eb03030d4b2e44b7e418cb55d27bb804affa9d5cb40d9426216067ed5e95cb:eyJzZWxlY3RlZExpbmVDb3VudCI6MzcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdmY2U1Njg1OTU0NTBiZWM0OTYwNjlmOTQxMmI1MDE1OWRlNjIyNTI4MDA2NTlkZWIwYTMwMDgxYzRiYjdmNWUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE3NTljMmJlYjBhYmYwNDcwM2MxNzQ5MTFmOTJjM2MyNThkZjE4ZmQ1OTFjNjIxYzhkNzQ3NGVmMmJjNTc2ZjEifQ" + } + ] + }, + { + "id": "claim_060bbea77d084d42b33d457061d3aa07", + "statement": "`StoreKitTrialTests` is a serialized macOS suite skipped without `TERMIND_STOREKIT_TESTS=1` because it requires manual authorization; its resettable `SKTestSession` fixture uses `StoreKit/Termind.storekit` to exercise trial and restore entitlements, lifetime precedence, pending and failed purchases, and modified subscription configurations.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L44-L44", + "version": "repo-lines-v1:sha256:8e048032048e87b0a61a7f30158a17a6e8051b4c48d50e14b2fb676b800ea2cc:eyJzZWxlY3RlZExpbmVDb3VudCI6MSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOGUwNDgwMzIwNDhlODdiMGE2MWE3ZjMwMTU4YTE3YTZlODA1MWI0YzQ4ZDUwZTE0YjJmYjY3NmI4MDBlYTJjYyIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiOGUwNDgwMzIwNDhlODdiMGE2MWE3ZjMwMTU4YTE3YTZlODA1MWI0YzQ4ZDUwZTE0YjJmYjY3NmI4MDBlYTJjYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNjZhNzFhZDgxY2FlOGI3MGJiZDYwMzkxNzllYTExZmU0OGExODY0YzdmMDcwNzU2MDQwYWJlOTYxNmVhNmMyYSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOTg2ZjBmYzI2Yzg1ZWJjYjA4ODA0ODE3YmIwZDNkYmQ3YTA5YTYxYTU3ZGE5YTA1OTdhYWM5ZTc1ZDBkNzQ5MiJ9" + }, + { + "resource": "repo://TFMTests/StoreKitTrialTests.swift#L14-L20", + "version": "repo-lines-v1:sha256:3fea9f0a159afbd1927f42484d64e5acddf636a101b4cdf4a274b4b62362254d:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzE4MDI1MDRmMjViYTNjZDBiOGZmMTAwYjk0YmViNTI2ZDVlZTI1NDFjMmQ4OTBkODFmM2E0OTY2M2IxMjFjMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZmY5NzAxMDYyNTQ2ODJmNzJhNDQzZGM1NGFjODhmMjQ5NTY5MTIzMDQ4YjJkMTMyMGIzZWM0ZDVjMGM1MjNlMSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiNzU1MmM5NzExMGEwMzVmM2RiNDYxYjMzZWNmZDUzMDA3OTk4MzFlYmViN2UyYTM5OGQzMmJjZmY1MmViMWU1ZSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiOTUxZmY4MGIxYjE1OWJiMGYxMDIyODAxNmE0NGViMTc1MGUxMjExYTk5NWVkZGEzMWE0Y2ZjMWRkOWEyY2ZjYSJ9" + }, + { + "resource": "repo://TFMTests/StoreKitTrialTests.swift#L177-L245", + "version": "repo-lines-v1:sha256:37e100d42a523a4a7a4c1c18ff7395b7c73277abf9151e5f4e6795859ca154a7:eyJzZWxlY3RlZExpbmVDb3VudCI6NjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQyOGY3YjBiMjZlNGFjYmE0NTJiYTk4OTYwNWU4MGVjYjI2MTJhMjRiNjJhMzc0ZjE0NWQ0ZWMzODNkYTVlN2YiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjI1OWU1MzhlMTZhYzBmYTBiMzZhMDY5ZjQwZmFlMDliODFhNGFjZGU3OGY4MWY1YWZhNTEyNmY5NDcwNzQ4MGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFMTests/StoreKitTrialTests.swift#L21-L175", + "version": "repo-lines-v1:sha256:0b6cb21f0f1757fb3cb296d655faedee32d0eaa595497a26b5baf658ab80d29e:eyJzZWxlY3RlZExpbmVDb3VudCI6MTU1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI0Y2YwOWViMGM1NzQ0ZmI5NzMzMWI5OGZmM2ZiZjA1YTYwMmJhM2Y3ZjY3ZTVkYTViZTkwOTUwMzNmNjI1ODI1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI0NDFjM2NhNDkxMWNhYWY3OWU3YTE2OTM5ZDY3ZDg5OTY2YTg0N2ZkMDc3ZTRhZDU5ZjM0MTk3ZWFhY2QwOWY5IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI3YTM1NmNjMGQwZDg1YzZlMGE3N2M0MGU5NDIyNWQ2N2QwNmM2MDhlNmQwZmI5MjI2OGFkNWM2OTA4ZGRkMGY5In0" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/quickstart.json b/openwiki/.claims/quickstart.json index dd74fb0c..3e9e43d3 100644 --- a/openwiki/.claims/quickstart.json +++ b/openwiki/.claims/quickstart.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:acf6dc6d43a7314db512e046d19dad8aa17f3056196ad9c5f6b540a591bb4d73", + "pageVersion": "sha256:ed6123ee29f371389d58e4ef425a381efb7f9a251c135b317d168b2e7ec27e70", "claims": [ { "id": "claim_83870f4f1ad6403ea0d8bd8775729a76", @@ -26,15 +26,15 @@ "evidence": [ { "resource": "repo://TFI/App/MobileRootView.swift", - "version": "repo-file-v1:sha256:5391ee5b542127ba539cac32e1f3d49c335e78f9c09aa06499c6c61fd00e42fa" + "version": "repo-file-v1:sha256:f7b86ed89575ed3b8d34683c776d646efa81ead11ae75f125ed47b2ae384e99c" }, { "resource": "repo://TFI/App/TermindIOSApp.swift", - "version": "repo-file-v1:sha256:9daf1c0933fdbcff826165a8edc171876c54faa343a184348284e63f736e86bf" + "version": "repo-file-v1:sha256:a6722f9b8e04de670c0e17ec823b23cd344c8cdfe9286052edb9bca9854f43f4" }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:fcf66bc2cd5aa8569f2f1a7074d91ede68b5509b387d5c14508affb8f79ba8a0" }, { "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L17-L49", @@ -48,7 +48,7 @@ "evidence": [ { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:fcf66bc2cd5aa8569f2f1a7074d91ede68b5509b387d5c14508affb8f79ba8a0" } ] }, @@ -57,8 +57,8 @@ "statement": "`TermindIOSApp` performs language migration and creates a single live or testing `MobileAppModel`; its window injects the model container on success and presents an unavailable-data view when startup composition fails.", "evidence": [ { - "resource": "repo://TFI/App/TermindIOSApp.swift#L5-L33", - "version": "repo-lines-v1:sha256:1574c44f26f386fca5834af375adbea23b9471aaca384b9aa647006e94caec2e:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVjZmJkYmI1MDE2YWM3ZGVlYTU2ZTg5MGFlOTNhZDc3MzY1Y2I0ZDhhMGQ4NjhiMmU2YzliZTNjYzExYzQ2NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE0MDI1ZTA5ZDBlYTM3ZDMyNTYyMDVjODkwYTg5YjU0NmE0MDcwNTg4MDJmZWUyZDY1N2Q2ZjJmODg5MzllMTAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQwOWRlZDA1YTMwZTBiMDk1ZjI3NWRkNTcwMzRmNzU2NTgzNjBjOWQ4ZWIyNTg3NjNjNGI0MDMwYmM5ZGRjYjEifQ" + "resource": "repo://TFI/App/TermindIOSApp.swift", + "version": "repo-file-v1:sha256:a6722f9b8e04de670c0e17ec823b23cd344c8cdfe9286052edb9bca9854f43f4" } ] }, @@ -112,7 +112,7 @@ }, { "resource": "repo://AGENTS.md#L40-L48", - "version": "repo-lines-v1:sha256:e0e8c9958812182ec2d7001a28a31979a8ef4bba9255fe9f04867d56046faca6:eyJzZWxlY3RlZExpbmVDb3VudCI6OSwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiOTdmYzk4NmVmMDFlZTVmNThjNmYxZmEyNjViOGE2NDEzMTE2OGY4YWE1OTkzZDc4ODZkOTZjNmUxODk4OTQzMiIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODQ1MThlZDQyNWZhZWNhNTgxNGExYzEwMTU0ZjEzMjgxOGViM2VjMGI2ZTgzOThkZjQ5NGI4YWRmN2MzYTI0NiIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiZDFkYTg3Nzk4Y2M5NTc1N2I3NzQ0NThlYzQ5Yjg0MWRjYWMzODA1MWQ5MjljZGI5ODE5MGJiMTdiMjdkZmQ4OCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMGVkYzQzMzI5OGFkNTgxMjllZTBhODg1MmMxM2Y1MjkyMGRhYWY5NGE4YzY0YTQ4NzFlZWVmNDZlMTMxNWVkMiJ9" + "version": "repo-lines-v1:sha256:1504391daf2c6128093191cf4154eebb7c2a830ea322086e3cbf2a30066708cc:eyJzZWxlY3RlZExpbmVDb3VudCI6MTMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijk3ZmM5ODZlZjAxZWU1ZjU4YzZmMWZhMjY1YjhhNjQxMzExNjhmOGFhNTk5M2Q3ODg2ZDk2YzZlMTg5ODk0MzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg0NTE4ZWQ0MjVmYWVjYTU4MTRhMWMxMDE1NGYxMzI4MThlYjNlYzBiNmU4Mzk4ZGY0OTRiOGFkZjdjM2EyNDYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQxZGE4Nzc5OGNjOTU3NTdiNzc0NDU4ZWM0OWI4NDFkY2FjMzgwNTFkOTI5Y2RiOTgxOTBiYjE3YjI3ZGZkODgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBlZGM0MzMyOThhZDU4MTI5ZWUwYTg4NTJjMTNmNTI5MjBkYWFmOTRhOGM2NGE0ODcxZWVlZjQ2ZTEzMTVlZDIifQ" } ] }, @@ -125,10 +125,98 @@ "version": "repo-lines-v1:sha256:a556c3aea2c14cdaa85d89a15243c4606e48562f600fe675a3e4f75594c7a07e:eyJzZWxlY3RlZExpbmVDb3VudCI6MywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2VkMDNiODMzODVkNTYyYTZmN2VhN2FjNzljMDRjOTAyYjliNDc1YmU2ZGRmMGJmZWU4NmJmNGY1MWYxMTAyOSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiODI1YTI1OWIwZmM4NzNiZDgwYjhhOTVlYzE0NTVlYjI4YWNmMDBjZDE1YzAzZGQxN2Q5NGU4YmVlNDI4NTEzYyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTAyZjA5NDM5NjA4ZjcyZGY0MzQxYzNiZWJlODVjNDFiMGI1YWQyNmFmZjY1ZTYwZDhjZGI2MzAzNjAyNjAxMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9" } ] + }, + { + "id": "claim_c024c979a5864f7c864a6e33042d4316", + "statement": "MobileAppModel aggregates scene phases so all scenes must background before it pauses monitoring, memory, sync, metrics and outbox; background-task expiration suspends workspaces, stops forwarding, pauses transfers and expires the Assistant, while an active scene resumes eligible services.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:b24747ff9dedd849a5aabeba6b978fa6c7e3b61954033dcee5163d5ed8064123" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift", + "version": "repo-file-v1:sha256:f7b86ed89575ed3b8d34683c776d646efa81ead11ae75f125ed47b2ae384e99c" + } + ] + }, + { + "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.", + "evidence": [ + { + "resource": "repo://TFM/App/TermindApp.swift", + "version": "repo-file-v1:sha256:fcf66bc2cd5aa8569f2f1a7074d91ede68b5509b387d5c14508affb8f79ba8a0" + } + ] + }, + { + "id": "claim_454657f6df2c48f0ba5f8d101fc90939", + "statement": "Mac app termination fences new Assistant work, cancels and drains conversations and pending preparations before agent resource closure, while stopping MCP and transfers; AppKit receives one termination reply on cleanup completion or after a three-second fallback.", + "evidence": [ + { + "resource": "repo://TFM/App/AppModel.swift", + "version": "repo-file-v1:sha256:197fa5f7cbf890923e277a7e68154263c39a7c6751f07f399bf960ab016ebb41" + }, + { + "resource": "repo://TFM/App/TermindApp.swift", + "version": "repo-file-v1:sha256:fcf66bc2cd5aa8569f2f1a7074d91ede68b5509b387d5c14508affb8f79ba8a0" + }, + { + "resource": "repo://TFMTests/AppTerminationTests.swift", + "version": "repo-file-v1:sha256:b20c89cdeef69667b3220ca2e4ce86656855ed4b9d942a4b1dfd0f046bb4ecdc" + } + ] + }, + { + "id": "claim_ff89031fb529435fa8af6ac31eabda49", + "statement": "Mobile scenes share an app model and its live workspace instances, but each MobileRootView creates a scene-local navigation model; saved descriptors are restored without reconnecting at cold launch and connection-history entries are ended when the owning workspace closes.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:b24747ff9dedd849a5aabeba6b978fa6c7e3b61954033dcee5163d5ed8064123" + }, + { + "resource": "repo://TFI/App/MobileRootView.swift", + "version": "repo-file-v1:sha256:f7b86ed89575ed3b8d34683c776d646efa81ead11ae75f125ed47b2ae384e99c" + }, + { + "resource": "repo://TFI/App/TermindIOSApp.swift", + "version": "repo-file-v1:sha256:a6722f9b8e04de670c0e17ec823b23cd344c8cdfe9286052edb9bca9854f43f4" + } + ] + }, + { + "id": "claim_bab15ba1864d4119a35c8d60fd8c76a5", + "statement": "Mobile key-window integration tests are opt-in with `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1`, disabled parallel testing and a narrow TFITests filter; manual-authorization StoreKit tests are separately opt-in with `TERMIND_STOREKIT_TESTS=1`.", + "evidence": [ + { + "resource": "repo://AGENTS.md", + "version": "repo-file-v1:sha256:7c19a99ec73d4473ac94bb134b62a1306c62d1285e5b8af26430f1d466de35a7" + }, + { + "resource": "repo://TFITests/MobileEditorToolbarTests.swift", + "version": "repo-file-v1:sha256:b7bdc9c7e0f80d81f6610283c947786cfc0f0d13dc06ddd683a4240e1236b38a" + }, + { + "resource": "repo://TFMTests/StoreKitTrialTests.swift", + "version": "repo-file-v1:sha256:74c325de244d31d41b7799dd7a8bf4694630e4cb98e3d1b1b2ab165bc6d41765" + } + ] + }, + { + "id": "claim_b929e9957fc64a1fba4955c60b9c8b83", + "statement": "App copy changes require completed simplified and traditional Chinese translations and the localization script, while language behavior changes use AppLanguageTests and website changes require a production build and English/Chinese route checks.", + "evidence": [ + { + "resource": "repo://AGENTS.md", + "version": "repo-file-v1:sha256:7c19a99ec73d4473ac94bb134b62a1306c62d1285e5b8af26430f1d466de35a7" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/testing/behavioral-boundaries-and-fixtures.json b/openwiki/.claims/testing/behavioral-boundaries-and-fixtures.json index be54c440..a77454fb 100644 --- a/openwiki/.claims/testing/behavioral-boundaries-and-fixtures.json +++ b/openwiki/.claims/testing/behavioral-boundaries-and-fixtures.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:9579877be3cc10fce322964052e0c007da12304bb1edf564dab07afb04cea323", + "pageVersion": "sha256:15029cc4d76549f995f92d10b81402f0764575eeb49c402d9577fa1bc5c8756d", "claims": [ { "id": "claim_b7fbd64158554b8b8ca80a0a613b3bc3", @@ -272,47 +272,173 @@ }, { "id": "claim_612b95bf7d214bf6b16c67c57ea31156", - "statement": "Application edit tests reject invalid replacements before repository calls and preserve live history after injected repository rejection; controller cancellation after committed editing checks interrupted staging adoption. These fixtures replace the persistence port and do not inject real SwiftData storage failure.", + "statement": "Conversation operations reject a non-user replacement without invoking truncation and preserve visible messages and transcript when an injected repository truncation rejects; controller edit-failure and post-edit cancellation tests check captured replacement context, preserved history, and interrupted real-run adoption of staging. These port-level failures do not inject real SwiftData transaction faults.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantConversationOperationsTests.swift#L228-L266", - "version": "repo-lines-v1:sha256:d504dc650e02ce7236152c633382cef19bd6762a026047c05f7c1ad0785f7a7c:eyJzZWxlY3RlZExpbmVDb3VudCI6MzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEyNWIwMmI1NzE0ZDA2NmZkMzIxNmQyMjMxYmRkZGFjYjM2ZDcwODc3OTE4NmRhYzg5MjQyYWViZDA2ZjQ1M2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiYjYzYjhkYTE1ZTdkOGZhNDBlNjhmYjhkNjY0YzhjZDQ4NGFlMzQ4NGEyMjEzNWU0NDAwYjA4NjI3Yjg2ZjciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIyNWU4YzMwNjkwMDIyNmYwNDA2OWM5YTZmMTZjNmY0ODE2NzkzYzM5NTNjZDM3YWFlNzQ5OWY2OGQ1YjAyNmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ" + "resource": "repo://FrameworkTests/AssistantConversationOperationsTests.swift#L473-L512", + "version": "repo-lines-v1:sha256:1eacb7da0a9be772b50964fdc54146c45614974861d3a1f6012b27a56dd08053:eyJzZWxlY3RlZExpbmVDb3VudCI6NDAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjEyNWIwMmI1NzE0ZDA2NmZkMzIxNmQyMjMxYmRkZGFjYjM2ZDcwODc3OTE4NmRhYzg5MjQyYWViZDA2ZjQ1M2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImIyNWU4YzMwNjkwMDIyNmYwNDA2OWM5YTZmMTZjNmY0ODE2NzkzYzM5NTNjZDM3YWFlNzQ5OWY2OGQ1YjAyNmIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZiMDM2MTMwMWU4MTI1M2UyNTUzNzExYmY4ZWUyOTU3NzBmOTY4NDYyZTY5YjZkMjIwNTc4NWQ4NzJjNjFiZTAifQ" }, { - "resource": "repo://FrameworkTests/AssistantConversationOperationsTests.swift#L290-L309", - "version": "repo-lines-v1:sha256:1aadebda28ab65aaf172c7524dd75bfbc882c73879618892eee83488349e51aa:eyJzZWxlY3RlZExpbmVDb3VudCI6MjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyMGI5NDg0YjQ4YTE3M2QzMTM2ZjhkYWRiNzdiNTUwYWQ5ZmRiMzU4YjMyMjllNTRjOGQyNjg1NGNkMWVlNGMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijc1MjhmNGExMDgwN2M3ZDcxOTRjZTUxNTlmMzNmMjFiZjM1YzYxMzA5ZGNhNDkzNjgyOTViZjBkYzE3Y2QyYTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZkMWY5Njk2ZTM2ODQ2MzcxNzIxODJiOGMzZmNlMWFlMzQ4Yzc4MzJkOGU4OTE0ZDVjZjJlZjU1NDIxNDIwYWUifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L596-L619", + "version": "repo-lines-v1:sha256:9013a9b0c8dda08deb9c74c8b93dd354b89a5d981c5c43457c083341a7639434:eyJzZWxlY3RlZExpbmVDb3VudCI6MjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjZjMWE5ZjIzZTE1YzkwM2U4NGYxMDdkNGI4YmQ2NDZhYjcwNmRkNmEyNjczZWI5N2VhMTZkODc0ZTRhYzMxZTUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImEwNTYyNGUyNDJmZjU3YTY0YjU1M2YxMTQzNzBlMmQxZmViYmU4ODIyZjI5NzA2ZmZlYmI4YTgwZjVhM2FiMzcifQ" }, { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L450-L534", - "version": "repo-lines-v1:sha256:fd0683e00df11cd8ca35568565d1b1d43a68ad37ab7bf54e5f68803954f14349:eyJzZWxlY3RlZExpbmVDb3VudCI6ODUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZkYTc3OGQ5NDJjNzRkNGFjOGYzMmM1MTgyMDg2MGFlOGE2MDQ5YWE1NDUwYTE5NjMzMTM4MmNmNWVmNWU1MGEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk1NTUyNmNmOWEwOGQ4Yzc1ZTA5ZThhMWZhMTIwODkxZmQ3MWEwMDNhMjkwY2U5ZTEzY2YwOWQ5NjRmYjkxYWUifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L719-L747", + "version": "repo-lines-v1:sha256:cafc285231544b00272d58ff3d5e4205703f2bd167937c426e285a131b1184ec:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE4ZGIwNzEzYzU1NTE0MjI3ZmQ3NGRmMTNlODYzZjQyMTU0MGFiMDk1YzVhNDU2Mjg5OTJiYzE3YjdlZDE1M2MiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk1NTUyNmNmOWEwOGQ4Yzc1ZTA5ZThhMWZhMTIwODkxZmQ3MWEwMDNhMjkwY2U5ZTEzY2YwOWQ5NjRmYjkxYWUifQ" + }, + { + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L987-L1004", + "version": "repo-lines-v1:sha256:9108dcb76cfe849fe223f5949339615531b451b34f5d1bd2950254864f3cad06:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjUwZjZmN2RhOTIxZWZhNTY1NWE3YTRiODVmYzc5MGIzNDEzYmNhMmM5N2NiYmJlMThkMDYwMWZkNjAwZDhjM2EiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY2OTQzMDY2Y2ZmNTM1NDRmYWI5M2UwNTUxZTNiNGYwYjQ5OTEwMzg1YjRmZGU4YzAyOTBlOTNjN2RjOTE4OTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoyLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFiMDdjYTMxZWU1YjNkMTdjMmY4ZGZmYWM1NWU2Njk5ZjVhN2MyYTBlOTZhY2IzNDExNjdhZjAyNTUzN2YzMGEifQ" } ] }, { "id": "claim_9b91e98a29a34c4caa268050b13a5f3e", - "statement": "Missing-credential and selection-during-preparation tests wait for the recording repository's failed snapshot as well as checking live failure because production captured failures publish before asynchronous save; actor waiters handle both already-recorded and future snapshots.", + "statement": "Captured missing-model or missing-credential preparation failures construct a failed snapshot and keep preparation active until an asynchronous repository save succeeds; only then does the live conversation record failure, while a save error appends an assistant error instead. Controller tests gate the save and verify joining/projection ordering; missing-credential and navigation tests separately wait for a recorded failed save attempt, which does not itself prove save completion.", "evidence": [ { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L231-L255", + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L376-L400", "version": "repo-lines-v1:sha256:63509c11ab1c2718bead3930614de6427e1e6df47c0e787aeed401498661891c:eyJzZWxlY3RlZExpbmVDb3VudCI6MjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjY0YzVmZGJhOWRmZTUwNjMwNjlkYTdlN2RiZWVjM2QzZWRiNjE3YmUzMTQxYjBmNGEyYzY0OTEzNWI0N2M2ZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImIyMzkzYWYzYmRiOTExYzA2ZWFmMjNkYjMxZTkyMmNkNGY3NDc2MmYzNGFmMTE1NTJkNDczYzc1ODhhZmFhZTkifQ" }, { "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L66-L86", - "version": "repo-lines-v1:sha256:80d25cc0451a928bc50f91e07a28b411b83c0d7299889938c179b8d5e96fb33b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY1OGZlNzcyYzJiNDExMGEyYzJhOWQxYTk5MjI3OGY4ZTNmZDg5YzMzNzJlZjZmYjE0Y2NjYmU1NDU3MmQyMWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZkMzMwZjllZDlkNjUwYTVhMDRlNTk4Y2YxNmE2NmZkOTM3NWZjYWIxMzhkMmJiNmE0MWYxNTJjYzRjMjExNDQifQ" + "version": "repo-lines-v1:sha256:80d25cc0451a928bc50f91e07a28b411b83c0d7299889938c179b8d5e96fb33b:eyJzZWxlY3RlZExpbmVDb3VudCI6MjEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImY1OGZlNzcyYzJiNDExMGEyYzJhOWQxYTk5MjI3OGY4ZTNmZDg5YzMzNzJlZjZmYjE0Y2NjYmU1NDU3MmQyMWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijk3ZGY0M2ExZTA3MDM2YzJmMjk2OGUwYzdmMjZhMzQ2ZDJjOTliNWU4MmUyYWU2ODFkZWVhODQ5MWFlMmE2ZWUifQ" }, { - "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L661-L689", - "version": "repo-lines-v1:sha256:74df831f049f3d94b2df3e3684005e41efcfdbae4210f2a76d72f07088772ff4:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjI3M2UyMmU5ZjA4MTYzZWY3NDM5ODE2MTc3YzcyODZiZjg0MGRhODFhYTAxODc0ZTUxOTExNDM3NTNhNTIzNTMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4YTQ5OThkMTFmOGNhNTNkOWY1ZWE2OWQ3ZmJmYmE1MGViMTFhMzBhMTdkNDZiNzQzZDZiN2EyNzA5MDhlYzciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImVjYWZkOTVhYTdjMWM0MzA0YWEyNTI0OTg4YWNlMTM1NjQwMjU1MGZjYTg1ZmY5ODlhODEzYjNmNTEwNmJmZDciLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImRlMzE4ODBjNjRmODIxZTk5ZmMxNGNjNWE0MDY5OTE0MzQzZTIwNGUwYmQ3N2U4NjU5ODhjMzQ1Y2RkZTdiMDgifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L89-L184", + "version": "repo-lines-v1:sha256:8ecd718a0eeee7e604484a492c11582ee8447262bfc696d0429756e8a19915d0:eyJzZWxlY3RlZExpbmVDb3VudCI6OTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY4NzZiOTY4ZTBiYTUzZTU1MTZkN2QyMzg4MjAyNTY1NjNkOTU1MzQ3OGVmYzEwNmExYWE5NDllMWM0YTk5MmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjVlNDExNjlhZjJjNDQ2NjUzNzVkOWJhMjYwNmRhOWUzZjk4YzQwZGUyOTZlNGU0N2RiOWM4ZTJjYjQ4ZjBhMTAifQ" }, { - "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L765-L793", - "version": "repo-lines-v1:sha256:e87d08aec434dbaca6f03d91f4f5c0cab6e7e04e6040b3e13dc277d1eff4ed2f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU4MzY5NDdmMWVlZjZmNjIwZWJlZmQzMGE0N2EwNWI4ZDhiZWI2ZTNkYTFlZjkzOTM3MTg5OTZiZTI1NDkxYWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImE2ODhmNzU3ODA1NDczNjk2N2U4NzY5MmJiYTg2YjI4MDhmMzI0MTk3NTQ0MDVlYmZkNmM0NWI3MTk4OWQ0NzQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ3MTVmNGViNzI5YTZmMGMwMDk2MWMyN2JhMzFjNmU2ZGQxNWIwNTFkOTRhOGI5NzY3YWQ4Zjg3NGZmODBjZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjRjNmM3Y2RjOGM0ZWMwYmM5ZGU4ZTY5MThmYWUwYWE5ODQ0MTJiNDJjZTVjMzY5ZWExZTMzMjg0N2Y4ZjIyOWIifQ" + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L909-L953", + "version": "repo-lines-v1:sha256:cb72be486241cd24fb1ff192767f453dfdcfc06fafcf88fccc805a2499e50915:eyJzZWxlY3RlZExpbmVDb3VudCI6NDUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjhjYTIzYTEzNjJkN2VhODNlMDQ5ZDU4ODU1ZmI2NWEzOTEyMzZiODJjN2JjOTUzNzgxYmZhMWM3N2RjNmZjYjgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImMyYjM0ZWYyMjY4OTRlMTE4MjQxY2JhMDZlYjlkNjE2ZTg1NTQwYzNlMjA1MjlkZDE5YTdjYTVjYThlYzNmZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjViMjI1MGU1ODYwNmNjNTE3NWNiOWMyYzE3ZmY3ODU5NzM5YzMxMDQ4MDE3ZjYxMjJkYjU1MGVmM2Y4MTljNjEifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L359-L384", + "version": "repo-lines-v1:sha256:4a022fd2ff113b343d83bcbf21049418b3b9cfecd4cca03ffbf010665fcbea4d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxOWFhMTM0NTE5ODU0M2M0MTVlZjcyZDYzMDcxMmRmOGE3YzRhMzE5YTgzZWQ1MGRjMzJjOGViZmFlY2UyMWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImRjMWRjYmZiMTVjMWU5ZGNiMDFiODBhZTEyMWMxYTJjYjM5NDkyNzkyZTAwNGI0ZDcxNTg3Yjg3ZjRlZjgzMTUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU3MDMwNGY3Y2ZhYzBhYTM4ZGEwYjQ0MWZhYTc3MGQ4NWQwMzJiOTJjNDAwNTk1Y2E1OWZlODAwNzYzMTYwYTUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImFiMDVjYjY2MmMxYmVkOTlhYTM5ZWIxNTEwNWEyNTkwMGI5ZjEwOTJlOWU5MTI5NTcwZmQ5MjA2NGRlYTY1OTkifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L784-L821", + "version": "repo-lines-v1:sha256:bd653d42cab6085696236694f1bade43057e0ef81deb1a80530564cd9052282c:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ5NDc3Yzk3MjM2ZjdjMzNlNGNlYmM4Y2Y0MzQ4NmEwYzU3YmQ1ZjFhMWFlZTY1ZTc4YzM1ODZkNmIxM2Q3MDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ3MTVmNGViNzI5YTZmMGMwMDk2MWMyN2JhMzFjNmU2ZGQxNWIwNTFkOTRhOGI5NzY3YWQ4Zjg3NGZmODBjZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkxNDVmN2U5NmE0M2YyYjc3N2RlNTYwODkwNTUwNjJhY2JlNzk1MWQ1M2FiYjFkNWQzYWI0NzIxNjdmODBkMzYifQ" + } + ] + }, + { + "id": "claim_015d1c1ddfdd41aab15c7f0554d2c1c9", + "statement": "Manual compaction is refused while agent preparation is held at a memory snapshot barrier, without starting compaction activity; edit and cancellation fixtures also prohibit stale or cancelled prepared edits from entering truncation and join in-flight truncation before recording interruption.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L279-L374", + "version": "repo-lines-v1:sha256:50f7ba5dd5a79924a379eebd2254833cb2f3459b25e2cf641a47f2e54f3b75d9:eyJzZWxlY3RlZExpbmVDb3VudCI6OTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNhYTJmZDVlYWY1OGI2OTc2ODY3MzYxOGRhMTY0MDU5NWRiYzRmMWMwZGNlMGMzMDJmYjkzZGFkZDE5M2ZjNDEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxNTEwODE3N2ViMDRiOGRiOTZhNmI0YWE0YTM3MTZiMDBkZGY2NjFmY2FkOWY4NzA5Yjc0N2Q2YjYxMGVlYzYifQ" + }, + { + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L519-L540", + "version": "repo-lines-v1:sha256:86b94fd10a8c9d7ca8a12fd280f314f6ed57b669f92add6b32897973ab5fbe31:eyJzZWxlY3RlZExpbmVDb3VudCI6MjIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImUxNDk2NDE4YTVkMGU3OTIyYmYzZjczOGMzMzJmZmNhM2UxZGJlMjkwNmFiMWVhMzBkYmE1YjVmNzdiNGYzNDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBjOGE2MGMzNzZlZGJkOWFjYTMwZGY1NDgwMjUwOGVmMDcxYWU4YmYzN2VmZWE3ZjI3ZTkwOTk0Y2VhZTBhYjAifQ" + } + ] + }, + { + "id": "claim_e1546ff6a4b548049848c0da7aaf53ef", + "statement": "After an edited replacement commits, a pending failed-run save blocks further edit and fork and later adopts the real failed-run ownership; if that save instead throws, preparation retires without adopting staging or recording a completed failed snapshot and displays an assistant error.", + "evidence": [ + { + "resource": "repo://FrameworkTests/AssistantExecutionControllerTests.swift#L651-L716", + "version": "repo-lines-v1:sha256:24a37e6db9a28e2df6a846c75003bc452e86c9b046243ad437f00bc7775874a2:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjczZDI1MDVmNDM1NjgxMTE3ZDRhOTY5MGVkZjE3NmVkNzBjZWFiYzhhYmU2N2JlODMyOTIxOTRkMjVhYTU2OWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjJhOTU4ZTIzMDAzNTJiNWU3NmQ0YzYyZWM3ODUyYjY4NjViZTQ4ZDgxODg3NDg2Nzk2ZTkyMTI2MmZkNGRmNTcifQ" + }, + { + "resource": "repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift#L784-L821", + "version": "repo-lines-v1:sha256:bd653d42cab6085696236694f1bade43057e0ef81deb1a80530564cd9052282c:eyJzZWxlY3RlZExpbmVDb3VudCI6MzgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ5NDc3Yzk3MjM2ZjdjMzNlNGNlYmM4Y2Y0MzQ4NmEwYzU3YmQ1ZjFhMWFlZTY1ZTc4YzM1ODZkNmIxM2Q3MDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ3MTVmNGViNzI5YTZmMGMwMDk2MWMyN2JhMzFjNmU2ZGQxNWIwNTFkOTRhOGI5NzY3YWQ4Zjg3NGZmODBjZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjkxNDVmN2U5NmE0M2YyYjc3N2RlNTYwODkwNTUwNjJhY2JlNzk1MWQ1M2FiYjFkNWQzYWI0NzIxNjdmODBkMzYifQ" + } + ] + }, + { + "id": "claim_78f8d81d663b4c5fb8f7c9ca60534d7b", + "statement": "Tool presentation regression tests protect the composed AgentKit/Termind presenter ID namespace, equivalent restored and legacy card detail, safe decoding of older metadata, and structured approval details that include provided command/input rather than promising redaction.", + "evidence": [ + { + "resource": "repo://TFMTests/AgentToolPresentationTests.swift#L18-L96", + "version": "repo-lines-v1:sha256:d7cbb9925387883a07ea20a4a73a0ec7adc642a071ffd321b25567fa02aaa9ca:eyJzZWxlY3RlZExpbmVDb3VudCI6NzksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNmZjQxNDhjYTY0MjI2YzYyNzM2MDM3ZjMwMDRiNTMyMGM3MGJkZDYyODMxYWFhOTM4YThkYjY0OTFhYTViNDYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjM5OTE0NGY4ZTFmMTAxMDVkZmFmY2FmNGVmMWQ2OTA4MDA5NmM4NTI3Yjc1MDY2OWM0NzFhM2FjNTM1NzFmYmQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY3Yzg4MDk0OGI3YmE3MDJiMGJkODA0N2FjNjc4MzdhOWZhMjIwYzQ5YjEzMzhlNGIwZDljYTYzMmVlOWFmYmYifQ" + }, + { + "resource": "repo://TFMTests/AgentToolPresentationTests.swift#L733-L823", + "version": "repo-lines-v1:sha256:498039f24b8065013b6cbe6421281c9b4213a1c879d3df28c5e5d82357451c2a:eyJzZWxlY3RlZExpbmVDb3VudCI6OTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjRhY2VhZThhMWRmOTZjNDQwMjA2YzIxZGNmNzEwMGE3MzQ4Nzc0NjliMzE5NGJlZjg5OTg4ZDIxNTU5MmU2OWQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNjMzA4ODIxYWI0YzcyYzNkYmM0N2Q3ODJmNTc0NWQxYTUxZWI0OWM3YjJiNmZkZjVlZDM4NGNhNzNjYjE5NGMifQ" + } + ] + }, + { + "id": "claim_08a2265b3a6242e5ad6c9270b9c8f61c", + "statement": "MCP upload tests exercise scoped ticket capacity, acknowledged-offset resume and full digest, stream backpressure, cancellation and cleanup, conflict and terminal status with a fake SFTP client and controllable clock; a loopback HTTP test sends fresh and resumed bodies beyond the ordinary MCP body limit without a real remote SFTP server.", + "evidence": [ + { + "resource": "repo://TFMTests/MCPUploadTests.swift#L109-L199", + "version": "repo-lines-v1:sha256:0bb89d05c6cbf912adddacee09067a7294ed505b654a33d63ca6d29d90465dc0:eyJzZWxlY3RlZExpbmVDb3VudCI6OTEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjNiMzJhMTA1NTNkMjE1N2I1MGQ5NmE3N2FlMGI3NjAwNjIzMmUzZTE2MjE0NmVhMDM4YTI2N2IyZjFmYzk0ZjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBmZWRkZDIzN2RmMzgwNGU5NzZkNmMxZDg2MDAzZDc3YTYxZTZhM2E5MDE1YTAxMTMwOGM0YjE5OGI3Zjk2MjciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU4ZWFmM2UxZGIyODRmNmE2ZmQ0ZTA2NmFlMmZiNjU0YWU2OGZkZmNmM2U3ZTRkY2E0YzJkZDIxNGE0OWI5ZDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjlhMjA2ZjE3N2FiZmU2OTRhODM5NGM3ODBkYzJiYTE4YWJmMjIzYmYwYjY2YWMzZWEyYWZjYzY0ZjUxZTgzYjQifQ" + }, + { + "resource": "repo://TFMTests/MCPUploadTests.swift#L16-L45", + "version": "repo-lines-v1:sha256:76eac58ab509219efc87394272fa4f8b9cd1a4d536657160e9cef6e5cba8af4e:eyJzZWxlY3RlZExpbmVDb3VudCI6MzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlmY2VkNmIzYWFmM2IzNmM0NzAzNjhkNTU0YjBmMDNiZjBhMjVkNzQ5YzQ4ZjMyMjA2YmQyNDI1ZjI5Njk2ZTYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU1ZDNlYzM2MGVlNTljOTZkOWMxMTllZDExZGFjMTJkYTcwMTM2MTRlZGMwM2ZiYTk2MmJlZWYyZjE4N2M3OWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjliZTNjNmIwMjM5ODhlMjA5YmZkOGMzMDY1ZmM4MWIwNDFiYTk5MDQyNzcwZWFmM2E1ZGUyMGJmN2M5ZjY1ZDcifQ" + }, + { + "resource": "repo://TFMTests/MCPUploadTests.swift#L202-L381", + "version": "repo-lines-v1:sha256:d35498fb2c532e5cfede2e6a33accc1124a60650c89cd716d1d1ea45bc458781:eyJzZWxlY3RlZExpbmVDb3VudCI6MTgwLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJiYjM3ZGE1YTY3NzA0OWMwMmY1NjRmM2YzYjkyNmJkYjEwYzRlZWQ3MzZiNzQ3NzExOTBhYjMzYzI1OTY0ZGE1IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiIwMWJhNDcxOWM4MGI2ZmU5MTFiMDkxYTdjMDUxMjRiNjRlZWVjZTk2NGUwOWMwNThlZjhmOTgwNWRhY2E1NDZiIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI2NjQ2Y2JlYTllMzY4MTQ3OTFkZTE3ODNmMDEyMDQ0MjU2NDg1OWYxMzE5ZDU3ZGQyODNiODFjMmJmZmFjMzA0IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJiZjAzZTljZDBlYTM4ODg3YmEzMWY1Y2I0MmE0YmU3YmE5NmFiYmYzYTFhZjgxMjgzODRhN2VhNzQ3NTg4ZGZkIn0" + }, + { + "resource": "repo://TFMTests/MCPUploadTests.swift#L391-L500", + "version": "repo-lines-v1:sha256:6170abf4e6d6c895681fde4c067cfeb4b4734b75e207845a710c285214a1373b:eyJzZWxlY3RlZExpbmVDb3VudCI6MTEwLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI1MTg1NWJjNWI3NWNlODEzOTE2MmQ1YmZhMTgwN2QyNDY0ZmE2OWU4NjVkZjliMWRhMWQzOTk1YjZmMjg1OGYyIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJjNmRlZGI4OGE0MDg1YTJlMmY2ZDlmMmNhNGMzYjhjMWNhNjk4MGFmNzY2ZmY0ZDhjYmI2YjhhMWJkYzI2ZDYwIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI4ODJjOWQyNDhhODY1OGM5ZTFmMWE3NDUyMmQ4MmY3ZWQ3MjBkYjhkNTk1ZTRlZWRiNDA0OWMyMzg0YzA2NGQxIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI3MTQ0ZGU3Y2Y5MGQzMmQ3YmRjMjVlNGNiY2Q3ZjIxOWQ4YzhkMjk5OTAwYjhlZGU1MjNhNGI5YWNkYjIyOGNjIn0" + }, + { + "resource": "repo://TFMTests/MCPUploadTests.swift#L503-L535", + "version": "repo-lines-v1:sha256:e417524e821c08d749ebf77615bc01268917ebf059f0eb5c54948f8e4940c32d:eyJzZWxlY3RlZExpbmVDb3VudCI6MzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjlhOGYzMTY1Zjg0NDE1OWE5ZTM4MzQxN2Y1ODY1MjNlMTE3MTBiYWNiN2UyZTMxMDVhMzJkYTIwZGRjYzA3NjciLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEyZTkzYjBkOTk4ZmY2M2Y4ZWZiYmEwZGE5Y2Q2NGU3NDY0YjU1OTNkNDMyMWNmNmQ1ODcwODM4MDU3ZjE0MTgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc1ZmRhMmE5MmMwNmVjYzllMjc4ZDMyOWE3NmY3MTA2NmQ4OTI3ZGVmNDdjOWFmZWFmYTFmN2U1ZWIxMjhjZjMifQ" + } + ] + }, + { + "id": "claim_73eb465055b04cc5bd7cb9a079bec417", + "statement": "MobileBackgroundController retires a background lease once; platform-spy tests cover repeated/stale expiration, synchronous reentrant expiration during begin that preserves a replacement lease, and invalid task identifiers that expire without ending a UIKit task.", + "evidence": [ + { + "resource": "repo://TFI/Platform/MobileBackgroundController.swift#L27-L84", + "version": "repo-lines-v1:sha256:b633f63ef830e7665dc60afef2702d82bfbfd1cac1b84192699778c674465a93:eyJzZWxlY3RlZExpbmVDb3VudCI6NTgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ0NzUxNDBlMjZlOWM1YTE3MTFkNjQ0NWExOGI3ZjRhZTIwMjJmOTkzZWY2Mjg0MDc1NTQzMDFiOTZlMGRjMjAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" + }, + { + "resource": "repo://TFITests/MobileBackgroundControllerTests.swift#L8-L95", + "version": "repo-lines-v1:sha256:4fffd4fec2a91bcf37361ae1bcc965d0cf134030e5ea98b1aaf9848a43796cc8:eyJzZWxlY3RlZExpbmVDb3VudCI6ODgsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImI4YzgzZDk2MmE2NDhmZWZkZTJjMjEzZDVkYjQwNWM5MThmNmRiMWU5MzdkMGI4MTMwNmU1ZDY2ZjI2Y2JkMmEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjgyNmNkODQwNGM5Zjc1MjhkODk1MDg3MzBmMTczMjc1M2JhZWZiZWQxMWFmZmI5N2FkNmRiNTllOWQ4NmE4MzQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjowLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUzYjBjNDQyOThmYzFjMTQ5YWZiZjRjODk5NmZiOTI0MjdhZTQxZTQ2NDliOTM0Y2E0OTU5OTFiNzg1MmI4NTUifQ" + } + ] + }, + { + "id": "claim_200f3513ad9e4572a43d268fb6a3f788", + "statement": "MobileCardTests verifies card width/accessibility column policy and stable measured heights offscreen, while exercising saved-host timestamp and draft-color persistence through an in-memory MobileAppModel rather than requiring a UIKit key window.", + "evidence": [ + { + "resource": "repo://TFITests/MobileCardTests.swift#L164-L245", + "version": "repo-lines-v1:sha256:4e761b34d17cd99ceb885160e9b2a7d2235d73f7b1a22b8321753a3f455ef939:eyJzZWxlY3RlZExpbmVDb3VudCI6ODIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY4ZDNlNWIxNTZmODNkNGNkYjAxY2E1ZGNiNWRhMTExNDc3NzA3M2U0ODA4YTllOGFiNDY2OWRjZTg1M2I5YWYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjY1NTJlNzJlOGU0ZWE2NDNkNDYyYmQyMTAxNTA3Mjg0NWY5OThiYjQ4ZDVhMjFhNTRhZGNjNWM1ZjZmMDhjYmEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjgwNTE0Yzc4NzM5ZDkxMzdiNWM0NDk0OThmOTA0NDI3OTEwMGJhODU0ZjIzMmYyZWZjZmRiN2FjNTI1ZGVmMGEifQ" + }, + { + "resource": "repo://TFITests/MobileCardTests.swift#L277-L280", + "version": "repo-lines-v1:sha256:2b493cc9e932c2c8fe37f9c4f23a298bbd2cccbf103160cd8b7d79f6b605c2cf:eyJzZWxlY3RlZExpbmVDb3VudCI6NCwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2FiMjk1ODIwZTMwNzY2ZmZjZGE1YjFmOGI0NGYxZjMwMTMyNTY3M2EyZWJjNzRmNzc4ZDU1NjIzOTJjMjUxMSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDg5M2Y0MGUzNzgxZWI4OTZjODJkMDQ2YTA4MDY3YTExZTM1Y2RmMmYxZGZhZjI2ZmVhOTBiOGRiNjY3NjQxMyIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiOTk5YmRlZmVlYWNhNjM0MGUwMjkwZGM4NmU4ODljODlkNWUxODlhYTViYTQ0YjU4NWIzYjcwNzM0ZjRhNjJkOCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiODkzZGM5OTI5ODM3NTQ3MmRkMTQwYTA1OGE0ZTlmM2QyYTIyOTczYzg3MmViZGNkYjI4OGQwMWY5OTEwMWQzNSJ9" + }, + { + "resource": "repo://TFITests/MobileCardTests.swift#L38-L86", + "version": "repo-lines-v1:sha256:dfabb2c83bfc0e5d451ff40166d6d3a4d1a5e3772c563ee00e5ac0228ea2061d:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkwZDExMDRlNGI2ZGUzNDcwNDllMmE1NTBlMGUwNjQ3M2UyMWJkNmZhNWYyZGQ4NWUxYmY1ZjNmZWNmNzhhZTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImZjY2Q5NGQ2N2E3ZjI4ODM4MDEwMTQ1NjZjZGM5OGYwZTJjM2M1MTRiOTBhODM4ZjY2YTgwNjVkMDRlYzgxMDcifQ" + } + ] + }, + { + "id": "claim_c18a815575dc4b92a35d831d9897a418", + "statement": "Mobile key-window integration suites are opt-in and must run without parallel testing because UIKit presentation state is process-wide; StoreKit tests require separate manual opt-in, and macOS visible-window tests retain their own opt-in gate.", + "evidence": [ + { + "resource": "repo://AGENTS.md#L40-L46", + "version": "repo-lines-v1:sha256:234a5eef8443b4d362174156c84cd70b777a307705ffd81785268d23fbf8080f:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiM2VkMDNiODMzODVkNTYyYTZmN2VhN2FjNzljMDRjOTAyYjliNDc1YmU2ZGRmMGJmZWU4NmJmNGY1MWYxMTAyOSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiMjBmNzBmODFjMjlmNzJjZWIzYjhjMGQwZWQ3MTBlNDMzYmJjMDgwNDNmNTBmOGZhMTdkNzU0NGRiZDA2NzA4ZCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYTAyZjA5NDM5NjA4ZjcyZGY0MzQxYzNiZWJlODVjNDFiMGI1YWQyNmFmZjY1ZTYwZDhjZGI2MzAzNjAyNjAxMSIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiZmVjYzgxYWMyZjE3ZWVjMDQwYzhjNWM2NzYwODkzYjJkNmJmMmJkMjVhN2M4MTlkMTBhMGMzMWZmMjE5M2NhZiJ9" + }, + { + "resource": "repo://TFITests/MobileEditorToolbarTests.swift#L8-L13", + "version": "repo-lines-v1:sha256:bada030d4a98c25e3cfa2f66f41e809a06dbeced7a912cf693f97fd2af314710:eyJzZWxlY3RlZExpbmVDb3VudCI6NiwiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiYzE4MDI1MDRmMjViYTNjZDBiOGZmMTAwYjk0YmViNTI2ZDVlZTI1NDFjMmQ4OTBkODFmM2E0OTY2M2IxMjFjMCIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiNDQ3NTE0MGUyNmU5YzVhMTcxMWQ2NDQ1YTE4YjdmNGFlMjAyMmY5OTNlZjYyODQwNzU1NDMwMWI5NmUwZGMyMCIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiYmNiZTZmZGYxZDQxMjk1ZjY1MDJiYTgxYzVkMmI3ZmU3ZDlmYTAxZmU1NDVkN2U2YTJhYmNjOWJlMzI0YjhiNCIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWU5OGYzZjc0YjBhMGM0MTQ2MGJkMDEzOWEyNzlmOGY4NWNhMDI5MmU5ZDM0YzI5ZjljYzUwOGRmMzE2OTIyOSJ9" } ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/workflows/sftp-transfer-and-external-edit.json b/openwiki/.claims/workflows/sftp-transfer-and-external-edit.json index e1ec61e7..89ce9c79 100644 --- a/openwiki/.claims/workflows/sftp-transfer-and-external-edit.json +++ b/openwiki/.claims/workflows/sftp-transfer-and-external-edit.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:cef9e5c9f0e1b70ca61f5e10ad12b40eff7609701401b8061dea667ff941840a", + "pageVersion": "sha256:bcad80bdae1c2dda36b882117fd053a20bce47dd9c10174cdbaec582ae1b38a5", "claims": [ { "id": "claim_5ca6241ea6cc4ebbb915ccbe304f8430", @@ -419,10 +419,172 @@ "version": "repo-lines-v1:sha256:ff6eb3116725e204720090c8a2e6ec95d0cafcf3a288a7d3875a5de54e506ccc:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiI2ZWRlZjM2OGUzMDY2MGY5N2M2ZjBiODYwNTM0MWJiYWMyNWZjZWRhMzkyYWUyYWViNzc1YjVkMjcxNDc3MGZiIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI0ODkzZjQwZTM3ODFlYjg5NmM4MmQwNDZhMDgwNjdhMTFlMzVjZGYyZjFkZmFmMjZmZWE5MGI4ZGI2Njc2NDEzIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIyOTBlMDhjMTViMzY3ZmY3ZDY0OTUxNmQ1OTE4YmY1YjE5ZDI4MjEzMjYzYWE1MzExMWE4M2NjMmE4OWEyOGYyIn0" } ] + }, + { + "id": "claim_c94e2ff9e5774371ad401400d839a924", + "statement": "Agent built-in SFTP read/write and scratch pull/push request logical-file admission, while SFTP metadata tools use the default non-data path; SFTP operations validate and normalize remote paths before using the authenticated pool lease.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSFTPTools.swift#L133-L206", + "version": "repo-lines-v1:sha256:7647a400325efb06e00b502f3195513ae9d3a66f5498707c795c3f0de4034910:eyJzZWxlY3RlZExpbmVDb3VudCI6NzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1YjdlYzM0MTVkN2YyM2M2Mjk5NDA1NzE1NTk1NDY1ZGFhZTAzNTcyMTc3ZTI0ZDhhNTcxY2Q0ZTgwNGFmNmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZhODhhY2FmNzgwYzRkMGFjOTBhMTY2ZDVjODdjMDVhYThjNTE0YmE4MjY2ZWViNGI3MWRhNGFmNjA4YWZlYTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjhmZWFmMjVkNTY2YWY3MDRlZDQyMDQ3YTk4MjY3NGQ0Y2U1OWQ0YzQ3N2NlZWQ4ODE0OGViNDc0MTIzMjc1OTUifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSFTPTools.swift#L26-L75", + "version": "repo-lines-v1:sha256:2dd802c6d28fc5e5338146df79eeffad4af2ac4af3bfacd2464aaba93c449bce:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImZlNjRhMmEzODVlM2IxNTJiN2U5YWFiYWQ5YjBlMzhmOTY4MTRmMTg3ZWE4NWUxZWZjZmJjMzVjN2MwZjUyYzIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImI5NTc2NTAzNzEwMDU0NWVkOTY2Nzc0NTUxYTBhOWJkOTg4NWRlY2M0MWY2OTZjOTgwMmEzM2VlYWI0ODZlMDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentScratchTransferTools.swift#L124-L146", + "version": "repo-lines-v1:sha256:7ffd0ebcfb86bc373a0dbb0e704ba6546f32af2bedc82eb98baa97443da09e34:eyJzZWxlY3RlZExpbmVDb3VudCI6MjMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1NjU0OWZjMWM5MzUwMzhjOWY4NTkyYzM1MDliMDQ3ZGZmYTdlM2Q0MDUyNjY5N2ExZGRhYTA2Y2VlYzk3NTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU1MDMyZTk2NGQwOTMyMzUxZTVkMTg1MjY5MjgxYjE3MWEzYTA5YjA4YjI4NmU2NjFlYTQ3MDMyM2M4MmViNGQiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImQxYjdiM2E4OGQ2M2EzODFiMTI4Y2ZlMGRiZTVlOTI1YTdlMjc2ZDM5MjViMDQxYzAxMmRmYzA0NjUxNzA4M2UifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentScratchTransferTools.swift#L49-L60", + "version": "repo-lines-v1:sha256:02578d2fd2419caeff10738035a5b4777da2ea2bb87aca8c8703f82a43315a9c:eyJzZWxlY3RlZExpbmVDb3VudCI6MTIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImM1NjU0OWZjMWM5MzUwMzhjOWY4NTkyYzM1MDliMDQ3ZGZmYTdlM2Q0MDUyNjY5N2ExZGRhYTA2Y2VlYzk3NTgiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijc1YjY0NjJlZDI5NWRhZWQzMzAwOTRhMDA3MDYwZjU2OWVkNzhiNzJlZjQ0M2MwYmM5NGFlZGI4ZGVkNDM4YjciLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU1NDJlOGI3ZTFiY2ZjMTFmY2Q3MWNmZmJjODFiYmJjNDYyMzNkYzQwNzdlZDA1MDI1ZGNlMzUyMTNlOWZiYWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjUzMzNiZDM2Nzg4YzI2ZjFiZmRkMTg3NTc1YTJhZmQxMzJjMzkwNGViMzRhNGEzZTUxOGRiMjQ0MGQwODkzZWUifQ" + } + ] + }, + { + "id": "claim_0d3a818da2504f6e992acd3b9fd57ca7", + "statement": "Agent authentication acquires a scheduler permit before authenticating and leasing a channel for requested data work; it owns and releases only permits it acquired itself, and connection/authentication retries occur before, never after, the SFTP operation starts.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L989-L1093", + "version": "repo-lines-v1:sha256:36d56775f50aa279d8a7a7abd0d69e1012d815a82209efee4af1840c90f7e6be:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA1LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJlMGExNWY2MmI0OGM1NzUyOGYwMTE4YjM3MGRiZWQwODgwMjQwZTU5NzMzNGQ5N2VhYWVjOGUxMTNjY2M3Yzk2IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiJlNmIwNDQ5MTQ2OTcyMmU4MzYzYTk0ZTQwNDQ1MzhlMDEzYTJhMjE3ZTM2YjFlNTY4YmE2MGFjYjdiNGM4ZjJlIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiI5OTliZGVmZWVhY2E2MzQwZTAyOTBkYzg2ZTg4OWM4OWQ1ZTE4OWFhNWJhNDRiNTg1YjNiNzA3MzRmNGE2MmQ4IiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiJmZjUwZjI0MjU1MDkwNTIwZGNlMDQ3M2UyNDE2MDhhYTViYjY0NGVmMWQyNjE1ZDczZjlkMmU0NDdiNjY0MmUzIn0" + } + ] + }, + { + "id": "claim_e3ecaa916e2c4feaa749ec760c4bc318", + "statement": "The Agent connection pool shares its Host-keyed primary SSH transport between exec and the primary SFTP subsystem across tool calls, joins concurrent primary opens, and invalidates reused connections on route changes or disappearance rather than reusing a connection to a different destination.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1462-L1527", + "version": "repo-lines-v1:sha256:1da7c51cc0159ce33261febbd8c56b7a66d621283da1e9a6528e3f9156dbe9a3:eyJzZWxlY3RlZExpbmVDb3VudCI6NjYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRiODUzNWJjMWVmM2IxNjU3NDVmZjk4Nzg5ZDA2YzcyMWU5OWE5YjM2MTc1YmJmM2YxMDg4OTY2N2JlMDYyNjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjNkM2FiNmRiZjc3NDE0ZjNhMzBlMzBiYjBkMGMyYzY0YTdkOGVhMzk2MTk3ODMzMjE0MmU4NjQ4YWE3MWZhZDMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZhMGZiYjQ1ZWNlZTdmYzAxZjc0NmJkZTY4MmUxMTRiOTJjNTU5OWRkOWUwNTE2ZDIyZDNjMzI1ZWQwMzc0NmYifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1607-L1673", + "version": "repo-lines-v1:sha256:562d766fb54f7311693f961d55e9e16e1c4518ce05f0d7d5f46342284f1cec46:eyJzZWxlY3RlZExpbmVDb3VudCI6NjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmMWZmZmIwODk3NWE2MWVlOThkY2NhMTQxODE5YjZiZjJhZTA2MjdiZmM1OThlYTBhZmVkOWI1NGQ2ZmJlMzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzZTZlMjQ4MzhhNTIxMzQxNzA1OTIxOGEwN2UzNWUyZjFjNmNkZTk0Mjg3NDZhZGNlOWVhNmI4ZTFmN2Y2M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ4NmQ0NGU0YTE3YjRlZTI4MWM4OWFiMGQxODY1OGM5ZDIxMGJiMDhhMDNkYjZlMzFlZTEzODY2MjYzYzhiNjUifQ" + }, + { + "resource": "repo://TFMTests/AgentConnectionPoolTests.swift#L138-L186", + "version": "repo-lines-v1:sha256:f24314e2d6ecbece14d7d9a93ee44c51ff9244df923d9930e896b107749a6ae5:eyJzZWxlY3RlZExpbmVDb3VudCI6NDksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJhNGRlNjI1MjMzYTE1NmZjZjY0N2FmOWFkMWEzMzE0MGM4ZGViOWNjYzVlZTU5ZTIzMGU0Y2IwN2RlMTRjMWYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImJlYWE1Y2FjNTgzZGRmM2I5YjEwNjkwMmEwNzE3ZjE0MjIxZGIzNTVhNDI4MzZkNWM4MTgzNDEzYmZlOWE5Y2YifQ" + }, + { + "resource": "repo://TFMTests/AgentConnectionPoolTests.swift#L256-L286", + "version": "repo-lines-v1:sha256:67843424db7f6e65e44c10053594c5cae064b0e67af1e3a79307ead53c5307c6:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjRjZjA5ZWIwYzU3NDRmYjk3MzMxYjk4ZmYzZmJmMDVhNjAyYmEzZjdmNjdlNWRhNWJlOTA5NTAzM2Y2MjU4MjUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjdmY2UyZTZjMDg3NDllNjFhZjMzMzZjMGNkZjg4MmQ4YzkzZTE1YzI5Y2IxNzY0NWZkMjA1Mzc1ZTg5MTA1YjQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjIzMTUyZjRmZDg0NTJlNmRmN2M5ODY1NTVhOTFmYjJkZWJhZjVmMjEyNTNlYTFiMGFlMjU3NWZkYWU0NzQ3YmQifQ" + } + ] + }, + { + "id": "claim_92a667b0a91e4a938cb590d81cef107d", + "statement": "Agent route fingerprints describe destination, hops, identity, proxy, host-key trust and charset without reading Keychain secrets, so credential rotation alone does not retire an authenticated connection while removal of a temporary pane-backed target prevents further reuse.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1607-L1635", + "version": "repo-lines-v1:sha256:568cb2a46d89fa8d7c5f2691e4a096038f7c096aa72887ce91eb25f6ea52238f:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFmMWZmZmIwODk3NWE2MWVlOThkY2NhMTQxODE5YjZiZjJhZTA2MjdiZmM1OThlYTBhZmVkOWI1NGQ2ZmJlMzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0MWZlNzViNTUyMjBiMTk1ZDE3ZDQ4NGNlY2Y2ZDEzZjZjOTgzOThiY2RmOWQ5N2UyNDA0ZDk3YTAzMGFlMTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImYzZTZlMjQ4MzhhNTIxMzQxNzA1OTIxOGEwN2UzNWUyZjFjNmNkZTk0Mjg3NDZhZGNlOWVhNmI4ZTFmN2Y2M2UiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc4MWUzMzFkZmNmYTQyZTgxMzlhMWZjYjQ1NTZhODhlZWRiYjQzZGMzNjg3NGVkNDViOTA0ZjliZWNlZjE1YjgifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L492-L527", + "version": "repo-lines-v1:sha256:5a4404eed27a5160465ec868dcc98d3be6f3c52233d195a323b10fc3fdd25597:eyJzZWxlY3RlZExpbmVDb3VudCI6MzYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImMxYThmMzBjODI1ZjMwNzNlNGE3NGI2MWI0MzEzYjkwNWZlNDJlMmNhYjA3MTk5YmU5ZjRkN2E4YmJiZTVkZTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijg0NTFjODUzOTdkOTc1ZGJmOGI5OTZjZDE3MzhjMTk1NGUyMWU5OTRmYmJhZDY3ZTZhM2QzZGZlZDljNjA5ZTcifQ" + } + ] + }, + { + "id": "claim_e1607ae650b341cfa47ce7a02d64e40f", + "statement": "Agent channel-only overlap leases siblings on the primary and, if sibling opening fails for a non-cancellation reason, waits for an idle primary; connection-preferred overlap probes silent extra connections and downgrades to sibling channels when silent setup fails, but propagates sibling failure on that path.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1259-L1365", + "version": "repo-lines-v1:sha256:77343b5e024d771fec726d0b4f9c3ffa6d4b9ec7f869804c06e9a352a206cbea:eyJzZWxlY3RlZExpbmVDb3VudCI6MTA3LCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJjOTQ3MDA2YTA4ZmQ2OTZmYWNmMGY5MzYwMTM5YTA1NTAzNmUwZTk1ODg3NGVmODE1YzBlN2U2YWE5NDAwNmJhIiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiIwZDM3NzY4NDNiZWIzZDM1MTI5NWEyZThkM2RjM2M1NDZjMTIxMGQ0YzM4ZTQ0YjVkNjc4YjAwYWIzYjU4NTE5IiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIxMjhmMWU2YWQ1MDhlNGRiODE2YjI2NGZlZWM5YTlmM2QzYmM2ODZkY2UyMTM3NzJiYTlkNmNlMzVlNjJjOWMyIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiIwMDJiZGY0Y2JjYzc2N2MyNzkzZGRmYzYyMzFmYjE1MTNiOGQyNjg1MTA2YWJmNjVmYWI1YmU1MjUxZmU4NTFjIn0" + } + ] + }, + { + "id": "claim_54bf7f62a8484513a65d951cfaeb433e", + "statement": "Agent pooled SFTP primary and auxiliary records become reusable on lease release while ephemeral siblings disconnect; idle sweeping removes idle auxiliaries and closes the primary with its exec connection only after no active leases remain and the idle timeout expires.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1368-L1386", + "version": "repo-lines-v1:sha256:a2203615454935a552f3040c108eee51e54961b96ae97197a8b55ddfb8867e11:eyJzZWxlY3RlZExpbmVDb3VudCI6MTksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU4ODY1MmY4ZDViOTNkMTIyM2IzZTM5YTQyMGY4NjQ3ZTIzMjVkY2JmZGVhNTMwNTk4N2JlNmIzNmE0YTI3YWQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImEyNzIxOGFjYjI5OWUxZGEwOTk5MTJlYThlN2E5MDdmNjg2MjcwMzNmYjUwZTJmODE4MDYxYmVhYjliYWQyNzAiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjJiMmE0NDM5NTdlMTViMzIzZWJlMjQ2NjM1ZWNmMDU5ZjRhZTQzMTlkODdkMDNhMzc1ZmMzMjI0OGI1YmYzOGIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImExMjMyNjI1MGIyOGY3Yzg0NmRmODVkODZhMWM1MmM1MjBhNjM1Y2Y5ZGIzMTY3MjFhNTE1MDdjY2E2NjE4NGYifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1564-L1605", + "version": "repo-lines-v1:sha256:ccfbf3556875d3cb477f6208aec0c4a88c874e1d6ba9eb322ef61ad999005749:eyJzZWxlY3RlZExpbmVDb3VudCI6NDIsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM5MDZjYTI5YmVjMjdhMGQzNTFiNGVjZGVjMTg0YWQyNmY3ODM5ODM0MWIyYjM4OWNhMzUxMzcwYTAzZDI3NGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE1MDU5MDUwMWE4YjVhYzQ5YmJkOTc5NzZjZTJkYTk1MDRhNDQzNzE2ZmNjNjgzYTllNGQ3YzQyZGY5ZGE4MTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2OTFiYmExNWI2Zjg2ZjVjOGZlNDNjY2ZjNTBmNmY5MjcyYTVmMWMxYWNiYWFhNjcyZjU5YmM1ZmNhYzE3MDgifQ" + } + ] + }, + { + "id": "claim_ae10898f0af544fca2500239bea74554", + "statement": "Disconnecting or invalidating an Agent Host cancels active SFTP lease tokens and disconnects channels and SSH transport; connection-loss errors after an operation evict the Host but do not replay the operation.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1034-L1049", + "version": "repo-lines-v1:sha256:f1c6e5c9445910b4cbf0018fd3eac6591a52c39eab418394d66d7188a216c1bc:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU4NDBlMGRkYjQ0MThlMzE5OTYxZmQ2MTk3ZTA5NTNiZDI0MTJhNTMxN2JlMWEyOWIxNThjMDNhMGI2ZmU5ZDMiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjBjNjQ3OWNjMjMwNDQwZmQ0MWU4MjI0MjE4Njc5Njk4NTU5ZDI4OTNiZDY3YjQzODBhZmFiODExYjM4YTU1YWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImU5NmNiZmNjMTQ0NmFjZTU4Mjc5ZTExOWQxMGJlNjRlM2Y0ZmM5NTk1ZmU3NGUyNGM3MGU1MGRmNmU0YzFjZWEiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQ0ZmY4MTYwZmU2ZTUyZGIzOTE0ZTA1MzA3ZTQ2OTI2NWFkZmUwNWRjNzgyNzAzOGRkZGY1YTVhY2I2NTk1MzgifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1529-L1562", + "version": "repo-lines-v1:sha256:e12e5bb28ae3f8a555590ebebcd0e65afb876f9b567f075026fc63fc04a11f53:eyJzZWxlY3RlZExpbmVDb3VudCI6MzQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQwNGM2YTlkZDY3YzA4MTliYTRkZGE5YTBhYWYzYTc1ZGU2OTYyZGQ4MDVjZTJjMjYwNDY5NjY1MDI2ZjEzZmYiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6Ijc2N2E1ZTBlMzc3OTY4ZjhjZThhYjRmN2JmOGUxOGMzN2I3ZTJjYzI1NzVkZWYxZGNlYjM5MmJjMjY3NmVjNDUifQ" + } + ] + }, + { + "id": "claim_a7395d3e036649078d0eed546bd1c890", + "statement": "Agent authentication contexts are shared only among overlapping attempts for a Host and discarded with the last lease, allowing interactive authentication retries during connection setup without turning custom credentials into a persistent pool cache.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1059-L1128", + "version": "repo-lines-v1:sha256:099c06cbb31f8c209118e8a50a15a0a73f15cbaafdae58a18fa58eedcd27a490:eyJzZWxlY3RlZExpbmVDb3VudCI6NzAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjE2M2E1N2M2NDE3Y2NlY2M1YWYzMmNiNjNmMWNlNzBkZThjMTQ4ZDI0YjViMTVjOTk1NzA1MmZkOTY1MGUwYzEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjdkYTc3YzM5ZTVlMTNkZjhjMzU5Y2VkYzUwY2JkZmRjMzZkMTBmOThiN2MwOGIyZmYxMDRkMDkyMjlkNzdkOTcifQ" + }, + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L912-L926", + "version": "repo-lines-v1:sha256:11c1bbdc2248516b9f2a14428af213d4653d9e02b8d17166a5a2d957a914cef0:eyJzZWxlY3RlZExpbmVDb3VudCI6MTUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImFjYjRhNmQ0MzczYWNjNTgxNWU5OGI2ZWMzNDMzZDg1ZTBmNjU1YjU5NWVjMThlODUzNGJmMWVlYzk3MDIwYWEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImQ2OGNhYzM5NWM1ZGU2MTBmYmYzNWQxMjcwYTM4ZDkzZTI2NWYwNWMxMzM5OWNlYjhhMDQ0MjZmZDEyZGQwYTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjE5ZTc2MzU1Y2YxMTk5NDgwYzNmOTk4MzZiMTQ4NmM4NDFkODkxZmFhZDkwNGM2MDhlMDkzMDIyZDM3NTdhZWUiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImNjOWExYWFjNTQ2MDRkYzI2N2M1MTRhNGRlZDMxZmFhMDhlZjljOTEzMWQ2ZDVlN2U4NzFjMTY3ODA4YmExYmQifQ" + } + ] + }, + { + "id": "claim_50e2a324a1b94faca6c6d5fd754678d7", + "statement": "Agent sftp_copy obtains one destination-anchored permit charged to both endpoint Hosts and passes that permit into endpoint leases; same-host channel-only copies reuse one channel instead of opening a second endpoint lease.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/SFTPCopyTool.swift#L93-L156", + "version": "repo-lines-v1:sha256:20340aa6e5956d65bd9c7a9f7e2cb691415e345be0914d4829866adbeb2d1c90:eyJzZWxlY3RlZExpbmVDb3VudCI6NjQsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImIyN2U1MTdmNTRhYmNiYmFmMzEzNGVlYTViZmViNDM2MGRhNDdlYjI3ZDY1ZmMxYTMwYzk3ZGUxZjViYjUyNDUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImU2YjA0NDkxNDY5NzIyZTgzNjNhOTRlNDA0NDUzOGUwMTNhMmEyMTdlMzZiMWU1NjhiYTYwYWNiN2I0YzhmMmUiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImZmMGQ3NTk1MGRmMGZmOWEzZWU5NjYzOWRjYzhmZjVlYWVkYjQwZDY4MmJlYTkyNjIyYjUyMGRkODg3ZDkzZTkiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjZiOGY4NGE4MzQ5NmI1MWQ3NjVmNjM3MGQ2NTc3M2NhODA5ZmQ2NzVkMjY3NTJkZjZiNTkzYmFlZDI3NzIwNzkifQ" + } + ] + }, + { + "id": "claim_1dfa81c96eb64851bec37e6a0b018e01", + "statement": "MCP uploads are session-bound HTTP tickets with a separate upload budget and offset/length/token validation; their streaming SFTP transfer uses the Agent pool and file scheduler, not browser coordinator queue rows, while cleanup acquires a separate non-data SFTP lease.", + "evidence": [ + { + "resource": "repo://TFM/Application/MCPServer/MCPServerTools.swift#L37-L63", + "version": "repo-lines-v1:sha256:22f0d6a315104b5fd2d9ab180e8d95c250b38dbc1a5cc5b5504e37a516e0db63:eyJzZWxlY3RlZExpbmVDb3VudCI6MjcsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6Ijg3ZjA1ODBhYjJkOTc0YWEyYmEyNzE4MzE4ZDA0ZmVjOGFlMDA5NTBkMjFiMDIzOTJlZmJkODMxZjQ5ZjgxMTAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6ImVmNjA3ODI4ZDQxZDU5YjhjM2Y0YmZmOWQ0ZWQyZDRkODYyMzRlOGZmOGE4M2U5OTQ4OGYyMjhjNWQzMzMzZWEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjA5ZTUyZmRhNjQyNWQzM2ZhY2IxNzc0NTQ2NWQ4Mjc2MzhkOTIwMTM4YzUwMTU4NzRiNjU1NmNiMzdhMWMwY2EiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjNiM2U1MGViOTg5ZWIyYWRkMzUwZDBiY2I1MzJlOGY5Yzk5ZmU1N2JhM2Q1YzUxZDNiOTUyOTAxN2Q5MWRjOTYifQ" + }, + { + "resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift#L94-L195", + "version": "repo-lines-v1:sha256:2d7de272e785f6489922898d4852c2b31e9c2e6e248e428121bda1c40d7c751d:eyJzZWxlY3RlZExpbmVDb3VudCI6MTAyLCJmaXJzdFNlbGVjdGVkTGluZUhhc2giOiJlMDVlYTMzZjA1NjAxMWQwZTI5MjM4YTdhMjQ4YTNiYWI2YjU5MzQwOWYwOWFjNDg3NGVmMjFlOTA2NzMxZmM2IiwibGFzdFNlbGVjdGVkTGluZUhhc2giOiI1OTA5YTUzYTYxOGQwMjhlMWQzMDAwYzBhN2FiY2VlY2JlNWZiMzdmNGU1MTFlZmU0NjY0M2ZhZDZlNjY4NzJmIiwicHJlY2VkaW5nQ29udGV4dExpbmVDb3VudCI6MywicHJlY2VkaW5nQ29udGV4dEhhc2giOiIxMDcwOWIwMTViMmY3MjU0MTM1YWRiNTA0NzkxMTBhNDAwYmIzMTRmYmVjYjkyZmU4YjQyYjBlYmM3YTZhN2UxIiwiZm9sbG93aW5nQ29udGV4dExpbmVDb3VudCI6MywiZm9sbG93aW5nQ29udGV4dEhhc2giOiI2YTE3YTI1MTg4ZjNlZmJmNTZhYjdkNGU4MzhjMzBiMzdhMjNkNTM4MjIxYTJmMWJmOTFiZjAzNGQ5YmM5YzhkIn0" + } + ] + }, + { + "id": "claim_18edeea27c494113afc6f9651a8efd69", + "statement": "MCP upload interruption or recoverable failure can pause an unexpired ticket for an explicit offset-matched HTTP retry, whereas integrity failure or cancellation triggers partial cleanup instead of silently replaying the upload.", + "evidence": [ + { + "resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift#L159-L165", + "version": "repo-lines-v1:sha256:2fdd3f006390a418bdffec5b0b7087004a887fc1e1f90c80156a3145ec22991c:eyJzZWxlY3RlZExpbmVDb3VudCI6NywiZmlyc3RTZWxlY3RlZExpbmVIYXNoIjoiZmJiYTU2ODk2NzU3NDg0NjdhMzJmYTIzNjZiYzI5YWI0YjgyOGQzMmYxZmE5NzlmYWQ1NWZlZWU4NWY3NTk0OSIsImxhc3RTZWxlY3RlZExpbmVIYXNoIjoiZTZiMDQ0OTE0Njk3MjJlODM2M2E5NGU0MDQ0NTM4ZTAxM2EyYTIxN2UzNmIxZTU2OGJhNjBhY2I3YjRjOGYyZSIsInByZWNlZGluZ0NvbnRleHRMaW5lQ291bnQiOjMsInByZWNlZGluZ0NvbnRleHRIYXNoIjoiMzA5MTY2MjQ1M2IyOWQ0NjQxODk0N2ZjYzA4OWYzOTMyZGUzMzcyODU2YjFmNjQzZDI0NmE1ZDE2ZDAwN2YzMiIsImZvbGxvd2luZ0NvbnRleHRMaW5lQ291bnQiOjMsImZvbGxvd2luZ0NvbnRleHRIYXNoIjoiMWU4MDA2ZjQxNDdhNDk3NjkxOTQ2NTViZDRiY2ZkNjJhNDkzZTRjZjhjNTE4NTIwY2ViYTRhZDU0ZTk5NjQ2NCJ9" + }, + { + "resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift#L231-L280", + "version": "repo-lines-v1:sha256:729927b1e0165464e3fc9e82dd12a48162370a5305d7090a3ffcd16fe3bf3123:eyJzZWxlY3RlZExpbmVDb3VudCI6NTAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6ImNjN2JiZTc5ZTlkMjJkOTY2MzA2MDM1NjFlYmUwM2UzZjgwZWRlMjAzNzE2MzkwYjk2ZWMxMGFjYWZhNTAzZGQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjM4NzJkZmU3NmNhMGMyY2Q1MjUxMWY3NGE4ZDFlY2VjNzMxZjhiNTQ1ZGI3N2FjMjA4MmUzNjQ2NGI1NjFiYjYiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjQ3YzFkOTgyY2MyNWRkM2JlZjMwNDIyZTY1MGJlZGJiZTBkODFkM2QyMzJhY2I0NmRiNGU5ZTViMTRkZGQxOTQiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImY2NzlhZDU5YWY5MjYwZTU3NDI3Mzg1YzgxZDAyMGQwNmNjNjM3NjNmMGY1MjE2NTY5OGFiNTg0MWM3YmVhOTUifQ" + }, + { + "resource": "repo://TFM/Application/MCPServer/MCPUploadCoordinator.swift#L329-L388", + "version": "repo-lines-v1:sha256:6bf522c841df9b7b688acd5a22ff6c56a0707ce00a3714a987df80e231336f13:eyJzZWxlY3RlZExpbmVDb3VudCI6NjAsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ2ZTgxMjdjZTdhMmE1OTIzZjEyMmE4Mzg5ZDFiOWNiYWEyOGNhZDQxNGUxNWJlOWQ1MzUxZjc0YWQzMWM4YmQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjcxZTg4Zjc0OGFiNDM5ZjdhNzI1MTM2NDQ2ODViNjA0OTc5ZDJmOTM5YzI3ZjY5YTlmODVmNWI2ZGIwMzI4NDAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjAzMWJkZTJlYzY0OTU4MGM3M2Q3MTgzYTRmY2UwM2NlYjM4ZWNkNDVhN2ZiZjJiMmFkODhlZjhlYzRlZjM3NmUifQ" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.claims/workflows/ssh-session-lifecycle.json b/openwiki/.claims/workflows/ssh-session-lifecycle.json index 44f08fcf..986d6ae0 100644 --- a/openwiki/.claims/workflows/ssh-session-lifecycle.json +++ b/openwiki/.claims/workflows/ssh-session-lifecycle.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "pageVersion": "sha256:7e3576b0e372bee5a798e768751d114d3ba06db8df17a182ee83572b288f24f1", + "pageVersion": "sha256:557605f4c9e89cf5b14379eef061940a994954d683d87ed5f0e24b963c46f493", "claims": [ { "id": "claim_69a9de4ce918417c8a44c6c87c9f6564", @@ -121,32 +121,24 @@ "statement": "Desktop restoration does not reconnect live Workspaces, whereas mobile persists only connection-free descriptors containing workspace ID, Host ID, kind and title; cold launch performs no session or network restoration. Mobile background expiration closes transports and foreground can resume existing workspace intent.", "evidence": [ { - "resource": "repo://TFI/App/MobileAppModel.swift#L659-L687", - "version": "repo-lines-v1:sha256:79cc24d90367f9ef59be0ea4dd25af4951788cf734444c57cefc55aa8a746b6d:eyJzZWxlY3RlZExpbmVDb3VudCI6MjksImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjA4YjM0MjE2MjYzZjM3NTkzNDUyZGMyNDNlYTQyNTQ3MDJkZTEzYjI0OTliYTQ4ODYxODk2NTI4NGNmNDQzNmUiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQ1NWE2YmQ5MDhjMTBjOGM0MzYyZDBkNDAyZDI0Y2JkMDY2MDgyYjNjMjQ0N2YwZTA0MjZhYjEzY2M4NDc2M2MiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImE5MDlmNTg5MzgzODA2NjM1OTVhOTFhNDhlYjQzNWFhNjI1OGNiZWVlZDc1MjAzMDUxODZiYjBiMGI4MTZjMDIifQ" + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:b24747ff9dedd849a5aabeba6b978fa6c7e3b61954033dcee5163d5ed8064123" }, { - "resource": "repo://TFI/Features/Workspaces/MobileWorkspace.swift#L1056-L1101", - "version": "repo-lines-v1:sha256:0a7ae642dd083c84f164b264fee0281ba51d48288dcddb66d8c2e9912a631140:eyJzZWxlY3RlZExpbmVDb3VudCI6NDYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjljN2Y4NWI1NDQ5YmI0MTM0YjhmMTAzN2M1ZDkwNjU4ZDNiMjU4YWIxMDZlNWZmNjEzNTBiZjg2MzlmYzY4ODQiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6Ijk5OWJkZWZlZWFjYTYzNDBlMDI5MGRjODZlODg5Yzg5ZDVlMTg5YWE1YmE0NGI1ODViM2I3MDczNGY0YTYyZDgiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjE2ZGMzODIwMjNmZDQ2NDhkYjQzZmZhNjFjNWJmYjQ3ZjliOTZjZTIyZjFmNGI2OGYxZTczZGY3ODkxN2VlMDkifQ" + "resource": "repo://TFI/Features/Workspaces/MobileWorkspace.swift", + "version": "repo-file-v1:sha256:3d05ec07c3ea60a68e5a292a2c934ae7f24cc1fd674b1b76dc1003b84fed0059" }, { - "resource": "repo://TFI/Infrastructure/MobileWorkspaceStore.swift#L4-L68", - "version": "repo-lines-v1:sha256:b43cb4870d4d5319ae6dd1b68255f083bdf1c62a876c6ea566d2ef6c266f5cc6:eyJzZWxlY3RlZExpbmVDb3VudCI6NjUsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjAxNDkxODZkNzI0Y2I5MzM5MjJhN2U0MTQwZTVkMzhiNGI5MGQ5YzQyZjQxZmY0NDIzMzZjNjVkNWNhMGRlZDkiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImE1OGQ0YTkxMDc0MDU5ZjBjOGQyMTM2ZjliZjgwODM0NjE0OGZjOGNmYjM1NDNkZGNiYzc1MGU3NTc2ZTcyNjMiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjoxLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjQxMmNhMzQ1Y2NmNzViZjljMDgwNmJjZTY5NWJlOGRlODA4Yjc5OTg0MjUxYTdhNTRkMjAyY2Y2MTAxZGQ0NTEifQ" - }, - { - "resource": "repo://TFITests/MobileAppTests.swift#L1516-L1546", - "version": "repo-lines-v1:sha256:da0450e18748d4e9ec4ac784144804c174d495f485f47167f501f7493cc28fbe:eyJzZWxlY3RlZExpbmVDb3VudCI6MzEsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjkyNjg1Mjg5MWQ1ZjVjNTVlNjY5YzQyNjRiNzc3NzAyOTVkMDcwYTY0YTVlZDAyZTc4ZmJiYTJhMTk5NGFkNDAiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjllOWQzMmRjYWFlMWI1NmZiYzYzMTNjZTM2YzAyMGE5MDhkOGFiMTUxNDk5NTgyM2MyODFhOGI3YWE0ZjQwODEiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6IjczNzhlZjkzMGE2OGVlNWNmZTg4Y2NlMTZlOWYzYjkwMzBhNjExMzYwNzg2OTI0ZDM4ZGU5MzJlZGM3NjI0NDIiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjBjNTgzMzcyZWM2ZDg1Zjg4NDI1Mzk5ZWE4OWJlYmJlNGY5ODY4ZmExMmU1NWI3YTkzYTdiOTAzMDExNDZmYWUifQ" - }, - { - "resource": "repo://TFITests/MobileWorkspaceStoreTests.swift", - "version": "repo-file-v1:sha256:9953e49389c0c2b390fe6bd51e467de56c31ec1556a13633ae239ac842c9241d" + "resource": "repo://TFI/Infrastructure/MobileWorkspaceStore.swift", + "version": "repo-file-v1:sha256:ea46bc5d91b8f0cbbdf562a56e1383dc1d7732ba249b109dd676a54369acf9c6" }, { "resource": "repo://TFM/App/TermindApp.swift", - "version": "repo-file-v1:sha256:4bc8de73959fb7b78ab29e7936fbeab9a5f13a0e0f7555d520d99ff2bd731cec" + "version": "repo-file-v1:sha256:fcf66bc2cd5aa8569f2f1a7074d91ede68b5509b387d5c14508affb8f79ba8a0" }, { - "resource": "repo://TFM/Features/Workspaces/WindowModel.swift#L17-L32", - "version": "repo-lines-v1:sha256:ee52fc70a63ddae0b4a377ac03a5435f3ad519a3c7fff59a6f548eea69dfb70a:eyJzZWxlY3RlZExpbmVDb3VudCI6MTYsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjU0MzA5NzdmMDljNjhmODk4Yzg4ZGI3MTdiYjU2M2QxMTU4OGZlODRjYzRmOGU0MDVmODE4NDg5YzFkOWZhYTEiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjVkZmI5ZDI5ODQwNzU5MjVlNDRlZGY4MGE0NTViN2M0ZDFhNzhhNDE3NzM2Zjg2OTZjZTA2OTc1OTQ4YWIzMjIiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImEyNDgzZjMxMjRhMTUxZjE0YjJjNmU4ZjRkMTEwYzc1ODVmZTE0NWM0OTdkZDE0YjEyYWJmNjAwN2IxNTA5YjAiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6ImUxNzhjOWMzZjc5MjhjNGYxMmZjMDg0ZjY1YTU2MzA0OGI2Mjk2MmM4NTE4OTI4NDYwZTlkZjk3Y2I0ZGE0MjUifQ" + "resource": "repo://TFM/Features/Workspaces/WindowModel.swift", + "version": "repo-file-v1:sha256:4bd147972cb9d30bebe48592542710683383b5deaa2e3d1a49ac0dbbcce44644" } ] }, @@ -171,10 +163,132 @@ "version": "repo-lines-v1:sha256:28ad85483155b381f658e4828ea80953cc7a916b4bd99ad962ba6fd23a75db0b:eyJzZWxlY3RlZExpbmVDb3VudCI6NzMsImZpcnN0U2VsZWN0ZWRMaW5lSGFzaCI6IjdiMGE4OWZhY2U5NDE1ODFiNTg4NDc4OTU5Y2YzMTJkNTEwMzdmZWViZTgzMjFmN2MzNDNjMmM1M2QzMTg2YmIiLCJsYXN0U2VsZWN0ZWRMaW5lSGFzaCI6IjQ4OTNmNDBlMzc4MWViODk2YzgyZDA0NmEwODA2N2ExMWUzNWNkZjJmMWRmYWYyNmZlYTkwYjhkYjY2NzY0MTMiLCJwcmVjZWRpbmdDb250ZXh0TGluZUNvdW50IjozLCJwcmVjZWRpbmdDb250ZXh0SGFzaCI6ImQzNDU2OWJiNmExNjBkOTQxMzM3ZmVkMDI5N2ZmZGU4YTUyMDdiZGVmNTZkZTFmNWYyZjRmOTYzMDk1ODExYTYiLCJmb2xsb3dpbmdDb250ZXh0TGluZUNvdW50IjozLCJmb2xsb3dpbmdDb250ZXh0SGFzaCI6IjFlNDczYWE3ODczOTlhYzQyMzgyZjdiYWUzZWU3ZmI2ZWU5MTc2OTczOTdlOGVmMGNiZjI5MjU1N2EzNWExYjMifQ" } ] + }, + { + "id": "claim_04ad8be8bf024157b19dd5675f82dd89", + "statement": "On desktop TermindApp shares one AppModel across scenes but constructs a WindowModel for each window; AppModel holds app-wide host services including an AgentHostServices resolver, authentication registry, connection pool and background-command owner, distinct from window-owned workspace sessions.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentHostServices.swift", + "version": "repo-file-v1:sha256:78f3f9fcb8051efa9ee7115d5ffacc0ffbffb2f6f2d71d6468e46cb51bca6946" + }, + { + "resource": "repo://TFM/App/AppModel.swift", + "version": "repo-file-v1:sha256:197fa5f7cbf890923e277a7e68154263c39a7c6751f07f399bf960ab016ebb41" + }, + { + "resource": "repo://TFM/App/TermindApp.swift", + "version": "repo-file-v1:sha256:fcf66bc2cd5aa8569f2f1a7074d91ede68b5509b387d5c14508affb8f79ba8a0" + } + ] + }, + { + "id": "claim_ab8d01c7dc8e49f99bc19cb98baa63a3", + "statement": "Agent host listing exposes public Vault metadata and temporary pane targets without credentials; temporary SSH configuration comes from a live desktop pane, and resolution fails when a temporary pane-backed target no longer exists.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift", + "version": "repo-file-v1:sha256:fc831e3a719f03db15f95b43e0ed6adbe3c0e8cd197d564fa1226395d80de6c5" + }, + { + "resource": "repo://TFM/App/AppModel.swift", + "version": "repo-file-v1:sha256:197fa5f7cbf890923e277a7e68154263c39a7c6751f07f399bf960ab016ebb41" + } + ] + }, + { + "id": "claim_db26398d084a46068b316c64b4cb1a48", + "statement": "Agent SSH authentication collects missing proxy and host credentials in route order before connecting; the attempt handles host-key and keyboard-interactive challenges during handshake, with permanent host-key trust allowed only for saved Hosts and one-shot approval held in the authentication context.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift", + "version": "repo-file-v1:sha256:fc831e3a719f03db15f95b43e0ed6adbe3c0e8cd197d564fa1226395d80de6c5" + } + ] + }, + { + "id": "claim_a99b532134ea4be0b3c72776b1e9f7ce", + "statement": "Overlapping Agent connections to the same host share a temporary authentication context and pending configuration/open; cancelling the last waiter cancels its prompt, stale generations cannot erase newer answers, and successful authentication clears staged secrets so unrelated later connections cannot reuse custom credentials.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift", + "version": "repo-file-v1:sha256:fc831e3a719f03db15f95b43e0ed6adbe3c0e8cd197d564fa1226395d80de6c5" + }, + { + "resource": "repo://TFMTests/AgentHostAuthenticationTests.swift", + "version": "repo-file-v1:sha256:e0fc788e24877e6043dfa7d89ad5835df7e94f3b423fa0482e90f0e5447582aa" + } + ] + }, + { + "id": "claim_db9d2f5b9d5d4f8b885904edc7cd8133", + "statement": "AgentConnectionPool reuses an authenticated Host-ID-keyed connection across tools and runs according to a route fingerprint built without Keychain reads; route changes invalidate reuse, concurrent misses join an opening, and late cancelled openings are disconnected instead of committed.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift", + "version": "repo-file-v1:sha256:fc831e3a719f03db15f95b43e0ed6adbe3c0e8cd197d564fa1226395d80de6c5" + } + ] + }, + { + "id": "claim_8a0f9fc7616349f09f10321474c7b065", + "statement": "The Agent pool multiplexes exec and primary SFTP over its own SSH connection, can obtain auxiliary or sibling SFTP channels, exempts active exec/SFTP leases from idle sweeping, and disconnects on host deletion or explicit app shutdown.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift", + "version": "repo-file-v1:sha256:fc831e3a719f03db15f95b43e0ed6adbe3c0e8cd197d564fa1226395d80de6c5" + }, + { + "resource": "repo://TFM/App/AppModel.swift", + "version": "repo-file-v1:sha256:197fa5f7cbf890923e277a7e68154263c39a7c6751f07f399bf960ab016ebb41" + } + ] + }, + { + "id": "claim_c23478395cc94fb0bc817b846f10d053", + "statement": "ssh_exec uses a non-PTY command channel with safe-command parallelism and approval for unproven commands; its deadline includes connection, returning connecting without starting a command if setup is still pending, or handing a running command to a background handle while retaining the pooled connection; only a pre-channel connection failure can be retried.", + "evidence": [ + { + "resource": "repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSSHTools.swift", + "version": "repo-file-v1:sha256:53965fe94927e454ed8aac0a590512bd6ccced1aec98a434bbeeb64adb5a6819" + } + ] + }, + { + "id": "claim_35062280526e42febcba9b5983e964b8", + "statement": "Desktop termination checks pending external edits, closes window-owned sessions and app services, waits for Assistant/MCP and SFTP drains before closing Agent background commands and connections, and answers the native termination request after cleanup or a three-second fallback.", + "evidence": [ + { + "resource": "repo://TFM/App/AppModel.swift", + "version": "repo-file-v1:sha256:197fa5f7cbf890923e277a7e68154263c39a7c6751f07f399bf960ab016ebb41" + }, + { + "resource": "repo://TFM/App/TermindApp.swift", + "version": "repo-file-v1:sha256:fcf66bc2cd5aa8569f2f1a7074d91ede68b5509b387d5c14508affb8f79ba8a0" + } + ] + }, + { + "id": "claim_5714e81f84c94933bf3eff8231d1138b", + "statement": "When every mobile scene backgrounds, a UIKit background task is started; expiration synchronously requests workspace suspension, forwarding stop, transfer pause, and Assistant cancellation, then Assistant drains conversations before closing Agent background commands and pooled connections. Foreground ends the task and resumes only workspaces with recorded intent.", + "evidence": [ + { + "resource": "repo://TFI/App/MobileAppModel.swift", + "version": "repo-file-v1:sha256:b24747ff9dedd849a5aabeba6b978fa6c7e3b61954033dcee5163d5ed8064123" + }, + { + "resource": "repo://TFI/Application/Agent/MobileAssistantModel.swift", + "version": "repo-file-v1:sha256:8a9a00fed4426631856719583ac4fe07542c1b12d159913a3936b39342dcee8e" + }, + { + "resource": "repo://TFI/Platform/MobileBackgroundController.swift", + "version": "repo-file-v1:sha256:75c3d7bda5bf9ce83518666d5801cf3e01f9bbc82ed5acdc557bf17c2c6d4efc" + } + ] } ], "verification": { "by": "openwiki/0.5.2", - "at": "2026-09-23T10:08:51.776Z" + "at": "2026-09-23T10:36:38.039Z" } } diff --git a/openwiki/.last-update.json b/openwiki/.last-update.json index 5899c0a5..25512fad 100644 --- a/openwiki/.last-update.json +++ b/openwiki/.last-update.json @@ -1,8 +1,8 @@ { - "updatedAt": "2026-09-23T10:13:40.304Z", + "updatedAt": "2026-09-23T11:41:12.352Z", "command": "update", "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "model": "host-agent/codex", - "status": "complete", + "model": "gpt-6-sol", + "status": "interrupted", "language": "en" } diff --git a/openwiki/.page-manifest.json b/openwiki/.page-manifest.json index e8fea024..b71c69f7 100644 --- a/openwiki/.page-manifest.json +++ b/openwiki/.page-manifest.json @@ -2,200 +2,200 @@ "schemaVersion": 1, "pages": { "/openwiki/architecture/desktop-ui.md": { - "pageVersion": "sha256:f63ee68a44535a16e3e9c2cbce555c36e71ccd6c531a5f2be1ba12c409df160e", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:b9ac495e361094b701333dbc6741fb9eb235201a3428a88baa539e85b899368f", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/engineering-invariants.md": { - "pageVersion": "sha256:6c657e197430df2d01d976bdc75bfd503c6dbcfe5a6f9db0def86eeb8e459d1b", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:b3cf2c3e75779877055fc98f5005afa3c2c3ca927da6b0232fbf035d108cfe52", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/mobile-ui.md": { - "gitHead": "ae38d77013b7502c185781920ebfd4236afb1e6b", - "sourceFingerprint": "sha256:437b5dbe7eee74926b4f7906dc9421b029371a6e9727a372f3728b7e67628691", - "pageVersion": "sha256:5a57c9f6cd1214629ea2a75c3ba60386a70d5c2170cdb552f4dea473f0dde193", - "completedBy": "codex", - "completedRunId": "3212507d-fdea-4335-9994-e4980af3ccef" + "pageVersion": "sha256:1804e1b56dad3aff397363c08ac6c2af77f136d8fee3b4d6e8a2b80fa040f948", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/module-map.md": { - "pageVersion": "sha256:e3b8050ae27e288e93f95da211d5b461d2d1fae6ba7afce02d15c9a8937a9b24", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:bca96ac65afae5b3c664cba51d37fdd56b978934b1d494d475e95d057226bf98", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/native-app-directories.md": { - "pageVersion": "sha256:576b2a04372cf81fcde6d2915f6e8b918efb29ed6cb739e33ee70fb76991d17e", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:6fcee3a37158ff40799ce0b4dc356338d80ec4b9e1bc658f5d856c466618b2fe", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/platform-runtime.md": { - "pageVersion": "sha256:d3cd20c0a6365a0e940e562495075e28f5f59946fe18b68e5c8b459e02b4571f", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:b2e31af1e23b8eb56a0e9eaabf4e5a5b0a0ad90c94c725aa451f629dbe390f3f", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/shared-module-directories.md": { - "pageVersion": "sha256:e8da1978ed97e3c4dc6008ad373801967126a936955746a9426ecf5cea2fcae9", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:1d94baed34a4a63a7a933c51f451945882a2778972ab6bd10350dbd195285613", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/supporting-system-directories.md": { - "pageVersion": "sha256:7128b59755ba977881cdcb66403f656aca8e06a74e8217aae2fc581cd6b07aa9", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:28aa0deba6ac872df151035ac04d0aba9eb9619b16b76c706ecd36c2dbe08425", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/architecture/system-boundaries.md": { - "pageVersion": "sha256:f3b4a0dcddee51aa391d389de1ab210d6dc3216ee5664dfe83429fa642a50edb", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:a6f8d86c38688d119e171586b5b7c1c46a68416470c47cda9fbe3cbee3d02f9a", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/concepts/agent-runtime-and-assistant.md": { - "pageVersion": "sha256:88227616aa0b14b25c451de0e54bf45792788cfeaa77194995405b81c344be9a", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:40e0ea051b8758c505d4264ef66de5fe3e767ee52a8afa2858337c6827d609d1", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/concepts/commerce-localization-and-product-surfaces.md": { - "pageVersion": "sha256:bd337640d19689b0a49ced6065a75468c6db642b74b0fa43ef460aff4ebc1cf3", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:c9bc2c85241afa99871ff2b9d281f17d45acb8c76ef353b5c20844561140d378", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/concepts/persistence-and-secrets.md": { - "pageVersion": "sha256:511be363c8934aa5a750eaa3c71e72cfbeaff50c5ebb0f8b6c5ec09e6892eb72", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:1faf5315736b44da4aab78615dbdfeb81fd8888d3b52b10b884f9ac33af15aa6", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/concepts/remote-services-and-forwarding.md": { + "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", + "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704", "pageVersion": "sha256:9e0486ea1b4ef480f9b2de430e2beed9fdef98ddab424b93f4369fdc0b05748f", "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d" }, "/openwiki/concepts/shell-integration.md": { - "pageVersion": "sha256:93690003b8bab2fac2e0b4471cb3dc74e4b046473b3cce51e0a3e0d4e5f8f6b2", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:ae4a3bccb3836edf9362314d853ddc4634ebac972ee4c7f16eaf1c9c77c95123", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/concepts/ssh-multiplexing-and-scheduling.md": { - "pageVersion": "sha256:34fdcb119f481b5907ac4263413fb8b395af7b5c2200b99ae878bcf2fa78a269", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:ff1be2ef80ee4380d12600b617927c4a697e8a40d38e6b740cde639c9f25cc8d", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/concepts/ui-design-principles.md": { - "gitHead": "82ba6dc050bf2e3f907717bba4dd30bb9198b6a3", - "sourceFingerprint": "sha256:f625b15b2999e260a4375e9254de0e5fc1e622bbc3d1daf39aad616d6ff28ccc", - "pageVersion": "sha256:92110e4a68f9373b2a5339feea69ea1a11bb1fe73727dd0e4709661aa7cb595a", - "completedBy": "codex", - "completedRunId": "60f8c625-152f-4c3f-8755-bcc5d849e8d9" + "pageVersion": "sha256:0abbaadf6ae386fe26eba5e0ce8010dfc8cd8a5eba91e389977e9d5ee6c76fb4", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/integrations/mcp-server-and-bridge.md": { - "pageVersion": "sha256:8813e9d352ffc558ec59d677d22b494424eb3bb01bc65a25060eb3b812791721", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:d346d4ae2b393ff1fa231f3fdb05e737eded8665a2627acc44df7c382333a96c", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/operations/build-test-and-release.md": { - "pageVersion": "sha256:bb9dbed6786dee54c410e058f3e9ef6f001e35e72cd4845bec4d80a4b56f9e46", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:18c4ab0086670df59a492485fb84903a16daf0e41e8c32cff217d1330fd49d7d", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/operations/cloudkit-release-readiness.md": { + "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", + "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704", "pageVersion": "sha256:b9dbb545487c1c5a8d13fdf488152837ab71e3086d9ffe1cc0bd4373b35243ff", "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d" }, "/openwiki/operations/marketing-assets-and-app-icons.md": { + "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", + "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704", "pageVersion": "sha256:40b2afc40830a574689fa94f4912436c70b25c0f10741b865ad55d6364fe7f1d", "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d" }, "/openwiki/operations/port-forwarding-benchmarks.md": { + "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", + "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704", "pageVersion": "sha256:1fd667e120679ccb152d5bfd893352c86f299dffe69edbb567ca514b3c8c0add", "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "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", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d" }, "/openwiki/quickstart.md": { - "pageVersion": "sha256:acf6dc6d43a7314db512e046d19dad8aa17f3056196ad9c5f6b540a591bb4d73", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:ed6123ee29f371389d58e4ef425a381efb7f9a251c135b317d168b2e7ec27e70", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/testing/behavioral-boundaries-and-fixtures.md": { - "pageVersion": "sha256:9579877be3cc10fce322964052e0c007da12304bb1edf564dab07afb04cea323", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:15029cc4d76549f995f92d10b81402f0764575eeb49c402d9577fa1bc5c8756d", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/workflows/port-forwarding-pool-and-dispatch.md": { + "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", + "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704", "pageVersion": "sha256:9244f1bae4c911019a9394307c4876a9e5b71ccc4a6ffc9d289d7fdd6eca9e42", "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "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", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d" }, "/openwiki/workflows/sftp-transfer-and-external-edit.md": { - "pageVersion": "sha256:cef9e5c9f0e1b70ca61f5e10ad12b40eff7609701401b8061dea667ff941840a", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:bcad80bdae1c2dda36b882117fd053a20bce47dd9c10174cdbaec582ae1b38a5", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" }, "/openwiki/workflows/ssh-session-lifecycle.md": { - "pageVersion": "sha256:7e3576b0e372bee5a798e768751d114d3ba06db8df17a182ee83572b288f24f1", - "completedBy": "codex", - "completedRunId": "926e6b73-de8e-49f4-a260-18e94f16fa8d", - "gitHead": "25b88f90fcbb3b535d07481665cdbe3e9cef9f38", - "sourceFingerprint": "sha256:ee2bf42987f687d1217a632cdf8c816e2ecf304111a2ae7daa0fffd7042c7704" + "pageVersion": "sha256:557605f4c9e89cf5b14379eef061940a994954d683d87ed5f0e24b963c46f493", + "completedBy": "openwiki/0.5.2", + "completedRunId": "30c2e3a7-893f-43e0-b809-385cb93a0b74", + "gitHead": "69adfd3f51210783aeae565485b3571a1d186603", + "sourceFingerprint": "sha256:3c9219886395ca00b7a26127792532b09bf4478762382ef78648f6892c5725ac" } } } diff --git a/openwiki/architecture/desktop-ui.md b/openwiki/architecture/desktop-ui.md index d211a4bb..04b12b15 100644 --- a/openwiki/architecture/desktop-ui.md +++ b/openwiki/architecture/desktop-ui.md @@ -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-23T10:08:51.776Z + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-e09fb7bc8e7ca0579f6d446e resource: repo://Frameworks/TermindApplication/FeatureModels/DeviceDirectoryModel.swift @@ -15,6 +15,8 @@ sources: resource: repo://TFM/App/RootView.swift - id: openwiki-source-6570374eaac2e0278fa84640 resource: repo://TFM/App/TermindApp.swift + - id: openwiki-source-6a1a95f7d01cc8e15a397f6b + resource: repo://TFM/App/TermindCommands.swift - id: openwiki-source-f490cb5bfbb8ce236a7f1bf4 resource: repo://TFM/Design/DesignTokens.swift - id: openwiki-source-95f72232fb896aa95dd5f6c7 @@ -33,6 +35,12 @@ sources: resource: repo://TFM/Features/Workspaces/WindowModel.swift - id: openwiki-source-931aff66b28d38cd69ce2324 resource: repo://TFM/Features/Workspaces/WorkspaceContentView.swift + - id: openwiki-source-7e364c6182a8339831ecab24 + resource: repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift + - id: openwiki-source-22e92f96394f292a731fc6fb + resource: repo://TFM/Platform/MainWindowCoordinator.swift + - id: openwiki-source-5e2670d68f19777e2dd312ea + resource: repo://TFM/UI/Components/WindowToolbar.swift - id: openwiki-source-f6a967b4f14bf50d1af51b8b resource: repo://TFM/UI/Managed/ManagedCardPage.swift - id: openwiki-source-23acce6fe9173a886d433b44 @@ -41,7 +49,13 @@ sources: resource: repo://TFMTests/PersistentWorkspaceDeckLayoutTests.swift - id: openwiki-source-dceb8d7e7c5bb09359e70052 resource: repo://TFMTests/ResponsivePageLayoutTests.swift -generated: { by: "codex", at: "2026-09-23T05:17:08.701Z" } + - id: openwiki-source-91826a88f242f001f33fff89 + resource: repo://TFMTests/WindowToolbarFindTests.swift + - id: openwiki-source-a3093a0c1d98ecc1cdbc0279 + resource: repo://TFMTests/WorkspaceNavigatorDropTests.swift + - id: openwiki-source-05f0aeba12df8388b97b3c76 + resource: repo://TFMTests/WorkspaceNavigatorRenameTests.swift +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # TFM Desktop UI Architecture @@ -85,7 +99,26 @@ 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` shares `AppModel` across main windows but creates a `WindowModel` for each. `RootView` exposes that model through the environment and focused scene values so commands can target the correct window. The dedicated external-authentication scene is not another normal workspace window and is removed from the ordinary scene-opening commands. +`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. + +`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. + +```mermaid +sequenceDiagram + participant Navigator as Workspace Navigator + participant Coordinator as MainWindowCoordinator + participant Scene as Main WindowGroup + participant Source as Source WindowModel + participant Target as Target WindowModel + Navigator->>Coordinator: moveWorkspace with workspace ID + Coordinator->>Scene: createScene with request UUID + Scene->>Target: create fresh window model + Target->>Coordinator: register native window and request UUID + Coordinator->>Source: takeWorkspaceForMove + Coordinator->>Target: open live workspace +``` + +A workspace move waits for native destination registration before changing ownership. [Source: `TFM/Platform/MainWindowCoordinator.swift` and `TFM/Features/Workspaces/WindowModel.swift`.] ## The window shell owns chrome once @@ -95,6 +128,8 @@ The sidebar is one column whose mode rail switches between Navigator, Assistant, The column's material belongs to the native split view on macOS 26 and later; `RootView` does not layer another glass sheet over it. Earlier systems receive `LegacySidebarMaterialBackground`, an AppKit visual-effect fallback. Explicit glass remains on controls: the mode rail is one capsule with a neutral moving selection highlight, readable symbols, selected accessibility traits and a separate key-window keyboard-focus outline. Reduce Motion disables its selection animation. See [UI Design Principles](/openwiki/concepts/ui-design-principles.md) for row foreground and active/inactive selection roles. +The tool modes are projections of the **current window and focused pane**, not new destinations. Snippets searches the shared host-library snippets in its own footer, inserts into a live focused SSH/Telnet terminal on a single click, and double-click execution of a risky command asks for a second confirmation. History chooses SSH command history, SFTP browse history, or connection history from the focused pane; it uses the native `ListViewKit`-backed `SidebarNativeList` for stable card geometry and blank-area context menus. Snippet package folding is a persisted sidebar-only preference, separate from expansion on the main Snippets page. The snippet and history footer fields are not the titlebar Find field. + Keep the following coordinates distinct: - **Destination**: Vault, a workspace, full Assistant, Metrics or Settings. @@ -102,7 +137,42 @@ 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. Page searches, selections and archive presentation are window-local, so two windows may inspect the same shared data differently. +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. + +### Navigator interactions and workspace lifetime + +`WorkspaceNavigatorView` is an AppKit-backed SwiftUI `List` of Welcome, Metrics, Vault pages, Workspaces and Settings. A workspace row selects its workspace without starting a drag; the close affordance closes that workspace (Option-click closes the others). Its context menu can save/update a template, rename/reset eligible names, separate split panes, duplicate or split combinable sessions, move a workspace to another window, or close one/others/all. Context actions that operate on the selected pane first select the row's workspace. Section expansion is stored with `@AppStorage` and selecting a Vault page or workspace expands the corresponding section; this is sidebar presentation state, not the workspace collection. + +Inline rename seeds the editor with `workspace.title(in: app.hostLibrary, locale: locale)` **before** activating the rename field; commit sends the text to `WindowModel.rename`, cancel discards it. The model refuses non-renameable workspaces and trims whitespace: split names belong to the workspace, single-pane overrides to its pane; clearing restores an automatically allocated/derived name. This ordering matters because the native text field selects its initial text when focused. The visible-window `WorkspaceNavigatorRenameTests` exercise both the context-menu and double-click entrypoints and require the full existing title in the editable field. + +The layout drop receiver overlays the `List`, rather than attaching a target behind its native rows. Workspace and pane drags carry IDs, but live `WindowModel.dragging` identifies the payload during native callbacks, even before another SwiftUI render. On macOS 26+, the workspace row uses `.draggable` and the **active** native drag session sets this state from the pasteboard; querying a writer after a click must not start a drag. Earlier systems set it with `.onDrag`. Row/header frames are measured in global coordinates, translated at the receiver, then insertion geometry excludes the dragged workspace from the mutation index. A valid drop reorders with `move` or lifts a pane from a split workspace with `detachPane`; a lone pane cannot detach. Drops outside the Workspace section or after switching away from Navigator are rejected, and successful drops clear drag state. Older systems may retain drag state after a release outside any target until the next click or drag, so receivers still validate the pasteboard. See `WorkspaceNavigatorDropTests` for native drag, scrolled insertion previews, immediate callbacks, mode-change rejection and pane detachment. + +### Toolbar commands follow the detail, not the mode rail + +The window titlebar contributes creation actions from `WindowModel.creationActions` for the **foreground destination**: a single action is a plus button, several form a New menu, and Settings/Metrics detail can replace that position with Back or contextual controls. A Vault row's context menu calls `creationActions(for:)` through `creationMenu(for:locale:)`, so it can offer that page's creation verbs even when another page is in front. Switching the sidebar from Navigator to Assistant does not change the titlebar's New or Find target. + +`WindowModel.findKind` resolves the foreground Vault page, full Assistant, Metrics list/process detail, or the **focused** SSH/Telnet/Serial terminal or SFTP pane. Welcome has its own content search and no titlebar Find; Settings and unsearchable panes offer none. `findContext()` binds the toolbar to the actual page/window query or session query, with SSH/Serial terminal navigation and cancel callbacks. A focused Telnet pane reports `.terminal` from `findKind` and `focusToolbarFind()` presents its terminal search, but `findContext()` currently has no Telnet binding: unlike SSH/Serial it cannot render a usable titlebar field through that path. Per-page queries survive page switches. `TermindCommands` routes Find to the focused window model, which stands down pane focus *before* presenting terminal search, increments the focus request and invokes the mounted toolbar field's focus handler. Welcome instead increments its content-field request; with no searchable target it does nothing. + +```mermaid +sequenceDiagram + participant Command as Find command + participant Model as WindowModel + participant Toolbar as Toolbar search + participant Pane as Focused pane + Command->>Model: focusToolbarFind + alt Welcome content search + Model->>Model: request Welcome field focus + else Searchable foreground content + Model->>Pane: suppress pane keyboard claim + Model->>Pane: present terminal find if applicable + Model->>Toolbar: request focus through installed handler + Toolbar->>Model: bind query and report keyboard ownership + end +``` + +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. ## Persistent workspace deck: hidden is not destroyed @@ -208,13 +278,14 @@ Before changing a UI owner, trace both what happens when its view disappears and | Change | Focused seams | | --- | --- | -| Multi-window navigation, return routes or sidebar modes | `WindowModel`, `WindowSidebarTests`, `MultiWindowTests`, `SettingsNavigationTests`. | +| Scene ownership, workspace moves, window close or return routes | `TermindApp`, `MainWindowCoordinator`, `MultiWindowTests`, `WindowStateTests`, `SettingsNavigationTests`. | +| Sidebar modes, Navigator rename or layout drops | `WindowSidebarTests`, `WorkspaceNavigatorRenameTests` (visible-window), `WorkspaceNavigatorDropTests` (some visible-window cases), `WorkspaceLayoutDropTests`. | | Shared Assistant Archive state and surface-aware blank-area menus | `AssistantConversationMenuTests.archiveStateIsSharedWhileSidebarActionKeepsWorkspaceInFront` and `WindowStateTests` compact/full-screen navigation cases. | | Hidden workspace layout or drag geometry | `PersistentWorkspaceDeckLayoutTests`; split/pane interaction and broadcast tests. | | Narrow editor or Metrics detail layout | `ResponsivePageLayoutTests`, including native table identity and retained scroll positions. | | Managed selection/reordering | `ManagedCardDropResolver`, selection and marquee tests; resource-specific move tests. | | Transcript persistence, incremental updates or mounting | `TranscriptListViewTests`, rendering and performance suites. | -| Focused toolbar and terminal commands | `WindowToolbarFindTests`, `TerminalFindTests`, `UserInputModalityTests`. | +| Focused toolbar and terminal commands | `WindowToolbarFindTests` pins foreground/focused-pane routing, Welcome focus and per-page queries; `TerminalFindTests` and `UserInputModalityTests` cover terminal interaction. | | Welcome Recents, connection-history limits or pane close tracking | `ConnectionHistoryTests`, `VaultSyncTests`, and workspace close/reopen tests. | Some rendering tests explicitly require a visible window; routine checks should not enable those globally. The narrow-editor rendering cases cover English, Simplified Chinese and Traditional Chinese. This guide was derived from implementation and tests; it does not report a new test run or visual approval. Use [Build, Test, and Release Operations](/openwiki/operations/build-test-and-release.md) for the appropriate verification commands. diff --git a/openwiki/architecture/engineering-invariants.md b/openwiki/architecture/engineering-invariants.md index 21de7843..3ad34985 100644 --- a/openwiki/architecture/engineering-invariants.md +++ b/openwiki/architecture/engineering-invariants.md @@ -1,8 +1,11 @@ --- type: architecture-contract title: Cross-Cutting Engineering Invariants -description: Exhaustive architecture, ownership, lifecycle, security, persistence, remote-session, agent, sync, and mobile safety contracts that span Termind's specialized wiki pages. +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. tags: [architecture, invariants, lifecycle, security, persistence, remote-sessions, agent, mobile] +verified: + - by: openwiki/0.5.2 + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-8037e2358a2c4f9b2c722a11 resource: repo://AGENTS.md @@ -12,6 +15,8 @@ sources: resource: repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift - id: openwiki-source-1c48f72c0c7a3164d7d5c715 resource: repo://Frameworks/TermindApplication/Agent/ConversationModel.swift + - id: openwiki-source-875da2c4f1040409e53757af + resource: repo://Frameworks/TermindApplication/Events/HostDeletionHandlers.swift - id: openwiki-source-5c91b796f7e6d651aedf3023 resource: repo://Frameworks/TermindApplication/FeatureModels/CommandHistoryModel.swift - id: openwiki-source-dc7b363138921b0923d2dc2f @@ -24,6 +29,8 @@ sources: resource: repo://Frameworks/TermindApplication/SSHConnectionTypes.swift - id: openwiki-source-cd3e43e60522274ce1f1908b resource: repo://Frameworks/TermindApplication/SSHSecret.swift + - id: openwiki-source-c3006decff414f8b4ca021c4 + resource: repo://Frameworks/TermindDomain/Hosts/HostDeletion.swift - id: openwiki-source-1d1f503a260f304a969fcee4 resource: repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift - id: openwiki-source-4957f13c836c497e7ebe4656 @@ -40,8 +47,12 @@ sources: resource: repo://Frameworks/TermindPersistence/HostPersistence.swift - id: openwiki-source-28d6772acb1a409d29ff1973 resource: repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift + - id: openwiki-source-63e25c47c9c7d38b354f4123 + resource: repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift - id: openwiki-source-7a9c6d90cba4ebd1d1398673 resource: repo://Frameworks/TermindPersistence/TermindPersistence.swift + - id: openwiki-source-5b42af91dbdc738123786a99 + resource: repo://Frameworks/TermindPresentation/AgentToolPresentation.swift - id: openwiki-source-8185a608f0b79f1af097efbd resource: repo://Frameworks/TermindPresentation/Terminal/TerminalAppearance.swift - id: openwiki-source-0689f4693840cd29f5ac352c @@ -66,6 +77,8 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift - id: openwiki-source-6ec3fb4cd6a582cdf278bab9 resource: repo://FrameworkTests/AssistantExecutionControllerTests.swift + - id: openwiki-source-aec5af6c3be13b44140585c2 + resource: repo://FrameworkTests/AssistantTranscriptPresentationTests.swift - id: openwiki-source-bf7a64e7c819eb9279e2f9e4 resource: repo://FrameworkTests/CloudSyncLifecycleTests.swift - id: openwiki-source-40cfadc2320da9a292c64d26 @@ -82,6 +95,8 @@ sources: resource: repo://TFI/App/MobileSceneModel.swift - id: openwiki-source-6c9f797fc6a1e7ce639b72b8 resource: repo://TFI/App/TermindIOSApp.swift + - id: openwiki-source-d44869be46c03fbd0ce9c64c + resource: repo://TFI/Application/Agent/MobileAssistantModel.swift - id: openwiki-source-02810e1f8eac4d0983f8cd44 resource: repo://TFI/Features/Settings/MobileTerminalSettingsView.swift - id: openwiki-source-3c85f29e2d0bdf3d44f4e0e8 @@ -92,14 +107,18 @@ sources: resource: repo://TFI/Features/Workspaces/MobileWorkspace.swift - id: openwiki-source-350d4a794cfef67e406ddf9b resource: repo://TFI/Infrastructure/MobileWorkspaceStore.swift + - id: openwiki-source-34542e0f07e1650e098824c7 + resource: repo://TFI/Platform/MobileBackgroundController.swift - id: openwiki-source-e396438eb6a8a7ca888da5f4 resource: repo://TFI/Platform/TerminalFontCatalog.swift - id: openwiki-source-b822b041afbf829d09a8555a resource: repo://TFITests/MobileAppTests.swift + - id: openwiki-source-a154b5d36ec59496392d45e4 + resource: repo://TFITests/MobileAssistantTests.swift + - id: openwiki-source-c9618f94f83d3b529a9860e1 + resource: repo://TFITests/MobileBackgroundControllerTests.swift - id: openwiki-source-16ec96bd78162e7e62effd0e resource: repo://TFITests/MobileConnectionPickerTests.swift - - id: openwiki-source-9b78a7e39bfa08bea5192722 - resource: repo://TFITests/MobileWorkspaceStoreTests.swift - id: openwiki-source-4dbea0ff2808163cb4ecdd8f resource: repo://TFM/App/AppModel.swift - id: openwiki-source-6570374eaac2e0278fa84640 @@ -110,14 +129,15 @@ sources: resource: repo://TFM/Features/Workspaces/WindowModel.swift - id: openwiki-source-385c953ef1c6bf095d1c1244 resource: repo://TFM/Platform/TerminalFontCatalog.swift + - id: openwiki-source-73c75477db0674192248aa00 + resource: repo://TFMTests/AppTerminationTests.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift + - id: openwiki-source-32c251eb2f83ec0be2f1a0e8 + resource: repo://TFMTests/RepositoryOutboxTests.swift - id: openwiki-source-9442022b3dba1be62a55f0f0 resource: repo://TFMTests/TerminalThemeTests.swift -generated: { by: "codex", at: "2026-09-23T03:34:06.838Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Cross-Cutting Engineering Invariants @@ -151,6 +171,10 @@ sibling working tree is not the app dependency. Follow `AGENTS.md` for package r 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 only; UI/copy/wiring need behavioral or visual coverage. + Their 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 constructing ad hoc change batches. These are source-boundary checks, + not a substitute for behavioral sync or UI tests. - 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 @@ -171,9 +195,7 @@ sibling working tree is not the app dependency. Follow `AGENTS.md` for package r ### Windows and sessions -- App-wide snapshots/preferences and `VaultStore` transactions feed narrow feature intents; sessions receive only - `RemoteSessionHostStore`. Each scene owns a `WindowModel`, shell/navigation/search/context panels. Process routing - is UUID-scoped with weak native windows. Paywalls stay pinned to one window; speech belongs to one composer. +- Desktop `AppModel` coordinates saved Hosts, settings, transfers, sync, Assistant conversation storage and process services; registered `WindowModel`s own their Workspaces and navigation/search/context panels. The app holds weak window registrations and routes Host opens into the selected window. On mobile, `MobileAppModel` owns the live Workspace array and process services while each `MobileSceneModel` owns its destination, selected Workspace and Assistant navigation. App-wide snapshots/preferences and `VaultStore` transactions feed narrow feature intents; sessions receive only `RemoteSessionHostStore`. Paywalls stay pinned to one window; speech belongs to one composer. - New desktop windows start at Welcome; Dock reopen preserves destination and Metrics entry selects Metrics. Dock New Window uses the registered factory and activates hidden/windowless apps. Restoration never reconnects live Workspaces. New windows snapshot ordinary content size once, after full-size content styling; fullscreen/auxiliary @@ -201,6 +223,7 @@ sibling working tree is not the app dependency. Follow `AGENTS.md` for package r - Known Hosts is independent of Host records: editing/deleting a Host never changes trust. Plain and OpenSSH `|1|` hashed endpoints share matching; hashed records retain wire hostname and ignore the separate port. +- Saved-Host deletion is a durable request, not an immediate cascade. `SwiftDataHostRepository.requestHostDeletion` commits the pending-deletion marker, ordered outbox jobs, revision and Vault mutation together; snapshots hide the marked Host before physical removal. The outbox runs Workspace close, transfer cancellation, forwarding stop, reference/history cleanup and final Host/owned-Identity removal. Repository cleanup retries after interruption; do not replace it with only an in-memory UI removal. Desktop `AppModel.requestHostDeletion` projects the Host and clears local histories after the request succeeds; its registered runtime/outbox callbacks revoke live work. Mobile `deleteHost` also proactively disconnects Assistant and closes current and unopened Workspace entries, invalidates edits/transfers/forwardings and removes Metrics before requesting deletion, then starts its outbox. This mobile preflight is not the durable commit: an unsuccessful request returns an error, not a guarantee of restored live sessions. Remote Vault removal has its own runtime invalidation path on both platforms. Focused checks: `TFMTests/RepositoryOutboxTests.swift` for marker/jobs/reference and trust behavior; `TFITests/MobileAppTests.swift` for both current and Recent entries. - SSH import previews are window-owned indexed public metadata. Host selection never selects credentials; imported identities require selected keys. The actor retains scoped descriptors/digests, not private-key text/passphrases; reread selected keys at unlock/commit and fail closed if changed. Picking/drop share validation; config parsing @@ -467,6 +490,37 @@ factories/Sendable buffer handlers. Timers/workers enter explicit short MainActo ## Agent runtime and security +```mermaid +sequenceDiagram + participant User as Caller + participant Controller as AssistantExecutionController + participant Conversation as ConversationModel + participant Repository as AgentRunPersisting + User->>Controller: submit or prepare edit + Controller->>Conversation: capture turn and install preparation identity + opt edit + Controller->>Repository: truncate selected history + Repository-->>Controller: committed edit + end + alt preparation cancelled + User->>Conversation: stop + Conversation->>Controller: invalidate preparation immediately + Controller->>Controller: join tracked history and preparation work + Controller->>Repository: save interrupted snapshot + Repository-->>Controller: save outcome + Controller->>Conversation: project interruption on success or report save error + else missing model or credential + Controller->>Conversation: mark failure persistence in progress + Controller->>Repository: save failed snapshot + Repository-->>Controller: save outcome + Controller->>Conversation: project failed run on success or report save error + else ready + Controller->>Conversation: start runtime + end +``` +Preparation has distinct cancellation and failure-save phases; `stop()` requests the first path but does not await the repository. + + ### Providers - Empty credential reference means anonymous; nonempty missing/empty/unreadable secret is an error. `modelSecret(for:)` applies consistently @@ -506,10 +560,7 @@ factories/Sendable buffer handlers. Timers/workers enter explicit short MainActo search, skills/registry, Guardian and preparation settings synchronously before memory or automatic compaction awaits. First-send promotion follows accepted capture; edit UI captures before creating its persistence task. Plan implementation captures acting mode and consumes attachments/armed skills once. Historical context replay does not reconstruct old model settings or skill-package bytes. -- Preparation is distinct from streaming. Stop/background expiration invalidates preparation identity synchronously and joins pending - history/preparation work before its interrupted save; stale captures cannot edit or start. Archive/delete cancel pending preparation, - manual compaction refuses it, and navigation alone leaves it running. See [Assistant Runtime](/openwiki/concepts/agent-runtime-and-assistant.md) - for the preparation boundary and existing runtime/recovery limitations. +- Preparation is distinct from streaming and from terminal-failure persistence. For a still-`preparing` capture, `stop`, global cancellation and mobile background expiration request cancellation immediately on the MainActor: the identity becomes noncurrent before async work joins, so a stale edit cannot enter history mutation or start a run. The cancellation task waits for tracked edit/history and preparation tasks, then attempts to save an interrupted snapshot before projecting interruption and retiring preparation. `stop()` itself does **not** wait for that save; use `stopAndWait()` or await `cancelPendingRuns().value` at a drain boundary. A failed interrupted save reports an error instead of claiming durable interruption. Archive/delete await preparation cancellation; manual compaction refuses active preparation, and selection alone does not cancel it. Once missing-model/credential handling enters `savingFailure`, cancellation instead joins the in-flight failure save without replacing it with an interrupted snapshot: the failure is projected only after successful persistence; a failed save leaves an error and retires preparation. Tests block memory, truncation and save independently, so do not generalize the interruption guarantee across these phases. See [Assistant Runtime](/openwiki/concepts/agent-runtime-and-assistant.md). - History edits validate before persistence and publish their live replacement only after truncation commits. The boundary is the selected user message in canonical run/message order, not its whole run: retain the same-run prefix and owned tool graph with a neutral completed summary, remove the suffix and later runs, and prune compactions by removed message IDs. Compacted display history still informs ownership @@ -517,7 +568,7 @@ factories/Sendable buffer handlers. Timers/workers enter explicit short MainActo - An edited replacement initially owns a staging run whose ID equals its message ID. The first real snapshot transaction adopts only that staged row and deletes the staging run; historical replay rows keep their owners. Live running, failed and interrupted projections use the same provenance and preserve the staging chronology lower bound. Retired run IDs reject late saves/events in the repository instance. - This is not universal persist-before-publish: missing-model/credential failures still project live before their asynchronous save. + Missing-model/credential *preparation* failures are different: they keep the preparation owned through the asynchronous save, project a failed run only after it commits, and leave staging unadopted if that save fails. An already-started runtime has its own cancellation/event-drain lifecycle; do not infer universal persist-before-publish for its streaming UI from the preparation rule. - Project tool output once before `toolFinished`: bounded preview and scratch reference, retaining crash/replay metadata and paging offsets. Later completion never shortens earlier results; `sftp_read`/`scratch_read` report complete lines/truthful offsets. - Terminal suggestions use latest delivered user snapshot, not focus. Surface availability is partial and does not restrict independent SSH/ @@ -572,6 +623,14 @@ factories/Sendable buffer handlers. Timers/workers enter explicit short MainActo - Approval callbacks idempotently stage the same card before response; queued events cannot erase denial irrespective of arrival order. Historical repair recognizes local presenter identity, never MCP/name-only matches. Bounded previews/scrollable arguments keep actions accessible without reading live skill/memory stores or changing authorization/results/persistence. +- Approval arguments are a **live, user-only** projection of the original in-memory request, never copied to the durable + card or model transcript. A resolved Host name can replace `host_id` in the displayed arguments, while a presenter + may format the remaining arguments for review; compact action titles keep commands/paths in scrollable detail. + Result detail decodes local built-ins through an injected presenter or generic formatting, but MCP keeps its remote + JSON output; failed/denied/interrupted knowledge results cannot be rendered by a success presenter. A denial reason + identical to the review reason is displayed only once. Batch summaries group by tool, state and knowledge action so + mixed failures cannot be mislabeled successful; preview keeps head/tail within 8,192 characters and 120 lines while + Copy retains the full transformed output. Focused checks: `FrameworkTests/AssistantTranscriptPresentationTests.swift`. ## Commerce, review invitations and metrics @@ -595,6 +654,13 @@ factories/Sendable buffer handlers. Timers/workers enter explicit short MainActo temporary trust clears on pause/removal/config change. Free cap atomically three cards including paused, never delete on downgrade; Pro unlimited. - Desktop status item/popover receives model explicitly; last window close retains app/monitors, Quit cancels. Sleep/inactive login independently suspend; resume only awake/active with Data Protection Keychain available. Native lifecycle stays in `TFM/Platform`. +- On macOS Quit, the native delegate first rechecks dirty remote edits and offers Cancel/Quit Anyway; confirmed termination + requests one idempotent `AppModel.shutdownForTermination()` task. It fences new Assistant admissions, cancels captured + preparations and stops all stored conversations **before** awaiting saves/event drains. MCP and SFTP stop in parallel; + Agent background commands and connections close after the Assistant drains. Windows, forwarding, metrics, speech, + transfers and outbox are also retired. The delegate replies after cleanup or a three-second timeout, whichever wins, + exactly once: the deadline bounds app termination, not a promise that every save has completed. See + `TFMTests/AppTerminationTests.swift` for blocked-save, admission-fence and timeout ordering cases. ## Settings replication @@ -644,13 +710,36 @@ factories/Sendable buffer handlers. Timers/workers enter explicit short MainActo ### Workspaces and activity - One SSH session/SFTP Channel per mobile Workspace, no Welcome/pane composition even with Pro; Assistant independent. Peer switch retains connection, - Recent opens on demand, cross-open retains live paths. Explicit close never retries; failures stay in Journey. Background expiration closes - transports but retains intent; foreground resumes existing Workspaces. + Recent opens on demand, cross-open retains live paths. Explicit close never retries; failures stay in Journey. When all scenes background, the app pauses sync, Metrics, edits and outbox and begins a finite background task; **only on its expiration** it suspends Workspace transports, stops forwarding, pauses transfers and expires Assistant work. Foreground resumes only existing live Workspaces with foreground-resume intent; it does not cold-open other saved descriptors. This resume can initiate a fresh connection attempt, so it is not an implicit trust approval or command replay. +- `MobileBackgroundController` delivers expiration on the MainActor **synchronously** before retiring its finite UIKit + lease; the expiration closure immediately requests Workspace/forwarding/transfer/Assistant cancellation, but async + Assistant persistence and transport drains remain best effort under OS suspension. Replacement/finished leases ignore + late callbacks and each valid UIKit task ends once, even if expiration reenters `begin` before it returns; a failed + `.invalid` begin still requests expiration without ending an invalid task. `MobileAssistantModel` fences new sends, + edits, compaction and plan implementation while suspending, stops every conversation before awaiting any drain, then + closes background commands and connections. Do not equate expiration-handler return with a durable interrupted save. + Check `TFITests/MobileBackgroundControllerTests.swift` and `TFITests/MobileAssistantTests.swift`. + +```mermaid +sequenceDiagram + participant UIKit + participant Lease as MobileBackgroundController + participant App as MobileAppModel + participant Assistant as MobileAssistantModel + UIKit->>Lease: background task expires + Lease->>App: invoke expiration synchronously + App->>App: suspend workspaces and stop forwarding and transfers + App->>Assistant: expireBackground + Assistant->>Assistant: request all cancellations before draining + App-->>Lease: expiration returns + Lease->>UIKit: end valid task once + Assistant->>Assistant: drain saves then close agent transports best effort +``` +The finite UIKit lease ends after synchronous cancellation requests, not after asynchronous Assistant cleanup. - `mobile.workspaces.v1` persists ordered local descriptors only (ID/Host/kind/title), no commands/secrets/paths/content/transfers. - Cold launch after Hosts loads Recent only, no sessions/history/network. MainActor open-by-ID reuses or registers/connects once across scenes; - failure needs explicit retry. Save retains unopened entries/order. Read legacy arrays/v1 and migrate legacy arrays to the versioned envelope; + Cold launch after Hosts loads Recent only, no sessions/history/network. MainActor open-by-ID reuses or publishes then connects one instance across scenes; repeated selection does not retry a failed first attempt. Save retains unopened entries/order. Read legacy arrays/v1 and migrate legacy arrays to the versioned envelope; only successful loads permit save. Corrupt/unknown bytes remain/write-blocked. Prune missing Hosts; close/exit/delete removes live+Recent entries; - Close All preserves connection history. Host-delete outbox cancels related runtime/local history. + Close All preserves connection history. Local Host deletion closes both live and unopened descriptors immediately, with outbox cleanup for surviving durable work; remote removal closes them through Vault-apply handling. - Connection history is a synchronized Vault event stream for saved-host SSH/Telnet/SFTP only; Serial and temporary targets never enter it. Each event carries a stable `sourceDeviceID`, start time and optional end time, but no device name. The reusable synchronized device directory maps installation IDs to mutable display names, so a rename updates every feature that resolves that ID without rewriting history events. Closing a diff --git a/openwiki/architecture/index.md b/openwiki/architecture/index.md index 64ee0172..cdb87d01 100644 --- a/openwiki/architecture/index.md +++ b/openwiki/architecture/index.md @@ -1,11 +1,11 @@ # 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) - Exhaustive architecture, ownership, lifecycle, security, persistence, remote-session, agent, sync, and mobile safety contracts that span Termind's specialized wiki pages. +- [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. - [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) - Second-level directory responsibilities in TFM and TFI, including every feature area, platform adapters, reusable native UI, and the different window and scene ownership models. +- [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. - [Platform Runtime, App Composition, and Lifetimes](platform-runtime.md) - How Termind composes shared services and persistence on macOS and iOS, and where app-wide, window-local, scene-local, and session state begin and end. -- [Shared Framework Directory Responsibilities](shared-module-directories.md) - Functional directory responsibilities across Termind's six shared frameworks and shared resources, including flat-root concerns and how policy, persistence, transport, and presentation collaborate. +- [Shared Framework Directory Responsibilities](shared-module-directories.md) - Responsibilities and boundaries of Termind's shared frameworks and bundle resources, including agent execution, durable replay, SSH charset handling, and synchronized Xcode target membership. - [Supporting Products, Packages, and Tooling](supporting-system-directories.md) - Directory responsibilities and integration relationships for AgentKit, the MCP bridge, Live Activities, tests, benchmarks, the Astro site, marketing assets, scripts, and repository automation. - [System Boundaries and Dependency Ownership](system-boundaries.md) - Static framework layers, platform composition roots, persistence ownership, and the external AgentKit boundary that keep Termind changes dependency-safe. diff --git a/openwiki/architecture/mobile-ui.md b/openwiki/architecture/mobile-ui.md index 37f136dc..c3af91df 100644 --- a/openwiki/architecture/mobile-ui.md +++ b/openwiki/architecture/mobile-ui.md @@ -3,7 +3,14 @@ type: architecture guide title: TFI Mobile UI Architecture description: "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." tags: [ios, ipados, tfi, ui, navigation, adaptive-layout, swiftui, uikit] +verified: + - by: openwiki/0.5.2 + at: 2026-09-23T10:36:38.039Z sources: + - id: openwiki-source-d1d534769c300d5fb8dbe9d7 + resource: repo://Frameworks/TermindApplication/FeatureModels/HostCustomIdentityDraft.swift + - id: openwiki-source-eec1a2bc6dfc2c60b2bee55c + resource: repo://Frameworks/TermindPresentation/HostConnectionFields.swift - id: openwiki-source-906678adb91c2fce2d3fcaed resource: repo://TFI/App/MobileAppModel.swift - id: openwiki-source-60d390fe6fbfea55a2a8230a @@ -14,6 +21,8 @@ sources: resource: repo://TFI/App/MobileSceneModel.swift - id: openwiki-source-d44869be46c03fbd0ce9c64c resource: repo://TFI/Application/Agent/MobileAssistantModel.swift + - id: openwiki-source-851edcded7143bb79a41f6c6 + resource: repo://TFI/Application/Workspaces/MobileConnectionHistory.swift - id: openwiki-source-99e98ad50ba8a7c6df018977 resource: repo://TFI/Design/MobileDesignTokens.swift - id: openwiki-source-0368ecce931d0fb26fe8f35f @@ -26,6 +35,10 @@ sources: resource: repo://TFI/Features/AI/MobileAssistantConversation.swift - id: openwiki-source-d43ef236ba4bbb23d8dab797 resource: repo://TFI/Features/Assistant/MobileAssistantView.swift + - id: openwiki-source-fc448263e4e5ce330b8cbda1 + resource: repo://TFI/Features/HostEditor/MobileHostEditor.swift + - id: openwiki-source-ad662f2a7016a994d8522bf2 + resource: repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift - id: openwiki-source-3f37062f55fb57a9f2e97f35 resource: repo://TFI/Features/Vault/MobileVaultView.swift - id: openwiki-source-a337b6f93e72977e59faaf14 @@ -36,20 +49,23 @@ sources: resource: repo://TFI/Platform/MobileHomeScreenQuickActions.swift - id: openwiki-source-ca0b3e6e839587396cdeaf54 resource: repo://TFI/Platform/MobileTerminalSurface.swift + - id: openwiki-source-3af0aeffcab26dc81096aefc + resource: repo://TFI/UI/Components/MobileEditorSheet.swift - id: openwiki-source-c99ab42abad536ed4396933c resource: repo://TFI/UI/Managed/MobileCards.swift - id: openwiki-source-fffc181d864b6caea779a6f5 resource: repo://TFITests/MobileAdaptiveLayoutTests.swift - id: openwiki-source-b822b041afbf829d09a8555a resource: repo://TFITests/MobileAppTests.swift + - id: openwiki-source-c32ed562101f11a0c3c89663 + resource: repo://TFITests/MobileCardTests.swift - id: openwiki-source-16ec96bd78162e7e62effd0e resource: repo://TFITests/MobileConnectionPickerTests.swift + - id: openwiki-source-5636c5d112b9e5b2266c3058 + resource: repo://TFITests/MobileVaultFeatureTests.swift - id: openwiki-source-11c91698354a4f95be3c4654 resource: repo://TFITests/MobileWorkspaceMenuTests.swift -generated: { by: "codex", at: "2026-09-23T00:59:31.979Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T02:40:53.789Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # TFI Mobile UI Architecture @@ -81,6 +97,8 @@ flowchart TD Assistant --> Conversation[MobileAssistantConversation] ``` +Application services are shared while each scene retains its own feature navigation and Assistant selection. + `MobileFeatureRegistry` is the single registration table for feature identity, order, localized title, symbol and view builder. Its standard order is Vault, Metrics, Workspaces, Assistant, Settings, and duplicate destination registration is rejected. `MobileRootView` iterates registrations rather than maintaining independent tab/sidebar/destination switches. Each registered destination gets its own `NavigationStack`; the enclosing `TabView` uses `.sidebarAdaptable`. The system can change where navigation appears without the app rebuilding a different root tree for “phone” and “tablet.” `MobileLayout` supplies a compact/regular hint, defaulting to compact when size class is absent; it is not the whole adaptive layout algorithm. @@ -117,6 +135,8 @@ sequenceDiagram List->>List: push MobileWorkspaceView ``` +Cross-tab activation defers the push until the Workspaces destination has had a chance to mount. + When already on Workspaces, the scene can present the route directly. When changing tabs, pending activation waits for the Workspaces destination to participate before pushing its detail. Selecting another top-level destination clears pending workspace activation rather than leaving a delayed push armed. Host activation and explicit connection actions are different: @@ -139,19 +159,48 @@ connection-state dot; a saved-but-dormant descriptor has no dot. Rename edits ei descriptor directly, while Close removes the saved item and also disconnects it when a runtime exists. The detail switcher includes both kinds, marks the selected descriptor with a checkmark, and uses the protocol symbol for every other item. +### Deleting a Host is not popping a workspace + +Vault's confirmed **Delete Host** calls `MobileAppModel.deleteHost`, not the detail's back action. The app asks Assistant's connection pool to disconnect that Host, closes its saved live **and** unopened workspace descriptors (disconnecting any matching live workspace), invalidates SFTP edits, cancels transfers, stops/removes forwarding rules, removes Metrics selection, then requests repository deletion, projects the Host out of the library and starts the durable outbox. A repository error is reported through `app.error` and returns `false`; this is not an atomic rollback of the earlier cleanup. The registered outbox deletion handlers repeat workspace/history/projection, transfer and forwarding cleanup as the durable job proceeds. Deleting a Host group with `keepHosts: false` uses this Host path for each member; remote Vault removal closes associated saved descriptors and clears histories and Metrics too. Scenes reconcile routes against the changed live workspace IDs rather than owning the deletion itself. + ### Local Recents versus synchronized History -The Workspaces destination and the Vault expose different projections over the shared synchronized event stream: +The Workspaces destination and Vault History expose different projections over the shared synchronized event stream. `MobileVaultView` provides the navigation link (and searchable link); `MobileConnectionHistoryView` owns the History list, search, row actions and clear confirmation. `MobileConnectionHistory` builds the rows rather than either view storing a separate timeline: -- Workspaces Recents uses only events from this installation, aggregates every protocol and attempt into one row per Host, and keeps the newest five Hosts. A primary tap uses current Host capability preference (SSH before Telnet); protocol context and swipe actions keep SSH, Telnet and SFTP visible while disabling unavailable choices. Deleting the aggregate clears that Host's events across devices. -- Home Screen quick actions use the same local per-Host projection, publish at most three host-only `server.rack` items, and resolve the current preferred terminal protocol at activation. Older payloads that carried a protocol still decode, but that stale protocol is ignored. -- Vault's History page follows Known Hosts and displays up to 50 individual events from every synchronized device. The leading symbol remains protocol-specific, while the right column and search resolve the event's `sourceDeviceID` through the reusable synchronized device directory. Row deletion removes one event; **Clear History** clears the complete timeline. +- Workspaces Recents appears only if the ordered saved/live Workspace collection is empty. It uses this installation's events, aggregates protocols and attempts into one row per Host, and keeps the newest five Hosts. A primary tap resolves the Host's *current* preferred terminal protocol (SSH before Telnet); context and swipe actions offer only currently enabled SSH, Telnet or SFTP capabilities. Clearing a recent Host clears that Host's history across devices. +- Home Screen quick actions use the same local per-Host projection, publish at most three openable host-only `server.rack` items, and resolve the current preferred terminal protocol at activation. Older payloads carrying a protocol still decode, but that stale protocol is ignored. Root refreshes shortcuts on scene phase, history, Host and identity changes. +- Vault History follows Known Hosts in the unfiltered links and shows up to 50 individual events from all devices. Search filters by Host, login address, protocol and source-device name before applying the limit; Vault's own search can link into History with the query. The leading symbol stays protocol-specific and the device name comes from `DeviceDirectoryModel`. An event for a now-disabled protocol stays visible but cannot be tapped; row deletion removes one event, while **Clear History** clears the entire timeline, not just 50 displayed rows. The unified Workspaces rows and local Recents align their text from the same 36-point Host distribution icon slot and 12-point gap. Workspace rows always show protocol at the common right edge and only live runtimes overlay the status dot; aggregated Recents omits both protocol and live state. Local Recents replaces the empty Workspace section rather than appearing beside saved-but-dormant Workspaces. TFI exposes no Serial workspace or connection-history kind. +## Vault cards, search and editor ownership + +`MobileVaultView` is the Vault landing page, not the owner of every Vault operation. It composes Keychain, Port Forwarding, Snippets, Known Hosts and History as links in its own feature stack. Searching replaces the normal Host/group presentation with matching Host cards and deep links to matching items or page titles; linked subpages receive the query when the match was an item. Metrics search is a cross-tab selection, not an empty Vault detail. Vault's Host sections use the library's group projection: nested groups have path titles, empty groups remain visible, collapse is stored in the library, and search still finds Hosts inside collapsed groups. New Host and New Group are in the add menu; per-group menus create Hosts/subgroups and edit or delete a group. Group deletion offers keeping Hosts (ungrouping them) or deleting the tree's Hosts through the app's Host deletion path. + +`MobileCardPage` is a grouped-background scrolling page; `MobileCardGrid` measures its actual width and computes flexible columns with 12-point gaps, forcing a single column at accessibility text sizes. `MobileCard` and `MobileActionCard` share a 106-point minimum-height surface. On iOS 26 the surface uses a concentric shape and glass only when transparency/contrast settings permit; older or higher-contrast/reduced-transparency presentation uses a solid grouped surface. The action card makes the *whole card* the primary button, leaving secondary actions in a context menu. Cards keep at most two visible Host tags to avoid varying the standard height; this is a display limit, not removal of tags from the Host. + +A Vault Host card opens/reuses a terminal workspace through `scene.activateHost`; its context menu offers enabled SSH/Telnet/SFTP explicit connections separately from Edit, Duplicate and Delete. The card's relative timestamp comes from app connection history. `MobileAppModel.duplicateHost` gives the copy a new ID/name and strips Host-custom identity references rather than sharing Host-specific secrets. The edit sheet binds `scene.editingHost` so a New Host command can select Vault and present the same editor; Vault keeps only temporary delete/group confirmation state. Known Hosts is a *separate* Vault-linked card page: its primary card tap edits a known SSH host key, context actions copy the fingerprint or request deletion, and its add/edit sheet saves through `app.knownHosts`, not through the Host connection editor. + +```mermaid +flowchart TD + Tap["Vault Host card"] --> Activate["Scene activates preferred terminal Host"] + Menu["Host context menu"] --> Connect["Explicit protocol connection"] + Menu --> Edit["Scene-bound Host editor sheet"] + Menu --> Duplicate["App duplicates Host without custom identity references"] + Menu --> Confirm["Confirm Host deletion"] + Confirm --> Cleanup["App deletes Host and cleans shared work"] + Link["Vault History link"] --> Events["History view over shared event rows"] +``` + +Vault gestures route to scene selection or application services; a Vault page does not own a running connection or the history repository. + +`MobileHostEditor` holds an in-memory Host draft plus `HostCustomIdentityDraft` (password fields live only for the editor's lifetime). Shared `TermindPresentation` Host organization, protocol-profile and connection sections provide the form, while mobile-specific sheets let the user create a group, identity or environment variable and apply that result to the draft. Selecting the SSH or Telnet profile changes which authentication, proxy and session controls appear; save requires an address, an enabled terminal protocol, valid enabled ports, identity/proxy validation and valid SSH environment variables. `HostCustomIdentityDraft.save(into:using:)` persists applicable custom identities and then the Host via the library, throwing on failure. Do not treat a profile switch or sheet dismissal as a save. + +`MobileEditorSheet` owns async Save/Cancel behavior for these forms: dirty Cancel asks before discard, Save disables editing and shows progress, a thrown error stays on the sheet in an alert, and success dismisses it. Dirty or saving sheets cannot be interactively dismissed; disappearance cancels the in-flight task. Group and Known Host editors use the same wrapper with their own validation/storage boundary; the Known Host editor distinguishes Add from Edit and does not expose a port field for hashed addresses whose original address/port cannot be recovered. + ## Adaptation has three inputs, not one device check | Input | Mechanism | What it controls | @@ -178,6 +227,8 @@ flowchart LR Assistant --> Layout[MobilePaneLayout with stable children] ``` +Reserved geometry determines usable content and optional Assistant pane placement without replacing its native children. + Production reserved-region and vertical-toolbar queries require both the `TERMIND_HAS_IOS_27_1_SDK` compilation gate and runtime availability. On older builds/systems the reader falls back to no reserved regions, while previews/tests can inject regions through the environment. The presence of deterministic fold-like tests is not a claim of verification on every physical device. `MobilePaneLayout` retains a valid size per child index and places the same children into their new frames. Covered content keeps a valid size rather than replacing or reparenting its native surface. The layout must be paired with opacity, hit-testing and accessibility gates: parked geometry alone does not make a covered view noninteractive. @@ -236,6 +287,10 @@ Implemented principles: 5. **Keep app work out of transient view lifetimes.** Scene routes select shared work; they do not own every connection or Agent run. 6. **Hide covered interaction as well as pixels.** Hit testing and accessibility must follow the visible region. -`MobileAdaptiveLayoutTests` exercises native tab identity across compact/regular widths, all five destinations, Dynamic Type and English/Chinese variants. It also checks that region changes retain the Metrics list and scroll position, and preserve Assistant conversation identity, native transcript, composer focus and marked Chinese text. These tests validate injected geometry and navigation behavior; platform availability and real-device presentation still need appropriate device verification. +`MobileAdaptiveLayoutTests` mounts `MobileRootView` in a UIKit window and checks the same native `UITabBarController` with five selectable destinations over simulated 1024/600/375/320-point widths, regular/compact traits, large/accessibility Dynamic Type, and English, Simplified and Traditional Chinese locales. In compact mode it asserts all five tab labels are visible; on regular iPad widths the system bar can scroll. Other tests retain Assistant conversation/draft and Metrics navigation through resizing, check title-menu/icon switchers and Settings edit sheets, and isolate two scene models. Injected division and occlusion changes verify Metrics keeps the same native list and scroll offset and Assistant keeps its conversation, transcript `ListScrollView`, focused composer and Chinese marked text; a save-in-flight test preserves a sheet and failure feedback through width changes. These are simulated layout and injected-geometry tests, not proof of every physical device or SDK availability branch. + +`MobileAppTests` separately covers descriptor order after restoring, opening and renaming live/dormant workspaces, transient external entries, single-connect restoration across scenes, explicit retry after failed connection, and local/remote Host deletion removing both open and unopened descriptors while retaining unrelated Hosts. The adaptive suite also checks localized compact/regular Workspace rows and that choosing a dormant row restores only that runtime without moving the row. + +`MobileCardTests` tests card column thresholds (one below 652 points, two from 652, three from 984, but always one for accessibility text), stable Host/action-card height with long or absent tags, the two-tag display limit, nested/empty/collapsed Host groups, Known Host add/edit titles, and Host connection timestamps. `MobileVaultFeatureTests` exercises capability-filtered Host context menus, independent duplication, keep/delete group-tree behavior and proxy validation; `MobileConnectionPickerTests` checks that History caps *matching event rows* at 50, searches device names and leaves disabled-protocol events visible but not openable. These policy tests complement, rather than replace, the UIKit-hosted adaptive tests for real navigation and sheet continuity. For a change, inspect scene routing tests for navigation, region/layout tests for geometry, workspace/terminal tests for session continuity, and Assistant tests for run-versus-selection ownership. See [Platform Runtime Composition](/openwiki/architecture/platform-runtime.md) and [Build, Test, and Release Operations](/openwiki/operations/build-test-and-release.md) before changing the lifetime boundary. diff --git a/openwiki/architecture/module-map.md b/openwiki/architecture/module-map.md index 005ab518..bc378ae9 100644 --- a/openwiki/architecture/module-map.md +++ b/openwiki/architecture/module-map.md @@ -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-23T10:36:38.039Z sources: - id: openwiki-source-ed77bc20b48d193bace3dde6 resource: repo://.gitmodules @@ -30,12 +33,18 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift - 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-a62bfbbc7de13a894444718b resource: repo://TermindMCPBridge/main.swift + - id: openwiki-source-dc9295278cc250ed20567540 + resource: repo://TFI/App/MobileAppDependencies.swift - id: openwiki-source-906678adb91c2fce2d3fcaed resource: repo://TFI/App/MobileAppModel.swift - id: openwiki-source-e43a0da5ab77c2fc3554244d resource: repo://TFI/App/MobileSceneModel.swift + - id: openwiki-source-6c9f797fc6a1e7ce639b72b8 + resource: repo://TFI/App/TermindIOSApp.swift - id: openwiki-source-d1ffd558b3360478aa85b5af resource: repo://TFIWidgets/WorkspaceLiveActivity.swift - id: openwiki-source-6570374eaac2e0278fa84640 @@ -46,10 +55,7 @@ sources: resource: repo://TFMTests/ArchitectureBoundaryTests.swift - id: openwiki-source-0f8d0f9d08d6674698dd054c resource: repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift -generated: { by: "codex", at: "2026-09-22T09:17:11.491Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Module and Directory Architecture Map @@ -102,11 +108,11 @@ flowchart TB Application --> Domain ``` -Both app targets directly depend on all six frameworks. The diagram also explains why Persistence is not interchangeable with general Infrastructure: Infrastructure can use Persistence, while Persistence must not depend on Infrastructure or Remote Infrastructure. Shared frameworks never depend on an app target. +Both `TFM` and `TFI` directly depend on all six frameworks; `TermindDomain` has no shared-target dependency. These are explicit `PBXTargetDependency` edges, not inferred from directory proximity or imports. The diagram also explains why Persistence is not interchangeable with general Infrastructure: Infrastructure can use Persistence, while Persistence must not depend on Infrastructure or Remote Infrastructure. Shared frameworks never depend on an app target. `FrameworkTests` depends on all six shared frameworks, while `TFMTests` and `TFITests` depend on their respective app plus selected shared frameworks; the benchmark does not depend on either app or a test target. ## Product and package boundaries -Arrows here are **labeled relationships**, not a complete link graph. The shared-framework group expands into the graph above. AgentKit's package products are linked by multiple layers, including Domain, Application, Persistence, Remote Infrastructure, and app composition; the single package edge below groups those consumers rather than implying one exclusive entry point. +Arrows here are **labeled relationships**, not a complete link graph. The shared-framework group expands into the graph above. The remote AgentKit package supplies `AgentKit` to Domain, Application, Persistence, both apps, and tests; `AgentKitScrubber` is linked by Remote Infrastructure and desktop composition. The single package edge below groups those consumers rather than implying one exclusive entry point. `TermindPresentation` instead directly links the Ghostty and MarkdownView package products, and `TermindRemoteInfrastructure` links `CSSH2` and `OpenSSL`. Check target `packageProductDependencies` for the exact package linkage before relocating code. ```mermaid flowchart LR @@ -118,11 +124,13 @@ flowchart LR Activity["WorkspaceActivitySupport"] -.->|source compiled into both| Mobile Activity -.->|source compiled into both| Widget Package["Resolved AgentKit package products"] -.->|linked by owning consumers| Shared - Checkout["AgentKit reference checkout"] -.->|inspect separately; not an Xcode path dependency| Package + Checkout["AgentKit reference checkout"] -.->|not an Xcode path dependency| Package Benchmark["Port-forwarding benchmark"] -->|depends on| Remote["Remote Infrastructure + Application + Domain"] ``` -The MCP bridge translates stdio requests into authenticated HTTP calls to the desktop server; it is not the server itself. The widget renders a bounded workspace summary; it does not establish SSH sessions. The benchmark is a standalone executable, not app startup logic or a test-host dependency. +The MCP bridge translates stdio requests into authenticated HTTP calls to the desktop server; it is not the server itself. `TFM` builds and embeds this separate tool. `TFI` builds and embeds the `TermindWidgets` extension, which directly depends on Presentation; `WorkspaceActivitySupport` is source-compiled in both the app and extension (and in `TFITests`), not a seventh framework. The widget renders a bounded workspace summary; it does not establish SSH sessions. The benchmark is a standalone executable linked to Remote Infrastructure, Application, and Domain, not app startup logic or a test-host dependency. + +**AgentKit version boundary:** `.gitmodules` names an `AgentKit/` reference checkout, and repository guidance also describes a sibling `../AgentKit` development tree. Neither is wired into this Xcode project as a local package path: the project declares a remote `upToNextMajorVersion` requirement starting at `0.14.0`, and `Package.resolved` currently pins the remote to `0.14.0` at revision `ffc4aa41c8854142aa47c35231e57f56f961ba9f`. A local checkout edit alone will not change the Xcode build; release the package change, update the project requirement, and re-resolve the pin together. AgentKit owns the generic agent loop and tools; Termind registers host-specific SSH/SFTP tools in Remote Infrastructure. ## How responsibilities meet @@ -137,7 +145,9 @@ The MCP bridge translates stdio requests into authenticated HTTP calls to the de This split is also a placement rule: shared behavior belongs with its existing owner; native lifetime or platform API usage stays in the app. Similar names such as `Agent`, `Transfers`, `Terminal`, or `Metrics` in different modules do not imply duplicated responsibilities. -## State boundaries to keep in mind +## Composition and state boundaries + +`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. - **Desktop window:** navigation, workspace collection, pane selection, searches, and transcript caches. @@ -146,3 +156,7 @@ This split is also a placement rule: shared behavior belongs with its existing o - **Durable storage:** metadata, histories, configuration, and separately governed memory; not live transports or transient credentials. For lifetime diagrams, continue with [Native App Directory Responsibilities](native-app-directories.md) and [Platform Runtime](platform-runtime.md). For change-oriented navigation and verification, return to the [Engineering Quickstart](../quickstart.md). + +## 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). diff --git a/openwiki/architecture/native-app-directories.md b/openwiki/architecture/native-app-directories.md index 77998ec8..9b28fd13 100644 --- a/openwiki/architecture/native-app-directories.md +++ b/openwiki/architecture/native-app-directories.md @@ -1,8 +1,11 @@ --- type: architecture directory guide title: Native App Directory Responsibilities -description: Second-level directory responsibilities in TFM and TFI, including every feature area, platform adapters, reusable native UI, and the different window and scene ownership models. +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-23T10:36:38.039Z sources: - id: openwiki-source-c4b6e224fdbea6dcd393344d resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift @@ -10,16 +13,28 @@ sources: resource: repo://Termind.xcodeproj/project.pbxproj - 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-e43a0da5ab77c2fc3554244d resource: repo://TFI/App/MobileSceneModel.swift + - id: openwiki-source-6c9f797fc6a1e7ce639b72b8 + resource: repo://TFI/App/TermindIOSApp.swift - id: openwiki-source-83cf4f34941d19114f080a3a resource: repo://TFI/Application/Connections/MobileWorkspaceConnectionServices.swift - id: openwiki-source-deb061208994fd7d84d4f029 resource: repo://TFI/Application/Transfers/MobileSFTPChannelModel.swift + - id: openwiki-source-851edcded7143bb79a41f6c6 + resource: repo://TFI/Application/Workspaces/MobileConnectionHistory.swift - id: openwiki-source-0368ecce931d0fb26fe8f35f resource: repo://TFI/DesignSystem/MobileContentRegions.swift - id: openwiki-source-d43ef236ba4bbb23d8dab797 resource: repo://TFI/Features/Assistant/MobileAssistantView.swift + - id: openwiki-source-fc448263e4e5ce330b8cbda1 + resource: repo://TFI/Features/HostEditor/MobileHostEditor.swift + - id: openwiki-source-ad662f2a7016a994d8522bf2 + resource: repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift - id: openwiki-source-e21fae39ef7af76f86acbff6 resource: repo://TFI/Features/Settings/MobileSettingsView.swift - id: openwiki-source-17e754ff6e9f61a92b68cb8a @@ -38,6 +53,18 @@ sources: resource: repo://TFI/Platform/MobileSFTPOpenWithPresenter.swift - id: openwiki-source-ca0b3e6e839587396cdeaf54 resource: repo://TFI/Platform/MobileTerminalSurface.swift + - id: openwiki-source-b822b041afbf829d09a8555a + resource: repo://TFITests/MobileAppTests.swift + - id: openwiki-source-c9618f94f83d3b529a9860e1 + resource: repo://TFITests/MobileBackgroundControllerTests.swift + - id: openwiki-source-16ec96bd78162e7e62effd0e + resource: repo://TFITests/MobileConnectionPickerTests.swift + - id: openwiki-source-282855f9369e6dc0c3447dc8 + resource: repo://TFITests/MobileSettingsPortTests.swift + - id: openwiki-source-b8fca76c89564e16eccfbb53 + resource: repo://TFM/App/MCPServerController.swift + - id: openwiki-source-873894299539cce9a737a860 + resource: repo://TFM/App/RootView.swift - id: openwiki-source-6570374eaac2e0278fa84640 resource: repo://TFM/App/TermindApp.swift - id: openwiki-source-8a6e94328a445c3566ef9d57 @@ -58,6 +85,8 @@ sources: resource: repo://TFM/Features/SFTP/SFTPChannelModel.swift - id: openwiki-source-07825e2cdc632a818b8c30ee resource: repo://TFM/Features/Shell/WindowRoute.swift + - id: openwiki-source-0854be84b166268626a3cb08 + resource: repo://TFM/Features/Sidebar/WindowSidebarView.swift - id: openwiki-source-7e796927b780e67cc73f6a5b resource: repo://TFM/Features/Terminal/SSHSessionModel.swift - id: openwiki-source-507cd94a8ae82f840ac8591f @@ -84,10 +113,11 @@ sources: resource: repo://TFM/UI/Managed/ManagedCardPage.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.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-47dc468698b2904f0004ee04 + resource: repo://TFMTests/MCPUploadTests.swift + - id: openwiki-source-ea148dc5de8cabfc00dc07ae + resource: repo://TFMTests/WindowSidebarTests.swift +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Native App Directory Responsibilities @@ -139,6 +169,8 @@ The app composition roots also adapt platform device naming into the shared devi 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 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. + ## Feature subdirectories Every current immediate child of either `Features` directory is included here. @@ -150,10 +182,10 @@ Every current immediate child of either `Features` directory is included here. | `Commerce` | Pro paywall presentation. | Mobile Pro purchase presentation. | | `ExternalRequests` | Feature-owned external authentication coordination and its dedicated window. | Not present; mobile features retain their own authentication UI. | | `HostChooser` | Select hosts/connections for desktop actions. | Mobile connection picker. | -| `HostEditor` | Host connection and metadata editor. | Mobile host editor. | -| `Hosts` | Host management page, host actions, and group creation. | Not present as a separate directory; host management is composed into mobile Vault. | +| `HostEditor` | Host connection and metadata editor. | Host draft sheet for SSH/Telnet profiles, identity/proxy, group and session settings; uses the app's host library to save rather than owning a connection. | +| `Hosts` | Host management page, host actions, and group creation. | Not present as a separate directory; host cards, groups and their actions live in mobile Vault. | | `Keychain` | Saved key/identity management and identity creation. | Credential list and key editor. These are metadata/editor surfaces, not the Keychain implementation. | -| `KnownHosts` | Saved server-trust management. | Mobile saved server-trust management. | +| `KnownHosts` | Saved server-trust management. | Searchable trusted-host cards and a validated add/edit sheet backed by `app.knownHosts`, not a transport trust store owned by the view. | | `Metrics` | Overview/detail dashboards, responsive layouts, server details, and connection-journey presentation. | Mobile metrics dashboard and details. | | `Ports` | Port-forwarding library and rule interaction. | Forwarding library and editor. The connection controller remains in Remote Infrastructure. | | `QuickOpen` | Keyboard-oriented quick navigation/connection surface. | Not present. | @@ -161,12 +193,12 @@ Every current immediate child of either `Features` directory is included here. | `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. | | `Shell` | Window destination/route and title values. | Mobile destination and navigation values. **Neither folder is the remote shell protocol implementation.** | -| `Sidebar` | Desktop Navigator/contextual Assistant/Snippets/History column. | Not present; mobile uses its registered tab/sidebar navigation shell. | +| `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. | | `StatusBar` | Workspace status overlay and related interaction. | Not present as a separate directory. | | `Terminal` | SSH, Telnet, and serial session models; persistent terminal surface; serial controls and placeholders. | Terminal keyboard, selection, history, snippets, and list presentation. Live connection ownership is in `Features/Workspaces`, while the native surface adapter is in `Platform`. | | `Transfers` | Not present as a separate feature directory; transfer-library state is in `Application/FeatureModels`. | Transfer queue presentation and actions. | -| `Vault` | Vault routing/page state and list/detail workspace composition across managed resources. | Mobile Vault entry and resource-management composition. | +| `Vault` | Vault routing/page state and list/detail workspace composition across managed resources. | Searchable host/group cards and navigation links to credentials, forwarding, snippets, trusted hosts and connection History; contains the History view, not its persistent store. | | `Workspaces` | Window/workspace/pane models, split layout, persistent deck, Navigator integration, templates, and empty panes. | Workspace runtime, workspace list/detail, and rename interaction. | ### Why similarly named areas stay separate @@ -174,9 +206,31 @@ Every current immediate child of either `Features` directory is included here. - **AI versus Assistant:** `AI` contains reusable conversation pieces; `Assistant` composes the product destination and navigation. - **Shell versus Terminal:** `Shell` is navigation vocabulary; `Terminal` is terminal interaction/session presentation. Remote shell bootstrap and transport execution belong to the shared remote stack. - **SFTP versus Transfers:** browsing/control state is not the scheduler or lifetime of a queued file operation. -- **Vault versus Hosts/Keychain/KnownHosts/Snippets/Ports:** Vault composes management destinations; specialized areas own resource-specific interaction. +- **Vault versus Hosts/Keychain/KnownHosts/Snippets/Ports:** Desktop Vault routes to dedicated manager pages. Mobile Vault itself renders host/group cards and owns only local search, sheet and confirmation state; its links push specialized screens. Mobile History's SwiftUI view happens to be in `Features/Vault/MobileVaultView.swift`, while row filtering/action policy lives in `Application/Workspaces` and the connection-history model is app-owned. A file location or a pushed destination does not transfer the data or session lifetime to Vault. - **Settings versus service models:** closing Settings must not end synchronization, metrics, forwarding, or transfer work. +### Native navigation and editing boundaries + +On mobile, `App/MobileFeatureRegistry.swift` registers Vault, Metrics, Workspaces, Assistant and Settings. `MobileRootView` mounts a separate `NavigationStack` for each registered tab and retains one `MobileSceneModel` per scene. Vault receives scene callbacks and a binding to `scene.editingHost`: tapping a host card asks the scene to reuse or open its preferred terminal workspace; SSH/Telnet/SFTP menu actions explicitly open a connection, while Edit presents `MobileHostEditor` as a sheet. The editor keeps a host draft and custom-identity draft, validates protocol, port, authentication and environment fields before saving through `HostLibraryModel`; nested identity/group/environment editors stay in the sheet workflow. Host deletion instead calls `MobileAppModel.deleteHost`, which closes matching workspaces, invalidates edits, cancels transfers and cleans up forwarding/metrics before deleting the host projection. Do not move these app-level effects into the Vault card or sheet. + +Vault search links to resource pages can pass the search query into the pushed page; Metrics search switches the registered top-level destination. Its History link opens `MobileConnectionHistoryView` in the Vault file, showing up to 50 filtered events resolved against the host library and device directory. A history row opens only if that protocol is still enabled for its host; deletion and clear-all act on `app.connectionHistory`. The separate `MobileKnownHostsView` uses `app.knownHosts` for search, save and delete; its editor surfaces storage failure rather than silently treating a failed save as success. Neither screen owns the persisted records simply because Vault pushes it. + +```mermaid +flowchart TD + Registry["App feature registry"] --> Root["MobileRootView tab and navigation stack"] + Root --> Vault["Vault host and resource navigation"] + Vault -->|"host tap or connect menu"| Scene["MobileSceneModel selects workspace"] + Scene -->|"open if needed"| AppModel["MobileAppModel retains live workspaces"] + Vault -->|"edit host"| Editor["MobileHostEditor draft sheet"] + Editor -->|"save"| Library["Host library"] + Vault -->|"history link"| History["MobileConnectionHistoryView"] + History -->|"read and delete"| HistoryStore["App connection history"] +``` + +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. + ## Infrastructure subdirectories | TFM directory | Responsibility | @@ -222,6 +276,8 @@ flowchart TB Models -->|uses policy and values| Shared["TermindApplication + TermindDomain"] ``` +App assembly connects feature interaction to injectable services without making every feature a passive view. + A dependency object supplies live/test alternatives; it does not itself become the lifetime owner of every object it creates. Some feature runtime owners legitimately retain remote services. The boundary tests prohibit direct concrete construction/storage access in feature code rather than pretending features contain only passive views. ## Runtime ownership: desktop is not mobile @@ -247,6 +303,32 @@ flowchart TB desktop ~~~ mobile ``` -Desktop destination switches park persistent workspace views; mobile route changes select retained runtime objects. Neither is equivalent to closing a connection. Mobile background expiration is a separate app-level boundary, and persisted workspace descriptors restore connection intent rather than authenticated transports. +Per-window desktop state and per-scene mobile routes have different owners from the shared app services. -For mechanisms and tests, continue with [Desktop UI](desktop-ui.md), [Mobile UI](mobile-ui.md), and [Platform Runtime](platform-runtime.md). `ArchitectureBoundaryTests` checks placement; window/sidebar tests, mobile scene/workspace tests, and adaptive-layout tests protect behavior. Return to the [Module Map](module-map.md) for the full dependency picture. +Desktop destination switches park persistent workspace views; mobile route changes select retained runtime objects. Neither is equivalent to closing a connection. Persisted mobile workspace descriptors restore connection intent rather than authenticated transports: `openWorkspace` publishes the shared runtime before connecting so two scenes cannot independently start the same restored session. An explicit close removes its descriptor and disconnects it. The macOS `WindowGroup` constructs a new `WindowModel` for each window and injects the shared `AppModel` and SwiftData container; its delegate handles system-level activation, window reopening, and termination, including pending SFTP edit confirmation. By contrast, iOS `TermindIOSApp` builds one `MobileAppModel` for its `WindowGroup`, while each `MobileRootView` retains its own `MobileSceneModel` for selection, Assistant drafts and presentations. + +### Mobile lifecycle and sync boundary + +`MobileRootView` reports each scene phase and removal to the app model, and observes Pro changes to call `reconcileSync`. The app records phases per scene. On the first transition where **all registered scenes** are backgrounded (including removal of the last active scene while another remains backgrounded), it pauses monitoring, memory, sync engines, metrics and outbox, suspends Assistant recording and asks `MobileBackgroundController` for a UIKit background-task lease. It does **not** immediately disconnect healthy workspaces. Lease expiry requests workspace suspension and stops forwarding, transfers and Assistant background execution. The controller retires a lease exactly once; stale expiry callbacks cannot affect a replacement lease, and synchronous expiry during `begin` or an invalid identifier is handled without leaking an end call. + +On an active scene transition, the app finishes the lease, resumes affected workspaces, monitoring and memory, rechecks edited files, refreshes Pro, restarts outbox/metrics and Live Activities, and reconciles sync. `reconcileSync` starts vault, metrics and settings sync **only when at least one tracked scene is active and Pro permits vault sync**; otherwise it pauses all three. `setSyncEnabled` guards enabling with `pro.require(.vaultSync)`, stores the preference, migrates custom passwords when enabling vault/iCloud sync and calls `reconcileSync`—the individual coordinators still enforce their own enabled preferences. A `.inactive` scene is not an active scene for this decision, and an empty scene registry does not trigger background entry, but reconciliation pauses sync. In-memory/test composition omits the cloud coordinators altogether. + +```mermaid +flowchart TD + Phase["Scene phase or scene removal"] --> Track["MobileAppModel records phases"] + Track --> AllBG{"All tracked scenes backgrounded now"} + AllBG -->|first transition| Pause["Pause services and begin UIKit lease"] + Pause --> Expire["Lease expires"] + Expire --> Suspend["Suspend workspaces and background work"] + Track -->|active scene| Foreground["Finish lease and resume services and workspaces"] + Foreground --> Sync["Reconcile sync"] + Track -->|scene removed| Sync + Pro["Pro entitlement change or sync setting"] --> Sync + Sync --> Gate{"Active scene and Pro vault sync"} + Gate -->|yes| Start["Start three sync coordinators"] + Gate -->|no| Stop["Pause three sync coordinators"] +``` + +Scene registration and entitlement gate app-owned synchronization independently of the visible route. + +Mobile phase transitions, lease expiration and entitlement changes operate on app-owned services, not a scene's route. For focused coverage, `TFITests/MobileAppTests.swift` tests expiration/re-entry, the last-active-scene removal, and restoration across scenes; `TFITests/MobileBackgroundControllerTests.swift` tests synchronous expiration, replacement and invalid leases; `TFITests/MobileSettingsPortTests.swift` verifies in-memory composition has no cloud engines. `TFMTests/MCPUploadTests.swift` exercises resumable offset/digest, revocation, timeout, retention and rejection before consumption. For more mechanisms continue with [Desktop UI](desktop-ui.md), [Mobile UI](mobile-ui.md), and [Platform Runtime](platform-runtime.md). `ArchitectureBoundaryTests` checks placement; window/sidebar and adaptive-layout tests protect behavior. Return to the [Module Map](module-map.md) for the full dependency picture. diff --git a/openwiki/architecture/platform-runtime.md b/openwiki/architecture/platform-runtime.md index 440cd50b..fea6a3ed 100644 --- a/openwiki/architecture/platform-runtime.md +++ b/openwiki/architecture/platform-runtime.md @@ -3,7 +3,22 @@ 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-23T10:36:38.039Z sources: + - id: openwiki-source-875da2c4f1040409e53757af + resource: repo://Frameworks/TermindApplication/Events/HostDeletionHandlers.swift + - id: openwiki-source-1d1f503a260f304a969fcee4 + resource: repo://Frameworks/TermindInfrastructure/Cloud/CloudSyncLifecycle.swift + - id: openwiki-source-3effdff7f6b04e2a66d8f651 + resource: repo://Frameworks/TermindInfrastructure/Cloud/MetricsSyncCoordinator.swift + - id: openwiki-source-04ef2b2f02773f8833db9a8b + resource: repo://Frameworks/TermindInfrastructure/Cloud/SettingsSyncCoordinator.swift + - id: openwiki-source-eaa9d39ab551840299164d96 + resource: repo://Frameworks/TermindInfrastructure/Cloud/VaultSyncCoordinator.swift + - id: openwiki-source-63e25c47c9c7d38b354f4123 + resource: repo://Frameworks/TermindPersistence/SwiftDataHostRepository.swift - id: openwiki-source-cd0be716a2446029f345525a resource: repo://Termind.xcodeproj/project.pbxproj - id: openwiki-source-dc9295278cc250ed20567540 @@ -18,10 +33,20 @@ sources: resource: repo://TFI/App/TermindIOSApp.swift - id: openwiki-source-9c78befae6b387426c603305 resource: repo://TFI/Application/Workspaces/MobileWorkspaceDescriptor.swift + - id: openwiki-source-492f738896225c6b3acf7d2f + resource: repo://TFI/Features/Workspaces/MobileWorkspace.swift + - id: openwiki-source-34542e0f07e1650e098824c7 + resource: repo://TFI/Platform/MobileBackgroundController.swift + - id: openwiki-source-d34ac3e852773901d0566033 + resource: repo://TFI/Platform/MobileHomeScreenQuickActions.swift - id: openwiki-source-b822b041afbf829d09a8555a resource: repo://TFITests/MobileAppTests.swift + - id: openwiki-source-c9618f94f83d3b529a9860e1 + resource: repo://TFITests/MobileBackgroundControllerTests.swift - id: openwiki-source-2c8d92432bb6dac7ede21141 resource: repo://TFITests/MobileForwardingLifecycleTests.swift + - id: openwiki-source-68ab6aaabd7a3499cfe23434 + resource: repo://TFITests/MobileHomeScreenQuickActionTests.swift - id: openwiki-source-4dbea0ff2808163cb4ecdd8f resource: repo://TFM/App/AppModel.swift - id: openwiki-source-873894299539cce9a737a860 @@ -36,14 +61,15 @@ sources: resource: repo://TFM/Platform/MacDeviceName.swift - id: openwiki-source-22e92f96394f292a731fc6fb resource: repo://TFM/Platform/MainWindowCoordinator.swift + - id: openwiki-source-73c75477db0674192248aa00 + resource: repo://TFMTests/AppTerminationTests.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift - id: openwiki-source-531f6567ecf96fd4b0c5e97a resource: repo://TFMTests/ExternalConnectionURLTests.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-32c251eb2f83ec0be2f1a0e8 + resource: repo://TFMTests/RepositoryOutboxTests.swift +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Platform Runtime, App Composition, and Lifetimes @@ -103,7 +129,7 @@ This diagram shows the desktop composition root and the split between one app ru `AppModel` is the cross-window coordinator and service owner. It owns the host and credential projections, known-hosts/snippet/forwarding/transfer libraries, terminal and SSH/SFTP settings, histories, AI/skills/memory, metrics, entitlement and review controllers, remote connection coordination, SFTP edit/transfer services, forwarding, MCP services, and sync/outbox integration. It also owns the global conversation store and one speech transcription coordinator, avoiding duplicate conversation state and competing audio taps across windows. -The model keeps only weak registrations for open `WindowModel`s. Registration injects shared stores and coordinators into a window and attaches that window's assistant library to the process-wide conversation store. Fan-out operations—such as a host route change or deletion—find registered windows and disconnect or close the affected window-owned workspaces. This is coordination, not ownership transfer: the window remains responsible for its own UI and workspaces. +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. @@ -119,7 +145,7 @@ A host-opening action is centralized in `AppModel`, which chooses the requested 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()`. -Shutdown is deliberately idempotent and bounded by the delegate. It suspends memory and edit monitoring, stops metrics, speech, windows, SFTP work, external authentication, forwarding, and the outbox; concurrently awaits MCP and SFTP cancellation, then closes agent background commands and connection pools. The delegate replies to macOS when cleanup completes or after a three-second fallback, preventing an unbounded quit wait. +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. ## Mobile composition @@ -151,21 +177,39 @@ This diagram shows that mobile scenes have independent navigation but select fro `MobileAppModel` creates or receives its `ModelContainer`, then builds the host repository, outbox, Keychain or in-memory secret store, settings/metrics persistence and sync coordinators, host and credential libraries, AI/skills/memory, assistant, metrics, transfers and SFTP edits, forwarding, histories, the generic device directory, and live activities. The device directory and connection history use separate repositories on the same Vault context and share the stable installation ID; each repository journals its own payload kind transactionally. Workspace publication starts an event and explicit close records its end. Production uses `Termind.store` under Application Support; tests or supplied repositories use an in-memory container and do not enable production live activities or sync coordinators. -The app model wires cross-service invalidation at construction. Host deletion and route changes invalidate edits, cancel transfers, stop/reconfigure forwarding, remove relevant metrics/history, and disconnect or close live workspaces as appropriate. Remote sync application similarly computes a change plan before replacing the local projection, so route-affecting changes retire affected runtime work rather than leaving it attached to stale configuration. +The app model wires cross-service invalidation at construction. Local `deleteHost` first disconnects the assistant, closes saved descriptors and live workspaces for that Host, invalidates edits, cancels transfers, retires forwarding and metrics, then requests repository deletion, projects the removal, and starts the outbox; failure is reported in `error`. The deletion request commits a hidden-host marker and ordered outbox jobs together, so durable reference cleanup and final removal can resume after a crash. Outbox handlers also close workspaces and clear histories, cancel transfers, and remove forwarding rules. Host route edits disconnect matching live protocols rather than deleting descriptors. Remote sync application computes a change plan before replacing the local projection: changed routes invalidate edits, sessions, transfers and forwarding, while removed Hosts additionally close saved workspaces and clear histories/metrics. This keeps runtime work from using stale configuration. ### Scene-local navigation, app-wide mobile workspaces `MobileRootView` creates `@State` `MobileSceneModel` for its scene and reports `scenePhase` to the shared app model. It uses one sidebar-adaptable `TabView`, but each tab hosts its own `NavigationStack`; adapting the tab UI does not replace the feature tree. The scene model owns destination selection, selected/pending workspace IDs, connection-picker and editor presentation, external-link confirmation, local assistant-library route, review page, and recency used to choose an already-open workspace. Focused scene values route commands to that scene. +The UIKit `MobileSceneDelegate` holds a pending Home Screen quick action per scene; `TermindIOSApp` passes its action and one-shot consumer into `MobileRootView`. The root consumes it on change and asks its own `MobileSceneModel` to open the connection picker or open a recent Host using the Host's **current** preferred connection kind. Unknown shortcuts are rejected; a missing or unusable Host presents the workspace-unavailable alert instead of trying to restore a stale session. The system's shortcut list is refreshed from local connection history and host changes, limited to three openable recent Hosts. + `MobileAppModel`, rather than a scene, owns `workspaces` and the persisted descriptor list. `openWorkspace(_:)` first returns an already-live workspace; otherwise it validates the saved descriptor's Host, constructs the workspace, publishes it, and then starts its connection. Publishing before connecting is an invariant: multiple scenes selecting the same descriptor share an instance and cannot trigger duplicate first connections. A scene only selects/presents that shared workspace. Mobile persistence deliberately restores **descriptors, not sessions**. On cold launch `loadRecentWorkspaces()` reads descriptors, removes those whose Hosts are absent, and publishes no live workspace or connection; it also clears leftover Live Activities. A descriptor contains only workspace ID, Host ID, title, and connection kind, while initial commands, paths, connection secrets, and transports stay outside it. Opening a saved descriptor connects it on demand. Closing removes both the live instance and descriptor; externally linked temporary workspaces are not persisted. ### Mobile foreground and background boundaries -Scene phases are aggregated by scene ID. The app only enters global background behavior when every tracked scene is backgrounded, so one backgrounded scene cannot suspend work still visible in another. On that transition it stops edit monitoring, suspends memory and sync, pauses metrics and outbox work, suspends recording, and starts a finite platform background task. If the task expires, it asks each live workspace to handle background expiration, stops forwarding, pauses transfers, and expires assistant work. It updates Live Activities but does not use them to retain connections. +Scene phases are aggregated by scene ID. The app only enters global background behavior when every tracked scene is backgrounded, so one backgrounded scene cannot suspend work still visible in another. Removing the last active scene can trigger that transition when other tracked scenes remain backgrounded; removing the last tracked scene does not. On that transition it stops edit monitoring, suspends memory and sync, pauses metrics and outbox work, suspends recording, and starts a finite platform background task. If the task expires, it asks each live workspace to handle background expiration, stops forwarding, pauses transfers, and expires assistant work. Expiration detaches active workspace transports, clears interactive authentication state and marks a foreground reconnect intent; returning before expiration does not force a reconnect. It updates Live Activities but does not use them to retain connections. -When any scene becomes active, mobile refreshes its current device-directory record, reenables edit monitoring, finishes the background task, asks existing workspaces to resume, reconciles sync according to foreground entitlement, restarts the outbox and metrics, refreshes entitlement asynchronously, and updates activities. Returning before expiration therefore preserves healthy connections; after expiration, workspace recovery follows the workspace's reconnection journey. Expired forwarding and pending interactive authentication are stopped rather than silently restarted on foreground. +`MobileBackgroundController` owns one UIKit background-task lease. Beginning another lease finishes the old one; foreground `finish()` and expiration retire a valid identifier at most once. Expiration calls its cancellation callback synchronously before ending the task, even when UIKit expires during `begin`; a late callback for a retired lease is ignored. If UIKit returns `.invalid`, the controller expires immediately without trying to end an invalid identifier. Async disconnects started by the callback are best effort, not a guarantee that every drain completed before the lease ends. + +When any scene becomes active, mobile refreshes its current device-directory record, reenables edit monitoring, finishes the background task, asks existing workspaces to resume, reconciles sync, restarts the outbox and metrics, refreshes entitlement asynchronously, and updates activities. `reconcileSync()` calls `start()` on Vault, Metrics and Settings coordinators only if at least one tracked scene is `.active` **and** Pro permits Vault sync; otherwise it pauses all three. This is a foreground/entitlement gate, **not** an override of user sync choices: each coordinator's `CloudSyncLifecycle.start()` separately checks the global iCloud switch and that category's enabled preference and pauses if disabled. `setSyncEnabled(_:key:)` gates enabling on Pro, writes the selected preference, migrates custom passwords when enabling global/Vault sync, then reconciles. `MobileRootView` also reconciles when Pro access changes. Desktop `AppModel` starts/reconciles those three coordinators against Pro access without a scene-phase gate, but their individual preferences still govern actual activation. Returning before expiration preserves healthy connections; after expiration, workspace recovery follows the workspace's reconnection journey. Expired forwarding and pending interactive authentication are stopped rather than silently restarted on foreground. + +```mermaid +stateDiagram-v2 + [*] --> Tracked: Scene reports phase + Tracked --> Foreground: Any tracked scene active + Foreground --> Background: All tracked scenes backgrounded + Background --> Foreground: A scene becomes active + Background --> Expired: Background lease expires + Expired --> Foreground: A scene becomes active + Foreground --> Tracked: No tracked scene active + Tracked --> Background: All tracked scenes backgrounded +``` + +Mobile phase aggregation controls a single background lease and foreground sync eligibility; expiration retires live runtime work, not persisted workspace descriptors. An empty scene registry is not treated as all-backgrounded. ## Ownership invariants and safe extension points @@ -188,9 +232,13 @@ For a service that represents navigation, focus, a sheet, an editor draft, a des Tests exercise the lifetime contracts rather than merely constructing views: -- `MobileAppTests` verifies saved descriptors reopen on demand without replaying commands or paths, and that two scenes selecting one restored workspace create only one connection. +- `MobileAppTests` verifies saved descriptors reopen on demand without replaying commands or paths, two scenes selecting one restored workspace create only one connection, and local/remote Host deletion removes both opened and unopened descriptors. - `MobileWorkspaceConnectionRecoveryTests` verifies background expiration disconnects affected mobile workspaces and foreground resumes them, while a quick foreground return preserves a healthy connection. - `MobileForwardingLifecycleTests` verifies all-scenes background is required before expiration, and expired forwarding/authentication does not revive merely on foreground. +- `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. +- `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. diff --git a/openwiki/architecture/shared-module-directories.md b/openwiki/architecture/shared-module-directories.md index daf8ca2b..db6f9963 100644 --- a/openwiki/architecture/shared-module-directories.md +++ b/openwiki/architecture/shared-module-directories.md @@ -1,9 +1,14 @@ --- type: architecture directory guide title: Shared Framework Directory Responsibilities -description: Functional directory responsibilities across Termind's six shared frameworks and shared resources, including flat-root concerns and how policy, persistence, transport, and presentation collaborate. +description: Responsibilities and boundaries of Termind's shared frameworks and bundle resources, including agent execution, durable replay, SSH charset handling, and synchronized Xcode target membership. tags: [architecture, directories, frameworks, domain, persistence, presentation, ssh] +verified: + - by: openwiki/0.5.2 + at: 2026-09-23T10:36:38.039Z sources: + - id: openwiki-source-cd70c531c7abdbbdcb0ea290 + resource: repo://AgentKit/Sources/AgentKit/Providers/ModelCapabilityResolver.swift - id: openwiki-source-8037e2358a2c4f9b2c722a11 resource: repo://AGENTS.md - id: openwiki-source-96ab247f0823a449c632fdd9 @@ -64,6 +69,8 @@ sources: resource: repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift - id: openwiki-source-fe1dc993163bb9ff61397be7 resource: repo://Frameworks/TermindPersistence/HostPersistence.swift + - id: openwiki-source-28d6772acb1a409d29ff1973 + resource: repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift - id: openwiki-source-0b6ab59ec6a684de8101ff8e resource: repo://Frameworks/TermindPersistence/SwiftDataDeviceDirectoryRepository.swift - id: openwiki-source-7a9c6d90cba4ebd1d1398673 @@ -84,10 +91,18 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/Security/KeychainSecretStore.swift - id: openwiki-source-9c5b1553c1819d34c34b714b resource: repo://Frameworks/TermindRemoteInfrastructure/Security/SecureEnclaveKey.swift + - id: openwiki-source-9dfd0d1178e2ed5b33263580 + resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift + - id: openwiki-source-dd3df578da8881d8ba0638e6 + resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift - id: openwiki-source-e980c605b1828a2d960bfd5e resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnection.swift + - id: openwiki-source-ab74624bdc6b7046d91bcbac + resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnectionWorker.swift - id: openwiki-source-d371db64770fd2fcc301086b resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHMaxSessionsPolicy.swift + - id: openwiki-source-8c4abf5c09db535e2818e3c4 + resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift - id: openwiki-source-7d9f0c3ee94cd4060d5507d8 resource: repo://Frameworks/TermindRemoteInfrastructure/SSHImport/SSHImportReader.swift - id: openwiki-source-1f7380cad037b68eb1bec322 @@ -100,19 +115,26 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferContext.swift - id: openwiki-source-c4b6e224fdbea6dcd393344d resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift + - id: openwiki-source-017f5e2abe9b13df755a5322 + resource: repo://FrameworkTests/AgentReplayPersistenceTests.swift + - id: openwiki-source-6ec3fb4cd6a582cdf278bab9 + resource: repo://FrameworkTests/AssistantExecutionControllerTests.swift + - id: openwiki-source-72f95a523c9b93bf5c81d9e5 + resource: repo://FrameworkTests/RemoteCharsetTests.swift + - id: openwiki-source-41a7ded3800c9422f058a3ef + resource: repo://Scripts/check-zh-localization.sh + - id: openwiki-source-66092b0aa632065907bc7606 + resource: repo://Scripts/update-linux-distribution-icons.sh - id: openwiki-source-cd0be716a2446029f345525a resource: repo://Termind.xcodeproj/project.pbxproj - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift -generated: { by: "codex", at: "2026-09-23T00:14:42.075Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Shared Framework Directory Responsibilities -The six module roots live under `Frameworks`. Paths in each table are **relative to the named framework root**. All current functional child directories are covered; these modules mostly stop at that level. Persistence is flat, while Presentation and Application also contain substantial root-level functionality. The “root files” rows are real responsibilities, not proposed folders. +The six module roots live under `Frameworks`. Paths in each table are **relative to the named framework root**. All current functional child directories are covered; these modules mostly stop at that level. Persistence is flat, while Presentation and Application also contain substantial root-level functionality. The “root files” rows are real responsibilities, not proposed folders. Xcode uses file-system-synchronized groups for the framework roots; the shared `Resources` group is attached to product targets, not to every framework target. A file's directory and its compiled target membership must not be conflated. See the [Module Map](module-map.md) for build dependencies and [Native App Directories](native-app-directories.md) for the app-owned halves of these features. @@ -162,6 +184,31 @@ Application depends on Domain and AgentKit abstractions. It exposes the capabili `HostLibraryModel` is broader than its name: it projects hosts, groups, identities, keys, snippets, forwarding rules, transfers, Known Hosts, and templates. Specialized feature models provide narrower operations over that shared data. Live connection status is kept separate from the saved Host values. +`AssistantExecutionController` is the shared entrypoint for sending drafts/text, editing a prior user turn, starting a run, and manual compaction. It captures model credentials, permission mode, tool registry, skill inventory, and the turn's context snapshot **before** asynchronous memory or compaction preparation; an old turn is not silently reinterpreted using later UI settings. The conversation owns its runtime; the controller tracks one preparation by conversation ID, rejects overlapping submissions, and invalidates cancelled/superseded preparations before the runtime can start. Missing model or credential becomes a persisted failed run before the visible failure state is adopted; cancellation can persist an interrupted run. The injected `AgentRunPersisting` port is the durable boundary, not a SwiftData dependency of Application. The registry factory supplies Termind's host tools to an AgentKit runtime, which combines them with eligible skill/memory tools, uses a single ordered event channel for review and tool events, and keeps approval tied to weak conversation interaction (a closed conversation denies). Compaction persists its record before rewriting the observable transcript. + +```mermaid +sequenceDiagram + participant Surface as App surface + participant Controller as Application execution controller + participant Conversation as Conversation model + participant Repository as Agent run repository + participant Runtime as AgentKit runtime + Surface->>Controller: Send or edit turn + Controller->>Conversation: Capture prompt and frozen context + Controller->>Controller: Prepare memory and optional compaction + alt missing model or credential + Controller->>Repository: Save failed snapshot + Repository-->>Controller: Save completed + Controller->>Conversation: Adopt failure + else valid run + Controller->>Runtime: Construct with registry and event channel + Controller->>Conversation: Start runtime + Runtime->>Repository: Persist snapshots and durable events + end +``` + +A captured turn becomes either a saved failure or a run; the observable failure is not committed ahead of its durable snapshot. + ## TermindPersistence — one stored-model owner This module currently has **no functional subdirectories**. Its root spans several concerns; the rows below are responsibility groups, not physical folders. @@ -170,13 +217,15 @@ This module currently has **no functional subdirectories**. Its root spans sever | --- | --- | | Schema and migration | Current SwiftData schema, frozen historical representations, migration plan, and the sole shared container factory. | | Vault and histories | Persistent Host/credential metadata and related Vault records; command and SFTP local histories; separate synchronized connection-event and generic device-directory repositories; and Vault journal integration. | -| AI, Agent, skills, and audit | Provider/configuration records, agent-run/message replay, tool-audit storage, skill packages, and persistence redaction. | +| AI, Agent, skills, and audit | Provider/configuration records, agent-run/message replay, tool-audit storage, skill packages, and persistence redaction. `SwiftDataAgentRunRepository` implements the AgentKit persistence port; its SwiftData rows are not the AgentKit loop. | | Preferences and sync journals | SSH/SFTP/terminal settings, metrics/settings/Vault local stores, mutation journals, scoped upload restrictions, recovery checkpoints, and sync-facing persistence adapters. | | Secret metadata/adapters | AI secret references and storage policy bridged to the injected Keychain service; not a plaintext secret database. | | Memory | Actor-owned GRDB/SQLite memory state, conversation snapshots, session/message indexing, and full-text search. This is distinct from SwiftData's model container. | The container factory selects the complete versioned schema and migration plan; platform roots choose its location and lifetime. It disables automatic SwiftData CloudKit storage because the explicit CloudKit coordinators use their own records and journals. No app feature or general infrastructure module may introduce a competing `@Model` owner. +The agent repository saves runs by run ID but deduplicates replayed history by **message ID**; compaction messages are not stored as ordinary transcript rows. It keeps per-message frozen context/model text and attachments alongside run, tool, review, and result rows. On reload, it sorts messages within run order, restores the compaction projection and recovers a tool result already persisted before its transcript snapshot, rather than leaving an unanswered call in model history. Initialization marks unfinished runs interrupted. Editing a user turn truncates the suffix and stages a replacement run; the real run adopts the staged message instead of inserting it twice. Deletes remove the associated message/replay/attachment/tool graph, and guards prevent late saves for deleted conversations or retired runs. Title writes redact model-influenced text. These rules belong to Persistence, while the Application controller decides *when* to run, compact, approve, or display failure. + Details: [Persistent Data, Migrations, and Secrets](../concepts/persistence-and-secrets.md). ## TermindInfrastructure — general concrete services @@ -206,6 +255,8 @@ This layer can use Persistence. It does not depend on either native app, and a C `SSH` has multiple responsibilities because it is the protocol boundary, not just a terminal client. `Transfers` builds file-operation lifecycles on top of that boundary. **A logical file permit, an SSH session-channel lease, and a physical connection are different resources.** +`RemoteCharsetStreamConverter` is the shared iconv adapter under `SSH`, not an app view or Domain policy: the selected `RemoteCharset` is a Domain value, but byte conversion happens at the protocol edge. It strictly encodes command/PTY input, environment values, and SFTP paths, so unrepresentable text fails instead of being silently changed; exec stdout/stderr, PTY output, SFTP filenames, and Telnet streams decode through the adapter. Fragmented multibyte input is buffered until complete. Malformed received bytes pass through without interrupting the byte stream (final string decoding can replace invalid UTF-8); optional recovery for invalid outgoing UTF-8 reports rejection, while normal encoding throws. `RemoteOSC7CharsetFilter` rewrites shell-integration working-directory paths into percent-encoded UTF-8 before Ghostty receives them, retaining partial frames across chunks and bounding incomplete payloads. + The following diagram shows **collaboration**, not target dependencies. A solid arrow means “requests or uses”; a dashed arrow means an injected callback/result relationship. It summarizes representative paths without claiming all features share one live transport. ```mermaid @@ -226,6 +277,8 @@ flowchart TB Parsers -.->|domain snapshots| Monitor["Application / Metrics"] ``` +The remote-operation path crosses Application policy, AgentKit execution, protocol adapters, and feature-owned interaction without making Application depend on libssh2. + Keep trust/authentication interaction with the initiating feature. Additional silent connections and queued operations have different permissions and retirement rules from a user's interactive terminal. See [SSH Lifecycle](../workflows/ssh-session-lifecycle.md), [SSH Multiplexing and Scheduling](../concepts/ssh-multiplexing-and-scheduling.md), [SFTP Workflow](../workflows/sftp-transfer-and-external-edit.md), and [Assistant Runtime](../concepts/agent-runtime-and-assistant.md). ## TermindPresentation — shared content without native ownership @@ -249,7 +302,9 @@ Details: [UI Design Principles](../concepts/ui-design-principles.md). | `Assets.xcassets/LinuxDistributions` | Distribution-specific `LinuxDistro-*.imageset` assets used by host/system presentation. | | `LinuxDistributionIcons` | Upstream icon license and disclaimer material, separate from the actual image sets. | -Shared resources are compiled into product bundles; platform-specific icons stay in the apps. Resource consumers such as distribution icons and model catalogs should not create a new dependency on an app target. App localization and AgentKit localization have separate ownership. +`Frameworks/Resources` is a file-system-synchronized Xcode group included in **TFM, TFI, TermindWidgets, and FrameworkTests**, not the six shared framework targets. The empty explicit resources phases do not enumerate its files individually. Shared data is therefore available in those product/test bundles; do not assume it is in `Bundle(for:)` of an arbitrary shared framework. `LinuxDistributionIconCatalog` loads `LinuxDistributionIcons.json` from `Bundle.main` and matches detected distribution IDs (falling back to like IDs); AgentKit's model capability resolver searches the main and package bundles for the Pi catalog and optional overrides. If the icon catalog cannot load, icon lookup returns no entry. Platform-specific icons stay in `TFM/Resources` and `TFI/Resources`. Resource consumers should not create a dependency on an app target. + +App text belongs in `Localizable.xcstrings`, bundle metadata text in `InfoPlist.xcstrings`, and AgentKit runtime text in its own localization catalog. Add finished `zh-Hans` and `zh-Hant` translations with new English strings; run `Scripts/check-zh-localization.sh` and relevant `AppLanguageTests`. For Linux icon refreshes, `Scripts/update-linux-distribution-icons.sh` takes a pinned Simple Icons version and regenerates catalog, image sets and separate license material together; the app does not fetch icons at runtime. ## Cross-layer flow: edit, persist, synchronize, render @@ -268,12 +323,14 @@ flowchart TB Model -.->|secret reference operations| Secrets["Remote / Security Keychain implementation"] ``` +The edit-and-sync path uses explicit journals and CloudKit coordinators, not automatic SwiftData mirroring; secret storage stays a separate injected path. + The editor owns interaction, the model owns the operation, Persistence owns stored representation, and the coordinator owns synchronization lifecycle. Secret bytes follow their separate storage policy; they do not become ordinary Vault/Settings record payloads. ## Verification seams - `ArchitectureBoundaryTests`: import direction, feature construction boundaries, and single SwiftData-model ownership. -- `FrameworkTests`: portable model/policy, persistence compatibility, sync, presentation, and shared-service behavior. +- `FrameworkTests`: portable model/policy, persistence compatibility, sync, presentation, and shared-service behavior. In particular `AssistantExecutionControllerTests` check frozen capture, cancellation and failure-save ordering; `AgentReplayPersistenceTests` cover staged edit adoption, replay snapshots and tool-result recovery; `RemoteCharsetTests` cover charset round trips, chunk boundaries, invalid bytes and OSC 7 rewriting. - Remote/session/transfer suites: transport, authentication, admission, cancellation, and recovery semantics. - Native test targets: screen routing, runtime lifetimes, and platform integration; those contracts are not proven by shared value tests alone. diff --git a/openwiki/architecture/supporting-system-directories.md b/openwiki/architecture/supporting-system-directories.md index 78d285d7..cc0d86a5 100644 --- a/openwiki/architecture/supporting-system-directories.md +++ b/openwiki/architecture/supporting-system-directories.md @@ -3,6 +3,9 @@ type: architecture directory guide title: Supporting Products, Packages, and Tooling description: Directory responsibilities and integration relationships for AgentKit, the MCP bridge, Live Activities, tests, benchmarks, the Astro site, marketing assets, scripts, and repository automation. tags: [architecture, directories, agentkit, mcp, widgets, testing, website, tooling] +verified: + - by: openwiki/0.5.2 + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-6d4b4e707b8d60b6ccfa3425 resource: repo://.github/workflows/openwiki-update.yml @@ -46,6 +49,8 @@ sources: resource: repo://LandingPage/src/pages/zh/index.astro - id: openwiki-source-446ef49ac8edac86b5511fe5 resource: repo://Marketing/README.md + - id: openwiki-source-d32eeff4d814c0dbd05e14b8 + resource: repo://Scripts/benchmark-port-forwarding.py - id: openwiki-source-41a7ded3800c9422f058a3ef resource: repo://Scripts/check-zh-localization.sh - id: openwiki-source-a90133154199a9c011127920 @@ -78,10 +83,7 @@ sources: resource: repo://TFMTests/ArchitectureBoundaryTests.swift - id: openwiki-source-0f8d0f9d08d6674698dd054c resource: repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift -generated: { by: "omp", at: "2026-09-22T03:45:03.442Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Supporting Products, Packages, and Tooling @@ -92,7 +94,7 @@ Not every top-level directory is an app module. This guide distinguishes separat The repository includes an `AgentKit` Git submodule as a reference checkout. **The Xcode project still declares a remote, versioned Swift package**, with its actual revision recorded in the resolved dependency graph. Neither this checkout nor the sibling development repository automatically overrides that dependency. -The directory table describes the checked-out package's organization, not a guarantee that a future checkout and the app's resolved package revision are identical. +The directory table describes the checked-out package's organization, not a guarantee that a future checkout and the app's resolved package revision are identical. For a cross-repository change, test and release AgentKit first, then update the Xcode package minimum version and re-resolve `Package.resolved` in the app-side commit. `ArchitectureBoundaryTests` also guards against redefining AgentKit-owned runtime types in app source. | Directory, relative to AgentKit | Responsibility | | --- | --- | @@ -142,7 +144,9 @@ flowchart TB Services -.->|when interaction is required| Auth["TFM / Features / ExternalRequests"] ``` -The server's lifetime/controller is assembled by the desktop app. Upload/download application policy, transfer tickets, bearer-token handling, and native authentication presentation stay on their respective sides of this boundary. Details: [MCP Server and Bridge](../integrations/mcp-server-and-bridge.md). +The diagram shows stdio-to-desktop requests and the separate interactive authorization boundary. + +The server's lifetime/controller is assembled by the desktop app. The bridge takes `TERMIND_MCP_URL` (default `http://127.0.0.1:7391/mcp`) and `TERMIND_MCP_TOKEN`, overrideable by `--url` and `--token`; it refuses a missing token or invalid URL. It skips malformed stdin objects, returns JSON-RPC errors to callers with request IDs on HTTP/transport failures, and sends a best-effort DELETE for its session at EOF. Upload/download application policy, transfer tickets, bearer-token handling, and native authentication presentation stay on their respective sides of this boundary. Details: [MCP Server and Bridge](../integrations/mcp-server-and-bridge.md). ## Live Activity product and shared source @@ -163,7 +167,9 @@ flowchart TB Scene -->|select retained workspace| Workspaces ``` -Here solid arrows are updates/navigation and dashed arrows are shared type contracts. The payload has bounded session summaries and excludes credentials and terminal output. The extension displays state; it does not keep an SSH connection alive. +The diagram shows how shared ActivityKit content connects app-owned updates, widget rendering, and workspace navigation. + +Here solid arrows are updates/navigation and dashed arrows are shared type contracts. The payload has bounded session summaries and excludes credentials and terminal output. The extension displays state; it does not keep an SSH connection alive. The app controller restores one active or stale activity and ends duplicates, serializes start/update/end, ends when no workspaces remain, and only starts a missing activity after an explicit open intent and permission to start; ordinary updates cannot resurrect one dismissed by the user. ## Tests, fixtures, benchmarks, and scripts @@ -178,6 +184,8 @@ Here solid arrows are updates/navigation and dashed arrows are shared type contr | `Scripts/Tests` | Python regression tests for version bumping and forwarding-benchmark tooling. | | `StoreKit` | Local StoreKit product/test configuration; not the production entitlement implementation. | +The standalone benchmark reads fixture metadata, enforces the host's 1–64 connection limit, and exits with diagnostics on invalid inputs or workload failures. `Scripts/benchmark-port-forwarding.py` builds its own Release scheme with resolved package versions and collects `FORWARDING_METRIC` output; `ArchitectureBoundaryTests` protects it from becoming an app dependency or a test-host workload. + The script root has multiple independent workflows: - **Release and resource maintenance:** version bumping, Chinese-localization validation, Linux-distribution icon refresh, and model-catalog refresh. @@ -229,6 +237,8 @@ flowchart TB Brand["Design / Brand"] -.->|visual source and guidance| Store ``` +The diagram distinguishes source captures, derived web frames, and separate final App Store compositions. + The App Store branch represents a separate artwork workflow, not a claim that the frame generator automatically emits final store compositions. Asset conventions and capture verification live in [Marketing Assets and App Icons](../operations/marketing-assets-and-app-icons.md). ## Project metadata and documentation tooling diff --git a/openwiki/architecture/system-boundaries.md b/openwiki/architecture/system-boundaries.md index 9261a614..4119929e 100644 --- a/openwiki/architecture/system-boundaries.md +++ b/openwiki/architecture/system-boundaries.md @@ -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-23T10:36:38.039Z sources: - id: openwiki-source-8037e2358a2c4f9b2c722a11 resource: repo://AGENTS.md @@ -40,10 +43,7 @@ sources: resource: repo://TFM/Platform/MacDeviceName.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift -generated: { by: "codex", at: "2026-09-23T00:14:42.075Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # System Boundaries and Dependency Ownership @@ -52,32 +52,23 @@ Termind is built as two native applications around shared static frameworks. The ```mermaid flowchart TD - Domain["TermindDomain values and rules"] --> Application["TermindApplication ports and use cases"] - Domain --> Infrastructure["TermindInfrastructure local and cloud implementations"] - Application --> Infrastructure - Domain --> Remote["TermindRemoteInfrastructure SSH SFTP Telnet"] - Application --> Remote - Infrastructure --> Remote - Persistence["TermindPersistence SwiftData schemas and stores"] --> Infrastructure - Domain --> Presentation["TermindPresentation reusable SwiftUI policy"] - Application --> Presentation - Domain --> TFM["TFM macOS app composition and UI"] - Application --> TFM - Infrastructure --> TFM - Remote --> TFM - Persistence --> TFM - Presentation --> TFM - Domain --> TFI["TFI iOS app composition and UI"] - Application --> TFI - Infrastructure --> TFI - Remote --> TFI - Persistence --> TFI - Presentation --> TFI - AgentKit["AgentKit pinned remote package"] --> Application - AgentKit --> Remote + TFM["TFM macOS app composition and UI"] --> Shared["Six shared frameworks"] + TFI["TFI iOS app composition and UI"] --> Shared + Presentation["TermindPresentation reusable SwiftUI policy"] --> Application["TermindApplication ports and use cases"] + Presentation --> Domain["TermindDomain values and rules"] + Remote["TermindRemoteInfrastructure SSH SFTP Telnet"] --> Infrastructure["TermindInfrastructure general implementations"] + Remote --> Application + Remote --> Domain + Infrastructure --> Persistence["TermindPersistence SwiftData schemas and stores"] + Infrastructure --> Application + Infrastructure --> Domain + Persistence --> Application + Persistence --> Domain + Application --> Domain + Package["Resolved AgentKit package"] -.-> Shared ``` -This diagram shows the permitted ownership direction at a high level; apps assemble shared layers and are never dependencies of them. +Solid arrows point from consumer to dependency (the six-framework subgraph reflects explicit Xcode target dependencies); the dotted package arrow groups external consumers rather than implying every framework links AgentKit. Both apps depend on all six frameworks; no framework depends on an app. For a directory-oriented view, start with the [Module and Directory Architecture Map](module-map.md). Its companion guides describe the shared frameworks, native apps, and supporting systems through their second-level functional directories; the build graph there uses explicit consumer-to-dependency arrows. @@ -89,7 +80,7 @@ For a directory-oriented view, start with the [Module and Directory Architecture | `TermindApplication` | Use cases, feature models, repository and service ports, connection/import policy, and cross-feature policy. | SwiftUI/AppKit/UIKit, SwiftData/GRDB, concrete Keychain/network/SSH implementations, and concrete infrastructure construction. | | `TermindInfrastructure` | General implementations such as in-memory repositories, CloudKit-backed sync, metrics parsers, logging, StoreKit, and settings/Vault services. | Native app targets and platform UI. It may depend on Application, Domain, and Persistence. | | `TermindRemoteInfrastructure` | SSH, SFTP, Telnet, Keychain-backed remote credentials, host-key/authentication mechanics, transfers, forwarding, and the Termind-specific agent tools. | App targets and their UI; a feature should use its injected services rather than construct remote transports itself. | -| `TermindPersistence` | Every SwiftData `@Model`, versioned schema, migration plan, SwiftData repository/store, and `ModelContainer` factory. | Application-infrastructure implementation dependencies, remote infrastructure, and app targets. | +| `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. | | `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. | @@ -97,7 +88,7 @@ For a directory-oriented view, start with the [Module and Directory Architecture ### Dependency rules that are enforced -`ArchitectureBoundaryTests` scans production source imports rather than relying on conventions alone. It prevents Domain from importing platform/UI, storage, security, networking, commerce, SSH, or terminal frameworks. It prevents Application and app feature code from importing UI/storage/transport implementation frameworks or constructing known concrete persistence, SSH/SFTP, and URL-session symbols. Presentation is separately prohibited from depending on platform UI, persistence, or remote infrastructure. +`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. 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. @@ -107,9 +98,9 @@ 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 everywhere else and requires Persistence to contain Swift files. A new persisted SwiftData entity therefore requires a Persistence schema/migration decision—not a model embedded in a feature, app, or general infrastructure module. +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. -Both app roots call `TermindPersistence.makeContainer`. Desktop turns an unavailable local database into a startup `fatalError`, avoiding silent replacement with an empty store. iOS builds a `MobileAppModel` during startup and displays an unavailable-data screen when composition fails. See [Platform Runtime, App Composition, and Lifetimes](platform-runtime.md) for the app/window/scene lifetime split and platform-specific failure handling. +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 @@ -119,7 +110,7 @@ Do not use this as permission to move live state into the app-wide layer. Durabl ## AgentKit is an external, host-neutral boundary -`AgentKit` is a separately developed remote Swift Package dependency at `https://github.com/AkinoKaede/AgentKit.git`. The project declares a minimum version and `Package.resolved` pins the build to an exact release revision. Xcode builds that resolved remote package, **not** a sibling `../AgentKit` working tree; an uncommitted sibling change cannot affect Termind. +`AgentKit` is a separately developed remote Swift Package dependency at `https://github.com/AkinoKaede/AgentKit.git`. The project declares `upToNextMajorVersion` from `0.14.0`, and `Package.resolved` currently pins version `0.14.0` at revision `ffc4aa41c8854142aa47c35231e57f56f961ba9f`. Xcode builds that resolved remote package, **not** a sibling `../AgentKit` working tree; an uncommitted sibling change cannot affect Termind. AgentKit owns the host-neutral agent runtime: its loop, approval gate, provider adapters, MCP client, built-in tools, and their core types. Do not redefine AgentKit-owned runtime types in Termind, and do not edit AgentKit to add the Termind name, SSH, SFTP, app UI, or other host-specific behavior. A cross-repository change must be released and tested in AgentKit first, then consumed by bumping the project dependency and resolving `Package.resolved` in the same Termind change. diff --git a/openwiki/concepts/agent-runtime-and-assistant.md b/openwiki/concepts/agent-runtime-and-assistant.md index 3ad04952..c077eed9 100644 --- a/openwiki/concepts/agent-runtime-and-assistant.md +++ b/openwiki/concepts/agent-runtime-and-assistant.md @@ -3,6 +3,9 @@ type: agent runtime concept title: Assistant, Agent Runtime, Skills, and Memory description: How Termind assembles AgentKit into durable assistant conversations, applies approval and host-security boundaries, and manages skills, scratch workspaces, and device-local Hermes memory. tags: [assistant, agent-runtime, approval, persistence, skills, memory, ssh, sftp] +verified: + - by: openwiki/0.5.2 + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-0e8cfe7d74554d8a17af60b7 resource: repo://AgentKit/Sources/AgentKit/Runtime/AgentRuntime.swift @@ -26,6 +29,8 @@ sources: resource: repo://Frameworks/TermindPersistence/GRDBMemoryStore.swift - id: openwiki-source-28d6772acb1a409d29ff1973 resource: repo://Frameworks/TermindPersistence/SwiftDataAgentRunRepository.swift + - id: openwiki-source-5b42af91dbdc738123786a99 + resource: repo://Frameworks/TermindPresentation/AgentToolPresentation.swift - id: openwiki-source-1fc00d0407016efa5a0378eb resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSSHTools.swift - id: openwiki-source-0c82bf45bc197f879a54fd3a @@ -40,10 +45,18 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/TermindAgentTools.swift - id: openwiki-source-6d759b4cb61f68a067dae42c resource: repo://FrameworkTests/AgentSteeringTests.swift + - id: openwiki-source-32bb2b0bf7a39f2a4856d7bf + resource: repo://FrameworkTests/AgentUserInputTests.swift - id: openwiki-source-247755d873c5d94b0a364217 resource: repo://FrameworkTests/AssistantConversationOperationsTests.swift - id: openwiki-source-6ec3fb4cd6a582cdf278bab9 resource: repo://FrameworkTests/AssistantExecutionControllerTests.swift + - id: openwiki-source-aec5af6c3be13b44140585c2 + resource: repo://FrameworkTests/AssistantTranscriptPresentationTests.swift + - id: openwiki-source-256e2b134a8446ea63b15585 + resource: repo://FrameworkTests/HermesMemoryTests.swift + - id: openwiki-source-cd0be716a2446029f345525a + resource: repo://Termind.xcodeproj/project.pbxproj - id: openwiki-source-a62bfbbc7de13a894444718b resource: repo://TermindMCPBridge/main.swift - id: openwiki-source-906678adb91c2fce2d3fcaed @@ -78,23 +91,20 @@ sources: resource: repo://TFMTests/ChatComposerStateTests.swift - id: openwiki-source-8d265a8732f0af93c5d4e274 resource: repo://TFMTests/MCPServerToolsTests.swift -generated: { by: "codex", at: "2026-09-23T03:40:50.823Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Assistant, Agent Runtime, Skills, and Memory Termind's Assistant is a durable conversation product built around a host-neutral agent loop. **AgentKit** owns the model-provider adapters, run loop, context pipeline, approval gate, MCP client, generic built-in tools, secret broker, and generic scratch/skill/memory tool interfaces. **Termind** owns the host-specific integration: SSH and SFTP tools and transport pools, Vault-backed host resolution, application policy and prompts, SwiftData conversation persistence, Hermes memory lifecycle, and the UI that renders events and collects approvals or SSH challenges. -This split is a security boundary as well as a modularity boundary. A model proposes tool calls; it does not gain direct access to a PTY, Keychain material, stored credentials, another conversation's workspace, or the persistence store. +This split is a security boundary as well as a modularity boundary. A model proposes tool calls; it does not gain direct access to a PTY, Keychain material, stored credentials, another conversation's workspace, or the persistence store. The sibling `AgentKit/` checkout is useful for reading runtime contracts, but the Xcode project resolves AgentKit as a remote Swift package (`AkinoKaede/AgentKit`, minimum 0.14.0), not from that sibling directory. ## Responsibilities and assembly `AssistantExecutionController` is the application entry point for a submitted turn. Before recording a new turn it rejects overlapping starts, archived/history-changing conversations, active compaction, unfinished attachments, and unauthorized use. Accepted submission synchronously captures the composed prompt, images and context attachments; session, plan and surface context; chat model/provider/credential; reasoning and permission mode; search choice; skills and base registry; Guardian configuration; and memory/compaction preparation settings. Only then can asynchronous compaction or memory loading begin. Runtime assembly consumes this capture instead of re-reading mutable composer or configuration state after an await. A missing model or credential remains a captured failure even if Settings changes during preparation. -A runtime is deliberately single-run. It owns one event stream and one event consumer. `ConversationModel` owns the live runtime and projects its events into visible messages, tool cards, approval and input queues, run summaries, and the authoritative model transcript. The visible message list is not replay history: tool calls and results are separately rendered as cards, so replay must use `transcript`. +A runtime is deliberately single-run. It owns one event stream and one event consumer. `ConversationModel` owns the live runtime and projects its events into visible messages, tool cards, approval and input queues, run summaries, and the authoritative model transcript. The visible message list is not replay history: tool calls and results are separately rendered as cards, so replay must use `transcript`. A composed user turn likewise has two texts: `authoredText` is the user's draft shown in the bubble, edit form and title input, while model-facing `text` also includes captured attachment blocks and an armed skill directive. Images and context attachments travel as structured payloads; `pendingPriorMessages` omits the final user turn because the run request appends that prompt itself. The tool catalog and plan posture are captured at submission; AgentKit selects that captured catalog's executable mode-specific subset when the runtime starts. A tool-capable model receives the captured skill catalog, AgentKit built-ins, and Termind tools; a model without tool-call capability does not receive the skill/tool catalog. `AgentTurnContextSnapshot` is the persistable context portion of the capture: session facts, skill catalog text, plan posture, surface availability, and memory-session identity. It is not a durable copy of provider credentials or all runtime configuration. Surface availability follows the latest delivered user snapshot rather than mutable UI focus. @@ -184,9 +194,9 @@ While a run is live, a further user message is queued as steering rather than st Steering captures the sending session context and updates only the `terminal_suggest` availability entry. It preserves other tool overrides, the fixed skill catalog and plan contract, and the memory-session identity. Queuing does not change `ConversationModel.activeContextSnapshot`; delivery does. If the conversation has no legacy snapshot, steering keeps that context unknown instead of filling it from current UI state. The persisted availability key remains `terminal_suggest`. -For an already-started runtime, stopping requests cancellation of runtime/tool work, discards run-scoped secrets, marks running cards interrupted in the presentation, and returns undelivered steering text. `stopAndWait()` joins preparation cancellation first, then requests runtime cancellation and waits for the event consumer before clearing live ownership. +For an already-started runtime, stopping requests cancellation of runtime/tool work, discards run-scoped secrets, marks running cards interrupted in the presentation, and returns undelivered steering text. `stopAndWait()` requests preparation and active-run cancellation before awaiting preparation and the tracked run consumers; it does not wait to request runtime cancellation until preparation finishes. -The preparation guarantees do not eliminate the separate runtime handoff edge case: `ConversationModel.start` schedules its event consumer, and an immediate stop before that task calls `AgentRuntime.start` can prevent runtime startup without persisting a runtime snapshot. The ordering between `stopAndWait()` and this queued start remains a distinct boundary; do not infer universal cancellation durability from preparation tests. +The queued-runtime handoff has its own cancellation persistence path. `ConversationModel.start` installs an owner before scheduling its event consumer; if stop wins while that owner is still queued, it constructs a cancelled snapshot from captured request data, starts a separate repository save and `stopAndWait()` joins the consumer that awaits it. If the consumer has entered `AgentRuntime.start`, runtime cancellation and its terminal snapshot path take over. Thus a queued stop need not create a *running* snapshot or call the provider, but a successful queued-cancellation save is durable; the presentation may show cancellation before the save finishes, and the queued save currently swallows repository errors. Do not confuse this handoff with preparation interruption, which is an earlier, separately saved state. ## Approval, secrets, and trust boundaries @@ -202,6 +212,32 @@ SSH authentication and host-key prompts are Termind interactions, not model-visi `request_user_secret` is only for command standard input, not SSH login. Its handle is scoped to run, tool, host, and stated purpose, single-use, and is removed from replay and durable history. Plaintext secrets must not enter model requests, Guardian review, events, logs, SwiftData, or Hermes memory. +### User questions and live approval presentation + +`request_user_input` and `request_user_secret` use AgentKit's interaction interface and Termind's `ConversationModel` queue, not a new agent run. The former accepts at most three validated questions; an optional `timeout_seconds` is bounded to 1–1,800 seconds and defaults to five minutes. Requests are ordered by creation time, but only the visible head starts its deadline and owns answer drafts. Navigation between its questions does not reset that deadline. A question must be answered or explicitly skipped to advance; secrets cannot be skipped and use a separate draft that is cleared on submit, cancellation or timeout. Skipped questions are absent from the interaction response; `request_user_input` reports them to the model as null answers rather than silently losing the question. Cancellation and timeout discard partial drafts instead of returning partial answers. + +Manual approvals have their own creation-ordered queue. Only its head can be answered; `requestApproval` holds the continuation and stages the card before the ordered event consumer drains `toolProposed`. A late approval notification cannot turn a denied card back into a waiting card. Stopping interrupts pending review/approval cards and resolves outstanding interactions rather than leaving a stale prompt. The live approval projection shows reviewable in-memory arguments, including the exact command, without attaching that projection to the durable card or model transcript. + +```mermaid +sequenceDiagram + participant Runtime + participant Conversation + participant Person as Assistant UI + Runtime->>Conversation: request user input + Conversation->>Conversation: enqueue by creation time + Conversation-->>Person: display head and start deadline + alt answered or explicitly skipped + Person->>Conversation: submit answers + Conversation-->>Runtime: answered response + else timeout or cancellation + Conversation->>Conversation: clear head drafts + Conversation-->>Runtime: timed out or cancelled + end + Conversation-->>Person: show next head with new deadline +``` + +This interaction sequence describes the queue's per-head deadline, not the lifetime of a model turn or an approval decision. + ## Host tools and plan mode Termind tools operate through noninteractive per-command SSH channels and exclusive SFTP leases; they never type into the user's interactive terminal. `terminal_suggest` creates a user-operated command card and never executes it. The standalone Assistant can discover and target configured hosts even without a sidebar session or open PTY; session context is only an optional default target. `list_hosts` lists enabled protocols without credentials, including Telnet-only hosts. SSH/SFTP execution requires SSH to be enabled; discovering a Telnet-only host does not provide an Agent Telnet execution capability. @@ -226,7 +262,7 @@ A saved context snapshot preserves historical session, skill-catalog text, plan Persisted text, tool arguments, titles, reasoning, and attachments go through redaction. In particular, secret handles are replaced with expired lifecycle content on restore, and sensitive header values are redacted. -Tool cards resolve their persisted presenter ID through the immutable presenter registry. Cards predating those IDs use the closed legacy tool-name list and its `builtin.` IDs. Registration and surface-availability changes preserve those identities and the persisted context key; they do not require a SwiftData schema change. +Tool cards resolve their persisted presenter ID through the immutable presenter registry, combining AgentKit built-in presenters with Termind registrations. Cards predating those IDs use the closed legacy tool-name list and its `builtin.` IDs. Registration and surface-availability changes preserve those identities and the persisted context key; they do not require a SwiftData schema change. Presentation is a separate projection: built-in JSON results can use a registered structured presenter or a generic fallback, while MCP keeps remote-defined JSON output. Tool summaries group by tool, state and knowledge action so mixed successes and failures do not read as one success. Display text previews are bounded to 8,192 characters and 120 lines, retaining the full transformed output for Copy; this does not truncate the original execution/replay result. Compaction changes the **model-facing** transcript, not the scrollable display history. Its summary record is persisted before the live conversation applies it; after recovery the model receives a synthetic compaction summary plus recent messages while the user can still read the full original conversation. @@ -238,7 +274,7 @@ Tool cleanup follows ownership before time. Known source-message and run-local c The replacement is durable before a runtime exists: its message ID also identifies an independent, completed, failure-free staging run containing that one user row and no tool graph. Its start time is placed after the latest retained run if clocks tie or move backward, including when the earlier retained run has no messages. On the first real snapshot containing that staged final user turn, `save` transactionally moves only the staged message to the real run, assigns its snapshot sequence, retains its attachments/replay backing, deletes the staging run and retires its ID. Historical messages replayed into the snapshot keep their existing owners and are not duplicated. Adoption preserves the staging start-time lower bound; subsequent snapshots cannot move it backward, and terminal time is clamped to that start when necessary. -`ConversationModel` mirrors adoption on `runStarted`, captured failure and preparation interruption; `runFinished` retains the adjusted chronology. A failed or interrupted replacement therefore has the real run's provenance rather than an abandoned staging summary. The ordering of publication still depends on the path: preparation cancellation awaits the interrupted save and rechecks identity before adopting, while `recordFailedRun` for a missing model/credential projects live first and starts a separate asynchronous save. Neither `!isPreparingAgentRun` nor a visible failed state proves that this save finished. The persist-before-live contract above is specifically the history mutation boundary. +`ConversationModel` mirrors adoption on `runStarted`, successfully saved captured failure, preparation interruption and queued prestart cancellation; `runFinished` retains the adjusted chronology. A committed failed, interrupted or prestart-cancelled replacement therefore has the real run's provenance rather than an abandoned staging summary. Preparation cancellation awaits the interrupted save and rechecks identity before adopting. Missing-model/credential failure instead holds preparation in a `savingFailure` phase: it saves before calling `recordFailedRun` and retires preparation only after success or error. A failed save leaves the staging owner intact and shows an error rather than claiming a durable failed run. The queued prestart path projects cancellation before its save completes; use `stopAndWait()` to join it. The persist-before-live contract above specifically concerns the history mutation boundary, not every transient presentation update. The repository instance retires the edited target run, removed later runs and adopted staging run so late snapshots or durable tool events cannot resurrect the discarded suffix. Truncation and snapshot save roll back SwiftData changes and restore the previous in-memory retired-ID set on error. These rules use the existing schema and Termind's Application/Persistence adapters, without changing AgentKit or its package pin. See [Persistent Data](persistence-and-secrets.md) for the storage contract. @@ -254,9 +290,11 @@ stateDiagram-v2 Interrupted --> Ready: history and cards restored Completed --> Ready: history and cards restored Ready --> Preparing: accepted capture - Preparing --> Running: current capture handed to runtime - Preparing --> Interrupted: cancellation saved - Preparing --> Failed: captured configuration unavailable + Preparing --> Queued: current capture handed to conversation + Preparing --> Interrupted: cancellation save succeeds + Preparing --> Failed: captured failure save succeeds + Queued --> Cancelled: prestart cancellation save succeeds + Queued --> Running: runtime starts Running --> WaitingApproval: Ask action pending WaitingApproval --> Running: allow WaitingApproval --> Running: denial result recorded @@ -268,7 +306,7 @@ stateDiagram-v2 Completed --> Ready: next submitted turn ``` -This state diagram distinguishes recovery from automatic resumption: interrupted work is visible and recoverable as history, never silently rerun. +This state diagram separates preparation, queued handoff and runtime terminal paths; terminal arrows describe successful persistence, not a guarantee that a failing repository committed the state. Restored interrupted history is never silently rerun. Conversation metadata mutations are persistence-first. Archive clears pinning and prevents editing; after cancelling pending preparation, archive/delete remain guarded while streaming or compaction is active. Reordering commits the whole ordering update before changing the in-memory library. These rules avoid UI state claiming a history mutation that failed to save. @@ -284,9 +322,9 @@ A skill is procedure-bearing only when read through `skill_read_file` from its ` Hermes memory is optional and disabled by default. AgentKit supplies the memory tools, screening/learning model, revocable session snapshots, and access interface. Termind supplies Settings and lifecycle management, while `GRDBMemoryStore` alone owns the memory database at `Termind/HermesMemory`; SwiftData remains the source of truth for conversations. -The GRDB store opens lazily, so disabled memory does not create or open its database. It keeps memory state, frozen per-conversation prompt snapshots, review checkpoints, a redacted conversation/message index, and an FTS5 search index. Conversation history is copied into this separate index only after successful relevant history changes; indexed text is redacted and compaction-only synthetic messages are excluded. +The GRDB store opens lazily, so disabled memory does not create or open its database. `MemoryModel.session` also checks enabled and suspension state before a load, and checks the generation again after an awaited snapshot; a frozen session ID is eligibility, not a guarantee that memory remains available. It keeps memory state, frozen per-conversation prompt snapshots, review checkpoints, a redacted conversation/message index, and an FTS5 search index. Conversation history is copied into this separate index only after successful relevant history changes; indexed text is redacted and compaction-only synthetic messages are excluded. -A memory session receives a frozen snapshot for its conversation. Memory reviews use a compare-and-apply base state, so a stale review cannot overwrite newer memory. Disabling memory invalidates sessions, cancels indexing and reviews, and closes the database while preserving stored data. Destroying memory first persists disabled/destroy-pending state, revokes contexts and joins ongoing work, then closes and removes the owned directory; failure remains disabled and is retried on a later launch. Memory and credentials are device-local and are not synced. +A memory session receives a frozen snapshot for its conversation. Memory reviews use a compare-and-apply base state, so a stale review cannot overwrite newer memory. Disabling memory invalidates sessions, cancels indexing and reviews, and closes the database while preserving stored data. Mobile backgrounding and desktop termination also suspend memory, revoking existing contexts and access without deleting data; on mobile, background expiration separately requests cancellation of Assistant preparation and active runs before draining and closing host connections. Resuming memory reloads current state and schedules history reindexing. Generation checks reject stale access/results and prevent publishing stale writes into the current UI state; they are not a rollback of storage writes already in flight. Resume can reload current state after such a commit. Destroying memory first persists disabled/destroy-pending state, revokes contexts and joins ongoing work, then closes and removes the owned directory; failure remains disabled and is retried on a later launch. Memory and credentials are device-local and are not synced. New submissions capture whether they have a memory-session identity before preparation awaits. Enabling memory afterward does not add a session to that captured turn. Disabling it remains a revocation boundary: `MemoryModel` invalidates existing contexts and rejects a late snapshot load from the old generation, so capture does not override a later disable. @@ -297,11 +335,12 @@ The focused tests establish behavior that is important when changing this area: - `TFMTests/AgentRuntimeTests.swift` covers schema-before-approval/execution, approval mode routing, Guardian timeout/failure fail-closed behavior, single-use secret handles, steering delivery, tool cancellation, registry shadowing, and durable-event filtering. - `TFMTests/AgentPersistenceTests.swift` covers redaction, interrupted-run recovery, replay deduplication, tool-result repair, graph deletion, same-run edit prefix/tool preservation, canonical equal-time ordering, empty retained runs, staging adoption, late-write rejection, fork persistence and compaction restoration. `ChatComposerStateTests.swift` checks the compacted live prefix, tool cards, title, plans and adopted run summaries. - `FrameworkTests/AgentReplayPersistenceTests.swift` checks failed/interrupted staging adoption and reloads through a fresh `ModelContext` and repository to verify durable provenance and replay backing. -- `FrameworkTests/AssistantExecutionControllerTests.swift` covers capture across a memory barrier, missing credentials, first-send guards and payload folding, plan implementation, edit persistence/cancellation barriers, failed/interrupted replacement provenance, superseded captures, navigation, compaction refusal, memory revocation, and neutral legacy context. Repository snapshot waiters distinguish async save completion from a live failed state. -- `FrameworkTests/AssistantConversationOperationsTests.swift` verifies persistence-first archive/rename/order/edit mutations, invalid edit rejection before repository calls, failed edits leaving the live prefix unchanged, activity guards, and that immediate stop prevents a queued runtime's model call. That last test does not establish snapshot persistence for the runtime handoff gap. +- `FrameworkTests/AssistantExecutionControllerTests.swift` covers capture across a memory barrier, missing credentials, first-send guards and payload folding, plan implementation, edit persistence/cancellation barriers, failed/interrupted replacement provenance, superseded captures, navigation, compaction refusal, memory revocation, and neutral legacy context. Blocked and failing saves verify that captured failure keeps preparation owned until save completion and only adopts staging on success. +- `FrameworkTests/AssistantConversationOperationsTests.swift` verifies persistence-first archive/rename/order/edit mutations, invalid edit rejection before repository calls, failed edits leaving the live prefix unchanged, and activity guards. Immediate `stopAndWait()` also verifies a persisted cancelled prestart snapshot with captured prompt and context but no provider/tool calls; a gated-save test verifies the join. - `TFMTests/AgentScratchTests.swift` verifies workspace containment, symlink refusal, inter-conversation isolation, quotas, and bounded reads. - `TFMTests/AgentBuiltInToolAvailabilityTests.swift` checks exact Termind planning/acting/reviewing sets, the shared SSH schema with mode-specific preflight, and execution spies proving the surface gate blocks only terminal suggestions. - `FrameworkTests/AgentSteeringTests.swift` and `TFITests/MobileAssistantTests.swift` check snapshot preservation, delivery timing, legacy unknown context, mobile send/steer availability, acting-mode plan implementation, and tool-incapable models. Mobile's SwiftData restore/edit fixture also verifies same-run prefix preservation and replacement provenance. +- `FrameworkTests/AgentUserInputTests.swift` checks timeout schema and defaults, question validation, navigation, head-only deadlines, skip/null semantics, cancellation and dedicated secret drafts. `FrameworkTests/AssistantTranscriptPresentationTests.swift` checks direct-approval/event races, denial display, structured presenter output and bounded previews; `FrameworkTests/HermesMemoryTests.swift` checks suspension/revocation, stale writes/reviews, index catch-up, destroy retry and lazy disabled storage. - `TFMTests/MCPServerToolsTests.swift` checks the exported acting subset against shared descriptors, transfer tools and disabled calls; `AgentHostProtocolListingTests.swift` checks protocol-neutral discovery, and `AgentToolPresentationTests.swift` retains legacy presentation coverage alongside the persistence suite. ## Change guidance diff --git a/openwiki/concepts/commerce-localization-and-product-surfaces.md b/openwiki/concepts/commerce-localization-and-product-surfaces.md index f408dc16..f64f2bea 100644 --- a/openwiki/concepts/commerce-localization-and-product-surfaces.md +++ b/openwiki/concepts/commerce-localization-and-product-surfaces.md @@ -5,16 +5,20 @@ description: Explains StoreKit-derived Pro access, native paywall and review own tags: [commerce, storekit, localization, product-surfaces, marketing, widgets] verified: - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-8037e2358a2c4f9b2c722a11 resource: repo://AGENTS.md + - id: openwiki-source-a8a9aade8fbc89d5829a491e + resource: repo://Frameworks/Resources/Localizable.xcstrings - id: openwiki-source-b2f57db7a90dcc30dd3886da resource: repo://Frameworks/TermindApplication/FeatureModels/AppReviewController.swift - id: openwiki-source-b37c974aaea12bd08606d67d resource: repo://Frameworks/TermindDomain/Commerce/ProAccessTypes.swift - id: openwiki-source-3aa42bdd0f8eaf866f06599f resource: repo://Frameworks/TermindInfrastructure/Commerce/ProAccessController.swift + - id: openwiki-source-a298d9034d557f1b420cb306 + resource: repo://Frameworks/TermindPresentation/ProOfferPresentation.swift - id: openwiki-source-eae5d91412d0e2847dacd5b6 resource: repo://FrameworkTests/AppReviewControllerTests.swift - id: openwiki-source-103853faf6b28763354a1c79 @@ -31,31 +35,51 @@ sources: resource: repo://StoreKit/Termind.storekit - id: openwiki-source-906678adb91c2fce2d3fcaed resource: repo://TFI/App/MobileAppModel.swift + - id: openwiki-source-c8d832474c03f5ebad7b0578 + resource: repo://TFI/App/MobileRootView.swift - id: openwiki-source-e43a0da5ab77c2fc3554244d resource: repo://TFI/App/MobileSceneModel.swift - id: openwiki-source-0ffab0ae6452f870ce4a0efe resource: repo://TFI/Features/Commerce/MobileProView.swift + - id: openwiki-source-ad662f2a7016a994d8522bf2 + resource: repo://TFI/Features/KnownHosts/MobileKnownHostsView.swift - id: openwiki-source-4bb1006b8fba7cd74268940b resource: repo://TFI/Features/Settings/MobileMCPSettings.swift + - id: openwiki-source-db402cad9d68dd8e66bdd7ee + resource: repo://TFI/Features/Snippets/MobileSnippetsView.swift + - id: openwiki-source-3f37062f55fb57a9f2e97f35 + resource: repo://TFI/Features/Vault/MobileVaultView.swift - id: openwiki-source-4c2de67bfdb2238d765a642a resource: repo://TFI/Features/Workspaces/MobileWorkspaceView.swift - id: openwiki-source-637644793f7e37cc057eb973 resource: repo://TFI/Platform/MobileLiveActivityController.swift + - id: openwiki-source-7a29627adf93e3da4a56dd5d + resource: repo://TFITests/MobileCardRenderingTests.swift + - id: openwiki-source-c32ed562101f11a0c3c89663 + resource: repo://TFITests/MobileCardTests.swift - id: openwiki-source-d1ffd558b3360478aa85b5af resource: repo://TFIWidgets/WorkspaceLiveActivity.swift - id: openwiki-source-4dbea0ff2808163cb4ecdd8f resource: repo://TFM/App/AppModel.swift + - id: openwiki-source-873894299539cce9a737a860 + resource: repo://TFM/App/RootView.swift - id: openwiki-source-2b65afedbf9d80b1d387f50a resource: repo://TFM/App/ScreenshotDemo.swift + - id: openwiki-source-6570374eaac2e0278fa84640 + resource: repo://TFM/App/TermindApp.swift - id: openwiki-source-766dc23f16ac26a41a5b5c22 resource: repo://TFM/Features/Commerce/ProPaywallView.swift + - id: openwiki-source-bf08592e56aa88a7189a7fb5 + resource: repo://TFM/Features/KnownHosts/KnownHostsPageView.swift + - id: openwiki-source-793d7861000adc19f0c3df01 + resource: repo://TFMTests/AppLanguageTests.swift - id: openwiki-source-0da64bbb5811b467bbf89b7f resource: repo://TFMTests/ProAccessTests.swift - id: openwiki-source-0dd012e3740bcc348fc36ccb resource: repo://TFMTests/StoreKitTrialTests.swift - id: openwiki-source-0f8d0f9d08d6674698dd054c resource: repo://WorkspaceActivitySupport/WorkspaceActivityAttributes.swift -generated: { by: "openwiki/0.5.2", at: "2026-09-22T00:31:10.149Z" } +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- ## Scope and ownership @@ -84,17 +108,17 @@ flowchart TD This shows the entitlement resolution path used by `ProAccessController`; product metadata loading is separate from access resolution. -Access is based only on verified StoreKit transactions. A valid, non-revoked lifetime entitlement takes precedence over annual status. An annual transaction grants Pro during an introductory trial, active subscription, or verified grace period; billing retry, expiry, revocation, and verification failure do not. Cancellation does not itself remove access before expiry. The controller consumes `Transaction.updates`, including deferred Ask to Buy approval, finishes verified transactions after refresh, and schedules another refresh at a currently access-granting entitlement's expiration. It refreshes independently from product metadata, so a metadata/network failure clears offers and reports a recoverable catalog error without taking away already verified access. +Access is based only on verified StoreKit transactions. A valid, non-revoked lifetime entitlement takes precedence over annual status. An annual transaction grants Pro during an introductory trial, active subscription, or verified grace period; billing retry, expiry, revocation, and verification failure do not. Cancellation does not itself remove access before expiry. The controller consumes `Transaction.updates`, including deferred Ask to Buy approval, finishes verified transactions after refresh, and schedules another entitlement check for an access-granting subscription at the earlier of expiration or 60 seconds later. Both app targets also refresh on activation, rather than waiting for a paywall visit. It refreshes independently from product metadata, so a metadata/network failure clears offers and reports a recoverable catalog error without taking away already verified access. The controller serializes duplicate operations: it prevents a second purchase while processing or pending, tracks the specific pending product, treats user cancellation as non-error, and uses `AppStore.sync()` followed by a refresh for Restore Purchase. A successful verified purchase or restore closes the paywall; a restore without qualifying entitlement reports that no active purchase was found. ### What remains free -The gate set is intentionally narrower than the product’s general remote-workspace experience. Free users can still use the ordinary workspace, SSH/SFTP work, Vault, settings, and the first three Metrics cards. The enforced boundaries are: assistant execution; dropping files onto an SSH terminal; creating/editing/connecting remote MCP servers; enabling or resuming the built-in macOS MCP server; iCloud Vault, Metrics, and Settings synchronization; and Metrics cards beyond three. When Pro sync is unavailable, sync services pause rather than attempting background synchronization; when built-in MCP access is lost, an enabled server is suspended. Local Vault and workspace data are not erased by that transition. +The gate set is intentionally narrower than the product’s general remote-workspace experience. Free users can still use the ordinary workspace, SSH/SFTP work, Vault, settings, and the first three Metrics cards. The enforced boundaries are: assistant execution; dropping files onto an SSH terminal; creating/editing/connecting remote MCP servers; enabling or resuming the built-in macOS MCP server; iCloud Vault, Metrics, and Settings synchronization; and Metrics cards beyond three. When Pro sync is unavailable, sync services pause rather than attempting background synchronization; when built-in MCP access is lost, an enabled server is suspended. Local Vault and workspace data are not erased by that transition. On macOS, `TermindApp` installs the live controller outside tests and demo mode; `RootView` reconciles sync and MCP whenever status changes. On iOS, `MobileAppModel` uses the live controller outside in-memory/test setups; active scenes refresh access and `MobileRootView` reconciles sync when Pro access changes. Sync on mobile also requires an active foreground scene, even for Pro users. ### 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. +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. ## Review invitation policy @@ -106,7 +130,15 @@ Eligibility requires at least seven days since first use, three distinct active User-facing app strings belong in `Frameworks/Resources/Localizable.xcstrings`, which is compiled into every app bundle; bundle metadata belongs in `InfoPlist.xcstrings`. The separate AgentKit runtime owns its own `../AgentKit/Localizations/Localizable.xcstrings`; its catalog must be rebuilt with `../AgentKit/Scripts/build-localizations.sh` after changes because a plain Swift build copies those resources rather than compiling them. -Any new or changed English app string requires completed `zh-Hans` and `zh-Hant` translations in the same commit. Preserve placeholders and Chinese punctuation conventions. `Scripts/check-zh-localization.sh` requires `jq` and rejects invalid catalog JSON, missing locale entries, unfinished string units, and Chinese/Latin or punctuation spacing violations. Run it in the normal commit pipeline even when localization was not intentionally changed; run `AppLanguageTests` when behavior changes. Product configuration likewise carries English, Simplified Chinese, and Traditional Chinese names and descriptions, so App Store Connect updates must remain synchronized with the local fixture and the localized product copy. +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. + +### Vault labels and locale-sensitive presentation + +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. + +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. ## Mobile Live Activity and widget boundary @@ -124,7 +156,7 @@ The public site is a separate Astro app in `LandingPage/`, with strict TypeScrip ## Change and verification guide -- For an access change, update `ProFeature`/callers and `ProAccessController` together; test entitlement phases, verification failures, pending Ask to Buy, restore, and metadata failure separately. `StoreKitTrialTests` exercises the local `SKTestSession` configuration, while `CommerceConfigurationTests` catches drift between product identifiers and the fixture. +- 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, complete all three languages, run `Scripts/check-zh-localization.sh`, and run `AppLanguageTests` where applicable. diff --git a/openwiki/concepts/index.md b/openwiki/concepts/index.md index 1367cd7f..77f795be 100644 --- a/openwiki/concepts/index.md +++ b/openwiki/concepts/index.md @@ -4,6 +4,6 @@ - [Commerce, Localization, and Product Surfaces](commerce-localization-and-product-surfaces.md) - Explains StoreKit-derived Pro access, native paywall and review ownership, localization completion rules, and the app, widget, screenshot, and marketing-site surfaces that present the product. - [Persistent Data, Migrations, and Secret Boundaries](persistence-and-secrets.md) - How Termind owns SwiftData and GRDB durable data, evolves compatible schemas, projects records through repositories, and keeps credentials in Keychain-backed and runtime-only boundaries. - [Remote services and forwarding](remote-services-and-forwarding.md) - Cross-service ownership of SSH terminal, metrics, SFTP, Agent, and forwarding runtimes, with routing to detailed channel scheduling, shell integration, and multi-connection dispatch mechanisms. -- [Shell Integration: Bootstrap, OSC Events, and Terminal State](shell-integration.md) - How Termind installs session-local Bash, Zsh, and Fish hooks over the PTY, hides bootstrap exchanges, decodes OSC events, and drives cwd, history, startup commands, and command composition on macOS and iOS. +- [Shell Integration: Bootstrap, OSC Events, and Terminal State](shell-integration.md) - How SSH PTY shell hooks bootstrap and decode command and cwd events, and how remote charset conversion differs between SSH PTY and Telnet terminal data paths. - [SSH Multiplexing, Channel Admission, and I/O Scheduling](ssh-multiplexing-and-scheduling.md) - The concrete ownership and scheduling layers behind Termind SSH: per-connection session leases, serial libssh2 workers, exec state machines, multiplexed SFTP retries, readiness, backpressure, and feature-specific connection reuse. - [UI Design Principles and Shared Presentation Boundaries](ui-design-principles.md) - 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. diff --git a/openwiki/concepts/persistence-and-secrets.md b/openwiki/concepts/persistence-and-secrets.md index c08b7fcc..c8c5fa45 100644 --- a/openwiki/concepts/persistence-and-secrets.md +++ b/openwiki/concepts/persistence-and-secrets.md @@ -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-23T10:36:38.039Z sources: - id: openwiki-source-685b7f8e7dbcf91b4e2a50e2 resource: repo://Frameworks/TermindApplication/Agent/AssistantConversationOperations.swift @@ -10,8 +13,12 @@ sources: resource: repo://Frameworks/TermindApplication/Agent/AssistantExecutionController.swift - id: openwiki-source-1c48f72c0c7a3164d7d5c715 resource: repo://Frameworks/TermindApplication/Agent/ConversationModel.swift + - id: openwiki-source-2d98a2885dc21f508f49b749 + resource: repo://Frameworks/TermindApplication/Agent/MemoryIndexedAgentRepository.swift - id: openwiki-source-dc7b363138921b0923d2dc2f resource: repo://Frameworks/TermindApplication/FeatureModels/ConnectionHistoryModel.swift + - id: openwiki-source-7397a04f40a393c81b0ca52d + resource: repo://Frameworks/TermindApplication/FeatureModels/MemoryModel.swift - id: openwiki-source-7ca30f0e781e8c2df826b47a resource: repo://Frameworks/TermindApplication/HistoryLimits.swift - id: openwiki-source-4ddcdd630c9bc1c622a037df @@ -68,12 +75,16 @@ sources: resource: repo://FrameworkTests/CloudSyncSafetyPersistenceTests.swift - id: openwiki-source-eb9518e5c7eb3782fa0cccc0 resource: repo://FrameworkTests/CloudSyncSafetyTests.swift + - id: openwiki-source-256e2b134a8446ea63b15585 + resource: repo://FrameworkTests/HermesMemoryTests.swift - id: openwiki-source-8428b9f5de49b8a561d93fa5 resource: repo://FrameworkTests/PersistenceCompatibilityTests.swift - id: openwiki-source-906678adb91c2fce2d3fcaed resource: repo://TFI/App/MobileAppModel.swift - id: openwiki-source-3f37062f55fb57a9f2e97f35 resource: repo://TFI/Features/Vault/MobileVaultView.swift + - id: openwiki-source-4dbea0ff2808163cb4ecdd8f + resource: repo://TFM/App/AppModel.swift - id: openwiki-source-6570374eaac2e0278fa84640 resource: repo://TFM/App/TermindApp.swift - id: openwiki-source-0854be84b166268626a3cb08 @@ -82,10 +93,7 @@ sources: resource: repo://TFMTests/AgentPersistenceTests.swift - id: openwiki-source-1d1efb20e239b1f2142f6cb7 resource: repo://TFMTests/SettingsSyncTests.swift -generated: { by: "codex", at: "2026-09-23T03:40:50.823Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Persistent Data, Migrations, and Secret Boundaries @@ -112,9 +120,9 @@ This diagram distinguishes durable SwiftData and GRDB records from Keychain mate ## Store ownership and startup -`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 construct separate `ModelContext` instances where independent repository contexts are needed; they do not assemble a partial schema per feature or scene. +`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 propagate out of these composition paths rather than being silently replaced with a new empty database: data availability is an explicit startup failure condition. +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. ### Repository projections and atomic mutation @@ -122,6 +130,8 @@ SwiftData rows are persistence representations, not the feature API. `SwiftDataH Deletion is a durable saga, not an immediate blind removal: `requestHostDeletion` atomically writes a pending-deletion marker, outbox jobs, and the revision. The snapshot hides marked hosts. Later steps remove dependent jump/snippet/history/forwarding references and finally remove host-owned identities, the host, and the marker. This lets a crash expose either the live host or a complete, resumable deletion intent rather than a partial state. +The platform projections differ around the durable deletion request. On macOS `AppModel.requestHostDeletion` clears command, SFTP and connection History for the host, stops forwarding and projects the host out; its registered outbox close-workspaces handler also clears connection History, while other handlers cancel transfers and revoke dependent access. On iOS `MobileAppModel.deleteHost` first disconnects the assistant and closes workspaces, invalidates SFTP edits, cancels transfers, stops forwarding and removes metrics, then requests deletion, projects the host out and starts the outbox. It does **not** clear the three History models in this method: mobile's registered outbox close-workspaces handler clears command, SFTP and connection History later, as well as projecting the deleted host (including after a restart). Do not infer identical *immediate* History behavior from the shared repository deletion saga; on either platform, a failure after pre-request side effects may leave those side effects even if the host projection is not removed. + Agent conversations use a separate SwiftData repository with similarly deliberate projections. `SwiftDataAgentRunRepository` stores run snapshots, messages, context/replay backing, tool invocations/results, reviews, compactions, and ordering. It deduplicates replayed earlier turns by message ID, sanitizes persisted text and tool-call JSON, and marks nonterminal runs interrupted when the repository is initialized. Loading orders transcript rows by run and sequence, then restores recorded tool results that were committed before the next transcript snapshot. ### Assistant history edits: one message boundary, one transaction @@ -136,7 +146,7 @@ The first real snapshot whose final ordinary user turn is this staged replacemen The repository's in-memory retired-ID set includes the edited target run even when its prefix survives, all removed later runs, and adopted staging runs. `save` and durable-event `record` ignore retired IDs, preventing late work from rebuilding the discarded suffix. This is a repository-instance guard, not a new persisted tombstone or schema migration. Both truncation and snapshot save restore the previous retired-ID set and roll back their `ModelContext` changes if the transaction fails. -`AssistantConversationOperations` applies the live history edit only after the repository commits; invalid replacements and rejected writes leave history unchanged. Live running, failed and interrupted projections adopt staging provenance too, but publication ordering is not universal: a captured missing-model/credential failure still updates live state before its separate asynchronous save. See [Assistant Runtime](agent-runtime-and-assistant.md) for that boundary and the distinct immediate-stop runtime-handoff limitation. Shared replay tests restore failed/interrupted adoption through a fresh context; desktop and mobile fixtures compare same-run prefix history and provenance after edits. These fixtures do not inject a real disk-full or read-only SwiftData failure. +`AssistantConversationOperations` applies the live history edit only after the repository commits; invalid replacements and rejected writes leave history unchanged. Captured missing-model/credential failure now schedules a separate asynchronous save and **only then** calls `recordFailedRun` to adopt and publish the failed run; preparation remains active in its saving-failure phase until this finishes. Preparation cancellation that records interruption also saves its terminal snapshot before adopting and publishing the interrupted state. A save error appends a visible error rather than projecting a successful failed/interrupted adoption. This commit-before-projection rule does not make every stop a durability barrier: `ConversationModel`'s queued-before-start cancellation projects `.cancelled` when it launches a best-effort `prestartPersistence` task, and `stopAndWait` joins the consumer but the save error is swallowed. See [Assistant Runtime](agent-runtime-and-assistant.md) for runtime handoff. Shared replay tests reopen failed/interrupted adoption through a fresh context and cover queued cancellation and captured configuration failure; desktop and mobile fixtures compare same-run prefix history and provenance after edits. These fixtures do not inject a real disk-full or read-only SwiftData failure. ## Schema evolution: preserve the past exactly @@ -200,6 +210,25 @@ Memory updates run in database writes. A review is accepted only when its expect The focused Hermes tests prove disabled memory creates no files, snapshots survive a close/reopen, stale background reviews cannot overwrite foreground changes, indexed history is searchable and removed with history replacement, and destroy revokes old access before a later enable can backfill retained conversation history. +`MemoryIndexedAgentRepository` wraps agent history rather than moving it into GRDB: it requests indexing only after a successful terminal run save, conversation creation, title change, truncation or deletion. `MemoryModel` loads the SwiftData-backed conversation projection through `AgentRunPersisting` and replaces the separate searchable memory history; disabled or suspended memory does not start that work. Reindexing coalesces changes while a task is running, and a memory search waits for the current indexing task. This is a derived local index, not a second authoritative copy of agent runs. The GRDB replacement compares redacted message IDs and content, not timestamps alone, so editing a turn with an unchanged timestamp still refreshes the index. + +Suspension is not deletion. Mobile suspends memory when all scenes enter the background and resumes it on foreground return; desktop suspends it on termination. Suspension rotates a generation token, invalidates session contexts and access handles, and cancels index and review tasks. A resumed session receives a new access handle; an in-flight write that committed across suspension can still finish in GRDB, but its obsolete caller receives cancellation and the current generation reloads the committed state rather than publishing a stale result. Index changes saved during suspension are picked up on resume, while a review computed before suspension cannot apply afterward. Disabling memory closes the store without erasing it. Destroy instead disables access, cancels and joins pending work, then removes the GRDB directory; a `hermesMemoryDestroyPending` preference keeps a failed destroy disabled and triggers a retry at next initialization. Re-enabling after a successful destroy can reindex conversations that remain in SwiftData, but cannot revive destroyed memory entries or old access handles. + +```mermaid +flowchart TD + History["SwiftData agent conversation commits"] --> Wrapper["MemoryIndexedAgentRepository"] + Wrapper --> Gate{"Memory enabled and not suspended"} + Gate -->|yes| Index["Load conversations and replace GRDB history"] + Gate -->|no| Deferred["No indexing until enable or resume"] + Index --> Search["Search waits for current index task"] + Suspend["Suspend or destroy"] --> Invalidate["Invalidate generation and cancel work"] + Invalidate --> Resume{"Resume or destroy"} + Resume -->|resume| Index + Resume -->|destroy| Delete["Close store and remove memory directory"] +``` + +Memory history indexing follows committed agent data; suspension invalidates consumers while destroy removes only the separate memory store. + ## Change checklist 1. **Adding SwiftData data:** put the `@Model` in `TermindPersistence`, add it to the current schema, decide whether a new frozen schema/version and migration stage are required, and extend compatibility coverage. diff --git a/openwiki/concepts/shell-integration.md b/openwiki/concepts/shell-integration.md index 6e471f78..70d1994b 100644 --- a/openwiki/concepts/shell-integration.md +++ b/openwiki/concepts/shell-integration.md @@ -1,8 +1,11 @@ --- type: implementation guide title: "Shell Integration: Bootstrap, OSC Events, and Terminal State" -description: "How Termind installs session-local Bash, Zsh, and Fish hooks over the PTY, hides bootstrap exchanges, decodes OSC events, and drives cwd, history, startup commands, and command composition on macOS and iOS." -tags: [ssh, terminal, shell-integration, osc, command-history, charset, lifecycle] +description: "How SSH PTY shell hooks bootstrap and decode command and cwd events, and how remote charset conversion differs between SSH PTY and Telnet terminal data paths." +tags: [ssh, telnet, terminal, shell-integration, osc, command-history, charset, lifecycle] +verified: + - by: openwiki/0.5.2 + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-209392b5f97bd72d0bd87a15 resource: repo://Frameworks/TermindApplication/Agent/TerminalCommandDraftController.swift @@ -12,6 +15,10 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/RemoteCharsetConverter.swift - id: openwiki-source-8c4abf5c09db535e2818e3c4 resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift + - id: openwiki-source-1f7380cad037b68eb1bec322 + resource: repo://Frameworks/TermindRemoteInfrastructure/Telnet/TelnetConnection.swift + - id: openwiki-source-72f95a523c9b93bf5c81d9e5 + resource: repo://FrameworkTests/RemoteCharsetTests.swift - id: openwiki-source-492f738896225c6b3acf7d2f resource: repo://TFI/Features/Workspaces/MobileWorkspace.swift - id: openwiki-source-7e796927b780e67cc73f6a5b @@ -22,10 +29,7 @@ sources: resource: repo://TFMTests/HostShellIntegrationSessionTests.swift - id: openwiki-source-b1446950c4c60caef12aa43a resource: repo://TFMTests/ShellIntegrationBootstrapTests.swift -generated: { by: "omp", at: "2026-09-22T02:43:23.140Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Shell Integration: Bootstrap, OSC Events, and Terminal State @@ -55,6 +59,8 @@ flowchart TD WorkingDirectory --> Feature ``` +SSH PTY receive flow: event frames are removed before charset conversion, while cwd is rewritten before terminal parsing. + `deliverOutput` first lets the bootstrap suppress its exchange. `applyShellIntegrationUpdate` queues any next command, emits availability/home/system events, and routes visible bytes through `deliverIntegratedOutput`. That method removes recognized OSC 777 frames, forwards remaining output, then emits its ordered event array. `emitConvertedOutput` rewrites OSC 7 before the streaming charset converter and terminal callback. Thus parsing is not performed by searching already-rendered terminal text, and ordering within the event array does not imply atomic ordering with native terminal rendering. ## Probe and install state machine @@ -86,6 +92,8 @@ stateDiagram-v2 Installing --> Complete: installation deadline ``` +Bootstrap lifecycle: a late probe can still install hooks unless the user already wrote to the PTY. + The first probe deadline is **3 seconds**. It restores ordinary output and reports home resolution unavailable, but intentionally does **not** mark the bootstrap complete: a late-signature scanner remains active. The scanner streams unrelated output through, retains only a possible signature suffix, and flushes an unresolved suffix after **500 ms** of quiet. Recognized late-probe suppression ends at its 3-second deadline or after 500 ms of quiet. Installation gets its own 3-second deadline. `write(_:)` calls `noteUserInput` before appending user bytes. If a supported probe arrives **late** after any user write, the bootstrap skips installation so it does not inject a hook command into the user's new input. This check is specifically the late-probe branch; it is not a general rule that any early keystroke immediately cancels bootstrap. An unsupported shell likewise gets no installation command. Successful installation emits the saved banner plus bytes after the DONE line; timeout cleanup attempts to keep the latest prompt while hiding probe/installer echo. @@ -117,13 +125,15 @@ The following are descriptions of wire frames, not strings to paste into a termi `RemoteCommandEventFilter` finds the earliest recognized prefix, preserves preceding output, waits for BEL, decodes the event, and repeats. It retains incomplete prefix suffixes across SSH reads, so a frame split at any byte still works. Command/draft payloads are percent-decoded to remote-charset bytes and then converted to text. Status must be `0...255`; a valid optional duration is an unsigned value no larger than `31_536_000_000` milliseconds and is converted to seconds. Invalid duration becomes absent rather than invalidating a valid status. +For command and draft text, `decodePercentEncoded` unescapes valid `%HH` triplets to bytes, then uses the configured remote charset to produce a Swift string; HOME uses the same helper, while the SHELL and SYSTEM markers decode their raw bytes with that charset. These are per-frame conversions, not the streaming display decoder. If conversion fails, the helper falls back to lossy UTF-8; even when conversion succeeds, bypassed malformed bytes may become replacement characters when converted to a Swift string. The UTF-8 `%FF` command test specifically expects `.commandStarted("�")`; the GB18030 command test establishes non-UTF-8 decoding, but neither test promises byte-perfect command history for malformed text. + Payload retention is capped at **64 KiB** for recognized frames. An oversized unterminated frame is dropped so future output can resume; an oversized terminated frame is skipped. Ordinary output, OSC 0/2 titles, and wrong-token OSC 777 data remain on the terminal path and generate no local command events. The token provides **session scoping and accidental/spoofed-frame rejection without the matching token**, not cryptographic authentication against the remote host: the installer sends the token to that host and stores it in shell state. Treat command text, paths, and system fields as remote input even after they pass this parser. Also, OSC 7 is a standard terminal signal and is not authenticated by the OSC 777 token. ## Cwd, home, history, and composition are different state -- **Cwd** comes through the terminal's OSC 7 handling. `RemoteOSC7CharsetFilter` recognizes `file://localhost`, decodes the remote-charset path and re-encodes it as percent-encoded UTF-8 before the terminal parses it. Desktop observes `TerminalViewState.workingDirectory`. **Home** comes from the bootstrap HOME marker and is stored separately for path display; an unresolved home is not evidence that cwd is absent. +- **Cwd** comes through the terminal's OSC 7 handling. `RemoteOSC7CharsetFilter` recognizes `file://localhost`, buffers split prefixes/frames, unescapes the path bytes, decodes using the remote charset and re-encodes them as percent-encoded UTF-8 before the terminal parses them. For malformed UTF-8 `%FF`, the resulting path is `/%EF%BF%BD`, not the original byte. Its 64 KiB unterminated payload limit passes the oversized data through instead of retaining it indefinitely; an unfinished prefix is flushed on PTY close. Desktop observes `TerminalViewState.workingDirectory`. **Home** comes from the bootstrap HOME marker and is stored separately for path display; an unresolved home is not evidence that cwd is absent. - **Availability** means installation completed. On desktop, `.available` sets integration available but leaves `isShellPromptReady = false`; `.promptReady` sets it true and `.commandStarted` clears it. Mobile intentionally also treats `.available` and `.commandFinished` as prompt-ready recovery boundaries, because a separate prompt marker may not reach mobile state. Do not merge these policies during a shared-state refactor. - **History** is driven by command-start/completion events, not by recording every keystroke. Both consumers normalize explicit line continuations and associate completion with the active recorded row. Their one-shot startup-command exclusion suppresses only the matching synthetic command rather than disabling subsequent history. - **Startup submission readiness** is separate from command-generator prompt readiness. Desktop can unblock a pending startup command on `.available`, `.promptReady`, or `.homeResolutionUnavailable`, so failed/late integration does not indefinitely withhold startup work. @@ -131,6 +141,26 @@ The token provides **session scoping and accidental/spoofed-frame rejection with Desktop callbacks reject a mismatched `connectionAttemptID`. Mobile serializes exit and shell events through one `AsyncStream` consumer guarded by the workspace generation, preserving event consumption order across MainActor delivery. Closing the PTY clears bootstrap, command filter, converters, and pending input; the underlying SSH connection may remain alive if sibling SFTP channels still own it. See the transfer lifetime distinction in [SFTP Workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md). +## Charset boundary and the separate Telnet path + +`RemoteCharsetStreamConverter` maps the configured `RemoteCharset` to iconv names (UTF-8, GB18030, Big5, Shift_JIS, EUC-JP, EUC-KR, ISO-8859-1, Windows-1252). It retains incomplete source characters between `convert` calls and `finish` flushes trailing input. **Outgoing encoding is strict**: an unrepresentable character or invalid UTF-8 raises `RemoteCharsetConversionError` by default; only callers explicitly opting into `recoveringInvalidInput` may discard invalid input and see `rejectedInput`. Inbound conversion favors uninterrupted display: UTF-8 decoding passes bytes through unchanged, including invalid bytes; for legacy decoding, iconv converts valid sequences, bypasses malformed source bytes in place, and holds incomplete sequences until later input or flushes them verbatim at finish. A byte stream that survives decoding is not necessarily valid UTF-8: Swift `String(decoding:as:)` used for metadata/events is lossy for invalid UTF-8, and the terminal backend may render such bytes as replacements. Do not interpret `rejectedInput == false` on decode as proof of valid text, or generalize the UTF-8 bypass test to claim all charsets take an identical byte-for-byte path. + +For SSH PTY, the worker creates distinct input and output converters from the connection charset. Environment variable names and values are strictly encoded before channel setup; user input is encoded before entering the pending SSH write queue, and an encoding error reports through the charset-error callback rather than sending the offending text (the write error branch still queues any bracketed-paste delimiters found in that input). The receive chain in the diagram strips command events and rewrites OSC 7 on raw PTY bytes before streaming text conversion. On terminal close, `finishCharsetOutput` flushes the OSC 7 filter remainder through the output converter and finishes the decoder before clearing session state; catastrophic receive conversion errors fall back to raw bytes rather than halting the PTY. Cwd rewriting is installed even if shell integration is disabled, so a remote OSC 7 frame can still reach the terminal; this does not install Termind command hooks. + +Telnet uses the same converter **but does not run the SSH shell bootstrap, OSC 777 filter, or OSC 7 rewrite**. Both direct TCP and proxied-socket connection paths configure encoder and decoder before opening the transport. `TelnetProtocolParser` first strips Telnet negotiations and handles NVT data, then the worker decodes application bytes for the terminal and login-prompt scanner; a decoder exception falls back to raw application bytes. Input (including automated username/password) is strictly encoded before Telnet NVT formatting and IAC escaping. A user-write encoding error calls `charsetError` without sending that write; an automatic-login encoding error clears the secret, reports the error and continues manually. Cleanup finishes the output converter to deliver its remaining bytes and clears converter and prompt state. Desktop and mobile Telnet session models pass converted output to their terminal backends and surface charset errors, but do not consume SSH shell integration events for Telnet. + +```mermaid +flowchart TD + Wire[Telnet TCP or proxy socket] --> Protocol[Telnet protocol and NVT parser] + Protocol --> Decode[Streaming remote charset decode] + Decode --> Backend[Terminal backend and login prompt scanner] + Input[User or automated login text] --> Encode[Strict charset encoding] + Encode --> NVT[NVT formatting and IAC escaping] + NVT --> Wire +``` + +Telnet terminal data path: negotiation is removed before decoding, and outgoing text is encoded before wire escaping; there is no SSH hook installation in this route. + ## Debugging and focused test map | Symptom or change | First seam to inspect | Regression evidence | @@ -138,7 +168,8 @@ Desktop callbacks reject a mismatched `connectionAttemptID`. Mobile serializes e | Probe/installer text appears, or a slow login loses its prompt | `receiveProbe`, `scanForLateProbe`, `poll`, `cleanBufferedOutput` | `ShellIntegrationBootstrapTests`: redraw, chunked late probe, quiet timeout, user-input skip, unsupported shell. | | Zsh prompt or ordinary output disappears | Installer's prompt hook and exit-status preservation | `zshRunsPromptHooksAndPreservesCommandOutput`, including startup-output capture. | | History duplicates or has no completion | OSC token/parser, then feature's active history row | `CommandHistoryTests`, including split frames, order, wrong token, invalid status and oversized recovery. | -| Cwd contains mojibake | OSC 7 rewrite before output conversion, not history decoding | `RemoteOSC7CharsetFilter` and `RemoteCharsetTests`. | +| Cwd contains mojibake or invalid path bytes | OSC 7 rewrite before output conversion, not history decoding | `RemoteCharsetTests`: GB18030 cwd UTF-8 rewrite and UTF-8 `%FF` lossy rewrite. | +| Text cannot be sent, or malformed incoming bytes display oddly | Outgoing strict encoding versus inbound byte bypass and terminal rendering; Telnet strips protocol bytes before decoding | `RemoteCharsetTests`: representative charset round-trips, every GB18030 multibyte split, ISO-8859-1 rejection, UTF-8 bypass and legacy malformed/trailing-byte recovery. | | Compose is enabled while a command runs | Availability versus prompt-ready transitions | `TerminalCommandDraftControllerTests`; `MobileCommandGeneratorAndUploadTests` prompt/integration cases. | | Settings change an already connected shell | Attempt-time preference capture | `HostShellIntegrationSessionTests`; mobile `integrationUsesConnectionSnapshotUntilManualOrAutomaticReconnect`. | diff --git a/openwiki/concepts/ssh-multiplexing-and-scheduling.md b/openwiki/concepts/ssh-multiplexing-and-scheduling.md index 368473ac..580e9b1d 100644 --- a/openwiki/concepts/ssh-multiplexing-and-scheduling.md +++ b/openwiki/concepts/ssh-multiplexing-and-scheduling.md @@ -3,7 +3,12 @@ type: implementation guide title: SSH Multiplexing, Channel Admission, and I/O Scheduling description: "The concrete ownership and scheduling layers behind Termind SSH: per-connection session leases, serial libssh2 workers, exec state machines, multiplexed SFTP retries, readiness, backpressure, and feature-specific connection reuse." tags: [ssh, multiplexing, scheduling, libssh2, backpressure, sftp, concurrency] +verified: + - by: openwiki/0.5.2 + at: 2026-09-23T10:36:38.039Z sources: + - id: openwiki-source-4f78037bc69b6dfc293aca3d + resource: repo://Frameworks/TermindApplication/SSHConnectionTypes.swift - id: openwiki-source-8e06414c0a0a26e45de192bd resource: repo://Frameworks/TermindDomain/Connections/SSHPreferences.swift - id: openwiki-source-0c82bf45bc197f879a54fd3a @@ -26,14 +31,15 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHPTYChannel.swift - id: openwiki-source-e63615bc111f4678ec12525d resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHStreamPump.swift + - id: openwiki-source-0260a25fb41739d94e23d2ea + resource: repo://TFMTests/AgentConnectionPoolTests.swift + - id: openwiki-source-cfbc34def649c94f760c5695 + resource: repo://TFMTests/AgentHostAuthenticationTests.swift - id: openwiki-source-7364a5d16e49e89eb03bbee2 resource: repo://TFMTests/SSHForwardingPumpTests.swift - id: openwiki-source-ec3ec372dd69a7df3113c6b1 resource: repo://TFMTests/SSHMaxSessionsPolicyTests.swift -generated: { by: "omp", at: "2026-09-22T02:43:23.140Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # SSH Multiplexing, Channel Admission, and I/O Scheduling @@ -76,7 +82,9 @@ This is a conceptual layering diagram, not a claim that every owner supports eve Metrics deliberately opts out of concurrent operations: `SSHExclusiveConnectionAdapter.withConnection` uses a busy flag and FIFO continuations to serialize complete operations on its owned connection. That adapter has no topology/fallback policy. Similar-looking SSH usage does not authorize merging Metrics, terminal, Agent, and forwarding lifetimes. -The Agent has a separate higher-level reuse policy: `AgentConnectionPool` keys connections by Host ID plus route fingerprint, joins same-fingerprint in-flight opens, and opens primary SFTP on its pooled SSH connection. Reuse survives a follow-up Agent run; default idle expiry is 180 seconds, and active exec/SFTP leases prevent whole-host idle retirement. Missing/changed routes invalidate reuse. This is an Agent-owned pool, not the terminal or forwarding pool. +The Agent has a separate higher-level reuse policy: `AgentConnectionPool` keeps one primary SSH connection per Host ID and route fingerprint across tool calls, runs, and conversations. Exec and primary SFTP share it; same-fingerprint connection opens and primary SFTP opens are joined rather than duplicated. A changed route retires the old connection and its SFTP state; failure to resolve a deleted/closed target disconnects it. A successful open is bound to the **post-authentication** route fingerprint, so saving an identity during a prompt does not immediately invalidate that new connection. This is an Agent-owned pool, not the terminal or forwarding pool. + +Idle retirement defaults to 180 seconds (swept every 30 seconds in the app). Active exec or SFTP operation leases block whole-host retirement; idle auxiliary SFTP connections can be retired separately. Idle expiry then closes the primary and its SFTP state. `openConnectionCount` includes pooled primaries and auxiliary SFTP connections, not sibling subsystem channels. `disconnect(hostID:)` and `closeAll()` also cancel pending opens and SFTP activity. The Agent's `withSFTP` acquires an exclusive channel lease for an operation; overlap can use silent auxiliary connections or sibling channels according to scheduling mode, but the operation itself is never replayed. ## Session-channel budget: local FIFO, not server discovery @@ -148,7 +156,32 @@ Any libssh2 read can decode packets for another channel. The forwarding worker t Socket dispatch sources are queue-confined. `SSHSocketEvents.cancel` resumes suspended sources after cancellation and runs the descriptor-close completion only after **both** cancellation handlers have retired. The exec worker increments its generation on cleanup, clears queued work, closes SFTP and the channel budget, and rejects stale scheduled pumps/events. Transport errors report connection failure once and fail outstanding commands; one command's channel-local error follows its own close/free path instead. -The Agent's automatic replacement retry is deliberately narrow: `AgentConnectionPool.execute` retries `SSHCommandExecutionError.connectionUnavailable` once, not arbitrary errors after a remote command may have started. Multiplexing is not permission to replay a command or an established TCP stream. +## Agent authentication and pool retry boundaries + +`AgentSSHAuthenticationRegistry` leases one `AgentSSHAuthenticationContext` per destination to overlapping calls, including exec and SFTP. It removes the context when the last call finishes; temporary passwords/passphrases are **not** a cross-run credential cache even though the authenticated pool connection can persist. A missing connection first resolves local route checkpoints (proxy credentials, identity, required key passphrase) before opening a socket. Configuration attempts and prompts join by generation; cancelling a waiter removes it without cancelling another waiter's work, and the last waiter cancels the shared attempt. Host-key prompts and keyboard-interactive answers are carried on the attempt request, not returned as tool content. + +```mermaid +flowchart TD + Call["Agent exec or SFTP acquisition"] --> Reuse{"Pooled connection exists?"} + Reuse -->|yes| Pooled["Open without fresh credential attempt"] + Reuse -->|no| Config["Resolve local route requirements and join generation attempt"] + Config --> Open["Join pooled open by Host and fingerprint"] + Pooled --> Open + Open --> Result{"Open result"} + Result -->|success| Success["Consume attempt secrets and return client"] + Result -->|server authentication failure| Evict["Evict pooled connection for ordinary opens"] + Evict --> Retry["Advance generation and reprompt failing route node"] + Retry --> Config + Result -->|local authentication requirement| Local["Resolve configuration without failed-generation reset"] + Local --> Config + Result -->|cancellation or other error| Fail["Propagate without replaying operation"] +``` + +Agent authentication retry and pool acquisition; `withSFTP` uses the same auth loop with pooled eviction disabled during lease acquisition. + +For an authentication rejection (`shouldRequestAuthentication`), `openAuthenticated` normally evicts the pooled connection, calls `retry(after:generation:)`, and obtains a new attempt; `withSFTP` deliberately disables that eviction while acquiring a lease. The failed generation alone may clear staged secrets and force a new prompt for the failing route node (including proxy failures); late failures cannot erase a newer answer. A **local** requirement (`isLocalAuthenticationRequirement`, such as missing credentials, username, or key passphrase) instead re-resolves configuration without treating it as a rejected server attempt. Cancellation is checked before each open and after a rejection for transfer tokens; unrelated errors propagate. Authentication success consumes one-shot secrets. `withSFTP` releases its lease on success or failure, disconnects on SFTP connection loss, and never retries the already-running file operation. + +A separate, narrower safety net lives in `AgentConnectionPool.execute`: it retries **once** only for `SSHCommandExecutionError.connectionUnavailable`, after disconnecting and replacing the connection. `SSHConnectionWorker` emits that error when the session budget is gone or the connection/budget changed before the exec channel was enqueued. Channel rejection or an error after command start is not a safe replay. When an in-flight pool open loses its only waiter, it cancels the open and disconnects any late successful socket; cancelling just one of multiple waiters leaves their shared open alive. Multiplexing is not permission to replay a command or an established TCP stream. ## Focused verification and diagnostic routing diff --git a/openwiki/concepts/ui-design-principles.md b/openwiki/concepts/ui-design-principles.md index 70c2db4c..3e5a9c8e 100644 --- a/openwiki/concepts/ui-design-principles.md +++ b/openwiki/concepts/ui-design-principles.md @@ -3,11 +3,18 @@ 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-23T10:36:38.039Z sources: + - id: openwiki-source-d1d534769c300d5fb8dbe9d7 + resource: repo://Frameworks/TermindApplication/FeatureModels/HostCustomIdentityDraft.swift - id: openwiki-source-4ae2a0061a7bd729d6e132b4 resource: repo://Frameworks/TermindApplication/FeatureModels/TerminalSettingsModel.swift - id: openwiki-source-0ad8e888a4a6fb517fde6f7a resource: repo://Frameworks/TermindDomain/Sessions/TerminalFontPreferences.swift + - id: openwiki-source-5b42af91dbdc738123786a99 + resource: repo://Frameworks/TermindPresentation/AgentToolPresentation.swift - id: openwiki-source-400e4d9303a3f9d98f90660d resource: repo://Frameworks/TermindPresentation/AssistantTranscriptEntry.swift - id: openwiki-source-eec1a2bc6dfc2c60b2bee55c @@ -36,22 +43,34 @@ sources: resource: repo://TFI/Features/AI/MobileAssistantConversation.swift - id: openwiki-source-fc448263e4e5ce330b8cbda1 resource: repo://TFI/Features/HostEditor/MobileHostEditor.swift + - id: openwiki-source-a053f8c3524e81f98b0b0938 + resource: repo://TFI/Features/Metrics/MobileMetricsView.swift - id: openwiki-source-5503f969776cb509a7d69160 resource: repo://TFI/Features/Ports/MobileForwardingView.swift - id: openwiki-source-02810e1f8eac4d0983f8cd44 resource: repo://TFI/Features/Settings/MobileTerminalSettingsView.swift - id: openwiki-source-db402cad9d68dd8e66bdd7ee resource: repo://TFI/Features/Snippets/MobileSnippetsView.swift + - id: openwiki-source-3f37062f55fb57a9f2e97f35 + resource: repo://TFI/Features/Vault/MobileVaultView.swift - id: openwiki-source-e396438eb6a8a7ca888da5f4 resource: repo://TFI/Platform/TerminalFontCatalog.swift + - id: openwiki-source-3af0aeffcab26dc81096aefc + resource: repo://TFI/UI/Components/MobileEditorSheet.swift - id: openwiki-source-a4f3a690a8395e2ac9b065b9 resource: repo://TFI/UI/Components/MobileNativeList.swift - id: openwiki-source-c99ab42abad536ed4396933c resource: repo://TFI/UI/Managed/MobileCards.swift - id: openwiki-source-fffc181d864b6caea779a6f5 resource: repo://TFITests/MobileAdaptiveLayoutTests.swift + - id: openwiki-source-c32ed562101f11a0c3c89663 + resource: repo://TFITests/MobileCardTests.swift + - id: openwiki-source-7341d7b266d976d7aac5d161 + resource: repo://TFITests/MobileEditorToolbarTests.swift - id: openwiki-source-8194e1eb3652c7ad61d75cfa resource: repo://TFITests/MobileTerminalFontTests.swift + - id: openwiki-source-5636c5d112b9e5b2266c3058 + resource: repo://TFITests/MobileVaultFeatureTests.swift - id: openwiki-source-873894299539cce9a737a860 resource: repo://TFM/App/RootView.swift - id: openwiki-source-f490cb5bfbb8ce236a7f1bf4 @@ -62,6 +81,8 @@ sources: resource: repo://TFM/Features/Assistant/AssistantView.swift - id: openwiki-source-1e0cf223ab8448c8eee3f345 resource: repo://TFM/Features/HostEditor/HostEditorView.swift + - id: openwiki-source-b0f15ccf6473e8cbe34bd9c3 + resource: repo://TFM/Features/Hosts/HostActions.swift - id: openwiki-source-f1d91230931f6a1921af6d03 resource: repo://TFM/Features/Ports/PortForwardingView.swift - id: openwiki-source-cfe2a6b22338023c37a5b503 @@ -72,26 +93,37 @@ sources: resource: repo://TFM/Features/Sidebar/WindowSidebarView.swift - id: openwiki-source-23281ca04cda9d7abc31173f resource: repo://TFM/Features/Snippets/SnippetsPageView.swift + - id: openwiki-source-564c1a0cc523e70840b9fc66 + resource: repo://TFM/Features/Workspaces/PaneLayoutDropController.swift - id: openwiki-source-ba160208435f3410138a3539 resource: repo://TFM/Features/Workspaces/PersistentWorkspaceDeckLayout.swift + - id: openwiki-source-931aff66b28d38cd69ce2324 + resource: repo://TFM/Features/Workspaces/WorkspaceContentView.swift + - id: openwiki-source-7e364c6182a8339831ecab24 + resource: repo://TFM/Features/Workspaces/WorkspaceNavigatorView.swift - id: openwiki-source-385c953ef1c6bf095d1c1244 resource: repo://TFM/Platform/TerminalFontCatalog.swift - id: openwiki-source-4a6780d3dff41f37f56a094f resource: repo://TFM/UI/Components/SidebarRow.swift + - id: openwiki-source-5e2670d68f19777e2dd312ea + resource: repo://TFM/UI/Components/WindowToolbar.swift + - id: openwiki-source-f941c4bd7cfa47476dcdb53f + resource: repo://TFM/UI/Components/WorkspaceLayoutDropTarget.swift - id: openwiki-source-f6a967b4f14bf50d1af51b8b resource: repo://TFM/UI/Managed/ManagedCardPage.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift + - id: openwiki-source-98505b843db3ce6b8e4ca024 + resource: repo://TFMTests/PersistentWorkspaceDeckLayoutTests.swift - id: openwiki-source-dceb8d7e7c5bb09359e70052 resource: repo://TFMTests/ResponsivePageLayoutTests.swift - id: openwiki-source-2891f940e682279163740c83 resource: repo://TFMTests/TerminalFontRenderingTests.swift - id: openwiki-source-9442022b3dba1be62a55f0f0 resource: repo://TFMTests/TerminalThemeTests.swift -generated: { by: "codex", at: "2026-09-23T05:17:08.701Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T05:17:08.701Z + - id: openwiki-source-1c583949c6f00d5acc015c90 + resource: repo://TFMTests/WorkspaceLayoutDropTests.swift +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # UI Design Principles and Shared Presentation Boundaries @@ -121,6 +153,8 @@ flowchart TD Mobile --> UIKit[UIKit terminal / list / input adapters] ``` +The shared layer supplies values and fields; each app composes and owns its native shell. + 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. @@ -174,7 +208,7 @@ TFI's card surface similarly uses system glass where available, but keeps a near Desktop `ManagedCardPage` is a protocol-oriented page composition seam. It supplies typed sections, externally owned selection, capabilities, card/header/ghost views and presentation modifiers to `ManagedCardPageRenderer`. The renderer handles geometry, selection and drag mechanics, then reports stable IDs back to the page's actions. -Mobile uses a simpler `MobileCardPage` / `MobileCardGrid` / `MobileActionCard` composition. A card's primary action fills the card, while secondary actions live in its context menu. Other mobile lists use swipe actions and navigation links. There is no requirement to reproduce the desktop marquee-selection renderer on touch devices merely because both display Hosts. +Mobile uses a simpler `MobileCardPage` / `MobileCardGrid` / `MobileActionCard` composition. A card's primary action fills the card, while secondary actions live in its context menu. Other mobile lists use swipe actions and navigation links. There is no requirement to reproduce the desktop marquee-selection renderer on touch devices merely because both display Hosts. For a Vault Host, tapping the card invokes the scene's host activation; its context menu is instead grouped into connection protocols (SSH/SFTP only if SSH is enabled, Telnet only if Telnet is enabled), Edit/Duplicate, and destructive Delete. Even a Host with no enabled protocol retains the editing and deletion groups. The menu delegates opening to the scene, duplication to `MobileAppModel` (with a fresh ID and without reusing Host-custom identities), and deletion to confirmation before the app-owned delete path. Desktop `HostContextMenu` has its own Quick Connect, Connect submenu and Copy SSH Command; do not assume the two platforms have an identical set of verbs or move these operations into shared card rendering. The intended separation is: @@ -188,21 +222,40 @@ flowchart LR Update --> Data ``` +A card reports intent; the feature/application owner decides whether and how to perform it. + Use capabilities to say what a renderer may offer; keep the operation's actual validity check with its owner. Disabled UI is useful feedback, not a replacement for business validation. Native menu structure can differ without changing the operation. A single desktop Port Forwarding card groups **Address** and **SSH Command** under **Copy**, before the Edit/Duplicate group. Mobile keeps flat **Copy Address** and **Copy SSH Command** actions in the equivalent position. Both write through their native pasteboard adapter and disable SSH-command copying when the library cannot generate a command; copying never starts forwarding. Snippet library cards expose one **Run** action instead of separate Execute and Execute on Hosts actions; the mobile detail and host-selection surfaces use the same Run vocabulary. Target selection and destructive confirmation remain in the existing feature flow: desktop fills missing saved targets through its chooser, while mobile asks when no valid targets remain. Renaming the action and removing the duplicate override affordance does not remove the host validation or destructive-script confirmation boundary. +### Keep toolbar commands attached to the content in front + +Desktop titlebar Find is a window-level control, not a second search field in each feature. `WindowModel.findContext()` binds it to the active Vault page, Assistant, Metrics or focused terminal/SFTP query; terminal Find additionally supplies Return/Shift-Return navigation and Escape cancellation. `NativeSearchField` retains an AppKit field owner and a keyboard-focus claim across toolbar bridge rebuilds as filtering changes the page. The command installs a direct focus callback because a toolbar-item refresh is not guaranteed to deliver a focus counter change; the field releases that claim on actual user exit so panes can regain focus. On older macOS versions a compact Metrics layout uses a toolbar popover; the toolbar slot remains chosen by OS availability rather than changing the page's view parent on navigation. The leading New menu similarly resolves actions from the front destination, while Navigator row menus can request the same page-specific verbs without first navigating there. This is an example of sharing *intent and ownership*, not making every feature implement its own titlebar. + ## 5. Share form fields; keep draft and route lifetimes explicit Both Host editors reuse `HostOrganizationSection`, `HostProtocolProfileControls` and `HostConnectionFields`, but their containers are intentionally different: - TFM edits a local Host draft in the Vault work column. Nested editing stays in that column; introducing another `NavigationStack` there can promote its destination into the enclosing split detail and cover the collection. -- TFI edits a local Host draft in `MobileEditorSheet`, with mobile routes, dirty-state checking and save eligibility. Shared fields add platform-appropriate keyboard/autocorrection behavior where needed. -- Group/tag controls are injected by each platform into the shared organization section rather than forcing one platform's picker into the other. +- TFI presents `MobileHostEditor` from Vault's `editingHost` sheet route. It seeds a local Host draft from the selected or newly created Host; the shared protocol control switches which SSH/Telnet connection fields are edited. Group/tag controls are injected by each platform into the shared organization section rather than forcing one platform's picker into the other. Shared connection fields apply iOS URL/number keyboards and no autocorrection for addresses. +- The mobile editor passes draft dirtiness and save eligibility to `MobileEditorSheet`. Its save gate requires a nonblank address, at least one enabled terminal protocol, enabled-port ranges, valid custom SSH/Telnet/proxy identities and SSH environment variables. `HostCustomIdentityDraft` holds temporary custom credentials separately from the Host draft, loads them once on appearance and saves them through the Host library along with the Host only when Save runs. Desktop additionally checks SSH route and SFTP initial-path validity in its own commit policy; do not infer identical validation just because the visible fields are shared. +- Child editing on mobile uses item-based sheets for identities, groups and environment variables; saved children update the parent draft or its selections. Desktop instead keeps nested routes in the Vault work column. The mobile sheet owns Cancel/discard confirmation, disabled Save and content during an in-flight save, error alert and dismissal only after successful save. A failed save leaves the editor visible for correction. -The data path is draft binding → shared fields → platform validation/save action. It is not shared fields → database or transport. +```mermaid +flowchart TD + Vault["Vault Add or Edit"] --> Editor["Host draft and identity draft"] + Editor --> Fields["Shared fields and mobile-only sections"] + Fields --> Validate["Mobile save eligibility"] + Validate -->|invalid| Disabled["Save disabled"] + Validate -->|valid| Sheet["MobileEditorSheet Save"] + Sheet --> Library["Identity draft saves through Host library"] + Library -->|success| Dismiss["Dismiss editor"] + Library -->|failure| Error["Keep sheet and show error"] +``` + +The mobile form's draft, child routes, validation gate and save lifecycle are distinct from the shared field fragments. The data path is draft binding → shared fields → platform validation/save action, not shared fields → database or transport. ### Terminal preferences: shared fields, native adapters @@ -216,6 +269,10 @@ Focused tests cover complete macOS monospaced-family membership, typography prec `SingleLineTextInput` illustrates a narrow shared policy. It replaces runs of newline scalars with one space, preserves attributed paste content, and normalizes only edits through the binding setter. Reading the original bound value does not rewrite stored data. This is not a general sanitizer for secrets, multiline commands, snippets or existing repository records. Native paste/input insertion is supplied by app-owned environment adapters so selection and input-method handling can stay platform-specific. +### Shared presentation must not change execution data + +`AgentToolPresentation` converts Assistant tool calls/results into localized human-readable summaries, batch tints and details for both apps. A live approval projection uses the in-memory request's unredacted arguments for the person reviewing it, but does not attach those arguments to the durable tool card or model transcript. Built-in tool results become structured detail where possible; remote-defined MCP output keeps its JSON presentation, and failed/denied results cannot select a success-shaped knowledge presenter. The display preview bounds long output while retaining the full transformed text for Copy. These are display policies, not approval, execution, replay or persistence policies. When adding a tool or localized label, change its presentation metadata/projector and test the visible wording and failure state without rewriting protocol payloads. + ## 6. Native rendering is a deliberate workload boundary SwiftUI composes pages, but terminal and high-update list workloads use native adapters. `ArchitectureBoundaryTests` restricts ListViewKit importers to a specific set of native-list workloads rather than permitting it throughout every feature. @@ -240,23 +297,47 @@ The implementation already treats accessibility as behavior, not a final label p - Motion helpers accept Reduce Motion, and native-list adapters propagate motion and scene activity into hosted rows. - Mobile geometry tests retain marked Chinese text and first responder status during region changes, not just the final draft string. -Localization likewise affects measurement and identity-sensitive presentation. The existing adaptive/rendering cases exercise English, Simplified Chinese and Traditional Chinese, including narrow desktop editors and the mobile tab set. A layout that works only with the shortest English label is not proven by a source-level logic test. +Localization likewise affects measurement and identity-sensitive presentation. The existing adaptive/rendering cases exercise English, Simplified Chinese and Traditional Chinese, including narrow desktop editors and the mobile tab set. A layout that works only with the shortest English label is not proven by a source-level logic test. On mobile, `MobileRootView` keeps a scene-owned destination binding and a `NavigationStack` per registered tab under `.sidebarAdaptable`, rather than rebuilding a compact-only tab set. The adaptive test checks the *same* native `UITabBarController` with five available tabs through regular and compact widths with both ordinary and accessibility text sizes; it selects every tab and checks that scene selection, selected native tab identity and a visible title agree. At regular width the system bar may scroll, whereas compact width requires all five titles to be visible. Other tests retain the same Assistant navigation/conversation/draft, Metrics page and native list/scroll offset, Vault search controller, nested Settings editor draft and in-flight Save sheet across width changes. They also exercise Assistant title/switcher and Metrics detail toolbar placement, including vertical menu layout and iPad sidebar transitions. These are behavioral identity checks and captured layout regressions, not a promise that every screen is pixel-identical at every width. Do not claim all animation sites are already Reduce Motion-aware: the helpers make that policy available, but each changed call site still needs inspection. Likewise, an accessibility label does not prove that focus order, clipping, menu reachability or large-text layout is correct. ## 8. Continuity has a cost budget -The platform guides describe several different retention strategies: +The platform guides describe several different retention strategies. `MobileContentRegions` subtracts active divisions and occlusions, chooses the largest unobstructed continuous rectangle and only offers a split when both sides are usable. Assistant assigns transcript to the first region and composer to the second; Metrics displays both panels when the split is usable (or on sufficiently wide continuous space), otherwise keeps the selected panel. `MobilePaneLayout` places the *same* children even when a frame disappears, caching their last usable sizes rather than giving a covered native surface a zero-size proposal. Usability gates visibility, hit testing and accessibility together. The fold tests check that the Assistant transcript native scroll view and focused composer with marked input remain the very same objects through horizontal and vertical divisions, occlusion and reopening; Metrics retains its native list and offset when the segmented picker becomes a vertical toolbar menu and returns. + | Mechanism | What is preserved | How unnecessary work is limited | | --- | --- | --- | | Desktop workspace deck | Mounted session views and native terminal state. | Hidden geometry is parked and invisible controls are disabled. | | Desktop transcript owner cache | Native list, measurements and presentation caches across remounts. | LRU trimming of unmounted owners; separate keys for sidebar/full screen. | -| Mobile workspace registry | Shared session and native terminal across navigation. | Explicit close and app background-expiration policy, not unconditional foreground work. | +| Mobile workspace registry | `MobileAppModel` publishes live workspaces independently of scenes; saved descriptors are recent rows, not connected sessions at cold launch. | Explicit close disconnects and removes the descriptor; when all scenes background, expiration suspends workspaces, while foreground activity resumes them. | | Mobile region layout | Native child identity during adaptive geometry changes. | Only usable regions accept input/accessibility; covered children keep valid sizes. | +The mobile registry saves descriptors separately from live workspaces, publishes a restored workspace before calling `connect()` so scenes share one instance and attempt, and removes missing-Host descriptors rather than trying to connect them. A cold launch lists recent descriptors without opening every session; selecting one connects only that workspace. Closing a live workspace disconnects it, removes its saved row and updates activity state. Background expiration suspends live sessions; returning to an active scene resumes them without reconstructing the tab hierarchy. + +```mermaid +flowchart TD + Saved["Saved workspace descriptor"] --> Recent["Recent row with no live session"] + Recent --> Selected["Scene selects workspace"] + Selected --> Published["App publishes one live workspace"] + Published --> Connecting["Connect once"] + Connecting --> Background["All scenes backgrounded"] + Background --> Expired["Expiration suspends live work"] + Expired --> Active["Active scene resumes work"] + Connecting --> Closed["Explicit close disconnects and removes descriptor"] + Active --> Closed +``` + +Saved rows and live workspaces follow different lifetimes; only selection connects and explicit close removes the descriptor. + +Mobile descriptor and live-session lifetimes are separate; a fold or tab switch is not a close operation. + +Desktop continuity includes an interaction constraint as well as a layout cache. `WorkspaceContentView` keeps a dragged pane mounted but temporarily omits its branch from split geometry, disabling hit testing and accessibility for that pane; removing its native drag source would end AppKit's session prematurely. Its pane-level native receiver reads the live `WindowModel` and displayed workspace at drag time, previews the nearest edge on an occupied pane (whole-area replacement on an empty slot), and only mutates the model on drop. `WorkspaceNavigatorView` overlays its native List with one receiver for workspace-section insertion, using measured global row frames; preview boundaries include the dragged row while the move index excludes it. The source session is cleaned up after mutation, and unrelated pasteboard data or a destination that became hidden must not commit a layout change. `WorkspaceLayoutDropTests` cover edge merges, live pane rearrangement, empty slots, stale drags and the changed-destination rejection; `PersistentWorkspaceDeckLayoutTests` cover parked sizes and sidebar insertion indices. + “Keep state” does not mean “keep every view measuring, animating and accepting events forever.” Conversely, unmounting a view does not by itself authorize terminating the work it displays. +For changes at these seams, use focused tests rather than only visual snapshots: `MobileCardTests` measures tag-insensitive card height and container-width columns (including one column at accessibility sizes); `MobileVaultFeatureTests` checks proxy defaults, preserved custom ports and credential validity; and the opt-in, serialized `MobileEditorToolbarTests` exercises Cancel, in-flight Save, failed Save and overflow actions with English and Chinese toolbar labels. The last suite needs `TERMIND_MOBILE_UI_TESTS=1` and nonparallel key-window testing. Shared Assistant presentation tests cover preview shortening; a new projector needs cases for localized wording, approval detail and failure handling as well as the app's native row rendering. + ## Practical extension checklist Before adding or refactoring a UI feature: diff --git a/openwiki/index.md b/openwiki/index.md index 368acb76..eb59557e 100644 --- a/openwiki/index.md +++ b/openwiki/index.md @@ -4,7 +4,7 @@ okf_version: "0.2" # Files -- [Termind Engineering Quickstart](quickstart.md) - A task-oriented guide to finding the right Termind owner, lifecycle boundary, workflow documentation, and focused validation before making a change. +- [Termind Engineering Quickstart](quickstart.md) - Task-oriented routes to Termind's owning layer, startup and shutdown lifetimes, focused tests, and build gates. # Directories diff --git a/openwiki/integrations/index.md b/openwiki/integrations/index.md index 3dcb0dca..428cfb57 100644 --- a/openwiki/integrations/index.md +++ b/openwiki/integrations/index.md @@ -1,3 +1,3 @@ # Files -- [MCP Server, Transfer APIs, and Stdio Bridge](mcp-server-and-bridge.md) - How the macOS-only Termind MCP listener authenticates local clients, executes host tools through external UI authentication, and provides scoped HTTP SFTP transfers. Covers the bundled termind-mcp stdio bridge and MCP session lifecycle. +- [MCP Server, Transfer APIs, and Stdio Bridge](mcp-server-and-bridge.md) - 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. diff --git a/openwiki/integrations/mcp-server-and-bridge.md b/openwiki/integrations/mcp-server-and-bridge.md index 8cba428e..16d6060d 100644 --- a/openwiki/integrations/mcp-server-and-bridge.md +++ b/openwiki/integrations/mcp-server-and-bridge.md @@ -1,8 +1,11 @@ --- type: integration guide title: MCP Server, Transfer APIs, and Stdio Bridge -description: How the macOS-only Termind MCP listener authenticates local clients, executes host tools through external UI authentication, and provides scoped HTTP SFTP transfers. Covers the bundled termind-mcp stdio bridge and MCP session lifecycle. +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-23T10:36:38.039Z sources: - id: openwiki-source-1fc00d0407016efa5a0378eb resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSSHTools.swift @@ -12,6 +15,8 @@ sources: resource: repo://TermindMCPBridge/main.swift - id: openwiki-source-906678adb91c2fce2d3fcaed resource: repo://TFI/App/MobileAppModel.swift + - id: openwiki-source-4dbea0ff2808163cb4ecdd8f + resource: repo://TFM/App/AppModel.swift - id: openwiki-source-b8fca76c89564e16eccfbb53 resource: repo://TFM/App/MCPServerController.swift - id: openwiki-source-76b1cdca4a02038756187f92 @@ -42,15 +47,14 @@ sources: resource: repo://TFMTests/MCPTransferTicketTests.swift - id: openwiki-source-47dc468698b2904f0004ee04 resource: repo://TFMTests/MCPUploadTests.swift -generated: { by: "codex", at: "2026-09-23T01:34:03.251Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # MCP Server, Transfer APIs, and Stdio Bridge -Termind’s built-in MCP endpoint is a **macOS-only, local integration boundary**. The desktop app owns the listener, the tool registry, external authentication UI, audit trail, and transfer lifecycle; an MCP client supplies JSON-RPC requests. The listener accepts only loopback connections and authenticates normal MCP traffic with a device-local Bearer token. It is not a remote-access server and iOS does not start a local MCP listener. +Termind’s built-in MCP **server** is a **macOS-only, local integration boundary**. `TFM/App/AppModel.swift` constructs `MCPServerController`, which owns the listener, tool registry, external authentication UI, audit trail, and transfer lifecycle; an MCP client supplies JSON-RPC requests. The listener accepts only loopback connections and authenticates normal MCP traffic with a device-local Bearer token. It is not a remote-access server. The iOS `MobileAppModel` instead composes a mobile Assistant and ordinary SFTP transfers, not this listener. iOS **does** support the other side of MCP: its Pro-gated remote MCP settings/editor can discover HTTP(S) servers with `MCPClient`, store a bearer credential, configure per-tool permissions, and make their tools available to the Assistant. Do not confuse the mobile outbound client with the desktop inbound server or its `/uploads` and `/downloads` routes. + +The shared `AgentHostServices.live(...)` composition is not a shared MCP listener: macOS passes its resolver, connection pool, authentication registry, and background commands to `MCPServerController`, while iOS passes its host services to `MobileAssistantModel` and separately creates its app SFTP transfer coordinator. The MCP upload/download ticket coordinators and their HTTP byte routes belong to the desktop server, not the mobile transfer coordinator. The endpoint is normally `http://127.0.0.1:7391/mcp`, but the port is configurable. The server is off by default and requires the MCP Server Pro entitlement to enable, configure, rotate its token, or change exported tools. @@ -137,13 +141,38 @@ Tool audit records are registered per MCP session. The UI can show client, tool, Large or binary data does not travel in the 4 MiB MCP body. An MCP call creates a transfer ticket and returns a loopback URL, method, scoped Bearer capability, and identifier; status is queried using the ticket ID through MCP. Ticket creation itself does not open SSH, local files, or the remote source. -Upload and download are separate state machines and separate capabilities, even though they share a global budget of four active slots. Each ticket is bound to the creating MCP session/run, host, remote path, direction and intent; its 256-bit token expires after ten minutes. Waiting and paused tickets expire, while active work is allowed to finish. Each direction permits up to 64 unfinished tickets, retains up to 256 terminal records for 30 minutes, and terminal status remains queryable during that retention interval. Host/session revocation, server stop, token rotation, or disabling the matching direction cancels/revokes work. +Upload 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. ### Upload: `sftp_upload` then `PUT /uploads/` -The upload ticket binds the expected byte count, SHA-256 digest, target path, and overwrite intent. The byte route accepts only its capability and required binary request shape, claims the ticket atomically, and streams with backpressure into a dedicated SFTP operation—no scratch workspace or whole-file staging. The remote write commits only after exact length and incremental digest verification. A duplicate/parallel claim cannot replay committed bytes. +The upload ticket binds the expected byte count (up to 10 GiB), SHA-256 digest, target path, and overwrite intent. Its MCP result includes `upload_id`, `upload_url`, `upload_token`, `expires_at`, method `PUT`, and the initial `Authorization`, `Content-Type`, `Content-Length`, and `Upload-Offset` headers. The byte route accepts only its capability and required binary request shape: no URL query/fragment, a loopback `Origin` if supplied, `application/octet-stream`, decimal suffix `Content-Length`, matching decimal `Upload-Offset` (default `0`), no chunked transfer encoding, and only `Expect: 100-continue` if an expectation is sent. Header/token/offset failures leave the ticket waiting or paused; `100 Continue` is sent only **after** authorization and the atomic claim, before body reading. The route streams bounded chunks with backpressure into a dedicated SFTP operation—no scratch workspace or whole-file staging. A duplicate/parallel claim cannot replay committed bytes. -Interrupted uploads can resume only from the coordinator’s acknowledged remote offset. The client must provide matching `Upload-Offset` and suffix `Content-Length`; the remote prefix is verified before continuation. Digest mismatch, truncation, cancellation, or cleanup failure does not publish a successful remote file. The status may report a possible temporary remote path if cleanup fails. Uploads never overwrite directories; `overwrite` is only meaningful for an existing regular file. +```mermaid +stateDiagram-v2 + [*] --> waiting: create ticket + waiting --> connecting: valid PUT and capacity claim + waiting --> expired: ten minute deadline + waiting --> cancelled: revoke + connecting --> transferring: progress + connecting --> paused: recoverable interruption + transferring --> paused: recoverable interruption + connecting --> succeeded: verified remote commit + transferring --> succeeded: verified remote commit + connecting --> cleaning: revoke with temporary file + transferring --> cleaning: revoke with temporary file + paused --> connecting: valid suffix PUT before expiry + paused --> expired: ten minute deadline + paused --> cleaning: revoke with temporary file + cleaning --> cancelled: cleanup attempted + connecting --> failed: nonresumable failure + transferring --> failed: nonresumable failure + connecting --> cancelled: revoke + transferring --> cancelled: revoke +``` + +Upload ticket states and representative transitions in `MCPUploadCoordinator`; cleanup can also run on a failed attempt before it becomes terminal, and expired/revoked tickets cannot resume. + +Interrupted uploads can resume only from the coordinator’s acknowledged remote `upload_offset`. Poll `sftp_upload_status` in the same live MCP session after an interruption or a lost HTTP response; if `paused` and `resumable`, PUT only the suffix with matching `Upload-Offset` and remaining `Content-Length`. The remote prefix is verified before continuation. A successful remote commit sets `succeeded` even if a late disconnect loses the HTTP response; never repeat a succeeded upload. The remote write commits only after exact length and incremental full-file digest verification. Digest mismatch (`422`), invalid/truncated body (`400`), changed partial (`409`), or timeout (`504`) must not be interpreted as success; recoverable connection loss/timeout or disconnect can pause when not explicitly revoked and before expiry. Cancellation/revocation (`410`) and integrity failures cannot resume. Failure cleanup runs outside the failed HTTP attempt's cancellation context; `temporary_file_may_remain` reports a possible remote partial path if cleanup fails, not the file body. Uploads never overwrite directories; `overwrite` is only meaningful for an existing regular file. ### Download: `sftp_download` then `GET /downloads/` diff --git a/openwiki/operations/build-test-and-release.md b/openwiki/operations/build-test-and-release.md index 90986b8c..aaeb5928 100644 --- a/openwiki/operations/build-test-and-release.md +++ b/openwiki/operations/build-test-and-release.md @@ -1,11 +1,11 @@ --- type: release operations -title: Build, Validation, Localization, and Dependency Release Operations -description: Safe, targeted validation and release procedures for Termind’s Xcode targets, localization catalogs, screenshots, Astro landing page, and pinned AgentKit dependency. +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. tags: [operations, build, testing, localization, release, agentkit, screenshots] verified: - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-ea70eb6c045047448e446296 resource: repo://.gitignore @@ -27,14 +27,30 @@ sources: resource: repo://Termind.xcodeproj/project.pbxproj - id: openwiki-source-105d05d558f14996921a83f6 resource: repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved + - id: openwiki-source-cd81b8b97e761c0120fdfccb + resource: repo://Termind.xcodeproj/xcshareddata/xcschemes/TFI.xcscheme + - id: openwiki-source-60081fe11e88625a130dd44c + resource: repo://Termind.xcodeproj/xcshareddata/xcschemes/TFM.xcscheme + - id: openwiki-source-fffc181d864b6caea779a6f5 + resource: repo://TFITests/MobileAdaptiveLayoutTests.swift + - id: openwiki-source-7341d7b266d976d7aac5d161 + resource: repo://TFITests/MobileEditorToolbarTests.swift + - id: openwiki-source-f4b87eae375fa9241ff8cb35 + resource: repo://TFITests/MobileForwardingRenderingTests.swift + - id: openwiki-source-96b0d4f1528e0e0e4e7b6a12 + resource: repo://TFITests/MobileHostIntegrationRenderingTests.swift + - id: openwiki-source-1068a19b8ad42f734f4b4bb6 + resource: repo://TFITests/MobileSavedNameRenderingTests.swift - id: openwiki-source-793d7861000adc19f0c3df01 resource: repo://TFMTests/AppLanguageTests.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-22T01:13:21.371Z" } +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- -# Build, Validation, Localization, and Dependency Release Operations +# Build, Test, and Release This page is the operational playbook for proving a change without accidentally changing the dependency graph or committing local artifacts. The repository has one Xcode project with the macOS `TFM` and iPhone/iPad `TFI` schemes, shared-framework tests in `FrameworkTests/`, and platform tests in `TFMTests/` and `TFITests/`. The Astro landing page is a separate Node workspace under `LandingPage/`. @@ -79,7 +95,7 @@ Constrain a run when a focused suite directly establishes the changed contract, xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test -only-testing:TFMTests/AppLanguageTests ``` -Use the matching mobile scheme and a concrete simulator for `TFITests` work. Typical focused choices are the test file that names the changed feature, `TFMTests/ArchitectureBoundaryTests.swift` for dependency placement, and `TFMTests/AppLanguageTests.swift` for language-selection/catalog behavior. Do not use an unrelated focused test as a substitute for the affected default suite. +Use the matching mobile scheme and a concrete simulator for `TFITests` work. The `TFM` test action includes `TFMTests` and `FrameworkTests`; `TFI` includes `TFITests` and `FrameworkTests`. Typical focused choices are the test file that names the changed feature, `TFMTests/ArchitectureBoundaryTests.swift` for dependency placement, and `TFMTests/AppLanguageTests.swift` for language-selection/catalog behavior. Do not use an unrelated focused test as a substitute for the affected default suite. Check which suites actually ran: a passing default command does not prove a disabled opt-in suite passed. ### Formatting is a strict check @@ -103,6 +119,30 @@ TEST_RUNNER_TERMIND_WINDOW_TESTS=1 xcodebuild -project Termind.xcodeproj -scheme 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. +### Mobile key-window integration tests + +Do not treat mobile integration suites as part of routine default coverage. Suites that take UIKit's process-wide key-window/presentation state, including `MobileEditorToolbarTests`, `MobileForwardingRenderingTests`, `MobileHostIntegrationRenderingTests`, and `MobileSavedNameRenderingTests`, use a suite-level `TERMIND_MOBILE_UI_TESTS=1` gate and serialization. To run a changed suite, use an installed iPhone or iPad simulator, disable parallel testing, and narrow the selection: + +```sh +TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1 xcodebuild -project Termind.xcodeproj -scheme TFI -destination 'platform=iOS Simulator,name=' -onlyUsePackageVersionsFromResolvedFile -parallel-testing-enabled NO test -only-testing:TFITests/MobileEditorToolbarTests +``` + +`TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1` is the command-line opt-in; Xcode forwards it to the test host as `TERMIND_MOBILE_UI_TESTS=1`. `MobileAdaptiveLayoutTests` is a separate serialized, **ungated** suite: it mounts `MobileRootView` in a temporary key `UIWindow`, resizes size classes and widths, checks tab and navigation identity, drafts, scroll/focus/marked text, and attaches captures across English and both Chinese locales. Its fixture restores the prior key window after each run. Because it also uses process-wide UIKit state, target it narrowly with `-parallel-testing-enabled NO` when investigating adaptive behavior rather than assuming it has the suite-level opt-in: + +```sh +xcodebuild -project Termind.xcodeproj -scheme TFI -destination 'platform=iOS Simulator,name=' -onlyUsePackageVersionsFromResolvedFile -parallel-testing-enabled NO test -only-testing:TFITests/MobileAdaptiveLayoutTests +``` + +### StoreKit authorization gate + +`StoreKitTrialTests` is serialized and skipped unless its host has `TERMIND_STOREKIT_TESTS=1`; it requires manual authorization, not just a successful default macOS test run. When authorized, run it alone with the resolved graph and set the host environment explicitly (in Xcode's Test action, use `TERMIND_STOREKIT_TESTS=1`): + +```sh +TERMIND_STOREKIT_TESTS=1 xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile test -only-testing:TFMTests/StoreKitTrialTests +``` + +The suite creates and resets an `SKTestSession` against `StoreKit/Termind.storekit`, clears transactions around each fixture, and checks annual trial entitlement and restore, lifetime precedence, pending Ask to Buy, cancellation/network failures, unverified transactions, and invalid or missing introductory-offer configurations. These local StoreKit tests do not replace storefront/Sandbox verification. + For an isolated interactive desktop demo, use a supported scene and one of the three supported languages: ```sh @@ -183,8 +223,9 @@ Do not skip the release or resolve steps: a project-file bump alone does not est 3. Run strict Swift format lint for Swift changes. 4. Run `Scripts/check-zh-localization.sh` for every commit; complete both Chinese translations and run `AppLanguageTests` when localization behavior changes. 5. For landing-page changes, run `cd LandingPage && npm ci && npm run build` and inspect English/Chinese routes. -6. Run visible-window tests only with explicit opt-in and a narrow suite; regenerate marketing captures only through their dedicated scripts when product imagery changes. -7. For AgentKit work, complete release → minimum-version bump → re-resolve, and commit both dependency files. -8. Inspect the staged diff for secrets, local environment files, derived data, build output, and accidental lock/artifact churn before committing. +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. +8. For AgentKit work, complete release → minimum-version bump → re-resolve, and commit both dependency files. +9. Inspect the staged diff for secrets, local environment files, derived data, build output, and accidental lock/artifact churn before committing. CloudKit production deployment and signed-device delivery are separate release evidence, not consequences of a successful local build. Use [CloudKit Schema Deployment and Signed-Device Release Readiness](/openwiki/operations/cloudkit-release-readiness.md) for that matrix. Storefront metadata and Sandbox validation live in [App Store Commerce Configuration and Release Verification](/openwiki/operations/storefront-commerce-release.md); capture, Figma export, and icon checks live in [Marketing Assets, Screenshot Production, Figma Exports, and App Icons](/openwiki/operations/marketing-assets-and-app-icons.md); historical transport performance methodology lives in [Port Forwarding Benchmark Design, Results, and Reproduction](/openwiki/operations/port-forwarding-benchmarks.md). diff --git a/openwiki/operations/index.md b/openwiki/operations/index.md index 1f444cc0..0ce0f202 100644 --- a/openwiki/operations/index.md +++ b/openwiki/operations/index.md @@ -1,6 +1,6 @@ # Files -- [Build, Validation, Localization, and Dependency Release Operations](build-test-and-release.md) - Safe, targeted validation and release procedures for Termind’s Xcode targets, localization catalogs, screenshots, Astro landing page, and pinned AgentKit dependency. +- [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. - [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. diff --git a/openwiki/quickstart.md b/openwiki/quickstart.md index d7402ac4..bce5269e 100644 --- a/openwiki/quickstart.md +++ b/openwiki/quickstart.md @@ -1,8 +1,11 @@ --- type: engineering quickstart title: Termind Engineering Quickstart -description: A task-oriented guide to finding the right Termind owner, lifecycle boundary, workflow documentation, and focused validation before making a change. +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-23T10:36:38.039Z sources: - id: openwiki-source-8037e2358a2c4f9b2c722a11 resource: repo://AGENTS.md @@ -12,82 +15,64 @@ sources: resource: repo://Termind.xcodeproj/project.pbxproj - id: openwiki-source-105d05d558f14996921a83f6 resource: repo://Termind.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved + - id: openwiki-source-906678adb91c2fce2d3fcaed + resource: repo://TFI/App/MobileAppModel.swift - id: openwiki-source-c8d832474c03f5ebad7b0578 resource: repo://TFI/App/MobileRootView.swift - id: openwiki-source-6c9f797fc6a1e7ce639b72b8 resource: repo://TFI/App/TermindIOSApp.swift + - id: openwiki-source-7341d7b266d976d7aac5d161 + resource: repo://TFITests/MobileEditorToolbarTests.swift + - id: openwiki-source-4dbea0ff2808163cb4ecdd8f + resource: repo://TFM/App/AppModel.swift - id: openwiki-source-6570374eaac2e0278fa84640 resource: repo://TFM/App/TermindApp.swift - id: openwiki-source-22b9fca540c3029c5ace451e resource: repo://TFM/Features/Workspaces/WindowModel.swift + - id: openwiki-source-73c75477db0674192248aa00 + resource: repo://TFMTests/AppTerminationTests.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift -generated: { by: "omp", at: "2026-09-22T03:23:14.035Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z + - id: openwiki-source-0dd012e3740bcc348fc36ccb + resource: repo://TFMTests/StoreKitTrialTests.swift +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Termind Engineering Quickstart -Termind is one Xcode project with two native products: `TFM` for macOS and `TFI` for iPhone/iPad. They compose shared static frameworks, but platform UI and lifecycle remain app-owned. Start from the task you intend to change, identify the state and dependency owner, then use the focused tests that protect that boundary. Source and tests are authoritative. Read [Cross-Cutting Engineering Invariants](/openwiki/architecture/engineering-invariants.md) for the exhaustive safety contract, then use the routed specialist page for mechanisms, release operations, and historical benchmark constraints. +Termind is one Xcode project with native `TFM` (macOS) and `TFI` (iPhone/iPad) products over shared frameworks; platform UI and lifecycle remain app-owned. Source and tests are authoritative. Before changing an ownership boundary, read [Cross-Cutting Engineering Invariants](/openwiki/architecture/engineering-invariants.md) and the narrowest topic page below. -## Explore modules and directories +## Find the owner -Start with the [Module and Directory Architecture Map](/openwiki/architecture/module-map.md) for module ownership and dependency diagrams. Its companion guides cover at least second-level functional directories, explicitly identify flat modules, and distinguish directory containment from runtime ownership: +| Change | Route and focused check | +| --- | --- | +| Module placement, imports, nested directories, or shared resources | [Module and Directory Architecture Map](/openwiki/architecture/module-map.md), [Shared Framework Directory Responsibilities](/openwiki/architecture/shared-module-directories.md), [Native App Directory Responsibilities](/openwiki/architecture/native-app-directories.md), and [Supporting Products, Packages, and Tooling](/openwiki/architecture/supporting-system-directories.md); run `ArchitectureBoundaryTests` for dependency changes. | +| Composition, startup failure, window/scene state, backgrounding, quit | [Platform Runtime, App Composition, and Lifetimes](/openwiki/architecture/platform-runtime.md); use `AppTerminationTests`, `MobileAppTests`, or `MobileForwardingLifecycleTests` for the changed lifetime. | +| Desktop Navigator, sidebar, workspaces, Vault, Assistant layout | [TFM Desktop UI Architecture](/openwiki/architecture/desktop-ui.md); target window/navigation or layout tests. | +| Mobile tabs, scene routes, cards, editors, terminal continuity | [TFI Mobile UI Architecture](/openwiki/architecture/mobile-ui.md); target `MobileAdaptiveLayoutTests`, `MobileNavigationParityTests`, or the relevant feature test. | +| Shared UI conventions, fields, tokens, accessibility | [UI Design Principles and Shared Presentation Boundaries](/openwiki/concepts/ui-design-principles.md); check platform renderings and `ArchitectureBoundaryTests`. | +| SSH/Telnet, credentials, routes, host-key trust, session cleanup | [SSH, Telnet, Trust, and Workspace Session Lifecycle](/openwiki/workflows/ssh-session-lifecycle.md); run connection, trust, authentication, and session tests. For channel admission and backpressure see [SSH Multiplexing and I/O Scheduling](/openwiki/concepts/ssh-multiplexing-and-scheduling.md). | +| 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. | +| 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. | +| 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. | -- [Shared Framework Directory Responsibilities](/openwiki/architecture/shared-module-directories.md): the six frameworks and shared bundle resources. -- [Native App Directory Responsibilities](/openwiki/architecture/native-app-directories.md): TFM/TFI application, feature, infrastructure, platform, UI, and resource areas. -- [Supporting Products, Packages, and Tooling](/openwiki/architecture/supporting-system-directories.md): AgentKit, bridge, widgets, tests, benchmarks, website, assets, and automation. +## Lifetime and change boundaries -## Before editing +`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. -1. **Read the cross-cutting invariants and the narrowest routing page below**, then follow their cited code and tests. Do not use this page as a substitute for the detailed workflow. -2. **Locate the owner before adding an import.** `TermindDomain` holds portable values and rules; `TermindApplication` holds ports, use cases, and cross-feature policy; Persistence owns all SwiftData models and container construction; infrastructure implements concrete services; `TFM` and `TFI` own native UI, composition, and lifecycle. Shared frameworks must not depend on either app target. -3. **Classify the lifetime.** App-wide services and durable stores are shared; desktop navigation and workspaces are window-local; mobile navigation is scene-local; an SSH/SFTP transport belongs to the workspace/session that opened it. Do not turn transient connections or credentials into restored state. -4. **Keep secrets and remote behavior at their existing boundaries.** Metadata can be persisted, while secrets are referenced through Keychain-backed storage. SSH/SFTP, host-key trust, and transport ownership belong on the Termind side of the host-neutral AgentKit boundary. -5. **Plan the regression check alongside the change.** Add or update the focused test that demonstrates the contract, then run the appropriate build/test command using the resolved package graph. +`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. -## Task-routing map +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. -| If you are changing… | Start here | Also inspect | Focused validation | -| --- | --- | --- | --- | -| Finding what a module or nested directory owns, or understanding how modules collaborate | [Module and Directory Architecture Map](/openwiki/architecture/module-map.md) | Shared-framework, native-app, and supporting-system directory guides | Follow the owning feature's focused tests; use architecture checks for dependency changes | -| App startup, dependency assembly, window/scene behavior, backgrounding, or shutdown | [Platform Runtime, App Composition, and Lifetimes](/openwiki/architecture/platform-runtime.md) | `TFM/App/TermindApp.swift`, `TFI/App/TermindIOSApp.swift` | Relevant `TFMTests` or `TFITests` lifecycle/window suite | -| A module import, framework placement, SwiftData model, shared resource, or AgentKit-facing API | [System Boundaries and Dependency Ownership](/openwiki/architecture/system-boundaries.md) | `TFMTests/ArchitectureBoundaryTests.swift` and the owning composition root | `ArchitectureBoundaryTests` plus the affected feature tests | -| TFM window chrome, Navigator modes, split panes, persistent workspaces, Vault editors, or desktop Assistant rendering | [TFM Desktop UI Architecture](/openwiki/architecture/desktop-ui.md) | Component and ownership diagrams; [UI Design Principles](/openwiki/concepts/ui-design-principles.md) | Window/sidebar, workspace layout, responsive editor and transcript tests | -| TFI feature tabs, scene routes, mobile toolbars, adaptive regions, terminal continuity, or composer focus | [TFI Mobile UI Architecture](/openwiki/architecture/mobile-ui.md) | Scene-versus-runtime ownership and native surface identity across layout changes | `MobileAdaptiveLayoutTests` plus scene, workspace and Assistant behavior tests | -| Shared form fields, presentation values, visual tokens, collection interaction, accessibility, or cross-platform UI reuse | [UI Design Principles and Shared Presentation Boundaries](/openwiki/concepts/ui-design-principles.md) | Platform-specific owners; architecture restrictions on shared presentation and native adapters | `ArchitectureBoundaryTests`, input/presentation tests, and targeted multilingual rendering checks | -| SSH, Telnet, proxy/jump routing, trust prompts, credentials, or workspace reconnect | [SSH, Telnet, Trust, and Workspace Session Lifecycle](/openwiki/workflows/ssh-session-lifecycle.md) | Remote Infrastructure callers and the owning session feature | SSH preparation, host-key, authentication, journey, and session tests | -| Terminal services, metrics, port forwarding, channel limits, or shared remote transport policy | [Remote Services: Terminal, Metrics, and Port Forwarding](/openwiki/concepts/remote-services-and-forwarding.md) | [Port Forwarding Benchmarks](/openwiki/operations/port-forwarding-benchmarks.md) for measurement semantics | The relevant terminal, metrics, or forwarding suite | -| SSH connection reuse, session-channel admission, exec/SFTP queue turns, libssh2 retries, or backpressure | [SSH Multiplexing, Channel Admission, and I/O Scheduling](/openwiki/concepts/ssh-multiplexing-and-scheduling.md) | Separate file permits, channel leases, owner queues, and physical pools before changing a limit | `SSHMaxSessionsPolicyTests`, `SSHForwardingPumpTests`, and the affected Agent/SFTP tests | -| Shell bootstrap, Bash/Zsh/Fish hooks, OSC parsing, cwd/home, command history, or prompt/draft readiness | [Shell Integration: Bootstrap, OSC Events, and Terminal State](/openwiki/concepts/shell-integration.md) | Preserve desktop/mobile differences in event delivery and prompt readiness | `ShellIntegrationBootstrapTests`, `CommandHistoryTests`, and mobile command-generator tests | -| Forwarding pool warm-up, local/SOCKS distribution, remote listeners, silent recovery, or listener retirement | [Port Forwarding: Multi-Connection Pool and Flow Dispatch](/openwiki/workflows/port-forwarding-pool-and-dispatch.md) | Distinguish auxiliary repair from whole-context recovery; use the benchmark guide for measurements | Pump and reconnect suites; opt-in forwarding wire tests when the fixture is available | -| SFTP browsing, transfer scheduling/topology, conflict behavior, resume, external editing, or cleanup | [SFTP Transfer, Scheduling, and External Edit Workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md) | The feature owner plus `SFTPTransferContext`/scheduler callers | Matching SFTP transfer, edit, conflict, or mobile SFTP tests | -| Assistant turns, approval, host tools, skills, scratch space, agent persistence, or Hermes memory | [Assistant, Agent Runtime, Skills, and Memory](/openwiki/concepts/agent-runtime-and-assistant.md) | AgentKit boundary in [System Boundaries](/openwiki/architecture/system-boundaries.md) | Agent, approval, scratch, skill, or memory suites in `TFMTests`/`FrameworkTests` | -| Hosts, Vault records, migrations, Keychain references, repositories, or data compatibility | [Persistent Data, Migrations, and Secret Boundaries](/openwiki/concepts/persistence-and-secrets.md) | Persistence compatibility tests and schema owners | Persistence, repository, secret, and migration tests | -| CloudKit selection, sync lifecycle, journals, account transitions, settings, or secret-upload authorization | [Settings, Vault, Metrics, and Cloud Sync Workflow](/openwiki/workflows/settings-and-cloud-sync.md) | [CloudKit Release Readiness](/openwiki/operations/cloudkit-release-readiness.md) for deployment/device checks | Sync lifecycle/coordinator and affected feature tests | -| macOS MCP server, external authentication, transfers, bearer tokens, or `termind-mcp` | [MCP Server, Transfer APIs, and Stdio Bridge](/openwiki/integrations/mcp-server-and-bridge.md) | `TermindMCPBridge/` and MCP server/transfer tests | MCP token, server-session, upload, download, and bridge tests | -| Entitlements, StoreKit, localization, widgets, screenshots, or marketing/landing-page work | [Commerce, Localization, and Product Surfaces](/openwiki/concepts/commerce-localization-and-product-surfaces.md) | [Storefront Commerce Release](/openwiki/operations/storefront-commerce-release.md), [Marketing Assets and App Icons](/openwiki/operations/marketing-assets-and-app-icons.md), and [Build, Test, and Release](/openwiki/operations/build-test-and-release.md) | Localization check, relevant app tests, screenshots, Sandbox checks, or `npm run build` | -| Choosing a regression seam or a representative test across framework and platform targets | [Testing Strategy and Behavioral Boundaries](/openwiki/testing/behavioral-boundaries-and-fixtures.md) | Existing tests nearest the feature | Narrow behavioral test first, then affected target suite | +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. -## The ownership decisions that prevent most regressions +## Focused validation -### Put behavior with the correct layer - -A feature model should depend on an injected port or service, not construct a database, Keychain store, SSH client, or network implementation because it is nearby. `ArchitectureBoundaryTests` actively rejects lower-layer platform/storage/transport imports, duplicate AgentKit runtime types, and SwiftData models outside Persistence. Treat a boundary-test failure as an architectural error, not a test to work around. - -AgentKit is a separately versioned remote package. It owns the generic agent loop, approval gate, provider adapters, MCP client, and host-neutral tools; Termind owns SSH/SFTP tools and registers them additively. A change that genuinely spans the package boundary must be released in `../AgentKit`, then update AgentKit's `minimumVersion` in `Termind.xcodeproj/project.pbxproj` and the resolved revision together. A sibling working-tree edit is not used by Xcode's resolved build. - -### Preserve runtime and failure boundaries - -The macOS app constructs its model container and app-wide services in `TermindApp`; failure to open the local database terminates startup instead of silently substituting a blank store. The iOS app creates one `MobileAppModel` at startup and shows an unavailable-data view when that composition fails. Test and screenshot modes explicitly select in-memory/test composition rather than modifying production persistence behavior. - -Remote trust and authentication are part of the real connection attempt: route preparation supplies a snapshot, while Remote Infrastructure completes socket, handshake, host-key authorization, and authentication. The feature that started the connection retains its journey UI, retry lifetime, and workspace/session ownership. This is why a trust, route, or credential change should be traced through both its shared remote policy and the initiating feature rather than patched in a single screen. - -## Validation baseline - -Use the narrowest test that proves the changed contract, followed by the affected product suite when risk warrants it. Keep `-onlyUsePackageVersionsFromResolvedFile`; without it an ordinary build can resolve a dependency revision different from `Package.resolved`. +Run the nearest behavioral regression first, then the relevant product suite. Always keep `-onlyUsePackageVersionsFromResolvedFile` so ordinary builds do not silently move the resolved dependency graph: ```sh xcodebuild -project Termind.xcodeproj -scheme TFM -destination 'platform=macOS' -onlyUsePackageVersionsFromResolvedFile build @@ -97,15 +82,6 @@ xcrun swift-format lint --strict --recursive Frameworks TFM TFI FrameworkTests T Scripts/check-zh-localization.sh ``` -Use an installed iPhone or iPad simulator destination for `TFI` tests. Keep visible-window macOS tests opt-in with `TEST_RUNNER_TERMIND_WINDOW_TESTS=1` and a narrow `-only-testing` selection; routine checks should stay headless. UI string changes require completed `zh-Hans` and `zh-Hant` translations in `Frameworks/Resources/Localizable.xcstrings`; landing-page work is separately validated with `cd LandingPage && npm ci && npm run build`. +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/`. Mobile key-window integration suites require `TEST_RUNNER_TERMIND_MOBILE_UI_TESTS=1`, `-parallel-testing-enabled NO`, and a narrow `-only-testing:TFITests/`. 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. -## Change checklist - -- Identify the domain and owner in the routing map; read the detailed page before implementing. -- Trace callers and callees across the integration boundary; include lifecycle, retry/cancellation, persistence, and cleanup paths—not only the happy path. -- Preserve the contracts in the routed OpenWiki page and update `ArchitectureBoundaryTests` when an intentional ownership rule changes; generated pages are refreshed through the OpenWiki lifecycle rather than hand-maintained as a parallel architecture log. -- Add a targeted regression test at the layer where the behavior is observable, and run the relevant focused check. -- Run resolved-package product validation, strict formatting, and the localization gate appropriate to the changed surface. -- Inspect the diff for secret material, accidental generated artifacts, unintended `Package.resolved` churn, and cross-layer imports. - -For general commands, localization, and the AgentKit release procedure, continue with [Build, Test, and Release](/openwiki/operations/build-test-and-release.md). Use the dedicated operations pages for CloudKit deployment, App Store commerce, marketing/assets/icons, and historical forwarding benchmarks. +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. diff --git a/openwiki/testing/behavioral-boundaries-and-fixtures.md b/openwiki/testing/behavioral-boundaries-and-fixtures.md index faee1810..68dfff72 100644 --- a/openwiki/testing/behavioral-boundaries-and-fixtures.md +++ b/openwiki/testing/behavioral-boundaries-and-fixtures.md @@ -3,6 +3,9 @@ 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-23T10:36:38.039Z sources: - id: openwiki-source-8037e2358a2c4f9b2c722a11 resource: repo://AGENTS.md @@ -30,36 +33,45 @@ sources: resource: repo://FrameworkTests/SSHInteractionPolicyTests.swift - id: openwiki-source-350d4a794cfef67e406ddf9b resource: repo://TFI/Infrastructure/MobileWorkspaceStore.swift + - id: openwiki-source-34542e0f07e1650e098824c7 + resource: repo://TFI/Platform/MobileBackgroundController.swift - id: openwiki-source-b822b041afbf829d09a8555a resource: repo://TFITests/MobileAppTests.swift - id: openwiki-source-a154b5d36ec59496392d45e4 resource: repo://TFITests/MobileAssistantTests.swift + - id: openwiki-source-c9618f94f83d3b529a9860e1 + resource: repo://TFITests/MobileBackgroundControllerTests.swift - id: openwiki-source-7a29627adf93e3da4a56dd5d resource: repo://TFITests/MobileCardRenderingTests.swift + - id: openwiki-source-c32ed562101f11a0c3c89663 + resource: repo://TFITests/MobileCardTests.swift - id: openwiki-source-16ec96bd78162e7e62effd0e resource: repo://TFITests/MobileConnectionPickerTests.swift + - id: openwiki-source-7341d7b266d976d7aac5d161 + resource: repo://TFITests/MobileEditorToolbarTests.swift - id: openwiki-source-9b78a7e39bfa08bea5192722 resource: repo://TFITests/MobileWorkspaceStoreTests.swift - id: openwiki-source-cfbc34def649c94f760c5695 resource: repo://TFMTests/AgentHostAuthenticationTests.swift - id: openwiki-source-715de8d16be5a3d06ae915ad resource: repo://TFMTests/AgentPersistenceTests.swift + - id: openwiki-source-23ab3fe73660b171f78763a4 + resource: repo://TFMTests/AgentToolPresentationTests.swift - id: openwiki-source-d3d065330c730839f5cc6112 resource: repo://TFMTests/ArchitectureBoundaryTests.swift - id: openwiki-source-78797a18dd3153d23a2c42e2 resource: repo://TFMTests/ChatComposerStateTests.swift - id: openwiki-source-c15cd5bef4646aaf64df407e resource: repo://TFMTests/ConnectionHistoryTests.swift + - id: openwiki-source-47dc468698b2904f0004ee04 + resource: repo://TFMTests/MCPUploadTests.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-23T03:34:06.838Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # Testing Strategy and Behavioral Boundaries @@ -103,9 +115,11 @@ A message edit inside one run needs a fixture such as `opening → assistant/too - Shared `AgentReplayPersistenceTests` parameterizes the first real replacement snapshot as `.failed` or `.interrupted`. It checks the single surviving message/run/replay backing and reloads with a new `ModelContext` and repository over the same in-memory container to verify provenance, terminal state, failure and frozen context. This is fresh-context visibility, not a disk-relaunch test. - `ChatComposerStateTests.editingSteeringKeepsCompactedSameRunPrefixAndLegacyToolOwnership` checks full visible-prefix retention even when model history is compacted, alongside tool cards, title, plans, compaction records/marks and run-summary chronology through `runStarted`/`runFinished`. Mobile's `swiftDataRestoreAndEditPreserveASameRunPrefixOnMobile` exercises the same repository/store/operations path and compares live and restored message ownership. -Application error and timing fixtures complement those real SwiftData checks. `AssistantConversationOperationsTests` proves an invalid replacement never reaches persistence and a rejecting truncation leaves both visible and model history unchanged. Controller tests hold preparation at a memory barrier, cancel after a successful edit, and assert interrupted real-run provenance replaces staging. These seams do not inject disk-full or read-only failures into the real SwiftData transaction; its rollback path must not be described as fault-injection tested. +Application error and timing fixtures complement those real SwiftData checks. `AssistantConversationOperationsTests.invalidReplacementNeverCallsPersistence` rejects a non-user replacement without invoking truncation; `truncationFailureLeavesInMemoryHistoryUnchanged` throws from a rejecting repository and keeps both visible messages and transcript unchanged. In `AssistantExecutionControllerTests`, `manualCompactionIsRefusedWhileRunPreparationIsActive` holds the memory snapshot barrier and verifies no compaction activity starts; `editFailurePreservesHistoryButUsesTheSynchronouslyCapturedReplacement` checks that rejected truncation preserves history while the attempted replacement retains captured host and plan context. `cancellationAfterSuccessfulEditAdoptsTheInterruptedRunProvenance` holds memory preparation after the edit commits, then checks that the interrupted real run owns the replacement rather than its staging ID. These port-level failure seams do not inject disk-full or read-only failure into a real SwiftData transaction; its rollback path must not be described as fault-injection tested. -Use the boundary that the assertion needs as its wait condition. Captured missing-model/credential failure projects `.failed` before launching a separate asynchronous repository save, so `!isPreparingAgentRun` is not a save barrier. The controller fixture's `waitUntilSnapshot(state:)` checks existing snapshots or suspends an actor-owned continuation; `save` records the snapshot before resuming matching waiters. The missing-credential and navigation tests retain both live-state and repository-state assertions and wait for the latter explicitly. This does not change production failure ordering or prove durability across the separate queued-runtime immediate-stop handoff. +Use the boundary that the assertion needs as its wait condition. `beginFailedRunPersistence` constructs a failed snapshot and starts a repository-save task, but keeps preparation active and does **not** project `.failed` into the live conversation until `save` succeeds; on save failure it appends an error message instead. `missingModelFailureStaysOwnedUntilSaveAndAllCancellationPathsJoinIt` and `missingCredentialAfterMemoryPreparationProjectsOnlyAfterSaveCompletes` block the first save and verify stop, cancellation, and projection ordering. `credentialAddedAfterCaptureDoesNotReviveTheTurn` and `selectingAnotherConversationDoesNotCancelPreparation` check live `.failed` after preparation and additionally wait for the recording repository's failed snapshot. The fixture's `waitUntilSnapshot(state:)` checks existing snapshots or suspends an actor-owned continuation; `save` records the attempt before resuming matching waiters. A recorded attempt is **not** proof of a completed save: use `completedSnapshots` or the joined preparation where completion is the contract. This does not prove durability across the separate queued-runtime immediate-stop handoff. + +The controller's `failedReplacementSaveCannotBeSupersededOrMutatedBeforeItCompletes` holds a failed-run save after truncation: edit/fork cannot bypass the pending preparation, and after release the failed real run takes the replacement's ownership. `failedSnapshotSaveRetiresPreparationWithoutAdoptingStaging` injects a save error at the repository port instead: the staging owner remains, no failed summary is adopted, an assistant error appears, and no save completes. When changing edit/cancel ordering, also run `cancelledPreparedEditCannotEnterHistoryMutation`, `supersededPreparedEditCannotEnterHistoryMutation`, `cancellationDuringEditJoinsHistoryWorkBeforeRecordingInterruption`, and `supersededPreparationIgnoresAnOlderCancellationCompletion` to keep stale operations from mutating the new history. ### CloudKit compatibility: test prohibited uploads, not just decoding @@ -142,6 +156,10 @@ SFTP transfer tests use a controlled `TransferChannelHarness`, a `TransferChanne Those tests are intentionally actor-driven and use polling only to wait for observable harness state. Prefer this style for races: hold the transfer at a known point, make the ownership transition, then release it and assert the terminal state and disconnect count. +For tool-card changes use `AgentToolPresentationTests`: the registered tool's argument projection appears in approval detail (including submitted command/input, not a claimed secret-redaction guarantee), while unknown tools get generic fields. Check the composed AgentKit-plus-Termind presenter ID catalog for collisions, restored and legacy cards for equivalent detail, and old descriptor metadata for safe defaults before relying on a new presentation field. Batch and long-output fixtures cover mixed lifecycle states, Unicode preview bounds and full-copy content; avoid replacing structured detail with an untested JSON string. + +For MCP upload changes use `MCPUploadTests` with the real coordinator and streaming operation, a fake SFTP client and controlled clock. Protect ticket/run scope and capacity, acknowledged-offset resume and full digest, bounded streaming/backpressure, timeout/cancellation and cleanup residue, revocation on disable, conflict policy and queryable terminal status. `actualHTTPRouteStreamsAboveTheMCPBodyLimit` additionally runs a loopback HTTP server for fresh and resumed bodies larger than the ordinary MCP limit; a passing fake SFTP upload does not establish interoperability with a real remote server. + ### Mobile: app state, scenes, and device-local restoration `TFITests` owns `MobileAppModel` composition and mobile scene behavior. Mobile app tests build `MobileAppModel(inMemory: true)` or supply dependency seams, which permits assertions over the actual shared schema and repositories without using the user's database or Keychain. Representative tests verify that scenes share durable conversations while navigation, selected conversation, and composer drafts stay scene-local; shared SwiftData history is observable from fresh repositories over the same container. @@ -150,6 +168,10 @@ External connection URLs are another ownership boundary: opening one creates an `MobileWorkspaceStoreTests` protects the device-local restoration format. The store contains connection intent only—workspace descriptor identity, host reference, title and kind—not credentials, commands, duplicate indices or live session state. It migrates legacy arrays into the versioned snapshot while preserving IDs, titles and kinds and discarding legacy indices. If bytes are malformed, unknown-version, or invalid (including duplicate IDs), loading and later saving fail while the original bytes remain untouched; a successful load is required before replacement. Add a fixture for every format transition and for corruption behavior, because silently replacing unreadable restoration data with an empty list loses recoverable user state. +`MobileBackgroundControllerTests` replaces UIKit's background-task platform to drive expiration synchronously. The tests check stale/repeated callbacks end each lease at most once, reentrant expiration during `begin` retires the returned old identifier without overwriting a newly begun lease, and an invalid identifier expires once without an `end` call. Use these for lease mechanics; `MobileAppTests` covers foreground recovery and retired workspace callbacks at the app boundary. + +`MobileCardTests` exercises card policy offscreen: adaptive column thresholds and accessibility sizing, bounded tag display and measured stable card heights, plus in-memory app/repository checks for saved-host timestamps and draft color persistence. Use `MobileCardRenderingTests` or the affected mobile rendering suite for visual output instead of making basic layout-policy tests acquire a key window. + ## Fixture design rules 1. **Inject at the owner boundary.** Use `MobileAppDependencies.testing`, in-memory repositories, `MemoryHostSecretStore`, a responder closure, or a protocol test client to replace I/O while retaining the production coordinator/model. Do not duplicate production policy inside a mock. @@ -168,7 +190,7 @@ 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. A visual change still needs behavior-appropriate coverage: an offscreen test for state/policy, a visible-window test for focus/presentation when applicable, and screenshot/marketing capture only where that workflow owns the deliverable. +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/` 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. ## Change-to-regression matrix @@ -180,7 +202,10 @@ In Xcode, set `TERMIND_WINDOW_TESTS=1` in the Test action environment. Existing | 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. | | SSH credentials, prompts, host trust, or agent authentication | Authentication and interaction-policy fixtures | Ephemeral secrets stay ephemeral, prompt scope/order/coalescing is correct, forbidden work stays noninteractive, and secrets are invalidated after use. | | SSH/SFTP transfer scheduling or pane/session teardown | `SFTPTransferContextTests` with a controlled channel harness | Concurrency bounds hold, background transfer ownership survives UI teardown, cancellation cleans up, and fallback does not invite interaction. | -| Mobile workspace, scene, restoration, or background lifecycle | `MobileAppTests` and `MobileWorkspaceStoreTests` | State is shared or local at the intended scope, external sessions remain ephemeral, restoration is safe, and callbacks cannot revive retired state. | +| Mobile workspace, scene, restoration, or background lifecycle | `MobileAppTests`, `MobileWorkspaceStoreTests`, and `MobileBackgroundControllerTests` | State is shared or local at the intended scope, external sessions remain ephemeral, restoration is safe, leases retire once, and callbacks cannot revive retired state. | +| 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. | ## Execution strategy diff --git a/openwiki/workflows/index.md b/openwiki/workflows/index.md index 35122157..aa19c666 100644 --- a/openwiki/workflows/index.md +++ b/openwiki/workflows/index.md @@ -2,5 +2,5 @@ - [Port Forwarding: Multi-Connection Pool and Flow Dispatch](port-forwarding-pool-and-dispatch.md) - Trace forwarding rules through Host-scoped intent, primary and auxiliary SSH workers, local/SOCKS socket dispatch, remote-listener ownership, bounded flow pumps, silent recovery, and ordered teardown. - [Settings, Vault, Metrics, and Cloud Sync Workflow](settings-and-cloud-sync.md) - How Termind independently synchronizes Vault, Settings, and Metrics through CloudKit, including lifecycle gates, durable journals, account and environment transitions, conflict handling, and AI-secret upload authorization. -- [SFTP Transfer, Scheduling, and External Edit Workflow](sftp-transfer-and-external-edit.md) - How SFTP browser operations become scheduled transfers, choose an SSH topology, resolve conflicts and resume safely, and support explicit external-file editing without durable staging or replay. +- [SFTP Transfer, Scheduling, and External Edit Workflow](sftp-transfer-and-external-edit.md) - How browser SFTP jobs are scheduled and resumed, how Agent SFTP leases reuse authenticated SSH connections, and how MCP uploads and external edits remain separate workflows. - [SSH, Telnet, Trust, and Workspace Session Lifecycle](ssh-session-lifecycle.md) - Traces how Termind prepares SSH and Telnet connections, routes them through proxies and jump hosts, authorizes server identity, consumes credentials, and retires or restores live workspace sessions. diff --git a/openwiki/workflows/sftp-transfer-and-external-edit.md b/openwiki/workflows/sftp-transfer-and-external-edit.md index 86676db8..ae260807 100644 --- a/openwiki/workflows/sftp-transfer-and-external-edit.md +++ b/openwiki/workflows/sftp-transfer-and-external-edit.md @@ -1,16 +1,22 @@ --- type: workflow title: SFTP Transfer, Scheduling, and External Edit Workflow -description: How SFTP browser operations become scheduled transfers, choose an SSH topology, resolve conflicts and resume safely, and support explicit external-file editing without durable staging or replay. +description: How browser SFTP jobs are scheduled and resumed, how Agent SFTP leases reuse authenticated SSH connections, and how MCP uploads and external edits remain separate workflows. tags: [sftp, file-transfer, ssh, scheduling, external-editing, lifecycle] verified: - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z + at: 2026-09-23T10:36:38.039Z sources: - id: openwiki-source-46ef2fcd9e3aba751015021b resource: repo://Frameworks/TermindDomain/Transfers/SFTPPreferences.swift + - id: openwiki-source-96c4e228b6057cf9d989eb04 + resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSFTPTools.swift - id: openwiki-source-0c82bf45bc197f879a54fd3a resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift + - id: openwiki-source-e1a028bd99d4dbe6d1e14f6a + resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentScratchTransferTools.swift + - id: openwiki-source-f2860ea1e34da1a6d9ec1510 + resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/SFTPCopyTool.swift - id: openwiki-source-dd3df578da8881d8ba0638e6 resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift - id: openwiki-source-f45e107ba4ae15ff23a99333 @@ -33,13 +39,19 @@ sources: resource: repo://Frameworks/TermindRemoteInfrastructure/Transfers/SFTPTransferCoordinator.swift - id: openwiki-source-d92ce4bb378fe3506b55c85a resource: repo://FrameworkTests/SFTPRemoteConflictResolverTests.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-0260a25fb41739d94e23d2ea + resource: repo://TFMTests/AgentConnectionPoolTests.swift - id: openwiki-source-83498f1ebb2addd4dded3bc1 resource: repo://TFMTests/SFTPConcurrencySchedulerTests.swift - id: openwiki-source-bdee3a21bf24d48b877a78fe resource: repo://TFMTests/SFTPEditTests.swift - id: openwiki-source-53e2b2fd2e661123f63e69e1 resource: repo://TFMTests/SFTPTransferContextTests.swift -generated: { by: "omp", at: "2026-09-22T02:21:47.705Z" } +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- ## Scope and operating model @@ -168,11 +180,47 @@ Assume setup succeeds, no other files consume the stated limits, and the SSH ses ## Agent SFTP reuse is related, not identical -Agent data work joins the same file-admission mechanism through `AgentSSHAuthenticationRegistry.withSFTP` when `schedulesDataTransfer` is true. Metadata calls can bypass a data permit and default to channel mode; callers with a supplied permit do not acquire/release it twice. Authentication and the channel lease are obtained inside that admitted operation. +Agent SFTP does **not** borrow the browser's `SFTPTransferContext`. `SFTPToolDefinition` validates host and normalized absolute path in preflight, then routes the operation through `AgentToolSupport.withAuthenticatedSFTP` and `AgentSSHAuthenticationRegistry.withSFTP`. `sftp_read` and `sftp_write` request data admission (using bounded read size or UTF-8 write length); list, stat, mkdir, move, chmod and delete use the default metadata path without a file permit. `scratch_pull` and `scratch_push` also request data admission. `withSFTP` acquires a permit from the shared scheduler for `.agentRun(runID ?? invocationID)` only when requested and no permit was supplied, then authenticates and acquires a pool lease **inside** admission, releasing its owned permit on both success and failure. An externally supplied permit is not released by this wrapper. [^agent-tools] [^agent-admission] [^scratch-admission] -`AgentConnectionPool.acquireSFTP` first reuses an eligible idle record, preferring least-recently-used idle records; channel-only mode limits record reuse to the primary. If that primary is busy, channel-only work opens a sibling and can wait/retry the primary on sibling failure. Connection-preferred overlap joins a per-Host unknown-capability probe or opens another silent connection after capability is known. Pooled records become idle on lease release; ephemeral siblings are disconnected. Idle auxiliaries can later be swept, unlike the coordinator context's operation-scoped extras. +```mermaid +sequenceDiagram + participant Tool as Agent Tool + participant Registry as Auth Registry + participant Scheduler + participant Pool as Agent Pool + participant SSH as SSH Connection + Tool->>Registry: withSFTP with data flag and size + opt data work without supplied permit + Registry->>Scheduler: acquire agentRun permit + Scheduler-->>Registry: mode and permit + end + Registry->>Registry: join authentication context for host + Registry->>Pool: acquireSFTP with selected mode + Pool->>SSH: reuse or open primary SFTP subsystem + alt primary busy + Pool->>SSH: lease idle auxiliary or open silent auxiliary or sibling + end + Pool-->>Registry: exclusive channel lease + Registry->>Tool: run operation once + Registry->>Pool: releaseSFTP + opt owned permit + Registry->>Scheduler: release permit + end +``` -Do not copy browser-context assumptions wholesale into this pool. In particular, the Agent's shared initial-probe catch updates capability before rethrowing cancellation, whereas the browser context checks cancellation before recording a downgrade. They also have different final fallback paths and cache lifetimes. Review the specific owner and tests for a scheduling change rather than inventing one universal SFTP pool. +*File admission and the Agent pool's exclusive channel lease are separate resources; acquiring a lease never replays the tool operation.* + +The Agent pool retains **one primary SSH connection per Host across tool calls, runs and conversations**; exec and primary SFTP share its transport, and simultaneous initial exec/SFTP opens join rather than creating competing primary connections. The primary SFTP subsystem is opened once on that SSH connection. Reuse checks a route fingerprint (host, route hops, login identity, proxy, known-host fingerprints and destination charset); changing or deleting the route retires the old connection. The fingerprint deliberately does not read Keychain secrets: rotating a credential without changing login identity does not break an already authenticated session, but affects the next connection. A pane-backed temporary target stops resolving when its pane disappears. [^agent-primary] [^agent-route] [^agent-pool-tests] + +`AgentConnectionPool.acquireSFTP` first obtains the primary and reuses an eligible idle record, preferring the least-recently-used idle one. In `channelsOnly`, only an idle primary record qualifies; overlap opens a sibling on the primary transport. If sibling opening actually fails (not cancellation), it polls until the primary is free and retries acquisition. In `connectionsPreferred`, an unknown Host capability uses a shared, interaction-forbidden extra-connection probe; success stores an auxiliary record and marks connections capable. Further overlap can silently open other auxiliaries. Failed silent setup downgrades to sibling channels, but unlike channel-only fallback, a sibling-opening failure on this path propagates. The initial shared-probe catch records channel capability *before* rethrowing cancellation; browser `SFTPTransferContext` instead checks cancellation before downgrading. No extra credential prompt is allowed for an auxiliary open. [^agent-lease] [^agent-probe] [^context-probe] + +On release a pooled primary or auxiliary becomes idle, while an ephemeral sibling disconnects. Idle auxiliaries are swept independently; the primary and exec connection close together only after the Host has no active exec/SFTP leases and the 180-second idle timeout has passed (the app's sweep interval defaults to 30 seconds). Disconnect, route invalidation and `closeAll` cancel active SFTP lease tokens and close channels/connections; `SFTPError.notConnected` or `.connectionLost` evicts the Host after the operation fails, **not** by rerunning it. Authentication can retry a rejected connection attempt before the operation starts; overlapping attempts share a short-lived authentication context that is discarded after its last lease, not a persistent cache of custom passwords. [^agent-release] [^agent-sweep] [^agent-auth] [^agent-admission] + +For an Agent `sftp_copy`, the tool obtains **one** destination-anchored global permit charged to both endpoint Hosts and passes it into each endpoint's `withSFTP`, so neither endpoint acquires another permit. A same-host copy in channel-only mode uses its one leased channel for both endpoints; other copies acquire source then destination leases and stream through `SFTPRemoteCopyOperation`. This differs from browser coordinator copy leases and from a pair of independent single-host Agent tools. [^agent-copy] [^remote-copy-leases] + +MCP uploads are a separate HTTP ticket workflow, **not** browser queue rows or scratch files. `MCPUploadCoordinator` validates target path, byte count and SHA-256, issues a session-bound loopback PUT URL/token, and checks origin, token, body length and resumable offset before claiming the MCP transfer budget. `MCPServerTools` then runs `SFTPStreamUploadOperation` through the same Agent authentication/pool lease and scheduler with `schedulesDataTransfer: true`; cleanup uses another SFTP lease without data admission. A disconnected HTTP attempt or recoverable SFTP failure may pause a ticket for an explicit offset-matched retry while it is unexpired; integrity errors and cancellations clean up rather than silently replaying bytes. Ticket status and cancellation belong to the MCP coordinator, not `SFTPTransferCoordinator`. [^mcp-tickets] [^mcp-transfer] [^mcp-failure] + +Do not copy browser-context assumptions wholesale into the Agent pool: browser auxiliaries are operation-scoped, Agent auxiliaries remain eligible for reuse, and MCP's HTTP budget/tickets are not scheduler permits. Focused pool tests verify one handshake across repeated execs, concurrent primary opens and exec/SFTP sharing, cancellation of one or the last connection opener, route retirement, idle sweeps and no replay of a command that already started. These tests cover primary reuse rather than exhaustively asserting every SFTP auxiliary-mode branch. [^agent-pool-tests] [^agent-lease] ## From a file lease to libssh2 turns @@ -258,6 +306,22 @@ Discard is intentionally non-destructive to user work: it stops tracking and for Focused tests cover the materially risky cases: scheduler fairness across hosts/sources, cross-host capacity accounting, and the Smart threshold; topology fallback, cancellation of a silent probe, pane-close continuity, and resume after release; conflict mapping, cancellation points, and safe recursive delete; and edit confirmation, immutable snapshots, loss-to-pause, invalidation, observation of atomic saves, discard, and cleanup. [^scheduler-tests] [^context-tests] [^resolver-tests] [^edit-tests] +[^agent-tools]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSFTPTools.swift#L26-L75`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSFTPTools.swift#L79-L348`. +[^scratch-admission]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentScratchTransferTools.swift#L49-L61`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentScratchTransferTools.swift#L124-L146`. +[^agent-admission]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L989-L1057`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSFTPTools.swift#L626-L657`. +[^agent-primary]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1131-L1141`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1462-L1527`. +[^agent-route]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L492-L527`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1607-L1635`. +[^agent-lease]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1234-L1296`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1359-L1386`. +[^agent-probe]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1298-L1365`. +[^agent-release]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1368-L1386`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1529-L1562`. +[^agent-sweep]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1154-L1157`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1564-L1605`. +[^agent-auth]: `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L912-L926`; `Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift#L1059-L1128`. +[^agent-copy]: `Frameworks/TermindRemoteInfrastructure/Agent/SFTPCopyTool.swift#L93-L156`. +[^agent-pool-tests]: `TFMTests/AgentConnectionPoolTests.swift#L43-L186`; `TFMTests/AgentConnectionPoolTests.swift#L200-L342`. +[^mcp-tickets]: `TFM/Application/MCPServer/MCPUploadCoordinator.swift#L7-L28`; `TFM/Application/MCPServer/MCPUploadCoordinator.swift#L94-L195`. +[^mcp-transfer]: `TFM/Application/MCPServer/MCPServerTools.swift#L37-L81`. +[^mcp-failure]: `TFM/Application/MCPServer/MCPUploadCoordinator.swift#L231-L280`; `TFM/Application/MCPServer/MCPUploadCoordinator.swift#L329-L388`. + [^client-channel]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPClient.swift#L293-L387`; `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L120-L160`. [^resume-state]: `Frameworks/TermindRemoteInfrastructure/Transfers/SFTPResumeState.swift#L5-L75`. [^channel-prefix]: `Frameworks/TermindRemoteInfrastructure/SSH/SFTPChannel.swift#L985-L1031`. diff --git a/openwiki/workflows/ssh-session-lifecycle.md b/openwiki/workflows/ssh-session-lifecycle.md index 532098e8..38b24aec 100644 --- a/openwiki/workflows/ssh-session-lifecycle.md +++ b/openwiki/workflows/ssh-session-lifecycle.md @@ -3,6 +3,9 @@ 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-23T10:36:38.039Z sources: - id: openwiki-source-cb178f0d078ab3218679c80e resource: repo://Frameworks/TermindApplication/Connections/RemoteSessionConnectionController.swift @@ -10,6 +13,12 @@ sources: resource: repo://Frameworks/TermindApplication/Connections/SSHConnectionPreparation.swift - id: openwiki-source-4f78037bc69b6dfc293aca3d resource: repo://Frameworks/TermindApplication/SSHConnectionTypes.swift + - id: openwiki-source-1fc00d0407016efa5a0378eb + resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentBuiltInSSHTools.swift + - id: openwiki-source-0c82bf45bc197f879a54fd3a + resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentConnections.swift + - id: openwiki-source-ead8e57ca19639dd536b792d + resource: repo://Frameworks/TermindRemoteInfrastructure/Agent/AgentHostServices.swift - id: openwiki-source-e980c605b1828a2d960bfd5e resource: repo://Frameworks/TermindRemoteInfrastructure/SSH/SSHConnection.swift - id: openwiki-source-ab74624bdc6b7046d91bcbac @@ -26,24 +35,25 @@ sources: resource: repo://FrameworkTests/SSHHostKeyAuthorizationTests.swift - id: openwiki-source-906678adb91c2fce2d3fcaed resource: repo://TFI/App/MobileAppModel.swift + - id: openwiki-source-d44869be46c03fbd0ce9c64c + resource: repo://TFI/Application/Agent/MobileAssistantModel.swift - id: openwiki-source-492f738896225c6b3acf7d2f resource: repo://TFI/Features/Workspaces/MobileWorkspace.swift - id: openwiki-source-350d4a794cfef67e406ddf9b resource: repo://TFI/Infrastructure/MobileWorkspaceStore.swift - - id: openwiki-source-b822b041afbf829d09a8555a - resource: repo://TFITests/MobileAppTests.swift - - id: openwiki-source-9b78a7e39bfa08bea5192722 - resource: repo://TFITests/MobileWorkspaceStoreTests.swift + - id: openwiki-source-34542e0f07e1650e098824c7 + resource: repo://TFI/Platform/MobileBackgroundController.swift + - id: openwiki-source-4dbea0ff2808163cb4ecdd8f + resource: repo://TFM/App/AppModel.swift - id: openwiki-source-6570374eaac2e0278fa84640 resource: repo://TFM/App/TermindApp.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: "codex", at: "2026-09-23T00:14:42.075Z" } -verified: - - by: openwiki/0.5.2 - at: 2026-09-23T10:08:51.776Z +generated: { by: "openwiki/0.5.2", at: "2026-09-23T10:36:38.039Z" } --- # SSH, Telnet, Trust, and Workspace Session Lifecycle @@ -52,7 +62,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, or forwarding can share preparation and transport policy without sharing UI lifetime or an interactive prompt. +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. ```mermaid sequenceDiagram @@ -163,6 +173,43 @@ Authentication answers whether a transport may be installed. The next layer deci - [SFTP Transfer, Scheduling, and External Edit Workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md) explains file permits before channel acquisition, independent-connection preference, sibling/primary fallback, and detached transfer ownership. - [Port Forwarding: Multi-Connection Pool and Flow Dispatch](/openwiki/workflows/port-forwarding-pool-and-dispatch.md) follows pool publication, local/SOCKS flow assignment, primary-only remote listeners, and the distinction between auxiliary repair and whole-context recovery. +## Agent SSH connections are not workspace sessions + +`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. + +`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. + +```mermaid +sequenceDiagram + participant Tool as Agent SSH tool + participant Registry as Authentication registry + participant Resolver as Host resolver + participant Pool as Agent connection pool + participant Server as SSH server + Tool->>Registry: connectionContext for host + Registry->>Pool: check pooled connection + alt no reusable connection + Registry->>Resolver: resolve route and local credentials + 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 + else reusable connection + Pool-->>Registry: pooled transport + end + Registry-->>Tool: connection + Tool->>Pool: acquire exec lease + Tool->>Server: run non PTY command channel +``` + +*The Agent shares its own transport across tools, not a workspace's interactive session; prompts and one-use secrets belong to the connection attempt.* + +`ssh_exec` preflight classifies safe commands for parallel execution and asks approval for unproven commands, which run sequentially. Optional secret stdin is consumed from a handle bound to the run, host, tool and purpose; it is not an SSH login credential. Its reporting deadline includes connection setup. If setup is still pending, it returns `connecting` and starts **no** command; if an already-started command exceeds the deadline, `AgentBackgroundCommands` adopts its session and output under a handle for `ssh_wait`, while the shared connection stays available. A dead pooled connection can be retried once only if no command channel opened; never replay an operation that might have had effects. + ## Retry, retirement, and workspace behavior A connection failure before the first successful session remains a failed journey requiring an explicit user retry. Once a session has connected, `RemoteSessionConnectionController` can schedule recovery through `SessionReconnectController`; it pauses recovery for trust or authentication interaction and resets recovery state on disconnect. Retiring a session cancels prompt queues, rejects pending host-key approval, clears temporary trust, stops reconnect work, and hides the journey. @@ -173,9 +220,11 @@ The platform rules intentionally differ: | --- | --- | --- | | Window or app restoration | Native scene/frame restoration restores window presentation, not live Workspace transports. Dynamic Workspaces are window-owned and are not reconnected simply because a window is restored. | `mobile.workspaces.v1` stores only ordered local descriptors containing workspace ID, Host ID, kind and title. Cold launch shows saved descriptors but creates no sessions, history, or network activity. | | Reopen/select | Mounting a preserved desktop workspace does not repeat authentication; explicit retry or reopen may. Moving a workspace preserves its surfaces, transport, splits, and state. | Opening a descriptor reuses or registers one live workspace across scenes and makes at most one initial connection attempt; a failure needs explicit retry. Peer switching retains the live workspace. | -| Background/foreground | Desktop quit/close follows owned-session teardown; independent transfers and services have their own lifetime. | Background expiration closes transports but retains workspace intent. Foreground resumes existing workspaces when their recorded foreground-resume intent is set. | +| 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. + Telnet is intentionally a separate terminal transport rather than an SSH fallback. `TelnetConnection` opens direct TCP with `NWConnection`, or obtains a proxied socket through `TerminalSocketConnector`; its own UUID generation rejects stale Network and socket callbacks. It performs incremental IAC negotiation, NVT line conversion, terminal type and NAWS support, and applies the configured charset only to application data. Optional username/password automation responds to recognized prompts, consumes and clears the password after use, and falls back to manual interaction when the expected flow does not materialize. It has no SSH host-key verification, jump-host route, SFTP channel, or shell integration. ```mermaid @@ -207,13 +256,15 @@ When changing connection code, preserve these boundaries: - Keep proxy submission and SSH submission separate, and preserve the proxy `ownerHostID` so the Journey stays on the prior endpoint. - Do not make a URI fingerprint or temporary approval durable trust, and do not bypass authorization on a known-host mismatch. - Put callbacks from sockets, timers, detached preparation, and authentication behind the current attempt/generation check before touching feature state. -- Have the owner that opened a client retire it on every failed connect and on explicit close; do not transfer a half-open client to a workspace. +- 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. +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. ## Related pages - [Platform runtime and lifetime ownership](/openwiki/architecture/platform-runtime.md) +- [Agent runtime and Assistant](/openwiki/concepts/agent-runtime-and-assistant.md) - [Persistence and secrets](/openwiki/concepts/persistence-and-secrets.md) - [Remote services and forwarding](/openwiki/concepts/remote-services-and-forwarding.md) - [SFTP transfer and external edit workflow](/openwiki/workflows/sftp-transfer-and-external-edit.md)