interlatch 0.29.0__tar.gz → 0.29.2__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 (533) hide show
  1. {interlatch-0.29.0 → interlatch-0.29.2}/CHANGELOG.md +28 -0
  2. {interlatch-0.29.0 → interlatch-0.29.2}/PKG-INFO +1 -1
  3. {interlatch-0.29.0 → interlatch-0.29.2}/ROADMAP.ja.md +0 -4
  4. {interlatch-0.29.0 → interlatch-0.29.2}/ROADMAP.md +0 -6
  5. interlatch-0.29.2/changelog.d/hub-glossary-members.md +4 -0
  6. interlatch-0.29.2/changelog.d/hub-project-page.md +6 -0
  7. {interlatch-0.29.0 → interlatch-0.29.2}/docs/dashboard.md +35 -5
  8. {interlatch-0.29.0 → interlatch-0.29.2}/docs/demo/make_demo.py +71 -1
  9. {interlatch-0.29.0 → interlatch-0.29.2}/docs/design/innerlatch.md +16 -4
  10. {interlatch-0.29.0 → interlatch-0.29.2}/docs/design/ja/innerlatch.md +14 -3
  11. {interlatch-0.29.0 → interlatch-0.29.2}/docs/development.md +6 -0
  12. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/dashboard.md +32 -3
  13. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/development.md +6 -0
  14. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/party.md +18 -0
  15. {interlatch-0.29.0 → interlatch-0.29.2}/docs/party.md +22 -1
  16. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/i18n/ja.py +9 -0
  17. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/party.py +88 -0
  18. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/projects.py +40 -7
  19. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/handler.py +13 -2
  20. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/routes.py +6 -3
  21. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/gates.py +8 -3
  22. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/hero.py +5 -5
  23. interlatch-0.29.2/src/interlatch/knowledge/interview.py +298 -0
  24. interlatch-0.29.2/src/interlatch/knowledge/jobprep.py +273 -0
  25. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/jobs.py +30 -4
  26. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/party.py +8 -4
  27. interlatch-0.29.2/src/interlatch/projects/team.py +199 -0
  28. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/access.py +35 -4
  29. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/adventure.js +29 -1
  30. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/app.css +28 -0
  31. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/app.js +252 -16
  32. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/battle.js +6 -1
  33. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/field.js +19 -7
  34. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/innerlatch.css +30 -0
  35. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/innerlatch.js +167 -9
  36. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/ja.js +103 -0
  37. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_battle_web.py +14 -0
  38. interlatch-0.29.2/tests/test_interview.py +168 -0
  39. interlatch-0.29.2/tests/test_jobprep.py +146 -0
  40. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_jobs.py +13 -0
  41. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_party_map.py +1 -1
  42. interlatch-0.29.2/tests/test_project_team.py +248 -0
  43. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_route_matrix.py +6 -0
  44. interlatch-0.29.0/changelog.d/innerlatch-gates.md +0 -5
  45. interlatch-0.29.0/changelog.d/innerlatch-hero.md +0 -5
  46. interlatch-0.29.0/changelog.d/innerlatch-job-goal.md +0 -4
  47. {interlatch-0.29.0 → interlatch-0.29.2}/.github/dependabot.yml +0 -0
  48. {interlatch-0.29.0 → interlatch-0.29.2}/.github/windows-ja-qa/driver.ps1 +0 -0
  49. {interlatch-0.29.0 → interlatch-0.29.2}/.github/windows-ja-qa/ja_check.py +0 -0
  50. {interlatch-0.29.0 → interlatch-0.29.2}/.github/windows-ja-qa/report.py +0 -0
  51. {interlatch-0.29.0 → interlatch-0.29.2}/.github/windows-ja-qa/shots.py +0 -0
  52. {interlatch-0.29.0 → interlatch-0.29.2}/.github/windows-ja-qa/user.ps1 +0 -0
  53. {interlatch-0.29.0 → interlatch-0.29.2}/.github/workflows/changelog.yml +0 -0
  54. {interlatch-0.29.0 → interlatch-0.29.2}/.github/workflows/ci.yml +0 -0
  55. {interlatch-0.29.0 → interlatch-0.29.2}/.github/workflows/docs.yml +0 -0
  56. {interlatch-0.29.0 → interlatch-0.29.2}/.github/workflows/release.yml +0 -0
  57. {interlatch-0.29.0 → interlatch-0.29.2}/.github/workflows/windows-ja-qa.yml +0 -0
  58. {interlatch-0.29.0 → interlatch-0.29.2}/.gitignore +0 -0
  59. {interlatch-0.29.0 → interlatch-0.29.2}/.pre-commit-config.yaml +0 -0
  60. {interlatch-0.29.0 → interlatch-0.29.2}/.python-version +0 -0
  61. {interlatch-0.29.0 → interlatch-0.29.2}/CONTRIBUTING.md +0 -0
  62. {interlatch-0.29.0 → interlatch-0.29.2}/LICENSE +0 -0
  63. {interlatch-0.29.0 → interlatch-0.29.2}/README.ja.md +0 -0
  64. {interlatch-0.29.0 → interlatch-0.29.2}/README.md +0 -0
  65. {interlatch-0.29.0 → interlatch-0.29.2}/SECURITY.md +0 -0
  66. {interlatch-0.29.0 → interlatch-0.29.2}/careers/README.md +0 -0
  67. {interlatch-0.29.0 → interlatch-0.29.2}/careers/boards.json +0 -0
  68. {interlatch-0.29.0 → interlatch-0.29.2}/careers/pipeline.py +0 -0
  69. {interlatch-0.29.0 → interlatch-0.29.2}/changelog.d/README.md +0 -0
  70. {interlatch-0.29.0 → interlatch-0.29.2}/dev.sh +0 -0
  71. {interlatch-0.29.0 → interlatch-0.29.2}/docker/.dockerignore +0 -0
  72. {interlatch-0.29.0 → interlatch-0.29.2}/docker/.env.example +0 -0
  73. {interlatch-0.29.0 → interlatch-0.29.2}/docker/Caddyfile +0 -0
  74. {interlatch-0.29.0 → interlatch-0.29.2}/docker/Dockerfile +0 -0
  75. {interlatch-0.29.0 → interlatch-0.29.2}/docker/compose.yaml +0 -0
  76. {interlatch-0.29.0 → interlatch-0.29.2}/docker/wheels/.gitignore +0 -0
  77. {interlatch-0.29.0 → interlatch-0.29.2}/docs/README.md +0 -0
  78. {interlatch-0.29.0 → interlatch-0.29.2}/docs/_site/hooks.py +0 -0
  79. {interlatch-0.29.0 → interlatch-0.29.2}/docs/analysis.md +0 -0
  80. {interlatch-0.29.0 → interlatch-0.29.2}/docs/cli.md +0 -0
  81. {interlatch-0.29.0 → interlatch-0.29.2}/docs/configuration.md +0 -0
  82. {interlatch-0.29.0 → interlatch-0.29.2}/docs/demo/record_demo.py +0 -0
  83. {interlatch-0.29.0 → interlatch-0.29.2}/docs/design/ja/learning.md +0 -0
  84. {interlatch-0.29.0 → interlatch-0.29.2}/docs/design/learning.md +0 -0
  85. {interlatch-0.29.0 → interlatch-0.29.2}/docs/devices.md +0 -0
  86. {interlatch-0.29.0 → interlatch-0.29.2}/docs/diagrams/analysis.excalidraw.svg +0 -0
  87. {interlatch-0.29.0 → interlatch-0.29.2}/docs/diagrams/architecture.excalidraw.svg +0 -0
  88. {interlatch-0.29.0 → interlatch-0.29.2}/docs/docker.md +0 -0
  89. {interlatch-0.29.0 → interlatch-0.29.2}/docs/faq.md +0 -0
  90. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/demo.gif +0 -0
  91. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/group-connections.png +0 -0
  92. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/hero.png +0 -0
  93. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/home.png +0 -0
  94. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/job-goal.png +0 -0
  95. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/map.png +0 -0
  96. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/palette.png +0 -0
  97. {interlatch-0.29.0 → interlatch-0.29.2}/docs/images/session.png +0 -0
  98. {interlatch-0.29.0 → interlatch-0.29.2}/docs/install.md +0 -0
  99. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/README.md +0 -0
  100. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/analysis.md +0 -0
  101. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/cli.md +0 -0
  102. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/configuration.md +0 -0
  103. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/devices.md +0 -0
  104. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/docker.md +0 -0
  105. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/faq.md +0 -0
  106. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/install.md +0 -0
  107. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/join-a-hub.md +0 -0
  108. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/mcp.md +0 -0
  109. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/moving-from-chronicle.md +0 -0
  110. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/postgres.md +0 -0
  111. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/privacy.md +0 -0
  112. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/profiles.md +0 -0
  113. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/sources.md +0 -0
  114. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/suggestions.md +0 -0
  115. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/troubleshooting.md +0 -0
  116. {interlatch-0.29.0 → interlatch-0.29.2}/docs/ja/vscode.md +0 -0
  117. {interlatch-0.29.0 → interlatch-0.29.2}/docs/join-a-hub.md +0 -0
  118. {interlatch-0.29.0 → interlatch-0.29.2}/docs/mcp.md +0 -0
  119. {interlatch-0.29.0 → interlatch-0.29.2}/docs/moving-from-chronicle.md +0 -0
  120. {interlatch-0.29.0 → interlatch-0.29.2}/docs/postgres.md +0 -0
  121. {interlatch-0.29.0 → interlatch-0.29.2}/docs/privacy.md +0 -0
  122. {interlatch-0.29.0 → interlatch-0.29.2}/docs/profiles.md +0 -0
  123. {interlatch-0.29.0 → interlatch-0.29.2}/docs/sources.md +0 -0
  124. {interlatch-0.29.0 → interlatch-0.29.2}/docs/suggestions.md +0 -0
  125. {interlatch-0.29.0 → interlatch-0.29.2}/docs/troubleshooting.md +0 -0
  126. {interlatch-0.29.0 → interlatch-0.29.2}/docs/vscode.md +0 -0
  127. {interlatch-0.29.0 → interlatch-0.29.2}/leaderboard/.firebaserc +0 -0
  128. {interlatch-0.29.0 → interlatch-0.29.2}/leaderboard/.gitignore +0 -0
  129. {interlatch-0.29.0 → interlatch-0.29.2}/leaderboard/README.md +0 -0
  130. {interlatch-0.29.0 → interlatch-0.29.2}/leaderboard/firebase.json +0 -0
  131. {interlatch-0.29.0 → interlatch-0.29.2}/leaderboard/firestore.indexes.json +0 -0
  132. {interlatch-0.29.0 → interlatch-0.29.2}/leaderboard/firestore.rules +0 -0
  133. {interlatch-0.29.0 → interlatch-0.29.2}/mkdocs.yml +0 -0
  134. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/README.md +0 -0
  135. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/art.json +0 -0
  136. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/filing.html +0 -0
  137. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/loops.json +0 -0
  138. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/loops.py +0 -0
  139. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/members.js +0 -0
  140. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/render.html +0 -0
  141. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/render.py +0 -0
  142. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/scenes-more.js +0 -0
  143. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/icons3d/scenes.html +0 -0
  144. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/Chronicle.icns +0 -0
  145. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/Interlatch.spec +0 -0
  146. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/build.sh +0 -0
  147. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/entitlements.plist +0 -0
  148. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/icon-3d.webp +0 -0
  149. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/icon-blueprint-prompt.md +0 -0
  150. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/icon-blueprint.webp +0 -0
  151. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/icon.png +0 -0
  152. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/interlatch_app.py +0 -0
  153. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/macos/make_icon.py +0 -0
  154. {interlatch-0.29.0 → interlatch-0.29.2}/packaging/release.py +0 -0
  155. {interlatch-0.29.0 → interlatch-0.29.2}/pyproject.toml +0 -0
  156. {interlatch-0.29.0 → interlatch-0.29.2}/src/chronicle/__init__.py +0 -0
  157. {interlatch-0.29.0 → interlatch-0.29.2}/src/chronicle/__main__.py +0 -0
  158. {interlatch-0.29.0 → interlatch-0.29.2}/src/chronicle/windows.py +0 -0
  159. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/__init__.py +0 -0
  160. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/__main__.py +0 -0
  161. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/__init__.py +0 -0
  162. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/digest.py +0 -0
  163. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/language.py +0 -0
  164. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/queue.py +0 -0
  165. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/__init__.py +0 -0
  166. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/api.py +0 -0
  167. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/base.py +0 -0
  168. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/bob.py +0 -0
  169. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/claude.py +0 -0
  170. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/codex.py +0 -0
  171. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/factory.py +0 -0
  172. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/off.py +0 -0
  173. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/opencode.py +0 -0
  174. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/process.py +0 -0
  175. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/replies.py +0 -0
  176. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/runners/settings.py +0 -0
  177. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/screen.py +0 -0
  178. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/session.py +0 -0
  179. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/analysis/worker.py +0 -0
  180. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/application/__init__.py +0 -0
  181. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/application/profiles.py +0 -0
  182. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/application/records.py +0 -0
  183. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/application/search.py +0 -0
  184. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/application/workflows.py +0 -0
  185. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/artifacts/__init__.py +0 -0
  186. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/artifacts/files.py +0 -0
  187. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/artifacts/queries.py +0 -0
  188. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/cli.py +0 -0
  189. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/__init__.py +0 -0
  190. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/agents.py +0 -0
  191. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/artifact_records.py +0 -0
  192. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/budget.py +0 -0
  193. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/config.py +0 -0
  194. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/diagrams.py +0 -0
  195. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/i18n/__init__.py +0 -0
  196. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/machine.py +0 -0
  197. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/paths.py +0 -0
  198. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/pricing.py +0 -0
  199. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/process.py +0 -0
  200. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/profiles.py +0 -0
  201. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/redact.py +0 -0
  202. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/sessions.py +0 -0
  203. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/core/util.py +0 -0
  204. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/__init__.py +0 -0
  205. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/analyses.py +0 -0
  206. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/archive.py +0 -0
  207. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/chat_import.py +0 -0
  208. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/deletion.py +0 -0
  209. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/history.py +0 -0
  210. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/memory.py +0 -0
  211. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/persistence.py +0 -0
  212. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/report.py +0 -0
  213. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/ingestion/service.py +0 -0
  214. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/__init__.py +0 -0
  215. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/__init__.py +0 -0
  216. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/__init__.py +0 -0
  217. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/archive.py +0 -0
  218. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/hubs.py +0 -0
  219. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/knowledge.py +0 -0
  220. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/operations.py +0 -0
  221. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/recording.py +0 -0
  222. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/setup.py +0 -0
  223. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/commands/sharing.py +0 -0
  224. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/common.py +0 -0
  225. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/main.py +0 -0
  226. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/cli/parser.py +0 -0
  227. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/exports/__init__.py +0 -0
  228. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/exports/diagrams.py +0 -0
  229. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/exports/markdown.py +0 -0
  230. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/exports/sessions.py +0 -0
  231. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/exports/vault.py +0 -0
  232. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/mcp.py +0 -0
  233. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/__init__.py +0 -0
  234. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/__init__.py +0 -0
  235. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/artifacts.py +0 -0
  236. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/common.py +0 -0
  237. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/devices.py +0 -0
  238. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/hub_admin.py +0 -0
  239. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/hubs.py +0 -0
  240. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/knowledge.py +0 -0
  241. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/leaderboard.py +0 -0
  242. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/sessions.py +0 -0
  243. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/settings.py +0 -0
  244. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/sources.py +0 -0
  245. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/status.py +0 -0
  246. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/storage.py +0 -0
  247. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/api/team.py +0 -0
  248. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/app.py +0 -0
  249. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/assets.py +0 -0
  250. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/context.py +0 -0
  251. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/jobs.py +0 -0
  252. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/interfaces/web/server.py +0 -0
  253. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/__init__.py +0 -0
  254. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/arena.py +0 -0
  255. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/bag.py +0 -0
  256. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/cases.py +0 -0
  257. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/formation.py +0 -0
  258. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/freshness.py +0 -0
  259. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/friction.py +0 -0
  260. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/glossary.py +0 -0
  261. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/group_graph.py +0 -0
  262. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/instructions.py +0 -0
  263. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/ladder.py +0 -0
  264. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/learning.py +0 -0
  265. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/market.json +0 -0
  266. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/reviews.py +0 -0
  267. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/roadmap.json +0 -0
  268. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/study.py +0 -0
  269. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/suggest.py +0 -0
  270. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/synthesize.py +0 -0
  271. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/knowledge/weekly.py +0 -0
  272. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/__init__.py +0 -0
  273. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/groups.py +0 -0
  274. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/hubgroups.py +0 -0
  275. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/labels.py +0 -0
  276. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/owners.py +0 -0
  277. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/progress.py +0 -0
  278. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/resume.py +0 -0
  279. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/routing.py +0 -0
  280. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/scope.py +0 -0
  281. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/projects/systems.py +0 -0
  282. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/__init__.py +0 -0
  283. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/connectors.py +0 -0
  284. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/container.py +0 -0
  285. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/feedback.py +0 -0
  286. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/hooks.py +0 -0
  287. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/install.py +0 -0
  288. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/migrate.py +0 -0
  289. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/notify.py +0 -0
  290. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/platforms/__init__.py +0 -0
  291. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/platforms/desktop.py +0 -0
  292. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/platforms/menubar.py +0 -0
  293. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/platforms/windows.py +0 -0
  294. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/statusline.py +0 -0
  295. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/tailnet.py +0 -0
  296. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/runtime/update.py +0 -0
  297. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/__init__.py +0 -0
  298. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/arena.py +0 -0
  299. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/client.py +0 -0
  300. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/identity.py +0 -0
  301. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/leaderboard.py +0 -0
  302. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/market.py +0 -0
  303. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/membership.py +0 -0
  304. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/news.py +0 -0
  305. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/people.py +0 -0
  306. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/projects.py +0 -0
  307. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/protocol.py +0 -0
  308. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/pull.py +0 -0
  309. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/push.py +0 -0
  310. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sharing/receiver.py +0 -0
  311. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/__init__.py +0 -0
  312. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/antigravity.py +0 -0
  313. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/bob.py +0 -0
  314. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/builder.py +0 -0
  315. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/chatgpt.py +0 -0
  316. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/chats.py +0 -0
  317. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/claude/__init__.py +0 -0
  318. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/claude/export.py +0 -0
  319. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/claude/files.py +0 -0
  320. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/claude/parser.py +0 -0
  321. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/codex/__init__.py +0 -0
  322. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/codex/cloud.py +0 -0
  323. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/codex/parser.py +0 -0
  324. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/copilot.py +0 -0
  325. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/discovery.py +0 -0
  326. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/opencode.py +0 -0
  327. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/sources/prompts.py +0 -0
  328. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/__init__.py +0 -0
  329. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/fts.py +0 -0
  330. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/kv.py +0 -0
  331. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/migrations.py +0 -0
  332. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/mirror.py +0 -0
  333. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/postgres.py +0 -0
  334. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/schema.py +0 -0
  335. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/sqlite.py +0 -0
  336. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/storage/team.py +0 -0
  337. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/AGENT-ICONS.txt +0 -0
  338. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/PLEX-OFL.txt +0 -0
  339. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-antigravity.svg +0 -0
  340. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-bob.svg +0 -0
  341. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-chatgpt.svg +0 -0
  342. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-claude-ai.svg +0 -0
  343. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-claude.svg +0 -0
  344. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-codex.svg +0 -0
  345. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-copilot.svg +0 -0
  346. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/agent-opencode.svg +0 -0
  347. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-book.webp +0 -0
  348. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-camera.webp +0 -0
  349. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-chip.webp +0 -0
  350. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-clock.webp +0 -0
  351. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-cloud.webp +0 -0
  352. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-coins.webp +0 -0
  353. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-container.webp +0 -0
  354. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-dashboard.webp +0 -0
  355. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-dex.webp +0 -0
  356. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-document.webp +0 -0
  357. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-flag.webp +0 -0
  358. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-folder.webp +0 -0
  359. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-gateway.webp +0 -0
  360. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-gears.webp +0 -0
  361. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-glitch.webp +0 -0
  362. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-globe.webp +0 -0
  363. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-laptop.webp +0 -0
  364. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-log.webp +0 -0
  365. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-lumi.webp +0 -0
  366. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-magnifier.webp +0 -0
  367. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-pip.webp +0 -0
  368. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-plug.webp +0 -0
  369. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-rack.webp +0 -0
  370. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/art-tink.webp +0 -0
  371. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/boot.js +0 -0
  372. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/favicon.png +0 -0
  373. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/i18n.js +0 -0
  374. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/icon-180.png +0 -0
  375. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/icon-192.png +0 -0
  376. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/icon-512.png +0 -0
  377. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/icon.png +0 -0
  378. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/index.html +0 -0
  379. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/learning.js +0 -0
  380. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/manifest.webmanifest +0 -0
  381. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/panel.css +0 -0
  382. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/panel.html +0 -0
  383. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/panel.js +0 -0
  384. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/plex-mono-400.woff2 +0 -0
  385. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/plex-mono-500.woff2 +0 -0
  386. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/plex-mono-600.woff2 +0 -0
  387. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/plex-sans-400.woff2 +0 -0
  388. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/plex-sans-500.woff2 +0 -0
  389. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/plex-sans-600.woff2 +0 -0
  390. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/plex-sans-700.woff2 +0 -0
  391. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/rough.js +0 -0
  392. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/scene.js +0 -0
  393. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/signin.js +0 -0
  394. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/web/sprites.js +0 -0
  395. {interlatch-0.29.0 → interlatch-0.29.2}/src/interlatch/windows.py +0 -0
  396. {interlatch-0.29.0 → interlatch-0.29.2}/tests/antigravity_fixture.py +0 -0
  397. {interlatch-0.29.0 → interlatch-0.29.2}/tests/codex_fixture.py +0 -0
  398. {interlatch-0.29.0 → interlatch-0.29.2}/tests/conftest.py +0 -0
  399. {interlatch-0.29.0 → interlatch-0.29.2}/tests/copilot_fixture.py +0 -0
  400. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/0.21.3/chronicle.db +0 -0
  401. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/0.21.3/expected.json +0 -0
  402. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/0.27.8/chronicle.db +0 -0
  403. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/0.27.8/expected.json +0 -0
  404. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/0.5.0/chronicle.db +0 -0
  405. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/0.5.0/expected.json +0 -0
  406. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/README.md +0 -0
  407. {interlatch-0.29.0 → interlatch-0.29.2}/tests/fixtures/db/make_fixture.py +0 -0
  408. {interlatch-0.29.0 → interlatch-0.29.2}/tests/friction_fixture.py +0 -0
  409. {interlatch-0.29.0 → interlatch-0.29.2}/tests/golden.py +0 -0
  410. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/cli.json +0 -0
  411. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/diagram.json +0 -0
  412. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/parsers/antigravity.json +0 -0
  413. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/parsers/bob.json +0 -0
  414. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/parsers/claude_code.json +0 -0
  415. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/parsers/codex.json +0 -0
  416. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/parsers/copilot.json +0 -0
  417. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/parsers/opencode.json +0 -0
  418. {interlatch-0.29.0 → interlatch-0.29.2}/tests/goldens/systems.json +0 -0
  419. {interlatch-0.29.0 → interlatch-0.29.2}/tests/hubs_fixture.py +0 -0
  420. {interlatch-0.29.0 → interlatch-0.29.2}/tests/opencode_fixture.py +0 -0
  421. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_adventure_web.py +0 -0
  422. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_analysis.py +0 -0
  423. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_antigravity.py +0 -0
  424. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_architecture.py +0 -0
  425. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_arena.py +0 -0
  426. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_artifacts.py +0 -0
  427. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_bag.py +0 -0
  428. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_bob_analysis.py +0 -0
  429. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_boot_web.py +0 -0
  430. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_careers.py +0 -0
  431. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_case_files.py +0 -0
  432. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_cases.py +0 -0
  433. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_chat_import.py +0 -0
  434. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_cli_pins.py +0 -0
  435. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_codex.py +0 -0
  436. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_codex_analysis.py +0 -0
  437. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_codex_cloud.py +0 -0
  438. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_container.py +0 -0
  439. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_copilot_bob.py +0 -0
  440. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_db_compat.py +0 -0
  441. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_dedicated_hub.py +0 -0
  442. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_dedupe.py +0 -0
  443. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_desktop.py +0 -0
  444. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_diagram.py +0 -0
  445. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_doctor_agents.py +0 -0
  446. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_ee_boundary.py +0 -0
  447. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_feedback.py +0 -0
  448. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_field_web.py +0 -0
  449. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_fix_effect.py +0 -0
  450. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_formation.py +0 -0
  451. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_friction.py +0 -0
  452. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_game_mode.py +0 -0
  453. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_gates.py +0 -0
  454. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_glossary.py +0 -0
  455. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_group_graph.py +0 -0
  456. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_group_sharing.py +0 -0
  457. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_guidance.py +0 -0
  458. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hero.py +0 -0
  459. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_home_agents.py +0 -0
  460. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub.py +0 -0
  461. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_accept.py +0 -0
  462. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_cookie.py +0 -0
  463. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_groups.py +0 -0
  464. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_inventory_scope.py +0 -0
  465. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_leave_join.py +0 -0
  466. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_news.py +0 -0
  467. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_payload_privacy.py +0 -0
  468. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_projects.py +0 -0
  469. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_projects_listed.py +0 -0
  470. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_purge.py +0 -0
  471. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_send_problems.py +0 -0
  472. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_hub_sharing_race.py +0 -0
  473. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_i18n_web.py +0 -0
  474. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_ingest.py +0 -0
  475. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_instructions.py +0 -0
  476. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_integration.py +0 -0
  477. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_knowledge_freshness.py +0 -0
  478. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_ladder.py +0 -0
  479. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_language.py +0 -0
  480. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_leaderboard.py +0 -0
  481. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_learning_glance.py +0 -0
  482. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_learning_interests.py +0 -0
  483. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_learning_web.py +0 -0
  484. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_leave_project.py +0 -0
  485. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_legacy_package.py +0 -0
  486. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_map_goldens.py +0 -0
  487. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_market.py +0 -0
  488. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_mcp_resume.py +0 -0
  489. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_menubar.py +0 -0
  490. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_migrate.py +0 -0
  491. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_mirror.py +0 -0
  492. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_notify.py +0 -0
  493. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_opencode.py +0 -0
  494. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_opencode_analysis.py +0 -0
  495. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_parser.py +0 -0
  496. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_parser_goldens.py +0 -0
  497. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_party.py +0 -0
  498. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_people.py +0 -0
  499. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_people_hub.py +0 -0
  500. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_people_web.py +0 -0
  501. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_profile_hubs.py +0 -0
  502. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_profile_scope.py +0 -0
  503. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_profiles.py +0 -0
  504. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_project_groups.py +0 -0
  505. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_project_progress.py +0 -0
  506. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_providers.py +0 -0
  507. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_queue.py +0 -0
  508. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_regressions.py +0 -0
  509. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_release.py +0 -0
  510. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_roadmap_catalog.py +0 -0
  511. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_screen.py +0 -0
  512. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_security.py +0 -0
  513. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_session_context_budget.py +0 -0
  514. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_setup.py +0 -0
  515. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_statusline.py +0 -0
  516. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_study.py +0 -0
  517. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_suggest.py +0 -0
  518. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_suggest_cli.py +0 -0
  519. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_systems.py +0 -0
  520. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_team.py +0 -0
  521. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_team_home.py +0 -0
  522. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_update.py +0 -0
  523. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_weekly_reanalysis.py +0 -0
  524. {interlatch-0.29.0 → interlatch-0.29.2}/tests/test_windows.py +0 -0
  525. {interlatch-0.29.0 → interlatch-0.29.2}/tests/windows_smoke.py +0 -0
  526. {interlatch-0.29.0 → interlatch-0.29.2}/uv.lock +0 -0
  527. {interlatch-0.29.0 → interlatch-0.29.2}/vscode-extension/.vscodeignore +0 -0
  528. {interlatch-0.29.0 → interlatch-0.29.2}/vscode-extension/LICENSE +0 -0
  529. {interlatch-0.29.0 → interlatch-0.29.2}/vscode-extension/README.md +0 -0
  530. {interlatch-0.29.0 → interlatch-0.29.2}/vscode-extension/extension.js +0 -0
  531. {interlatch-0.29.0 → interlatch-0.29.2}/vscode-extension/media/icon.png +0 -0
  532. {interlatch-0.29.0 → interlatch-0.29.2}/vscode-extension/media/interlatch.svg +0 -0
  533. {interlatch-0.29.0 → interlatch-0.29.2}/vscode-extension/package.json +0 -0
