remo-cli 4.3.3__tar.gz → 4.3.5__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 (670) hide show
  1. remo_cli-4.3.5/.github/codeql/codeql-config.yml +21 -0
  2. remo_cli-4.3.5/.github/dependabot.yml +75 -0
  3. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/ci.yml +20 -4
  4. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/codeql.yml +1 -0
  5. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/release.yml +2 -2
  6. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/smoke-test-cleanup.yml +1 -1
  7. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/smoke-test.yml +1 -1
  8. remo_cli-4.3.5/.release-please-manifest.json +3 -0
  9. {remo_cli-4.3.3 → remo_cli-4.3.5}/AGENTS.md +18 -2
  10. {remo_cli-4.3.3 → remo_cli-4.3.5}/CHANGELOG.md +17 -0
  11. {remo_cli-4.3.3 → remo_cli-4.3.5}/CLAUDE.md +19 -3
  12. {remo_cli-4.3.3 → remo_cli-4.3.5}/CONTRIBUTING.md +20 -8
  13. {remo_cli-4.3.3 → remo_cli-4.3.5}/PKG-INFO +70 -17
  14. {remo_cli-4.3.3 → remo_cli-4.3.5}/README.md +68 -15
  15. remo_cli-4.3.5/ansible/group_vars/all.yml +50 -0
  16. remo_cli-4.3.5/ansible/roles/nested_docker/defaults/main.yml +31 -0
  17. remo_cli-4.3.5/ansible/roles/nested_docker/tasks/main.yml +260 -0
  18. remo_cli-4.3.5/ansible/roles/nested_docker/templates/devcontainer-shim.sh.j2 +149 -0
  19. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/tasks/configure_dev_tools.yml +12 -0
  20. {remo_cli-4.3.3 → remo_cli-4.3.5}/docker/Dockerfile +1 -1
  21. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/aws.md +1 -1
  22. remo_cli-4.3.5/docs/examples/orbstack-cloud-init-tailscale.yaml +211 -0
  23. remo_cli-4.3.5/docs/examples/orbstack-cloud-init.yaml +185 -0
  24. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/feature-history.md +1 -1
  25. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/hetzner.md +1 -1
  26. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/incus.md +1 -1
  27. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/maintaining-generated-types.md +12 -0
  28. remo_cli-4.3.5/docs/nested-overlayfs.md +201 -0
  29. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/proxmox.md +1 -1
  30. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/web-session-interface.md +68 -11
  31. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/package-lock.json +3 -3
  32. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/package.json +5 -1
  33. remo_cli-4.3.5/frontend/playwright.geometry.config.ts +71 -0
  34. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/openapi.json +31 -1
  35. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/schema.d.ts +70 -0
  36. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AwaitingAdoption.css +7 -0
  37. remo_cli-4.3.5/frontend/src/components/AwaitingAdoption.test.tsx +107 -0
  38. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AwaitingAdoption.tsx +47 -20
  39. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/PairToSync.css +10 -0
  40. remo_cli-4.3.5/frontend/src/components/PairToSync.test.tsx +119 -0
  41. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/PairToSync.tsx +41 -22
  42. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TerminalCard.test.tsx +78 -0
  43. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TerminalCard.tsx +37 -41
  44. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/WorkspacePane.test.tsx +3 -0
  45. remo_cli-4.3.5/frontend/src/terminal/TerminalConnection.test.ts +280 -0
  46. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/TerminalConnection.ts +62 -1
  47. remo_cli-4.3.5/frontend/src/terminal/fitLoop.ts +77 -0
  48. remo_cli-4.3.5/frontend/tests/geometry/global.d.ts +26 -0
  49. remo_cli-4.3.5/frontend/tests/geometry/harness/index.html +27 -0
  50. remo_cli-4.3.5/frontend/tests/geometry/harness/main.tsx +189 -0
  51. remo_cli-4.3.5/frontend/tests/geometry/terminal-fit.spec.ts +269 -0
  52. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tsconfig.json +9 -2
  53. {remo_cli-4.3.3 → remo_cli-4.3.5}/install.sh +3 -3
  54. {remo_cli-4.3.3 → remo_cli-4.3.5}/pyproject.toml +1 -1
  55. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/contracts/pairing-api.md +5 -0
  56. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/contracts/setup-api.md +16 -7
  57. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/data-model.md +1 -1
  58. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/spec.md +5 -3
  59. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/tasks.md +1 -1
  60. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/shell.py +67 -23
  61. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/web_adopt.py +177 -22
  62. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/added.py +2 -0
  63. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/setup.py +65 -8
  64. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/image/test_docker_image.py +2 -2
  65. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_web_adopt_e2e.py +10 -9
  66. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_shell.py +43 -14
  67. remo_cli-4.3.5/tests/unit/cli/test_shell_added.py +149 -0
  68. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_web_adopt_cmd.py +3 -3
  69. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_code.py +6 -2
  70. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_trust.py +261 -2
  71. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_push_self_heal.py +184 -0
  72. remo_cli-4.3.5/tests/unit/test_dependabot_config.py +112 -0
  73. remo_cli-4.3.5/tests/unit/test_devcontainer_shim.py +485 -0
  74. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_docs_examples.py +54 -0
  75. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_setup_api.py +1 -1
  76. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_setup_dormancy.py +53 -11
  77. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_terminal_resize.py +66 -0
  78. {remo_cli-4.3.3 → remo_cli-4.3.5}/uv.lock +1 -1
  79. remo_cli-4.3.3/.github/dependabot.yml +0 -42
  80. remo_cli-4.3.3/.release-please-manifest.json +0 -3
  81. remo_cli-4.3.3/ansible/group_vars/all.yml +0 -29
  82. remo_cli-4.3.3/docs/examples/orbstack-cloud-init-tailscale.yaml +0 -182
  83. remo_cli-4.3.3/docs/examples/orbstack-cloud-init.yaml +0 -120
  84. remo_cli-4.3.3/docs/install.sh +0 -200
  85. remo_cli-4.3.3/frontend/src/terminal/TerminalConnection.test.ts +0 -147
  86. remo_cli-4.3.3/tests/unit/cli/test_shell_added.py +0 -76
  87. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/release/SKILL.md +0 -0
  88. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-analyze/SKILL.md +0 -0
  89. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-checklist/SKILL.md +0 -0
  90. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-clarify/SKILL.md +0 -0
  91. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-constitution/SKILL.md +0 -0
  92. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-converge/SKILL.md +0 -0
  93. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-commit/SKILL.md +0 -0
  94. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-feature/SKILL.md +0 -0
  95. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-initialize/SKILL.md +0 -0
  96. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-remote/SKILL.md +0 -0
  97. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-validate/SKILL.md +0 -0
  98. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-implement/SKILL.md +0 -0
  99. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-plan/SKILL.md +0 -0
  100. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-specify/SKILL.md +0 -0
  101. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-tasks/SKILL.md +0 -0
  102. {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-taskstoissues/SKILL.md +0 -0
  103. {remo_cli-4.3.3 → remo_cli-4.3.5}/.devcontainer/devcontainer.json +0 -0
  104. {remo_cli-4.3.3 → remo_cli-4.3.5}/.dockerignore +0 -0
  105. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/CODEOWNERS +0 -0
  106. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/dependency-review.yml +0 -0
  107. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/dev-build.yml +0 -0
  108. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/provision.yml +0 -0
  109. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/release-please.yml +0 -0
  110. {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/teardown.yml +0 -0
  111. {remo_cli-4.3.3 → remo_cli-4.3.5}/.gitignore +0 -0
  112. {remo_cli-4.3.3 → remo_cli-4.3.5}/.maverick/checkpoints/feature/implementation_complete.json +0 -0
  113. {remo_cli-4.3.3 → remo_cli-4.3.5}/.maverick/checkpoints/feature/phase_${{ index }}_complete.json +0 -0
  114. {remo_cli-4.3.3 → remo_cli-4.3.5}/.maverick/checkpoints/feature/validation_complete.json +0 -0
  115. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/.registry +0 -0
  116. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/README.md +0 -0
  117. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.commit.md +0 -0
  118. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.feature.md +0 -0
  119. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.initialize.md +0 -0
  120. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.remote.md +0 -0
  121. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.validate.md +0 -0
  122. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/config-template.yml +0 -0
  123. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/extension.yml +0 -0
  124. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/git-config.yml +0 -0
  125. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/auto-commit.sh +0 -0
  126. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/create-new-feature.sh +0 -0
  127. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/git-common.sh +0 -0
  128. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/initialize-repo.sh +0 -0
  129. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
  130. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/create-new-feature.ps1 +0 -0
  131. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/git-common.ps1 +0 -0
  132. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
  133. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions.yml +0 -0
  134. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/feature.json +0 -0
  135. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/init-options.json +0 -0
  136. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/integration.json +0 -0
  137. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/integrations/claude.manifest.json +0 -0
  138. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/integrations/speckit.manifest.json +0 -0
  139. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/memory/constitution.md +0 -0
  140. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/check-prerequisites.sh +0 -0
  141. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/common.sh +0 -0
  142. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/create-new-feature.sh +0 -0
  143. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/setup-plan.sh +0 -0
  144. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/setup-tasks.sh +0 -0
  145. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/update-agent-context.sh +0 -0
  146. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/agent-file-template.md +0 -0
  147. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/checklist-template.md +0 -0
  148. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/constitution-template.md +0 -0
  149. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/plan-template.md +0 -0
  150. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/spec-template.md +0 -0
  151. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/tasks-template.md +0 -0
  152. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/workflows/speckit/workflow.yml +0 -0
  153. {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/workflows/workflow-registry.json +0 -0
  154. {remo_cli-4.3.3 → remo_cli-4.3.5}/Dockerfile +0 -0
  155. {remo_cli-4.3.3 → remo_cli-4.3.5}/LICENSE +0 -0
  156. {remo_cli-4.3.3 → remo_cli-4.3.5}/SECURITY.md +0 -0
  157. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/.ansible-lint +0 -0
  158. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/README.md +0 -0
  159. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/ansible.cfg +0 -0
  160. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_configure.yml +0 -0
  161. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_resize.yml +0 -0
  162. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_site.yml +0 -0
  163. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_teardown.yml +0 -0
  164. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/group_vars/incus_containers.yml +0 -0
  165. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/group_vars/proxmox_containers.yml +0 -0
  166. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_configure.yml +0 -0
  167. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_provision.yml +0 -0
  168. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_resize.yml +0 -0
  169. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_site.yml +0 -0
  170. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_teardown.yml +0 -0
  171. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_bootstrap.yml +0 -0
  172. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_configure.yml +0 -0
  173. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_provision.yml +0 -0
  174. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_resize.yml +0 -0
  175. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_site.yml +0 -0
  176. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_teardown.yml +0 -0
  177. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/inventory/hosts.yml +0 -0
  178. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/inventory/incus_containers.yml +0 -0
  179. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_bootstrap.yml +0 -0
  180. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_configure.yml +0 -0
  181. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_provision.yml +0 -0
  182. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_resize.yml +0 -0
  183. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_site.yml +0 -0
  184. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_teardown.yml +0 -0
  185. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/requirements.yml +0 -0
  186. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/defaults/main.yml +0 -0
  187. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/ebs.yml +0 -0
  188. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/ec2.yml +0 -0
  189. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/main.yml +0 -0
  190. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/patch_manager.yml +0 -0
  191. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/preflight.yml +0 -0
  192. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/security_group.yml +0 -0
  193. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/deacon/defaults/main.yml +0 -0
  194. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/deacon/tasks/main.yml +0 -0
  195. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/devcontainers/tasks/main.yml +0 -0
  196. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/docker/handlers/main.yml +0 -0
  197. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/docker/tasks/main.yml +0 -0
  198. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/fzf/tasks/main.yml +0 -0
  199. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/github_cli/tasks/main.yml +0 -0
  200. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/hetzner_server/defaults/main.yml +0 -0
  201. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/hetzner_server/tasks/main.yml +0 -0
  202. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_bootstrap/defaults/main.yml +0 -0
  203. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_bootstrap/handlers/main.yml +0 -0
  204. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_bootstrap/tasks/main.yml +0 -0
  205. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/defaults/main.yml +0 -0
  206. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/handlers/main.yml +0 -0
  207. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/meta/main.yml +0 -0
  208. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/tasks/main.yml +0 -0
  209. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/tasks/preflight.yml +0 -0
  210. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container_teardown/defaults/main.yml +0 -0
  211. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container_teardown/meta/main.yml +0 -0
  212. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container_teardown/tasks/main.yml +0 -0
  213. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/nodejs/defaults/main.yml +0 -0
  214. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/nodejs/files/nodesource-repo.gpg.key +0 -0
  215. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/nodejs/tasks/main.yml +0 -0
  216. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_bootstrap/defaults/main.yml +0 -0
  217. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_bootstrap/meta/main.yml +0 -0
  218. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_bootstrap/tasks/main.yml +0 -0
  219. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/defaults/main.yml +0 -0
  220. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/handlers/main.yml +0 -0
  221. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/meta/main.yml +0 -0
  222. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/tasks/main.yml +0 -0
  223. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/tasks/preflight.yml +0 -0
  224. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container_teardown/defaults/main.yml +0 -0
  225. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container_teardown/meta/main.yml +0 -0
  226. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container_teardown/tasks/main.yml +0 -0
  227. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/defaults/main.yml +0 -0
  228. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/tasks/main.yml +0 -0
  229. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/devshell.sh.j2 +0 -0
  230. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/project-launch.sh.j2 +0 -0
  231. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/project-menu.sh.j2 +0 -0
  232. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/remo-host.sh.j2 +0 -0
  233. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/defaults/main.yml +0 -0
  234. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/tasks/main.yml +0 -0
  235. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/templates/config.kdl.j2 +0 -0
  236. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/templates/layouts/minimal.kdl.j2 +0 -0
  237. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/ssh_configure.yml +0 -0
  238. {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/tasks/repair_apt_sources.yml +0 -0
  239. {remo_cli-4.3.3 → remo_cli-4.3.5}/docker/compose.example.yml +0 -0
  240. {remo_cli-4.3.3 → remo_cli-4.3.5}/docker/entrypoint.sh +0 -0
  241. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/maintaining-claude-md.md +0 -0
  242. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/providers.md +0 -0
  243. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/remo-web-speckit-input.md +0 -0
  244. {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/remo-web.html +0 -0
  245. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/index.html +0 -0
  246. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/playwright.config.ts +0 -0
  247. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/scripts/check-types-fresh.mjs +0 -0
  248. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/scripts/generate-frame-types.mjs +0 -0
  249. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/scripts/generate-schema-types.mjs +0 -0
  250. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/client.test.ts +0 -0
  251. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/client.ts +0 -0
  252. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/README.md +0 -0
  253. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/terminal-frames.d.ts +0 -0
  254. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/terminal-frames.json +0 -0
  255. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated.test.ts +0 -0
  256. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AppRoot.tsx +0 -0
  257. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AppShell.css +0 -0
  258. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AppShell.tsx +0 -0
  259. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/OfflineOverlay.css +0 -0
  260. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/OfflineOverlay.tsx +0 -0
  261. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SessionRail.css +0 -0
  262. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SessionRail.tsx +0 -0
  263. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SettingsPage.css +0 -0
  264. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SettingsPage.tsx +0 -0
  265. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/ShortcutsModal.css +0 -0
  266. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/ShortcutsModal.tsx +0 -0
  267. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TerminalCard.css +0 -0
  268. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TopBar.css +0 -0
  269. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TopBar.tsx +0 -0
  270. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/WorkspacePane.css +0 -0
  271. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/WorkspacePane.tsx +0 -0
  272. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/masterLayout.test.ts +0 -0
  273. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/masterLayout.ts +0 -0
  274. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/providerMeta.test.ts +0 -0
  275. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/providerMeta.ts +0 -0
  276. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/railModel.test.ts +0 -0
  277. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/railModel.ts +0 -0
  278. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/lib/clipboard.ts +0 -0
  279. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/lib/fullscreen.ts +0 -0
  280. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/main.tsx +0 -0
  281. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/discovery.test.ts +0 -0
  282. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/discovery.ts +0 -0
  283. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/fonts.ts +0 -0
  284. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/health.test.ts +0 -0
  285. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/health.ts +0 -0
  286. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/latency.test.ts +0 -0
  287. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/latency.ts +0 -0
  288. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/settings.test.ts +0 -0
  289. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/settings.ts +0 -0
  290. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/useConsoleKeyboard.ts +0 -0
  291. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/workspace.test.ts +0 -0
  292. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/workspace.ts +0 -0
  293. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/.gitkeep +0 -0
  294. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/RendererAdapter.ts +0 -0
  295. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/XtermRenderer.ts +0 -0
  296. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/defaultRenderer.ts +0 -0
  297. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/keymap.test.ts +0 -0
  298. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/keymap.ts +0 -0
  299. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/test/setup.ts +0 -0
  300. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/fonts.ts +0 -0
  301. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/terminalThemes.test.ts +0 -0
  302. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/terminalThemes.ts +0 -0
  303. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/tokens.css +0 -0
  304. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/fixtures.ts +0 -0
  305. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/keyboard-routing.spec.ts +0 -0
  306. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/mobile.spec.ts +0 -0
  307. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/reconnect.spec.ts +0 -0
  308. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/terminal-shell-io.spec.ts +0 -0
  309. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/terminal-tui-compatibility.spec.ts +0 -0
  310. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/workspace-layout.spec.ts +0 -0
  311. {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/vite.config.ts +0 -0
  312. {remo_cli-4.3.3 → remo_cli-4.3.5}/maverick.yaml +0 -0
  313. {remo_cli-4.3.3 → remo_cli-4.3.5}/project-menu.sh +0 -0
  314. {remo_cli-4.3.3 → remo_cli-4.3.5}/release-please-config.json +0 -0
  315. {remo_cli-4.3.3 → remo_cli-4.3.5}/remo +0 -0
  316. {remo_cli-4.3.3 → remo_cli-4.3.5}/remo.svg +0 -0
  317. {remo_cli-4.3.3 → remo_cli-4.3.5}/run.sh +0 -0
  318. {remo_cli-4.3.3 → remo_cli-4.3.5}/scripts/export_openapi.py +0 -0
  319. {remo_cli-4.3.3 → remo_cli-4.3.5}/scripts/palette-check.sh +0 -0
  320. {remo_cli-4.3.3 → remo_cli-4.3.5}/scripts/setup-aws-oidc.sh +0 -0
  321. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/checklists/requirements.md +0 -0
  322. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/checklists/validation.md +0 -0
  323. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/contracts/playbook-interface.yaml +0 -0
  324. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/contracts/role-interface.yaml +0 -0
  325. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/data-model.md +0 -0
  326. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/plan.md +0 -0
  327. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/quickstart.md +0 -0
  328. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/research.md +0 -0
  329. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/spec.md +0 -0
  330. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/tasks.md +0 -0
  331. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/checklists/requirements.md +0 -0
  332. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/contracts/playbook-interface.yaml +0 -0
  333. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/contracts/role-interface.yaml +0 -0
  334. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/data-model.md +0 -0
  335. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/plan.md +0 -0
  336. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/quickstart.md +0 -0
  337. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/research.md +0 -0
  338. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/spec.md +0 -0
  339. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/tasks.md +0 -0
  340. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/checklists/requirements.md +0 -0
  341. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/data-model.md +0 -0
  342. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/plan.md +0 -0
  343. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/quickstart.md +0 -0
  344. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/research.md +0 -0
  345. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/spec.md +0 -0
  346. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/tasks.md +0 -0
  347. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/004-proxmox-container-support/spec.md +0 -0
  348. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/checklists/requirements.md +0 -0
  349. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/contracts/cli-surface.md +0 -0
  350. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/data-model.md +0 -0
  351. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/plan.md +0 -0
  352. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/quickstart.md +0 -0
  353. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/research.md +0 -0
  354. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/spec.md +0 -0
  355. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/tasks.md +0 -0
  356. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/checklists/requirements.md +0 -0
  357. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/contracts/remo-host-protocol.md +0 -0
  358. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/contracts/rest-api.md +0 -0
  359. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/contracts/terminal-websocket.md +0 -0
  360. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/data-model.md +0 -0
  361. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/plan.md +0 -0
  362. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/quickstart.md +0 -0
  363. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/research.md +0 -0
  364. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/spec.md +0 -0
  365. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/tasks.md +0 -0
  366. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/checklists/requirements.md +0 -0
  367. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/contracts/cli-web-adopt.md +0 -0
  368. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/contracts/setup-api.md +0 -0
  369. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/data-model.md +0 -0
  370. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/plan.md +0 -0
  371. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/quickstart-results.md +0 -0
  372. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/quickstart.md +0 -0
  373. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/research.md +0 -0
  374. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/spec.md +0 -0
  375. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/tasks.md +0 -0
  376. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/contracts/cli-web-adopt.md +0 -0
  377. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/plan.md +0 -0
  378. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/quickstart.md +0 -0
  379. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/research.md +0 -0
  380. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/contracts/cli-sync.md +0 -0
  381. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/contracts/marker-commands.md +0 -0
  382. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/data-model.md +0 -0
  383. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/plan.md +0 -0
  384. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/quickstart.md +0 -0
  385. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/research.md +0 -0
  386. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/spec.md +0 -0
  387. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/tasks.md +0 -0
  388. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/contracts/add-command.md +0 -0
  389. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/contracts/remove-command.md +0 -0
  390. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/data-model.md +0 -0
  391. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/plan.md +0 -0
  392. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/quickstart.md +0 -0
  393. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/research.md +0 -0
  394. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/spec.md +0 -0
  395. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/tasks.md +0 -0
  396. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/checklists/requirements.md +0 -0
  397. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/contracts/mirror-payload-v2.md +0 -0
  398. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/contracts/registry-accessor-api.md +0 -0
  399. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/contracts/registry-file-v2.md +0 -0
  400. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/data-model.md +0 -0
  401. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/plan.md +0 -0
  402. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/quickstart.md +0 -0
  403. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/research.md +0 -0
  404. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/spec.md +0 -0
  405. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/tasks.md +0 -0
  406. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/checklists/requirements.md +0 -0
  407. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/contracts/cli-sync.md +0 -0
  408. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/contracts/provider-probe.md +0 -0
  409. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/data-model.md +0 -0
  410. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/plan.md +0 -0
  411. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/quickstart.md +0 -0
  412. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/research.md +0 -0
  413. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/spec.md +0 -0
  414. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/tasks.md +0 -0
  415. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/checklists/requirements.md +0 -0
  416. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/cli-web-push.md +0 -0
  417. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/cli-web-status.md +0 -0
  418. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/revocation.md +0 -0
  419. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/setup-status-marker.md +0 -0
  420. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/data-model.md +0 -0
  421. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/plan.md +0 -0
  422. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/quickstart.md +0 -0
  423. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/research.md +0 -0
  424. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/spec.md +0 -0
  425. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/tasks.md +0 -0
  426. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/baseline-notes.md +0 -0
  427. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/checklists/requirements.md +0 -0
  428. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/cli-surface.md +0 -0
  429. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/errors.md +0 -0
  430. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/lifecycle-templates.md +0 -0
  431. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/provider-protocol.md +0 -0
  432. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/sync-merge.md +0 -0
  433. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/data-model.md +0 -0
  434. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/plan.md +0 -0
  435. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/quickstart.md +0 -0
  436. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/research.md +0 -0
  437. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/spec.md +0 -0
  438. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/tasks.md +0 -0
  439. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/checklists/requirements.md +0 -0
  440. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/contracts/cli-surface-delta.md +0 -0
  441. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/contracts/docs-structure-check.md +0 -0
  442. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/data-model.md +0 -0
  443. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/plan.md +0 -0
  444. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/quickstart.md +0 -0
  445. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/research.md +0 -0
  446. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/spec.md +0 -0
  447. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/tasks.md +0 -0
  448. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/checklists/requirements.md +0 -0
  449. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/contracts/drift-checks.md +0 -0
  450. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/contracts/terminal-frames-v1.md +0 -0
  451. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/data-model.md +0 -0
  452. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/plan.md +0 -0
  453. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/quickstart.md +0 -0
  454. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/research.md +0 -0
  455. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/spec.md +0 -0
  456. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/tasks.md +0 -0
  457. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/contracts/cli-surface.md +0 -0
  458. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/contracts/descriptor-schema.md +0 -0
  459. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/data-model.md +0 -0
  460. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/plan.md +0 -0
  461. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/quickstart.md +0 -0
  462. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/research.md +0 -0
  463. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/spec.md +0 -0
  464. {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/tasks.md +0 -0
  465. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/__init__.py +0 -0
  466. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/__main__.py +0 -0
  467. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/__init__.py +0 -0
  468. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/added.py +0 -0
  469. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/cp.py +0 -0
  470. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/main.py +0 -0
  471. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/providers/__init__.py +0 -0
  472. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/providers/factory.py +0 -0
  473. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/web.py +0 -0
  474. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/__init__.py +0 -0
  475. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/ansible_runner.py +0 -0
  476. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/completion.py +0 -0
  477. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/config.py +0 -0
  478. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/errors.py +0 -0
  479. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/known_hosts.py +0 -0
  480. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/lifecycle.py +0 -0
  481. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/output.py +0 -0
  482. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/picker.py +0 -0
  483. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/provider_protocol.py +0 -0
  484. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/provider_registry.py +0 -0
  485. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/reconcile.py +0 -0
  486. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/registry.py +0 -0
  487. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/remo_host_client.py +0 -0
  488. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/rsync.py +0 -0
  489. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/snapshot.py +0 -0
  490. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/ssh.py +0 -0
  491. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/validation.py +0 -0
  492. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/version.py +0 -0
  493. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/web_drift.py +0 -0
  494. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/__init__.py +0 -0
  495. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/capability.py +0 -0
  496. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/discovery.py +0 -0
  497. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/host.py +0 -0
  498. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/session_target.py +0 -0
  499. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/snapshot.py +0 -0
  500. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/__init__.py +0 -0
  501. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/aws.py +0 -0
  502. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/aws_descriptor.py +0 -0
  503. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/builtin.py +0 -0
  504. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/hetzner.py +0 -0
  505. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/hetzner_descriptor.py +0 -0
  506. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/incus.py +0 -0
  507. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/incus_descriptor.py +0 -0
  508. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/proxmox.py +0 -0
  509. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/proxmox_descriptor.py +0 -0
  510. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/__init__.py +0 -0
  511. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/__init__.py +0 -0
  512. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/hosts.py +0 -0
  513. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/pairing.py +0 -0
  514. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/terminals.py +0 -0
  515. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/app.py +0 -0
  516. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/check.py +0 -0
  517. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/config.py +0 -0
  518. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/discovery.py +0 -0
  519. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/frames.py +0 -0
  520. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/health.py +0 -0
  521. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/logging_config.py +0 -0
  522. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/models.py +0 -0
  523. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/operator_auth.py +0 -0
  524. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/pairing.py +0 -0
  525. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/ssh_master.py +0 -0
  526. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/state.py +0 -0
  527. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/terminal.py +0 -0
  528. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/terminal_registry.py +0 -0
  529. {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/tokens.py +0 -0
  530. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/__init__.py +0 -0
  531. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/__init__.py +0 -0
  532. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_apt_sources_repair.py +0 -0
  533. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_authorized_keys_bootstrap.py +0 -0
  534. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_remo_host_idempotency.py +0 -0
  535. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_ssh_configure_connection.py +0 -0
  536. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_user_setup_docker_group.py +0 -0
  537. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/conftest.py +0 -0
  538. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/image/__init__.py +0 -0
  539. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/__init__.py +0 -0
  540. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/_nine_terminal_fixture.py +0 -0
  541. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/fish_completion.sh +0 -0
  542. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/orbstack-cloud-init.yml +0 -0
  543. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/orbstack.sh +0 -0
  544. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_nine_terminals.py +0 -0
  545. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_nine_terminals_soak.py +0 -0
  546. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_registry_concurrency.py +0 -0
  547. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_remo_host_e2e.py +0 -0
  548. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_security_rejections.py +0 -0
  549. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_setup_payload_versions.py +0 -0
  550. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_sync_reconcile.py +0 -0
  551. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_terminal_attach.py +0 -0
  552. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_web_cli_parity.py +0 -0
  553. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/perf/__init__.py +0 -0
  554. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/perf/test_latency.py +0 -0
  555. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/perf/test_registry_perf.py +0 -0
  556. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/__init__.py +0 -0
  557. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/__init__.py +0 -0
  558. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_aws_snapshot.py +0 -0
  559. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_hetzner_snapshot.py +0 -0
  560. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_incus_snapshot.py +0 -0
  561. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_incus_sync_all.py +0 -0
  562. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_proxmox_snapshot.py +0 -0
  563. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_proxmox_sync_all.py +0 -0
  564. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/surface_baseline.py +0 -0
  565. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_add_cmd.py +0 -0
  566. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_cli_uniformity.py +0 -0
  567. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_configure_cmd.py +0 -0
  568. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_cp.py +0 -0
  569. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_main.py +0 -0
  570. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_remove_cmd.py +0 -0
  571. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_startup_imports.py +0 -0
  572. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_surface_preservation.py +0 -0
  573. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/__init__.py +0 -0
  574. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ansible_runner.py +0 -0
  575. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_completion.py +0 -0
  576. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_config.py +0 -0
  577. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_errors.py +0 -0
  578. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_known_hosts.py +0 -0
  579. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_lifecycle.py +0 -0
  580. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_migration_tagging_notice.py +0 -0
  581. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_output.py +0 -0
  582. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_picker.py +0 -0
  583. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_provider_registry.py +0 -0
  584. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_reconcile.py +0 -0
  585. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_registry_format.py +0 -0
  586. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_registry_locking.py +0 -0
  587. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_registry_migration.py +0 -0
  588. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_remo_host_client.py +0 -0
  589. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_rsync.py +0 -0
  590. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_snapshot.py +0 -0
  591. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh.py +0 -0
  592. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh_added.py +0 -0
  593. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh_controlpath.py +0 -0
  594. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh_identity_opts.py +0 -0
  595. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_validation.py +0 -0
  596. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_version.py +0 -0
  597. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_authorize.py +0 -0
  598. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_payload.py +0 -0
  599. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_drift.py +0 -0
  600. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_push.py +0 -0
  601. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/__init__.py +0 -0
  602. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/test_capability.py +0 -0
  603. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/test_discovery.py +0 -0
  604. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/test_session_target.py +0 -0
  605. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/__init__.py +0 -0
  606. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/fake_provider.py +0 -0
  607. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_add.py +0 -0
  608. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_configure.py +0 -0
  609. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_provider_guard.py +0 -0
  610. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_update_remove.py +0 -0
  611. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_verify.py +0 -0
  612. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_provider_protocol.py +0 -0
  613. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_snapshot.py +0 -0
  614. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_sync.py +0 -0
  615. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_upgrade_resize.py +0 -0
  616. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_entry_adapters.py +0 -0
  617. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_http.py +0 -0
  618. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_label.py +0 -0
  619. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_resize.py +0 -0
  620. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_snapshot.py +0 -0
  621. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_sync.py +0 -0
  622. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_host_user_consistency.py +0 -0
  623. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_entry_adapters.py +0 -0
  624. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_marker.py +0 -0
  625. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_resize.py +0 -0
  626. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_snapshot.py +0 -0
  627. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_sync.py +0 -0
  628. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_missing_sdk.py +0 -0
  629. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_provider_conformance.py +0 -0
  630. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_provider_registry_entries.py +0 -0
  631. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_devcontainer_runtime.py +0 -0
  632. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_marker.py +0 -0
  633. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_provider_protocol.py +0 -0
  634. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_resize.py +0 -0
  635. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_snapshot.py +0 -0
  636. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_sync.py +0 -0
  637. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_ansible_templates.py +0 -0
  638. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_architecture.py +0 -0
  639. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_docs_structure.py +0 -0
  640. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_host_model.py +0 -0
  641. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_host_ssh_type.py +0 -0
  642. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_lockfile_version.py +0 -0
  643. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_schema_drift.py +0 -0
  644. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_workflow_action_pins.py +0 -0
  645. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/__init__.py +0 -0
  646. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/_pairing_support.py +0 -0
  647. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/conftest.py +0 -0
  648. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/fixtures/hosts_response.json +0 -0
  649. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/fixtures/sessions_response.json +0 -0
  650. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_backpressure.py +0 -0
  651. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_check.py +0 -0
  652. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_csp.py +0 -0
  653. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_discovery.py +0 -0
  654. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_discovery_refresh_force.py +0 -0
  655. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_frames.py +0 -0
  656. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_health_states.py +0 -0
  657. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_hosts_mapping.py +0 -0
  658. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_lazy_import.py +0 -0
  659. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_log_redaction.py +0 -0
  660. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_mint_gating.py +0 -0
  661. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_operator_auth.py +0 -0
  662. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_pairing.py +0 -0
  663. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_pairing_origin.py +0 -0
  664. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_payload_equivalence.py +0 -0
  665. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_registry_readonly.py +0 -0
  666. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_service_identity_selection.py +0 -0
  667. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_setup_auth.py +0 -0
  668. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_state.py +0 -0
  669. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_terminals_api.py +0 -0
  670. {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_tokens.py +0 -0
@@ -0,0 +1,21 @@
1
+ name: "remo CodeQL config"
2
+
3
+ # Scope the scan to code this repository actually ships.
4
+ #
5
+ # `docs/remo-web.html` is an 881 KB single-file design mockup produced by a
6
+ # page bundler, checked in as the visual reference the console's design was
7
+ # adopted from (cited by `frontend/src/theme/tokens.css` and
8
+ # `frontend/src/state/workspace.ts`). It is not served by anything: no Pages
9
+ # workflow publishes `docs/`, nothing links to it, and it is absent from both
10
+ # the wheel and the container image. You open it from disk.
11
+ #
12
+ # Scanning it produced one alert (js/xss-through-dom) whose "DOM text" source
13
+ # is the file's OWN embedded `<script type="__bundler/template">` literal,
14
+ # read back at line 86 and handed to `DOMParser.parseFromString`. That is how
15
+ # every self-unpacking bundle works; there is no external input anywhere in
16
+ # the flow, and no origin to be cross-site against.
17
+ #
18
+ # Only the one file is excluded, not `docs/` -- `docs/examples/` holds real
19
+ # cloud-init YAML, and anything executable added there later should be scanned.
20
+ paths-ignore:
21
+ - docs/remo-web.html
@@ -0,0 +1,75 @@
1
+ version: 2
2
+ updates:
3
+ # Python dependencies (pyproject.toml)
4
+ - package-ecosystem: "pip"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
8
+ day: "monday"
9
+ open-pull-requests-limit: 5
10
+ # Let a new release settle before we bump to it, so we don't chase
11
+ # immediately-yanked or regression releases.
12
+ cooldown:
13
+ default-days: 7
14
+ groups:
15
+ # One PR per week with all minor/patch production deps bumped together.
16
+ production-minor-patch:
17
+ dependency-type: "production"
18
+ update-types:
19
+ - "minor"
20
+ - "patch"
21
+ # One PR per week with all minor/patch dev-only deps bumped together.
22
+ dev-minor-patch:
23
+ dependency-type: "development"
24
+ update-types:
25
+ - "minor"
26
+ - "patch"
27
+ # Major bumps still get individual PRs so they can be reviewed carefully.
28
+
29
+ # GitHub Actions workflow versions
30
+ - package-ecosystem: "github-actions"
31
+ directory: "/"
32
+ schedule:
33
+ interval: "weekly"
34
+ day: "monday"
35
+ open-pull-requests-limit: 5
36
+ cooldown:
37
+ default-days: 7
38
+ groups:
39
+ actions:
40
+ update-types:
41
+ - "minor"
42
+ - "patch"
43
+
44
+ # Docker base images. Two Dockerfiles ship images:
45
+ # /Dockerfile — the CLI image (python:3.13-slim)
46
+ # /docker/Dockerfile — the remo-web service (node:24-slim, python:3.11-slim)
47
+ # Nothing watched these before, so a base image could sit on an unpatched
48
+ # tag indefinitely — the CVEs that matter for a container usually arrive via
49
+ # the base image, not via the app's own dependencies.
50
+ - package-ecosystem: "docker"
51
+ directories:
52
+ - "/"
53
+ - "/docker"
54
+ schedule:
55
+ interval: "weekly"
56
+ day: "monday"
57
+ open-pull-requests-limit: 5
58
+ cooldown:
59
+ default-days: 7
60
+ groups:
61
+ docker-images:
62
+ update-types:
63
+ - "minor"
64
+ - "patch"
65
+ ignore:
66
+ # Dependabot picks the highest published tag and has no concept of
67
+ # Node's release lines. Left alone it proposed node:20-slim ->
68
+ # node:25-slim (#156): 25 is an odd-numbered "Current" release that
69
+ # never becomes LTS and went EOL on 2026-06-01, so that bump would have
70
+ # swapped one unpatched base image for another — the exact failure this
71
+ # ecosystem entry exists to prevent. Node majors are picked by hand
72
+ # instead, on the LTS cadence (even-numbered, each October). Minor and
73
+ # patch bumps, which carry the base-image CVE fixes, keep flowing.
74
+ - dependency-name: "node"
75
+ update-types: ["version-update:semver-major"]
@@ -143,9 +143,17 @@ jobs:
143
143
  name: Frontend (typecheck + unit + build)
144
144
  runs-on: ubuntu-latest
145
145
  # Fast, backend-free coverage of the SPA: tsc typecheck, the Vitest
146
- # unit/component suite (frontend/src/**/*.test.ts), and a production build.
147
- # The Playwright e2e suite (frontend/tests/e2e) is NOT run here — it needs a live
148
- # `remo web serve` backend (REMO_E2E_BASE_URL); see playwright.config.ts.
146
+ # unit/component suite (frontend/src/**/*.test.ts), the browser geometry
147
+ # suite (frontend/tests/geometry), and a production build.
148
+ #
149
+ # The geometry suite runs here because it is self-contained: it serves a
150
+ # fixture page with Vite and answers the terminal API/WebSocket from inside
151
+ # the spec. It covers what jsdom structurally cannot — jsdom has no layout
152
+ # engine, so every element measures 0x0 and any assertion about the terminal
153
+ # grid fitting its box passes vacuously there.
154
+ #
155
+ # The Playwright e2e suite (frontend/tests/e2e) is still NOT run here — it needs
156
+ # a live `remo web serve` backend (REMO_E2E_BASE_URL); see playwright.config.ts.
149
157
  defaults:
150
158
  run:
151
159
  working-directory: frontend
@@ -154,7 +162,7 @@ jobs:
154
162
 
155
163
  - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
156
164
  with:
157
- node-version: "20"
165
+ node-version: "24"
158
166
  cache: npm
159
167
  cache-dependency-path: frontend/package-lock.json
160
168
 
@@ -170,5 +178,13 @@ jobs:
170
178
  - name: Unit tests
171
179
  run: npm run test
172
180
 
181
+ # Chromium only — the geometry suite runs the same specs twice against it
182
+ # (WebGL and DOM renderers) and needs no other browser.
183
+ - name: Install Chromium for the geometry suite
184
+ run: npx playwright install --with-deps chromium
185
+
186
+ - name: Browser geometry tests
187
+ run: npm run test:geometry
188
+
173
189
  - name: Build
174
190
  run: npm run build
@@ -37,6 +37,7 @@ jobs:
37
37
  with:
38
38
  languages: ${{ matrix.language }}
39
39
  build-mode: ${{ matrix.build-mode }}
40
+ config-file: .github/codeql/codeql-config.yml
40
41
 
41
42
  - name: Perform CodeQL Analysis
42
43
  uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
@@ -161,7 +161,7 @@ jobs:
161
161
  run: uv build
162
162
 
163
163
  - name: Publish to PyPI
164
- uses: pypa/gh-action-pypi-publish@ba38be9e461d3875417946c167d0b5f3d385a247 # release/v1
164
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
165
165
 
166
166
  publish-image:
167
167
  # Publishes the remo-web container image that docker/compose.example.yml
@@ -186,7 +186,7 @@ jobs:
186
186
  - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
187
187
 
188
188
  - name: Log in to GHCR
189
- uses: docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
189
+ uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4
190
190
  with:
191
191
  registry: ghcr.io
192
192
  username: ${{ github.actor }}
@@ -20,7 +20,7 @@ jobs:
20
20
  timeout-minutes: 10
21
21
  steps:
22
22
  - name: Configure AWS credentials (OIDC)
23
- uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6
23
+ uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6
24
24
  with:
25
25
  role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
26
26
  role-session-name: remo-cleanup-${{ github.run_id }}
@@ -58,7 +58,7 @@ jobs:
58
58
  run: uv sync
59
59
 
60
60
  - name: Configure AWS credentials (OIDC)
61
- uses: aws-actions/configure-aws-credentials@517a711dbcd0e402f90c77e7e2f81e849156e31d # v6
61
+ uses: aws-actions/configure-aws-credentials@e6de054238d6b7531b4efff3b6587d9aade6a06c # v6
62
62
  with:
63
63
  role-to-assume: ${{ secrets.AWS_OIDC_ROLE_ARN }}
64
64
  role-session-name: remo-ci-${{ github.run_id }}
@@ -0,0 +1,3 @@
1
+ {
2
+ ".": "4.3.5"
3
+ }
@@ -47,7 +47,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
47
47
  ├── __main__.py # python -m remo_cli entry point
48
48
  ├── cli/ # Click command layer (parsing only, no business logic)
49
49
  │ ├── main.py # Root CLI group; mounts one group per remo_cli.core.provider_registry.all_descriptors()
50
- │ ├── shell.py # remo shell — registry-dispatched update_entry() (delegates to upgrade()); prompt names the exact `remo <type> upgrade <name>` it will run; unknown type/ssh handled explicitly (no silent no-op)
50
+ │ ├── shell.py # remo shell — pre-connect version check for EVERY host type; _run_tools_upgrade() dispatches to the provider's update_entry() (delegates to upgrade()) or, for type="ssh", providers/added.configure(); prompt names the exact `remo <type> upgrade <name>` / `remo configure <name>` it will run; unknown type raises (no silent no-op); an added host with no `~/.remo-version` marker connects silently (FR-011)
51
51
  │ ├── cp.py # remo cp
52
52
  │ ├── added.py # remo add / remo remove / remo configure — provider-neutral SSH host registration (014) and configure (022)
53
53
  │ ├── web.py # remo web {serve,check,push,status,adopt} — serve/check lazy-import remo_cli.web.* (NFR-008); push/status/adopt use core/web_adopt + core/web_drift only (adopt is a deprecated alias for push)
@@ -121,6 +121,12 @@ frontend/ # remo-web browser SPA (Vite + React + TypeScript)
121
121
  │ │ # + masterLayout.ts (pure pane geometry: uniform grid + master/stack tiling)
122
122
  │ ├── state/ # discovery.ts, workspace.ts (layout persisted to localStorage)
123
123
  │ └── terminal/ # RendererAdapter (seam), XtermRenderer (the one engine), TerminalConnection, keymap
124
+ │ # + fitLoop.ts (the container->emulator->PTY fit, extracted so the
125
+ │ # browser geometry suite drives the shipped code and not a copy)
126
+ └── tests/
127
+ ├── e2e/ # Playwright console suite — needs a live `remo web serve` (REMO_E2E_BASE_URL)
128
+ └── geometry/ # Playwright terminal-geometry suite — no backend, gates CI
129
+ └── harness/ # Vite fixture mounting the REAL TerminalCard + paneLayout
124
130
 
125
131
  docker/ # remo-web container packaging (010-web-session-interface, US4)
126
132
  ├── Dockerfile # multi-stage: frontend build -> wheel build -> slim Python runtime
@@ -130,6 +136,12 @@ docker/ # remo-web container packaging (010-web-session-inter
130
136
  ansible/ # Ansible playbooks (invoked by Python via subprocess)
131
137
  ├── roles/
132
138
  │ ├── incus_bootstrap/
139
+ │ ├── nested_docker/ # Hosts whose kernel refuses NESTED overlayfs mounts (OrbStack): a
140
+ │ │ │ # native-snapshotter buildx builder + a devcontainer shim (#160/#171).
141
+ │ │ │ # Gated on group_vars' docker_nested_overlayfs; no-op elsewhere
142
+ │ │ └── templates/
143
+ │ │ └── devcontainer-shim.sh.j2 # /usr/local/bin/devcontainer: picks DOCKER_BUILDKIT /
144
+ │ │ # COMPOSE_BAKE / updateUID per project, per invocation
133
145
  │ └── user_setup/
134
146
  │ └── templates/
135
147
  │ └── remo-host.sh.j2 # Versioned `remo-host` command (capabilities/sessions/attach)
@@ -228,6 +240,9 @@ cd frontend && npm ci
228
240
  npm run build # tsc -b && vite build -> frontend/dist
229
241
  npm run lint # tsc --noEmit
230
242
  npm run test # Vitest unit/component suite (jsdom, no backend)
243
+ npm run test:geometry # Playwright terminal-geometry suite (no backend; serves its own
244
+ # fixture. jsdom has no layout engine, so this is the only place
245
+ # the terminal grid is checked against the box that clips it)
231
246
  npm run test:e2e # Playwright (needs REMO_E2E_BASE_URL -> live remo web serve)
232
247
  ```
233
248
 
@@ -282,6 +297,7 @@ made conditional to get a build green — fix the code or amend the gate by PR.
282
297
  | Lint | `uv run ruff check src/remo_cli` | Code Style |
283
298
  | Types | `uv run mypy src/remo_cli` | Code Style |
284
299
  | Frontend | `cd frontend && npm run lint && npm run test && npm run build` | Code Style |
300
+ | Browser geometry | `cd frontend && npm run test:geometry` | Terminal grid fits its box (jsdom cannot check this) |
285
301
  | Fish completion | `./tests/integration/fish_completion.sh` | Principle VI (completion runs, not just reads) |
286
302
  | Packaging | wheel install smoke, Docker amd64+arm64 | Distribution integrity |
287
303
  | Security | CodeQL, dependency review | Supply chain |
@@ -319,9 +335,9 @@ checking nothing.
319
335
  - Ansible 2.14+ / YAML: Follow standard conventions plus Constitution principles
320
336
 
321
337
  ## Recent Changes
338
+ - issues #160/#171 — nested overlayfs (OrbStack): Made hosts whose kernel refuses NESTED overlayfs mounts able to build devcontainers at all. An OrbStack "machine" is a container on a shared kernel (rootfs is a btrfs subvolume under `/scon/containers/<id>`), not a VM, so Docker inside it is nested and an overlay mount is refused — and Docker 29 made the containerd overlayfs snapshotter the default, so a freshly-configured host lands on the broken path with nothing to steer it. `remo configure` completed cleanly, `remo-host` responded, `remo web push` reported capabilities OK, and then every BuildKit build died on the first `RUN` with `mount source: "overlay" … operation not permitted`, surfaced as an opaque devcontainer-CLI stack trace that read like a project problem. New `ansible/roles/nested_docker/`, included from `tasks/configure_dev_tools.yml` (so all five configure playbooks inherit it) behind `group_vars/all.yml`'s `docker_nested_overlayfs`, which keys off `-orbstack-` in `ansible_kernel` — NOT `/mnt/mac`, which is absent under `orb create --isolated` and would have silently skipped the fix on exactly the configuration a user picks for a cleaner VM. It runs after `user_setup`, and every buildx task carries `become_user: remo_user`: buildx state lives in `~/.docker/buildx`, so a builder created for root leaves `project-launch` just as broken as no builder. **Two halves, because one fix is not enough.** (1) #160: a `docker-container` builder (`remo-native`) whose buildkitd.toml selects the `native` snapshotter, which copies layers instead of overlaying them — correct, and materially slower; `--bootstrap` so a broken image pull fails the configure rather than surfacing days later, and the builder is *recreated* when buildkitd.toml changes because `buildx create` reads `--config` once and an edited file otherwise never reaches an existing builder. (2) #171: the devcontainer CLI shells out to two builders whose requirements here are mutually exclusive — `docker compose build` HONOURS `DOCKER_BUILDKIT=0` and drops to the classic builder, which rejects the `additional_contexts` the CLI injects to install Features, while `updateUID`'s plain `docker build` needs exactly that setting to avoid the daemon's embedded BuildKit. No global value is correct for both, so a shim decides per invocation from the project's own `devcontainer.json`: Compose → `DOCKER_BUILDKIT=1 COMPOSE_BAKE=1` (verified: `COMPOSE_BAKE` alone still fails) plus `--update-remote-user-uid-default never` on `up`/`build` only — the CLI rejects the flag on `exec`, which `project-launch` uses; anything else → `DOCKER_BUILDKIT=0`, argv untouched; both → `BUILDX_BUILDER=remo-native`, so a user changing their default builder cannot silently break every devcontainer. Three placement decisions the tests pin, each defending a *silent* failure: the shim installs to `/usr/local/bin/devcontainer`, NOT `~/.local/bin` (that directory is added to PATH inside `~/.bashrc`, which returns early for non-interactive shells — a shim there would miss `ssh host 'devcontainer up …'`, the exact case it exists to fix, while passing every interactive test); it calls the real CLI by absolute path, because `command devcontainer` resolves through PATH, finds the shim again and recurses; and it declines to skip `updateUID` unless the host UID matches `user_setup`'s 1000 pin, since skipping at any other UID would trade a broken build for silently unwritable bind mounts. `docker buildx install` was rejected as the "clean" general fix — the docker-container driver cannot resolve the local-only image `updateUID`'s `FROM $BASE_IMAGE` names. remo NAMES a hand-added global `DOCKER_BUILDKIT` but does not delete it (the operator's line, in a file remo has no managed block in — the #121 authorized_keys lesson), and reports both costs it cannot fix via the task NAME, since `_filter_line` suppresses `debug` bodies: slower builds, and `apt` inside a running container failing with `Invalid cross-device link` (which is why `playwright install --with-deps`, and so E2E browser tests, cannot work on such a host — easy to miss, because a well-written `postCreateCommand` treats it as non-fatal and `devcontainer up` still reports success). New `tests/unit/test_devcontainer_shim.py` renders the template and *executes* it against a stub CLI for every branch. New `docs/nested-overlayfs.md`. No registry schema change; no new runtime deps; no new CLI flag or tool toggle — it is a repair for the tools already selected, not another tool.
322
339
  - 022-configure-added-hosts: Made manually-added SSH hosts first-class by giving them the one thing `remo add` (014) never did — a configure path. New provider-neutral `remo configure NAME` runs a new generic `ansible/ssh_configure.yml` against a registry `type="ssh"` entry, so an added host finally gets `remo-host`/zellij/`project-launch` and stops sitting in the `remo web` rail permanently badged `no_remo_host` with zero session targets. **No refactor of the four provider plays**: the role list was already shared via `tasks/configure_dev_tools.yml`, so a fifth playbook inherits the whole toolchain — the change is purely additive. The new play is two plays: a `localhost` play that asserts (never defaults) `remo_ssh_host`/`remo_ssh_user`/`remo_ssh_port` and `add_host`s them onto `ansible_host`/`ansible_user`/`ansible_port`/`ansible_ssh_private_key_file`, then a play targeting that named group (NOT `hosts: all`, which would pick up `inventory/hosts.yml`'s `hetzner_server` and whose zero-host case exits rc 0 — a silent false success). Four decisions the tests pin, each defending a *silent* failure: the identity is `| default(omit)`, never `'~/.ssh/id_rsa'` (aws_configure.yml's anti-pattern — a path default offers the WRONG key); it is paired with an explicit `-o IdentitiesOnly=yes`, which ansible-core does not add for `private_key_file` (without it a busy agent hits MaxAuthTries and dies "Too many authentication failures" while the passed key is never tried); both `raw` pre-flight probes (python3, `sudo -n true`) set `become: false`, since `ansible.cfg` sets `become = True` globally and a sudo probe run THROUGH sudo proves nothing; and `remo_user` is bound to `remo_ssh_user` rather than `group_vars/all.yml`'s `"remo"` — everything `user_setup` installs lands in `/home/{{ remo_user }}/.local/bin` and discovery logs in as the REGISTERED user, so the default would install `remo-host` into a second account and leave the console still reporting `no_remo_host` after a "successful" configure (it also skips the UID-1000 displacement, which only fires when 1000's holder is someone else). Root is refused (UID-1000 pin), the prompt defaults to no, and remo never reboots a host it did not provision — it reports via the task NAME, since `_filter_line` suppresses `debug` bodies. `core/known_hosts.py` gains `guard_added_ssh_host_only`, the mirror of `guard_not_added_ssh_host`: a provider host is refused naming `remo <type> upgrade NAME`, because the five configure plays are not interchangeable and a mis-target would succeed while configuring wrongly. **Bug fix in the same change** (`core/web_adopt.py`): `remo web push` hardcoded port 22 in `scan_and_verify_host_key`'s `ssh-keyscan` and `_lookup_trusted_keys`' `ssh-keygen -F`, so an added host on another port was reported `skipped/unreachable` — `authorize_service_key` never ran — with a remediation blaming a host that was reachable, or, worse, a different machine answering on 22 had its keys pushed. New `known_hosts_lookup_key()` follows OpenSSH's record form (bare for 22, `[host]:port` otherwise; verified against the real binary — neither direction is forgiving), and `-p` is omitted for 22 so every provider host's argv is byte-identical. `providers/added.py`'s `_reject_unsafe_field` now also rejects Jinja delimiters (registry values become extra-vars, which Ansible templates on the CONTROL NODE), re-checked on the configure read path so pre-existing entries are covered. `web/discovery.py`'s `no_remo_host` remediation now names the real command per host type instead of "re-run configure", which for an added host pointed at nothing. No registry schema change; no new runtime deps.
323
340
  - 021-cli-plane-separation: Split the three-intent `remo <provider> update` verb into three single-intent verbs — `upgrade` (in-instance configure play only, zero provider-side writes, SC-001), `resize` (resource change only — the factory rejects a dimensionless invocation with a `PreconditionError` listing that provider's dimension flags, before dispatching to the provider), and `tag` (managed-marker write only, generated iff `supports_managed_marker`; read-before-write no-op when already tagged, `OperationFailedError` — not `create`'s warn-and-continue — on write failure, SC-002) — and moved `bootstrap` off the flat instance plane into a new descriptor-driven `host` subgroup (`remo {incus,proxmox} host bootstrap`, generated iff `host_commands` is non-empty; `CommandSpec` gained a `target: ArgumentSpec | None` field so host commands take the host positionally — incus optional/defaults to localhost, proxmox required). `core/provider_registry.py`: `ProviderDescriptor.update_options` removed, replaced by `upgrade_options`/`resize_dimensions`/`resize_options`/`tag_options`/`host_commands`; new `ArgumentSpec` dataclass. `cli/providers/factory.py`: `_build_update` replaced by `_build_upgrade`/`_build_resize`/`_build_tag`/`_build_host_group`; `_instance_argument` grew a `param` kwarg so the new verbs take `NAME` positionally (matching the provider impl's `name` kwarg) while `create`/`destroy`/`info` keep `--name`; `_resolve_entry_for_destroy`'s user-hint lookup is now descriptor-driven (reads `kwargs` under the `registry_fields` JSON key ending in `_user`) instead of a `"user"` literal. Every provider module split `update()` into `upgrade()`/`resize()`/`tag()` (marker-supporting providers only) reusing existing private helpers unchanged; `update_entry()` (the `remo shell` tools-update path) now delegates to `upgrade()`. Renamed `--user` → `--host-user` (incus) / `--node-user` (proxmox) everywhere it appears (`remo add --user`, a different flag, is unchanged). Made every printed remedy truthful (SC-003): the registry-migration tagging notice and `sync`'s "Mark permanently:" line now recommend `tag` (previously wrongly recommended `sync`/`update`, which never wrote the marker); `remo shell`'s version-mismatch prompt now names the exact `remo <type> upgrade <name>` command it will run. Breaking change, no shim, no registry schema change: `remo <type> update`, flat `bootstrap`, and the old `--user` spelling are all Click "unknown command"/"no such option" errors post-change. FakeProvider's descriptor gained `upgrade_options`/`resize_dimensions`/`tag_options`/one `host_commands` entry, proving the full new surface is descriptor-only (SC-005).
324
- - 020-openapi-type-generation: Made the FastAPI service the machine-checked source of truth for every shape the browser console consumes, and made drift a build failure with an actionable message — three moves, in dependency order. **(1) Contract completeness, declaration-only** (not one serialized byte moves): `web/api/hosts.py` annotates `InstanceOut.status`/`SessionTargetOut.zellij_state`/`devcontainer_running` with the existing closed domain enums (dropping the `.value` unwrapping — a `str`-Enum serializes identically) and adds `KnownProviderType(str, Enum)` (`incus`/`hetzner`/`aws`/`proxmox`, fixed to the built-in set per FR-004a — never derived from the live `provider_registry`, so a third-party provider install can't perturb the artifact) typed `KnownProviderType | str` (`anyOf[$ref, string]`, keeping the wire field open); new `ErrorEnvelope`/`HealthResponse`/`ReadinessResponse`/`MintPairingResponse`/`DetailResponse` response models declare what four previously-untyped routes (`/health`, `/ready`, `/pairing/mint`, `POST /terminals`) already return, with the `{"error": {...}}` envelope declared only on routes that actually return it (never on `pairing.py`, whose 403 is `{"detail": ...}`). **(2) Generate and consume**: new stdlib `scripts/export_openapi.py` exports `frontend/src/api/generated/openapi.json` (`create_app().openapi()`, `sort_keys=True` + trailing newline for byte-reproducibility) and `terminal-frames.json` (a new `web/frames.py`: six Pydantic control-frame models + `InboundFrame`/`OutboundFrame` discriminated unions, wrapped via `TypeAdapter(...).json_schema()` in a `{protocol: "remo-terminal.v1", frame_version: 1, ...}` envelope that versions independently of the REST contract); `openapi-typescript` v7 (exact-pinned frontend devDependency) generates `schema.d.ts`, and a small synthetic-OpenAPI wrapper (`frontend/scripts/generate-frame-types.mjs`) generates `terminal-frames.d.ts` (openapi-typescript itself only accepts genuine OpenAPI documents). `web/api/terminals.py`'s five ad-hoc `{"v": 1, ...}` WS control-frame dict literals are gone, replaced by typed `frames.py` model construction/validation — `_handle_control`'s silent-drop behavior for malformed JSON, non-object payloads, and unknown frame types is preserved exactly (the one place this refactor could have changed runtime behavior; dedicated tests cover it). `frontend/src/api/client.ts` replaced ~12 hand-declared service-shaped interfaces with `components["schemas"][...]` aliases (console-owned shapes — `ApiError`, `ServiceStatus`, the forward-auth re-auth path — stay hand-written); `frontend/src/components/providerMeta.ts` now keys a `Record<InstanceStatus | KnownProviderType, ...>` off the generated unions, so a new enum member is a compile error at the presentation mapping while an off-union runtime value still renders via a preserved fallback (FR-013a — deleting that fallback to "achieve exhaustiveness" is explicitly wrong). **(3) Gate it**: three drift checks modeled on `tests/unit/test_docs_structure.py`'s established shape (name the artifact, group findings by kind, close with the exact regeneration command and a dependency-bump note) — `tests/unit/test_schema_drift.py` (REST + frame freshness against the live Python app, `test` CI job) and `frontend/scripts/check-types-fresh.mjs` (regenerated `.d.ts` vs. checked-in, `frontend` CI job) — fail, never skip, and never write a tracked file. New `docs/maintaining-generated-types.md` documents the four generated artifacts (never hand-edited; internal build input, no external compatibility promise, FR-029) and how to read a failure. No registry schema change; no new service runtime dependency.
325
341
  Only the newest three entries live here — `update-agent-context.sh` discards the rest on every run. The complete history is archived in [`docs/feature-history.md`](docs/feature-history.md); move displaced entries there rather than letting the generator drop them.
326
342
 
327
343
 
@@ -1,5 +1,22 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.3.5](https://github.com/get2knowio/remo/compare/v4.3.4...v4.3.5) (2026-08-16)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * **cli:** check the tools version on added SSH hosts too ([#178](https://github.com/get2knowio/remo/issues/178)) ([#179](https://github.com/get2knowio/remo/issues/179)) ([1727b72](https://github.com/get2knowio/remo/commit/1727b724faef9b5b994640c41e80c3ebb550d240))
9
+
10
+ ## [4.3.4](https://github.com/get2knowio/remo/compare/v4.3.3...v4.3.4) (2026-08-15)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * **ansible:** make devcontainers buildable where nested overlayfs is refused ([#173](https://github.com/get2knowio/remo/issues/173)) ([d500ff0](https://github.com/get2knowio/remo/commit/d500ff0e6ee397822be36d6c2de4d6489f47aa2c)), closes [#160](https://github.com/get2knowio/remo/issues/160) [#171](https://github.com/get2knowio/remo/issues/171)
16
+ * **web:** re-assert the terminal size so a dropped resize self-heals ([#174](https://github.com/get2knowio/remo/issues/174)) ([78b1dd4](https://github.com/get2knowio/remo/commit/78b1dd435a7305006c97eddf6817eaa624f9ab5b))
17
+ * **web:** rename trusted_store so CodeQL stops reading a path as a secret ([#168](https://github.com/get2knowio/remo/issues/168)) ([d370ab6](https://github.com/get2knowio/remo/commit/d370ab661f7d1d988595645b9f91cbca82cd5fa4))
18
+ * **web:** the push/adopt defect trio ([#157](https://github.com/get2knowio/remo/issues/157), [#158](https://github.com/get2knowio/remo/issues/158), [#159](https://github.com/get2knowio/remo/issues/159)) ([#166](https://github.com/get2knowio/remo/issues/166)) ([fe4bf31](https://github.com/get2knowio/remo/commit/fe4bf31d1acb8f9ca1efa5bddeee4f23e33668ee))
19
+
3
20
  ## [4.3.3](https://github.com/get2knowio/remo/compare/v4.3.2...v4.3.3) (2026-08-06)
4
21
 
5
22
 
@@ -47,7 +47,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
47
47
  ├── __main__.py # python -m remo_cli entry point
48
48
  ├── cli/ # Click command layer (parsing only, no business logic)
49
49
  │ ├── main.py # Root CLI group; mounts one group per remo_cli.core.provider_registry.all_descriptors()
50
- │ ├── shell.py # remo shell — registry-dispatched update_entry() (delegates to upgrade()); prompt names the exact `remo <type> upgrade <name>` it will run; unknown type/ssh handled explicitly (no silent no-op)
50
+ │ ├── shell.py # remo shell — pre-connect version check for EVERY host type; _run_tools_upgrade() dispatches to the provider's update_entry() (delegates to upgrade()) or, for type="ssh", providers/added.configure(); prompt names the exact `remo <type> upgrade <name>` / `remo configure <name>` it will run; unknown type raises (no silent no-op); an added host with no `~/.remo-version` marker connects silently (FR-011)
51
51
  │ ├── cp.py # remo cp
52
52
  │ ├── added.py # remo add / remo remove / remo configure — provider-neutral SSH host registration (014) and configure (022)
53
53
  │ ├── web.py # remo web {serve,check,push,status,adopt} — serve/check lazy-import remo_cli.web.* (NFR-008); push/status/adopt use core/web_adopt + core/web_drift only (adopt is a deprecated alias for push)
@@ -104,7 +104,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
104
104
  │ ├── pairing.py # In-memory, single-live, TTL'd pairing-code session manager replacing the static setup API token
105
105
  │ └── api/
106
106
  │ ├── hosts.py # GET /api/v1/hosts, /sessions, POST /discovery/refresh
107
- │ ├── setup.py # Token-gated /api/v1/setup/{status,identity,registry,verify} (011-web-adopt)
107
+ │ ├── setup.py # Pairing-gated /api/v1/setup/{status,identity,registry,verify,end} (011-web-adopt; `end` added by #158)
108
108
  │ ├── terminals.py # POST/GET/DELETE /api/v1/terminals, WS /api/v1/terminals/{id}
109
109
  │ └── pairing.py # POST /api/v1/pairing/{mint,end} — operator-auth-gated pairing-code control plane, outside the dormant setup router
110
110
  └── models/
@@ -121,7 +121,13 @@ frontend/ # remo-web browser SPA (Vite + React + TypeScript)
121
121
  │ │ # + masterLayout.ts (pure pane geometry: uniform grid + master/stack tiling)
122
122
  │ ├── state/ # discovery.ts, workspace.ts (layout persisted to localStorage), settings.ts (display prefs: site light/dark mode, accent, fonts, terminal theme + per-target overrides)
123
123
  │ ├── terminal/ # RendererAdapter (seam), XtermRenderer (the one engine), TerminalConnection, keymap
124
+ │ │ # + fitLoop.ts (the container->emulator->PTY fit, extracted so the
125
+ │ │ # browser geometry suite drives the shipped code and not a copy)
124
126
  │ └── theme/ # tokens.css (light-dark() palette, one pair per token), fonts.ts, terminalThemes.ts (8 terminal color schemes: a token-derived Remo Dark/Light pair the default 'auto' selection tracks, plus 6 curated third-party)
127
+ └── tests/
128
+ ├── e2e/ # Playwright console suite — needs a live `remo web serve` (REMO_E2E_BASE_URL)
129
+ └── geometry/ # Playwright terminal-geometry suite — no backend, gates CI
130
+ └── harness/ # Vite fixture mounting the REAL TerminalCard + paneLayout
125
131
 
126
132
  docker/ # remo-web container packaging (010-web-session-interface, US4)
127
133
  ├── Dockerfile # multi-stage: frontend build -> wheel build -> slim Python runtime
@@ -131,6 +137,12 @@ docker/ # remo-web container packaging (010-web-session-inter
131
137
  ansible/ # Ansible playbooks (invoked by Python via subprocess)
132
138
  ├── roles/
133
139
  │ ├── incus_bootstrap/
140
+ │ ├── nested_docker/ # Hosts whose kernel refuses NESTED overlayfs mounts (OrbStack): a
141
+ │ │ │ # native-snapshotter buildx builder + a devcontainer shim (#160/#171).
142
+ │ │ │ # Gated on group_vars' docker_nested_overlayfs; no-op elsewhere
143
+ │ │ └── templates/
144
+ │ │ └── devcontainer-shim.sh.j2 # /usr/local/bin/devcontainer: picks DOCKER_BUILDKIT /
145
+ │ │ # COMPOSE_BAKE / updateUID per project, per invocation
134
146
  │ └── user_setup/
135
147
  │ └── templates/
136
148
  │ └── remo-host.sh.j2 # Versioned `remo-host` command (capabilities/sessions/attach)
@@ -229,6 +241,9 @@ cd frontend && npm ci
229
241
  npm run build # tsc -b && vite build -> frontend/dist
230
242
  npm run lint # tsc --noEmit
231
243
  npm run test # Vitest unit/component suite (jsdom, no backend)
244
+ npm run test:geometry # Playwright terminal-geometry suite (no backend; serves its own
245
+ # fixture. jsdom has no layout engine, so this is the only place
246
+ # the terminal grid is checked against the box that clips it)
232
247
  npm run test:e2e # Playwright (needs REMO_E2E_BASE_URL -> live remo web serve)
233
248
  ```
234
249
 
@@ -283,6 +298,7 @@ made conditional to get a build green — fix the code or amend the gate by PR.
283
298
  | Lint | `uv run ruff check src/remo_cli` | Code Style |
284
299
  | Types | `uv run mypy src/remo_cli` | Code Style |
285
300
  | Frontend | `cd frontend && npm run lint && npm run test && npm run build` | Code Style |
301
+ | Browser geometry | `cd frontend && npm run test:geometry` | Terminal grid fits its box (jsdom cannot check this) |
286
302
  | Fish completion | `./tests/integration/fish_completion.sh` | Principle VI (completion runs, not just reads) |
287
303
  | Packaging | wheel install smoke, Docker amd64+arm64 | Distribution integrity |
288
304
  | Security | CodeQL, dependency review | Supply chain |
@@ -320,9 +336,9 @@ checking nothing.
320
336
  - Ansible 2.14+ / YAML: Follow standard conventions plus Constitution principles
321
337
 
322
338
  ## Recent Changes
339
+ - issues #160/#171 — nested overlayfs (OrbStack): Made hosts whose kernel refuses NESTED overlayfs mounts able to build devcontainers at all. An OrbStack "machine" is a container on a shared kernel (rootfs is a btrfs subvolume under `/scon/containers/<id>`), not a VM, so Docker inside it is nested and an overlay mount is refused — and Docker 29 made the containerd overlayfs snapshotter the default, so a freshly-configured host lands on the broken path with nothing to steer it. `remo configure` completed cleanly, `remo-host` responded, `remo web push` reported capabilities OK, and then every BuildKit build died on the first `RUN` with `mount source: "overlay" … operation not permitted`, surfaced as an opaque devcontainer-CLI stack trace that read like a project problem. New `ansible/roles/nested_docker/`, included from `tasks/configure_dev_tools.yml` (so all five configure playbooks inherit it) behind `group_vars/all.yml`'s `docker_nested_overlayfs`, which keys off `-orbstack-` in `ansible_kernel` — NOT `/mnt/mac`, which is absent under `orb create --isolated` and would have silently skipped the fix on exactly the configuration a user picks for a cleaner VM. It runs after `user_setup`, and every buildx task carries `become_user: remo_user`: buildx state lives in `~/.docker/buildx`, so a builder created for root leaves `project-launch` just as broken as no builder. **Two halves, because one fix is not enough.** (1) #160: a `docker-container` builder (`remo-native`) whose buildkitd.toml selects the `native` snapshotter, which copies layers instead of overlaying them — correct, and materially slower; `--bootstrap` so a broken image pull fails the configure rather than surfacing days later, and the builder is *recreated* when buildkitd.toml changes because `buildx create` reads `--config` once and an edited file otherwise never reaches an existing builder. (2) #171: the devcontainer CLI shells out to two builders whose requirements here are mutually exclusive — `docker compose build` HONOURS `DOCKER_BUILDKIT=0` and drops to the classic builder, which rejects the `additional_contexts` the CLI injects to install Features, while `updateUID`'s plain `docker build` needs exactly that setting to avoid the daemon's embedded BuildKit. No global value is correct for both, so a shim decides per invocation from the project's own `devcontainer.json`: Compose → `DOCKER_BUILDKIT=1 COMPOSE_BAKE=1` (verified: `COMPOSE_BAKE` alone still fails) plus `--update-remote-user-uid-default never` on `up`/`build` only — the CLI rejects the flag on `exec`, which `project-launch` uses; anything else → `DOCKER_BUILDKIT=0`, argv untouched; both → `BUILDX_BUILDER=remo-native`, so a user changing their default builder cannot silently break every devcontainer. Three placement decisions the tests pin, each defending a *silent* failure: the shim installs to `/usr/local/bin/devcontainer`, NOT `~/.local/bin` (that directory is added to PATH inside `~/.bashrc`, which returns early for non-interactive shells — a shim there would miss `ssh host 'devcontainer up …'`, the exact case it exists to fix, while passing every interactive test); it calls the real CLI by absolute path, because `command devcontainer` resolves through PATH, finds the shim again and recurses; and it declines to skip `updateUID` unless the host UID matches `user_setup`'s 1000 pin, since skipping at any other UID would trade a broken build for silently unwritable bind mounts. `docker buildx install` was rejected as the "clean" general fix — the docker-container driver cannot resolve the local-only image `updateUID`'s `FROM $BASE_IMAGE` names. remo NAMES a hand-added global `DOCKER_BUILDKIT` but does not delete it (the operator's line, in a file remo has no managed block in — the #121 authorized_keys lesson), and reports both costs it cannot fix via the task NAME, since `_filter_line` suppresses `debug` bodies: slower builds, and `apt` inside a running container failing with `Invalid cross-device link` (which is why `playwright install --with-deps`, and so E2E browser tests, cannot work on such a host — easy to miss, because a well-written `postCreateCommand` treats it as non-fatal and `devcontainer up` still reports success). New `tests/unit/test_devcontainer_shim.py` renders the template and *executes* it against a stub CLI for every branch. New `docs/nested-overlayfs.md`. No registry schema change; no new runtime deps; no new CLI flag or tool toggle — it is a repair for the tools already selected, not another tool.
323
340
  - 022-configure-added-hosts: Made manually-added SSH hosts first-class by giving them the one thing `remo add` (014) never did — a configure path. New provider-neutral `remo configure NAME` runs a new generic `ansible/ssh_configure.yml` against a registry `type="ssh"` entry, so an added host finally gets `remo-host`/zellij/`project-launch` and stops sitting in the `remo web` rail permanently badged `no_remo_host` with zero session targets. **No refactor of the four provider plays**: the role list was already shared via `tasks/configure_dev_tools.yml`, so a fifth playbook inherits the whole toolchain — the change is purely additive. The new play is two plays: a `localhost` play that asserts (never defaults) `remo_ssh_host`/`remo_ssh_user`/`remo_ssh_port` and `add_host`s them onto `ansible_host`/`ansible_user`/`ansible_port`/`ansible_ssh_private_key_file`, then a play targeting that named group (NOT `hosts: all`, which would pick up `inventory/hosts.yml`'s `hetzner_server` and whose zero-host case exits rc 0 — a silent false success). Four decisions the tests pin, each defending a *silent* failure: the identity is `| default(omit)`, never `'~/.ssh/id_rsa'` (aws_configure.yml's anti-pattern — a path default offers the WRONG key); it is paired with an explicit `-o IdentitiesOnly=yes`, which ansible-core does not add for `private_key_file` (without it a busy agent hits MaxAuthTries and dies "Too many authentication failures" while the passed key is never tried); both `raw` pre-flight probes (python3, `sudo -n true`) set `become: false`, since `ansible.cfg` sets `become = True` globally and a sudo probe run THROUGH sudo proves nothing; and `remo_user` is bound to `remo_ssh_user` rather than `group_vars/all.yml`'s `"remo"` — everything `user_setup` installs lands in `/home/{{ remo_user }}/.local/bin` and discovery logs in as the REGISTERED user, so the default would install `remo-host` into a second account and leave the console still reporting `no_remo_host` after a "successful" configure (it also skips the UID-1000 displacement, which only fires when 1000's holder is someone else). Root is refused (UID-1000 pin), the prompt defaults to no, and remo never reboots a host it did not provision — it reports via the task NAME, since `_filter_line` suppresses `debug` bodies. `core/known_hosts.py` gains `guard_added_ssh_host_only`, the mirror of `guard_not_added_ssh_host`: a provider host is refused naming `remo <type> upgrade NAME`, because the five configure plays are not interchangeable and a mis-target would succeed while configuring wrongly. **Bug fix in the same change** (`core/web_adopt.py`): `remo web push` hardcoded port 22 in `scan_and_verify_host_key`'s `ssh-keyscan` and `_lookup_trusted_keys`' `ssh-keygen -F`, so an added host on another port was reported `skipped/unreachable` — `authorize_service_key` never ran — with a remediation blaming a host that was reachable, or, worse, a different machine answering on 22 had its keys pushed. New `known_hosts_lookup_key()` follows OpenSSH's record form (bare for 22, `[host]:port` otherwise; verified against the real binary — neither direction is forgiving), and `-p` is omitted for 22 so every provider host's argv is byte-identical. `providers/added.py`'s `_reject_unsafe_field` now also rejects Jinja delimiters (registry values become extra-vars, which Ansible templates on the CONTROL NODE), re-checked on the configure read path so pre-existing entries are covered. `web/discovery.py`'s `no_remo_host` remediation now names the real command per host type instead of "re-run configure", which for an added host pointed at nothing. No registry schema change; no new runtime deps.
324
341
  - 021-cli-plane-separation: Split the three-intent `remo <provider> update` verb into three single-intent verbs — `upgrade` (in-instance configure play only, zero provider-side writes, SC-001), `resize` (resource change only — the factory rejects a dimensionless invocation with a `PreconditionError` listing that provider's dimension flags, before dispatching to the provider), and `tag` (managed-marker write only, generated iff `supports_managed_marker`; read-before-write no-op when already tagged, `OperationFailedError` — not `create`'s warn-and-continue — on write failure, SC-002) — and moved `bootstrap` off the flat instance plane into a new descriptor-driven `host` subgroup (`remo {incus,proxmox} host bootstrap`, generated iff `host_commands` is non-empty; `CommandSpec` gained a `target: ArgumentSpec | None` field so host commands take the host positionally — incus optional/defaults to localhost, proxmox required). `core/provider_registry.py`: `ProviderDescriptor.update_options` removed, replaced by `upgrade_options`/`resize_dimensions`/`resize_options`/`tag_options`/`host_commands`; new `ArgumentSpec` dataclass. `cli/providers/factory.py`: `_build_update` replaced by `_build_upgrade`/`_build_resize`/`_build_tag`/`_build_host_group`; `_instance_argument` grew a `param` kwarg so the new verbs take `NAME` positionally (matching the provider impl's `name` kwarg) while `create`/`destroy`/`info` keep `--name`; `_resolve_entry_for_destroy`'s user-hint lookup is now descriptor-driven (reads `kwargs` under the `registry_fields` JSON key ending in `_user`) instead of a `"user"` literal. Every provider module split `update()` into `upgrade()`/`resize()`/`tag()` (marker-supporting providers only) reusing existing private helpers unchanged; `update_entry()` (the `remo shell` tools-update path) now delegates to `upgrade()`. Renamed `--user` → `--host-user` (incus) / `--node-user` (proxmox) everywhere it appears (`remo add --user`, a different flag, is unchanged). Made every printed remedy truthful (SC-003): the registry-migration tagging notice and `sync`'s "Mark permanently:" line now recommend `tag` (previously wrongly recommended `sync`/`update`, which never wrote the marker); `remo shell`'s version-mismatch prompt now names the exact `remo <type> upgrade <name>` command it will run. Breaking change, no shim, no registry schema change: `remo <type> update`, flat `bootstrap`, and the old `--user` spelling are all Click "unknown command"/"no such option" errors post-change. FakeProvider's descriptor gained `upgrade_options`/`resize_dimensions`/`tag_options`/one `host_commands` entry, proving the full new surface is descriptor-only (SC-005).
325
- - 020-openapi-type-generation: Made the FastAPI service the machine-checked source of truth for every shape the browser console consumes, and made drift a build failure with an actionable message — three moves, in dependency order. **(1) Contract completeness, declaration-only** (not one serialized byte moves): `web/api/hosts.py` annotates `InstanceOut.status`/`SessionTargetOut.zellij_state`/`devcontainer_running` with the existing closed domain enums (dropping the `.value` unwrapping — a `str`-Enum serializes identically) and adds `KnownProviderType(str, Enum)` (`incus`/`hetzner`/`aws`/`proxmox`, fixed to the built-in set per FR-004a — never derived from the live `provider_registry`, so a third-party provider install can't perturb the artifact) typed `KnownProviderType | str` (`anyOf[$ref, string]`, keeping the wire field open); new `ErrorEnvelope`/`HealthResponse`/`ReadinessResponse`/`MintPairingResponse`/`DetailResponse` response models declare what four previously-untyped routes (`/health`, `/ready`, `/pairing/mint`, `POST /terminals`) already return, with the `{"error": {...}}` envelope declared only on routes that actually return it (never on `pairing.py`, whose 403 is `{"detail": ...}`). **(2) Generate and consume**: new stdlib `scripts/export_openapi.py` exports `frontend/src/api/generated/openapi.json` (`create_app().openapi()`, `sort_keys=True` + trailing newline for byte-reproducibility) and `terminal-frames.json` (a new `web/frames.py`: six Pydantic control-frame models + `InboundFrame`/`OutboundFrame` discriminated unions, wrapped via `TypeAdapter(...).json_schema()` in a `{protocol: "remo-terminal.v1", frame_version: 1, ...}` envelope that versions independently of the REST contract); `openapi-typescript` v7 (exact-pinned frontend devDependency) generates `schema.d.ts`, and a small synthetic-OpenAPI wrapper (`frontend/scripts/generate-frame-types.mjs`) generates `terminal-frames.d.ts` (openapi-typescript itself only accepts genuine OpenAPI documents). `web/api/terminals.py`'s five ad-hoc `{"v": 1, ...}` WS control-frame dict literals are gone, replaced by typed `frames.py` model construction/validation — `_handle_control`'s silent-drop behavior for malformed JSON, non-object payloads, and unknown frame types is preserved exactly (the one place this refactor could have changed runtime behavior; dedicated tests cover it). `frontend/src/api/client.ts` replaced ~12 hand-declared service-shaped interfaces with `components["schemas"][...]` aliases (console-owned shapes — `ApiError`, `ServiceStatus`, the forward-auth re-auth path — stay hand-written); `frontend/src/components/providerMeta.ts` now keys a `Record<InstanceStatus | KnownProviderType, ...>` off the generated unions, so a new enum member is a compile error at the presentation mapping while an off-union runtime value still renders via a preserved fallback (FR-013a — deleting that fallback to "achieve exhaustiveness" is explicitly wrong). **(3) Gate it**: three drift checks modeled on `tests/unit/test_docs_structure.py`'s established shape (name the artifact, group findings by kind, close with the exact regeneration command and a dependency-bump note) — `tests/unit/test_schema_drift.py` (REST + frame freshness against the live Python app, `test` CI job) and `frontend/scripts/check-types-fresh.mjs` (regenerated `.d.ts` vs. checked-in, `frontend` CI job) — fail, never skip, and never write a tracked file. New `docs/maintaining-generated-types.md` documents the four generated artifacts (never hand-edited; internal build input, no external compatibility promise, FR-029) and how to read a failure. No registry schema change; no new service runtime dependency.
326
342
  Only the newest three entries live here — `update-agent-context.sh` discards the rest on every run. The complete history is archived in [`docs/feature-history.md`](docs/feature-history.md); move displaced entries there rather than letting the generator drop them.
327
343
 
328
344
 
@@ -104,7 +104,7 @@ pre-release, and publishes the prerelease to PyPI + GHCR (`latest` is never
104
104
  moved). Users can install with:
105
105
 
106
106
  ```bash
107
- curl -fsSL https://get2knowio.github.io/remo/install.sh | bash -s -- --pre-release
107
+ curl -fsSL https://raw.githubusercontent.com/get2knowio/remo/main/install.sh | bash -s -- --pre-release
108
108
  ```
109
109
 
110
110
  > Prefer testing **without** publishing when you can — a local wheel or a
@@ -127,7 +127,7 @@ You do **not** bump the version or push a tag by hand for stable releases:
127
127
 
128
128
  Users install the stable release with:
129
129
  ```bash
130
- curl -fsSL https://get2knowio.github.io/remo/install.sh | bash
130
+ curl -fsSL https://raw.githubusercontent.com/get2knowio/remo/main/install.sh | bash
131
131
  ```
132
132
 
133
133
  > **One-time setup — publish trigger:** the tag release-please creates must be
@@ -180,12 +180,24 @@ We use [Semantic Versioning](https://semver.org/):
180
180
 
181
181
  ## Updating the Installer
182
182
 
183
- When you modify `install.sh`:
183
+ `install.sh` at the repo root is the one copy, served straight off `main`:
184
184
 
185
- 1. The `sync-install.yml` workflow automatically copies it to `docs/install.sh`
186
- 2. GitHub Pages serves the updated version at https://get2knowio.github.io/remo/install.sh
185
+ ```
186
+ https://raw.githubusercontent.com/get2knowio/remo/main/install.sh
187
+ ```
188
+
189
+ There is no publish step and no second copy to keep in sync — a merge to
190
+ `main` *is* the deploy. Note the URL is pinned to `main`, not to a tag: users
191
+ should always get the current installer, and pinning a *release* is what the
192
+ script's own `--version` flag is for.
187
193
 
188
- No manual sync needed.
194
+ Because it ships the instant it merges, treat a change to `install.sh` as a
195
+ change to production: run `bash -n install.sh` at minimum, and prefer testing
196
+ the raw URL from your own branch first —
197
+
198
+ ```bash
199
+ curl -fsSL https://raw.githubusercontent.com/get2knowio/remo/<your-branch>/install.sh | bash
200
+ ```
189
201
 
190
202
  ## Testing Changes
191
203
 
@@ -206,6 +218,6 @@ remo incus destroy test-container --yes --host <incus-host>
206
218
  ### Test Installer
207
219
 
208
220
  ```bash
209
- # Test from branch
210
- curl -fsSL https://get2knowio.github.io/remo/install.sh | bash -s -- --branch my-feature
221
+ # Test the latest pre-release
222
+ curl -fsSL https://raw.githubusercontent.com/get2knowio/remo/main/install.sh | bash -s -- --pre-release
211
223
  ```
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: remo-cli
3
- Version: 4.3.3
3
+ Version: 4.3.5
4
4
  Summary: Remote development environment CLI
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -327,6 +327,13 @@ remo configure mybox --skip docker # everything except Docker
327
327
  remo web push # authorize the web service on it
328
328
  ```
329
329
 
330
+ Re-running it is how a configured host stays current — it refreshes
331
+ `project-menu`, `remo-host`, `project-launch` and the rest of the toolchain, and
332
+ applies system package updates. `remo shell` checks the version on connect and
333
+ offers to run it for you when the host is behind, exactly as it does for
334
+ provider hosts. A host you added but never configured is left alone: no marker,
335
+ no prompt, straight into a login shell.
336
+
330
337
  #### Example: an OrbStack VM
331
338
 
332
339
  [`docs/examples/orbstack-cloud-init.yaml`](docs/examples/orbstack-cloud-init.yaml)
@@ -334,30 +341,76 @@ prepares an [OrbStack](https://orbstack.dev) VM on a Mac so `remo add` and
334
341
  `remo configure` work first time:
335
342
 
336
343
  ```bash
337
- orb create ubuntu remo-mbp -c docs/examples/orbstack-cloud-init.yaml
344
+ orb create ubuntu remo-mbp -u orbadmin -c docs/examples/orbstack-cloud-init.yaml
345
+ remo add mbp remo@<name-that-resolves> --verify
338
346
  ```
339
347
 
340
348
  It installs only what Ansible needs to connect and hand over — `remo configure`
341
- does the rest. It deliberately creates no user: OrbStack already makes one named
342
- after your macOS account holding UID 1000, and registering *that* user is what
343
- puts `remo-host` in the home directory the web service logs into, while skipping
344
- `user_setup`'s UID-1000 reassignment entirely.
345
-
346
- To reach the VM from anywhere — your workstation, a homelab box, or the
347
- `remo web` service — rather than only from its Mac, use
349
+ does the rest. It creates a `remo` account at **UID 1000** and installs your key
350
+ there, which is the account to register.
351
+
352
+ `-u orbadmin` is not optional. OrbStack creates a Linux account named after your
353
+ macOS user, pins it to your **macOS UID** (501, not 1000), and does so *after*
354
+ cloud-init finishes — it will even renumber a cloud-init-created account that
355
+ shares its name. Giving OrbStack a throwaway name to own leaves UID 1000 free.
356
+ That matters because `user_setup` pins `remo_user` to UID 1000: register an
357
+ account at any other UID and `remo configure` runs `usermod -u 1000` against the
358
+ account Ansible is logged in as, which shadow-utils refuses to do for a user with
359
+ running processes. Add `--isolated` too if you want a plain VM with no Mac file
360
+ sharing; it is independent of the UID fix.
361
+
362
+ **Which name to register.** An OrbStack VM is not on your LAN — it gets a static
363
+ address on OrbStack's internal bridge, and OrbStack has no bridged/DHCP-from-your
364
+ -router mode — so its own IP means nothing to any other machine. Three paths, in
365
+ increasing reach:
366
+
367
+ | From | Register | Notes |
368
+ |------|----------|-------|
369
+ | The Mac itself | `remo-mbp.orb.local` | OrbStack's DNS. Nothing to set up. |
370
+ | Your LAN, or a VPN | `<your-mac>` | OrbStack forwards the VM's `:22` to the Mac and exposes it on every interface, so the Mac's name reaches the VM's sshd with nothing installed in the VM. |
371
+ | Anywhere | `remo-mbp.<tailnet>.ts.net` | The Tailscale example below — needed only if you want the VM itself on the tailnet. |
372
+
373
+ Prefer a **bare name** over an FQDN or an IP: it resolves through whichever
374
+ search domain is up — your VPN's or your router's — so one entry keeps working
375
+ as you move. That is why a registered host reads `"host": "dev1"`.
376
+
377
+ Two gotchas on the middle row. It routes through the *Mac's* `:22`, so only one
378
+ VM can own it (and it collides with macOS Remote Login) — for a second VM,
379
+ change `Port` in the sshd drop-in and register `remo@<mac>:<port>`. And a Mac
380
+ does not register itself in your router's DNS the way a Linux DHCP client does:
381
+ macOS sends the DHCP hostname only when `HostName` is set, which it is not by
382
+ default (`LocalHostName`, the mDNS `.local` name, is never sent, and Linux hosts
383
+ generally cannot resolve `.local` at all). Fix it once with
384
+ `sudo scutil --set HostName <name> && sudo ipconfig set en0 DHCP` — after which
385
+ the address may change freely, since DNS follows it.
386
+ If a VPN or a Tailscale exit node with LAN access claims OrbStack's subnet
387
+ (`orb config get network.subnet4`), even the Mac-local path black-holes; check
388
+ with `route -n get <vm-ip>`.
389
+
390
+ **Devcontainer builds.** An OrbStack machine is a container on a shared kernel,
391
+ so Docker inside it is nested and the kernel refuses the overlayfs mounts
392
+ BuildKit's default snapshotter needs — without help, no devcontainer builds at
393
+ all. `remo configure` detects this and provisions a `native`-snapshotter buildx
394
+ builder plus a `devcontainer` shim that picks the right build environment per
395
+ project; builds work, but are noticeably slower. Two limits it cannot fix —
396
+ `apt` inside a running container, and therefore `playwright install --with-deps`
397
+ — are covered in [`docs/nested-overlayfs.md`](docs/nested-overlayfs.md).
398
+
399
+ To reach the VM from anywhere — including a `remo web` service that cannot reach
400
+ your Mac — use
348
401
  [`docs/examples/orbstack-cloud-init-tailscale.yaml`](docs/examples/orbstack-cloud-init-tailscale.yaml)
349
402
  instead. Same file plus Tailscale; it prints the address to register on first
350
- boot. Register the MagicDNS name, **not** the OrbStack IP:
403
+ boot:
351
404
 
352
405
  ```bash
353
- orb create ubuntu remo-mbp -c docs/examples/orbstack-cloud-init-tailscale.yaml
354
- remo add mbp <user>@remo-mbp.<your-tailnet>.ts.net --verify
406
+ orb create ubuntu remo-mbp -u orbadmin -c docs/examples/orbstack-cloud-init-tailscale.yaml
407
+ remo add mbp remo@remo-mbp.<your-tailnet>.ts.net --verify
355
408
  ```
356
409
 
357
- An OrbStack VM's own IP is reachable from its Mac and nowhere else, so a
358
- registry entry pointing at it is useless to a `remo web` service running
359
- anywhere else. Use an **ephemeral** auth key: cloud-init keeps your user-data
360
- on the VM's disk, so the key outlives the boot that used it.
410
+ Use an **ephemeral** auth key: cloud-init keeps your user-data on the VM's disk,
411
+ so the key outlives the boot that used it. Leaving the placeholder is fine —
412
+ tailscaled still installs, and `sudo tailscale up` joins interactively with no
413
+ credential on disk.
361
414
 
362
415
  `remo remove NAME [--yes]` deregisters an added host by deleting **only** the
363
416
  local registry entry — it makes no connection to and no change on the remote