Skip to content

release: Document Sync Agent on-device validation #63

Description

@Adron

Summary

The Document Sync Agent (SyncAgent/) is built and tested — 53 passing tests including a read-only live check. The packaging pipeline embeds it at InterlinedList.app/Contents/Library/LoginItems/InterlinedListSync.app and registers it as an SMAppService.agent via Settings ▸ Document Sync.

What remains cannot be run headless: it needs a real Aqua session and a Developer ID signature. That makes it part of the release gate, not the feature backlog.

What the agent is

A bundled LSUIElement menu-bar utility that mirrors documents to a local Markdown folder (the Obsidian use case). It reads the bearer token from the shared Keychain group $(AppIdentifierPrefix)com.interlinedlist.shared, so it syncs with no separate sign-in. Correlation uses xattr plus path.

Validation checklist

  • Menu-bar GUI smoke — status item appears, Preferences window opens and behaves.
  • Full notarized .pkg install path, end to end:
    • Install the .pkg on a clean machine
    • SMAppService.agent registration succeeds and is visible in System Settings ▸ Login Items
    • The running agent reads the bearer token from the shared Keychain group
    • It syncs with no separate sign-in
    • Confirm the legacy-token → shared-group migration path for a machine that had an older build
  • Exercise the live write paths once — create, update, delete. They share the request-building and envelope decoder that the read paths already cover, but they have never been run against production.

Two things worth deciding while validating

  1. Per-machine settings belong on the server now. /help/app-settings describes per-machine settings as exactly this case — a sync folder path is meaningful on one machine only. The agent's configuration is a natural first tenant for the Applications settings work. Not a blocker for validation, but decide whether it lands before or after the release cut.
  2. Account switching. If multi-account switching is ever built, a running agent mirroring one account's documents to a local folder needs an explicit answer for what a switch means. Flagged in that spike; noted here so the agent's owner sees it.

Acceptance criteria

  • Every box above ticked on a real machine with a notarized build.
  • Any defect found is filed separately rather than fixed silently inside the validation pass.

Notes

work-consolidation.md §3b. Blocked on the release issue producing a signed .pkg — sequence them together.

Activity

  1. Adron commented on Sep 16, 2026

    @Adron
    MemberAuthor

    Needs you at a keyboard — this one is inherently manual

    I cannot do on-device validation. Everything here requires a signed build installed on a real Mac, a real Obsidian vault, and observation over time.

    What I can confirm from the code

    The Document Sync Agent is implemented and unit-tested: SyncAgent/, the shared-Keychain token, the SMAppService LaunchAgent registration, and the xattr + path correlation. swift test --package-path Packages/InterlinedPersistence covers the sync engine and the outbox.

    Two things changed today that touch this issue directly:

    1. PR fix(persistence): order the sync outbox by a monotonic sequence, not by a timestamp #100 fixes a real ordering defect in the sync outbox. It was sorted by enqueuedAt alone — a non-total key — so two changes queued in the same instant could replay in either order, which for document sync means an update replayed before the create it depends on. If you were going to validate the agent on-device, validate it after that merges, or you would be exercising the bug.
    2. The agent's per-machine configuration is the case feat(settings): finish the Applications pane - main workstation, rename, remove, copy to shared #56 is about (app-settings per-machine storage). That is in flight.

    What I need from you

    A validation pass on a real machine, roughly:

    1. Install a signed build, enable the agent in Settings ▸ Document Sync, point it at a folder inside an Obsidian vault.
    2. Confirm the LaunchAgent survives a logout/login and a reboot — SMAppService registration is the part most likely to be wrong in a notarised build versus a debug one.
    3. Edit a document in the app → confirm the file changes on disk. Edit the file in Obsidian → confirm the app picks it up.
    4. Rename a document; confirm the xattr correlation keeps the file associated rather than creating a duplicate.
    5. Force-quit mid-sync and relaunch; confirm the outbox drains rather than losing or duplicating a change.
    6. Leave it running a day and check Console for repeated errors or runaway wakeups.

    What would help most if something goes wrong

    The rotating debug log (shipped in PR #9) and the Console output for the agent's subsystem. If step 2 fails, that is almost certainly an entitlement or a signing difference between the debug and notarised builds, and the notarised build is the only one that can show it — which is why this is blocked behind #62 in practice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions