remo-cli 2.2.0rc1__tar.gz → 2.2.0rc2__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 (413) hide show
  1. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.devcontainer/devcontainer.json +2 -2
  2. remo_cli-2.2.0rc2/.specify/feature.json +3 -0
  3. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/CLAUDE.md +7 -4
  4. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/PKG-INFO +14 -6
  5. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/README.md +13 -5
  6. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docker/compose.example.yml +97 -0
  7. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docker/entrypoint.sh +8 -0
  8. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/web-session-interface.md +322 -8
  9. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/api/client.ts +14 -4
  10. remo_cli-2.2.0rc2/frontend/src/components/AppRoot.tsx +25 -0
  11. remo_cli-2.2.0rc2/frontend/src/components/AwaitingAdoption.css +115 -0
  12. remo_cli-2.2.0rc2/frontend/src/components/AwaitingAdoption.tsx +109 -0
  13. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/TopBar.tsx +5 -0
  14. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/main.tsx +5 -4
  15. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/state/health.ts +20 -8
  16. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/pyproject.toml +1 -1
  17. remo_cli-2.2.0rc2/specs/011-web-adopt/checklists/requirements.md +44 -0
  18. remo_cli-2.2.0rc2/specs/011-web-adopt/contracts/cli-web-adopt.md +78 -0
  19. remo_cli-2.2.0rc2/specs/011-web-adopt/contracts/setup-api.md +98 -0
  20. remo_cli-2.2.0rc2/specs/011-web-adopt/data-model.md +123 -0
  21. remo_cli-2.2.0rc2/specs/011-web-adopt/plan.md +163 -0
  22. remo_cli-2.2.0rc2/specs/011-web-adopt/quickstart-results.md +29 -0
  23. remo_cli-2.2.0rc2/specs/011-web-adopt/quickstart.md +135 -0
  24. remo_cli-2.2.0rc2/specs/011-web-adopt/research.md +311 -0
  25. remo_cli-2.2.0rc2/specs/011-web-adopt/spec.md +507 -0
  26. remo_cli-2.2.0rc2/specs/011-web-adopt/tasks.md +213 -0
  27. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/web.py +155 -0
  28. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/ssh.py +45 -2
  29. remo_cli-2.2.0rc2/src/remo_cli/core/web_adopt.py +1338 -0
  30. remo_cli-2.2.0rc2/src/remo_cli/web/api/setup.py +394 -0
  31. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/app.py +40 -1
  32. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/check.py +71 -4
  33. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/config.py +65 -0
  34. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/discovery.py +9 -1
  35. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/health.py +74 -15
  36. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/logging_config.py +16 -0
  37. remo_cli-2.2.0rc2/src/remo_cli/web/state.py +287 -0
  38. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/terminal.py +29 -2
  39. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/image/test_docker_image.py +258 -1
  40. remo_cli-2.2.0rc2/tests/integration/test_web_adopt_e2e.py +736 -0
  41. remo_cli-2.2.0rc2/tests/unit/cli/test_web_adopt_cmd.py +354 -0
  42. remo_cli-2.2.0rc2/tests/unit/core/test_ssh_identity_opts.py +363 -0
  43. remo_cli-2.2.0rc2/tests/unit/core/test_web_adopt_authorize.py +346 -0
  44. remo_cli-2.2.0rc2/tests/unit/core/test_web_adopt_payload.py +253 -0
  45. remo_cli-2.2.0rc2/tests/unit/core/test_web_adopt_trust.py +554 -0
  46. remo_cli-2.2.0rc2/tests/unit/core/test_web_push.py +630 -0
  47. remo_cli-2.2.0rc2/tests/unit/web/conftest.py +188 -0
  48. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_csp.py +51 -0
  49. remo_cli-2.2.0rc2/tests/unit/web/test_health_states.py +304 -0
  50. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_log_redaction.py +39 -0
  51. remo_cli-2.2.0rc2/tests/unit/web/test_setup_api.py +484 -0
  52. remo_cli-2.2.0rc2/tests/unit/web/test_setup_auth.py +378 -0
  53. remo_cli-2.2.0rc2/tests/unit/web/test_state.py +292 -0
  54. remo_cli-2.2.0rc1/.specify/feature.json +0 -3
  55. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-analyze/SKILL.md +0 -0
  56. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-checklist/SKILL.md +0 -0
  57. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-clarify/SKILL.md +0 -0
  58. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-constitution/SKILL.md +0 -0
  59. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-converge/SKILL.md +0 -0
  60. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-git-commit/SKILL.md +0 -0
  61. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-git-feature/SKILL.md +0 -0
  62. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-git-initialize/SKILL.md +0 -0
  63. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-git-remote/SKILL.md +0 -0
  64. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-git-validate/SKILL.md +0 -0
  65. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-implement/SKILL.md +0 -0
  66. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-plan/SKILL.md +0 -0
  67. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-specify/SKILL.md +0 -0
  68. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-tasks/SKILL.md +0 -0
  69. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.claude/skills/speckit-taskstoissues/SKILL.md +0 -0
  70. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.dockerignore +0 -0
  71. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.github/dependabot.yml +0 -0
  72. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.github/workflows/ci.yml +0 -0
  73. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.github/workflows/provision.yml +0 -0
  74. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.github/workflows/release.yml +0 -0
  75. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.github/workflows/smoke-test-cleanup.yml +0 -0
  76. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.github/workflows/smoke-test.yml +0 -0
  77. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.github/workflows/teardown.yml +0 -0
  78. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.gitignore +0 -0
  79. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.maverick/checkpoints/feature/implementation_complete.json +0 -0
  80. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.maverick/checkpoints/feature/phase_${{ index }}_complete.json +0 -0
  81. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.maverick/checkpoints/feature/validation_complete.json +0 -0
  82. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/.registry +0 -0
  83. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/README.md +0 -0
  84. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/commands/speckit.git.commit.md +0 -0
  85. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/commands/speckit.git.feature.md +0 -0
  86. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/commands/speckit.git.initialize.md +0 -0
  87. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/commands/speckit.git.remote.md +0 -0
  88. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/commands/speckit.git.validate.md +0 -0
  89. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/config-template.yml +0 -0
  90. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/extension.yml +0 -0
  91. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/git-config.yml +0 -0
  92. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/bash/auto-commit.sh +0 -0
  93. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/bash/create-new-feature.sh +0 -0
  94. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/bash/git-common.sh +0 -0
  95. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/bash/initialize-repo.sh +0 -0
  96. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
  97. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/powershell/create-new-feature.ps1 +0 -0
  98. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/powershell/git-common.ps1 +0 -0
  99. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
  100. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/extensions.yml +0 -0
  101. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/init-options.json +0 -0
  102. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/integration.json +0 -0
  103. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/integrations/claude.manifest.json +0 -0
  104. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/integrations/speckit.manifest.json +0 -0
  105. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/memory/constitution.md +0 -0
  106. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/scripts/bash/check-prerequisites.sh +0 -0
  107. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/scripts/bash/common.sh +0 -0
  108. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/scripts/bash/create-new-feature.sh +0 -0
  109. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/scripts/bash/setup-plan.sh +0 -0
  110. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/scripts/bash/setup-tasks.sh +0 -0
  111. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/scripts/bash/update-agent-context.sh +0 -0
  112. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/templates/agent-file-template.md +0 -0
  113. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/templates/checklist-template.md +0 -0
  114. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/templates/constitution-template.md +0 -0
  115. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/templates/plan-template.md +0 -0
  116. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/templates/spec-template.md +0 -0
  117. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/templates/tasks-template.md +0 -0
  118. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/workflows/speckit/workflow.yml +0 -0
  119. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/.specify/workflows/workflow-registry.json +0 -0
  120. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/AGENTS.md +0 -0
  121. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/CONTRIBUTING.md +0 -0
  122. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/Dockerfile +0 -0
  123. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/LICENSE +0 -0
  124. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/.ansible-lint +0 -0
  125. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/README.md +0 -0
  126. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/ansible.cfg +0 -0
  127. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/aws_configure.yml +0 -0
  128. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/aws_resize.yml +0 -0
  129. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/aws_site.yml +0 -0
  130. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/aws_teardown.yml +0 -0
  131. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/group_vars/all.yml +0 -0
  132. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/group_vars/incus_containers.yml +0 -0
  133. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/group_vars/proxmox_containers.yml +0 -0
  134. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/hetzner_configure.yml +0 -0
  135. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/hetzner_provision.yml +0 -0
  136. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/hetzner_resize.yml +0 -0
  137. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/hetzner_site.yml +0 -0
  138. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/hetzner_teardown.yml +0 -0
  139. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/incus_bootstrap.yml +0 -0
  140. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/incus_configure.yml +0 -0
  141. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/incus_provision.yml +0 -0
  142. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/incus_resize.yml +0 -0
  143. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/incus_site.yml +0 -0
  144. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/incus_teardown.yml +0 -0
  145. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/inventory/hosts.yml +0 -0
  146. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/inventory/incus_containers.yml +0 -0
  147. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/proxmox_bootstrap.yml +0 -0
  148. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/proxmox_configure.yml +0 -0
  149. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/proxmox_provision.yml +0 -0
  150. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/proxmox_resize.yml +0 -0
  151. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/proxmox_site.yml +0 -0
  152. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/proxmox_teardown.yml +0 -0
  153. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/requirements.yml +0 -0
  154. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/aws_server/defaults/main.yml +0 -0
  155. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/aws_server/tasks/ebs.yml +0 -0
  156. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/aws_server/tasks/ec2.yml +0 -0
  157. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/aws_server/tasks/main.yml +0 -0
  158. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/aws_server/tasks/patch_manager.yml +0 -0
  159. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/aws_server/tasks/preflight.yml +0 -0
  160. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/aws_server/tasks/security_group.yml +0 -0
  161. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/deacon/defaults/main.yml +0 -0
  162. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/deacon/tasks/main.yml +0 -0
  163. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/devcontainers/tasks/main.yml +0 -0
  164. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/docker/handlers/main.yml +0 -0
  165. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/docker/tasks/main.yml +0 -0
  166. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/fzf/tasks/main.yml +0 -0
  167. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/github_cli/tasks/main.yml +0 -0
  168. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/hetzner_server/defaults/main.yml +0 -0
  169. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/hetzner_server/tasks/main.yml +0 -0
  170. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_bootstrap/defaults/main.yml +0 -0
  171. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_bootstrap/handlers/main.yml +0 -0
  172. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_bootstrap/tasks/main.yml +0 -0
  173. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container/defaults/main.yml +0 -0
  174. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container/handlers/main.yml +0 -0
  175. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container/meta/main.yml +0 -0
  176. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container/tasks/main.yml +0 -0
  177. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container/tasks/preflight.yml +0 -0
  178. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container_teardown/defaults/main.yml +0 -0
  179. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container_teardown/meta/main.yml +0 -0
  180. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/incus_container_teardown/tasks/main.yml +0 -0
  181. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/nodejs/defaults/main.yml +0 -0
  182. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/nodejs/tasks/main.yml +0 -0
  183. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_bootstrap/defaults/main.yml +0 -0
  184. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_bootstrap/meta/main.yml +0 -0
  185. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_bootstrap/tasks/main.yml +0 -0
  186. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container/defaults/main.yml +0 -0
  187. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container/handlers/main.yml +0 -0
  188. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container/meta/main.yml +0 -0
  189. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container/tasks/main.yml +0 -0
  190. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container/tasks/preflight.yml +0 -0
  191. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container_teardown/defaults/main.yml +0 -0
  192. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container_teardown/meta/main.yml +0 -0
  193. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/proxmox_container_teardown/tasks/main.yml +0 -0
  194. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/user_setup/defaults/main.yml +0 -0
  195. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/user_setup/tasks/main.yml +0 -0
  196. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/user_setup/templates/devshell.sh.j2 +0 -0
  197. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/user_setup/templates/project-launch.sh.j2 +0 -0
  198. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/user_setup/templates/project-menu.sh.j2 +0 -0
  199. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/user_setup/templates/remo-host.sh.j2 +0 -0
  200. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/zellij/defaults/main.yml +0 -0
  201. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/zellij/tasks/main.yml +0 -0
  202. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/zellij/templates/config.kdl.j2 +0 -0
  203. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/roles/zellij/templates/layouts/minimal.kdl.j2 +0 -0
  204. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/ansible/tasks/configure_dev_tools.yml +0 -0
  205. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docker/Dockerfile +0 -0
  206. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/aws.md +0 -0
  207. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/hetzner.md +0 -0
  208. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/incus.md +0 -0
  209. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/install.sh +0 -0
  210. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/proxmox.md +0 -0
  211. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/remo-web-speckit-input.md +0 -0
  212. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/docs/remo-web.html +0 -0
  213. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/index.html +0 -0
  214. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/package-lock.json +0 -0
  215. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/package.json +0 -0
  216. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/public/README.md +0 -0
  217. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/public/dist__ghostty-vt.wasm +0 -0
  218. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/public/ghostty-vt.wasm +0 -0
  219. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/scripts/copy-ghostty-wasm.mjs +0 -0
  220. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/AppShell.css +0 -0
  221. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/AppShell.tsx +0 -0
  222. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/OfflineOverlay.css +0 -0
  223. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/OfflineOverlay.tsx +0 -0
  224. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/SessionRail.css +0 -0
  225. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/SessionRail.tsx +0 -0
  226. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/SettingsPage.css +0 -0
  227. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/SettingsPage.tsx +0 -0
  228. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/ShortcutsModal.css +0 -0
  229. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/ShortcutsModal.tsx +0 -0
  230. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/TerminalCard.css +0 -0
  231. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/TerminalCard.tsx +0 -0
  232. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/TopBar.css +0 -0
  233. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/WorkspacePane.css +0 -0
  234. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/WorkspacePane.tsx +0 -0
  235. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/providerMeta.ts +0 -0
  236. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/components/railModel.ts +0 -0
  237. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/state/discovery.ts +0 -0
  238. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/state/fonts.ts +0 -0
  239. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/state/settings.ts +0 -0
  240. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/state/useConsoleKeyboard.ts +0 -0
  241. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/state/workspace.ts +0 -0
  242. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/terminal/.gitkeep +0 -0
  243. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/terminal/GhosttyRenderer.ts +0 -0
  244. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/terminal/RendererAdapter.ts +0 -0
  245. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/terminal/TerminalConnection.ts +0 -0
  246. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/terminal/XtermRenderer.ts +0 -0
  247. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/terminal/defaultRenderer.ts +0 -0
  248. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/theme/fonts.ts +0 -0
  249. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/src/theme/tokens.css +0 -0
  250. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/tsconfig.json +0 -0
  251. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/frontend/vite.config.ts +0 -0
  252. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/install.sh +0 -0
  253. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/maverick.yaml +0 -0
  254. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/playwright.config.ts +0 -0
  255. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/project-menu.sh +0 -0
  256. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/remo +0 -0
  257. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/run.sh +0 -0
  258. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/scripts/setup-aws-oidc.sh +0 -0
  259. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/checklists/requirements.md +0 -0
  260. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/checklists/validation.md +0 -0
  261. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/contracts/playbook-interface.yaml +0 -0
  262. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/contracts/role-interface.yaml +0 -0
  263. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/data-model.md +0 -0
  264. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/plan.md +0 -0
  265. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/quickstart.md +0 -0
  266. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/research.md +0 -0
  267. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/spec.md +0 -0
  268. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/001-bootstrap-incus-host/tasks.md +0 -0
  269. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/checklists/requirements.md +0 -0
  270. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/contracts/playbook-interface.yaml +0 -0
  271. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/contracts/role-interface.yaml +0 -0
  272. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/data-model.md +0 -0
  273. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/plan.md +0 -0
  274. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/quickstart.md +0 -0
  275. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/research.md +0 -0
  276. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/spec.md +0 -0
  277. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/002-incus-container-support/tasks.md +0 -0
  278. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/003-python-cli-rewrite/checklists/requirements.md +0 -0
  279. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/003-python-cli-rewrite/data-model.md +0 -0
  280. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/003-python-cli-rewrite/plan.md +0 -0
  281. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/003-python-cli-rewrite/quickstart.md +0 -0
  282. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/003-python-cli-rewrite/research.md +0 -0
  283. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/003-python-cli-rewrite/spec.md +0 -0
  284. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/003-python-cli-rewrite/tasks.md +0 -0
  285. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/004-proxmox-container-support/spec.md +0 -0
  286. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/checklists/requirements.md +0 -0
  287. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/contracts/cli-surface.md +0 -0
  288. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/data-model.md +0 -0
  289. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/plan.md +0 -0
  290. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/quickstart.md +0 -0
  291. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/research.md +0 -0
  292. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/spec.md +0 -0
  293. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/005-provider-snapshots/tasks.md +0 -0
  294. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/checklists/requirements.md +0 -0
  295. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/contracts/remo-host-protocol.md +0 -0
  296. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/contracts/rest-api.md +0 -0
  297. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/contracts/terminal-websocket.md +0 -0
  298. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/data-model.md +0 -0
  299. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/plan.md +0 -0
  300. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/quickstart.md +0 -0
  301. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/research.md +0 -0
  302. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/spec.md +0 -0
  303. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/specs/010-web-session-interface/tasks.md +0 -0
  304. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/__init__.py +0 -0
  305. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/__main__.py +0 -0
  306. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/__init__.py +0 -0
  307. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/cp.py +0 -0
  308. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/main.py +0 -0
  309. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/providers/__init__.py +0 -0
  310. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/providers/aws.py +0 -0
  311. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/providers/hetzner.py +0 -0
  312. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/providers/incus.py +0 -0
  313. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/providers/proxmox.py +0 -0
  314. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/cli/shell.py +0 -0
  315. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/__init__.py +0 -0
  316. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/ansible_runner.py +0 -0
  317. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/completion.py +0 -0
  318. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/config.py +0 -0
  319. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/known_hosts.py +0 -0
  320. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/output.py +0 -0
  321. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/picker.py +0 -0
  322. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/remo_host_client.py +0 -0
  323. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/rsync.py +0 -0
  324. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/snapshot.py +0 -0
  325. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/validation.py +0 -0
  326. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/core/version.py +0 -0
  327. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/models/__init__.py +0 -0
  328. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/models/capability.py +0 -0
  329. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/models/discovery.py +0 -0
  330. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/models/host.py +0 -0
  331. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/models/session_target.py +0 -0
  332. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/models/snapshot.py +0 -0
  333. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/providers/__init__.py +0 -0
  334. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/providers/aws.py +0 -0
  335. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/providers/hetzner.py +0 -0
  336. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/providers/incus.py +0 -0
  337. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/providers/proxmox.py +0 -0
  338. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/__init__.py +0 -0
  339. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/api/__init__.py +0 -0
  340. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/api/hosts.py +0 -0
  341. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/api/terminals.py +0 -0
  342. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/models.py +0 -0
  343. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/ssh_master.py +0 -0
  344. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/terminal_registry.py +0 -0
  345. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/src/remo_cli/web/tokens.py +0 -0
  346. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/__init__.py +0 -0
  347. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/ansible/__init__.py +0 -0
  348. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/ansible/test_remo_host_idempotency.py +0 -0
  349. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/conftest.py +0 -0
  350. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/e2e/fixtures.ts +0 -0
  351. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/e2e/ghostty-shell-io.spec.ts +0 -0
  352. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/e2e/ghostty-tui-compatibility.spec.ts +0 -0
  353. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/e2e/keyboard-routing.spec.ts +0 -0
  354. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/e2e/mobile.spec.ts +0 -0
  355. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/e2e/reconnect.spec.ts +0 -0
  356. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/e2e/workspace-layout.spec.ts +0 -0
  357. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/image/__init__.py +0 -0
  358. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/__init__.py +0 -0
  359. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/_nine_terminal_fixture.py +0 -0
  360. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/orbstack-cloud-init.yml +0 -0
  361. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/orbstack.sh +0 -0
  362. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/test_nine_terminals.py +0 -0
  363. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/test_nine_terminals_soak.py +0 -0
  364. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/test_remo_host_e2e.py +0 -0
  365. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/test_security_rejections.py +0 -0
  366. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/test_terminal_attach.py +0 -0
  367. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/integration/test_web_cli_parity.py +0 -0
  368. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/perf/__init__.py +0 -0
  369. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/perf/test_latency.py +0 -0
  370. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/__init__.py +0 -0
  371. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/__init__.py +0 -0
  372. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/providers/test_aws_snapshot.py +0 -0
  373. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/providers/test_hetzner_snapshot.py +0 -0
  374. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/providers/test_incus_snapshot.py +0 -0
  375. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/providers/test_proxmox_snapshot.py +0 -0
  376. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/test_cp.py +0 -0
  377. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/test_main.py +0 -0
  378. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/cli/test_shell.py +0 -0
  379. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/__init__.py +0 -0
  380. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_ansible_runner.py +0 -0
  381. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_config.py +0 -0
  382. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_known_hosts.py +0 -0
  383. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_output.py +0 -0
  384. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_picker.py +0 -0
  385. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_remo_host_client.py +0 -0
  386. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_rsync.py +0 -0
  387. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_snapshot.py +0 -0
  388. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_ssh.py +0 -0
  389. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_ssh_controlpath.py +0 -0
  390. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_validation.py +0 -0
  391. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/core/test_version.py +0 -0
  392. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/models/__init__.py +0 -0
  393. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/models/test_capability.py +0 -0
  394. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/models/test_discovery.py +0 -0
  395. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/models/test_session_target.py +0 -0
  396. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/providers/__init__.py +0 -0
  397. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/providers/test_aws_snapshot.py +0 -0
  398. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/providers/test_hetzner_snapshot.py +0 -0
  399. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/providers/test_incus_snapshot.py +0 -0
  400. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/providers/test_proxmox_devcontainer_runtime.py +0 -0
  401. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/providers/test_proxmox_snapshot.py +0 -0
  402. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/test_ansible_templates.py +0 -0
  403. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/test_host_model.py +0 -0
  404. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/__init__.py +0 -0
  405. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_backpressure.py +0 -0
  406. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_check.py +0 -0
  407. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_discovery.py +0 -0
  408. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_hosts_mapping.py +0 -0
  409. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_lazy_import.py +0 -0
  410. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_terminal_resize.py +0 -0
  411. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_terminals_api.py +0 -0
  412. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/tests/unit/web/test_tokens.py +0 -0
  413. {remo_cli-2.2.0rc1 → remo_cli-2.2.0rc2}/uv.lock +0 -0
