Skip to content

Capture.sh defaults every verification screenshot to the user's Downloads root, contradicting the hook that forces raw captures to /tmp (follow-up to #1566) #1892

Description

@xmasyx

Follow-up to #1530 and #1566. Both halves of #1566 shipped and work — the installer's name-anchored rules (interceptor-screenshot-*, interceptor-capture-*, plus interceptor-macos-screenshot-*, which is a good addition we hadn't proposed) keep captures out of a user's backup commit, and the ContextReduction rewrite is still there as defense in depth. This issue is about the half that was never in scope: not where captures must not go, but where they should go in the first place.

Upstream currently disagrees with itself

LifeOS/install/hooks/ContextReduction.hook.sh (~line 94) forces a raw interceptor screenshot --save into an ephemeral directory:

REWRITTEN="${ENV_PREFIX}mkdir -p /tmp/pai-screenshots && ( cd /tmp/pai-screenshots && $CMD_BODY )"

LifeOS/install/skills/Interceptor/Tools/Capture.sh (line 184) — the sanctioned wrapper the skill tells you to use instead of the raw command — sends every capture to the user's Downloads root:

OUT="${LIFEOS_DOWNLOADS_DIR:-${HOME}/Downloads}/interceptor-capture-${ts}-${rand}.png"

So the unsanctioned path is ephemeral and the sanctioned path is durable and user-facing. One of the two is wrong, and it is not the hook.

Why Downloads is the wrong default

A verification capture exists so the agent can look at a page and close a claim. Once viewed, it is dead weight. Sending that traffic to Downloads puts agent-internal artifacts in the one directory the human curates by hand, mixed in with files they actually downloaded. The observed outcome on an install doing routine web verification is a steady accumulation the user eventually deletes manually — which is the tell that the default was never serving them.

The gitignore rules from #1566 made these files safe. They did not make them wanted.

The distinction that fixes it

Captures fall into two classes, and which one applies is known at the moment the shot is taken:

  • verification — the agent needs to see a page. Ephemeral, agent-owned, should never reach the user's filesystem.
  • deliverable — the image is the product: it goes into a document for a client, the user asked to see it, or it is evidence they will reopen later. Durable, user-owned.

Because it is knowable at call time, this should be an explicit flag rather than a heuristic.

Proposed fix

In Capture.sh, default to the ephemeral directory the hook already designates, and add an opt-in for the durable case:

# arg parse
DELIVER=0
...
        --deliver)
            DELIVER=1
            shift
            ;;
# destination
if [ "$DELIVER" -eq 1 ]; then
    OUT="${LIFEOS_DOWNLOADS_DIR:-${HOME}/Downloads}/Interceptor/interceptor-capture-${ts}-${rand}.png"
else
    OUT="/tmp/pai-screenshots/interceptor-capture-${ts}-${rand}.png"
fi

Note the deliverable path is a subdirectory, not the Downloads root: a directory the tool owns can be reasoned about, and it keeps $LIFEOS_DOWNLOADS_DIR meaning "the downloads root" for every other consumer (the Art skill writes there too, and its output is meant to be seen — repointing that variable would bury it).

The --out PATH help text at line 45 still advertises ~/Downloads/interceptor-capture-*.png and needs updating with it.

Two consequences worth stating:

  1. This makes the hook's rewrite redundant on the sanctioned path — it stays valuable for the raw command, but the wrapper stops fighting it.
  2. Whatever housekeeping sweeps captures must not sweep the deliverable directory. We hit this immediately: an ephemeral-sweep root pointed at the deliverable folder will trash the one class of capture that is not disposable, on a timer, silently. The sweep belongs on the ephemeral directory only.

Verification

Implemented and measured on an install:

  • default → /tmp/pai-screenshots/interceptor-capture-<ts>-<pid>.png; --deliver<downloads>/Interceptor/interceptor-capture-<ts>-<pid>.png.
  • Two-pole check on the sweeper: with both files backdated to the same mtime, a dry run lists the ephemeral capture and leaves the deliverable one untouched.
  • bash -n clean.

Credit where it is due

The prompt for this was the install's human asking a question rather than filing a complaint: "what am I actually supposed to do with these screenshots?" The first response was to move them into a subfolder of Downloads, which answered the clutter and missed the point. The reframing — almost none of them are for the human at all — is what produced the fix. Worth recording because the tidier is the tempting build, and it is the wrong one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions