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.
- remo_cli-4.3.5/.github/codeql/codeql-config.yml +21 -0
- remo_cli-4.3.5/.github/dependabot.yml +75 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/ci.yml +20 -4
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/codeql.yml +1 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/release.yml +2 -2
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/smoke-test-cleanup.yml +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/smoke-test.yml +1 -1
- remo_cli-4.3.5/.release-please-manifest.json +3 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/AGENTS.md +18 -2
- {remo_cli-4.3.3 → remo_cli-4.3.5}/CHANGELOG.md +17 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/CLAUDE.md +19 -3
- {remo_cli-4.3.3 → remo_cli-4.3.5}/CONTRIBUTING.md +20 -8
- {remo_cli-4.3.3 → remo_cli-4.3.5}/PKG-INFO +70 -17
- {remo_cli-4.3.3 → remo_cli-4.3.5}/README.md +68 -15
- remo_cli-4.3.5/ansible/group_vars/all.yml +50 -0
- remo_cli-4.3.5/ansible/roles/nested_docker/defaults/main.yml +31 -0
- remo_cli-4.3.5/ansible/roles/nested_docker/tasks/main.yml +260 -0
- remo_cli-4.3.5/ansible/roles/nested_docker/templates/devcontainer-shim.sh.j2 +149 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/tasks/configure_dev_tools.yml +12 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docker/Dockerfile +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/aws.md +1 -1
- remo_cli-4.3.5/docs/examples/orbstack-cloud-init-tailscale.yaml +211 -0
- remo_cli-4.3.5/docs/examples/orbstack-cloud-init.yaml +185 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/feature-history.md +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/hetzner.md +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/incus.md +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/maintaining-generated-types.md +12 -0
- remo_cli-4.3.5/docs/nested-overlayfs.md +201 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/proxmox.md +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/web-session-interface.md +68 -11
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/package-lock.json +3 -3
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/package.json +5 -1
- remo_cli-4.3.5/frontend/playwright.geometry.config.ts +71 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/openapi.json +31 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/schema.d.ts +70 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AwaitingAdoption.css +7 -0
- remo_cli-4.3.5/frontend/src/components/AwaitingAdoption.test.tsx +107 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AwaitingAdoption.tsx +47 -20
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/PairToSync.css +10 -0
- remo_cli-4.3.5/frontend/src/components/PairToSync.test.tsx +119 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/PairToSync.tsx +41 -22
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TerminalCard.test.tsx +78 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TerminalCard.tsx +37 -41
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/WorkspacePane.test.tsx +3 -0
- remo_cli-4.3.5/frontend/src/terminal/TerminalConnection.test.ts +280 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/TerminalConnection.ts +62 -1
- remo_cli-4.3.5/frontend/src/terminal/fitLoop.ts +77 -0
- remo_cli-4.3.5/frontend/tests/geometry/global.d.ts +26 -0
- remo_cli-4.3.5/frontend/tests/geometry/harness/index.html +27 -0
- remo_cli-4.3.5/frontend/tests/geometry/harness/main.tsx +189 -0
- remo_cli-4.3.5/frontend/tests/geometry/terminal-fit.spec.ts +269 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tsconfig.json +9 -2
- {remo_cli-4.3.3 → remo_cli-4.3.5}/install.sh +3 -3
- {remo_cli-4.3.3 → remo_cli-4.3.5}/pyproject.toml +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/contracts/pairing-api.md +5 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/contracts/setup-api.md +16 -7
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/data-model.md +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/spec.md +5 -3
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/tasks.md +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/shell.py +67 -23
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/web_adopt.py +177 -22
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/added.py +2 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/setup.py +65 -8
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/image/test_docker_image.py +2 -2
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_web_adopt_e2e.py +10 -9
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_shell.py +43 -14
- remo_cli-4.3.5/tests/unit/cli/test_shell_added.py +149 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_web_adopt_cmd.py +3 -3
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_code.py +6 -2
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_trust.py +261 -2
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_push_self_heal.py +184 -0
- remo_cli-4.3.5/tests/unit/test_dependabot_config.py +112 -0
- remo_cli-4.3.5/tests/unit/test_devcontainer_shim.py +485 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_docs_examples.py +54 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_setup_api.py +1 -1
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_setup_dormancy.py +53 -11
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_terminal_resize.py +66 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/uv.lock +1 -1
- remo_cli-4.3.3/.github/dependabot.yml +0 -42
- remo_cli-4.3.3/.release-please-manifest.json +0 -3
- remo_cli-4.3.3/ansible/group_vars/all.yml +0 -29
- remo_cli-4.3.3/docs/examples/orbstack-cloud-init-tailscale.yaml +0 -182
- remo_cli-4.3.3/docs/examples/orbstack-cloud-init.yaml +0 -120
- remo_cli-4.3.3/docs/install.sh +0 -200
- remo_cli-4.3.3/frontend/src/terminal/TerminalConnection.test.ts +0 -147
- remo_cli-4.3.3/tests/unit/cli/test_shell_added.py +0 -76
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/release/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-analyze/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-checklist/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-clarify/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-constitution/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-converge/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-commit/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-feature/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-initialize/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-remote/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-git-validate/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-implement/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-plan/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-specify/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-tasks/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.claude/skills/speckit-taskstoissues/SKILL.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.devcontainer/devcontainer.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.dockerignore +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/CODEOWNERS +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/dependency-review.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/dev-build.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/provision.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/release-please.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.github/workflows/teardown.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.gitignore +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.maverick/checkpoints/feature/implementation_complete.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.maverick/checkpoints/feature/phase_${{ index }}_complete.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.maverick/checkpoints/feature/validation_complete.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/.registry +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/README.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.commit.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.feature.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.initialize.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.remote.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/commands/speckit.git.validate.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/config-template.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/extension.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/git-config.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/create-new-feature.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/git-common.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/create-new-feature.ps1 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/extensions.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/feature.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/init-options.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/integration.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/integrations/claude.manifest.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/integrations/speckit.manifest.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/memory/constitution.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/check-prerequisites.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/common.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/create-new-feature.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/setup-plan.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/setup-tasks.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/scripts/bash/update-agent-context.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/agent-file-template.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/checklist-template.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/constitution-template.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/plan-template.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/spec-template.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/templates/tasks-template.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/workflows/speckit/workflow.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/.specify/workflows/workflow-registry.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/Dockerfile +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/LICENSE +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/SECURITY.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/.ansible-lint +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/README.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/ansible.cfg +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_configure.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_resize.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_site.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/aws_teardown.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/group_vars/incus_containers.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/group_vars/proxmox_containers.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_configure.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_provision.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_resize.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_site.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/hetzner_teardown.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_bootstrap.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_configure.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_provision.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_resize.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_site.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/incus_teardown.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/inventory/hosts.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/inventory/incus_containers.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_bootstrap.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_configure.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_provision.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_resize.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_site.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/proxmox_teardown.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/requirements.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/ebs.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/ec2.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/patch_manager.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/preflight.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/aws_server/tasks/security_group.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/deacon/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/deacon/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/devcontainers/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/docker/handlers/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/docker/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/fzf/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/github_cli/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/hetzner_server/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/hetzner_server/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_bootstrap/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_bootstrap/handlers/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_bootstrap/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/handlers/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/meta/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container/tasks/preflight.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container_teardown/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container_teardown/meta/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/incus_container_teardown/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/nodejs/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/nodejs/files/nodesource-repo.gpg.key +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/nodejs/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_bootstrap/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_bootstrap/meta/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_bootstrap/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/handlers/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/meta/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container/tasks/preflight.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container_teardown/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container_teardown/meta/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/proxmox_container_teardown/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/devshell.sh.j2 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/project-launch.sh.j2 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/project-menu.sh.j2 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/user_setup/templates/remo-host.sh.j2 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/defaults/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/tasks/main.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/templates/config.kdl.j2 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/roles/zellij/templates/layouts/minimal.kdl.j2 +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/ssh_configure.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/ansible/tasks/repair_apt_sources.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docker/compose.example.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docker/entrypoint.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/maintaining-claude-md.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/providers.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/remo-web-speckit-input.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/docs/remo-web.html +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/index.html +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/playwright.config.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/scripts/check-types-fresh.mjs +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/scripts/generate-frame-types.mjs +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/scripts/generate-schema-types.mjs +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/client.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/client.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/README.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/terminal-frames.d.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated/terminal-frames.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/api/generated.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AppRoot.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AppShell.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/AppShell.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/OfflineOverlay.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/OfflineOverlay.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SessionRail.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SessionRail.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SettingsPage.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/SettingsPage.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/ShortcutsModal.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/ShortcutsModal.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TerminalCard.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TopBar.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/TopBar.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/WorkspacePane.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/WorkspacePane.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/masterLayout.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/masterLayout.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/providerMeta.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/providerMeta.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/railModel.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/components/railModel.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/lib/clipboard.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/lib/fullscreen.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/main.tsx +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/discovery.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/discovery.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/fonts.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/health.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/health.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/latency.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/latency.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/settings.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/settings.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/useConsoleKeyboard.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/workspace.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/state/workspace.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/.gitkeep +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/RendererAdapter.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/XtermRenderer.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/defaultRenderer.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/keymap.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/terminal/keymap.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/test/setup.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/fonts.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/terminalThemes.test.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/terminalThemes.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/src/theme/tokens.css +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/fixtures.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/keyboard-routing.spec.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/mobile.spec.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/reconnect.spec.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/terminal-shell-io.spec.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/terminal-tui-compatibility.spec.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/tests/e2e/workspace-layout.spec.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/frontend/vite.config.ts +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/maverick.yaml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/project-menu.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/release-please-config.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/remo +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/remo.svg +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/run.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/scripts/export_openapi.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/scripts/palette-check.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/scripts/setup-aws-oidc.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/checklists/validation.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/contracts/playbook-interface.yaml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/contracts/role-interface.yaml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/001-bootstrap-incus-host/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/contracts/playbook-interface.yaml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/contracts/role-interface.yaml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/002-incus-container-support/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/003-python-cli-rewrite/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/004-proxmox-container-support/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/contracts/cli-surface.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/005-provider-snapshots/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/contracts/remo-host-protocol.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/contracts/rest-api.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/contracts/terminal-websocket.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/010-web-session-interface/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/contracts/cli-web-adopt.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/contracts/setup-api.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/quickstart-results.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/011-web-adopt/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/contracts/cli-web-adopt.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/012-web-adopt-pairing/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/contracts/cli-sync.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/contracts/marker-commands.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/013-managed-instance-tags/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/contracts/add-command.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/contracts/remove-command.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/014-register-ssh-host/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/contracts/mirror-payload-v2.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/contracts/registry-accessor-api.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/contracts/registry-file-v2.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/015-registry-v2/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/contracts/cli-sync.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/contracts/provider-probe.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/016-sync-reconcile/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/cli-web-push.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/cli-web-status.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/revocation.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/contracts/setup-status-marker.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/017-web-adopt-simplify/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/baseline-notes.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/cli-surface.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/errors.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/lifecycle-templates.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/provider-protocol.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/contracts/sync-merge.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/018-provider-abstraction/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/contracts/cli-surface-delta.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/contracts/docs-structure-check.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/019-hygiene-deps-docs/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/checklists/requirements.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/contracts/drift-checks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/contracts/terminal-frames-v1.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/020-openapi-type-generation/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/contracts/cli-surface.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/contracts/descriptor-schema.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/data-model.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/plan.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/quickstart.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/research.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/spec.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/specs/021-cli-plane-separation/tasks.md +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/__main__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/added.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/cp.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/main.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/providers/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/providers/factory.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/cli/web.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/ansible_runner.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/completion.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/config.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/errors.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/known_hosts.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/lifecycle.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/output.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/picker.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/provider_protocol.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/provider_registry.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/reconcile.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/registry.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/remo_host_client.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/rsync.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/ssh.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/validation.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/version.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/core/web_drift.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/capability.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/discovery.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/host.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/session_target.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/models/snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/aws.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/aws_descriptor.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/builtin.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/hetzner.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/hetzner_descriptor.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/incus.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/incus_descriptor.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/proxmox.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/providers/proxmox_descriptor.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/hosts.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/pairing.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/api/terminals.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/app.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/check.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/config.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/discovery.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/frames.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/health.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/logging_config.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/models.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/operator_auth.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/pairing.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/ssh_master.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/state.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/terminal.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/terminal_registry.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/src/remo_cli/web/tokens.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_apt_sources_repair.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_authorized_keys_bootstrap.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_remo_host_idempotency.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_ssh_configure_connection.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/ansible/test_user_setup_docker_group.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/conftest.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/image/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/_nine_terminal_fixture.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/fish_completion.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/orbstack-cloud-init.yml +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/orbstack.sh +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_nine_terminals.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_nine_terminals_soak.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_registry_concurrency.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_remo_host_e2e.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_security_rejections.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_setup_payload_versions.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_sync_reconcile.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_terminal_attach.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/integration/test_web_cli_parity.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/perf/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/perf/test_latency.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/perf/test_registry_perf.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_aws_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_hetzner_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_incus_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_incus_sync_all.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_proxmox_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/providers/test_proxmox_sync_all.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/surface_baseline.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_add_cmd.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_cli_uniformity.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_configure_cmd.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_cp.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_main.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_remove_cmd.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_startup_imports.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/cli/test_surface_preservation.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ansible_runner.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_completion.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_config.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_errors.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_known_hosts.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_lifecycle.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_migration_tagging_notice.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_output.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_picker.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_provider_registry.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_reconcile.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_registry_format.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_registry_locking.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_registry_migration.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_remo_host_client.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_rsync.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh_added.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh_controlpath.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_ssh_identity_opts.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_validation.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_version.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_authorize.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_adopt_payload.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_drift.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/core/test_web_push.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/test_capability.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/test_discovery.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/models/test_session_target.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/fake_provider.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_add.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_configure.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_provider_guard.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_update_remove.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_added_verify.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_provider_protocol.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_sync.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_aws_upgrade_resize.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_entry_adapters.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_http.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_label.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_resize.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_hetzner_sync.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_host_user_consistency.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_entry_adapters.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_marker.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_resize.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_incus_sync.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_missing_sdk.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_provider_conformance.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_provider_registry_entries.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_devcontainer_runtime.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_marker.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_provider_protocol.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_resize.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_snapshot.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/providers/test_proxmox_sync.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_ansible_templates.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_architecture.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_docs_structure.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_host_model.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_host_ssh_type.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_lockfile_version.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_schema_drift.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/test_workflow_action_pins.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/__init__.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/_pairing_support.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/conftest.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/fixtures/hosts_response.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/fixtures/sessions_response.json +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_backpressure.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_check.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_csp.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_discovery.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_discovery_refresh_force.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_frames.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_health_states.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_hosts_mapping.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_lazy_import.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_log_redaction.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_mint_gating.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_operator_auth.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_pairing.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_pairing_origin.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_payload_equivalence.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_registry_readonly.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_service_identity_selection.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_setup_auth.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_state.py +0 -0
- {remo_cli-4.3.3 → remo_cli-4.3.5}/tests/unit/web/test_terminals_api.py +0 -0
- {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),
|
|
147
|
-
#
|
|
148
|
-
#
|
|
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: "
|
|
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@
|
|
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@
|
|
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@
|
|
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@
|
|
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 }}
|
|
@@ -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 —
|
|
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 —
|
|
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 #
|
|
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://
|
|
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://
|
|
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
|
-
|
|
183
|
+
`install.sh` at the repo root is the one copy, served straight off `main`:
|
|
184
184
|
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
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
|
|
210
|
-
curl -fsSL https://
|
|
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.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: remo-cli
|
|
3
|
-
Version: 4.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
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
`
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
on
|
|
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
|