@@ -16,7 +16,7 @@
16
16
  "ghcr.io/eitsupi/devcontainer-features/jq-likes:2": {},
17
17
  "ghcr.io/devcontainers-extra/features/starship:1": {},
18
18
  "ghcr.io/get2knowio/devcontainer-features/ai-clis:2": {
19
- "install": "claudeCode,specifyCli"
19
+ "install": "claudeCode,specifyCli,copilot,codex"
20
20
  },
21
21
  "ghcr.io/get2knowio/devcontainer-features/modern-cli-tools:2": {},
22
22
  "ghcr.io/get2knowio/devcontainer-features/python-tools:2": {
@@ -41,7 +41,7 @@
41
41
  "source=${localEnv:HOME}/.claude,target=/home/vscode/.claude,type=bind,consistency=cached",
42
42
  "source=${localEnv:HOME}/.aws,target=/home/vscode/.aws,type=bind,consistency=cached",
43
43
  "source=${localEnv:HOME}/.ssh,target=/home/vscode/.ssh,type=bind,consistency=cached",
44
- "source=${localWorkspaceFolder}/../site,target=/workspaces/site,type=bind,consistency=cached",
44
+ "source=${localWorkspaceFolder}/../site,target=/workspaces/site,type=bind,consistency=cached"
45
45
  ],
