interlatch 0.28.2__tar.gz → 0.28.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (498) hide show
  1. {interlatch-0.28.2 → interlatch-0.28.3}/CHANGELOG.md +18 -0
  2. {interlatch-0.28.2 → interlatch-0.28.3}/PKG-INFO +1 -1
  3. interlatch-0.28.3/changelog.d/hubs-page.md +4 -0
  4. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/profiles.md +2 -2
  5. {interlatch-0.28.2 → interlatch-0.28.3}/docs/profiles.md +5 -3
  6. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/i18n/ja.py +1 -0
  7. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/sharing.py +4 -1
  8. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/hubs.py +49 -3
  9. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/status.py +26 -4
  10. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/routes.py +11 -2
  11. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/app.css +6 -0
  12. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/app.js +155 -87
  13. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/ja.js +33 -7
  14. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_profile_hubs.py +60 -0
  15. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_route_matrix.py +1 -1
  16. interlatch-0.28.2/changelog.d/hub-groups.md +0 -6
  17. interlatch-0.28.2/changelog.d/hub-take-back.md +0 -6
  18. interlatch-0.28.2/changelog.d/hubs-dashboard.md +0 -3
  19. {interlatch-0.28.2 → interlatch-0.28.3}/.github/dependabot.yml +0 -0
  20. {interlatch-0.28.2 → interlatch-0.28.3}/.github/windows-ja-qa/driver.ps1 +0 -0
  21. {interlatch-0.28.2 → interlatch-0.28.3}/.github/windows-ja-qa/ja_check.py +0 -0
  22. {interlatch-0.28.2 → interlatch-0.28.3}/.github/windows-ja-qa/report.py +0 -0
  23. {interlatch-0.28.2 → interlatch-0.28.3}/.github/windows-ja-qa/shots.py +0 -0
  24. {interlatch-0.28.2 → interlatch-0.28.3}/.github/windows-ja-qa/user.ps1 +0 -0
  25. {interlatch-0.28.2 → interlatch-0.28.3}/.github/workflows/changelog.yml +0 -0
  26. {interlatch-0.28.2 → interlatch-0.28.3}/.github/workflows/ci.yml +0 -0
  27. {interlatch-0.28.2 → interlatch-0.28.3}/.github/workflows/docs.yml +0 -0
  28. {interlatch-0.28.2 → interlatch-0.28.3}/.github/workflows/release.yml +0 -0
  29. {interlatch-0.28.2 → interlatch-0.28.3}/.github/workflows/windows-ja-qa.yml +0 -0
  30. {interlatch-0.28.2 → interlatch-0.28.3}/.gitignore +0 -0
  31. {interlatch-0.28.2 → interlatch-0.28.3}/.pre-commit-config.yaml +0 -0
  32. {interlatch-0.28.2 → interlatch-0.28.3}/.python-version +0 -0
  33. {interlatch-0.28.2 → interlatch-0.28.3}/CONTRIBUTING.md +0 -0
  34. {interlatch-0.28.2 → interlatch-0.28.3}/LICENSE +0 -0
  35. {interlatch-0.28.2 → interlatch-0.28.3}/README.ja.md +0 -0
  36. {interlatch-0.28.2 → interlatch-0.28.3}/README.md +0 -0
  37. {interlatch-0.28.2 → interlatch-0.28.3}/ROADMAP.ja.md +0 -0
  38. {interlatch-0.28.2 → interlatch-0.28.3}/ROADMAP.md +0 -0
  39. {interlatch-0.28.2 → interlatch-0.28.3}/SECURITY.md +0 -0
  40. {interlatch-0.28.2 → interlatch-0.28.3}/careers/README.md +0 -0
  41. {interlatch-0.28.2 → interlatch-0.28.3}/careers/boards.json +0 -0
  42. {interlatch-0.28.2 → interlatch-0.28.3}/careers/pipeline.py +0 -0
  43. {interlatch-0.28.2 → interlatch-0.28.3}/changelog.d/README.md +0 -0
  44. {interlatch-0.28.2 → interlatch-0.28.3}/dev.sh +0 -0
  45. {interlatch-0.28.2 → interlatch-0.28.3}/docker/.dockerignore +0 -0
  46. {interlatch-0.28.2 → interlatch-0.28.3}/docker/.env.example +0 -0
  47. {interlatch-0.28.2 → interlatch-0.28.3}/docker/Caddyfile +0 -0
  48. {interlatch-0.28.2 → interlatch-0.28.3}/docker/Dockerfile +0 -0
  49. {interlatch-0.28.2 → interlatch-0.28.3}/docker/compose.yaml +0 -0
  50. {interlatch-0.28.2 → interlatch-0.28.3}/docker/wheels/.gitignore +0 -0
  51. {interlatch-0.28.2 → interlatch-0.28.3}/docs/README.md +0 -0
  52. {interlatch-0.28.2 → interlatch-0.28.3}/docs/_site/hooks.py +0 -0
  53. {interlatch-0.28.2 → interlatch-0.28.3}/docs/analysis.md +0 -0
  54. {interlatch-0.28.2 → interlatch-0.28.3}/docs/cli.md +0 -0
  55. {interlatch-0.28.2 → interlatch-0.28.3}/docs/configuration.md +0 -0
  56. {interlatch-0.28.2 → interlatch-0.28.3}/docs/dashboard.md +0 -0
  57. {interlatch-0.28.2 → interlatch-0.28.3}/docs/demo/make_demo.py +0 -0
  58. {interlatch-0.28.2 → interlatch-0.28.3}/docs/demo/record_demo.py +0 -0
  59. {interlatch-0.28.2 → interlatch-0.28.3}/docs/design/innerlatch.md +0 -0
  60. {interlatch-0.28.2 → interlatch-0.28.3}/docs/design/ja/innerlatch.md +0 -0
  61. {interlatch-0.28.2 → interlatch-0.28.3}/docs/design/ja/learning.md +0 -0
  62. {interlatch-0.28.2 → interlatch-0.28.3}/docs/design/learning.md +0 -0
  63. {interlatch-0.28.2 → interlatch-0.28.3}/docs/development.md +0 -0
  64. {interlatch-0.28.2 → interlatch-0.28.3}/docs/devices.md +0 -0
  65. {interlatch-0.28.2 → interlatch-0.28.3}/docs/diagrams/analysis.excalidraw.svg +0 -0
  66. {interlatch-0.28.2 → interlatch-0.28.3}/docs/diagrams/architecture.excalidraw.svg +0 -0
  67. {interlatch-0.28.2 → interlatch-0.28.3}/docs/docker.md +0 -0
  68. {interlatch-0.28.2 → interlatch-0.28.3}/docs/faq.md +0 -0
  69. {interlatch-0.28.2 → interlatch-0.28.3}/docs/images/demo.gif +0 -0
  70. {interlatch-0.28.2 → interlatch-0.28.3}/docs/images/home.png +0 -0
  71. {interlatch-0.28.2 → interlatch-0.28.3}/docs/images/map.png +0 -0
  72. {interlatch-0.28.2 → interlatch-0.28.3}/docs/images/palette.png +0 -0
  73. {interlatch-0.28.2 → interlatch-0.28.3}/docs/images/session.png +0 -0
  74. {interlatch-0.28.2 → interlatch-0.28.3}/docs/install.md +0 -0
  75. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/README.md +0 -0
  76. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/analysis.md +0 -0
  77. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/cli.md +0 -0
  78. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/configuration.md +0 -0
  79. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/dashboard.md +0 -0
  80. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/development.md +0 -0
  81. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/devices.md +0 -0
  82. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/docker.md +0 -0
  83. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/faq.md +0 -0
  84. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/install.md +0 -0
  85. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/join-a-hub.md +0 -0
  86. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/mcp.md +0 -0
  87. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/moving-from-chronicle.md +0 -0
  88. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/party.md +0 -0
  89. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/postgres.md +0 -0
  90. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/privacy.md +0 -0
  91. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/sources.md +0 -0
  92. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/suggestions.md +0 -0
  93. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/troubleshooting.md +0 -0
  94. {interlatch-0.28.2 → interlatch-0.28.3}/docs/ja/vscode.md +0 -0
  95. {interlatch-0.28.2 → interlatch-0.28.3}/docs/join-a-hub.md +0 -0
  96. {interlatch-0.28.2 → interlatch-0.28.3}/docs/mcp.md +0 -0
  97. {interlatch-0.28.2 → interlatch-0.28.3}/docs/moving-from-chronicle.md +0 -0
  98. {interlatch-0.28.2 → interlatch-0.28.3}/docs/party.md +0 -0
  99. {interlatch-0.28.2 → interlatch-0.28.3}/docs/postgres.md +0 -0
  100. {interlatch-0.28.2 → interlatch-0.28.3}/docs/privacy.md +0 -0
  101. {interlatch-0.28.2 → interlatch-0.28.3}/docs/sources.md +0 -0
  102. {interlatch-0.28.2 → interlatch-0.28.3}/docs/suggestions.md +0 -0
  103. {interlatch-0.28.2 → interlatch-0.28.3}/docs/troubleshooting.md +0 -0
  104. {interlatch-0.28.2 → interlatch-0.28.3}/docs/vscode.md +0 -0
  105. {interlatch-0.28.2 → interlatch-0.28.3}/leaderboard/.firebaserc +0 -0
  106. {interlatch-0.28.2 → interlatch-0.28.3}/leaderboard/.gitignore +0 -0
  107. {interlatch-0.28.2 → interlatch-0.28.3}/leaderboard/README.md +0 -0
  108. {interlatch-0.28.2 → interlatch-0.28.3}/leaderboard/firebase.json +0 -0
  109. {interlatch-0.28.2 → interlatch-0.28.3}/leaderboard/firestore.indexes.json +0 -0
  110. {interlatch-0.28.2 → interlatch-0.28.3}/leaderboard/firestore.rules +0 -0
  111. {interlatch-0.28.2 → interlatch-0.28.3}/mkdocs.yml +0 -0
  112. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/README.md +0 -0
  113. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/art.json +0 -0
  114. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/filing.html +0 -0
  115. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/loops.json +0 -0
  116. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/loops.py +0 -0
  117. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/members.js +0 -0
  118. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/render.html +0 -0
  119. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/render.py +0 -0
  120. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/scenes-more.js +0 -0
  121. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/icons3d/scenes.html +0 -0
  122. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/Chronicle.icns +0 -0
  123. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/Interlatch.spec +0 -0
  124. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/build.sh +0 -0
  125. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/entitlements.plist +0 -0
  126. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/icon-3d.webp +0 -0
  127. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/icon-blueprint-prompt.md +0 -0
  128. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/icon-blueprint.webp +0 -0
  129. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/icon.png +0 -0
  130. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/interlatch_app.py +0 -0
  131. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/macos/make_icon.py +0 -0
  132. {interlatch-0.28.2 → interlatch-0.28.3}/packaging/release.py +0 -0
  133. {interlatch-0.28.2 → interlatch-0.28.3}/pyproject.toml +0 -0
  134. {interlatch-0.28.2 → interlatch-0.28.3}/src/chronicle/__init__.py +0 -0
  135. {interlatch-0.28.2 → interlatch-0.28.3}/src/chronicle/__main__.py +0 -0
  136. {interlatch-0.28.2 → interlatch-0.28.3}/src/chronicle/windows.py +0 -0
  137. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/__init__.py +0 -0
  138. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/__main__.py +0 -0
  139. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/__init__.py +0 -0
  140. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/digest.py +0 -0
  141. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/language.py +0 -0
  142. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/queue.py +0 -0
  143. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/__init__.py +0 -0
  144. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/api.py +0 -0
  145. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/base.py +0 -0
  146. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/bob.py +0 -0
  147. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/claude.py +0 -0
  148. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/codex.py +0 -0
  149. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/factory.py +0 -0
  150. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/off.py +0 -0
  151. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/opencode.py +0 -0
  152. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/process.py +0 -0
  153. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/replies.py +0 -0
  154. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/runners/settings.py +0 -0
  155. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/screen.py +0 -0
  156. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/session.py +0 -0
  157. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/analysis/worker.py +0 -0
  158. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/application/__init__.py +0 -0
  159. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/application/profiles.py +0 -0
  160. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/application/records.py +0 -0
  161. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/application/search.py +0 -0
  162. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/application/workflows.py +0 -0
  163. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/artifacts/__init__.py +0 -0
  164. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/artifacts/files.py +0 -0
  165. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/artifacts/queries.py +0 -0
  166. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/cli.py +0 -0
  167. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/__init__.py +0 -0
  168. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/agents.py +0 -0
  169. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/artifact_records.py +0 -0
  170. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/config.py +0 -0
  171. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/diagrams.py +0 -0
  172. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/i18n/__init__.py +0 -0
  173. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/machine.py +0 -0
  174. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/paths.py +0 -0
  175. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/pricing.py +0 -0
  176. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/process.py +0 -0
  177. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/profiles.py +0 -0
  178. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/redact.py +0 -0
  179. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/sessions.py +0 -0
  180. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/core/util.py +0 -0
  181. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/__init__.py +0 -0
  182. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/analyses.py +0 -0
  183. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/archive.py +0 -0
  184. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/chat_import.py +0 -0
  185. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/deletion.py +0 -0
  186. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/history.py +0 -0
  187. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/memory.py +0 -0
  188. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/persistence.py +0 -0
  189. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/report.py +0 -0
  190. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/ingestion/service.py +0 -0
  191. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/__init__.py +0 -0
  192. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/__init__.py +0 -0
  193. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/__init__.py +0 -0
  194. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/archive.py +0 -0
  195. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/hubs.py +0 -0
  196. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/knowledge.py +0 -0
  197. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/operations.py +0 -0
  198. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/recording.py +0 -0
  199. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/commands/setup.py +0 -0
  200. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/common.py +0 -0
  201. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/main.py +0 -0
  202. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/cli/parser.py +0 -0
  203. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/exports/__init__.py +0 -0
  204. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/exports/diagrams.py +0 -0
  205. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/exports/markdown.py +0 -0
  206. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/exports/sessions.py +0 -0
  207. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/exports/vault.py +0 -0
  208. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/mcp.py +0 -0
  209. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/__init__.py +0 -0
  210. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/__init__.py +0 -0
  211. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/artifacts.py +0 -0
  212. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/common.py +0 -0
  213. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/devices.py +0 -0
  214. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/hub_admin.py +0 -0
  215. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/knowledge.py +0 -0
  216. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/leaderboard.py +0 -0
  217. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/party.py +0 -0
  218. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/projects.py +0 -0
  219. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/sessions.py +0 -0
  220. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/settings.py +0 -0
  221. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/sources.py +0 -0
  222. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/storage.py +0 -0
  223. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/api/team.py +0 -0
  224. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/app.py +0 -0
  225. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/assets.py +0 -0
  226. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/context.py +0 -0
  227. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/handler.py +0 -0
  228. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/jobs.py +0 -0
  229. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/interfaces/web/server.py +0 -0
  230. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/__init__.py +0 -0
  231. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/arena.py +0 -0
  232. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/bag.py +0 -0
  233. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/cases.py +0 -0
  234. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/formation.py +0 -0
  235. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/friction.py +0 -0
  236. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/glossary.py +0 -0
  237. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/group_graph.py +0 -0
  238. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/instructions.py +0 -0
  239. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/ladder.py +0 -0
  240. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/learning.py +0 -0
  241. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/market.json +0 -0
  242. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/party.py +0 -0
  243. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/reviews.py +0 -0
  244. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/roadmap.json +0 -0
  245. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/study.py +0 -0
  246. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/suggest.py +0 -0
  247. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/synthesize.py +0 -0
  248. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/knowledge/weekly.py +0 -0
  249. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/__init__.py +0 -0
  250. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/groups.py +0 -0
  251. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/hubgroups.py +0 -0
  252. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/labels.py +0 -0
  253. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/owners.py +0 -0
  254. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/progress.py +0 -0
  255. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/routing.py +0 -0
  256. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/scope.py +0 -0
  257. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/projects/systems.py +0 -0
  258. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/__init__.py +0 -0
  259. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/connectors.py +0 -0
  260. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/container.py +0 -0
  261. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/hooks.py +0 -0
  262. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/install.py +0 -0
  263. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/migrate.py +0 -0
  264. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/notify.py +0 -0
  265. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/platforms/__init__.py +0 -0
  266. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/platforms/desktop.py +0 -0
  267. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/platforms/menubar.py +0 -0
  268. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/platforms/windows.py +0 -0
  269. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/statusline.py +0 -0
  270. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/tailnet.py +0 -0
  271. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/runtime/update.py +0 -0
  272. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/__init__.py +0 -0
  273. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/access.py +0 -0
  274. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/arena.py +0 -0
  275. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/client.py +0 -0
  276. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/identity.py +0 -0
  277. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/leaderboard.py +0 -0
  278. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/market.py +0 -0
  279. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/membership.py +0 -0
  280. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/news.py +0 -0
  281. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/people.py +0 -0
  282. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/projects.py +0 -0
  283. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/protocol.py +0 -0
  284. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/pull.py +0 -0
  285. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/push.py +0 -0
  286. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sharing/receiver.py +0 -0
  287. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/__init__.py +0 -0
  288. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/antigravity.py +0 -0
  289. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/bob.py +0 -0
  290. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/builder.py +0 -0
  291. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/chatgpt.py +0 -0
  292. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/chats.py +0 -0
  293. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/claude/__init__.py +0 -0
  294. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/claude/export.py +0 -0
  295. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/claude/files.py +0 -0
  296. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/claude/parser.py +0 -0
  297. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/codex/__init__.py +0 -0
  298. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/codex/cloud.py +0 -0
  299. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/codex/parser.py +0 -0
  300. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/copilot.py +0 -0
  301. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/discovery.py +0 -0
  302. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/opencode.py +0 -0
  303. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/sources/prompts.py +0 -0
  304. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/__init__.py +0 -0
  305. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/fts.py +0 -0
  306. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/kv.py +0 -0
  307. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/migrations.py +0 -0
  308. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/mirror.py +0 -0
  309. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/postgres.py +0 -0
  310. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/schema.py +0 -0
  311. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/sqlite.py +0 -0
  312. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/storage/team.py +0 -0
  313. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/AGENT-ICONS.txt +0 -0
  314. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/PLEX-OFL.txt +0 -0
  315. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/adventure.js +0 -0
  316. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-antigravity.svg +0 -0
  317. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-bob.svg +0 -0
  318. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-chatgpt.svg +0 -0
  319. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-claude-ai.svg +0 -0
  320. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-claude.svg +0 -0
  321. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-codex.svg +0 -0
  322. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-copilot.svg +0 -0
  323. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/agent-opencode.svg +0 -0
  324. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-book.webp +0 -0
  325. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-camera.webp +0 -0
  326. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-chip.webp +0 -0
  327. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-clock.webp +0 -0
  328. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-cloud.webp +0 -0
  329. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-coins.webp +0 -0
  330. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-container.webp +0 -0
  331. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-dashboard.webp +0 -0
  332. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-dex.webp +0 -0
  333. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-document.webp +0 -0
  334. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-flag.webp +0 -0
  335. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-folder.webp +0 -0
  336. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-gateway.webp +0 -0
  337. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-gears.webp +0 -0
  338. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-glitch.webp +0 -0
  339. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-globe.webp +0 -0
  340. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-laptop.webp +0 -0
  341. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-log.webp +0 -0
  342. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-lumi.webp +0 -0
  343. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-magnifier.webp +0 -0
  344. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-pip.webp +0 -0
  345. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-plug.webp +0 -0
  346. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-rack.webp +0 -0
  347. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/art-tink.webp +0 -0
  348. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/battle.js +0 -0
  349. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/boot.js +0 -0
  350. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/favicon.png +0 -0
  351. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/field.js +0 -0
  352. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/i18n.js +0 -0
  353. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/icon-180.png +0 -0
  354. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/icon-192.png +0 -0
  355. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/icon-512.png +0 -0
  356. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/icon.png +0 -0
  357. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/index.html +0 -0
  358. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/innerlatch.css +0 -0
  359. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/innerlatch.js +0 -0
  360. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/learning.js +0 -0
  361. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/manifest.webmanifest +0 -0
  362. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/panel.css +0 -0
  363. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/panel.html +0 -0
  364. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/panel.js +0 -0
  365. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/plex-mono-400.woff2 +0 -0
  366. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/plex-mono-500.woff2 +0 -0
  367. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/plex-mono-600.woff2 +0 -0
  368. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/plex-sans-400.woff2 +0 -0
  369. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/plex-sans-500.woff2 +0 -0
  370. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/plex-sans-600.woff2 +0 -0
  371. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/plex-sans-700.woff2 +0 -0
  372. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/rough.js +0 -0
  373. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/scene.js +0 -0
  374. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/web/sprites.js +0 -0
  375. {interlatch-0.28.2 → interlatch-0.28.3}/src/interlatch/windows.py +0 -0
  376. {interlatch-0.28.2 → interlatch-0.28.3}/tests/antigravity_fixture.py +0 -0
  377. {interlatch-0.28.2 → interlatch-0.28.3}/tests/codex_fixture.py +0 -0
  378. {interlatch-0.28.2 → interlatch-0.28.3}/tests/conftest.py +0 -0
  379. {interlatch-0.28.2 → interlatch-0.28.3}/tests/copilot_fixture.py +0 -0
  380. {interlatch-0.28.2 → interlatch-0.28.3}/tests/friction_fixture.py +0 -0
  381. {interlatch-0.28.2 → interlatch-0.28.3}/tests/golden.py +0 -0
  382. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/cli.json +0 -0
  383. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/diagram.json +0 -0
  384. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/parsers/antigravity.json +0 -0
  385. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/parsers/bob.json +0 -0
  386. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/parsers/claude_code.json +0 -0
  387. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/parsers/codex.json +0 -0
  388. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/parsers/copilot.json +0 -0
  389. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/parsers/opencode.json +0 -0
  390. {interlatch-0.28.2 → interlatch-0.28.3}/tests/goldens/systems.json +0 -0
  391. {interlatch-0.28.2 → interlatch-0.28.3}/tests/hubs_fixture.py +0 -0
  392. {interlatch-0.28.2 → interlatch-0.28.3}/tests/opencode_fixture.py +0 -0
  393. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_adventure_web.py +0 -0
  394. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_analysis.py +0 -0
  395. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_antigravity.py +0 -0
  396. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_architecture.py +0 -0
  397. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_arena.py +0 -0
  398. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_artifacts.py +0 -0
  399. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_bag.py +0 -0
  400. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_battle_web.py +0 -0
  401. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_bob_analysis.py +0 -0
  402. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_boot_web.py +0 -0
  403. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_careers.py +0 -0
  404. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_case_files.py +0 -0
  405. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_cases.py +0 -0
  406. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_chat_import.py +0 -0
  407. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_cli_pins.py +0 -0
  408. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_codex.py +0 -0
  409. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_codex_analysis.py +0 -0
  410. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_codex_cloud.py +0 -0
  411. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_container.py +0 -0
  412. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_copilot_bob.py +0 -0
  413. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_dedicated_hub.py +0 -0
  414. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_dedupe.py +0 -0
  415. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_desktop.py +0 -0
  416. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_diagram.py +0 -0
  417. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_ee_boundary.py +0 -0
  418. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_field_web.py +0 -0
  419. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_fix_effect.py +0 -0
  420. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_formation.py +0 -0
  421. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_friction.py +0 -0
  422. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_game_mode.py +0 -0
  423. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_glossary.py +0 -0
  424. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_group_graph.py +0 -0
  425. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_group_sharing.py +0 -0
  426. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_guidance.py +0 -0
  427. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_home_agents.py +0 -0
  428. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub.py +0 -0
  429. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_accept.py +0 -0
  430. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_cookie.py +0 -0
  431. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_groups.py +0 -0
  432. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_inventory_scope.py +0 -0
  433. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_leave_join.py +0 -0
  434. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_news.py +0 -0
  435. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_payload_privacy.py +0 -0
  436. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_projects.py +0 -0
  437. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_projects_listed.py +0 -0
  438. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_purge.py +0 -0
  439. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_send_problems.py +0 -0
  440. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_hub_sharing_race.py +0 -0
  441. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_i18n_web.py +0 -0
  442. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_ingest.py +0 -0
  443. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_instructions.py +0 -0
  444. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_integration.py +0 -0
  445. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_ladder.py +0 -0
  446. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_language.py +0 -0
  447. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_leaderboard.py +0 -0
  448. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_learning_glance.py +0 -0
  449. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_learning_interests.py +0 -0
  450. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_learning_web.py +0 -0
  451. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_leave_project.py +0 -0
  452. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_legacy_package.py +0 -0
  453. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_map_goldens.py +0 -0
  454. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_market.py +0 -0
  455. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_menubar.py +0 -0
  456. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_migrate.py +0 -0
  457. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_mirror.py +0 -0
  458. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_notify.py +0 -0
  459. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_opencode.py +0 -0
  460. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_opencode_analysis.py +0 -0
  461. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_parser.py +0 -0
  462. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_parser_goldens.py +0 -0
  463. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_party.py +0 -0
  464. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_party_map.py +0 -0
  465. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_people.py +0 -0
  466. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_people_hub.py +0 -0
  467. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_people_web.py +0 -0
  468. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_profile_scope.py +0 -0
  469. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_profiles.py +0 -0
  470. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_project_groups.py +0 -0
  471. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_project_progress.py +0 -0
  472. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_providers.py +0 -0
  473. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_queue.py +0 -0
  474. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_regressions.py +0 -0
  475. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_release.py +0 -0
  476. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_roadmap_catalog.py +0 -0
  477. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_screen.py +0 -0
  478. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_security.py +0 -0
  479. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_setup.py +0 -0
  480. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_statusline.py +0 -0
  481. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_study.py +0 -0
  482. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_suggest.py +0 -0
  483. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_suggest_cli.py +0 -0
  484. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_systems.py +0 -0
  485. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_team.py +0 -0
  486. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_team_home.py +0 -0
  487. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_update.py +0 -0
  488. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_weekly_reanalysis.py +0 -0
  489. {interlatch-0.28.2 → interlatch-0.28.3}/tests/test_windows.py +0 -0
  490. {interlatch-0.28.2 → interlatch-0.28.3}/tests/windows_smoke.py +0 -0
  491. {interlatch-0.28.2 → interlatch-0.28.3}/uv.lock +0 -0
  492. {interlatch-0.28.2 → interlatch-0.28.3}/vscode-extension/.vscodeignore +0 -0
  493. {interlatch-0.28.2 → interlatch-0.28.3}/vscode-extension/LICENSE +0 -0
  494. {interlatch-0.28.2 → interlatch-0.28.3}/vscode-extension/README.md +0 -0
  495. {interlatch-0.28.2 → interlatch-0.28.3}/vscode-extension/extension.js +0 -0
  496. {interlatch-0.28.2 → interlatch-0.28.3}/vscode-extension/media/icon.png +0 -0
  497. {interlatch-0.28.2 → interlatch-0.28.3}/vscode-extension/media/interlatch.svg +0 -0
  498. {interlatch-0.28.2 → interlatch-0.28.3}/vscode-extension/package.json +0 -0
@@ -3,6 +3,24 @@
3
3
  <!-- Don't add lines here: a pull request puts its line in a new file in changelog.d/ (see changelog.d/README.md),
4
4
  and each release moves the files it took into a dated section below. -->
5
5
 
6
+ ## 0.28.2 (2026-10-20)
7
+
8
+ - **Several hubs: connect your groups.** `interlatch profile` became `interlatch hubs` and `interlatch group`: add a
9
+ hub (`interlatch hubs add Acme <address> --code <code>`), then connect a group of projects to it
10
+ (`interlatch group connect "Acme work" Acme`). What the group holds goes to that hub, and changing the group on the
11
+ dashboard's Projects page moves its sessions with it. A project taken out of a connected group waits for you
12
+ instead of going back to Personal. `--profile` is now `--hub`; the old name still works
13
+ ([Several hubs on one computer](docs/profiles.md)).
14
+ - **Several hubs on the dashboard.** Settings › Devices › Hubs lists this computer's hubs and their groups, adds and
15
+ joins one, and settles folders that wait for you; a group's page has **Goes to**, which connects the group to a hub
16
+ ([Several hubs on one computer](docs/profiles.md)).
17
+ - **Moving a folder takes its sessions back from the hub that had them.** When a group, a project or a waiting folder
18
+ moves to another hub (or a group is disconnected), the hub it left takes back the sessions this computer sent it,
19
+ before anything goes to the new one. One that can't be reached takes them back at the next send. Home now shows
20
+ folders that wait for you to choose a hub under **Needs you**
21
+ ([Moving takes sessions back](docs/profiles.md#moving-takes-sessions-back)). Update your hubs too: an older hub
22
+ can't take sessions back.
23
+
6
24
  ## 0.28.1 (2026-10-19)
7
25
 
8
26
  - **Profiles, first stage:** `interlatch profile create Acme --owns ~/work/acme` makes a named profile that owns a
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: interlatch
3
- Version: 0.28.2
3
+ Version: 0.28.3
4
4
  Summary: Shared memory for your coding agents: records every session (Claude Code, Codex, Copilot, Bob, Antigravity, OpenCode) locally and keeps what they learned, each lesson linked to the session it came from.
5
5
  Project-URL: Homepage, https://interlatch.com
6
6
  Project-URL: Documentation, https://interlatch.com/docs/
@@ -0,0 +1,4 @@
1
+ - **Settings › Hubs.** Each hub this computer sends to has its own card: whether sending works, the last share,
2
+ **Share now**, its dashboard (signed in as that hub's link), joining and leaving it. The Projects sidebar names the
3
+ hub each group goes to and lists folders waiting for a hub first, and the status bar names every hub
4
+ ([Several hubs on one computer](docs/profiles.md)).
@@ -29,7 +29,7 @@
29
29
 
30
30
  グループのフォルダーですでに記録されたセッションは Acme に移り、それ以降は Acme のハブに送られます。Personal のハブがすでに持っているものは、先にそのハブが取り下げます([移すとハブから取り下げる](#moving-takes-sessions-back))。`--dry-run` を付けると、何も変えずに、移るものと、そのうちハブが持っている数を表示します。
31
31
 
32
- **ダッシュボードでは:** **設定 › デバイス › ハブ**でハブを追加し(名前、アドレス、招待コード)、グループのページの**送り先**で、そのグループのセッションを送るハブを選びます。
32
+ **ダッシュボードでは:** **設定 › ハブ**に、ハブごとのカードがあります。送信がうまくいっているか、最後に送った時刻、**今すぐ共有**、ハブのダッシュボード、参加と脱退です。ハブの追加(名前、アドレス、招待コード)もここで行います。グループのページの**送り先**で、そのグループのセッションを送るハブを選びます。**プロジェクト**のサイドバーでは、ハブにつないだグループにそのハブの名前が表示され、選択を待つフォルダーが先頭に並びます。
33
33
 
34
34
  ほかのコンピューターと同じく、ハブに送られるのは、そのハブのプロジェクトに追加したフォルダーのものだけです(`interlatch --hub Acme hub add-folder ~/work/acme/app --project App`)。`--all-folders` を付けて参加した場合は別です。
35
35
 
@@ -67,7 +67,7 @@ interlatch group choose ~/work/acme/notes Acme # または personal
67
67
  interlatch group where ~/work/acme/app # フォルダーがどのハブに行くか、その理由
68
68
  ```
69
69
 
70
- **設定 › デバイス › ハブ**にも一覧があり、それぞれに**選ぶ**ボタンがあります。**ホーム**の**あなたの対応待ち**にも表示されます。あるフォルダーが選択待ちにしているプロジェクト(つないだグループの中にある、どのハブにもつないでいないグループ)は、そのフォルダーの下にまとめて表示します。
70
+ **設定 › ハブ**にも一覧があり、それぞれに**選ぶ**ボタンがあります。**ホーム**の**あなたの対応待ち**にも表示されます。あるフォルダーが選択待ちにしているプロジェクト(つないだグループの中にある、どのハブにもつないでいないグループ)は、そのフォルダーの下にまとめて表示します。
71
71
 
72
72
  ## エージェントに見えるもの
73
73
 
@@ -37,8 +37,10 @@ The sessions already recorded in the group's folders move to Acme, and go to Acm
37
37
  Personal's hub already has, it takes back first (see [Moving takes sessions back](#moving-takes-sessions-back)).
38
38
  `--dry-run` shows what would move, and how many of them a hub has, without changing anything.
39
39
 
40
- **On the dashboard:** **Settings › Devices › Hubs** adds a hub (its name, address and invite code), and a group's page
41
- has **Goes to**, where you pick the hub its sessions go to.
40
+ **On the dashboard:** **Settings › Hubs** has a card for each hub: whether sending to it works, when it last got
41
+ something, **Share now**, its dashboard, and joining or leaving it. It also adds a hub (its name, address and invite
42
+ code). A group's page has **Goes to**, where you pick the hub its sessions go to. In the **Projects** sidebar, a group
43
+ connected to a hub shows that hub's name, and folders waiting for you are listed first.
42
44
 
43
45
  As on any computer, a hub gets only the folders added to one of its projects
44
46
  (`interlatch --hub Acme hub add-folder ~/work/acme/app --project App`), unless you joined with `--all-folders`.
@@ -84,7 +86,7 @@ interlatch group choose ~/work/acme/notes Acme # or: personal
84
86
  interlatch group where ~/work/acme/app # who gets a folder, and why
85
87
  ```
86
88
 
87
- **Settings › Devices › Hubs** lists them too, with a **Choose** for each, and **Home** shows them under **Needs you**. Projects a folder holds waiting (a group
89
+ **Settings › Hubs** lists them too, with a **Choose** for each, and **Home** shows them under **Needs you**. Projects a folder holds waiting (a group
88
90
  connected to no hub inside a connected one) are listed once, under that folder.
89
91
 
90
92
  ## What agents see
@@ -482,4 +482,5 @@ JA: dict[str, str] = {
482
482
  "Pick a project to move.": "移動するプロジェクトを選んでください。",
483
483
  "This computer doesn't send to a hub.": "このコンピューターはハブに送っていません。",
484
484
  "Chronicle is now Interlatch. Updating moves this install from the agents-chronicle package to interlatch; the chronicle command keeps working.": "Chronicle は Interlatch になりました。更新すると、このインストールは agents-chronicle パッケージから interlatch に移ります。chronicle コマンドはそのまま使えます。",
485
+ "{hub} hasn't joined a hub yet.": "{hub} はまだハブに参加していません。",
485
486
  }
@@ -199,7 +199,10 @@ def cmd_hub(args) -> int:
199
199
  console.print(f"Joined the hub at {url}, sharing knowledge only. This computer keeps recording and "
200
200
  "analyzing its own sessions; the hub gets each analyzed session's summary and project "
201
201
  "lessons. Transcripts and lessons about you stay here.", highlight=False)
202
- if cfg.hub_all_folders:
202
+ if cfg.hub_all_folders and cfg.owner != "personal": # another hub: it gets what its groups hold
203
+ console.print("It shares sessions from every folder its groups hold (--all-folders): nothing until you "
204
+ "connect a group to it (`interlatch group connect <group> <hub>`).", highlight=False)
205
+ elif cfg.hub_all_folders:
203
206
  console.print("It shares sessions from every folder on this computer (--all-folders).", highlight=False)
204
207
  elif not args.code or got.get("projects") is None: # a limited person heard which projects above
205
208
  console.print("Only sessions in the hub's projects are shared: add your folder for each one with "
@@ -1,8 +1,9 @@
1
- """Several hubs on one computer (docs/profiles.md), on the dashboard: Settings › Devices › Hubs lists them and what
2
- waits for you; a group's page connects the group to one. application.profiles does the work."""
1
+ """Several hubs on one computer (docs/profiles.md), on the dashboard: Settings › Hubs lists them, how each one's sending
2
+ goes and what waits for you; a group's page connects the group to one. application.profiles does the work."""
3
3
 
4
4
  from __future__ import annotations
5
5
 
6
+ from ....core.i18n import tr
6
7
  from ..context import Context
7
8
 
8
9
 
@@ -22,6 +23,7 @@ def hubs(ctx: Context) -> dict:
22
23
  return {"error": str(exc), "hubs": [], "groups": [], "waiting": []}
23
24
  hubs = [r for r in rows if r["id"] != "waiting"]
24
25
  for r in hubs:
26
+ r.update(_sending(_hub_cfg(ctx, r["id"], reg)))
25
27
  r.pop("home", None) # this computer's folders: not needed to show them
26
28
  gs = []
27
29
  for g in groups(ctx.conn):
@@ -30,6 +32,31 @@ def hubs(ctx: Context) -> dict:
30
32
  return {"hubs": hubs, "groups": gs, "waiting": _waiting(waiting(ctx.conn), reg)}
31
33
 
32
34
 
35
+ def _hub_cfg(ctx: Context, hub_id: str, reg):
36
+ """The config that sends to hub `hub_id`: Personal's, or that hub's own folder's (None: no such hub)."""
37
+ from ....core.config import load_config
38
+
39
+ if hub_id == "personal":
40
+ return ctx.cfg
41
+ p = reg.profiles.get(hub_id) if reg else None
42
+ return load_config(p.home, create=False) if p and (p.home / "config.toml").exists() else None
43
+
44
+
45
+ def _sending(cfg) -> dict:
46
+ """How sending to the hub goes, as Settings › Devices shows it for Personal's: the hub's name as it last said, the
47
+ last share, a problem worth a warning, and the teammates' lessons it sent back."""
48
+ from ....sharing.projects import last_folders
49
+ from ....sharing.pull import last_team
50
+ from ....sharing.push import last_push, send_problem
51
+
52
+ if cfg is None or not cfg.is_spoke:
53
+ return {"joined": False}
54
+ pushed = last_push(cfg)
55
+ return {"joined": True, "hub_name": (last_folders(cfg) or {}).get("hub"), "share": cfg.hub_share,
56
+ "all_folders": cfg.hub_all_folders, "last_push": pushed, "push_problem": send_problem(pushed),
57
+ "team_lessons": (last_team(cfg) or {}).get("lessons")}
58
+
59
+
33
60
  def _waiting(rows: list[dict], reg=None) -> list[dict]:
34
61
  """What waits, one entry per choice to make: the projects a folder holds waiting (a group connected to no hub
35
62
  inside a connected one, a project picked out of one) together under that folder, with how many projects and
@@ -51,7 +78,8 @@ def _waiting(rows: list[dict], reg=None) -> list[dict]:
51
78
 
52
79
  def action_hubs(ctx: Context, verb: str, body: dict) -> tuple[dict, int]:
53
80
  """add (name, and optionally address and code to join it), remove, connect (group, hub; personal disconnects),
54
- choose (folder, hub or personal). A change the hubs can't make says why, 409, and changes nothing."""
81
+ choose (folder, hub or personal), push (hub: share with it now), leave (hub: stop sending to it). A change the hubs
82
+ can't make says why, 409, and changes nothing."""
55
83
  from ....application import profiles as ops
56
84
  from ....core.profiles import RegistryError
57
85
  from ....projects.groups import GroupError
@@ -87,6 +115,24 @@ def action_hubs(ctx: Context, verb: str, body: dict) -> tuple[dict, int]:
87
115
  moved = ops.connect(ctx.cfg, body.get("group"), hub, leave_on_hub=leave)
88
116
  return {"ok": True, "moved": sum(moved.sessions.values()), "taken": sum(moved.taken.values()),
89
117
  "to": {moved.labels.get(k, k): v for k, v in moved.to.items()}}, 200
118
+ if verb in ("push", "leave"):
119
+ key = str(body.get("hub") or "")
120
+ reg = ctx.cfg.profiles
121
+ hub_id = "personal" if key.strip().casefold() == "personal" else ops.find_profile(ctx.cfg.home, key).id
122
+ hcfg = _hub_cfg(ctx, hub_id, reg)
123
+ if hcfg is None or not hcfg.is_spoke:
124
+ return {"error": tr("{hub} hasn't joined a hub yet.", hub=key)}, 409
125
+ if verb == "push":
126
+ from ....sharing.push import push
127
+
128
+ return {"ok": True, "started": ctx.jobs.start("push", lambda progress: push(hcfg, progress=progress)
129
+ .summary())}, 200
130
+ from ....sharing.client import leave_hub
131
+
132
+ left = leave_hub(hcfg)
133
+ if hub_id == "personal":
134
+ ctx.cfg = left
135
+ return {"ok": True, "hub": hcfg.hub_url}, 200
90
136
  if verb == "choose":
91
137
  moved = ops.choose(ctx.cfg, str(body.get("folder") or ""), str(body.get("hub") or ""), leave_on_hub=leave)
92
138
  return {"ok": True, "moved": sum(moved.sessions.values()), "taken": sum(moved.taken.values())}, 200
@@ -156,12 +156,13 @@ def status_small(ctx: Context, limited: bool = False) -> dict:
156
156
  if limited: # the hub's own queue, jobs and updates are not theirs to see
157
157
  return {"pending": {"ready": 0, "queued": 0}, "analysis": {"auto": False, "max_per_run": 0, "label": ""}, "paused_until": None,
158
158
  "last_sync": None, "jobs": {}, "version": __version__, "update": None, "ui_build": UI_BUILD,
159
- "hub_url": None, "hub_problem": None, "limited": True}
159
+ "hub_url": None, "hub_urls": [], "hub_problem": None, "limited": True}
160
160
 
161
161
  recall(ctx.conn) # a check made by another dashboard process, or before a restart
162
162
  _maybe_check_daily(ctx)
163
163
 
164
164
  pending = count_pending(ctx.conn, ctx.cfg)
165
+ sending = _sending_to(ctx)
165
166
  return {
166
167
  "pending": pending,
167
168
  "analysis": {"auto": ctx.cfg.analysis.auto, "max_per_run": ctx.cfg.analysis.max_per_run,
@@ -175,14 +176,35 @@ def status_small(ctx: Context, limited: bool = False) -> dict:
175
176
  "update": available(),
176
177
  "ui_build": UI_BUILD,
177
178
  "hub_url": ctx.cfg.hub_url or None, # set on a computer that sends its sessions to a hub
178
- "hub_problem": _hub_problem(ctx), # its pushes don't get through: the status bar warns
179
+ "hub_urls": [c.hub_url for c in sending], # and the other hubs it sends to (docs/profiles.md)
180
+ "hub_problem": _hub_problem(sending), # its pushes don't get through: the status bar warns
179
181
  }
180
182
 
181
183
 
182
- def _hub_problem(ctx: Context) -> dict | None:
184
+ def _sending_to(ctx: Context) -> list:
185
+ """The configs that send to a hub: Personal's (when it joined one), then each other hub this computer joined."""
186
+ from ....application.profiles import joined
187
+
188
+ return ([ctx.cfg] if ctx.cfg.is_spoke else []) + joined(ctx.cfg)
189
+
190
+
191
+ def _hub_problem(sending: list) -> dict | None:
192
+ """The first hub whose sends don't get through, with its name when it isn't Personal's (`profile`)."""
193
+ from ....core.profiles import PERSONAL
183
194
  from ....sharing.push import last_push, send_problem
184
195
 
185
- return send_problem(last_push(ctx.cfg)) if ctx.cfg.is_spoke else None
196
+ for cfg in sending:
197
+ if problem := send_problem(last_push(cfg)):
198
+ if cfg.owner != PERSONAL:
199
+ from ....core.profiles import RegistryError
200
+
201
+ try:
202
+ reg = cfg.profiles
203
+ except RegistryError:
204
+ reg = None
205
+ problem["profile"] = reg.label(cfg.owner) if reg else cfg.owner
206
+ return problem
207
+ return None
186
208
 
187
209
 
188
210
  def status(ctx: Context) -> dict:
@@ -363,8 +363,17 @@ def _hub_signin(h, ctx, m, body):
363
363
  from ...sharing.client import dashboard_signin
364
364
  from ...sharing.protocol import HubError
365
365
 
366
+ cfg = ctx.cfg
367
+ if str(body.get("hub") or "personal").strip().casefold() != "personal": # another hub: signed in as its own link
368
+ from ...application.profiles import ProfileError, find_profile
369
+ from ...core.config import load_config
370
+
371
+ try:
372
+ cfg = load_config(find_profile(ctx.cfg.home, str(body["hub"])).home, create=False)
373
+ except ProfileError as exc:
374
+ return h._json({"error": str(exc)}, 400)
366
375
  try:
367
- return h._json({"url": dashboard_signin(ctx.cfg, page=body.get("next"))})
376
+ return h._json({"url": dashboard_signin(cfg, page=body.get("next"))})
368
377
  except HubError as exc:
369
378
  return h._json({"error": tr(str(exc))}, 400)
370
379
 
@@ -430,7 +439,7 @@ POST: list[Route] = [
430
439
  Route(r"/api/projects/shared/(add|remove)", HERE_OR_HUB_ADMIN, lambda h, ctx, m, b: h._json(
431
440
  *api.devices.action_shared_project(ctx, m.group(1), _body(b), by=h.viewer, here=h._from_here()))),
432
441
  # which hub each group goes to, and joining one: what leaves this computer, only from here
433
- Route(r"/api/hubs/(add|join|remove|connect|choose)", HERE,
442
+ Route(r"/api/hubs/(add|join|remove|connect|choose|push|leave)", HERE,
434
443
  lambda h, ctx, m, b: h._json(*api.hubs.action_hubs(ctx, m.group(1), _body(b)))),
435
444
  Route("/api/project-groups/share", HERE, # what leaves this computer: only from here
436
445
  lambda h, ctx, m, b: h._json(*api.projects.action_project_groups(ctx, "share", _body(b)))),
@@ -2336,6 +2336,12 @@ td.pg-cell { width: 1%; text-align: right; }
2336
2336
  /* On a computer that sends to a hub: the hub's projects, each over the folders here that go to it (projectsSidebar) */
2337
2337
  .sb-hub-head .sb-hub-ic { flex: none; width: 14px; height: 14px; margin-left: -4px; color: var(--hub-ink); }
2338
2338
  .sb-row.sb-hubproj { font-weight: 600; }
2339
+ /* a group connected to another hub names it; folders waiting for a hub come first (docs/profiles.md) */
2340
+ .sb-fold-head .sb-hub-badge { flex: none; max-width: 45%; display: inline-flex; align-items: center; gap: 3px; padding: 0 6px; border-radius: 999px;
2341
+ font-size: 11px; font-weight: 600; line-height: 18px; color: var(--hub-ink); background: color-mix(in srgb, var(--hub-ink) 12%, transparent); }
2342
+ .sb-hub-badge .icon { flex: none; width: 11px; height: 11px; }
2343
+ .sb-wait-head .sb-wait-ic { flex: none; width: 14px; height: 14px; margin-left: -4px; color: var(--warning-ink); }
2344
+ .sb-waiting > .sb-row .icon { color: var(--warning-ink); }
2339
2345
  .sb-row.sb-hubproj .sb-ext { display: none; width: 12px; height: 12px; }
2340
2346
  .sb-row.sb-hubproj:is(:hover, :focus-visible) .sb-ext { display: block; }
2341
2347
  .sb-row.sb-hubproj:is(:hover, :focus-visible) em { display: none; }