@@ -3,6 +3,34 @@
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.29.1 (2026-10-25)
7
+
8
+ - **The interview, your job goal's final boss:** three questions a day, written from the job description and from
9
+ your own past lessons, graded strong, fair or weak with what a strong answer covers and a better one from your own
10
+ work. It's practice until every must-have tower is lit; then two strong answers and none weak beat it and crown
11
+ the castle ([The interview](docs/party.md#the-interview)).
12
+ - **A job goal brings its own monsters:** practice battles written for each of its requirements, more where your gap
13
+ is bigger, roam their zones marked ♜ and count toward each module's gate like your own lessons, so even a skill with
14
+ no past lessons has a way in. The world map flags each requirement, the field shows the next tower to work on, and
15
+ your hero now leads the party in battle ([Job monsters](docs/party.md#job-monsters)).
16
+
17
+ ## 0.29.0 (2026-10-24)
18
+
19
+ - **You are the hero in Innerlatch:** the Party now starts with a character you make (a name and a pixel look) on a
20
+ career path you choose: a roadmap track, or the Generalist path of the modules most tracks share. Your hero levels
21
+ up only from the lessons you answer right in study battles (past answers count too), and shows your readiness in each
22
+ of your path's modules. Your coding agents become your companions, their levels unchanged
23
+ ([You, the hero](docs/party.md#you-the-hero)).
24
+ - **Gate bosses in Innerlatch:** five lessons understood in a module open its gate, a stone arch on the field and a
25
+ link on your hero's card. Rank 1 asks for an explanation in your own words; ranks 2 to 4 for your own pull requests,
26
+ commits or documents and what they show. The analysis model judges it against the module's check: a pass raises your
27
+ rank there and your hero's XP, a "not yet" says what's missing and the gate opens again tomorrow. Your hero now leads
28
+ the party on the field ([Gates](docs/party.md#gates)).
29
+ - **A job goal in Innerlatch:** paste a real job description and your analysis model maps it to the roadmap modules
30
+ and ranks it asks for, each with the line it came from; what the roadmap doesn't cover is listed apart. The job is a
31
+ castle whose towers light only with the ranks you show at gates, with the track that fits it best and the gates to
32
+ take next; its modules lead the field ([Job goal](docs/party.md#job-goal)).
33
+
6
34
  ## 0.28.8 (2026-10-22)
7
35
 
8
36
  - **A sign-in page that looks like Interlatch:** opening a hub's sign-in or invite link now shows the dashboard's own
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: interlatch
3
- Version: 0.29.0
3
+ Version: 0.29.2
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/
@@ -56,10 +56,6 @@ Interlatch にこれから入るものを、おおよそ取り組む順に並べ
56
56
  作りません)。エージェントには今までどおりすべての教訓を渡します。効果は、尋ねるのではなく、思い出せたかと、同じ gotcha が
57
57
  あなたのセッションでまた起きるかで測り、一人ひとりの指標はすべてあなたのコンピューターに残します
58
58
  ([設計](docs/design/ja/learning.md))。
59
- - **主人公はあなた、目指すは実際の仕事。** Innerlatch の冒険では、学びの戦闘で正解した教訓が、すでに
60
- 各ロードマップのモジュールの準備度として数えられ、主人公はそれでレベルが上がり、モジュールのゲートでは、分析モデルが判定する
61
- あなた自身の言葉と仕事でそこのランクが上がり、貼りつけた求人の説明が、求めるモジュールとランクに対応づけられて目標に
62
- なります。これから: その仕事とあなた自身の過去の仕事から書く面接の問いを、最後のボスにします([設計](docs/design/ja/innerlatch.md#2-主人公))。
63
59
  - **人の名前で、並べて見るチームメイトの教訓。** チームメイトの教訓は、プロジェクトのページと **All knowledge** に、
64
60
  どのコンピューターから来たかを示して表示されます。これから: コンピューター名ではなく人の名前で示すこと、週次レビューに
65
61
  チームメイトの教訓を入れること、2 人が述べた教訓を両方の事件として見せること([設計](docs/design/ja/learning.md#4-チーム))。
@@ -60,12 +60,6 @@ carefully.
60
60
  getting every lesson. Whether it works is measured by recall and by whether the same gotcha comes back in your
61
61
  sessions, not by asking, and every per-person measure stays on your computer
62
62
  ([design](docs/design/learning.md)).
63
- - **You as the hero, toward a real job.** In Innerlatch's Adventure, the lessons you answer right in study
64
- battles count toward your readiness in each roadmap module, your hero levels up from them, and at a module's gate
65
- your own words and work, judged by the analysis model, raise your rank there; a job description you paste is the
66
- goal, mapped to the modules and ranks it asks for. Still to come: interview questions written from that job and
67
- your own past work, as its final boss
68
- ([design](docs/design/innerlatch.md#2-the-hero)).
69
63
  - **Teammates' lessons, by person and side by side.** They show on project pages and in **All knowledge**, marked
70
64
  with the computers they came from. Still to come: the person's name instead of the computer's, teammates' lessons
71
65
  in the weekly review, and a lesson two people stated shown as both their cases
@@ -0,0 +1,4 @@
1
+ - **A project's glossary and mindmap on a team hub:** a project's page there has a **Glossary & map** tab: its terms
2
+ as a list or a mindmap. Teammates limited to some projects now see it too, with the terms their projects use and
3
+ what their projects say of them, never what another project wrote
4
+ ([On a team hub](docs/dashboard.md#on-a-team-hub)).
@@ -0,0 +1,6 @@
1
+ - **A project's page on a team hub:** the team's knowledge leads. Each knowledge base entry and lesson names whose
2
+ sessions taught it, lessons two people found separately sit side by side, **Since your last visit** lists new and
3
+ replaced lessons, **Start here** greets someone new to the project, **People** shows who has worked on what (never
4
+ a count per person), and **Who's working on it** draws each person's sessions over eight weeks. Tokens and cost
5
+ move to an admin-only Usage tab, and the Systems map is no longer offered where it would be empty or refused
6
+ ([On a team hub](docs/dashboard.md#on-a-team-hub)).
@@ -133,11 +133,41 @@ The other tabs hold the rest: **Working here** (the knowledge base, its [archite
133
133
  and the glossary), **Knowledge**, **Sessions**, **Artifacts** and **Usage** (the totals and the most edited files).
134
134
  The tab you pick stays in the address, so a link or a reload opens it again.
135
135
 
136
- The git rows and the roadmap file are read only in a browser on the computer the folder is on. On a hub with people,
137
- the cards are **Needs attention** and **Where the team left off**, and each session shows whose it is. Pull requests come
138
- from the transcripts computers send (`share = "everything"`), or from the links a session lists when a computer shares
139
- knowledge; commits only from transcripts. Someone limited to some projects sees the sessions, not their pull requests,
140
- as on a session's page.
136
+ The git rows and the roadmap file are read only in a browser on the computer the folder is on.
137
+
138
+ ### On a team hub
139
+
140
+ On a hub with people, a project's page is written for a teammate rather than for "you, coming back", and the team's
141
+ knowledge leads. It is still read from what computers shared, with nothing written by a model:
142
+
143
+ - **Overview:** the knowledge base's three headline points, with how many lessons arrived since it was last written
144
+ (or, when the hub has no analysis engine, why there is none). **Since your last visit:** the sessions, new lessons
145
+ and pull requests since you last opened the page, the lessons a newer one replaced (outdated or contradicted, and
146
+ whether it was yours) and the ones someone else found again. Pages you open within half an hour are one visit, so a
147
+ reload doesn't empty it. Beside it, **Needs attention** and **Only one person has worked on** (topics from one
148
+ person's sessions only: worth asking them, or pairing on it). Below, **Who's working on it**: each person's sessions
149
+ over the last eight weeks as dots, sized by active time and coloured by outcome, with a table view.
150
+ - **Start here:** the gotchas and fixes, decisions and commands the team learned, the most trusted first, and who to
151
+ ask. Someone with no sessions in the project opens the page here.
152
+ - **Knowledge base:** each entry names whose sessions taught it ("learned by"), with a badge when more than one person
153
+ found it. **Hit by more than one person** puts the sessions in which different people found the same lesson side by
154
+ side.
155
+ - **Glossary & map:** the project's terms as a list or as a mindmap (category, then theme), for everyone who sees the
156
+ project. Someone limited to some projects gets the terms their projects use, each with what their projects say of
157
+ it: a term's definition shows when one of their projects wrote it, and otherwise their project's own note on it.
158
+ What a term gathers across projects (aliases, related terms, how often it was mentioned, the sessions it came up in
159
+ most, a theme's description) isn't shown to them.
160
+ - **Lessons:** every lesson with who it was learned from, narrowed to a person or a kind, or the lessons a newer one
161
+ replaced.
162
+ - **People:** who has worked on what, as topics from their sessions here.
163
+ - **Activity:** **Where the team left off**, **Week by week** and the sessions. **Usage** (tokens, cost, most edited
164
+ files) is for admins only.
165
+
166
+ People are credited, never counted: the page shows no lessons, sessions or time per person. Pull requests come from
167
+ the transcripts computers send (`share = "everything"`), or from the links a session lists when a computer shares
168
+ knowledge; commits only from transcripts. Someone limited to some projects sees their projects only, and the sessions,
169
+ not their pull requests, as on a session's page. The Systems map isn't offered on a hub that takes knowledge only (it
170
+ reads the commands sessions ran, which stay on members' computers), nor to someone limited to projects.
141
171
 
142
172
  ## Project groups
143
173
 
@@ -3,6 +3,9 @@
3
3
  uv run python docs/demo/make_demo.py /tmp/interlatch-demo
4
4
  INTERLATCH_HOME=/tmp/interlatch-demo/home uv run python -m interlatch ui --port 8898 --open
5
5
 
6
+ With --hub, the demo computer is then a team hub with people: Ada at the hub, Yuma and Ueno sending from their own
7
+ computers, each with some of the sessions, so a project's page shows the team's side (whose sessions taught what).
8
+
6
9
  It writes synthetic Claude Code transcripts for a fictional developer (five projects, about six weeks), then runs the
7
10
  real pipeline over them: sync, analysis, knowledge bases, glossary and weekly reviews. Then a project group with its
8
11
  Mindmap analyzed, and game mode on with a hero in Innerlatch: a path, lessons studied, gates passed and a job goal.
@@ -554,7 +557,8 @@ print(json.dumps({"type": "result", "subtype": "success", "is_error": False, "re
554
557
 
555
558
 
556
559
  def main() -> None:
557
- out = Path(sys.argv[1] if len(sys.argv) > 1 else "/tmp/interlatch-demo").resolve()
560
+ paths = [a for a in sys.argv[1:] if not a.startswith("--")]
561
+ out = Path(paths[0] if paths else "/tmp/interlatch-demo").resolve()
558
562
  if out.exists():
559
563
  shutil.rmtree(out)
560
564
  claude_dir, home, bindir = out / "claude", out / "home", out / "bin"
@@ -609,6 +613,8 @@ def main() -> None:
609
613
  week = (now - timedelta(weeks=w)).strftime("%G-W%V")
610
614
  chronicle("review", week)
611
615
  subprocess.run([sys.executable, __file__, "--group-and-hero", str(home)], env=env, check=True)
616
+ if "--hub" in sys.argv:
617
+ subprocess.run([sys.executable, __file__, "--team-hub", str(home)], env=env, check=True)
612
618
  print(f"\nDemo ready. Open it with:\n INTERLATCH_HOME={home} uv run python -m interlatch ui --port 8898 --open")
613
619
 
614
620
 
@@ -647,8 +653,72 @@ def group_and_hero(home: Path) -> None:
647
653
  jobs.add(conn, cfg, cat, None, title=JOB["title"], company=JOB["company"], text=JOB["text"])
648
654
 
649
655
 
656
+ TEAM = (("Yuma", "yuma@example.com", ["billing-api", "storefront"]), ("Ueno", "ueno@example.com", None))
657
+ SHARED = ("billing-api", "storefront", "infra") # the projects whose sessions the team splits
658
+
659
+
660
+ def team_hub(home: Path) -> None:
661
+ """The demo computer as a team hub with people (--hub): Ada, an admin, works at the hub; Yuma (limited to two
662
+ projects) and Ueno send from their own computers. The sessions of SHARED are split between the three, a lesson of
663
+ each project is stated again in a teammate's session, and one is replaced by a newer one, so a project's page has
664
+ whose-sessions-taught-what, side-by-side cases and "since your last visit" to show. Prints a sign-in link each."""
665
+ from interlatch.core.config import load_config, set_config_value
666
+ from interlatch.core.machine import local_machine_id
667
+ from interlatch.core.util import to_iso, utcnow
668
+ from interlatch.projects.team import VISIT_KV
669
+ from interlatch.sharing import people
670
+ from interlatch.sharing.identity import new_token
671
+ from interlatch.storage.kv import kv_set
672
+ from interlatch.storage.sqlite import connect
673
+
674
+ cfg = load_config(home)
675
+ new_token(cfg)
676
+ set_config_value(cfg, "hub", "name", '"Acme team"')
677
+ conn = connect(cfg.db_path)
678
+ here = local_machine_id(cfg)
679
+ ada = people.add(conn, "Ada Lovelace", "ada@example.com", "admin")
680
+ conn.execute("UPDATE machines SET person_id = ? WHERE id = ?", (ada["id"], here))
681
+ links, machines = {"Ada Lovelace": people.invite(conn, ada["id"])}, [here]
682
+ for i, (name, email, projects) in enumerate(TEAM):
683
+ person = people.add(conn, name, email, "member", by=ada, projects=[f"{ROOT}/{p}" for p in projects] if projects else None)
684
+ mid = str(uuid.UUID(int=0xD3E0 + i, version=4))
685
+ conn.execute("INSERT INTO machines(id, name, role, first_seen, last_seen) VALUES (?, ?, 'spoke', ?, ?)",
686
+ (mid, f"{name.lower()}-laptop", to_iso(utcnow()), to_iso(utcnow())))
687
+ people.join_computer(conn, people.invite(conn, person["id"], machine=mid), mid, f"{name.lower()}-laptop")
688
+ links[name] = people.invite(conn, person["id"])
689
+ machines.append(mid)
690
+ rng = random.Random(11)
691
+ for project in SHARED:
692
+ sids = [r[0] for r in conn.execute("SELECT id FROM sessions WHERE project_path = ? ORDER BY started_at", (f"{ROOT}/{project}",))]
693
+ owner = {sid: machines[(i + rng.randrange(2)) % len(machines)] for i, sid in enumerate(sids)}
694
+ for sid, mid in owner.items():
695
+ conn.execute("UPDATE sessions SET machine_id = ? WHERE id = ?", (mid, sid))
696
+ lesson = conn.execute("SELECT id, session_id, confirmed_json FROM knowledge WHERE project_path = ? AND status = 'active' "
697
+ "AND kind IN ('gotcha', 'fix') ORDER BY id LIMIT 1", (f"{ROOT}/{project}",)).fetchone()
698
+ other = next((sid for sid in sids if lesson and owner.get(sid) != owner.get(lesson["session_id"])), None)
699
+ if other: # a teammate hit the same thing in a session of their own
700
+ confirmed = json.loads(lesson["confirmed_json"] or "[]") or [lesson["session_id"]]
701
+ conn.execute("UPDATE knowledge SET confirmed_json = ?, stage = 'established' WHERE id = ?",
702
+ (json.dumps([*confirmed, other]), lesson["id"]))
703
+ newest, older = conn.execute("SELECT id FROM knowledge WHERE project_path = ? AND status = 'active' ORDER BY id DESC LIMIT 2",
704
+ (f"{ROOT}/billing-api",)).fetchall()
705
+ conn.execute("UPDATE knowledge SET status = 'superseded', superseded_by = ?, superseded_reason = 'outdated', superseded_at = ? "
706
+ "WHERE id = ?", (newest[0], to_iso(utcnow() - timedelta(hours=20)), older[0]))
707
+ kid = conn.execute("SELECT MAX(id) FROM knowledge").fetchone()[0]
708
+ for (pid,) in conn.execute("SELECT id FROM people").fetchall(): # each last looked two days ago, before the newest lessons
709
+ for project in PROJECTS:
710
+ kv_set(conn, f"{VISIT_KV}p:{pid}:{ROOT}/{project}",
711
+ json.dumps({"seen": to_iso(utcnow() - timedelta(days=2)), "kid": kid - 4, "prev": None, "prev_kid": None}))
712
+ conn.commit()
713
+ print("\nTeam hub ready. Sign in as (open on the hub's address):")
714
+ for name, code in links.items():
715
+ print(f" {name}: /signin?code={code}")
716
+
717
+
650
718
  if __name__ == "__main__":
651
719
  if sys.argv[1:2] == ["--group-and-hero"]:
652
720
  group_and_hero(Path(sys.argv[2]))
721
+ elif sys.argv[1:2] == ["--team-hub"]:
722
+ team_hub(Path(sys.argv[2]))
653
723
  else:
654
724
  main()
@@ -3,7 +3,7 @@
3
3
  [← Roadmap](../../ROADMAP.md) · 日本語: [ja/innerlatch.md](ja/innerlatch.md) · Related: [lessons people learn from](learning.md)
4
4
 
5
5
  Status: study battles built in 0.27.3 (2026-10-18); the hero (section 2), gate bosses (section 7) and the job goal
6
- (section 8) built in October 2026. The interview boss (section 10) is still to come. The user guide is [Adventure](../party.md#adventure).
6
+ (section 8) with its interview built in October 2026. The user guide is [Adventure](../party.md#adventure).
7
7
 
8
8
  Innerlatch is the game behind the door at the bottom of the dashboard's rail. **You are the hero:** a character you
9
9
  make, on a career path you choose, who beats the lessons of your own past work and levels up toward a real job. Your
@@ -267,11 +267,23 @@ The goal at the end of the path: a real job you want.
267
267
  card and the Party's sidebar: the world map's layout had no room for it), one tower per requirement. A tower lights
268
268
  when your rank reaches what it needs. The match is the must-haves lit out of all must-haves, with the ranks still to
269
269
  go; readiness shows apart from it, as gates you could take next.
270
+ - **Job monsters.** A job brings its own enemies, so every requirement has some from the day it's added, one with
271
+ none of your own lessons included. Per requirement the model writes practice battles (study battles' shape) from the
272
+ posting's line, the module's study topics and your lessons there; how many follows the gap: 2, plus 2 a rank still
273
+ to go, plus 2 for a must-have, 2 fewer where you have 10 or more lessons of your own, between 3 and 10. They roam the
274
+ module's zone marked ♜, come back on the same spacing, and each one understood counts toward the module's gate as a
275
+ lesson does; ranks still need your own work there. A lit tower's monsters leave. On the world map each requirement is
276
+ a ♜ flag on its territory that takes you there. `src/interlatch/knowledge/jobprep.py`, `GET`/`POST /api/party/prep`.
270
277
  - **Steering the path.** The job suggests the track whose targets fit its requirements best; switching is your call.
271
278
  The job's modules lead the field (section 4).
272
279
  - **Several jobs.** Keep as many as you like; one is active at a time.
273
- - **Later: the final boss.** Interview questions written from the job description and grounded in your own past
274
- work, answered like a gate.
280
+ - **The final boss: the interview.** On the job's page. A sitting asks three questions, one per requirement
281
+ (must-haves first, unlit and weakest first, a different set each time), each written from the job description and
282
+ grounded in up to three of your own lessons in that module ("In <project>, you …: how would you …"). The model grades
283
+ each answer strong, fair or weak, says why, lists what a strong answer covers and sketches a better one from your own
284
+ work. Until every must-have tower is lit it is practice; then the boss is awake, and two strong answers with none
285
+ weak beat it and crown the castle. One sitting a day; it moves no rank and no XP. `knowledge/interview.py`,
286
+ `GET`/`POST /api/party/interview`.
275
287
 
276
288
  ## 9. Measuring it
277
289
 
@@ -287,7 +299,7 @@ One pull request each, judged before the next:
287
299
  card at the top of the Party page, companions under it.
288
300
  2. **Gate bosses** (section 7), which move the ranks.
289
301
  3. **The job goal** (section 8): paste, mapping, the castle, the match, the field led by its modules.
290
- 4. **The final boss**, later.
302
+ 4. **The final boss**, the interview (section 8).
291
303
 
292
304
  ## Not doing
293
305
 
@@ -3,7 +3,7 @@
3
3
  [← ロードマップ](../../../ROADMAP.ja.md) · English: [innerlatch.md](../innerlatch.md) · 関連: [人が学べる教訓](learning.md)
4
4
 
5
5
  状態: 学びの戦闘は 0.27.3(2026-10-18)で、主人公(2 節)、ゲートのボス(7 節)、仕事の目標(8 節)は 2026 年 10 月に
6
- できています。面接のボス(10 節)はこれからです。使い方は[冒険](../../ja/party.md#冒険)にあります。
6
+ 面接と一緒にできています。使い方は[冒険](../../ja/party.md#冒険)にあります。
7
7
 
8
8
  Innerlatch は、ダッシュボードのレールのいちばん下にある扉の奥のゲームです。**主人公はあなたです。** あなたが作った
9
9
  キャラクターが、自分で選んだキャリアの道を進み、自分の過去の仕事の教訓を倒してレベルを上げ、実際の仕事を目指します。
@@ -262,10 +262,21 @@ Innerlatch は、ダッシュボードのレールのいちばん下にある扉
262
262
  ワールドマップの配置には置く場所がありませんでした)の城になり、要件ごとに塔が 1 つあります。あなたのランクが必要なランクに
263
263
  届くと塔に灯がともります。合っている度合いは、必須の要件のうち灯がともったものの割合で、あといくつランクが要るかも
264
264
  出ます。準備度はそれとは別に、次に挑めるゲートとして出ます。
265
+ - **仕事のモンスター。** 仕事は自分のモンスターを連れてくるので、加えた日からどの要件にも敵がいます。自分の教訓がない要件も
266
+ です。要件ごとにモデルが、求人の行、モジュールの学習テーマ、そこでのあなたの教訓から練習の戦闘(学びの戦闘の形)を書きます。
267
+ 数は差しだいです:2 体、足りないランク 1 つにつき 2 体、必須ならさらに 2 体、自分の教訓が 10 以上あれば 2 体少なく、3〜10 体。
268
+ そのモジュールのゾーンを ♜ をつけて歩き、同じ間隔で戻ってきて、理解したものは教訓と同じくそのモジュールのゲートに数えられます。
269
+ ランクはそこで自分の仕事を示してはじめて上がります。塔に灯がともると、そのモンスターは去ります。ワールドマップでは要件ごとに、
270
+ その領地に ♜ の旗が立ち、そこへ連れていきます。`src/interlatch/knowledge/jobprep.py`、`GET`/`POST /api/party/prep`。
265
271
  - **道を寄せる。** 仕事は、目標が要件にいちばん合うトラックを勧めます。乗り換えるかはあなたが決めます。フィールドでは
266
272
  仕事のモジュールが先に出ます(4 節)。
267
273
  - **いくつもの仕事。** いくつでも残せます。有効なのは一度に 1 つです。
268
- - **あとで: 最後のボス。** 求人の説明から書き、あなた自身の過去の仕事にもとづく面接の問いで、ゲートと同じように答えます。
274
+ - **最後のボス: 面接。** 仕事のページにあります。1 回の面接で、要件ごとに 1 つ、3 つの問いが出ます(必須が先、灯のない
275
+ もの・遠いものが先、毎回ちがう組み合わせ)。どれも求人の説明から書かれ、そのモジュールのあなた自身の教訓 3 つまでにもとづきます
276
+ (「<プロジェクト> で、あなたは…:どうしますか」)。モデルが答えを強い・まずまず・弱いで判定し、理由、強い答えが触れること、
277
+ あなた自身の仕事からのもっとよい答えを示します。必須の塔すべてに灯がともるまでは練習で、そのあとはボスが目覚め、強い答え 2 つ以上で
278
+ 弱い答えがなければ突破となり、城に冠がつきます。面接は 1 日 1 回で、ランクも経験値も動きません。`knowledge/interview.py`、
279
+ `GET`/`POST /api/party/interview`。
269
280
 
270
281
  ## 9. 効果の測り方
271
282
 
@@ -280,7 +291,7 @@ Innerlatch は、ダッシュボードのレールのいちばん下にある扉
280
291
  いちばん上の主人公のカードと、その下の仲間。
281
292
  2. **ゲートのボス**(7 節)。ランクを動かします。
282
293
  3. **仕事の目標**(8 節)。貼りつけ、対応づけ、城、合っている度合い、仕事のモジュールが先に出るフィールド。
283
- 4. **最後のボス**、あとで。
294
+ 4. **最後のボス**、面接(8 節)。
284
295
 
285
296
  ## やらないこと
286
297
 
@@ -215,6 +215,12 @@ uv run python docs/demo/make_demo.py /tmp/interlatch-demo
215
215
  INTERLATCH_HOME=/tmp/interlatch-demo/home uv run python -m interlatch ui --port 8898 --open
216
216
  ```
217
217
 
218
+ With `--hub`, the demo computer then becomes a team hub with people: Ada, an admin, works at the hub, and Yuma (who
219
+ sees only *billing-api* and *storefront*) and Ueno send from their own computers. Their sessions of three projects
220
+ are split between them, so a project's page shows [the team's side](dashboard.md#on-a-team-hub). It prints a sign-in
221
+ link for each person; open one from another device, or through a proxy, to see the hub as that person (a browser at
222
+ the hub itself is always its admin).
223
+
218
224
  The README's GIF and tour video come from it too. With that dashboard running, `docs/demo/record_demo.py` drives
219
225
  headless Chromium through a scripted tour (it needs `ffmpeg` on PATH). It writes the whole tour to
220
226
  `docs/images/demo.mp4`, which git ignores, and a few seconds of it, under the 600 KB the large-file hook allows, to
@@ -82,10 +82,39 @@ macOS 以外では ⌘ の代わりに Ctrl を使います。macOS アプリで
82
82
  ほかのタブ:**作業の手引き**(ナレッジベース、[アーキテクチャ図](#アーキテクチャ図)、用語集)、**ナレッジ**、**セッション**、
83
83
  **成果物**、**使用量**(合計と編集の多いファイル)。選んだタブはアドレスに残るので、リンクや再読み込みでも同じタブが開きます。
84
84
 
85
- git の行とロードマップのファイルは、フォルダーがあるコンピューター上のブラウザーでだけ読み取ります。人のいるハブでは、カードは
86
- **要対応**と**チームが中断したところ**になり、各セッションに誰のものかが出ます。プルリクエストは、コンピューターが送る
85
+ git の行とロードマップのファイルは、フォルダーがあるコンピューター上のブラウザーでだけ読み取ります。
86
+
87
+ ### チームのハブでは
88
+
89
+ 人のいるハブでは、プロジェクトのページは「戻ってきた自分」ではなくチームメイトのために書かれ、チームのナレッジが先頭に来ます。
90
+ 内容はコンピューターが共有したものから読み取り、モデルが書くものはありません。
91
+
92
+ - **概要:** ナレッジベースの要点 3 つと、最後に作成した後に届いた教訓の数(ハブに分析エンジンがない場合は、ナレッジベースが
93
+ ない理由)。**前回の訪問以降:** 前回このページを開いてからのセッション、新しい教訓、プルリクエスト、新しい教訓に置き換えられた
94
+ 教訓(古くなったか矛盾したか、あなたの教訓だったか)、ほかの人も見つけた教訓。30 分以内に開いたページは 1 回の訪問として
95
+ 扱うので、再読み込みしても消えません。横に**要対応**と**一人だけが取り組んだテーマ**(一人のセッションにしか出てこない
96
+ テーマ。その人に聞くか、一緒に取り組む価値があります)。下に**誰が取り組んでいるか**: 直近 8 週間の各人のセッションを点で
97
+ 表示し、大きさは作業時間、色は結果です。表でも見られます。
98
+ - **はじめに:** チームが学んだ落とし穴と修正、決定、コマンドを信頼度の高い順に並べ、誰に聞くかも示します。このプロジェクトに
99
+ セッションがない人は、ここからページが開きます。
100
+ - **ナレッジベース:** 各項目に、どの人のセッションから学んだか(「から学んだ教訓」)を示し、複数の人が見つけた項目には
101
+ バッジが付きます。**複数の人が遭遇した教訓**では、別々の人が同じ教訓を見つけたセッションを並べて表示します。
102
+ - **用語集とマップ:** プロジェクトの用語を、一覧またはマインドマップ(カテゴリー、次にテーマ)で表示します。プロジェクトを
103
+ 見られる人なら誰でも見られます。一部のプロジェクトだけを見られる人には、そのプロジェクトが使う用語を、そのプロジェクトでの
104
+ 説明とともに表示します。用語の定義は、その人のプロジェクトが書いたものだけを表示し、それ以外はそのプロジェクトでの使われ方の
105
+ メモを代わりに表示します。複数のプロジェクトにまたがる情報(別名、関連する用語、言及の回数、よく出てきたセッション、テーマの
106
+ 説明)は表示しません。
107
+ - **教訓:** すべての教訓を、誰から学んだかとともに表示します。人や種類で絞り込んだり、新しい教訓に置き換えられた教訓を表示
108
+ したりできます。
109
+ - **利用者:** 誰が何に取り組んだかを、このプロジェクトでのセッションのテーマで示します。
110
+ - **アクティビティ:** **チームが中断したところ**、**週ごと**、セッション。**使用量**(トークン、コスト、編集の多いファイル)は
111
+ 管理者だけに表示します。
112
+
113
+ 人の名前は出しますが、数えません。人ごとの教訓、セッション、時間の数は表示しません。プルリクエストは、コンピューターが送る
87
114
  トランスクリプト(`share = "everything"`)から、ナレッジを共有するコンピューターではセッションが記録しているリンクから表示します。
88
- コミットはトランスクリプトからだけです。一部のプロジェクトだけを見られる人には、セッションのページと同じく、プルリクエストは表示しません。
115
+ コミットはトランスクリプトからだけです。一部のプロジェクトだけを見られる人には、そのプロジェクトだけを、セッションのページと同じく
116
+ プルリクエストなしで表示します。システムマップは、ナレッジだけを受け取るハブ(セッションが実行したコマンドを読むため、
117
+ メンバーのコンピューターに残ります)と、一部のプロジェクトだけを見られる人には表示しません。
89
118
 
90
119
  ## プロジェクトのグループ
91
120
 
@@ -201,6 +201,12 @@ uv run python docs/demo/make_demo.py /tmp/interlatch-demo
201
201
  INTERLATCH_HOME=/tmp/interlatch-demo/home uv run python -m interlatch ui --port 8898 --open
202
202
  ```
203
203
 
204
+ `--hub` を付けると、そのあとデモのコンピューターが人のいるチームのハブになります。管理者の Ada がハブで作業し、Yuma
205
+ (*billing-api* と *storefront* だけを見られます)と Ueno が自分のコンピューターから送ります。3 つのプロジェクトのセッションを
206
+ 3 人で分けるので、プロジェクトのページに[チームの側](dashboard.md#チームのハブでは)が表示されます。各人のサインイン用のリンクを
207
+ 表示します。その人としてハブを見るには、別のデバイスかプロキシ経由で開いてください(ハブのコンピューター上のブラウザーは常に
208
+ 管理者です)。
209
+
204
210
  README の GIF とツアー動画もこのデータから作ります。そのダッシュボードを動かしたまま `docs/demo/record_demo.py` を実行すると、
205
211
  ヘッドレスの Chromium が決まった順にダッシュボードを巡ります(`ffmpeg` が PATH に必要です)。ツアー全体は git が無視する
206
212
  `docs/images/demo.mp4` に、その数秒は大きなファイルを止めるフックが許す 600 KB 以内で `docs/images/demo.gif` に書き出されます。
@@ -81,6 +81,24 @@ Innerlatch の扉は、Google でサインインするまで開きません。
81
81
  仕事にいちばん合うトラックが出て、**このトラックを道にする**で道にできます。フィールドでは仕事のモジュールにモンスターが多く出て、
82
82
  ♜ の印がつきます。仕事は 20 件まで残せ、有効なのは一度に 1 つです。説明はこのコンピューターに残り、分析モデルにだけ送られます。
83
83
 
84
+ ### 仕事のモンスター
85
+
86
+ 仕事は自分のモンスターを連れてきます。仕事を加えると、モデルが要件ごとに、求人の行、モジュールの学習テーマ、そこでのあなた自身の教訓
87
+ から練習の戦闘を書きます。差が大きいほど多く出ます(2 体、足りないランク 1 つにつき 2 体、必須ならさらに 2 体、自分の教訓が十分に
88
+ あれば 2 体少なく。3〜10 体)。仕事の目標のページが、要件ごとに順に呼び出します。フィールドではそのゾーンを金色の ♜ をつけて歩き、
89
+ 学びの戦闘と同じように戦えて、正解するたびに、自分の教訓と同じくそのモジュールのゲートに近づきます。自分の教訓がない要件でも、
90
+ ゲートへの道があります。塔に灯がともると、そのモンスターは去ります。ワールドマップでは要件ごとに、その領地に ♜ の旗が立ちます
91
+ (必須は赤、灯がともると金)。押すとそこへ狩りに行けて、ゲートが開いていればゲートへ行きます。フィールドの帯には、仕事、次に取り組む
92
+ 塔、そのゲートまでの近さが出ます。どの戦闘でも主人公がパーティーの先頭に立ち、その教訓のエージェントが隣に並びます。
93
+
94
+ ### 面接
95
+
96
+ 仕事のページのいちばん下に、その**最後のボス、面接**が待っています。1 回の面接では、求人の説明から書かれ、あなた自身の過去の教訓に
97
+ もとづく 3 つの問いが出ます(「あなたのプロジェクトで、あなたは…:どうしますか」)。それぞれ数文で答えると、モデルが強い・まずまず・
98
+ 弱いで判定し、理由、強い答えが触れること、あなた自身の仕事からのもっとよい答えを示します。必須の塔すべてに灯がともるまでは練習です。
99
+ ともったあとは面接官が目覚め、強い答え 2 つ以上で弱い答えがなければ突破となり、城に冠(♛)がつきます。面接は 1 日 1 回で、毎回
100
+ ちがう問いが出ます。ランクも経験値も動きません。
101
+
84
102
  エージェントはあなたの**仲間**で、主人公の下に並びます。仲間のレベルはその教訓がカバーしていることを示し、あなたのレベルを
85
103
  動かすことはなく、あなたのレベルが仲間のレベルを動かすこともありません。主人公、答え、道はこのコンピューターに残ります。
86
104
  ハブにサインインしているときは主人公はおらず、アリーナは仲間だけのままです。
@@ -86,9 +86,30 @@ the mapping fails, or you disagree with it, **Map again** or **Pick by hand**.
86
86
  The job is a **castle**, one tower per requirement (a must-have stands taller). A tower lights when your rank in its
87
87
  module, shown at its gate, reaches what the job asks: your hero's level never counts. The page shows the must-haves lit,
88
88
  the ranks still to go, the gates you could take next, and the track that fits the job best, with **Follow this track**
89
- to make it your path. The job's modules hold more monsters on the field, marked ♜. Keep up to 20 jobs, one active at a
89
+ to make it your path. The job's zones hold more monsters on the field, marked ♜. Keep up to 20 jobs, one active at a
90
90
  time. The description stays on this computer and goes only to your analysis model.
91
91
 
92
+ ### Job monsters
93
+
94
+ A job brings its own enemies. When it's added, the model writes practice battles for each requirement, from the
95
+ posting's line, the module's study topics and your own lessons there: more where the gap is bigger (2, plus 2 for each
96
+ rank still to go, plus 2 for a must-have, 2 fewer where you already have plenty of lessons; 3 to 10). The Job goal page
97
+ summons them one requirement at a time. They roam their zones on the field with a gold ♜ over them and fight like study
98
+ battles, and each one you get right counts toward that module's gate, like your own lessons: a requirement you have no
99
+ lessons for still has a way to its gate. Once its tower is lit, its monsters leave. On the world map each requirement is
100
+ a ♜ flag on its territory (red for a must-have, gold once lit); click it to go hunting there, or to its gate when it's
101
+ open. On the field, a strip names the job, the next tower to work on and how close its gate is. Your hero leads the
102
+ party in every battle, with the lesson's agent beside you.
103
+
104
+ ### The interview
105
+
106
+ At the bottom of the job's page waits its **final boss: the interview**. Each sitting asks three questions written from
107
+ the job description and grounded in your own past lessons ("In your project, you …: how would you …"). Answer each in
108
+ a few sentences; the model grades it strong, fair or weak, says why, lists what a strong answer covers and sketches a
109
+ better one from your own work. Until every must-have tower is lit, a sitting is practice. Once they are, the
110
+ interviewer is awake: two strong answers and none weak beat it, and the castle gets its crown (♛). One sitting a day,
111
+ with new questions each time. It changes no rank and no XP.
112
+
92
113
  Your agents are your **companions**, listed under the hero. Their levels show what their lessons cover; they never
93
114
  move yours, and yours never moves theirs. Your hero, your answers and your path are kept on this computer: signed in to
94
115
  a hub, there is no hero, and the Arena stays companions only.
@@ -217,6 +217,7 @@ JA: dict[str, str] = {
217
217
  "forbidden": "許可されていません",
218
218
  "not found": "見つかりません",
219
219
  "bad json": "JSON が正しくありません",
220
+ "that's more than it can take: make it shorter": "大きすぎて受け取れません。短くしてください",
220
221
  "empty upload": "アップロードが空です",
221
222
  "upload cut off": "アップロードが途中で切れました",
222
223
  "unknown connector": "そのソースはありません",
@@ -377,6 +378,14 @@ JA: dict[str, str] = {
377
378
  "your job goals are kept on your own computer": "仕事の目標はあなた自身のコンピューターに残ります",
378
379
  "no such job": "その仕事はありません",
379
380
  "unknown action": "その操作はありません",
381
+ "interviews are taken on your own computer": "面接を受けるのはあなた自身のコンピューターです",
382
+ "set a mapped job goal first": "先に、対応づけた仕事の目標を設定してください",
383
+ "you sat this interview today: it opens again tomorrow": "今日この面接を受けました。明日また受けられます",
384
+ "start the interview first": "先に面接を始めてください",
385
+ "job monsters are fought on your own computer": "仕事のモンスターと戦うのはあなた自身のコンピューターです",
386
+ "no such job monster": "その仕事のモンスターはいません",
387
+ "answer every question in a few sentences: at least {n} characters each": "どの問いにも数文で答えてください(それぞれ {n} 文字以上)",
388
+ "keep each answer under {n} characters": "答えはそれぞれ {n} 文字以内にしてください",
380
389
  "paste the whole job description: at least {n} characters": "求人の説明を全部貼りつけてください({n} 文字以上)",
381
390
  "that's longer than a job description: keep it under {n} characters": "求人の説明としては長すぎます。{n} 文字以内にしてください",
382
391
  "you can keep {n} jobs: remove one first": "残せる仕事は {n} 件です。先に 1 件消してください",
@@ -281,6 +281,94 @@ def action_party_job(ctx: Context, viewer: dict | None, body: dict, *, here: boo
281
281
  return jb.view(ctx.conn, cat, _here_id(ctx)), 200
282
282
 
283
283
 
284
+ # ------------------------------------------------------------------ the interview (knowledge/interview.py): the final
285
+ # boss, questions from the active job and the person's own past work; only at their own computer
286
+ def interview(ctx: Context, viewer: dict | None) -> tuple[dict, int]:
287
+ """GET /api/party/interview: the active job's interview: awake or practice, today's questions, the last sitting."""
288
+ from ....knowledge import interview as iv
289
+ from ....knowledge import party as pt
290
+
291
+ if who(ctx, viewer) is None:
292
+ return _refused()
293
+ if viewer is not None:
294
+ return {"error": tr(iv.NOT_HERE)}, 403
295
+ return iv.view(ctx.conn, pt.load_catalog(), _here_id(ctx)), 200
296
+
297
+
298
+ def action_party_interview(ctx: Context, viewer: dict | None, body: dict, *, here: bool) -> tuple[dict, int]:
299
+ """POST /api/party/interview {"action": "start"} writes today's questions; {"action": "answer", "answers": [...]}
300
+ grades them. Answers what it did and the interview as it is now."""
301
+ from ....knowledge import interview as iv
302
+ from ....knowledge import party as pt
303
+
304
+ if who(ctx, viewer) is None:
305
+ return _refused()
306
+ if viewer is not None:
307
+ return {"error": tr(iv.NOT_HERE)}, 403
308
+ cat, here_id, act = pt.load_catalog(), _here_id(ctx), body.get("action")
309
+ try:
310
+ if act == "start":
311
+ got = iv.start(ctx.conn, ctx.cfg, cat, here_id, here=True)
312
+ elif act == "answer":
313
+ got = iv.answer(ctx.conn, ctx.cfg, cat, here_id, body.get("answers"), here=True)
314
+ else:
315
+ return {"error": tr("unknown action")}, 400
316
+ except iv.InterviewError as exc:
317
+ return {"error": tr(exc.template, **exc.kw)}, 400
318
+ except Exception as exc: # the model's call failed: nothing was kept
319
+ return {"error": tr(iv.NO_MODEL, reason=str(exc)[:200])}, 502
320
+ return {"result": got, "interview": iv.view(ctx.conn, cat, here_id)}, 200
321
+
322
+
323
+ # ------------------------------------------------------------------ job monsters (knowledge/jobprep.py): the enemies the
324
+ # active job brings to the field; only at the person's own computer
325
+ def prep(ctx: Context, viewer: dict | None, q: dict) -> tuple[dict, int]:
326
+ """GET /api/party/prep?id=<p:…>: one job monster's encounter and its question (never which answer is right)."""
327
+ from ....knowledge import jobprep
328
+ from ....knowledge import party as pt
329
+
330
+ if who(ctx, viewer) is None:
331
+ return _refused()
332
+ if viewer is not None:
333
+ return {"error": tr(jobprep.NOT_HERE)}, 403
334
+ try:
335
+ return {"encounter": jobprep.encounter(ctx.conn, pt.load_catalog(), _here_id(ctx), q.get("id") or ""),
336
+ "ask": jobprep.ask(ctx.conn, q.get("id") or "")}, 200
337
+ except (jobprep.PrepError, KeyError):
338
+ return {"error": tr("not found")}, 404
339
+
340
+
341
+ def action_party_prep(ctx: Context, viewer: dict | None, body: dict, *, here: bool) -> tuple[dict, int]:
342
+ """POST /api/party/prep {"action": "forge"} writes the next requirement's monsters (one requirement a call: the
343
+ page calls again while `left`); {"action": "pick", "id", "choice"} answers one."""
344
+ from ....knowledge import hero, jobprep, study
345
+ from ....knowledge import party as pt
346
+
347
+ if who(ctx, viewer) is None:
348
+ return _refused()
349
+ if viewer is not None:
350
+ return {"error": tr(jobprep.NOT_HERE)}, 403
351
+ act = body.get("action")
352
+ try:
353
+ if act == "forge":
354
+ got = jobprep.forge(ctx.conn, ctx.cfg, pt.load_catalog(), _here_id(ctx), here=True)
355
+ pt.clear_cache()
356
+ return got, 200
357
+ if act == "pick":
358
+ was = hero.total_xp(ctx.conn, study.studied_of(ctx.conn, "here"))
359
+ got = jobprep.pick(ctx.conn, body.get("id"), body.get("choice"), here=True)
360
+ out = {**got, "readiness": pt.adventure_map(ctx.conn, _here_id(ctx), viewer)["readiness"]}
361
+ if hero.load(ctx.conn) is not None:
362
+ now = hero.total_xp(ctx.conn, study.studied_of(ctx.conn, "here"))
363
+ out["hero"] = {"xp": now, "gained": now - was, "level": hero.level_of(now), "was_level": hero.level_of(was)}
364
+ return out, 200
365
+ return {"error": tr("unknown action")}, 400
366
+ except jobprep.PrepError as exc:
367
+ return {"error": tr(exc.template, **exc.kw)}, 400
368
+ except Exception as exc: # the model's call failed: nothing was kept
369
+ return {"error": tr(jobprep.NO_MODEL, reason=str(exc)[:200])}, 502
370
+
371
+
284
372
  # ------------------------------------------------------------------ the Town & gear (knowledge/bag.py)
285
373
  def bag(ctx: Context, viewer: dict | None) -> tuple[dict, int]:
286
374
  """GET /api/party/bag: the viewer's gold, items, what each agent wears and the battle stats it adds."""