46
46
  "postCreateCommand": "python3 --version && node --version"
47
47
  }
@@ -0,0 +1,3 @@
1
+ {
2
+ "feature_directory": "specs/011-web-adopt"
3
+ }
@@ -13,6 +13,7 @@ See `.specify/memory/constitution.md` for project principles and non-negotiable
13
13
  - Flat file (`~/.config/remo/known_hosts`, colon-delimited) (003-python-cli-rewrite)
14
14
  - Cross-provider snapshot model (`models/snapshot.py`) + shared helpers in `core/snapshot.py` (name generator, validator, table formatter, destroy-time cleanup hook). No new runtime deps. (005-provider-snapshots)
15
15
  - FastAPI/Uvicorn + WebSockets (backend, optional `web` extra), TypeScript/Vite/React + ghostty-web (frontend), Bash (`remo-host` host command templated by Ansible) (010-web-session-interface)
16
+ - Stdlib `urllib.request` CLI setup client + token-gated `/api/v1/setup/*` FastAPI surface; service state in flat files under the writable `REMO_HOME` volume (`web-identity/` keypair + service known_hosts, `~/.config/remo/web-service.json` saved credentials) (011-web-adopt)
16
17
 
17
18
  - Ansible 2.14+ / YAML + `ansible.builtin`, `community.general` (for zypper module) (001-bootstrap-incus-host)
18
19
 
@@ -27,7 +28,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
27
28
  │ ├── shell.py # remo shell
28
29
  │ ├── cp.py # remo cp
29
30
  │ ├── init_cmd.py # remo init
30
- │ ├── web.py # remo web {serve,check} — lazy-imports remo_cli.web.* (NFR-008)
31
+ │ ├── web.py # remo web {serve,check,adopt,push} — serve/check lazy-import remo_cli.web.* (NFR-008); adopt/push use core/web_adopt only
31
32
  │ └── providers/ # Provider CLI groups
32
33
  │ ├── incus.py # remo incus {create,destroy,update,list,sync,bootstrap}
33
34
  │ ├── hetzner.py # remo hetzner {create,destroy,update,list,sync}
@@ -45,6 +46,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
45
46
  │ ├── known_hosts.py # Flat-file host registry
46
47
  │ ├── ssh.py # build_ssh_base_cmd(), SSH options, terminal reset, timezone
47
48
  │ ├── remo_host_client.py # Versioned remo-host protocol client (shared by CLI + web)
49
+ │ ├── web_adopt.py # Workstation-side adoption/push engine (stdlib HTTP, keyscan trust verify, authorized_keys mgmt, --via tunnel)
48
50
  │ ├── ansible_runner.py # Ansible playbook subprocess
