mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-24 10:13:11 +02:00
## Thinking Path
> - Paperclip is the open source app people use to manage AI agents for
work
> - Git cache expiration keeps a workspace and reports
`inspection_failed` when an unexpected error interrupts its checks
> - It dropped that error, so the log never said what went wrong
> - This pull request adds a sanitized description of the error to the
expiration result, which the workspace reaper already logs
> - The benefit is that unexpected expiration failures can be diagnosed
without exposing commands or credentials
## Linked Issues or Issue Description
Refs #17248. Bug report described in-PR (bug report template).
**What happened?**
On one instance, a closed workspace was kept with `inspection_failed`.
The log entry carried only that reason, so the cause could not be
determined from the logs.
**Expected behavior**
An unexpected failure is logged with enough detail to diagnose it,
without leaking the command line or credentials.
**Steps to reproduce**
1. Break a closed issue's worktree so a git command fails, for example
by pointing its `.git` file at a missing directory.
2. Run expiration: the log says `inspection_failed` and nothing else.
**Paperclip version or commit:** `master` at 0fb152ee94.
**Deployment mode:** any.
**Agent adapter(s) involved:** not adapter-specific (core).
## What Changed
- `GitExpirationResult.failure` is set when the skip reason is
`inspection_failed`, by all three places that record a skip (the outer
catch and the two base-inspection catches, through one `recordSkip`
helper). It contains:
- `name`;
- `code` (for example git's exit code);
- `at` (the first stack frame);
- `stderr` (up to 500 characters).
- `describeGitExpirationFailure` builds it. It never includes the error
message, because a failed git command's message contains the full
command line, which can include `http.extraHeader` authentication. In
stderr, credentials in URLs and `authorization`, `token`, `password` or
`secret` values are redacted to the end of the line.
- The workspace reaper already spreads the result into its `Git
workspace cache expiration inspected` log entry, so no logging code
changed.
No code comments were added.
## Verification
- `pnpm exec vitest run src/__tests__/git-workspace-expiration.test.ts
-t "unexpected inspection failure|redacts credentials|while inspecting
the base"` (in `server/`): 4 passed.
- **Broken worktree:** a worktree whose `.git` link points at a missing
directory reports `inspection_failed` with a code, a stack frame and
git's "not a git repository" stderr, and is kept.
- **Failing command:** a real failing `git ls-remote` with credentials
in its arguments produces a description without them or the command.
- **Echoed credentials:** a stderr that echoes a credentialed URL and an
`Authorization: Bearer` header is redacted.
- **Base inspection:** an unreadable directory in the base, which fails
base inspection after the worktree is removed, reports
`inspection_failed` with code `EACCES` and a stack frame. Recording only
the reason in that catch fails this case.
- **Mutation check:** removing the redaction fails the
echoed-credentials case. That case also caught an earlier version that
redacted only the first word of a header value.
- `pnpm exec vitest run git-workspace-expiration execution-workspaces
git-restore-point` (in `server/`): 258 passed.
- `pnpm run typecheck` (in `server/`): pass.
- Not run: server build and boot smoke.
## Risks
- **Log volume:** one bounded object (about 1 KB at most) per failed
inspection.
- **Redaction is pattern-based:** the message and command line, where
git places configuration values, are never logged; stderr is redacted by
pattern.
## Model Used
- Claude Opus 5.5 (`claude-opus-5-5`), 1M context, through Claude Code
with tool use (shell, file edits, tests, read-only inspection of a live
instance).
## Checklist
- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge
---------
Co-authored-by: Paperclip <noreply@paperclip.ing>