Skip to content

fix(preview): avoid persisting cache and watch state during inspection #9

Closed as not planned

Description

@showxu

Summary

Several inspection paths mutate persistent state before returning their preview:

  • list can create or update source caches.
  • update without --apply can fetch and change the cached checkout.
  • status/diff --watch refresh the source and append watch-ledger events.

There is no general --dry-run flag in the current CLI. This report concerns the actual inspection commands and update's default apply=false behavior.

Code evidence at b742a99:

  • Sources/CLI/ListCommand.swift:42–59 calls RuntimeService.add with listOnly=true.
  • Sources/Core/RuntimeService.swift:228–237 resolves the source before the listOnly return at lines 273–275.
  • Sources/Core/ProcessRunner.swift:74–94 creates, fetches, and checks out persistent caches.
  • Sources/Core/WellKnownProvider.swift:120–137 removes and rematerializes the well-known cache.
  • Sources/Core/RuntimeService.swift:610 resolves update sources before the apply gate at line 649.
  • Sources/CLI/WatchCommands.swift:17,38,128–135 refreshes status/diff with apply=true.
  • Sources/Core/WatchLedger.swift:477–486 appends watched_head_refreshed and saves the ledger.

Impact: inspection dirties project state, grows ledger history, and changes cached source content.

Reproduction

Proposed steps; not executed for this report.

Watch-ledger case:

  1. Under a temporary root, create a source Git repository and a separate project directory.

  2. Commit source/skills/demo/SKILL.md with valid name: demo and description frontmatter.

  3. From the project directory:

    skill add <absolute-temporary-source-path> \
      --watch-only --scope project --agent codex --skill demo
    cp .agent/skills-state.json <temporary-root>/before.json
    
    skill diff <absolute-temporary-source-path> --watch --path skills/demo
    diff -u <temporary-root>/before.json .agent/skills-state.json
  4. Repeat with status --watch, taking a new snapshot first.

  5. No source commit needs to change: each invocation appends a refresh event.

Cache cases:

  • In a fresh temporary project, run list --branch main and inspect the newly created .agent/cache/sources checkout.
  • Add that source with --branch main, advance its main branch, then run update --scope project without --apply. Compare cached HEAD/FETCH_HEAD before and after.

Expected Behavior

Proposed contract: inspection does not persist changes to the existing source cache, watch ledger, resolved file, or installed content. Persisted refresh should be explicit.

Maintainer decision needed: whether ordinary refreshable caches are exempt from this contract. Documentation currently says watch commands refresh internally at Documentation/Reference/CLI.md:215–216, while line 222 calls diff read-only under "Cursor rules". The intended meaning of read-only should be explicit.

Completion checks:

  • Repeated diff/status does not append ledger events under the accepted inspection contract.
  • Preview side effects are tested at the CLI boundary, not only through WatchService.diff.
  • Cover Git and well-known cache paths.
  • Keep deliberate review check/seen/done writes working.
  • Run swift test.

Actual Behavior

Watch inspection persists refresh events even if the head has not changed. Source listing and ordinary update previews can alter persistent caches.

Scope limits:

  • Ordinary update without --apply does not pass the installation gate and does not thereby rewrite resolved state.
  • review check explicitly records a handoff; its writes are not an accidental preview side effect.
  • update --from-watch without --apply returns before installation at RuntimeService.swift:690–692.
  • This report does not claim that every read-like command mutates state.

No duplicate issue was found. Issue #4 concerns membership synchronization, not inspection side effects.

Environment

  • skill version: 0.2.1.
  • Source inspected: b742a99.
  • Swift version: not obtained in the read-only sandbox.
  • OS: macOS 27.0.1 (26A434).
  • Architecture: arm64.
  • Validation: static inspection only; reproduction not executed.

Decision needed

The current documentation describes both automatic cache refresh and read-only cursors, so this cannot be changed without choosing a boundary first: either inspection must not persist cache refreshes at all, or cache updates stay allowed and only managed records such as the watch ledger must remain unchanged.

Activity

  1. showxu commented on Oct 18, 2026

    @showxu
    ContributorAuthor

    Superseded by the design adopted in #29 (Commands, Source Cache). Previews may fetch into a source's mirror, which is a cache, but never change the declaration, lock, installed targets or watch state; the 0.2 watch ledger refresh no longer exists. Preview read-only behavior is covered by core tests.

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

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions