Skip to content

Honest session-complete count + ora spinner during sync#24

Merged
willwashburn merged 2 commits intomainfrom
opencode-sync-ux
Apr 23, 2026
Merged

Honest session-complete count + ora spinner during sync#24
willwashburn merged 2 commits intomainfrom
opencode-sync-ux

Conversation

@willwashburn
Copy link
Copy Markdown
Member

@willwashburn willwashburn commented Apr 23, 2026

Summary

Two coupled UX bugs in the mount-path session exit (reported after #23 landed):

1. Misleading sync count

✓ Synced 15 change(s) back to the repo claimed outbound-only, but @relayfile/local-mount@0.5.0's onAfterSync contract is explicit that the count is bidirectional — it sums autosync activity in both directions (inbound project→mount and outbound mount→project, including deletes) plus the final mount→project syncBack. A session where the agent wrote nothing still reported "15 changes back to the repo" because ambient initial-mirror / inbound scan events counted.

Rephrased to Session complete — N file event(s) during session so the line does not lie about which way files moved.

2. No visual indicator during the sync pause

First Ctrl-C previously printed a static ⏳ Syncing… line and the terminal then looked frozen for several seconds while autosync.stop() + final syncBack() walked the trees.

Wired sindresorhus/ora (v9.4, ESM, Node 20+) as an animated spinner whose lifecycle matches the existing three-stage SIGINT handler:

Event Spinner state
1st Ctrl-C .start() with "Syncing… (Ctrl-C again to skip)"
2nd Ctrl-C .text = aborting-warning form + shutdownSignal.abort()
3rd Ctrl-C .fail() + force-exit (existing behavior)
onAfterSync .succeed() with the honest event-count line
catch branch .fail('Sync did not complete') + existing error output
finally defensive .stop() if nothing else handled it

Known scope limit

Spinner only engages on the SIGINT path. Natural-exit (agent quits via :q) has no hook between child-exit and sync-start in launchOnMount 0.5.0 — we'd need an onBeforeSync option on relayfile upstream. Sync on natural exit is typically fast; the honest-count line is the main UX win there.

Test plan

  • corepack pnpm run check green — 39 + 26 + 50
  • Smoke: run any opencode persona, exit via Ctrl-C, confirm animated spinner during sync pause and honest succeed-line on completion
  • Smoke: run any opencode persona, exit via agent quit command (natural exit), confirm honest completion line (no spinner expected)

🤖 Generated with Claude Code


Open in Devin Review

Two coupled UX bugs in the mount-path session exit:

1. "Synced 15 change(s) back to the repo" was misleading. Per
   @relayfile/local-mount's onAfterSync contract (launch.d.ts:36-40),
   the count is *bidirectional* — it sums autosync activity in both
   directions (inbound project→mount AND outbound mount→project,
   including deletes) plus the final mount→project syncBack. Phrasing
   it as "synced back to the repo" overclaimed direction: a session
   where the agent wrote nothing still reported "15 changes back"
   because ambient initial-mirror / inbound scan events counted.
   Rephrase to "N file event(s) during session" so the line does not
   lie about which way files moved.

2. No visual indicator during the sync pause. First Ctrl-C previously
   printed a static "⏳ Syncing…" line and then the terminal looked
   frozen for several seconds while autosync.stop() + final syncBack()
   walked the trees. Wire ora (sindresorhus/ora v9.4, ESM, Node 20+)
   as an animated spinner whose lifecycle is:

     1st Ctrl-C → spinner.start with "Syncing… (Ctrl-C again to skip)"
     2nd Ctrl-C → spinner.text updated to the aborting-warning form
                  + shutdownSignal.abort()
     3rd Ctrl-C → spinner.fail, then force-exit (existing behavior)
     onAfterSync → spinner.succeed with the honest event-count line
     catch branch → spinner.fail + fall through to existing error msg
     finally → defensive spinner.stop if none of the above ran

Scope limit: the spinner only engages on the SIGINT path. The
natural-exit path (agent quits via :q) has no hook between child-exit
and sync-start in launchOnMount 0.5.0, so we cannot start a spinner
there without patching relayfile upstream. Sync on natural exit is
typically fast; the honest count line is the main UX win there.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 2 additional findings.

Open in Devin Review

Symptom: "the persona agent was not able to make any changes to the
codebase." The emitted opencode.json defined model + prompt + mode but
omitted the permission field, so opencode applied its restrictive
default — blocking edit/write/bash across every tool. Autosync then
had nothing outbound to propagate on exit, which is why the session-
complete line showed file events but no actual repo changes landed.

`opencode agent list` for the built-in `build` agent shows explicit
wildcard-allow rules (`permission: '*', action: 'allow', pattern: '*'`)
— that is how `build` earns its permissions, not a default. Matching
the same shape for persona-generated agents via `permission: 'allow'`
(the string form per the PermissionConfig schema at
https://opencode.ai/config.json).

The mount already sandboxes writes (autosync gates sync-back via
ignoredPatterns + shutdown semantics) so wildcard-allow does not
escape the session boundary outside of normal outbound propagation.
Callers who want a read-only persona (e.g. a code reviewer) can
refine this in a follow-up once the workforce PersonaPermissions
shape grows opencode support — the harness-kit already warns that
"opencode harness is not yet wired for runtime permission injection"
so this is consistent with current scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@willwashburn willwashburn merged commit 1660646 into main Apr 23, 2026
1 check passed
@willwashburn willwashburn deleted the opencode-sync-ux branch April 23, 2026 04:33
willwashburn added a commit that referenced this pull request Apr 23, 2026
…/harness-kit@0.2.0 @agentworkforce/cli@0.3.0

Reconciliation of the 2026-04-23 publish-run race: all three packages
published to npm successfully, but the workflow's final `git push
origin HEAD --follow-tags` was rejected because PR #22 (persona-maker)
merged to main during the job. Tags shipped but the chore(release)
commit was orphaned at 3b5b8f3.

This cherry-picks that commit back onto main and replaces the
auto-generated CLI changelog stub with a handwritten entry covering
PRs #20, #22, #23, #24.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant