Honest session-complete count + ora spinner during sync#24
Merged
willwashburn merged 2 commits intomainfrom Apr 23, 2026
Merged
Honest session-complete count + ora spinner during sync#24willwashburn merged 2 commits intomainfrom
willwashburn merged 2 commits intomainfrom
Conversation
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>
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
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 repoclaimed 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 sessionso 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 whileautosync.stop()+ finalsyncBack()walked the trees.Wired sindresorhus/ora (v9.4, ESM, Node 20+) as an animated spinner whose lifecycle matches the existing three-stage SIGINT handler:
.start()with "Syncing… (Ctrl-C again to skip)".text =aborting-warning form +shutdownSignal.abort().fail()+ force-exit (existing behavior)onAfterSync.succeed()with the honest event-count linecatchbranch.fail('Sync did not complete')+ existing error outputfinally.stop()if nothing else handled itKnown scope limit
Spinner only engages on the SIGINT path. Natural-exit (agent quits via
:q) has no hook between child-exit and sync-start inlaunchOnMount0.5.0 — we'd need anonBeforeSyncoption 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 checkgreen — 39 + 26 + 50🤖 Generated with Claude Code