49
51
  │ ├── picker.py # InquirerPy fuzzy picker
50
52
  │ ├── rsync.py # File transfer
@@ -52,7 +54,8 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
52
54
  │ └── init.py # remo init logic
53
55
  ├── web/ # remo-web service — FastAPI; optional `web` extra, lazily imported
54
56
  │ ├── app.py # FastAPI factory: routers, Host/Origin+CSP middleware, serves built SPA
55
- │ ├── config.py # WebSettings (REMO_WEB_* env vars, see docs/web-session-interface.md)
57
+ │ ├── config.py # WebSettings (REMO_WEB_* env vars incl. api_token, see docs/web-session-interface.md)
58
+ │ ├── state.py # ConfigurationState detection (unconfigured/adopted/mount_configured/broken) + service identity generation
56
59
  │ ├── discovery.py # Concurrent per-instance discovery via remo-host + SSH
57
60
  │ ├── ssh_master.py # Per-instance SSH ControlMaster lifecycle
58
61
  │ ├── terminal.py # PTY + `ssh -tt … remo-host sessions attach`, resize/backpressure
@@ -64,6 +67,7 @@ src/remo_cli/ # Python CLI package (src layout, hatchling build)
64
67
  │ ├── models.py # Service-only entities: TerminalAttachment, WsToken, SshMaster
