chore: distribution-readiness review — plan + immediate fixes
Some checks failed
ci / mutation test (broker) (push) Has been skipped
ci / test-health gate (push) Successful in 16s
ci / rust debug (push) Successful in 1m58s
ci / rust release (push) Successful in 2m5s
ci / python (push) Has been cancelled

External-review reading of the repo asked "ready for broad distribution?"
The verdict was "strong internal alpha/beta, not yet ready for public /
company-wide release" with concrete action items spanning install /
packaging, platform reliability, security, and remaining performance
work. Distill the actionable themes into a planning doc; land the two
bits that can ship right now.

planning/REVIEW_v0_6_4_DISTRIBUTION_PLAN.md (new)
- Numbered work items with [done] / [plan] / [needs-input] status,
  acceptance criteria, and cross-links to existing open issues
  (#32 large-file streaming, etc).
- Captures: command palette tier split, default-settings safe profile,
  stable vs dev release channel, macOS/Windows smoke CI, platform code
  signing, remote-install consent flow.

README + ssh_file_transport diagnostic-matrix [done]
- README claimed `session_helper` was downloaded directly by the remote
  via curl/wget. The actual implementation has been "editor-cache
  download → SSH push to remote" since v0.5.x; rust/local_bridge tests
  explicitly assert the remote provisioning command does not contain
  curl/wget. Update README + the H6_remote_download diagnostic-matrix
  hypothesis text to match the implementation.

sessions_show_dev_commands toggle [done]
- New setting (default false). Gates dev / debugging palette commands
  behind a maintainer flag so non-maintainer users see a tighter
  command surface. First gated command:
  `Sessions: Preview Remote Agent Payload` (reads arbitrary remote
  command stdout, renders JSON; useful when debugging the agent
  envelope round-trip, distracting clutter otherwise).
- 3 new tests cover the three visibility paths (default, flag-on,
  no-load_settings).

NOTE: The original review.md was lost mid-session (rm'd in error). This
plan is reconstructed from the partial content I had retained. If
additional review themes were in the original, append under the
"Open questions" section of the plan rather than starting a new doc.

1477 sublime tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 16:33:18 +09:00
parent 779387938c
commit 280d10552c
6 changed files with 334 additions and 10 deletions

View File

@@ -93,10 +93,12 @@ Example manifest:
**Current product policy (local vs remote):**
- **Remote host:** **Linux only.** The remote `session_helper` is still resolved
the same way: the **remote** machine downloads a pre-built binary from the
Gitea generic registry (`curl` / `wget`), keyed by Linux platform tag and
`rust/` revision. No remote `cargo build`.
- **Remote host:** **Linux only.** The remote `session_helper` is fetched by the
**editor** (not the remote): `local_bridge` downloads the matching binary from
the Gitea generic registry into the editor cache, then pushes it to the remote
over the existing SSH session. No `curl` / `wget` runs on the remote, and no
remote `cargo build`. Binary is keyed by Linux platform tag + workspace
semver from `rust/Cargo.toml`.
- **Local machine (editor side):** **Linux, macOS, and Windows** are supported for
running Sublime + this package. For day-to-day development, treat **`local_bridge`
as built on that machine** (`cargo build -p local_bridge`, see *Development*).
@@ -114,11 +116,13 @@ Current behavior:
session. Python sends NDJSON request envelopes and receives async responses via
a background reader thread. Each request gets a unique monotonic `envelope_id`
to prevent response mis-routing under concurrency.
- **Download-only helper resolution:** `session_helper` is downloaded directly by
the remote machine from the Gitea generic registry (no `cargo build` fallback,
no local download). The binary is identified by git revision + platform tag and
cached at `$HOME/.cache/sessions/helpers/<revision>/session_helper`. If the
download fails, the connection fails explicitly.
- **Editor-cache helper resolution:** `session_helper` is downloaded by the
editor host (`local_bridge`) from the Gitea generic registry into the editor
cache, then pushed to the remote over the existing SSH session — `curl` /
`wget` never run on the remote. Identified by workspace semver + Linux
platform tag, the remote-side cache lives at
`$HOME/.cache/sessions/helpers/<revision>/session_helper`. If the editor-side
download fails, the connection fails explicitly (no `cargo build` fallback).
- **Required handshake fields:** `Handshake.remote_home` and `Handshake.arch` are
required (no `Option`, no fallback). The bridge merges helper ensure + launch
into a single SSH command to avoid double authentication.

View File

@@ -0,0 +1,246 @@
# Review-driven distribution-readiness plan (v0.6.4 → v0.7+)
External-review reading of the repo asked: "ready for broad distribution
yet?" Verdict was: **strong internal alpha/beta**, **not yet ready** for
company-wide or public release. Reasons cluster into install/packaging,
platform reliability, feature surface, security/EDR, and remaining
performance scale items.
This plan distills the actionable themes into work items, splits them
into "in this batch" vs "deferred", and records acceptance criteria so
each item can be picked up later without re-reading the source review.
> The original review document was lost mid-session (rm'd in error). Items
> here are reconstructed from the partial review I had retained. If
> additional themes were in the original review, append them here under
> the right section rather than starting a new doc.
## Status legend
- `[done @ <commit>]` — landed in this batch, commit ref noted.
- `[plan]` — captured here; pick up later.
- `[needs-input]` — needs maintainer decision before scoping.
---
## Batch landing now (v0.6.5)
### 1. README ↔ implementation drift on `session_helper` resolution `[done]`
**Issue:** README (lines ~96-99 and ~117-121) says the remote machine
downloads `session_helper` directly from the Gitea generic registry via
`curl`/`wget`. The actual implementation since v0.5.x downloads to the
**editor cache** (`_ensure_session_helper_in_editor_cache`) then pushes
via SSH (`_needs_remote_session_helper_push` /
`_remote_session_helper_push_check_script`). Rust tests assert the
remote provisioning command does NOT contain `curl` / `wget`
(`local_bridge/src/lib.rs:1297-1298`). Settings comment matches the
real flow; README does not.
**Acceptance:** README describes the editor-cache + SSH-push flow; the
diagnostic-matrix `H6_remote_download` hypothesis text is updated to
reflect "editor download → SSH push" instead of "remote curl/wget".
### 2. Hide developer-only `Preview Remote Agent Payload` from main palette `[done]`
**Issue:** Review flagged the 27-command palette as too broad for
non-power users, and singled out `Sessions: Preview Remote Agent
Payload` as developer-flavored — it dumps the agent invocation argv
+ env into a scratch view, useful for debugging, distracting in the
main palette.
**Acceptance:** `is_visible` returns `False` by default. New setting
`sessions_show_dev_commands` (default `false`) flips it back on for
maintainers. Other palette commands unaffected.
---
## Deferred — architecture / packaging tracks
### 3. Command palette split: core / advanced / experimental `[plan]`
**Theme:** 27 commands at the top level mixes "Connect Remote
Workspace" (core flow) with "Preview Remote Agent Payload" (debug),
"Diagnose LSP Workspace" (debug), "Register Jupyter Kernel for Active
Python" (advanced flow). Power users like the breadth; broader users
read it as "the product center is unclear".
**Proposal:** Three tiers, gated by settings:
- **Core** (always visible): Connect, Open Recent, Open Remote
Folder, Open Remote Tree, Open Remote File, Reconnect, Settings,
Open Remote Terminal, Select Python Interpreter, New Agent Session,
Show Agent Switcher.
- **Advanced** (visible when `sessions_show_advanced_commands: true`,
default `true` for now, default `false` for v0.7 broad release):
Refresh Remote Workspace, Install/Remove/Status Remote Extension,
Open/Stop Remote Jupyter, Setup Remote Python Debugging, Register
Jupyter Kernel, Expand Deferred Directory, Kill Agent Session,
New Remote Terminal Pane, Kill Remote Terminal, Clear Python
Interpreter, Open Local SSH Config.
- **Dev** (visible when `sessions_show_dev_commands: true`, default
`false`): Preview Remote Agent Payload, Diagnose LSP Workspace.
**Acceptance:** Each command's `is_visible` reads its tier's setting.
Settings default values yield exactly the "core + advanced" set
visible today minus the dev commands. Test: assert visibility for
each known palette caption under the three setting-combination
matrices.
### 4. Default-settings "safe profile" toggle `[plan]`
**Theme:** First-experience defaults are aggressive:
`sessions_connect_auto_open_remote_folder=true`,
`sessions_mirror_auto_refresh=true`,
`sessions_mirror_include_files=true`. Good for power users; can be
loud for security-sensitive orgs or huge workspaces.
**Proposal:** `sessions_safe_profile` boolean. When `true`, force
`sessions_mirror_auto_refresh=false`,
`sessions_mirror_include_files=false`,
`sessions_connect_auto_open_remote_folder=false`,
auto-deepen depth=1, mirror_max_entries=300, mirror_max_dir_fanout=50.
Document in SECURITY.md as the recommended default for orgs running
Sessions across many workstations.
Don't flip the master defaults yet — too disruptive. Add the toggle,
document it, then in v0.7 consider flipping the default once the
"broad distribution" track is cleared.
**Acceptance:** New setting + override layer that takes precedence
over individual mirror caps when set. New SECURITY.md row in the
"deployment guidance" section. Tests: load with toggle on,
`SessionsSettings.from_loaded()` reflects the conservative caps.
### 5. Stable vs dev release channel `[plan]`
**Theme:** v0.6.0 → v0.6.4 in ~36 hours with several
cancelled/failed CI runs along the way. Internal iteration speed is a
feature, but external readers see a "fast-changing, still shifting"
product. Public users want a calm channel.
**Proposal:**
- Tag protocol: `v0.X.Y` continues to be the hot iteration channel
(default for `git fetch`, what CI publishes per push).
- New: `vX.Y-stable` rolling tags that move forward when an internal
test pass on macOS + Windows + Linux completes against a `v0.X.Y`
candidate. Release page links the latest stable tag separately.
- Documentation lists the stable tag as the recommended fetch for
non-maintainer users.
**Acceptance:** New scripts/`promote_stable.py` that takes a `vX.Y.Z`
tag and force-updates `vX.Y-stable` → that commit (signed). Release
asset cross-link in the Gitea release notes for the unstable tag
points to the matching stable tag (or "no matching stable yet").
SECURITY.md verification command updated to use the stable tag.
### 6. macOS / Windows smoke CI `[plan]`
**Theme:** Repository CI is single-platform (`ubuntu-latest`). Code
explicitly targets Win/macOS (CREATE_NO_WINDOW threading, macOS
PersistentBroker, etc.). External users can't verify the supported
platforms actually pass CI on those platforms.
**Proposal:** Add two cheap smoke jobs (no full test suite — just
"does it build + does the import smoke pass"):
- `cargo build --manifest-path rust/Cargo.toml -p local_bridge -p sessions_native`
on `macos-latest` and `windows-latest`.
- `python -m compileall -q sublime` and the runtime-import smoke test
on the same matrix.
Skip the full pytest suite there (Windows runners are slow and the
real coverage stays on Ubuntu). The smoke gate just answers "does it
load on those platforms".
**Acceptance:** New `.gitea/workflows/cross-platform-smoke.yml` (or
add jobs to the existing `ci.yml`) that runs on PR + main. Document
the matrix in CONTRIBUTING.md. Failures block merge.
### 7. Platform code-signing (Apple Developer ID, Windows Authenticode) `[plan]`
**Theme:** SECURITY.md admits binaries are unsigned (just GPG +
checksum). For corporate / public distribution this is insufficient —
macOS Gatekeeper still raises "unidentified developer" warnings on a
release-bundle binary; Windows SmartScreen does the same.
**Proposal:** Add per-platform signing pipelines, gated on the
existence of org-level credentials:
- macOS: notarize + staple via Apple Developer ID. Requires an Apple
Developer Program membership ($99/yr) and `xcrun notarytool` access.
Sign `local_bridge`, `session_helper`, `libsessions_native.dylib`.
- Windows: Authenticode sign via an EV code-signing cert (DigiCert et
al., ~$500/yr). Sign `local_bridge.exe`, `session_helper.exe`,
`sessions_native.dll`.
- Both pipelines lift the credential from CI secrets at signing time;
the credentials never enter a contributor workstation.
`[needs-input]`: budget approval for the certs + Apple membership.
Without those, this stays planned but not actionable.
**Acceptance:** Two new CI workflow steps (one per platform) that run
after the existing `cargo build --release` on the matrix runner.
Outputs are signed binaries that go into the release asset bundle
alongside the GPG signature. SECURITY.md updated to "platform
signature + GPG signature" dual-trust verification.
### 8. Remote install consent flow `[plan]`
**Theme:** Managed remote-extension catalog includes
`curl ... | bash` (Claude Code), `npm install -g @openai/codex`,
`pip install --user` (Jupyter, debugpy, pyright). The product crosses
the line from "remote code editor" to "remote tool installer" — every
install runs commands on the user's remote workstation under their
SSH identity. Power users want this; security/IT teams push back.
**Proposal:** Three-tier install gating:
- New setting `sessions_remote_extension_install_enabled` (default
`true` today; switch to `false` in v0.7 broad-release default).
- When `false`, the "Install Remote Extension" command shows a
one-shot consent dialog naming the exact commands that will run on
the remote, with "Run once" / "Always allow on this host" / "Never"
buttons. "Always allow" sets a per-host flag in `workspace_state`.
- "Never" leaves the catalog visible (so users see what's available)
but greys out the install button and hints at the setting toggle.
**Acceptance:** New setting + per-host opt-in registry. Existing
install flow gates on it. Tests: install command refused when setting
off + host not opt'd in; install proceeds when opt'd in. SECURITY.md
gains a "remote command surface" appendix listing every install
command + what it touches.
### 9. Large-file hydrate streaming (open issue #32) `[plan]`
**Theme:** Current hydrate has a small-file fast path; large or
high-latency files block the UI thread for the duration of the SSH
fetch. Issue #32 wants progressive streaming.
**Proposal:** Track on existing issue; not in scope for this batch.
Note here as "review-acknowledged".
**Acceptance:** Cross-link to issue #32 in SHIPPED.md once landed.
### 10. Diff-centric change review workflow `[plan]`
**Theme:** Open issue. Agent flow surfaces edits but there's no "show
me what the agent / I changed in this session, diff-style" view.
**Proposal:** Out of scope here. `agent_change_badge.py` exists; the
`file/watch` driver is the missing piece (already documented as a
v0.7 limitation in TEST_CHECKLIST §9).
**Acceptance:** v0.7 follow-up.
---
## Open questions / partial review recovery
- The original review.md may have called out additional items the head
preview did not capture (lost lower paragraphs). If you (Myeongseon)
paste the original back, append themes here under section 11+ rather
than restarting a new doc.
- The "Phase 9 — Quality Gates & Scale" milestone referenced in the
review presumably ties to these items 4 / 5 / 6 / 9; cross-link
when the milestone is reopened.

View File

@@ -177,6 +177,14 @@
}
],
// Show developer / debugging commands in the main palette. Default ``false``
// hides ``Sessions: Preview Remote Agent Payload`` (and any future
// dev-flagged command). Maintainers can flip this to ``true`` in
// Packages/User/Sessions.sublime-settings to surface them. See
// ``planning/REVIEW_v0_6_4_DISTRIBUTION_PLAN.md`` § "Command palette
// split" for the broader core / advanced / dev tier plan.
"sessions_show_dev_commands": false,
// Optional remote extension install/remove catalog (command palette install/remove/status).
// When this list is missing, invalid, or [], defaults are merged in code (bash -lc
// scripts: pip/ensurepip/get-pip fallbacks for Pyright/Ruff; rustup for rust-analyzer).

View File

@@ -3386,6 +3386,28 @@ def _remote_extension_exec_failure_detail(
class SessionsPreviewRemoteAgentPayloadCommand(sublime_plugin.WindowCommand):
"""Fetch a remote agent preview envelope and render it in an output panel."""
def is_visible(self) -> bool:
"""Hide from the main palette unless the dev-commands toggle is on.
This is a developer / debugging command — it reads an arbitrary
remote command's stdout and renders the JSON payload in a scratch
view. Useful when debugging the agent envelope round-trip;
distracting clutter for non-maintainer users. Gate behind
``sessions_show_dev_commands`` (default ``false``); maintainers
flip the flag in their User-level Sessions.sublime-settings.
"""
load_settings = getattr(sublime, "load_settings", None)
if not callable(load_settings):
return False
try:
stored = load_settings("Sessions.sublime-settings")
except Exception:
return False
getter = getattr(stored, "get", None)
if not callable(getter):
return False
return bool(getter("sessions_show_dev_commands", False))
def run(
self,
remote_command: str = "",

View File

@@ -1313,7 +1313,10 @@ def _bridge_diagnostic_hypothesis_catalog() -> list[dict[str, str]]:
{
"id": "H6_remote_download",
"rust_events": "bridge.rust.ensure_remote_helper_*",
"meaning": "Remote helper download via curl/wget; revision cache check.",
"meaning": (
"Editor-cache download + SSH push of session_helper; "
"revision cache check on the remote (no curl/wget runs there)."
),
},
{
"id": "H7_python_rust_id",

View File

@@ -1322,3 +1322,44 @@ def test_probe_remote_extension_installed_pyright_fallbacks_to_cli(
assert commands._probe_remote_extension_installed(context, spec) is True
assert _remote_extension_sh_c_contains(calls[0], "pyright-langserver")
assert _remote_extension_sh_c_contains(calls[1], "pyright --version")
# ---------------------------------------------------------------------------
# SessionsPreviewRemoteAgentPayloadCommand.is_visible — palette gating.
# ---------------------------------------------------------------------------
def _install_fake_load_settings(monkeypatch, value: object) -> None:
"""Patch ``sublime.load_settings`` so the command sees a sentinel value."""
class _StoredSettings:
def get(self, key: str, default=None):
assert key == "sessions_show_dev_commands"
return value
monkeypatch.setattr(
commands.sublime,
"load_settings",
lambda _name: _StoredSettings(),
raising=False,
)
def test_preview_remote_agent_payload_hidden_by_default(monkeypatch) -> None:
_install_fake_load_settings(monkeypatch, False)
cmd = commands.SessionsPreviewRemoteAgentPayloadCommand(FakeWindow())
assert cmd.is_visible() is False
def test_preview_remote_agent_payload_shown_when_dev_flag_on(monkeypatch) -> None:
_install_fake_load_settings(monkeypatch, True)
cmd = commands.SessionsPreviewRemoteAgentPayloadCommand(FakeWindow())
assert cmd.is_visible() is True
def test_preview_remote_agent_payload_hidden_when_load_settings_unavailable(
monkeypatch,
) -> None:
monkeypatch.setattr(commands.sublime, "load_settings", None, raising=False)
cmd = commands.SessionsPreviewRemoteAgentPayloadCommand(FakeWindow())
assert cmd.is_visible() is False