65
68
  │ └── api/
66
69
  │ ├── hosts.py # GET /api/v1/hosts, /sessions, POST /discovery/refresh
70
+ │ ├── setup.py # Token-gated /api/v1/setup/{status,identity,registry,verify} (011-web-adopt)
67
71
  │ └── terminals.py # POST/GET/DELETE /api/v1/terminals, WS /api/v1/terminals/{id}
68
72
  └── models/
69
73
  ├── host.py # KnownHost dataclass
@@ -182,10 +186,9 @@ Provider SDKs (boto3, hcloud) are lazy-imported with clear error messages if mis
182
186
  - Ansible 2.14+ / YAML: Follow standard conventions plus Constitution principles
183
187
 
184
188
  ## Recent Changes
189
+ - 011-web-adopt: Added CLI-to-web adoption — unconfigured boot with service-scoped ed25519 identity, token-gated `/api/v1/setup/*` (REMO_WEB_API_TOKEN, fail-closed), `remo web adopt`/`remo web push` (registry mirror + workstation-verified host keys + idempotent `remo-web@<id>` authorized_keys entries), AwaitingAdoption SPA page.
185
190
  - 010-web-session-interface: Added remo-web Docker service (FastAPI + React/ghostty-web) brokering browser terminal sessions across all Remo-managed instances via a new remo-host SSH command; web extra + remo web {serve,check} CLI group.
186
191
  - 005-provider-snapshots: Added cross-provider snapshot CLI (`remo <P> snapshot {create,list,restore,delete}`) + destroy-time cleanup hook across Incus / Proxmox / AWS / Hetzner.
187
- - 003-python-cli-rewrite: Added Python 3.11+ + Click (CLI framework), InquirerPy (interactive picker), boto3 (AWS, optional), hcloud (Hetzner, optional)
188
- - 002-incus-container-support: Added Ansible 2.14+ / YAML + `ansible.builtin`, `community.general` (existing), Incus CLI (local)
189
192
 
190
193
 
191
194
  <!-- MANUAL ADDITIONS START -->
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: remo-cli
3
- Version: 2.2.0rc1
3
+ Version: 2.2.0rc2
4
4
  Summary: Remote development environment CLI
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -357,11 +357,19 @@ uv run remo web serve --host 127.0.0.1 --port 8080 # local dev
357
357
  ```
358
358
 
359
359
  For a home-lab install, use Docker Compose — see [`docker/compose.example.yml`](docker/compose.example.yml)
360
- for a ready-to-adapt file (read-only registry + SSH material mounts, tmpfs runtime dir, healthcheck,
361
- non-root/read-only hardening).
362
-
363
- Full architecture, security model, Compose walkthrough, credentials/SSM setup, discovery states,
364
- terminal limits, troubleshooting, and upgrade notes: **[docs/web-session-interface.md](docs/web-session-interface.md)**.
360
+ for a ready-to-adapt file covering both deployment modes (tmpfs runtime dir, healthcheck,
361
+ non-root/read-only hardening in either case):
362
+
363
+ - **Bind-mount mode**: mount your existing registry and SSH key read-only — the container runs with
364
+ your identity, on the same box as your config.
365
+ - **Adopted mode**: mount nothing. The container generates its own SSH identity in a writable state
366
+ volume, and a single `remo web adopt` from your workstation pushes your registry and authorizes
367
+ that identity on every instance — your personal private key never leaves the workstation
368
+ (`remo web push` re-syncs later changes).
369
+
370
+ Full architecture, security model, Compose walkthrough, adoption workflow, credentials/SSM setup,
371
+ discovery states, terminal limits, troubleshooting, and upgrade notes:
372
+ **[docs/web-session-interface.md](docs/web-session-interface.md)**.
365
373
 
366
374
  ---
367
375
 
@@ -331,11 +331,19 @@ uv run remo web serve --host 127.0.0.1 --port 8080 # local dev
331
331
  ```
332
332
 
333
333
  For a home-lab install, use Docker Compose — see [`docker/compose.example.yml`](docker/compose.example.yml)
334
- for a ready-to-adapt file (read-only registry + SSH material mounts, tmpfs runtime dir, healthcheck,
335
- non-root/read-only hardening).
336
-
337
- Full architecture, security model, Compose walkthrough, credentials/SSM setup, discovery states,
338
- terminal limits, troubleshooting, and upgrade notes: **[docs/web-session-interface.md](docs/web-session-interface.md)**.
334
+ for a ready-to-adapt file covering both deployment modes (tmpfs runtime dir, healthcheck,
335
+ non-root/read-only hardening in either case):
336
+
337
+ - **Bind-mount mode**: mount your existing registry and SSH key read-only — the container runs with
338
+ your identity, on the same box as your config.
339
+ - **Adopted mode**: mount nothing. The container generates its own SSH identity in a writable state
340
+ volume, and a single `remo web adopt` from your workstation pushes your registry and authorizes
341
+ that identity on every instance — your personal private key never leaves the workstation
342
+ (`remo web push` re-syncs later changes).
343
+
344
+ Full architecture, security model, Compose walkthrough, adoption workflow, credentials/SSM setup,
345
+ discovery states, terminal limits, troubleshooting, and upgrade notes:
346
+ **[docs/web-session-interface.md](docs/web-session-interface.md)**.
339
347
 
340
348
  ---
341
349
 
@@ -117,3 +117,100 @@ services:
117
117
  retries: 3
118
118
  start_period: 10s
119
119
  restart: unless-stopped
120
+
121
+ # ---------------------------------------------------------------------------
122
+ # Adopted mode (011-web-adopt) — an ALTERNATIVE to `remo-web` above; run one
123
+ # or the other, not both (they publish the same host port).
124
+ #
125
+ # When to use which:
126
+ #
127
+ # - `remo-web` (above, bind-mount mode): you are happy to mount your
128
+ # existing registry and SSH material read-only into the container. The
129
+ # service boots fully configured with YOUR key; nothing else to do.
130
+ # Upgrading to this release changes nothing about that mode (SC-005).
131
+ #
132
+ # - `remo-web-adopted` (below): nothing from your workstation is mounted.
133
+ # The service boots UNCONFIGURED with an empty named state volume,
134
+ # generates its own service-scoped SSH identity there on first start
135
+ # (under web-identity/, comment `remo-web@<deployment-id>`), and waits
136
+ # in a stable "awaiting adoption" state (GET /api/v1/ready -> 200
137
+ # `{"status": "unconfigured"}`). Complete setup from a workstation with
138
+ # a working remo CLI:
139
+ #
140
+ # remo web adopt http://<docker-host>:8080
141
+ #
142
+ # which pushes your registry + instance host keys and authorizes the
143
+ # service's OWN public key on each instance — your personal private key
144
+ # never leaves the workstation. Later registry changes are re-pushed
145
+ # with `remo web push`.
146
+ #
147
+ # This service carries `profiles: ["adopted"]` so a plain `docker compose
148
+ # up` still starts only the bind-mount service above. Start this one with:
149
+ #
150
+ # docker compose --profile adopted up -d
151
+ remo-web-adopted:
152
+ profiles: ["adopted"]
153
+ # Same image (and the same optional `build:` override) as `remo-web`
154
+ # above — the mode is chosen purely by what is mounted, not by the image.
155
+ image: ghcr.io/get2knowio/remo-web:latest
156
+ ports:
157
+ # Adoption traffic (the token-gated /api/v1/setup/* calls made by
158
+ # `remo web adopt`) arrives over this same port. Loopback-only means
159
+ # the workstation running the CLI must be the Docker host itself —
160
+ # otherwise bind a LAN IP here deliberately, or keep loopback and run
161
+ # `remo web adopt --via <docker-host>` to tunnel over SSH.
162
+ - "127.0.0.1:8080:8080"
163
+ environment:
164
+ # REQUIRED for adopted mode: while this is unset/empty the setup API
165
+ # does not exist at all (every /api/v1/setup/* request gets a plain
166
+ # 404), so adoption is impossible. Generate a strong random value,
167
+ # e.g.:
168
+ #
169
+ # openssl rand -hex 24
170
+ #
171
+ # and pass the same value to the CLI via $REMO_API_TOKEN (or the
172
+ # interactive prompt) when running `remo web adopt`.
173
+ - "REMO_WEB_API_TOKEN=replace-me--generate-with--openssl-rand-hex-24"
174
+ # The REMO_WEB_ALLOWED_HOSTS / REMO_WEB_ALLOWED_ORIGINS notes on the
175
+ # service above apply here unchanged.
176
+ volumes:
177
+ # A writable named state volume at REMO_HOME — the ONLY volume in this
178
+ # mode (no registry mount, no ~/.ssh mounts; presence of those is what
179
+ # puts the service in mount-configured mode instead). It holds the
180
+ # pushed registry, per-instance host keys, and the service identity
181
+ # keypair. Deleting the volume resets the service to unconfigured with
182
+ # a NEW identity on next boot; it revokes nothing on the instances —
183
+ # remove the old `remo-web@<deployment-id>` authorized_keys line there.
184
+ - "remo-web-state:/home/remo/.config/remo"
185
+ # Identical hardening to the bind-mount service: adopted mode only moves
186
+ # WHERE configuration comes from, never loosens the runtime posture.
187
+ #
188
+ # The tmpfs mode is pinned because an option-less tmpfs mount is
189
+ # remounted root-owned 0755 (unwritable to uid 1000) by a container
190
+ # *restart* — `docker compose restart`, or the restart policy reviving
191
+ # the process — which would fail the startup runtime-dir check on every
192
+ # boot after the first. `rw,mode=1777` is exactly what Docker mounts on
193
+ # first boot anyway; pinning it just makes restarts behave the same.
194
+ tmpfs:
195
+ - "/run/remo-ssh:rw,mode=1777"
196
+ read_only: true
197
+ user: "1000:1000"
198
+ security_opt:
199
+ - "no-new-privileges:true"
200
+ cap_drop:
201
+ - "ALL"
202
+ healthcheck:
203
+ # /api/v1/ready answers 200 for BOTH `ready` and `unconfigured` — a
204
+ # container awaiting adoption is healthy and must not crash-loop or
205
+ # flap the healthcheck while it waits (SC-006).
206
+ test: ["CMD", "curl", "-fsS", "http://127.0.0.1:8080/api/v1/ready"]
207
+ interval: 30s
208
+ timeout: 5s
209
+ retries: 3
210
+ start_period: 10s
211
+ restart: unless-stopped
212
+
213
+ volumes:
214
+ # Adopted-mode state (see `remo-web-adopted`). Created on first
215
+ # `--profile adopted` start; harmless if you only use bind-mount mode.
216
+ remo-web-state:
@@ -20,6 +20,14 @@
20
20
  # Full per-instance diagnostics remain available via `remo web check` (no
21
21
  # flag), and readiness is (correctly) config-only via GET /api/v1/ready.
22
22
  #
23
+ # 011-web-adopt (SC-006): *unconfigured* is a PASSING state for this gate.
24
+ # A fresh writable state volume with no registry/key material yet makes
25
+ # `remo web check` report "awaiting adoption — run `remo web adopt`" and
26
+ # exit 0, so an adopted-mode container boots cleanly (no crash loop under
27
+ # `restart: unless-stopped`) while it waits for adoption. Only genuinely
28
+ # broken configuration (mounted artifacts present but unusable, missing
29
+ # runtime prerequisites) still aborts here.
30
+ #
23
31
  # `exec` replaces this script's process (PID 1) with `remo web serve` so it
24
32
  # receives signals (SIGTERM) directly, which graceful shutdown depends on.
25
33