Commit Graph
157 Commits
Author SHA1 Message Date
DottaandClaude Opus 5.5 2c0cc8ee64 fix(ui): resolve task status glyphs through one shared mapping (BUG-07)
The same task state rendered different status icons across views. A blocked
task covered by an active sub-task ("in queue") showed the blue queued glyph
in the task header and status trigger, but the status menu's current row, the
chat chip and the coordinator sidebar recents/project rows showed the red
blocked glyph, because those surfaces dropped blockerAttention (and some
dropped externalConversationState) before calling StatusIcon.

- Add ui/src/lib/task-status-presentation.ts: one resolver for glyph, label
  and accessible copy, plus taskStatusIconProps() so call sites pass every
  presentation field from a task record.
- StatusIcon and IssueStatusBadge use the resolver; the picker draws the
  current row with the trigger's presentation.
- Task call sites (sidebar, lists, inbox, properties, pills, search, chat
  chips, status cards) spread taskStatusIconProps.
- /issues/summaries returns blockerAttention for blocked rows; recent-task
  snapshots store and refresh it; sidebar project rows use the rows projection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 13:40:26 -06:00
DottaandClaude Opus 5.5 1eff07f29e feat(task-chat): show Claude subagents as a collapsible tree in the runner turn (#19264)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The task chat shows what an agent does in a run. The Paperclip
Runner sends this activity as canonical provider events.
> - Claude runs subagents through its Agent (Task) tool. A run that
delegates showed a confusing burst of unrelated tool calls.
> - The subagent data was already sent, but it was lost: ACPX dropped
`_meta`, the hardened sidecar dropped `rawInput`, and async subagents
report "launched" as the tool result.
> - This pull request maps each Agent call to a canonical `delegation`
event, links each child tool to its subagent, and shows subagents as a
collapsible card or tree.
> - The benefit is that operators can see what each subagent was asked,
what it is doing now, which tools it used, and what it returned.

## Linked Issues or Issue Description

Refs #19252 (the docked plan card used the same canonical-event pattern)
Refs #19259 (ACPX `_meta` passthrough, merged). This PR builds on it.

**What happened?**
When a Claude agent used its Agent tool, the task chat showed one
generic "Task" row and then the subagents' tool calls as flat rows in
the parent turn. The subagent type, prompt, progress and result were not
visible.

**Expected behavior**
Each subagent shows as its own card with its type, description, prompt,
live progress summary, nested tool rows and result. Subagents that start
together show as one tree with status dots.

**Steps to reproduce**
1. Assign a Claude (Paperclip Runner, ACPX) agent a task that asks it to
launch three Explore subagents in parallel.
2. Open the task while the run is live.
3. Before this change, the subagents' tool calls appear flat in the
parent turn.

## What Changed

- **claude-agent-acp patch:** Under the isolated runner context, the
patch turns on the SDK option `agentProgressSummaries`. It forwards each
subagent's `task_progress` summary and its terminal state and summary
onto the spawning tool call as `_meta.claudeCode.subagentProgress` and
`subagentState`. Native subagent sessions stay off, because ACPX cannot
follow child ACP sessions.
- **Runner:** The new file `claude-subagent-lineage.ts` tracks each
Agent/Task call across ACP update deltas. It maps the call to
`delegation.started|updated|completed` events and stamps child tools
with `parentItemId`. An async subagent stays running after its "Async
agent launched" result until its own state settles.
- **Sidecar path:** `acpx-runtime-sidecar.ts` reads the lineage before
it drops `_meta` and `rawInput`. Delegations go out as schema-checked
rich events. Child tools carry `parentToolCallId`, which Rust
(`acpx_event_payload.rs`, `provider_events.rs`) maps to `parentItemId`.
- **Contracts:** The provider-event schema adds optional `prompt` and
`result` to delegation children and optional `parentItemId` to tool
executions. The protocol modules are regenerated. ACPX Claude now
advertises the `delegation` event family.
- **UI:** `native-run-events.ts` keeps delegation payloads and the tool
parent link. `buildTurnTimelineRows` groups adjacent delegations into a
new `subagent_group` row, nests child tool rows (plain and
provider-activity shapes), and hides the spawning call's own tool row.
The new `TaskChatSubagentCard.tsx` renders the card and tree. A new size
token caps the result height.
- **Storybook:** The new story `Tasks and conversations/…/Task
chat/Subagents` has 7 states.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner exec vitest run src/cli
src/drivers/acpx src/provider-events.test.ts
src/claude-subagent-lineage.test.ts src/protocol` (2069 passed)
- `cargo test --release --locked -p paperclip-runner-core --lib` in
`packages/paperclip-runner/runner` (488 passed, including the new
parent-link test)
- `node --test test/protocol-contract.test.mjs
test/acpx-sidecar-contract.test.mjs
test/acpx-codex-package-contract.test.mjs
test/acpx-rich-extensions-package-contract.test.mjs` (48 passed)
- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat src/components/transcript`, including the new
`subagent-timeline.test.ts`
- `check:protocol-types`, `check:protocol-manifest`,
`check:acpx-profiles` and `pnpm check:token-gates` pass.
- **Live test:** A local test-drive instance ran a Claude Opus 5.5 agent
on the Paperclip Runner (hardened sidecar path). The agent ran real
tasks that launched three parallel Explore subagents. The live view
showed "Running 3 subagents · 2 done" with a progress summary. The
settled view showed "Ran 3 subagents", each with its prompt, nested
tools and its own result text.

## Risks

- `agentProgressSummaries` makes Claude Code generate a short progress
summary for each running subagent about every 30 seconds. This adds a
small model cost to runs that delegate.
- The adapter patch reads `task_notification` and terminal
`task_updated` messages. A future claude-agent-acp version can change
these. The patch hunks then fail to apply, and the dependency bump must
update them.
- If a delegation event is lost, child tools stay at the top level as
before. Nothing is hidden without a matching delegation.
- Codex is not changed. Codex subagents need `multi_agent`, which
Paperclip keeps off on purpose. Changing that is a separate policy
decision.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use
(shell, file edits, browser automation). It did the investigation,
implementation, tests and live test.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:58:35 +00:00
DottaandClaude Opus 5.5 d361f92071 feat(task-chat): show harness status notices as chips, out of the answer (#19267)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents run through the native runner. The runner turns harness
events from Codex and Claude into canonical provider events, and the
task chat shows them.
> - Harnesses report their own lifecycle: context compaction, retries,
model fallback, and warnings. Paperclip lost or mangled these reports.
> - Claude (claude-agent-acp 0.73) sends compaction, model-fallback and
warning banners as ordinary message text, so "Compacting..." ended up
inside the agent's answer and the issue comment.
> - Codex sends `error` with the text in `error.message` and a
`willRetry` flag. Paperclip read `params.message`, so every Codex error
said "Provider notice", and every retry looked fatal.
> - This pull request keeps these reports out of the answer and shows
them as small status chips between the turn's activity.
> - The benefit is that users can see why an agent paused, retried or
forgot earlier context, and the answer text stays clean.

## Linked Issues or Issue Description

**Subsystem affected**
Native runner provider-event mapping (TypeScript driver, ACPX sidecar
and Rust runner-core) and the task chat transcript.

**Problem or motivation**
Claude status banners are mixed into assistant answer text. Codex error
notices lose their message and their retry state. The task chat hid all
of these notices, and settled turns stripped every provider notice.

**Proposed solution**
Classify Claude banners as provider notices at the ACPX boundary. Map
Codex `TurnError` fields and `willRetry` correctly. Render status
notices as inline chips. A retry chip fades after later provider work. A
final error shows the real provider message.

**Alternatives considered**
Patch claude-agent-acp to tag banners in `_meta`. ACPX keeps only
`origin`, `kind` and `source` from `_meta`, and other sessions own the
ACPX `_meta` passthrough work. Banner chunks already have no
`messageId`, and model output always has one, so the classification
needs no adapter patch.

**Roadmap alignment**
This makes existing harness signals visible. It adds no new protocol
schema. It uses the existing `paperclip.provider.notice.v1` `category`
and `details` fields.

## What Changed

- Codex `error` notifications (TypeScript `provider-events.ts` and Rust
`runner-core/src/provider_events.rs`): read `error.message`, map
`willRetry: true` to a recoverable `provider_retry` notice, keep
category `error` for a final error, and add the `CodexErrorInfo` kind,
HTTP status, and the "Reconnecting... n/m" attempt count as notice
details. Retries in one turn share one notice id.
- New `claude-status-banners.ts`: classifies the claude-agent-acp
compaction, model-fallback and SDK informational banners. A chunk must
have no `messageId` and match a known banner exactly.
- ACPX sidecar and the TypeScript ACPX driver emit these banners as
`provider_notice` events instead of answer text. Compaction start and
end share one notice key and carry a `Phase` detail.
- Rust runner-core accepts an optional `noticeKey` and bounded `details`
on ACPX `provider_notice` events.
- UI: new `TaskChatStatusNotice` chip and
`status-notice-presentation.ts`. Status notices become top-level
timeline rows, render as chips wherever protocol cards render, and stay
visible in settled (historical) turns. Generic warnings stay hidden as
before.
- New tokens `--tc-status-notice-warning-*` in `ui/src/index.css`.
- Storybook story `Tasks and conversations/.../Task chat/Status notices`
with eight states.
- `doc/run-log-events.md`: describes the status notice categories.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat src/components/transcript`
- `pnpm --filter @paperclipai/paperclip-runner exec vitest run
src/provider-events.test.ts
src/drivers/acpx/claude-status-banners.test.ts
src/drivers/acpx/codex-acpx-driver.test.ts
src/cli/acpx-runtime-sidecar.test.ts`
- `cargo test -p paperclip-runner-core --lib provider_events` and
`--test acpx_provider_events`
- `pnpm check:token-gates`
- Storybook: open
`product-task-chat-status-notices--all-states-gallery`.
- Live test-drive on an isolated worktree instance:
- Codex (gpt-5.6-sol, app-server 0.160): a local pass-through proxy in
front of the real OpenAI API cut the first two response streams. Codex
ran its own retries. The chat showed an amber "Reconnecting" chip live,
then "Recovered after retry" once work continued. With every stream cut,
Codex made five retries and then sent a final error with the real
message.
- Claude (claude-haiku-5-5 through claude-agent-acp 0.73): a long
reading task triggered Claude's own auto-compaction twice. The chat
showed "Compacting context…" live and "Context compacted" afterwards.
The final answer and the issue comment contained no compaction text.
- Not verified live: model fallback and Claude informational banners.
They need a model refusal or a blocking hook. Unit tests cover them.

## Risks

- Low to medium. A Claude model message that is exactly a banner text
and has no `messageId` would become a notice. Model output from
claude-agent-acp always carries a `messageId`.
- Older stored Codex `error` notices (category `error`, not recoverable)
now render as a red row instead of being hidden.
- Claude retries (`api_retry`) are still not visible. claude-agent-acp
reports them only to clients that negotiate session-failure records, and
ACPX drops `_meta`. This is a follow-up that depends on the ACPX `_meta`
passthrough work.
- On a failed Codex turn the thread collapses to a summary, so the red
row does not show there. The existing task banner already shows the real
provider message.
- Some local suites failed on this machine. They do not touch the
changed code: Cursor Cloud staging-custody tests, the ACPX Claude
dependency-graph pin test (a timeout), and the Rust `task_memory`
monitor tests. CI is the reference for these.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use,
code execution and browser automation. Default context window. Extended
reasoning was not enabled.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

Refs paperclipai/paperclip#19252 (plan card precedent).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:38:57 +00:00
DottaandClaude Opus 5.5 cb0b7525e0 feat(task-chat): warn at the top of a run when an MCP server failed to start (#19289)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Each agent run shows its activity in the task chat. The Paperclip
runner turns harness events into that activity.
> - Codex reports `mcpServer/startupStatus/updated` when an MCP server
fails to start. The runner dropped this event at the notification
allowlist and in the Rust normalizer.
> - When an MCP server fails, the agent runs without its tools. The
agent then says "I could not reach the server", and the user cannot see
why.
> - This pull request maps a failed MCP start to a user-facing provider
notice and shows it as one warning line at the top of the run.
> - The benefit is that the cause of a "cannot reach my tools" answer is
visible next to that answer.

## Linked Issues or Issue Description

Refs #19252 (the plan card, which set the pattern for promoting a
dropped harness signal to a dedicated task-chat surface).

**Problem description**
Codex sends `mcpServer/startupStatus/updated` (`name`, `status`,
`error`, `failureReason`) during `thread/start`. The TypeScript
allowlist (`codex-thread-normalization.ts`) and the Rust normalizer
(`runner-core/src/provider_events.rs`) both dropped it. A run with a
broken MCP server showed no sign of the failure. The agent only said
that it could not reach the tools.

**Proposed solution**
Map `status: "failed"` to `provider.notice.recorded` with `category:
"mcp_server_startup_failed"`, `severity: "warning"`, `scope: "session"`
and `userActionable: true`. Show these notices as one run-health line
under the runner header: "github MCP server failed to start: No such
file or directory (os error 2)".

**Alternatives considered**
An inline notice row in the timeline. It scrolls away and sits among
tool rows. A run-level line next to the header is easier to connect to
the agent's answer.

## What Changed

- Runner (Rust, production Codex path): `normalize_codex_notification`
maps a failed `mcpServer/startupStatus/updated` to a
`provider.notice.recorded` notice. `starting`, `ready` and `cancelled`
stay out of the transcript. The new helper removes the Codex wrapper
text ("MCP client for \`x\` failed to start: MCP startup failed:") so
that the line shows the real reason. `reauthenticationRequired` becomes
"needs re-authentication".
- Runner (TypeScript): the same mapping in
`canonicalProviderEventsFromCodex`, and the method is added to
`isSupportedCodexNotificationMethod`.
- Server: the `view=conversation` run-event query keeps
`mcp_server_startup_failed` notices. A settled run can then still show
the warning. Other notices stay out of that view.
- UI: new `TaskChatRunHealthBanner`. `partitionRunHealthItems` takes MCP
failures out of the run's items, with one line per server where the
latest report wins. `TaskChatRunnerTurn` (live runs) and `TaskChatTurn`
(settled, historical and merged turns) show it under the header.
`coalesceSettledTurns` merges the failures when it merges turns.
- Storybook: `Tasks and conversations/…/Task chat/Run health` shows one
failure, several failures, a finished run and a healthy run, all through
the production runner turn.

## Verification

- `pnpm --filter @paperclipai/paperclip-runner exec vitest run
src/provider-events.test.ts src/drivers/codex src/protocol`: 508 tests
pass.
- `cargo test --release -p paperclip-runner-core --lib --
provider_events`: 20 tests pass.
- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat src/components/transcript
src/components/TaskChatThread.test.tsx`: 1340 tests pass, including the
new `TaskChatRunHealthBanner.test.tsx` (persisted event to rendered
banner, deduplication, settled historical turn, merged turns).
- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/task-cold-open.test.ts`: the conversation view keeps the
MCP notice and still excludes other notices.
- `pnpm check:token-gates` is clean. `node
scripts/typecheck-low-memory.mjs` passes.
- Live test on a local instance with Codex 0.160: a Codex agent with a
preconfigured Codex home whose `config.toml` has `[mcp_servers.github]
command = "github-mcp-server-not-installed"`. Codex reported the failure
during `thread/start`. The persisted event had the summary "github MCP
server failed to start: No such file or directory (os error 2)". The
banner showed while the run was live. It also showed on the settled turn
after "More run output", above the agent's answer that it could not
reach the GitHub MCP server.

## Risks

- Low risk. The change adds one notice category. It does not change how
existing notices map or render.
- A settled run whose transcript is deferred on a cold open (a
successful run with a posted agent comment) shows the warning only after
"More run output". This is the same as all other run activity under the
current compact history.
- Claude does not report MCP startup failures over ACP.
`claude-agent-acp` reads MCP status only for OAuth. This change is
therefore Codex-only.
- Provisional task titles from provider session names are not part of
this change. Codex app-server does not generate thread names (only its
TUI does). Claude generates its title after the turn ends, and ACPX
drops the title text.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), through Claude Code with tool use
(shell, file edits, browser automation for Storybook and the live test).

## 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
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:10:51 +00:00
DottaandPaperclip b400f76647 feat(ui): submit task composers with Enter by default (#19272)
Use Enter to submit task replies and new tasks, with Shift+Enter for a new line. Add an experimental preference to require Command/Ctrl+Enter.

Preserve autocomplete selection and IME confirmation, and retain the modifier shortcut until saved settings load.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-05 11:40:18 -06:00
DottaandClaude Opus 5.5 c6996799c4 feat(task-chat): show an inline diff for every file edit (#19269)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The task chat shows what an agent did during a run, including each
tool call
> - Codex and Claude both report the patch for every file edit, but
Paperclip dropped it. Claude's ACP `diff` content was never read. The
Codex `fileChange` item became a generic item with no patch. Codex
`turn/diff/updated` had no native-runner mapping
> - A reviewer could not see what an agent changed without opening the
workspace
> - This pull request carries a bounded patch on each edit call and
shows it in the edit row. Each turn that changed files ends with a
"Changed in this turn" card
> - The benefit is that a reviewer can check every change in the
conversation, with the same view for Codex and Claude

## Linked Issues or Issue Description

Refs #19252 (precedent: canonical `plan.updated` events as a docked plan
card).

**Subsystem affected**
Paperclip runner (Rust and TypeScript canonical event mapping), PRP
provider-event schema, and the task-chat UI.

**Problem or motivation**
Edit rows say "Edited a file" with no content. Claude Edit/Write `diff`
content is lost after the ACPX sidecar. The Codex native runner drops
`fileChange.changes` and `turn/diff/updated`. The existing
workspace-changes card showed a raw text patch in a dialog, and only on
the in-process Codex path.

**Proposed solution**
Add an optional, bounded `fileChanges` list to
`paperclip.tool.execution.v1`. Fill it from Codex `fileChange` items and
Claude ACP `diff` content. Map Codex `turn/diff/updated` to
`workspace.change.updated` on the native runner. In the UI, show `+N −M`
on each edit row, open a compact colored diff, and end the turn with the
change set.

**Alternatives considered**
A runner-side git diff at turn end. It needs workspace access and extra
cost on every turn. The harness patches are already available. For
Claude, the UI builds the turn card from the edit rows instead of new
per-turn runner state.

## What Changed

- Protocol: optional `fileChanges[]` on `toolExecution` in
`provider-event.schema.json`, with the regenerated schema bundle,
validators and manifest. Paths are workspace-relative. A patch is at
most 32 KiB, and a call has at most 32 files.
- Runner (Rust): new `tool_file_changes.rs`. A Codex `fileChange` item
now also emits `tool.execution.*` with `fileChanges`; the native item
event stays for the recovery and progress projections.
`turn/diff/updated` becomes `workspace.change.updated`.
`normalize_acpx_tool_call` re-validates the sidecar's `fileChanges`.
`normalize_codex_notification_in` resolves absolute paths against the
session cwd.
- Runner (Rust): `has_bounded_rich_display_shape` accepts schema-valid
workspace diffs. Without this change, durable storage cut each patch
string to a 4 KiB preview. Patches use the uncapped secret redactor.
- Runner (TS): new `tool-file-changes.ts`. The ACPX sidecar computes
`fileChanges` from ACP `diff` content with the working directory. The
in-process Codex and ACPX mappers do the same, with an optional
`context` argument.
- UI: new `TaskChatDiffView` (colored rows, hunk labels, a height cap,
"Show N more lines"). Edit rows show counts and the diff. Collapsed
activity groups show edit totals. The workspace card is now "Changed in
this turn", with in-place per-file diffs, and it sits at the end of the
turn. When a harness sends no whole-turn diff (Claude), the card is
built from the edit rows. A change set is marked complete when its run
ends.
- UI: `native-run-events.ts` maps `workspace.change.updated` and
attaches each edit's latest patch to its row (the `diff` transcript
entries now carry `toolUseId`).
- Design tokens: `--diff-add-*`, `--diff-remove-*` and
`--sz-edit-diff-max-h` come from the status icon hues.
- Storybook: `Tasks/Edit diffs` story. Docs: `doc/run-log-events.md`.

## Verification

- Real runs on a local instance (`test-drive`, native runner):
- Codex (`gpt-5.6-sol`): the "Applied a patch" rows show `+9` and `+35
−2` with their diffs. The turn ends with "Changed in this turn", 2
files, `+42`, from `turn/diff/updated`.
- Claude (`claude-opus-5-5` via ACPX): the Write and Edit rows show
`+5`, `+14 −1` and `+9` with correct hunks. The turn card is built from
the edit rows.
- Codex model note: with `gpt-5.4`, pinned Codex 0.160 reports "model
metadata not found". The model then wrote files through the shell, so no
`fileChange` items occurred.
- `pnpm check:token-gates`: all gates clean.
- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat src/components/transcript src/adapters`: 1073
passed.
- `packages/paperclip-runner`: `vitest run src/provider-events.test.ts
src/tool-file-changes.test.ts src/cli/acpx-runtime-sidecar.test.ts`
passed. `check:protocol-types` and `check:protocol-manifest` match.
- `cargo test -p paperclip-runner-core --lib provider_events
tool_file_changes`: passed. `cargo fmt --check`: clean.
- Storybook: open `Tasks and conversations/…/Tasks/Edit diffs`.

## Risks

- Larger payloads: an edit call can carry up to 96 KiB of patch in Rust,
and the sidecar keeps 48 KiB under its 128 KiB frame. Above the budget,
a file keeps its counts and drops its patch (`diffTruncated`).
- Redaction: each patch goes through the shared secret redactor. Before
this change, a 4 KiB preview cap also applied.
- Claude turn card: it joins each edit's patch in order. It is not a net
diff. For a file the turn created, the counts are net and exact. For an
existing file, the counts are summed over its edits.
- The workspace card moves to the end of the turn. One adapter test
changed to match.
- Local only: four Linux cgroup `task_memory` Rust tests fail on macOS.
They do not touch these modules.

## Model Used

Claude Opus 5.5 (`claude-opus-5-5`), via Claude Code with tool use
(shell, browser and file editing) and a long context window.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 17:39:07 +00:00
DottaandClaude Opus 5.5 d8c47159d4 feat(task-chat): show Codex reasoning summaries as headline bullets (#19271)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The task chat shows what an agent does while it runs, including a
"Thinking" row for provider reasoning
> - Real Codex runs produced reasoning items with no text
> - So the Thinking row only says "Thinking" and never tells the user
what the agent works on
> - This pull request asks Codex for its own reasoning summaries, keeps
every summary part, and shows the parts as bullets
> - The benefit is that a user can see what the agent is thinking about,
and a collapsed live run shows the newest headline as its status line

## Linked Issues or Issue Description

Refs #19252 (same pattern: show a harness signal that Paperclip already
receives)

**Subsystem affected**
Native runner (Rust runnerd Codex provider and event normalization, JS
Codex driver) and the task chat UI (Thinking row and activity rows).

**Problem or motivation**
Codex 0.160 resolves an unset reasoning summary from the model, and
current models resolve it to `"none"`. The rollout of a real gpt-5.6-sol
run records `turn_context.summary = "none"`, and all of its reasoning
items have `summary: []`. A local A/B with `codex exec` proved the
cause: `model_reasoning_summary=none` gives no reasoning text, and
`auto` gives headlines. Also, runnerd dropped `item/reasoning/*`
notifications and ignored the reasoning item's `summary[]`.

**Proposed solution**
Send `summary: "auto"` on Codex `turn/start`. Map
`item/reasoning/summaryTextDelta` and `summaryPartAdded` to reasoning
deltas, with a blank line before each later part. Use the joined
`summary[]` as the completed item text. In the UI, split the provider
text at headline lines and show one bullet per part.

**Alternatives considered**
Use `summary: "detailed"`. That gives longer text, but `auto` lets the
provider choose the best summarizer.

**Roadmap alignment**
This makes existing provider signals visible. It adds no new protocol
event type or data model.

**Additional context**
Research note: overlooked harness signals, item 2. Claude is out of
scope here. A live Claude run showed thinking blocks with signatures and
empty text: current models default `thinking.display` to `"omitted"`.
Claude Code ignores the `showThinkingSummaries` setting in SDK mode, and
ACPX does not forward a `thinking` option, so the fix needs a
claude-agent-acp patch hunk. That patch is also changed by #19264, so
the Claude change follows after #19264 merges. The UI in this PR already
shows prose-only (Claude) summaries.

## What Changed

- Rust runnerd (`codex_provider.rs`): send `summary: "auto"` on every
Codex `turn/start`.
- Rust runnerd (`provider_events.rs`): map
`item/reasoning/summaryTextDelta` and later `summaryPartAdded` to
`item.delta` with `kind: "reasoning"` and `channel: "summary"`. Use the
joined `summary[]` as a completed reasoning item's text.
- JS Codex driver: send `summary: "auto"` on direct app-server
transports, map `summaryPartAdded`, and read `summary[]` in `itemText`.
- UI: new `reasoning-summary.ts` splits provider text into headline
sections, and `TaskChatReasoningSummary` shows one bullet per part. The
Thinking row and the activity row use the newest headline as their
one-line status. Prose-only summaries (Claude) stay as prose.
- Storybook: new "Task chat reasoning summaries" story with live,
expanded, finished and Claude states.
- Tests: Rust normalizer test, JS driver test, and splitter unit tests.

## Verification

- `cargo test -p paperclip-runner-core` (provider events and the shared
identity golden).
- `pnpm --filter @paperclipai/paperclip-runner exec vitest run
src/drivers/codex`
- `pnpm --filter @paperclipai/ui exec vitest run
src/components/task-chat src/components/transcript`
- `pnpm check:token-gates`
- Live test on a local worktree instance with a real Codex agent
(gpt-5.6-sol). The Codex rollout now records `summary: "auto"`. Run
events contain `**Assessing transaction boundary issues**`, a part
break, and `**Planning atomic claim fix and verification**`. The task
chat shows "Thought · Planning atomic claim fix and verification", and
the expanded row lists both headlines as bullets.
- Storybook: open "Tasks and conversations / Task creation and lifecycle
/ Tasks / Task chat reasoning summaries".
- Claude was not changed. A live Claude run confirmed the cause for the
follow-up (empty, signed thinking blocks).

## Risks

- Codex now writes reasoning summaries, which adds a small number of
output tokens per turn. This is the same cost as Codex CLI with its
normal default.
- The UI treats a line that is only bold text as a headline. A prose
line that is only bold text also starts a new bullet. This is display
only.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use,
code execution and browser automation. Default context window.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 11:21:50 -06:00
DottaandClaude Opus 5.5 b0fa2ef9bf feat(task-chat): show web searches, model switches, waits and verification checks as dedicated rows (#19262)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents run through the native runner. The runner turns harness
activity into typed canonical events such as `research.*`,
`model.route.changed`, `wait.*` and the run's own verification checks.
> - The task chat flattened these events into generic tool rows. A web
search showed as "Ran Research eventType: research.started, summary: …".
The run's verification checks were dropped completely.
> - Live tests found a second break: the Rust runner core forwarded
Codex `webSearch` items without their query, action or results. The
canonical `research.*` events therefore had `query: null`.
> - This pull request keeps the full payload for these families (as
#19252 did for plans), adds small dedicated rows, and keeps the
web-search fields through the durable runner.
> - The benefit is that users see what the agent searched for, which
model actually ran, how long a wait lasts, and whether each check
passed, without opening the run log.

## Linked Issues or Issue Description

Refs #19252 (same pattern for the plan card)

**Subsystem affected**
Task chat activity rows (UI), the native run-event transcript mapping,
and the Rust runner core Codex normalizer.

**Problem or motivation**
Provider activity that the runner already maps to canonical events
reaches the task chat as unreadable generic rows. Verification checks
never appear. For Codex, the web-search query and action are lost before
they reach the canonical event.

**Proposed solution**
Keep `research`, `model_identity`, `artifact`, `review` and `wait`
events as `provider_activity` entries with their full payload. Project
the runner's `verification` items as a new `verification` family. Render
dedicated rows: a web search with its quoted query and source-domain
chips, a model switch as `from → to · reason`, a wait with a live
countdown, and green/red check lines. Keep bounded web-search and sleep
fields in the Rust normalizer.

**Alternatives considered**
A separate "Checks" block beside the final answer. We kept the checks in
the activity group, because the group summary already leads with "Check
failed" when a check fails.

## What Changed

- `ui/src/components/transcript/native-run-events.ts`: keep research,
model, artifact, review and wait events as `provider_activity` with the
full payload. Map `item.completed` items of kind `verification` to the
new `verification` family. Context, hook, safety and delegation stay on
the generic path, because other work items own them.
- `packages/adapter-utils/src/types.ts`,
`ui/src/components/task-chat/task-chat-model.ts`,
`ui/src/lib/issue-chat-messages.ts`: add the `verification`
provider-activity family.
- `ui/src/components/task-chat/task-chat-activity-presentation.ts`: add
labels: "Searched the web “query”", "Opened a web page host/path",
"Switched models a → b · reason", "Waiting 30s" / "Waited 30s", and
"Check passed" / "Check failed" / "Check not run".
- `ui/src/components/task-chat/TaskChatRunnerActivityGroup.tsx` and
`TaskChatProtocolActivityRow.tsx`: show up to three source-domain chips
under a finished search, a live countdown for a running wait, and a
check line with a tinted icon and its detail.
- `ui/src/components/task-chat/completed-activity-summary.ts`: the group
summary leads with "Check failed" when a check fails, and says "Switched
models" for a reroute.
- `ui/src/components/task-chat/transcript-adapter.ts`: verification
detail keys, and a `startedAt` timestamp that stays across lifecycle
merges (used by the countdown).
-
`packages/paperclip-runner/runner/crates/runner-core/src/provider_events.rs`:
keep bounded `query`, `action` and http(s) `results` for Codex
`webSearch` items, and `durationMs` for `sleep` items. Other item types
do not change.
- `ui/storybook/stories/tasks/task-chat-provider-activity.stories.tsx`:
new story. Its fixtures are persisted run events that go through the
production transcript path.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/transcript src/components/task-chat
src/components/TaskChatThread.test.tsx src/adapters/paperclip-runner
src/lib`: 275 files and 3669 tests pass.
- `cargo test -p paperclip-runner-core`: all tests pass, including the
new `keeps_bounded_web_search_and_sleep_identity`.
- UI typecheck is clean. `pnpm check:token-gates` is clean. `cargo fmt
--check` is clean.
- Storybook: open "Tasks and conversations / … / Task chat / Provider
activity". It shows a settled run, a live search, a live wait countdown
and a narrow layout.
- Live test on a local worktree instance with a real Codex agent
(gpt-5.6-sol, Codex app-server 0.160). The task asked for a web search,
a parser with tests, a pause, and two checks. The task chat showed
"Searched the web “ISO 8601 week date first week Thursday conversion
calendar date”" and two green check rows ("node --test week-date.test.js
· 8 tests passed; 0 failed.", "node --check week-date.js"). The group
summary read "Ran checks". Before the runner fix, the same search had
`query: null`.

Not verified live:
- The source-domain chips. Codex 0.160 sends `results: null`, because it
keeps search results on the server. The chips appear only when a
provider reports sources. Unit tests and the story cover them.
- The wait countdown and the model-switch row. In the live run Codex
paused with a shell `sleep`, not a native `sleep` item, and no reroute
occurred. Unit tests and the story cover both.
- Claude. Its WebSearch and WebFetch calls arrive as generic tool
executions, because ACPX drops the tool metadata. They show as tool
rows, as before. The ACPX `_meta` work is separate.

## Risks

- Low risk. The change only affects how canonical events display. The
generic path stays for the families that this PR does not change.
- The Rust normalizer now persists the web-search query and the source
URLs/titles in the run events. This data was already intended for the
canonical `research.v1` event, and it is bounded (4,000 characters per
text field, 64 results, http(s) URLs only).
- A search that Codex reports with `action: other` and no query shows as
"Searched the web" with no subject.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use
(shell, file edit, browser automation) and extended reasoning.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 16:37:05 +00:00
DottaandClaude Opus 5.5 8227259d86 feat(task-chat): show the agent's native plan as a task list above the composer (#19252)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents run through the native runner. The runner turns each
harness's native plan into a canonical `plan.updated` event.
> - The task chat did not show these plans. A small "Step 2 / 5" pill
showed the checklist only on hover, and in live runs it received no plan
data.
> - Live tests found three breaks. The UI flattened `plan.updated` into
tool rows. Headless Claude Code hides its task tools from current
models. Codex ships its `update_plan` tool disabled.
> - This pull request fixes the three breaks and replaces the pill with
a docked plan card above the composer.
> - The benefit is that users see what the agent finished, what it does
now, and what comes next. The view is the same for Claude, Codex, Grok
and Copilot.

## Linked Issues or Issue Description

**Subsystem affected**
Task chat UI (turn status island), native runner ACPX launch environment
for Claude, and native runner Codex app-server launch arguments.

**Problem or motivation**
Harnesses report native plans, and the runner records them as
`plan.updated` events. Users do not see them. The live transcript
builder converts `plan.updated` into generic tool rows, so the plan
steps are lost. Claude Code in headless mode does not offer
TaskCreate/TaskUpdate for current models, so Claude never makes a plan.
Codex 0.160 has `update_plan` disabled by default, so Codex writes its
checklist into a Paperclip document instead.

**Proposed solution**
Keep the full plan snapshot in the live transcript. Enable the Claude
task tools with `CLAUDE_CODE_ENABLE_TODO_TOOLS=1` in the ACPX launch
environment. Enable the Codex plan tool with
`tools.update_plan.enabled=true`. Show the plan as a docked card with
clear rules for when it shows, collapses and hides.

**Alternatives considered**
Show the plan only in the hover popover (the old behavior). Users did
not find it. Write the plan into the issue Plan document. That mixes a
per-turn checklist with the reviewed planning document.

**Roadmap alignment**
This makes existing native runner plan events visible. It adds no new
protocol or data model.

**Additional context**
Grok and Copilot needed no harness change. Cursor could not start in a
local worktree instance (an unrelated startup admission problem), so
this PR does not verify Cursor.

## What Changed

- `ui/src/components/transcript/native-run-events.ts`: keep
`plan.updated` as `provider_activity` with family `plan` and the full
payload, not as a tool row.
- `ui/src/components/task-chat/TaskChatTurnStatusIsland.tsx`: replace
the hover pill with a docked plan card. It shows done, current, upcoming
and blocked steps, a progress bar and file-change totals.
- Visibility rules: hidden with no steps and after the run ends;
collapses when all steps are done; header only for one-step plans and
while a question or approval is pending; window around the current step
for plans over 7 steps; collapsed by default on mobile.
- `ui/src/components/TaskChatThread.tsx`: pass `defaultCollapsed`
(mobile) and `compact` (pending runtime request), and reset the card per
run.
- `ui/src/components/task-chat/transcript-adapter.ts`: keep the `failed`
step status.
- `packages/paperclip-runner/src/drivers/acpx/environment.ts`: set
`CLAUDE_CODE_ENABLE_TODO_TOOLS=1` for Claude launches. A host value
cannot turn it off.
-
`packages/paperclip-runner/src/drivers/codex/codex-security-config.ts`:
add `-c tools.update_plan.enabled=true` before the policy overrides and
the `app-server` subcommand.
- `ui/storybook/stories/tasks/task-chat-agent-plan.stories.tsx`: new
story for each state. It uses the production composer dock, composer and
question takeover.
- Tests for all of the above. `ui/src/index.css` replaces the unused
popover size token with a list max-height token.

## Verification

- `pnpm --filter @paperclipai/ui exec vitest run
src/components/transcript src/components/task-chat
src/components/TaskChatThread.test.tsx src/adapters/paperclip-runner`
(1345 tests pass).
- `pnpm --filter @paperclipai/paperclip-runner exec vitest run
src/drivers/acpx/environment.test.ts src/drivers/codex` (pass).
- UI and runner typecheck are clean. `pnpm check:token-gates` is clean.
- Storybook: open "Tasks and conversations / … / Task chat / Agent
plan". The "All States Gallery" story shows every state. "Live Run
Simulation" animates a run.
- Live test on a local worktree instance with real API keys: a
multi-step task for each harness. The card showed and updated during the
run for Claude (Opus 5.5), Codex (gpt-5.6-sol), Grok (grok-4.7) and
Copilot (gpt-5.6-luna). For Claude the card collapsed when all steps
were done and hid after the run ended.
- Codex probe: `codex exec` with the pinned 0.160 binary reports no
`update_plan` tool by default and reports the tool with `-c
tools.update_plan.enabled=true`.

## Risks

- Claude and Codex now get their plan tools. Agents can spend a few
tokens on plan updates. The tools are standard harness features.
- The Codex flag goes before the web-search and project-instruction
policy overrides, so the existing policy tail check still holds.
- Runs that finish fast show the card only briefly. This is the intended
hide rule.
- Cursor plan display is not verified.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use
(shell, file edit, browser automation) and extended reasoning.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 09:09:39 -06:00
a3313f6944 fix(ui): complete read recovery and enforce query error rendering (#18822)
## Thinking Path

> - Paperclip lets people manage agent work through the board.
> - The board reads task, agent, settings, plugin, and run data from the
server.
> - A deploy can interrupt those reads after content is already visible.
> - Local error branches can replace that content with an error or show
raw codes.
> - This pull request moves the remaining reads to the shared recovery
behavior.
> - The query-error guard prevents new local error patterns from
returning.

## Linked Issues or Issue Description

**What happened?**
Loaded lists, settings, task panels, and manual reads could clear their
content or show errors during a server restart. Some reads also disabled
the shared retry policy.

**Expected behavior**
Keep loaded content during a temporary failure. Show the shared
connection banner. Retry reads after recovery. Replace content after a
real access denial or missing resource, with readable copy.

**Steps to reproduce**
Open a task, settings page, or run log. Return 503 with
`tenant_app_unavailable` from the API. Restore the API and check that
content refreshes. Repeat with 403 and 404 to check the failure state.

Related merged work: Refs #15754, Refs #15772, Refs #17960. This change
covers remaining reads and enforcement. Browser persistence and the
outage browser suite follow separately.

## What Changed

- Repair an existing PostgreSQL deadline fixture at UTC boundaries. A
daily cap defers a heartbeat until both its original interval and the
next UTC day allow it. Keep the counted run in its seeded day and cover
noon, just before midnight and the first second after midnight with
explicit clocks and real PostgreSQL. Production scheduling is unchanged.

- Integrate the saved list, settings, shell, task, and manual-read
recovery changes against current master. Preserve the current task,
Inbox, and run-log structure.
- Add `useResilientFetch` for component-local reads. Preserve loaded
data, cancel stale requests, and retry through the shared connectivity
policy. Keep browser and pairing capabilities in memory.
- Retain run log chunks across stream changes and catch up after
recovery without duplicate chunks or stalled requests.
- Keep genuine authorization and missing-resource failures visible.
Translate known single-word codes such as `forbidden`. Show known skills
and disconnected-app failures before sibling loading states. Keep Retry
bound to its failed request.
- Make the query-error guard enforce by default and run it in the CI
policy job. Document the narrow exceptions and the read recovery
contract.
- Invalidate pending OAuth discovery when the operator leaves setup or
its context changes. Keep reserved-popup cleanup bound to the current
attempt.

## Verification

- Current read head `09d1db29dea` is merge-ready: all 59 check runs are
completed (54 successful, three skipped, two neutral), the legacy Snyk
status is successful, and both required `ci / verify` and `ci / e2e`
gates pass. Greptile Apex reviewed this exact head at 5/5 with no
unresolved threads; the branch has no merge conflicts. The current CI
run is `41748339602`.
- Current read head `09d1db29dea` includes master `683fa4725e9`. The
latest change touches only the existing server deadline test fixture.
Application source remains the previously verified `86376fa751e`
revision: all 60 affected skills/disconnected-app tests and both
application UI typechecks passed, along with token gates and the
enforcing query-error guard. Those UI suites were not repeated for this
test-only repair.
- The fixture repair passes all seven deadline integration cases and the
complete server typecheck, including the server test layer. The old
assertion deterministically fails at 23:59:06.888 UTC; its
one-second-old run also fails the first-second-of-day probe. The
corrected fixture passes noon and both midnight probes. The permanent
three-case coverage uses seeded 2099 clocks.
- Twelve new regressions fail against the previous implementation. Both
skills variants and disconnected-app pages show either request's 403 or
429 while the sibling pauses or remains fetching. Permission failures
stay visible. Retry stays usable for its failed request and recovers
independently. An initial test-fixture query-key typo was corrected
before the passing run. The finding is replied to and resolved. Greptile
reviewed prior application revision `86376fa751e` at 5/5 with no new
actionable findings or unresolved threads. The current test-only head
has now received its own Apex 5/5 review with no unresolved threads, and
its CI is successful as recorded above.
- The preceding OAuth fix passed all 237 setup tests on both application
branches. Its ten regressions prove that Back, Cancel, unmount, or
context changes retire initial discovery without creating a connection,
caching old identities, navigating an abandoned popup, or closing a
newer attempt.
- Earlier master integration `e992f770339` passed all 309 tests across
eight affected Slack, recovery, retry, submission and task files, plus
UI typecheck, token gates, enforcing query-error scan and seven guard
tests. The integration preserves Slack workspace reconnect and shared
recovery, readable execution errors, source-inspection company scoping,
and current submission behavior. Newly inherited retained-file recovery
controls keep cached data through transient failures and hide it after
definitive denial.
- The preceding cache head `97c0bc3966f` passed 1,038 focused
cache/write/editor/account/task/API tests. All 22 built-UI
outage/write/loading cases passed in 4.7 minutes on exact browser head
`b7deaaee5da`, with strict checking of all three specs. The latest
skills/app rendering fix is covered by its affected component suites;
those broader cases were not repeated for this separate read path.
- Historical broader UI, CLI and build results and unresolved aggregate
server/DB/adapter failures remain in the PR discussion. Interrupted CI
runs were audited and recorded separately; they are not counted as
passes. Controlled local outages do not prove hosted authentication or a
real Cloud restart/deploy. Real hosted acceptance remains required after
merge and deployment.

Commands for the latest fix:

```sh
pnpm --filter @paperclipai/ui exec vitest run src/pages/CompanySkills.test.tsx src/pages/apps/AppNotConnected.test.tsx
pnpm --filter @paperclipai/ui typecheck
pnpm check:token-gates
node scripts/check-query-error-rendering.mjs --enforce --summary
```

## Risks

This migration touches many read surfaces. The main risks are initial
loading, request cancellation, retained authorization state, and run-log
paging. The tests cover those states. There are no server, schema,
dependency, or API contract changes. The follow-up browser suite and
hosted deploy acceptance are required before release acceptance.

Recovered commits retain their original authors. If squash-merging,
preserve `Co-Authored-By: Bender (Fable) <bender@agents.paperclip.ing>`
and the Paperclip trailer.

## Model Used

OpenAI `gpt-6.1-sol` through Codex, with xhigh reasoning effort, tool
use, and code execution. The context window size is not exposed. Saved
source commits keep their original authorship.

## 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 described the issue in-PR following the bug report template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] The affected local tests pass; broader limitations are recorded
above
- [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 risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Bender (Fable) <bender@agents.paperclip.ing>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-04 14:07:18 -08:00
Dotta c6cb7e2a2d fix(ui): accept file drops across task and new-task views (#18849)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People add images and files through task message composers.
> - A file drop requires a small target inside the composer.
> - A screen-wide target makes this action easier.
> - Task pages and new-task dialogs use the same composer.
> - This pull request adds one shared file-drop target.
> - The open dialog receives the drop when it covers a task page.

## Linked Issues or Issue Description

Refs #13206. This improves the task composer drop area.
Related PRs: #18689 adds image previews. #15964 adds direct uploads in
the Artifacts panel.

**What existing behavior does this improve?**

Image and file drops in the task composer and new-task dialog.

**Current behavior**

People must drop a file into the composer area.

**Proposed behavior**

People can drop a file anywhere on the screen when an available composer
is present. A full-screen overlay shows the destination.

**Reason and benefit**

People can add an image without aiming at the text field.

**Subsystem affected**

React board UI.

**Breaking changes**

The available composer captures file drops across the screen. Text and
link drags retain their current behavior. Upload rules and APIs stay the
same.

**Additional context**

ROADMAP.md lists task discussion and attachments as existing features.
This change improves their input area.

## What Changed

- Add a shared screen-wide drop target to the task composer.
- Give an open task dialog exclusive ownership of file drops. Keep file
drops available while a model or assignee picker is open.
- Give explicit editor, task attachment, and Artifacts drop areas
priority over the screen-wide composer target. Share one marker for
these areas.
- Keep image and file uploads in description, question, and protocol
editors. Read-only editors and editors that delegate uploads to a parent
keep the composer fallback.
- Prevent browser navigation from file drops while the active composer
is read-only.
- Use the existing file staging and upload callbacks.
- Disable drops during pause, queued message edits, uncertain sends,
submission, and read-only states.
- Exclude hidden and inert composers.
- Clear the overlay after drop, drag exit, cancellation, window blur,
and unmount.
- Add component tests and two Storybook drag-over examples.

## Verification

- 316 tests passed across the drop target, real MarkdownEditor, task
composer, new-task dialog, and Artifacts tab. Tests cover image and
text-file drops in a real editor, overlay reset, parent and read-only
editors, and task attachments.
- Two new cases failed before the editor and attachment fixes. Both
passed after the fixes.
- An earlier expanded run had three new-task upload assertion failures.
The five affected cases passed on the unchanged implementation in
isolation. The expanded run then passed all 316 tests. The cause of the
earlier failures remains unverified.
- UI typecheck and UI production build passed. The first typecheck
attempt lacked plugin SDK declarations. Building the SDK restored these
declarations; typecheck then passed.
- Design-token gates, Storybook catalog generation, and whitespace
checks passed.
- Chromium checks from the design review confirmed one image per screen
drop in each view. The editor stayed empty and the overlay cleared.
These checks used local Storybook fixtures.
- The requested screenshots were accepted before this PR was opened.
- Full repository typecheck and build were attempted. Both stopped in
the native Runner package because this environment has no cargo
executable.
- The full repository test run was attempted. It was stopped during the
first chat integration shard before a full-suite verdict. The focused UI
suite passed.
- The first CI attempt did not complete. Typecheck and build logs report
runner shutdown signals. Most browser shards were cancelled; their logs
could not be retrieved. No complete CI verdict is available. The new
commit starts a fresh CI run.
- Review findings about Artifacts drops, portaled pickers, read-only
drop navigation, and editor drop ownership are fixed. Current-head CI
and review are pending.
- The previous CI run passed build, typecheck, general tests, and six
browser shards. Browser shards 5/8 and 8/8 failed. Their logs returned
BlobNotFound; the causes remain unverified. The new commit starts a
fresh CI run.

Manual check: open a task, drag a PNG over the page header, and drop it.
Confirm one image preview. Open a new-task dialog over the task and
repeat. Confirm the file appears only in the new task. Cancel the drag
and confirm the overlay clears. Open the description editor. Drop an
image and then a text file into it. Confirm each upload stays with the
description and does not enter the chat draft.

## Risks

- Screen-wide file capture changes which surface receives file drops.
- Dialog ownership and disabled-state tests limit unintended uploads.
- No server, API, database, or migration changes are required.
- Full repository acceptance still requires the native Rust toolchain
and CI results.

## Model Used

OpenAI GPT-6 through Codex. The exact runtime snapshot ID and
context-window size were not exposed. Capabilities used: repository
inspection, code editing, shell commands, and browser automation.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-11-04 15:41:48 -06:00
DottaandPaperclip 54782706e1 fix(ui): render confirmation prompts as Markdown (#18851)
## Thinking Path

> - Paperclip helps people manage work by AI agents.
> - People use confirmation cards to review work before an agent
continues.
> - A prompt can include a Markdown link to the work that needs review.
> - Confirmation cards showed that link as text, which made review
harder.
> - The details section already uses the shared Markdown renderer.
> - This pull request uses that renderer for confirmation prompts too.
> - People can read formatted prompts and open their review links.

## Linked Issues or Issue Description

**What happened?**

Confirmation prompts show Markdown links as text in the task composer
and classic cards. Checkbox confirmations and expanded receipts have the
same problem.

**Expected behavior**

Render links, emphasis, code, lists, and paragraph breaks with the
shared Markdown renderer.

**Steps to reproduce**

1. Create a confirmation with this prompt: `Review the [two
screenshots](/issues/EXAMPLE-42#document-preview).`
2. Open the request above the task composer.
3. Observe the raw link text. Expect a link with the label “two
screenshots”.

**Paperclip version or commit**

Source checkout at `1f55073f9`.

**Deployment mode**

Built from source. The defect is in the shared board UI.

Related work: #17014 covers question prompts. This change covers
confirmation prompts.

## What Changed

- Render confirmation and checkbox prompts with `MarkdownBody` in
compact and classic cards.
- Keep prompt images as references and Mermaid diagrams as source text.
- Use the rendered checkbox prompt as the options group’s accessible
name.
- Use the same renderer in expanded confirmation receipts.
- Pass external link metadata to the prompt renderer.
- Add eight regression cases for document links, emphasis, code, lists,
paragraphs, and inert media. Check the checkbox group’s accessible
label.
- Replace CSS-specific paragraph checks with checks of the rendered
paragraphs.
- Document the prompt rendering rule in `DESIGN.md`.

## Verification

- Before the initial fix, all eight new regression cases failed because
the document link did not render. Before the review fix, the same cases
also proved that prompt images were live. Both defects are fixed.
- After the fix, 180 tests pass across the two card suites and two
Markdown suites.
- `pnpm check:token-gates` passes.
- `pnpm --filter @paperclipai/ui... build` passed for the initial
change. `pnpm --filter @paperclipai/ui build` passes after the review
fixes.
- Full `pnpm -r typecheck` and `pnpm build` could not complete. The
workspace does not have Rust `cargo`.
- `PAPERCLIP_TYPECHECK_LOW_MEMORY=1 pnpm --filter @paperclipai/ui
typecheck` passes. The first UI typecheck hit the workspace memory limit
before this successful retry.
- Full `pnpm test:run` started but did not complete locally. It was
stopped during the first chat integration shard when the task moved to a
scheduled CI check. No full-suite pass is claimed. GitHub CI runs the
full checks.
- Browser suites were not run locally. In the first CI run, build and
full typecheck passed. Server shard 8/12 and browser shards 1/8 and 7/8
failed because their self-hosted runners lost communication. Other jobs
were cancelled. See [the first CI
run](https://github.com/paperclipai/paperclip/actions/runs/41713671579).
The current head has fresh 5/5 reviews from Greptile and Paperclip. On
the first attempt of [the new-head CI
run](https://github.com/paperclipai/paperclip/actions/runs/41717410154),
the Runner package test job received a shutdown signal. One unchanged
CloudAccessGate test also failed: the reconnect banner was absent at its
assertion. Its root cause is not confirmed. The latest attempt of that
run passed on commit `591078ca568056369ee9067c9535845bd47d8dc1`. Build,
full typecheck, all test shards, all eight browser shards, and `ci /
verify` passed. The earlier assertion failure remains part of the
record; its root cause is not confirmed. All 58 current-head check runs
are complete: 54 passed, one review is neutral, and three checks were
skipped. The Snyk status passed. No review threads remain open.

## Risks

- Prompts use the shared Markdown and URL handling. Prompt images remain
inert, and Mermaid diagrams display as source text.
- Rich prompts can take more vertical space than plain text.
- Existing plan previews, selection rules, and approval callbacks remain
covered by the card tests.
- This change does not require an API or database migration.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, tool calls, and code
execution. The runtime does not expose the exact model ID or context
window size.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-03 17:06:39 -06:00
DottaandPaperclip 1f55073f96 fix(cursor-cloud): support API-only controllers on managed stacks (#18310)
## Thinking Path

> - Paperclip helps people manage AI agents at work.
> - Cursor Cloud hosts execution behind its API.
> - Product setup still expected a Paperclip Computer.
> - Managed-only tenants therefore rejected valid setup.
> - This admits the validated API-owned controller.
> - Authority, Stop proof, budgets and cleanup remain enforced.

## Linked Issues or Issue Description

Refs #18068 and #18069; both dependencies have merged.

**What happened?**

Managed-only setup still requested a Computer. Live tests exposed
missing Cursor Stop proof and duplicate replay.

**Expected behavior**

Use Cursor’s API controller. Verify provider/controller termination and
replay each log identity once.

**Steps to reproduce**

Enable native Runner/managed-only. Configure Cursor model/repository/key
without a Computer, then Test, finish setup, run and Stop.

## What Changed

- Derive API-only placement from validated native Cursor configuration;
reject placement/command/workspace/home overrides and keep
Kubernetes-only execution closed.
- Skip Computers/checkout/workspace realization. Keep scoped tools,
completion, private staging, budgets, leases and recovery. Persist
placement; reject contradictions.
- Align Cloud cards, Test, Save and Finish setup; hold unready drafts.
Legacy keeps its Computer, credential and policy checks.
- Verify Stop from exact API ownership, audited intent,
provider-terminal proof, no Computer/process ownership and controller
retirement. Recheck immediate/deferred retirement; wake existing
recovery on durable evidence.
- Clear warnings when the actual stopped target later has authoritative
confirmation. Keep missing/other-run negatives and the existing
predicate.
- Publish safe status refresh after full-proof ACK. Retain bounded
native/physical cancellation history; add no poller or weaker proof
path.

## Verification

Core merged as `3910352c923a`; Product merged as `27d35314be8e`. Public
branch `5f86eb66b081` has tree `67344151d303`. Its exact-head Greptile
summary is 5/5; the fresh audit found zero unresolved threads and
complete pagination. The controlled workspace retry and required summary
passed. All 59 current-head contexts are terminal and clean. Prior
green-36 evidence keeps its identity.

[Current
CI](https://github.com/paperclipai/paperclip/actions/runs/41680511731)
first failed workspaces-a 1/2: the CLI company-import/export beforeAll
30-second runtime-info/child-PID/HTTP readiness wait expired. All 431 UI
files/4,714 tests and 285 other CLI tests passed (one skip). The cause
remains UNKNOWN. Child output records startup recovery complete, but
buffered CI prefixes do not establish its relation to the waiter
deadline; runtime-file/PID/last-health state was not captured. Both
unchanged local probes were RED. The second observed dependency
preflight still pending at the deadline; observer overhead was not
quantified. Neither proves the CI cause. After all functional jobs
finished, only the queued metadata summary was cancelled; the other 48
records stayed unchanged. Attempt 1 retains 46 successes, the original
failure, one skip and the cancelled summary. One same-head debug retry
was admitted at 18:42 UTC on November 3. Its workspace job passed at
19:23 UTC on the same checkout: UI 431 files/4,714 tests and CLI 33
files/286 tests, including company import/export. Test caching was
disabled. The new `ci / verify` summary passed; workflow attempt 2
completed SUCCESS. Required `ci / e2e` also passed. The final check at
19:53 UTC on November 3 found all 59 current-head contexts terminal and
clean: zero pending and zero failing. The 47 inherited completed/skipped
rows are not new executions. No code, assertion or timeout changed;
success does not explain the original failure or erase the local REDs.

CI checkout is `1ea9d8608ced`/tree `78cb1ec13d59` (parents
`2e37c73c05fe`, 5f86); both workflows use 2e37. Its 20 extra paths add
low-memory build/Rust task-memory. Scripts cohere; later matrix changes
only labels, with no newer debug-cache steps. Static audit found no
blocker. Supported API arguments omit the memory flag: no default
monitor/instruction changes. Flagged external launchers can change
Cursor instructions/digests and remain unqualified.

The merge added 41 master-identical paths, retained the green-36 inbox
hunk and found UI fixtures matching upstream. Startup/backup, recovery
projection, sleep diagnostics and binary backup change production.
Static audit found eight Stop/ACK owner blobs and 37 sleep-work SQL
templates unchanged, with sleep fences/single-flight accounting intact.
Exact precommit tree: 416/416 across eight server files, binary backup
1/1, server types PASS; repeated scopes are not summed.

The deferred-retirement P1 reproduced three real-DB/owned-process
failures; missing proof stayed unverified. Recovery passed 47 process
cases/33 proof negatives. Warning repair binds actual targets to
same-run proof. Validation passed 729 scoped UI cases, a separate
359-case thread run, 111 backend cases (84 CAS, 6 assembled, 21
activity/privacy), types/tokens. Proof validators/predicate are
unchanged; no new poller or increased timeout.

The d8d3 attempt stays FAILED: 45 passes, two workspaces-a failures,
derived verify failure and one skip. Both shards shared three failures:
two successful mocks omitted the account guard’s required userId. The
two-line fixture repair changed no guard, assertion or timeout. Three
failures reproduced; 54 access/auth tests then passed, including
account-change/denial negatives, plus UI types/tokens.

The 69285 attempt stays FAILED: 49 jobs, 46 passed, serialized shard 9
failed, its verify aggregate failed and one selection job skipped. The
shard passed 575/576 cases. Its aborted-snapshot case expected nine
computes but saw eight: a final HTTP 200 coalesced while seven ordinary
reads had not proved the aborted compute settled. Earlier CI and the
unmodified local baseline passed with a miss; no local RED is claimed.
The repair awaits the snapshot, allows exactly one extra GET if
coalesced, then requires a miss and retains nine computes/all HTTP429
assertions. No production code, hook, loop, sleep or timeout changed.
Six inbox and seven cache/admission cases passed locally, plus server
types; 30 unrelated cases were filtered. Green 36 passed 576/576 without
taking the extra-GET branch; local runs also missed that schedule.
Current CI event merge 1ea9 now passed 576/576 and naturally exercised
the former failure: coalesced (count 2, 1ms), then exactly one fresh
miss (count 1, 16ms), with strict nine-compute/HTTP429 assertions
intact. No instrumentation or retry was added.

Earlier compatibility passed scoped remote/inbox, routine, API-placement
and UI tests, plus types/migrations/snapshots/maps/tokens. The 89-path
adoption restored fleet routing without workflow overrides or added
skips. Each result retains its source identity.

Live qualification remains actual `9af1a5de42a2`: unchanged Artifact
grader PASSED 17/17 and active-Stop grader PASSED 21/21. All three
provider test resources were deleted canonically with GET404;
post-delete download returned the exact 27 bytes. Histories stayed
stable (Artifact 121 and Stop 67 canonical identities), with 21 company
runs, zero active work and no accounting/cancellation/reservation debt
or integrity findings. Saved settings reopened; no-prompt Test/Linux
admission passed with `claude-sonnet-4-5`. No new Save is claimed.

The first Stop sampling case stays FAILED on a 10.373-second gap.
Unchanged retry kept all 24 samples: 35.076 seconds quiet, maximum gap
4.584 seconds, plus a separate CANCELLED/artifact-absent read after 180
seconds. Initial grading rejected locator spelling before functional
checks; metadata changed only after same-file/inode/byte proof, with raw
evidence/oracles unchanged. Original Question/Plan/reconnect and
historical deleted-artifact results keep their identities.

Git trees verified 11 history-only conflicts and six earlier mainline
paths. Hosted 9af to the public BRANCH differs in 222 paths; 13,500
other mode/blob leaves match. Runner runtime implementations and six
observer/driver pins match 9af on that branch only; inherited
`drivers/acpx/runtime-host.test.ts` differs. No all-Runner/src,
CI/latest-master runtime or image equality is claimed. Later static
audits through `8ab89f41e499` found no concrete API-only blocker. That
base adds completed-history sleep proofs and an MCP cleanup migration;
protected Stop/ACK owners are unchanged. These later changes are outside
this CI and have no live qualification here. Host duplicate-card and
later recovery/UI repairs retain separate proof, not deployed 9af
identity. Direct-key coverage requires absent aiConnection; API-only
placement skips inherited remote-workspace disk-full paths, and
config-read gates match their parent.

Other retained failures: stale fixture 132/133; E8 48/135 with 87
reset-hook failures; Mac 17 SQL failures/skips;
title/startup/custody/Stop/deletion unknown causes and bounded
recoveries; superseded warning/50 duplicate identities; pre-repair
ACK/Core CI failures. Fixture RED/GREEN passed 7/7 browser and 121/121
shutdown tests with a failing broken-unsubscribe control; stable WSP
wrapper passed 128 after physical teardown failure. No full local-suite
pass is inferred. All paid attempts remain recorded; vendor dollar cost
is UNKNOWN.

## Risks

Experimental: Cursor independently acknowledges neither the effective
model nor instruction digest before the first prompt. Explicit values
are submitted and behavior checked live; unpriced provider dollar cost
stays UNKNOWN.

The placement exception applies only to validated native Cursor API
execution. Other local work remains denied under managed-only policy.
Missing/stale Stop or cleanup proof stays pending; damaged archives
remain failed. Explicit Legacy keeps its existing policy owners.

## Model Used

OpenAI Codex/GPT-6 family: tools, execution, browser checks, delegated
review. API ID/context window unavailable.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used and the limits of available model
metadata
- [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 linked public issues or described the issue in this PR
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch describes the change and contains no internal ticket ID
- [x] I have run the scoped local tests reported above; retained
failures are stated separately
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented the risks
- [x] All required CI gates pass on the current head
- [x] Fresh Greptile is 5/5 with no unresolved findings on the current
head
- [x] I will address all reviewer comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-03 13:55:39 -06:00
DottaandPaperclip 27d35314be feat: connect experimental Cursor Cloud to native Runner (#18069)
## Thinking Path

> - Paperclip helps people manage AI agents at work.
> - Native Runner owns execution and task authority.
> - Operators need an explicit native Cursor Cloud choice.
> - Tools/files need company, task, session and run scope.
> - This connects setup and lifecycle to Runner Core.
> - Legacy agents retain their selected runtime/history.

## Linked Issues or Issue Description

Depends on #18068. Managed-only API placement and API-owned Stop
containment are in #18310. Refs #5664, #11803, #17299, and #17471. No
duplicate native integration was found.

## What Changed

- Add explicit native setup, Test, saved settings and dispatch with
no-prompt account/catalog/callback checks.
- Scope MCP to company, agent, task, session and run through
authenticated HTTPS. Register verified artifacts/work products; preserve
unpriced accounting, completion and budgets.
- Connect Question/Plan continuation, cold handoff and admitted fresh
sessions; recheck waiting admission under the task lock.
- Present audited Stop intent while preserving physical containment
proof; bound typed Stop metadata. Preserve title edits through
preference/navigation readiness.
- Select one live/history representation per run to prevent duplicate
settled cards. Integrate upstream task/read-state/retry/schema contracts
and repair two test fixtures.

## Verification

Core #18068 merged normally as `3910352c923a`. Product head
`5a60f541c982` has passing repository CI/build/browser checks, including
required `ci / verify` and `ci / e2e`, plus a fresh exact-head Greptile
5/5 review with zero unresolved threads. Two non-required external app
checks remain pending: Paperclip Review is queued waiting for its
assigned agent; Superagent Security Scan is reviewing the diff. These
are not claimed completed. The normal merge endpoint enforces the
repository rules; no policy or status override is used. The dependent
Top PR is addressing its fresh deferred-Stop review finding.

Product `5a60f541c982` passed 270 UI and 20 selected
Cloud/native/disk-full tests, UI/server typechecks, tokens and maps.
Top’s clean normal merge passed tokens/maps/diff checks; its matrix is
pending. Earlier receipts retain Core’s 47 Rust, 4 compiled-native
retirement and 19 settlement controls, normal Runner build, and runtime
9af build/recursive typecheck. Reproduced loading/shutdown CI fixture
failures passed 7/7 browser and 121/121 unit tests, including a
broken-unsubscribe negative control. No timeout/oracle was relaxed.

The actual-parent restack adopts 75 mainline paths, including
schema/permission and generic runtime changes, beyond the prior two
fixture repairs and client projection fix. The full difference from
hosted `9af1a5de42a2` is therefore larger than four files; backend
source also differs. The merged config-read checks match Core391, and
the Cursor placement/runtime/relay/selection modules match frozen9af;
selected affected regressions pass. Paid proof keeps its actual 9af
source/image identity. The separately tested live/history card fix is
not claimed deployed on that host.

On 9af, original saved settings survived reopening and fresh no-prompt
Test authenticated catalog/model/binding; no new Save is claimed. Fresh
Linux admission passed. With `claude-sonnet-4-5`, Artifact downloaded
exact 27 bytes and matched 121 canonical identities in complete
S3-served history. First Stop’s strict quiet FAILED on a 10.373-second
gap despite independent cancellation/no late artifact. One targeted
unchanged-sampler retry retained all 24 samples: 35.076 seconds quiet /
maximum gap 4.584 seconds, 67 ordered canonical identities, and separate
CANCELLED/artifact-absent status after the original 180-second deadline.
The pre-reload duplicate settled card is disclosed. Exact-ID cleanup for
the three new provider agents is awaiting authorization, so full grades
and the fresh Artifact’s post-cleanup download remain blocked. A
historical deleted-provider artifact was newly downloaded on 9af;
original F226 Question/Plan/reconnect and cleanup proof keep their
identities.

Retained failures: stale fixture 132/133; E8 48/135 with 87 reset-hook
failures; Mac 17 SQL failures/skips; earlier
title/startup/custody/Stop/deletion failures with unknown causes/bounded
recoveries; `dea023` Stop’s warning/50 duplicate identities; pre-repair
ACK and original Core CI failures. WSP’s 251-assertion, 7/8-suite
attempt failed physical PostgreSQL teardown; the unchanged wrapper rerun
passed 128. Retry alone establishes no cause or full local-suite pass.
All paid attempts remain recorded; vendor dollar cost is UNKNOWN.

## Risks

Experimental: Cursor independently acknowledges neither the effective
model nor instruction digest before the first prompt. Explicit values
are submitted and checked through behavior; unpriced provider dollar
cost stays UNKNOWN.

Callbacks need authenticated reachable HTTPS. Scope, revocation,
budgets, completion and cleanup remain authoritative. Operator Stop
intent is separate from physical containment. Saved legacy agents retain
their selected runtime. Prior shared title-save/deletion failures remain
disclosed.

## Model Used

OpenAI Codex, GPT-6 family, assisted with reasoning, repository tools,
code execution, browser verification, and delegated code review. The
serving model’s exact API ID and context window are not exposed. No
value is inferred from the model catalog.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used and the limits of available model
metadata
- [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 linked public issues or described the issue in this PR
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch describes the change and contains no internal ticket ID
- [x] I have run the scoped local tests reported above; pending gates
are stated separately
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have considered and documented the risks
- [x] All required CI gates pass on the current head
- [x] Fresh Greptile is 5/5 with no unresolved findings on the current
head
- [x] I will address all reviewer comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-03 09:01:39 -06:00
DottaandPaperclip 8bd45b5b30 fix(ui): expose redacted arguments in pending tool reviews (#18734)
## Thinking Path

> - Paperclip helps people manage AI agents and review their actions.
> - Ask first tool actions require a person to inspect the proposed
operation.
> - The task and Apps review surfaces share the pending tool-action
card.
> - That card shows a short preview but omits the available redacted
argument body.
> - A valid preview can omit important text, such as the date at the end
of a proposal.
> - This pull request adds optional argument inspection to the shared
card.
> - The person can inspect the proposed content before using the
existing decision controls.

## Linked Issues or Issue Description

Refs: #16540.

Related PRs: #16571 exposes reviewed arguments on formal board approvals
and scrolls the task review into view. #16716 routes tool actions to
their required formal board approvals. This change addresses the
separate shared pending tool-action card used by the task takeover and
linked Apps reviews. It does not close the other reported paths in
#16540.

## What Changed

- Add the existing Arguments and audit hash disclosure pattern to the
shared pending card.
- Show only the bounded argument summary already redacted by the server
and its audit hash. Show an unavailable message for missing, malformed,
or oversized fields.
- Keep the current approval, decline, and remembered-scope callbacks.
- Add a long-proposal story and update the tool-review feature recipe.
- Add React coverage for the real task review transition, the linked
Apps review, plain text rendering, invalid fields, and unchanged
decision calls.

## Verification

- The new task-review test failed on the parent because the disclosure
was absent. It opens Review request, inspects the proposal tail and
hash, then approves the same interaction.
- Oversized-whitespace controls fail on the previous guard ordering
because trimming runs before the length bound. The guard now checks
length first for both fields.
- Passed: 117 React tests across TaskChatInteractionCard,
IssueThreadInteractionCard, and ReviewQueueCard. The tests use the
repository UI config with the existing installed Vitest 5.0.3 dependency
tree.
- Passed: token gates, map checks, Storybook catalog checks, and git
diff checks.
- Local full UI typecheck did not pass. The linked dependency tree lacks
adapter and json-schema-to-ts declarations and has stale shared exports.
It reports no diagnostics in the changed files. This is not a successful
full typecheck.
- Full workspace build, browser, and provider checks were not run
locally. Current head 50600786f7 passed
all 48 normal CI jobs with one expected skip. Greptile and Paperclip
Review both report 5/5 at this head; all review threads are resolved. No
tool action or model call was run for this change.
- Inspect the new ToolActionLongProposal story. Open Arguments and audit
hash and read the final launch date. Inspection must not submit a
decision. Existing destructive, running, failed, declined, and expired
states keep their controls.

## Risks

- This changes the pending review presentation in tasks and linked Apps
reviews.
- The UI displays the existing server-redacted projection. It does not
request or reconstruct signed execution arguments. The existing server
schema caps the summary at 20,000 characters and the hash at 255
characters. The UI uses the same limits and escapes both as text.
- The server still owns redaction, scope checks, approval, and
execution. Inspection makes no API mutation. The current callbacks
retain the same request identity and permission scope.
- The PR will remain unmerged for separate review and candidate-source
integration.

## Model Used

OpenAI `gpt-6.1-sol` (Codex), with source inspection, code editing,
React tests, and Git/GitHub tools. The context window size is not
exposed in this session.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-03 06:28:21 -06:00
DottaandPaperclip 4814d1ab69 fix(ui): show composer images as rounded thumbnails (#18689)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People use the new-task and thread composers to send text and files.
> - Images currently enter the text editor or appear with other files.
> - Large images interrupt text entry and make the two composers
inconsistent.
> - This pull request puts image previews above the text in both
composers.
> - People can check and remove images while they continue to edit the
text.

## Linked Issues or Issue Description

Refs: #13206. Related shared-composer work: #15091.

**What existing behavior does this improve?**

Image selection, paste, and drop in the new-task and thread composers.

**Current behavior**

Thread images enter the editor at the text cursor. New-task images can
appear inline or with file attachments. Images do not have one preview
size.

**Proposed behavior**

Show images above the text as 80 by 80 previews with rounded corners.
Use the existing spacing and radius tokens. Keep file attachments in
their current row. Add image references when the thread message is sent.

**Reason and benefit**

People can review images without moving or deleting message text. One
shared image row keeps both composers consistent.

**Breaking changes**

New image uploads stay outside the editor until send. Old inline-image
drafts remain readable. No server API or database changes are required.

## What Changed

- Add `ComposerImageAttachments` for local previews, removal, upload
status, and retry.
- Let `TaskChatComposer` own the image row and all image input paths.
Keep attachment IDs in the existing send flow.
- Let `NewIssueDialog` stage images and upload retained files after task
creation. Save file bytes in browser IndexedDB by account and company.
Restore them after reload. Clear them after creation. Show storage
errors. Merge saved file changes in one IndexedDB transaction. Delete
only the files removed by that draft. This keeps files saved by other
open tabs.
- Keep rich editing for old image Markdown. Use the same MIME and
filename checks for image previews in both composers.
- Save optional MIME data with thread draft attachments. Existing draft
records remain valid.
- Add desktop and mobile Storybook examples. Update the task feature map
and component tests.

## Verification

- `pnpm exec playwright test --config tests/e2e/playwright.config.ts
tests/e2e/board-attachment-receipts.spec.ts`: all 14 Chromium tests pass
against the real local Board, API, storage, and disposable database. The
suite proves image recovery in two open tabs after saves and task
creation, new-task image recovery after reload, byte-for-byte upload
content, cleanup after creation, rich editing of old image drafts,
upload receipt recovery, and removal during pending uploads.
- The first local browser attempt could not start because Chromium was
absent. Chromium was installed. A later run passed 12 tests but the new
legacy-draft fixture restored an empty body. That fixture wrote storage
while an empty composer was mounted. It now seeds before React startup
and uses a real uploaded image. The complete 13-test rerun passes. Early
component runs also exposed the new restore timing. Submit and file
controls now wait for restoration. The test helper now waits for React
effects.

- 316 focused tests pass across `TaskChatComposer`, `NewIssueDialog`,
`MarkdownEditor`, `composer-draft`, and `useStagedIssueFiles`. The tests
cover explicit file removal, file recovery, account and company changes,
storage failures, MIME-empty images, upload retries, and removal.
- The two-tab browser test failed on the previous commit: the second
save erased the first image. The fix merges files in one read/write
transaction and records explicit removals. The first fixed run reached
the final create step but had no text request after the other tab
cleared the shared text draft. The test now enters a fresh request
before that step. The full 14-test rerun passes.
- `pnpm check:token-gates`, `node scripts/check-maps.mjs`, `node
scripts/storybook-catalog.mjs`, and `git diff --check` pass.
- `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter
@paperclipai/ui build` pass after building the local plugin SDK
dependency. Repository typecheck and build stop because this workspace
has no `cargo`. Full CI must pass before merge. The first CI run passed
typecheck, build, and all unit-test shards. Its browser failure expected
the old inline upload label. The assertion now uses the thumbnail upload
status.
- The prior browser review used the production components with simulated
upload and submit calls. Desktop, mobile, and dark-theme captures were
accepted before this PR. Browser checks confirmed equal-size rounded
previews above the editor, no inline image nodes, no horizontal
overflow, and removal that preserves text. These checks do not prove
live backend persistence.
- Earlier repository typecheck and build attempts also stopped without
`cargo`. An earlier full test run was killed with a recorded
out-of-memory event during a server integration shard. It had no
full-suite verdict. One document-recovery test timed out during that
concurrent run. Its isolated rerun and later complete focused runs
passed; the initial timeout cause was not established.
- An initial catalog command in this workspace ran before dependency
installation finished. It could not load Storybook. The command passed
after installation. The first UI typecheck could not find plugin SDK
declarations while that package was still building. The UI typecheck
passed after `pnpm --filter @paperclipai/plugin-sdk build`.

To inspect the layout, open `composer-new-task--images`,
`composer-new-task--mobile-images`, `composer-add-menu--images`, and
`composer-add-menu--mobile-images` in Storybook. Select images with
different aspect ratios. Check removal, mixed files, failed upload and
retry, and draft restoration.

- Greptile reports 5/5 for commit
`9b9e93beeed80371f667ad2e1a9573e82332c05c`. There are no open review
threads.
[CI](https://github.com/paperclipai/paperclip/actions/runs/41544180330)
passed on this commit. All 58 checks finished: 54 passed, one review is
neutral, and three optional checks were skipped. The legacy Snyk status
passed. Paperclip also reports 5/5. No review threads are open.

## Risks

- Open tabs share the account and company draft. Atomic file writes keep
changes from other tabs. A reload can restore those saved files.

- Attachment state now controls when image references enter a thread
message. Tests cover pending uploads, failures, retry, removed images,
and retained upload IDs.
- New-task images use the existing staged-file upload flow after task
creation. A failed upload follows that flow's existing error behavior.
Browser storage can be unavailable or full. The composer keeps the files
in memory and shows a recovery message.
- Legacy inline-image drafts retain their original text. No migration is
required.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, tool use, and shell
execution. The exact runtime snapshot ID and context-window size are not
exposed in this session. The earlier implementation's model snapshot is
not recorded in the handoff.

## 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 available in this session)
- [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 references)
- [x] My remote branch name describes the change and contains no
internal Paperclip ticket ID
- [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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 23:35:32 +00:00
DottaandPaperclip 912cff9392 fix(ui): link chat message identities to agent overviews (#18615)
## Thinking Path

> - Paperclip lets people manage and converse with agents.
> - Chat replies identify their author with an avatar and name.
> - Those identities currently offer no path to the responding agent's
profile.
> - The existing overview route already provides that context within the
current company.
> - This PR links the shared chat identity to that overview while
preserving its layout and typography.
> - People can inspect the responding agent by clicking either its name
or avatar.

## Linked Issues or Issue Description

Related: #17169 links the conversation's page header. This change covers
the author identity above messages and active turns.

**What existing behavior does this improve?**
Navigation from chat message authors to their agent overview.

**Subsystem affected**
ui/ — shared task and standing-chat identity component.

**Current behavior**
An agent's name and avatar above its message are plain text and an
image.

**Proposed behavior**
The name and avatar form one company-scoped link to the actual author's
overview. Both retain their appearance, including no underline on hover.
An identity without an agent ID remains plain text.

**Reason and benefit**
Readers can inspect the responding agent directly from the conversation.

**Breaking changes**
None; this adds navigation to an existing read surface.

## What Changed

- Link the shared agent identity to its existing overview route when an
ID is available.
- Preserve the existing avatar, text, spacing, and non-underlined
appearance.
- Document this entry point and the desktop/mobile verification recipe.

## Verification

- `pnpm -r typecheck` — passed.
- `pnpm build` — passed.
- Existing bubble, runner-turn, turn, task-thread, and AgentChat tests —
461 passed.
- `pnpm check:token-gates`, `node scripts/check-maps.mjs`, and `git diff
--check` — passed.
- Chromium production `TaskChatThread` in `Layout` (mixed-author
Storybook fixture): dark and light desktop identity screenshots are
pixel-identical before/after and on hover; no underline, and the href
points to the responding author in the same company. The preview is UI
evidence, not backend/provider acceptance. The separate standing-chat
preview had stale history/email fixtures, and the optional mobile
preview placed the identity behind its composer; neither is claimed as
acceptance evidence.
- Added router integration tests click both name and avatar from a
different agent's chat and assert the author's company-scoped overview;
unknown IDs remain unlinked. All 30 bubble/identity tests pass.
- Full UI project: 10,284 tests passed, one 5-second timeout in the
unchanged design-sandbox snapshot test. Its isolated rerun passed all 12
tests; the initial timeout remains recorded, and its cause was not
established.
- Final UI typecheck passed after adding the tests.
- `pnpm test:run` stopped before running tests: its unchanged server
chat shard filters selected no tests. The full UI result and isolated
rerun are recorded above. This is not a claim that the full local
repository suite passed.

- [Final-head CI
run](https://github.com/paperclipai/paperclip/actions/runs/41475021544)
passed, including build, typecheck, unit/integration suites, all browser
shards, and both aggregate gates. Greptile is 5/5 with its review thread
resolved. The separate Paperclip Review check is still queued, waiting
for its assigned agent; no assessment has been published yet.

## Risks

Low risk: navigation uses the existing company-aware router and explicit
author ID. Unknown identities stay unlinked. The shared identity is used
by standing chats, task replies, and runner headers.

## Model Used

OpenAI GPT-6, running as Codex with reasoning, code editing, and tool
execution. The exact served model ID and context-window size are not
exposed in this session.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 10:41:00 -06:00
DottaandPaperclip f6fc336a35 fix(ui): reveal task conversations without loading layout shifts (#18545)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Tasks combine saved messages, documents, run output, monitors, and
decisions.
> - Compact history makes long tasks load quickly.
> - The loading view still showed the real task header before the thread
scrolled to recent messages.
> - Different loading frames also changed the viewport, composer bounds,
and header typography.
> - This pull request uses one loading frame and reveals the prepared
conversation once.
> - The benefit is a stable first view without a material loading-speed
penalty.

## Linked Issues or Issue Description

**What happened?**

A cold task open could show a generic skeleton, then the real title and
monitor above placeholder messages, then jump to recent content. The
loading view changed width on desktop and height on mobile. Its title
line height differed from the real title.

**Expected behavior**

Keep the loading viewport and composer in place. Prepare the initial
reading position out of view. Reveal the recent conversation once its
data, fonts, scroll position, and composer bounds settle. Cap the font
wait at three seconds if the font host does not answer.

**Steps to reproduce**

1. Open a task with a long title, long saved replies, document cards, a
monitor, and a pending decision.
2. Reload it with CPU and network throttling.
3. Watch the header appear above placeholders, then move offscreen when
the recent conversation appears.

**Paperclip version or commit**

e122478368. The synthetic baseline recorded 10 animation frames with a
real header visible before the conversation was ready.

**Deployment mode**

Built from source. Local production previews used the same disposable
PostgreSQL fixture and API.

Related work: #17593, #16878, #18092, and #18461 preserve compact
startup and saved-card behavior. Older open PR #14667 addressed
transcript reveal and reading anchors; this change targets the remaining
loading-frame transition on current master.

## What Changed

- Prepare task data while the personal layout preference loads. Keep the
temporary page hidden until the correct layout is known. This removes a
12 px mobile header change.
- Share one matching loading frame across task metadata and history
preparation. Use the real composer surface and dock geometry for its
placeholder.
- Keep the real title and monitor concealed until the viewport, scroll
position, composer, and fonts settle. Bound a stalled font request to
three seconds.
- Reserve the final chat viewport and breadcrumb identifier position.
Mount task properties after the personal preference resolves.
- Match the loading title typography to the selected task interface,
including Classic.
- Add normal-CI browser coverage for rich tasks, Classic startup and
typography, mobile layout selection, and stalled fonts. Preserve the
outage recovery assertions.
- Add Design Guide examples and an optional retained fixture with 200
long messages, documents, a PR card, a monitor, and a pending
confirmation. Disable both interval and on-demand agent wakes in this
fixture.

## Verification

- Final UI source: `8398af3493`. The later commits change tests or merge
master. The recorded production build is `99867e2dc3`; its UI source is
identical to the final PR head.
- All 10,263 UI tests pass: `pnpm --filter @paperclipai/ui exec vitest
run`. Workspace typecheck and the full production build pass. Token
gates, module boundaries, map validation, and diff checks pass.
- Task browser checks pass 40 cases. Shared chat passes 22 cases. The
normal-CI loading and outage recovery suite passes all 13 cases on the
final head.
- The eight rich loading cases cover direct and list entry, delayed
fonts, and delayed personal preferences on desktop and mobile. At 4× CPU
slowdown and 80 ms latency, each records zero real-header frames before
reveal. Loading-frame, composer, and initial reading-position movement
are 0 px. Title typography matches.
- The normal browser suite also verifies that unresolved mobile layouts
stay hidden, the selected mobile viewport stays fixed, and a seeded
Classic loading title matches the resolved title after an uncached
reload.
- Cold speed: five fresh contexts per variant and viewport, alternating
before/after order. Same local API and synthetic fixture; 4× CPU
slowdown, 80 ms latency, 1.18 MB/s download. No interception,
recordings, builds, or test suites during measurement. Desktop median:
3578 ms before, 3572 ms after. Mobile median: 3500 ms before, 3476 ms
after. Sample ranges overlap.
- The unmodified baseline records 10 real-header frames before
readiness. The final eight-case matrix records zero. Local recordings
and failed prototype evidence are retained outside the repository. No
private staging content is published in this PR.
- CI initially counted hidden zero-size elements as visible frames. Its
saved data confirms the `(0, 0, 0, 0)` entries. Both browser samplers
now ignore those entries and retain all visible geometry checks. The
corrected local suite passes.
- The default `pnpm test:run` command stopped in the unchanged server
chat integration shard with `No test found ... in lines ...` and 1817
skipped tests. This is not a local full-suite pass. One unchanged
AgentActionButtons test also failed during a concurrent run; all 37
cases pass in isolation, and the full 10,263-test UI rerun passes
without source changes to that component.
- Final-head [CI
passes](https://github.com/paperclipai/paperclip/actions/runs/41320240728)
at `d1ef4a955f`. No checks are failed or pending. Greptile and Ponytail
Paperclip Review both report 5/5 for that exact head. All review threads
are resolved.
- The fix is not deployed to staging.

## Risks

- First reveal waits for stable geometry and fonts, with a three-second
font cap. A font that arrives after this degraded-mode cap can still
change text metrics. The existing history deadline still exposes usable
content if another dependency stalls.
- The loading frame cannot predict arbitrary conversation content. The
real content remains concealed until its initial position is ready.
- The shared thread also serves agent chat. Its browser startup and
scroll journeys are included in final verification.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, tool use, code execution, and
browser inspection. The host did not expose a more specific model ID or
the context-window size.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-11-02 08:13:34 -06:00
TonioandClaude Opus 5.5 8ea240218d feat(ui): bring the Refine-v2 layout to the agent page (#18378)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The agent page is where an operator reads and changes one agent.
> - The page grew one tab at a time. Ten tabs sit in one flat list, the
header holds many buttons, and the audit links leave the agent.
> - A design pass, called Refine-v2, made a calmer layout for this page.
It ran in a prototype on fixture data only.
> - This pull request moves the Refine-v2 layout and behavior into the
live agent page. Where the prototype and the live page differ, the live
behavior stays. For example, the floating save bar stays on screen.
> - The benefit is a shorter navigation, edits in place, and audit data
that stays inside the agent.

## Linked Issues or Issue Description

Refs #13716
Refs #9166

Both pull requests mount plugin tabs or slots on the agent page. They
touch the same files, so one of the three needs a rebase after the
others merge.

**Subsystem affected**

The agent detail page in `ui/` (`ui/src/pages/AgentDetail.tsx`, its
sidebar, header actions, and the shared agent config form).

**Problem or motivation**

The agent page is hard to scan. The navigation shows ten items in one
list. The header shows Run now, Pause, Clear error, and Assign task as
separate buttons. The name, title, and manager are form fields deep in
the Harness tab. Activity, Runs, Costs, and Budgets open company-wide
pages, so the operator loses the agent context. Each tab uses a
different card and table style.

**Proposed solution**

Use one layout system for every agent tab. Group the navigation into
Agent and Audit. Edit the name and title in the header. Move the work
actions into the actions menu. Show audit views inside the agent. Keep
the persistent save bar and add a status dot to it.

**Alternatives considered**

We considered a flag that lets operators opt in to the new layout. We
did not use a flag, because two layouts on one page double the test
surface. We also considered moving the save button to the end of the
scrolling content, as the prototype did. We kept the floating save bar,
because it is always visible.

**Roadmap alignment**

`ROADMAP.md` has no item for the agent page. This change is a UI
refinement of an existing page. It adds one optional field to an
existing API request and no database schema change.

## What Changed

- **Navigation.** The agent sidebar shows two groups. Agent has
Overview, Identity, Harness / Runtime, Secrets & variables, Permissions
/ Trust, and Advanced. Audit has Activity, Runs, Costs, and Budgets.
Skills, Tools, Channels, and API Keys leave the navigation. Their URLs
still open. The Instructions tab is now Identity, at `/identity`. The
old `/instructions` URL redirects.
- **Header.** The agent character shows at a larger size. The name and
title edit in place. Enter or blur saves. Escape cancels. An error
restores the old value. A rename updates the URL. While a tab has
unsaved changes, the header refuses the edit and asks the operator to
save or discard first. The third line shows the title and a link to the
manager. A crown button to the right of the name replaces the "Set as my
primary" link and the separate primary indicator. It is outlined and
dimmed until the agent is your primary, then fills with a short pop.
Replacing an existing primary asks for confirmation first, and the pop
plays after the dialog closes. Reduced motion skips the pop. Run now,
Pause or Resume, Clear error, and Agent history move into the actions
menu. Assign task is the primary button. For an agent that still needs
setup, Finish setup is the primary button and Assign task moves into the
menu.
- **Agent history.** A new dialog in the actions menu replaces the
Revisions entry. Each row shows a plain-language summary, the person or
agent who made the change, the date, and Restore. Restore asks for
confirmation. A failed restore shows its reason inside the confirmation.
- **Overview.** Four metric tiles show activity this week, runs this
week, costs this month, and budget used. Each tile links to its audit
view. When the list behind a count is capped, the tile shows a lower
bound, for example 200+. The activity tile follows live updates.
Profile, Skills, and Recent tasks panels follow. The Profile panel lists
direct reports under their label in at most two rows, then a "+N more"
button that expands the list. The Latest run card is removed.
- **Identity.** The file preview shows the raw text. A pencil button
switches to a plain text editor. Copy and Delete are icon buttons. A
chip next to the file name says "Managed by you" or "Managed
externally". Per-file history and unsaved edits stay.
- **External instructions.** "Advanced settings" opens Root path and
Entry file fields and a Load profile button. Load profile asks the
server to switch only if the root directory and the entry file already
exist. If either is missing, the server refuses and the panel shows the
reason. The entry file can have any name inside the root.
- **Instructions bundle API.** `PATCH /agents/:id/instructions-bundle`
accepts an optional `requireExistingEntry` flag (`packages/shared`
validator, `server` service, `ui` client). With the flag, the server
checks the root directory and entry file before it creates or copies
anything. Without the flag, the behavior does not change.
- **Harness / Runtime.** The config form gets a `panels` layout: Harness
and Execution side by side, then the runtime test, then environment
variables. The identity and run-policy sections are hidden from this
tab.
- **Secrets & variables and Advanced.** These tabs use the same filled
panels and table headers.
- **Permissions / Trust.** The trust presets show as selectable cards.
An Allowed connectors panel shows up to three connector logos and links
to Apps, filtered to installed connectors. Capabilities sit in their own
panel. Changes on this tab save at once, with no save bar.
- **Audit inside the agent.** Activity, Runs, Costs, and Budgets render
inside the agent page. Runs is locked to the current agent. A failed
budget incident action shows its reason under the incident.
- **Save bar.** The floating save bar stays. It shows an amber dot for
unsaved changes and a green dot with "Changes saved" after a save.
Discard stays.
- **Leave guard.** If the form has unsaved changes and the operator
clicks a link, a dialog asks to keep editing or discard the changes.
Browser back and the header actions keep the native confirm.
- **Apps.** `/apps?source=installed` opens the Apps page on the
Installed filter.
- **Tokens.** New `--agent-detail-*` tokens in `ui/src/index.css` hold
every spacing and fill value. Each fill is a mix of foreground into
background, so one value works in light and dark themes.
- **Tests and maps.** Tests cover the navigation model, sidebar, header
menu, Overview layout, Identity editor, and helpers. The
agent-configuration recipe in `maps/feature-map/agents.md` describes the
new page.

## Verification

- `cd ui && npx vitest run`: 849 test files and 10,081 tests pass.
- `cd server && npx vitest run
src/__tests__/agent-instructions-routes.test.ts
src/__tests__/agent-instructions-service.test.ts`: 40 tests pass.
- `npx playwright test --config tests/e2e/playwright.config.ts
tests/e2e/onboarding.spec.ts
tests/e2e/chat-adapters-ui-providers.spec.ts`: 26 tests pass.
- `cd ui && pnpm typecheck` passes. This includes the Storybook catalog
check. The `server` and `packages/shared` typechecks pass.
- `cd ui && pnpm build` passes.
- `pnpm run check:token-gates` reports all gates clean.
- `node scripts/check-maps.mjs` and `node scripts/storybook-catalog.mjs
--check` pass.
- Manual check on a local instance, in light and dark themes:
1. Open an agent. Confirm the sidebar shows the Agent and Audit groups.
2. Click the agent name in the header. Type a new name and press Enter.
Confirm the URL changes. Rename it back.
3. Open the actions menu. Open Agent history. Confirm the rows and the
Restore confirmation.
4. Open Identity. Click the pencil. Change a line. Confirm the save bar
shows the amber dot. Click a sidebar link. Confirm the discard dialog.
Click Keep editing, then save. Confirm the green dot.
5. Open Harness / Runtime, Secrets & variables, and Permissions / Trust.
Confirm the panels and the trust cards.
6. Open Runs under Audit. Confirm the list shows only this agent and the
page stays inside the agent.

## Risks

- This changes a high-traffic page for every operator at once. There is
no flag to switch back.
- Run policy and Reports to are no longer editable on the agent page.
The header shows the manager as a link only.
- Skills, Tools, Channels, and API Keys are reachable by URL only.
Operators who use them from the sidebar must use the URL.
- The pull request conflicts with #13716 and #9166 in `AgentDetail.tsx`
and the agent sidebar.
- Storybook stories for the agent page and `DESIGN.md` are not updated
in this pull request.
- The new `requireExistingEntry` flag is opt-in. Existing API callers
keep the old behavior, which creates a missing external directory and
entry file.
- I ran two e2e spec files locally, not the full `pnpm test:e2e` or
`pnpm test:release-smoke`. CI runs the full e2e suite. I did not run the
repo-wide `pnpm -r typecheck`, because the local toolchain has no Rust.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), in Claude Code, with
reasoning and tool use (shell, file edits, and a browser for visual
checks). A person directed every design decision.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 22:27:09 -08:00
DottaandPaperclip d38cdf261a perf(ui): speed up Tasks and Inbox startup (#18492)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Tasks and Inbox are the main entry points for that work.
> - Earlier changes made their data reads and row counts smaller.
> - Those changes remain, but shared controls now pull in the whole
task-detail bundle.
> - A cold open can also read a remembered organization before selecting
the one in the URL.
> - This pull request separates collection code and selects the
addressed organization first.
> - It warms task code after collection paint, so the next task open
stays fast.

## Linked Issues or Issue Description

Refs #17756, #18323, #16849, #17041, #17983, #17960, #18461.

**What happened?**

Tasks and Inbox still use their optimized index reads and row budgets.
However, small shared controls and hooks were placed in the task-detail
chunk. A collection had to download that whole chunk. The HTML also
preloaded it on every route. The original production profile loaded
about 6.5 MB of decoded JavaScript before useful rows, or 1.9 MB
transferred with compression.

Company bootstrap could select a different remembered organization
before Layout selected the URL's organization. This started unnecessary
company reads. A retained multi-company browser fixture reproduced two
attention-count requests for different companies.

**Expected behavior**

Show correctly scoped, stable collection rows without waiting for
task-detail code. Keep compact reads, bounded rendering, direct task
preloading, immediate New Task input, and fast follow-on navigation.

**Steps to reproduce**

1. Use a production UI build with Coordinator enabled and two active
organizations.
2. Remember one organization, then cold-open Tasks or Mine in the other.
3. Inspect startup script and company requests before the first useful
row.

The baseline UI revision is `91fdf02e95`. This is a UI change. It has no
API, schema, migration, or authorization changes.

## What Changed

- Group the static collection dependency trees above the task-detail
group. Keep the existing startup and task grouping strategy.
- Preload task detail and its static dependency closure early on direct
task and agent-chat URLs. Keep collection aliases out of that preload.
- Fetch the immutable task chunk at low priority after a collection
paints, or on a same-origin task-link hint. After a successful immutable
response is fully read, module-preload the cached chunk so it can
compile without executing. A failed HTTP probe skips module preload.
- Prefer an addressed active organization during bootstrap. Preserve
manual selection, archived-company handling, and account-scoped company
lists.
- Preserve a task reading anchor when a programmatic scroll event
reports an unchanged offset during restore reflow. Strengthen the Back
journey to wait for a completed collection navigation.
- Add production-browser checks for delayed indexes, correct company
scope, stable row geometry, failed speculation, and early direct-task
preload. Update collection verification notes and the feature map.

## Verification

Final source: `e402ab7fc6`; baseline UI: `91fdf02e95`.

- All **234 focused unit cases** and **44 production-browser journeys**
passed on the final source: 33 task journeys and 11 collection journeys.
Coverage includes compact history, saved cards, draft persistence,
avatar continuity, failed-probe recovery, delayed data, pagination, deep
links, desktop/mobile and reading-position restoration through Back.
Desktop and mobile screenshots were inspected.
- Workspace typecheck, full production build, map checks, token gates
and diff checks passed. The default local `pnpm test:run` still stops
before executing tests because the existing chat-test line selector
reports `No test found` (1,816 skipped). This is not a passed full local
test suite. Focused tests and remote CI remain separate evidence.
- Greptile reviewed the exact final commit at **5/5**, with zero open
review threads. Final code CI passed. The complete check inventory is
**55 successful, 3 skipped, 1 neutral**. The neutral result is the
separate Paperclip Review: its agent finished without completing an
assessment, so it is not a passing review score.

Five alternating baseline/candidate pairs per scenario, Chromium
151.0.7922.34, 1440×900, 4× CPU, 50ms latency, approximately 9Mbps down
/ 1.5Mbps up. Cold cases use fresh browser contexts with normal cache
writes enabled; warm cases use the same context and normal application
query cache. Both previews use the server's immutable hashed-asset cache
policy and uncached HTML, with real local feature settings and no
request interception. All task-owned builds and suites were stopped
during timing; other host activity was uncontrolled. Readiness requires
useful rows and editable search, or the readable task thread and
editable composer, followed by two animation frames.

| Journey | Baseline median (range) | PR median (range) | Median paired
saving |
| --- | --- | --- | --- |
| Cold Tasks | 3239 ms (3189–3333) | 2545 ms (2441–2682) | +752 ms |
| Cold Inbox | 3207 ms (3203–3268) | 2679 ms (2502–3062) | +541 ms |
| Warm Inbox | 717 ms (701–917) | 760 ms (745–768) | -47 ms |
| Warm Tasks | 1150 ms (1126–1207) | 1136 ms (1119–1174) | +18 ms |
| First task click | 943 ms (932–1008) | 1007 ms (976–1098) | -74 ms |
| Back to Tasks | 584 ms (568–617) | 566 ms (559–575) | +10 ms |
| Cold direct task control | 3389 ms (3377–3402) | 3415 ms (3395–3896) |
-13 ms |

All five pairs improved for each cold collection. The signed saving is
baseline minus candidate for each pair; it is distinct from the
difference of medians. Warm navigation is broadly similar. First task
click was 74ms slower by median paired difference. Direct-task median
paired difference was 13ms slower, with one slower 3.90s candidate
sample retained in the range; this is not a claimed direct-task speedup.

Completed script transfers by collection readiness fell from about
**1.91MB to 1.14MB** (Tasks), and **1.90MB to 1.14MB** (Inbox). Task
code warms after rows paint. At the test bandwidth, the removed 0.77MB
critical transfer represents roughly 0.65s of download time; CPU and
network overlap, so their savings are not added. Unthrottled loopback
API control medians stayed about 17–18ms in both variants. All 30 cold
samples had zero browser errors.

Rejected experiments remain separate: automatic splitting produced over
200 startup requests; disabling recursive grouping slowed direct tasks;
HTTP-only warming improved collection startup but slowed first task
opens. The final correction preloads direct dependencies and compiles
successfully cached code after paint. Routing disables HTTP caching, so
intercepted runs were kept as diagnostic evidence rather than used for
warm-cache acceptance; see [Playwright's cache
behavior](https://playwright.dev/docs/api/class-page#page-route). Vite
preview's default asset `no-cache` policy was also corrected to match
the shipped server before final measurement.


## Risks

- Bundle placement affects shared consumers. Browser checks cover
collections and task navigation; the full PR checks also cover other
routes.
- Code warming still transfers the task chunk if the user stays on a
populated collection. It moves that download past first paint and does
not execute it. This is a startup latency improvement, not a claim that
all eventual bytes disappear.
- A direct click before warming finishes still loads code on demand.
Direct task and chat URLs retain early module preload.
- Local browser evidence does not establish a deployed staging speedup.
This PR does not merge or deploy itself.

## Model Used

OpenAI GPT-6 (Codex), with reasoning, tool use and local code execution.
The context-window size is not exposed in this environment.

## 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 the relevant tests locally and they pass (234 unit
cases and 44 browser journeys; the full-command limitation is documented
above)
- [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
- [x] All code CI gates are green (the separate Paperclip Review is
neutral because its agent did not complete an assessment)
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 22:12:41 -05:00
DottaandPaperclip 91fdf02e95 perf(tasks): defer completed transcripts on compact opens (#18461)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task conversations must show the saved instruction and recent
replies quickly.
> - Compact task reads already limit the saved message window.
> - The conversation still waits for completed run transcripts even when
a saved reply contains the result.
> - Removing that wait alone can insert activity after the reader starts
reading.
> - This pull request defers that output until the reader opens history
and keeps required output in the initial reveal.
> - The benefit is a useful conversation sooner, with a stable first
layout and a working composer.

## Linked Issues or Issue Description

Refs #17593, #18092, #18312, #18358, #18422.

**What happened?**

Opening a task with a long saved investigation can wait for native
events or legacy logs before showing its existing replies. A slow
transcript request can hold the conversation behind the loading screen
until the 15-second fallback.

**Expected behavior**

Show the bounded saved conversation without reading completed output
that already has a usable saved reply. Keep that output available
through the existing history controls.

**Steps to reproduce**

1. Create a task with many completed runs and long saved agent replies.
2. Delay its run events and logs.
3. Open the compact task directly. Before this change, the transcript
read blocks the saved replies and composer.

## What Changed

- Defer completed successful run transcripts on compact task opens when
a usable saved reply is present. Load that output through the existing
history controls.
- Keep required output on the initial path: live and failed runs,
yielded runs, pending interactions, placeholder/progress-only replies,
explicit anchors, chats, and full history. Retain output already
selected during this visit when its run completes.
- Keep saved plans visible when their owning run output is deferred or
still loading.
- Keep the same composer and draft through history expansion. Offer
**More run output** when a single saved run has deferred output.
- Position same-task comment links after their target arrives. Wait only
for a missing target, with a 15-second limit. Unrelated stalled metadata
cannot block an available target after the reveal deadline.
- Preserve the reading anchor when a queued scroll event arrives during
a properties-pane width transition.
- Add a 200-reply/200-run PostgreSQL browser fixture with a saved plan,
covering both task views on desktop and mobile. Correct stale browser
setup for current routes and the shared mobile scroller.
- Remove a random company-prefix collision in the isolated privacy test
fixture that failed during CI.

## Verification

- Final revision `fba3f2fcbb`: 386 focused thread/scroller unit cases
and all 32 production-browser journeys passed. The browser cases cover
both task views on desktop/mobile, saved plans, delayed transcripts,
history, comment links, Back, drafts, retry, avatar continuity, media
and pane resizing. The 25 privacy fixture cases also passed against
PostgreSQL.
- Workspace typecheck and full build passed with Node 24. A broader
local UI run passed 10,220 cases across 849 files before the final
navigation/plan review fixes; the changed components were then rechecked
in the 386-case focused run.
- Five alternating pairs compared master `12b0cc6304` with this
revision, using 200 long saved replies and 200 completed native runs.
Both production UI builds used the same loopback API/database, Chromium
151.0.7922.34, 1440 × 900, fresh browser contexts, service workers
blocked, no CPU throttle, and a controlled 3-second events/log delay.
Builds and other suites were stopped during measurement. No page errors
occurred.

| Useful conversation + editable composer | Baseline median (range) |
Fixed median (range) |
| --- | --- | --- |
| Cold direct open | 3.570s (3.538–3.616s) | 1.056s (1.022–1.141s) |
| Task-list navigation | 3.373s (3.342–3.394s) | 0.899s (0.885–0.915s) |
| Back | 22ms (22–25ms) | 25ms (25–28ms) |

- Median paired savings: 2.519s cold, 2.470s from the list.
Completed-output requests: two per baseline sample, zero per fixed
sample. Recent-comments API control medians were 13.6ms for both, with
ranges 12.1–18.7ms and 11.6–50.8ms. No Back improvement is claimed; an
earlier revision's run also included one 1-second Back outlier, retained
in the local evidence.
- The full local default test command did **not** pass: it stopped on
the existing chat test line-selection error. After restoring embedded
PostgreSQL library symlinks omitted by an install with scripts disabled,
Node 24 passed 672 cases in the first two chat shards, then failed to
select the third. This is separate from the passing focused suites and
remote CI.
- Earlier CI failures were addressed: the privacy prefix collision is
fixed; the delegated task-completion reply case passed locally after
merging master's reply-recovery fix (#18465). Browser fixture
corrections retain the original behavior assertions. Red tests
reproduced the loading, navigation, resize and saved-plan regressions
before their fixes.
- Map, module-boundary, token-gate and added-line token checks passed.
The full-tree token scan still finds pre-existing active-username
fixtures; this PR adds zero forbidden token lines.
- Greptile: **5/5**, final revision, all four review threads resolved.
The final-revision PR CI workflow passed, including build, typecheck,
all server/chat/workspace test shards, all eight E2E shards, and every
Runner lane. GitHub reports 55 successful checks and three skipped
checks. The separate **Paperclip Review** check remains queued with
**Waiting for the assigned agent**; it has not produced an assessment
and has not been bypassed. The branch has no merge conflicts.

## Risks

- The default compact task omits completed transcript details when the
saved result is sufficient. The reader must open history to inspect
them.
- Required structural data remains inside the initial reveal boundary.
Slow server responses for that data remain visible latency.
- Link positioning falls back after 15 seconds when its target never
arrives. The conversation remains readable.
- The measurements use a controlled local delay. They do not establish a
deployed staging speedup.
- No API, schema, authorization, or migration changes.

## Model Used

OpenAI Codex, GPT-6, with tool use and code execution.

## 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
- [ ] I have run tests locally and they pass (focused suites pass; the
full default wrapper has the existing selection error documented above)
- [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 (code CI passed; the separate
assigned-agent Paperclip Review remains queued)
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 12:56:06 -05:00
DottaandPaperclip f46c8071fb fix(ui): make the Coordinator composer footer opaque (#18455)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - The Coordinator workspace shows a task transcript and a message
composer.
> - The composer footer can cover part of the transcript on desktop.
> - The footer has a transparent background, so text shows through
accessory panels and gaps.
> - This pull request gives the footer a solid background from the
active theme.
> - Users can read the composer controls without text from the
transcript behind them.

## Linked Issues or Issue Description

**What happened?**
The Coordinator composer footer lets transcript text show through the
area above the message field.

**Expected behavior**
The full footer has a solid surface in light and dark themes.

**Steps to reproduce**
1. Enable the Coordinator workspace.
2. Open a task with enough messages to scroll.
3. Show a composer accessory, such as queued messages or a pending
question.
4. Scroll the transcript behind the footer on desktop.

**Paperclip version or commit**
Base commit: f2db909393.

**Deployment mode**
Built from source. The change affects the Coordinator workspace.

Related work: https://github.com/paperclipai/paperclip/pull/17983 added
the workspace. Searches for an opaque or transparent composer fix found
no duplicate.

## What Changed

- Use `var(--background)` for the full Coordinator composer footer.
- Keep the outer footer square so transcript text cannot show at its
corners.
- Block clicks through the footer gaps. Forward wheel input from these
gaps to the transcript.
- Keep editor scrolling, zoom input, and the classic workspace behavior.
- Add regression tests for the footer surface, wheel input, and canceled
forwarded events.
- Keep wheel modifier keys. Use the font size to calculate horizontal
distance for line-mode input.
- Remove the old comment that describes a transparent footer.

## Verification

- Passed: 173 tests in `TaskChatComposerDock`, `TaskChatComposerStyles`,
`TaskChatComposer`, `TaskChatQueuedMessages`, and `TaskMessageScroller`.
- The surface and wheel tests fail on the previous implementation and
pass with this change.
- The latest wheel tests reproduce lost modifier keys and excessive
horizontal distance on the prior commit. The cancellation test fails
when the cancellation guard is removed.
- Passed: `pnpm check:token-gates` and `git diff --check`.
- Passed: local Chromium checks with the production dock and built UI
CSS in light and dark themes at desktop and mobile sizes. The checks
cover solid corners, blocked clicks in footer gaps, wheel input, message
entry, and horizontal overflow.
- The browser fixture reproduces the hidden-control click when the old
pointer rules are restored. These are local fixture checks, not a
deployed acceptance result.
- Passed: `pnpm --filter @paperclipai/ui typecheck` and `pnpm --filter
@paperclipai/ui build`.
- Full local `pnpm -r typecheck` and `pnpm build` could not finish
because Cargo is absent from this environment. The full local test run
was stopped without a complete result after these missing prerequisites
were confirmed. Full CI now passes on the current commit.

- Passed: [full
CI](https://github.com/paperclipai/paperclip/actions/runs/41205893876)
on commit `37feaef28`. Greptile and Paperclip both gave this commit 5/5.
Both review threads are resolved.
- Paperclip review found hidden clicks through footer gaps and exposed
corners. This change addresses both findings. The first CI quality
review required a regression test. This change adds those tests. The
later review requested a cancellation test and better horizontal wheel
handling. This change addresses both items.

## Risks

- Low risk. The CSS selector applies only inside the Coordinator
workspace.
- The footer now captures clicks across its full area. Wheel input in
empty footer space still scrolls the transcript.
- The dock forwards wheel input to the transcript handler so
earlier-history loading still receives that input.
- No API, data, or migration changes.

## Model Used

- OpenAI Codex, based on GPT-6 (`gpt-6`), with reasoning, tool use, and
code execution. The runtime does not expose its context window. The
model ID for the original saved CSS patch is not retained in the task
evidence.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 08:59:41 -05:00
DottaandPaperclip 59da15066a feat(runner): deliver native Kimi Code (#18391)
Deliver native Kimi Code setup, exact models, scoped credentials, verified packages and runtime packs. Preserve current upstream release attestations and restore verified same-run remote retry dispatch without weakening process ownership.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-30 22:26:15 -05:00
DottaandPaperclip 909e29dd07 fix(ui): show agent-created subtasks inline in the task feed (#18320)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The task feed shows agent messages, documents, and artifacts.
> - An agent can create a subtask or a separate follow-up task during
that work.
> - The reader must open the Tasks tab to find the new task.
> - This pull request adds a linked task card to the source feed at
creation time.
> - The card shows the current title, task number, and status.
> - The reader can inspect delegated work without searching a second
panel.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

Task creation visibility in the source task feed. Related work: #13823
added ancestor navigation in the Tasks panel.

**Current behavior**

Agent-created child tasks appear in the Tasks tab. The main feed has no
persistent link card for those tasks.

**Proposed behavior**

Show each agent-created direct child or source-linked follow-up task
once in the feed. Keep the card at creation time when status changes.
Keep existing chat handoff and accepted suggestion cards without
duplicates.

**Reason and benefit**

Readers can see which work an agent created and open that task from the
conversation.

**Breaking changes**

None. This change uses existing authorized task reads. It does not add
API or database fields.

## What Changed

- Pass the existing child and source-task reads from task detail to the
feed.
- Add a task card with a link, wrapping title, task number, and status
badge. Use existing design tokens.
- Suppress repeated cards and tasks already shown by accepted
suggestions or chat handoffs.
- Show task-read failures with Retry. Keep the conversation readable
during those failures.
- Add feed and page regression cases plus desktop, multiple-task, dark,
and mobile stories. Update the product description and delegation
recipe.
- Keep task selection and rendering in the task feed module. Existing
issue APIs continue to own access checks and company scope.

## Verification

- Passed: 224 focused tests with `pnpm exec vitest run
ui/src/components/TaskChatThread.task-creation-order.test.tsx
ui/src/pages/IssueDetail.test.tsx
ui/src/components/task-detail/TaskDetailTasksPanel.test.tsx
--maxWorkers=1`.
- Passed: `pnpm --filter @paperclipai/ui typecheck`.
- Passed: `pnpm check:token-gates`, `node scripts/check-maps.mjs`, and
`node scripts/storybook-catalog.mjs`.
- Cases cover creation order, current status, links, company filtering,
direct children versus grandchildren, duplicate suppression, and read
failure with retry.
- Passed: browser render and link assertions for desktop, multiple
tasks, dark theme, and mobile at 390px. All four story play phases
finished. No page errors or horizontal overflow occurred. Screenshots
use fixture task data and the production task feed. They do not prove
server persistence or agent execution.
- Passed: `pnpm --filter @paperclipai/ui build` after the concurrent
memory failure.
- The mobile preview frame needed spacing to contain the feed scrollbar
gutter. Fixed the frame and repeated the browser checks.
- Addressed the first Greptile finding: source-linked follow-ups now
load with Streamlined UI off. A regression test covers that setting.
- Full local build and typecheck cannot complete because Cargo is
absent. The first concurrent UI build and UI typecheck were killed by
the workspace memory limit. Both UI commands passed when run separately.
The full local test run was stopped to fit that limit. PR CI must supply
the full-suite verdict.

## Risks

- Low risk. Delayed task reads can insert an older card into a loaded
feed. Stable task IDs preserve the card during status updates.
- New cards use the same access-checked task data as the Tasks panel. No
task mutation or permission change is added.

## Model Used

- OpenAI Codex, GPT-6. The runtime does not expose a more specific model
ID or context size. Used reasoning, tool calls, code edits, tests, and
browser automation.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 21:42:24 -05:00
DottaandPaperclip 8ff812cdde feat(chat): deliver proactive task messages to agent chats (#18374)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat gives each person a persistent conversation with each
agent.
> - Tasks and routines produce results outside that conversation.
> - Those runs need a safe way to bring a requested result back to the
person.
> - The server must select the agent's own chat and check the source
task's access rules.
> - This pull request adds proactive chat messages and unread
indicators.
> - People can see the result, open its source task, and reply in the
same chat.

## Linked Issues or Issue Description

**Subsystem affected**

Server, native runner tools, shared contracts, database, and UI.

**Problem or motivation**

An agent can report progress on a task or comment on an authorized task.
It cannot send a routine result to its own standing chat with the
responsible person. A morning review routine therefore cannot leave a
visible digest in that person's chat.

**Proposed solution**

Add `send_chat_message({body, idempotencyKey})` and `POST
/api/agents/me/chat/messages`. The server selects the company, agent,
and responsible person from the active run. It saves an attributed
comment and audit record in one transaction. The chat shows a
source-task link and per-person unread state.

**Alternatives considered**

A destination parameter on a generic comment tool would expose
unnecessary routing authority. A new delivery worker would add another
durable delivery path. This change uses a dedicated tool and the
existing comment and live-event paths.

**Roadmap alignment**

This extends the experimental Agent Chat capability in `ROADMAP.md`. The
existing `enableAgentChat` setting controls it. Related public work:
Refs #13282, Refs #13283, and Refs #14408. Searches for proactive chat
and unread chat found no duplicate PR.

## What Changed

- Add a focused messaging service shared by the native tool and HTTP
route. It checks current run ownership, execution mode, recipient
membership, task access, and task privacy.
- Reuse the canonical company/agent/person conversation. Save the
comment and audit record together. Keep task completion and chat
execution separate from delivery.
- Add source-task provenance and source-scoped retry keys. Identical
retries return the saved receipt. Changed content returns a conflict.
- Enforce the conversation's fixed agent at the shared comment-write
boundary. Keep normal reply cancellation and session checks.
- Add chat unread state, accessible agent dots, aggregate Chat
indicators, and visible-message read cutoffs. Refresh through existing
live events.
- Add the request-key constraint, native tool contracts, documentation,
capability maps, stories, and regression coverage.

## Verification

- Local delivery/security proof: all 38 proactive-message cases pass.
Eight credential-scope regressions and four quota regressions fail
against the prior source. The repaired delivery and canonical
cross-issue cap suites pass all 49 cases; all 31 OpenAPI tests, server
typecheck, and capability-map checks pass. The shared per-run cap covers
native and HTTP sends, mixed ordinary mutations, concurrent last-slot
contention, and retry/recovery without double charging.
- Credential tests preserve the authenticated person and authorizer;
reject bridge/test credentials and persisted skill-test runs after
task-mode changes; and recheck API-key revocation, scope, and
responsible person after destination locking. The earlier
delivery/native-authority suites passed all 74 cases before the four
quota additions.
- Four PostgreSQL contention cases cover native and HTTP sends plus
retries during a native chat mutation. All four deadlock against the
earlier source and pass with destination-before-source/run locking.
Recovery and human-reply delivery enqueue only the human comment; a
proactive digest never wakes the chat agent.
- Passed 108 companion conversation, native-authority, and OpenAPI
tests; 112 runner catalog/workflow-report tests; 47 completion-delivery
tests; and 25 project-handoff tests. Focused runner tests cover native
tool availability without generic API tools.
- All 327 affected UI tests, UI typecheck, token gates, and catalog
checks pass. The read hook retries at most three times, respects server
retry delay, coalesces only seen cutoffs, recovers on reconnect, and
cancels on scope changes.
- Real browser journeys with a deterministic process agent verify
routine-to-chat delivery, first-chat creation, unread state across
reload, the source link, secondary chat navigation, and a follow-up
reply referring to the digest. This does not qualify live GitHub
retrieval or model output quality.
- The Storybook showcase uses production components with deterministic
network fixtures. Rendered interactions pass for the landing, ordinary
read success, transient read recovery, and persistent failure after
bounded retries. Both Chat navigation variants update from two unread
chats to one while only Kodi's dot clears. Mobile and light variants
were reviewed. The existing Coordinator Recents label contrast finding
is unchanged; no Linux visual baseline archive exists.
- Current master's independent sandbox migration retains 0418.
Regenerated the feature migration as 0419 from the combined schema and
retained exactly the newest five snapshots; numbering/safety, replay,
and schema-drift checks pass.
- Workspace typecheck and build passed before PR preparation; canonical
server/UI typechecks passed again on the combined tree. Migration
`0419_slippery_impossible_man.sql` passes safety and schema drift checks
on disposable PostgreSQL, including interrupted index repair, concurrent
migrators, one-time owner read-state backfill, preserved receipts, and
two SQL replays. A default five-second local snapshot comparison timed
out; a diagnostic 30-second run passed without drift.
- Earlier failures are retained in the record: full local `pnpm
test:run` and broad shards encountered embedded-PostgreSQL startup,
timing, and provider-recovery failures. Thirteen selected
external-channel cases pass in isolation on the original and changed
sources; an unordered comment-row assertion now explicitly orders both
reads. The earlier route registry, native tool count, runner catalog,
and accessible Chat badge-name failures were fixed and passed full
remote CI on `920b3bb7db`.
- Repeated managed-skill server8 failures came from CI's newer synthetic
merge: its Cloud guard correctly rejected the old local-disk fixture.
Master independently repaired the fixture in #18385; this branch keeps
that repair unchanged. All 57 managed-skill and Cloud prerequisite cases
pass on the combined tree, and that fixture has no remaining PR diff.
- Current reviewed head `dc16f314739a6d977bed21cb1446d0e80a541578`:
Greptile 5/5 with no findings, Superagent security assessment passed,
advisory Paperclip Review 5/5 with no findings, and zero open review
threads. All 55 current-head check runs pass, with five expected skips
and the advisory review neutral at 5/5; Snyk also passes. No checks are
pending or failing. Protected squash auto-merge is enabled and is
waiting for required code-owner approval. A normal exact-head merge was
refused by the base-branch policy; no admin bypass was used. The
previous head's Superagent quota finding is fixed and covered above.

## Risks

- Chat remains company-visible. Delivery rejects a source task with
private-task, project, or ancestor restrictions.
- Read state uses a comment timestamp cutoff. The server retains
database precision and never moves a read receipt backward.
- The new unique constraint changes comment query planning. An existing
regression now uses an explicit row order. The migration builds the
unique index concurrently, then takes a brief table lock to attach it.
It uses the existing top-level migration and interrupted-index recovery
path.
- The upgrade backfills missing chat-owner read-state rows at the latest
existing agent comment. Existing read receipts remain intact. New chats
can still be unread before the human participates.
- Quota observation commits atomically with delivery. A rejected send
rolls back its attempted denial audit row and any first-chat creation;
the canonical warning remains in server logs, and previously spent quota
remains enforced. Identical/conflicting retries and receipt recovery
spend no extra slot.
- This version delivers in-app only. It adds no external-channel, push,
or email delivery.
- Local full-suite acceptance remains limited by the failures recorded
above. The feature stays behind `enableAgentChat`.

## Model Used

OpenAI Codex. PR preparation and CI work used `gpt-6.1-sol` with tool
use and code execution. The earlier implementation also used Codex, but
its exact model ID was not recorded in the visible session. The
context-window size was not provided.

## 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 focused tests locally and they pass; the broad local
failures are recorded above
- [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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 21:39:07 -05:00
DottaandPaperclip 6dcf4160dd perf(chat): load recent messages and page history on scroll (#18358)
## Thinking Path

> - Paperclip lets people manage work done by agents.
> - A standing agent chat can hold months of conversation.
> - The chat route forced full-history mode, bypassing compact task
loading.
> - A cold visit fetched lifetime run summaries and hydrated historical
transcripts.
> - This PR starts with 20 recent messages and loads earlier pages on
upward scroll.
> - It preserves the reader's position, current questions, and draft
while history grows.

## Linked Issues or Issue Description

**What happened?**

Standing agent chats forced full-history loading. A long conversation
fetched full activity and run history before it became readable. Earlier
comments also used an explicit load control.

**Expected behavior**

Open a small recent conversation quickly. Load older messages when the
reader scrolls upward. Show an inline loading state. Keep the visible
message and composer mounted through paging, live updates, and Back
navigation.

**Steps to reproduce**

1. Open a standing agent chat with hundreds of messages and completed
runs.
2. Use a fresh browser query cache.
3. Observe full activity and run reads plus transcript requests for
historical runs.
4. Compare the recent window and upward paging after this change.

Related work: #18312 and #18323 restored compact task and collection
loading. #14848 added reopening of visited agent chats. A GitHub search
found no open PR for this chat-history optimization.

## What Changed

- Return 20 contiguous recent comments for standing chats, with a stable
oldest cursor. Keep the existing compact task exchange contract. Use the
existing company/issue/time index for cursor reads.
- Keep chats compact even if their task view previously expanded
history. Retain observed messages through live catch-up and cache-backed
return visits.
- Keep fetched history pages, acknowledged sends, and the observed
recent cursor separate. Reconcile live replies without losing history
after a send or deleted cursor.
- Hydrate metadata only for newly revealed message/run IDs; preserve
prior batches while paging. Slow-send recovery refreshes the recent
window. Receipts failures have an independent retry.
- Hydrate run summaries only for loaded messages and the latest turn.
Validate batches of at most 100 run IDs and keep the existing
issue/company access rules.
- Reuse hydrated terminal native streams when only history membership
changes. Preserve retry, resume, mode changes, reconnect recovery, and
interrupted recovery reads.
- Load older messages, decision receipts, and task handoffs through
upward scrolling. Support wheel, touch, and keyboard input. Keep pending
questions visible.
- Reserve a status slot while loading. Preserve a logical message anchor
and the mounted composer. Pause failed page reads until an inline Retry.
- Add database, route, controller, and scroll regressions, plus an
opt-in production-build browser rig for long chats on desktop and
mobile. Update design and feature/access documentation.

## Verification

- The real PostgreSQL cold-open suite passes all 12 tests, including
contiguous pages with equal timestamps, complete history, company
denial, and scoped run IDs.
- Activity route and OpenAPI suites pass 53 tests. The route run allowed
local cold-import overhead; CI retains the repository's normal timeouts.
- Three new paging regressions fail against the unchanged source. The
candidate's focused paging/window suite passes 26 tests. Broader UI
verification is recorded below when complete.
- Desktop and mobile browser acceptance covers recent-only startup,
per-frame reveal geometry, delayed and failed older pages, stable
reading anchors and drafts, Back, older comment links, and one persisted
live reply.
- Full workspace typecheck and build passed locally. The final UI source
also passes its typecheck and production build.
- Affected UI suites pass: 212 controller/history/paging tests, 352
thread/scroller tests, 26 native-stream tests, plus metadata batching
and live-cache hydration coverage. The issue mutation/access route suite
passes 179 tests.
- All 22 final desktop/mobile browser journeys pass, including delayed
image growth. The isolated second-page request proof also passes six
repeated desktop/mobile runs. A separate 6,000-message, 3,000-run
fixture passes cold-open and delayed-paging checks on both screen sizes,
still opening 20 messages and loading one 50-message page.
- Final matched production timings use baseline `aa58fa1073`
(`index-BaRiMbxd.js`) and candidate UI source `f9a26b9783`
(`index-DPWTbsFF.js`, identical application source at final head
`bf71ffd5af`). Chromium 151.0.7922.34, 1440×900, 4× CPU throttle, no
added network latency, browser HTTP cache disabled, fresh application
cache for each cold visit. Both variants block service workers and use
the same warm local API server and immutable 600-message/300-run
fixture. Only document HTML is intercepted for both variants; API
requests are real. The common API revision is `109981f8c1`; subsequent
commits change only UI and tests.

| Usable conversation | Baseline median (range) | Candidate median
(range) |
| --- | --- | --- |
| Cold direct URL | 6.57 s (5.69–7.45) | 3.07 s (2.50–3.28) |
| Warm in-app return | 3.76 s (3.54–4.76) | 0.67 s (0.58–1.46) |
| Back return | 2.53 s (2.12–4.20) | 0.51 s (0.47–1.18) |

Five pairs alternate order. Every paired difference favors the candidate
for all three journeys. Readiness requires a revealed, fully visible
latest reply above the composer and an editable composer. Return timing
starts after the Tasks route renders. Cold API requests fall from
953–954 to 71; API wire bytes fall from 517–559 KB to about 49 KB.
Separate CPU profiles and request waterfalls confirm the removal of
lifetime event hydration and are excluded from the five timing pairs.
Both variants have the same expected missing optional plan document
(404) and no browser exceptions. Control recent-window API reads have
medians of 37 ms / 32 ms, with shared-host outliers up to 376 ms.

The 6,000-message recent-window SQL uses
`issue_comments_company_issue_created_at_idx` (22 index rows read for a
21-row probe). Geometry assertions retain a 2-pixel tolerance for the
reading anchor and first-reveal layout. These are local synthetic
measurements, not deployed staging latency. Earlier timing probes are
excluded because they did not isolate service workers or composer
clearance. Final head `bf71ffd5afb5684ba9105a3127f617e7adf5139c` has 55
successful checks, three optional skips and one neutral result, with no
failures or pending checks. Greptile is 5/5 with no open review
findings.

### Failure record

Early local attempts exposed an unconditional scroller wrapper that
changed the old task layout, and automatic retries on chat page
failures. Both were corrected. The original task scroller structure
stays in place. Metadata request assertions wait for initial connection
recovery to settle, then verify only the new page’s reads;
retry/resume/reconnect revalidation remains intentional.

The initial review caught a send-before-scroll cache defect; its
controller regression failed before the fix. Later rapid-paging checks
caught scroll readiness being gated by metadata after the first reveal;
readiness now stays enabled once revealed. Live replies use the separate
acknowledged-message cache, then catch up from the server cursor.

Visual review exposed a pagination wrapper bypassing existing composer
clearance. The body is again a direct scroller child; cold-open browser
checks require the full latest reply above the composer. A
resize-observer regression failed before the fix and now passes.
Controlled delayed inline images prove both pinned following and a
stable reading anchor on desktop/mobile.

The first performance fixture lacked valid native event envelopes and
caused missing-log fallbacks. It is excluded from latency claims. The
final fixture uses saved native assistant events and conversation
session generations. The live test uses a temporary fixture-agent key,
attributes the reply to an existing synthetic run, and revokes the key.
It starts no model or agent process.

Local database attempts failed during a Docker shutdown. The retained
disposable database was restored and its suite passed. Early fixture
errors included a missing conversation identity field and session
generation. Mobile test setup also selected an offscreen sidebar link
and reused queued human input. Optional announcements could intercept
input; the fixture now dismisses them before the journeys. The scroll
observer now waits for the delivered wheel event and settled animation
frames, including when the viewport is already at the top. A
concurrently running live test briefly changed another probe’s row
count; the final acceptance and timing runs were sequential on separate
fixtures. The final rig uses the visible mobile navigation and a saved
agent reply. Anchor observation waits for the user's scroll to settle
before measuring the effect of live updates.

The full local `pnpm test:run` attempt hit repeated embedded PostgreSQL
initialization failures and failures in untouched native-session
executor suites; it was stopped after the repeated environment failures.
The targeted real-PostgreSQL suite passed, and final-head CI is required
before handoff. The first CI run also caught an exact mock expectation
missing the added company scope; the expectation is updated and its
179-test suite passes. The final-head first CI attempt also stalled an
assigned child task in the existing plan-approval scenario, then hit a
heartbeat-run row lock timeout during fixture cleanup. The failed shard
and aggregate check passed on an unchanged rerun of the same commit.
Scenario assertions and timeouts were unchanged. The failure and rerun
are retained in [CI run
41116120430](https://github.com/paperclipai/paperclip/actions/runs/41116120430).

## Risks

- Historical transcript diagnostics no longer load on a cold chat open.
Saved messages and conversation events remain available; diagnostic run
views keep their full records.
- Cursor paging must not omit comments with equal timestamps. Database
tests cover timestamp/UUID ordering and the complete set.
- Prepended or late content can move the reader. Browser checks cover
retained row identity, viewport offsets, mounted drafts, and Back.
Previously loaded pages stay in the query cache for its existing
lifetime.
- Local synthetic evidence does not establish deployed staging latency.
This PR does not merge or deploy the change.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, tool use, and code
execution. The exact backend deployment ID and context window were not
exposed in this session.

## 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 (affected checks; limits
are recorded above)
- [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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 15:12:24 -05:00
DottaandPaperclip 5a7a6b32ba fix(ui): restore compact Coordinator task loading and responder continuity (#18312)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People open tasks from their personal workspace and send replies to
agents.
> - Cold task opens should load recent conversation before older
history.
> - Classic settings could expand history before the Coordinator
preference arrived.
> - Coordinator lists also read full tasks, and response startup used
the previous assignee.
> - This pull request restores compact reads and keeps the selected
responder visible through runtime discovery.
> - People can read and reply without waiting for unrelated history or
losing response feedback.

## Linked Issues or Issue Description

Related: #17593, #17751, #17756, #17885, #17983, and #18092.

**What happened?**

A cold task could select Classic full history while its personal
workspace preference was pending. The full-history choice stayed cached
after Coordinator became active. Coordinator Tasks used full task reads.
Needs attention fetched one enriched task per pending task.

Sending to a newly selected agent could show no responder, show the
previous assignee, or clear feedback when assignment changed. Legacy
runtime discovery then replaced the startup identity with a generic
activity line.

**Expected behavior**

Wait for the workspace preference before selecting Classic history. Show
the task instruction and recent conversation with **More messages** for
older content. Read collection indexes and fetch diagnostics for visible
rows. Keep the selected responder mounted from Send through saved input
and runtime startup.

**Steps to reproduce**

1. Enable Classic task UI and Coordinator. Delay the personal workspace
preference on a cold task open.
2. Open Coordinator Tasks or its Needs attention view with many pending
tasks.
3. Open a task assigned to a person. Select another agent in the
composer and send a message.
4. Let the message save before runtime reads return. Then allow a legacy
run to appear.

## What Changed

- Wait for task interface settings before persisting Classic history
expansion.
- Use lightweight indexes for Coordinator Tasks. Resolve pending task
IDs in batches of at most 100. Keep search and participant filters on
the server. Enrich at most 50 visible rows through the existing hook
without replacing list membership or order.
- Preserve an error when a pending task cannot load, instead of showing
a false all-clear.
- Register board cards for row enrichment. Observe newly mounted cards
after column expansion or pagination, and track visibility by element so
hidden list rows cannot clear visible board cards with the same task ID.
- Track the recipient of each submitted message through reassignment. A
later draft's recipient does not change the response already starting.
- Share a stable response header across startup, native runtime, and
legacy runtime rendering. Keep the existing transcript renderers.
- Add regression tests, production-browser checks, design guidance, and
feature-map notes.

## Verification

- Red/green: delayed Coordinator preference started a full comments read
before the fix. It now retains compact history and still expands on
request.
- Red/green: sends from human or other-agent assignment showed no
identity or the wrong identity. Both now retain the selected responder
through assignment, acknowledgement, later draft selection, and
native/legacy startup.
- In a 105-task Needs attention fixture, the previous code made 105
enriched detail requests. The fixed code makes two bounded index
requests.
- All 659 final affected tests pass across task detail, thread, runner
turn, history window, Inbox, board, row enrichment, and Coordinator
collection suites.
- Review follow-up: the production board lost its next-step badge before
card registration. The regression now passes, along with column
pagination. The focused 82-test enrichment run and 371-test
header/thread run also pass.
- All 12 compact-startup browser checks pass against the production UI
and an isolated PostgreSQL container. They cover delayed preferences,
list navigation, saved-card geometry, document/comment anchors, history
expansion, draft retention, retry, and actual legacy process startup.
The final deterministic process case recorded 118 frames with zero
missing or replaced responder identities. It does not call a model
provider.
- Full workspace build and typecheck pass. Final UI build and typecheck
pass after the shared-header change. Token gates, map checks, module
boundaries, and diff checks pass.
- The full UI rerun before the board review follow-up passed all 10,034
tests across 844 files. The 659 affected tests pass after that
follow-up. The first full UI run passed 10,030 tests and timed out in
one unchanged IssuesList large-tree test. Its two variants pass in an
isolated rerun and in the full rerun. Those later passes establish
recovery; the earlier timeout's cause remains unproven.
- The full `pnpm test:run` attempt was stopped after repeated embedded
PostgreSQL initialization failures in server fixtures. No complete local
server-suite pass is claimed. Browser verification recovered with a
disposable container database.
- A later avatar browser rerun reused the previous same-title task and
its cancelled run through the existing 48-hour title deduplication. That
fixture never reached fresh runtime startup. The test now uses a unique
title and checks its initial assignment/status; a full 12-case rerun and
a second avatar run on the same instance pass. The failed trace is
retained locally.
- Final commit `7a18372da3` has 55 successful checks, two intentionally
skipped Storybook checks, and one neutral Paperclip Review. All required
verification gates are green. Greptile is 5/5 with no actionable
findings or open review threads. The advisory Paperclip review paused
without a complete assessment; no passing Paperclip assessment is
claimed.
- These checks establish bounded reads and stable rendering. No reliable
staging latency benchmark or staging deployment is claimed.

## Risks

- Collection projections omit task bodies. Detail navigation must retain
its normal core/full task reads. Search remains server-side.
- Startup feedback must end on rejection, unavailable agents, terminal
outcomes, or a visible run. Existing cases cover those transitions.
- The shared header changes the legacy live-turn layout to retain
identity beside its existing status line.
- No migration, mutation permission, provider protocol, or execution
authority change.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving deployment ID and
context-window size are not exposed in this session. The model used
reasoning, code editing, shell tools, automated Chromium checks, and
manual browser inspection.

## 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 (focused suites and browser
checks; full-suite limitations are recorded above)
- [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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-30 09:03:03 -05:00
DottaandPaperclip 61bd4ac691 feat(agents): set up Antigravity with saved Google subscriptions (#18189)
## Thinking Path

> - Paperclip manages agents and their work.
> - Users choose providers and managed accounts while adding agents.
> - Antigravity was missing from the ordinary additional-agent picker
and its saved Google path did not complete native readiness.
> - A user needs a successful Test, an enabled task action, and a stable
account binding.
> - This pull request connects the ordinary setup flow to the native
candidate.
> - It also preserves retired credential refreshes across database
failures and server restarts.

## Linked Issues or Issue Description

Built on merged #18188 and #18187. Refs: #12503, #14938 for related
legacy CLI proposals.

**Agent or provider**

Google Antigravity ACP 1.4.3.

**Why this adapter is useful**

Users need to set up an Antigravity agent and run real work through
their managed Google subscription.

**How the agent is invoked**

Native Paperclip Runner uses the pinned Antigravity ACP runtime. Exact
operator admission remains required; the local candidate result does not
enable general release.

## What Changed

- Show Google Antigravity in the ordinary adapter grid and preserve the
draft choice when setup resumes.
- Reuse the same user’s saved personal default Google subscription and
discover the exact low model through the native account.
- Run a prompt-free native Test and wait for authoritative readiness
before enabling task assignment.
- Carry the managed account through native runs and recover retired
refreshes through the existing encrypted, fsynced journal with exact
generation checks.
- Retain the latest rotated credential through verification, storage,
and partial home-removal failures. Retry the exact account’s retained
cleanup before another provider use.
- Reconcile cleanup before taking the credential mutation lock, fence
owners arriving during lock acquisition, and support nested lock holders
without a join cycle.
- Bound sign-in retirement outside database transactions and preserve
claims for the existing cleanup owner; one pending sign-in does not
block unrelated accounts.
- Cover Gemini and Pi API-key recovery, keep API-key bulk manual-model
editing usable, and keep adapter discovery available after candidate
expiry.
- Skip taskless native timer work before run or credential admission.
Preserve current master monitor and deadline scheduling.

## Verification

- The registered local saved-Google-subscription journey passed all 16
matchers in 196,520 ms using eval source `12aba` against actual serving
source `4a37ee7c`. Both turns stayed in one conversation, produced exact
downloaded files of 61 and 119 bytes after reload, and used distinct
native primary processes. All observed owners retired, leases released,
and credential fences settled. Independent readback confirmed Done work,
no active owned runs, a connected saved account, and the retained agent
paused for inspection.
- The measured runtime is production-equivalent to pre-restack
`65ef31dc` except its test-only transport fixture correction.
Current-master head `ff7c9249` preserves all 99 product paths: 98 exact
blobs and only eight inherited plugin-panel lines in `agents.ts`. Its
native binary was rebuilt for inherited Codex-only diagnostic changes;
the changed Rust behavior is outside Antigravity's ACPX execution path.
Shared native/UI changes have focused regression coverage. The recorded
live result is not represented as a measured replay of `ff7c9249`.
- Full workspace build and typecheck passed on `ff7c9249`. All 376
focused tests in 14 files passed, covering Google credential/retirement
controls and the inherited native-tool, redaction, route, and UI
recovery changes. Token gates, maps, and diff checks passed. The
required-close fixture was separately demonstrated red, then passed all
317 selected provider-wiring cases.
- [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/40959387972)
is green: 55 successful checks, two skipped workflow checks, and an
optional neutral review check. Required `ci / verify` and `ci / e2e`
passed. Greptile and Paperclip Review both report 5/5 on exact
`ff7c9249`, with zero unresolved review threads.
- This qualifies the selected operator-authorized local
saved-subscription candidate. The original exploratory journey remains
historical evidence; the repeatable fixed-driver eval is in the next PR.

## Risks

- Google refresh recovery must preserve the exact grant, account, and
credential generation. An uncertain native owner or failed encrypted
handoff retains the private home and blocks cleanup.
- A successful local saved-subscription candidate does not qualify fresh
OAuth, API keys, Cloud, Linux, other models, or general release.
- Timer filtering changes only taskless native Runner admissions.
Existing task-bound monitors and legacy adapters retain their owners.

## Model Used

OpenAI Codex (GPT-6). The host did not expose the exact model revision
or context limit. The model used tools for code edits, tests, and
review.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 16:51:50 -05:00
DottaandPaperclip 7e27bc5007 fix(tasks): keep anchored opens compact and stabilize saved cards (#18092)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task pages must make the current instruction and recent conversation
readable quickly.
> - Compact startup avoids reading all earlier messages and run
activity.
> - Every URL fragment previously selected the full-history path, even
for documents.
> - Saved document cards also arrived after the conversation was
visible. PR statistics could add another row later.
> - This pull request keeps anchors compact and reveals the saved
conversation structure together.
> - The benefit is stable reading position without loading unrelated
history.

## Linked Issues or Issue Description

Related: #17593 introduced compact startup. #14667 covers earlier reveal
and scroll work. This fix retains the bounded history contract.

**What happened?**

Opening a task document link loaded all task history. Ordinary cold
opens could reveal messages before saved document cards and plans
arrived. Later PR metadata added a statistics row and changed card
height.

**Expected behavior**

Every URL fragment keeps compact startup. Document links open their
pane. Older-comment links fetch only the target comment. Saved cards
keep their geometry after first reveal.

**Steps to reproduce**

1. Create a task with many comments, a saved plan, documents and saved
PR work products.
2. Delay the enriched task response and open the task. Observe cards
inserted after messages appear.
3. Open a document fragment. Observe full comment, activity and run
reads.
4. Delay PR metadata refresh. Observe each card grow when diff counts
arrive.

## What Changed

- Remove fragment and tab checks from automatic history expansion.
Resolve validated comment UUIDs through the authorized single-comment
endpoint, encode their path components, retain fetched targets across
document navigation, and preserve cancellation/deletion cache updates.
- Include the saved plan, document metadata and local work-product
projection in the core task read. Skip recovery, workspace and
related-task enrichment. Do not refresh providers. Summary queries no
longer select other document bodies.
- Seed saved work-product and plan queries from core, including already
pending or errored reads, without replacing known lists or an
authoritative empty result. Coordinate the bounded recent reads, saved
cards, latest transcript and settled initial pane width before first
reveal. Keep the thread and composer mounted during refresh and explicit
expansion.
- Open continuation summaries in the document pane. Reserve PR
statistics geometry while provider metadata loads.
- Add a reusable synthetic local task, nine browser checks, frame
measurements and video. Extend the PostgreSQL core-route fixture with a
saved PR row and assert its identity, URL, state and stored metadata
survive the response. Update design guidance and capability maps.

## Verification

- Red: visible document/plan cards changed from 0 to 1 to 4; thread
height grew from 690 to 1,432 pixels. Green: all seven saved cards
appear before reveal, with constant thread height and zero per-card
movement in the final reviewed browser run. The final 1,492-pixel layout
includes the reserved PR statistics lines.
- Red: delayed PR diff counts changed all three cards from 62 to 82
pixels. Green: their heights stay at 82 pixels before and after metadata
refresh.
- Nine browser journeys pass: delayed enrichment,
document/comment/unknown/continuation anchors, document clicks and
explicit history expansion with a retained draft, missing-comment retry,
delayed PR statistics, and retained older-comment position after
document navigation.
- 583 focused UI tests passed on `c91fa107ba`. After the plan-cache
follow-up, all 212 affected page/cache/plan-hook tests and UI typecheck
pass, including 14 plan-hook cases. The original 16 focused PostgreSQL
tests passed for the server changes.
- Merge-review red: holding the duplicate stored work-products read
blocked the first reveal past 10 seconds despite core already containing
the saved cards. Both empty and populated core projections now reveal
while that request remains pending. Malformed-comment tests prove no
target request is made; API tests prove path encoding and abort-signal
forwarding.
- The populated core-route test now inserts a real saved PR work product
alongside the plan and documents, then checks the complete saved
projection through HTTP. All ten task cold-open PostgreSQL tests pass.
- Plan-cache review red: an existing pending or errored plan query
prevented the saved core plan from reaching the consumer. Four real-hook
cases failed before the data-presence fix and pass afterward, for both
present and absent plans. A separately fetched newer plan or known
absent plan remains authoritative.
- Further layout red: the initial properties pane reduced visible thread
width from 775 to 742 pixels after reveal. The reveal now waits for two
stable width frames; the browser check includes width, height, card
counts and per-card geometry.
- `pnpm -r typecheck` and `pnpm build` passed for the original change;
UI typecheck and build pass after review fixes. Token, module-boundary
and map checks pass. `pnpm test:run` was stopped after about 15 minutes
in the serialized server lane. No full local test-suite pass is claimed.
On the earlier head, hosted build/typecheck and all Vitest lanes passed;
one E2E shard failed because the agent-configuration clipboard helper
copied page text into its YAML parser. On `c91fa107ba`, Greptile was 5/5
and every E2E shard passed, including the earlier clipboard case. One
unchanged Discord chat-binding test in server shard 8 returned false
after 185 ms; its 16-test integration file passes locally without
changes. The CI cause remains unestablished. On `be436ce492`, both
server shard 8 and E2E shard 7 passed without changing those tests or
their product code. On final head `e357b3bced`, all CI jobs pass,
including full general and serialized tests, all eight E2E shards,
typecheck, build and the aggregate verification gate. Exact-head
Greptile is 5/5 with no findings. The overall status rollup contains 55
successes, two intentionally skipped Storybook checks and a neutral
Paperclip Review. That advisory review ended without a complete
assessment; all previously posted findings are resolved and it added no
current findings.
- Test startup exceeded an initial 5-second deadline once while
development assets and other checks were active. The final browser
checks allow 10 seconds. These runs establish geometry and bounded
requests; they do not establish a reliable latency improvement. An
initial 503 error fixture exercised global reconnect/backoff. The
target-comment failure test uses a terminal 404.
- Browser data is synthetic. Provider metadata is simulated for the
delayed-response check. No staging deployment or live provider execution
is claimed.

## Risks

- Core task reads now include local saved-card queries and the saved
plan body. Other document bodies and all historical run activity remain
outside that path.
- First reveal waits for the bounded current structure. The existing
15-second incomplete-history fallback and inline retry remain available.
- Continuation-summary links open in the document pane in the current
task interface. Classic tasks keep their existing surface.
- No migration or mutation permission change.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, code editing, shell tools
and browser testing. The exact serving model ID and context-window size
are not exposed in this session.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 09:13:01 -05:00
Nicky LeachandPaperclip 80a2b9284b Define durable runtime activity events (#18129)
## Thinking Path

> - Paperclip manages agents and tasks.
> - Runner reports durable run events through PRP.
> - Runtime clients need a typed record of reported activity.
> - The event must keep the normal run authority and read boundaries.
> - This pull request adds the generic runtime activity event contract.
> - Later PRs can publish and consume this contract without private
plugin coupling.

## Linked Issues or Issue Description

First feature prerequisite extracted from #18050. Runner publishing is
#18050; the dependent consumer is #18131. Related independent test
stability work: #18128. The parent search and review history is
preserved in [the verification
archive](https://github.com/paperclipai/paperclip/pull/18050#issuecomment-6489369676).

**Subsystem affected**

Runner event protocol, server run-event persistence and redaction, and
UI event taxonomy.

**Problem or motivation**

Core needs a durable, typed activity record tied to the authenticated
run. A text marker is not an event contract.

**Proposed solution**

Add `runtime.activity.recorded` as a P1 event with a closed `{
namespace, activityKey }` payload. Runner knows no plugin or panel
identity. Run/session identity, sequence and emission time stay in the
outer envelope; Core resolves company, task and agent through the
authorized run binding. Use the existing authenticated persistence,
acknowledgement, replay and redaction paths.

## What Changed

- Define and validate the event in PRP v1, v2 and v3. Update the
generated protocol artifacts and event catalog.
- Preserve saved and live event redaction. Test persistence, replay
deduplication and the existing run-read boundary.
- Register the event in the UI taxonomy without changing panel display
behavior.
- Advance the source-bound Copilot identity to 78. Retain all published
historical identity fixtures without changing their bytes.

## Verification

- Root `pnpm typecheck` and `pnpm build`: passed for the revised
activity contract.
- Node protocol checks: 14 passed. Provider identity and registry tests:
185 passed. Server tests: 103 passed. UI event registry: five passed.
- Maintained Grok and Copilot identity generator checks and `git diff
--check`: passed.
- The first activity-contract review scored 4/5 because the dependent
producer and readers still used the earlier contract. Both dependent PRs
are now updated and restacked; the finding is resolved and review is
running again.
- Initial extraction retained a consumer-only import in one server
suite. That suite failed to load. The consumer case and import were
moved out; the final three server files passed all 103 cases.
- Earlier panel-specific head `6137c50bc` had green CI and standard/Apex
5/5. Those scores do not qualify this revised activity contract. Fresh
CI and reviews are pending. Earlier combined results in the archive
apply only to their recorded source revisions.

## Risks

This change is additive. It adds no route, publisher, filesystem
transport, provider sandbox grant, or panel display behavior. Activation
hints grant no permission to read a plugin view. Provider identities
bind the changed protocol source; historical identities remain
decode-only. No schema migration or dependency change is required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository tools and code
execution. The exact serving snapshot is not exposed.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-29 00:32:12 -07:00
scotttongandPaperclip 71f0c0c99e feat: add opt-in Coordinator workspace for chat, tasks, and decisions (#17983)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/147/changes/paperclip/147
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People coordinate work through conversations, tasks, and requests
for input.
> - These surfaces must share task state and preserve the context of
each decision.
> - The existing workspace makes people switch surfaces to follow that
context.
> - This pull request adds an optional Coordinator workspace with linked
conversations, tasks, documents, and decisions.
> - Each person can enable it in Settings > Experimental and return to
the classic workspace.
> - The benefit is a coherent path from a request to an assigned task
and reviewed work.

## Linked Issues or Issue Description

**Subsystem affected**
UI, server, shared contracts, and database.

**Problem or motivation**
People need a consistent way to start tasks from agent conversations,
answer questions, review work, and return to the source context.
Decisions and task state must agree across these surfaces.

**Proposed solution**
Add a personal, default-off workspace experiment. Keep one conversation
per agent. Add task proposals, compact task and decision cards,
contextual document panels, and a Needs You queue with search, filters,
sorting, grouping, and history.

**Alternatives considered**
Replacing the classic workspace for everyone would remove the opt-out
path. Keeping separate decision state in each surface would create
conflicting answers. This change uses the existing canonical task and
interaction records instead.

**Roadmap alignment**
This supports the existing agent chat, task management, and human review
capabilities. It is an experimental presentation choice. The user
requested this isolated implementation after design review. No Discord
discussion is claimed.

## What Changed

- Add per-person workspace preferences, a default-off setting, and an
additive migration.
- Add Coordinator navigation, pinned destinations, task lists, agent
switching, and contextual panels.
- Link task suggestions and creation to the source conversation. Default
new task ownership to the current agent unless the user specifies
another owner.
- Share pending questions, decision receipts, exact review targets, and
history across tasks, chat, and Needs You.
- Preserve task access, assignment authorization, revision binding, and
required output review gates.
- Add compact document links, relative timestamps, composer controls,
and reduced-motion support for task and decision transitions.
- Add component stories, regression coverage, and capability-map
documentation.

## Verification

- Final head: `4b839aae1e314bd7e8635a766f1d205ff1c03ba6`, based on
master `8bc051245f77a47bee0f8ba45896b8bfa5922e0a`. Verified October 29,
2026 at 00:10 UTC: **MERGEABLE, 56 checks passed, four conditional
skips, no pending or failed checks**. [Current CI
run](https://github.com/paperclipai/paperclip/actions/runs/40790639688)
passed without a rerun on this head.
- Fresh Greptile **5/5**, zero new comments and zero open review
threads; Superagent passed with no suspicious changes.
[Checks](https://github.com/paperclipai/paperclip/pull/17983/checks).
- Local workspace typecheck/build passed after the latest rebase. The
final account-read patch passed UI typecheck/build and all 12 related
preference/settings tests, including a delayed real-client request
across account changes. Earlier scoped checks cover review
deduplication/replay, decision deep links, cross-surface state, access
boundaries, and migration replay.
- Local database/browser rechecks after the latest rebase were limited
by exhausted macOS shared-memory IDs: `initdb` failed before database
creation. The local run passed 31 UI/snapshot tests and skipped 24
database tests; those skips and the blocked local browser start are not
claimed as passes. The independent Linux CI database and browser checks
passed. No running dev database or host setting was changed.
- Upstream migration 0403 is preserved. Preferences and durable review
retry aliases are generated as replay-safe migrations
`0404_tense_silver_sable.sql` and `0405_harsh_avengers.sql`; five newest
snapshots are retained. Every detected conflict was rebased and pushed
before waiting for CI/review, as requested.
- The PR is unmerged. The active master ruleset still requires
code-owner approval for the changed Paperclip skill; no approval or rule
change was performed.

<details>
<summary>Earlier verification failures, integration history, and
evidence</summary>

These entries preserve prior checkpoints and failures; the current
acceptance result is above.

- Focused UI and server checks from the isolated build are recorded in
the implementation plan.
- Browser checks covered the opt-in shell, navigation, task/document
links, and decision card states. No new live provider trial is claimed
for this handoff.
- Current acceptance head: `4b839aae1e314bd7e8635a766f1d205ff1c03ba6`,
rebased onto master `8bc051245` immediately after its GitHub
review-repair migration took 0403. Preferences are generated as
idempotent `0404_tense_silver_sable.sql`, preserving upstream
SQL/journal/snapshot history and five newest snapshots. GitHub reports
MERGEABLE after the immediate lease-protected push. Scott's updated
instruction is to rebase and push every conflict resolution first,
without waiting for CI or Greptile; verification follows the push.
- The final reviewed feature tree was consolidated for repeatable
single-commit rebases. The complete previous commit history remains
reachable through local recovery ref
`codex/coordinator-recovery-before-rebase-20261028` (resolved snapshot
`0e1bbdf4e`). The actual rebase completed, and its tree hash exactly
matches that resolved snapshot. The force-with-lease required the known
remote head `0e6ef7c44`, protecting against concurrent branch changes.
No PR merge or permission/runner setting change occurred. Fresh
CI/review are in progress for the current head.
- `2001132fa` received Greptile 5/5 with one nonblocking account-switch
read finding. Current head detaches path-coalesced preference GETs and
disables HTTP caching, retaining React Query's account-scoped sharing. A
delayed real-client GET regression proves account B can load its saved
choice before account A responds, and A's late response only updates A's
cache. Preference/settings tests 12/12 and UI typecheck passed; its
review thread is resolved. Fresh current-head CI/reviews are pending.
The prior CI chat shard 3 ended with “The operation was canceled” and no
assertion failure ([job
123171595631](https://github.com/paperclipai/paperclip/actions/runs/40789688333/job/123171595631),
`/tmp/pr17983-2001132-chat3.log`); no code/timeout change is attributed
to that cancellation.
- `843e823b4` reached fresh Greptile 5/5 with zero comments/open threads
and Superagent pass. All browser tests including the repaired YAML shard
passed, and 54 checks passed. General server shard 9 ended with “The
operation was canceled” and no failed assertion; its test step was
marked cancelled (job
[123164350893](https://github.com/paperclipai/paperclip/actions/runs/40787501761/job/123164350893),
log `/tmp/pr17983-843e-server9.log`). A single unchanged-head rerun was
started after the workflow completed, but master moved while it ran. A
local nested-clone check timed out in its 30-second database-startup
hook and then failed cleanup before the 20 database cases ran; this is
retained as a local verification limit
(`/tmp/pr17983-843e-nested-clone-check.log`), not claimed as a pass or
proof of the CI cancellation cause.
- Following Scott's instruction, the new conflict was rebased and pushed
immediately without waiting for that rerun. Upstream's
`0403_natural_cerise.sql` is preserved; regenerated preferences and
retry-alias migrations are `0404_tense_silver_sable.sql` and
`0405_harsh_avengers.sql`, replay-safe with five newest snapshots
retained. The YAML helper conflict combines upstream's click and header
behavior with the editor-selection guard and injected regression.
Recovery ref `codex/coordinator-recovery-843e823b4` preserves pre-rebase
work. Current head is MERGEABLE. Full workspace typecheck/build passed;
UI and snapshot checks passed 31 tests, but 24 database tests were
skipped by the local support probe, and the local browser server could
not initialize PostgreSQL. A direct disposable `initdb` diagnostic
established the host limitation: `could not create shared memory
segment: No space left on device` (`shmget`, shared-memory IDs
exhausted, not disk space). No dev database or host setting was changed.
Diagnostics: `/tmp/pr17983-2001132-initdb-probe.log`,
`/tmp/pr17983-2001132-db-probe.log`; checks:
`/tmp/pr17983-2001132-tests.log`, `/tmp/pr17983-2001132-browser.log`,
`/tmp/pr17983-2001132-types.log`, `/tmp/pr17983-2001132-build.log`.
These local skipped/blocked checks are not claimed as passes; fresh CI
on independent runners is in progress.
- `d18f683cd` reached fresh Greptile 5/5 with zero comments/open threads
and Superagent pass, but [E2E shard
7](https://github.com/paperclipai/paperclip/actions/runs/40785966243/job/123159719925)
failed parsing an Advanced YAML clipboard read beginning with “Skip to
Main Content.” The log is retained at `/tmp/pr17983-d18f-e2e7.log`.
Current head hardens the test helper to verify editor focus and
selection, clear stale clipboard content, and require the YAML header at
the start of a fresh copy before parsing. Saved-state assertions and
timeouts are unchanged. All six Advanced YAML browser journeys passed on
a disposable local instance (41.0s); the exact lost-response journey
also passed with a one-time injected surrounding-page copy, verifying
rejection/reacquisition (17.6s). The precise browser focus/clipboard
timing in CI remains unproven; the observed invalid-read path is now
guarded and deterministically exercised. Logs:
`/tmp/pr17983-yaml-clipboard-scope-browser.log`,
`/tmp/pr17983-yaml-clipboard-injected-browser.log`. Fresh current-head
CI and reviews are pending.
- `19e6dcb0b` passed Superagent and Greptile 5/5, with one nonblocking
deep-link finding. Current head preserves attention links using
`?decisionId=`: the requested pending decision is rendered even beyond
the first 40 cards, focused and scrolled into view, then only that
parameter is consumed so later refreshes do not refocus. Other URL
parameters remain. Needs You tests 10/10 and UI typecheck passed; its
review thread is resolved. The preceding post-rebase regression run
passed 45/45 tests. Fresh current-head CI/reviews are pending.
- `6d772b7cc` reached Greptile 5/5 with zero comments/open threads and
Superagent pass. While 32 checks had passed, master moved and caused a
documentation conflict in `maps/feature-map/onboarding.md`. Rebased
immediately, preserving both onboarding paragraphs. The complete
four-commit branch was pushed as `19e6dcb0b` before waiting on
CI/review, per Scott's instruction. A transient Git index lock
interrupted the first continue; the command sequence briefly pushed
intermediate `34e298c07`, then the completed rebase was immediately
pushed. All feature and security/retry fixes are present; local recovery
ref `codex/coordinator-recovery-6d772b7cc` preserves the pre-rebase
history. The only tree differences from that ref are upstream's two
smoke-test files and the combined documentation paragraph. GitHub
reports MERGEABLE. Fresh current-head verification is in progress;
prior-head review results are not current acceptance.
- `21efa3120` passed Superagent but Greptile scored 4/5 for a valid
retry-key persistence bug: an acknowledged duplicate key could reopen a
resolved review. Current head adds an additive, replay-safe
`0404_light_swarm.sql` migration for indexed, task-scoped aliases from
acknowledged retry keys to the canonical interaction. Alias registration
and retry lookup occur under the existing task lock; payload/actor
mismatch still conflicts, and each canonical review permits at most 100
aliases. Original and acknowledged keys replay the terminal result
rather than creating a new gate. Five newest migration snapshots are
retained. Service/routes tests 165/165 passed; final quality review plus
migration replay/snapshot checks 25/25 passed; server typecheck passed.
The P1 thread is resolved in code; fresh current-head reviews and CI are
pending.
- `69c2c7543` passed 55 checks and Greptile 5/5 with no open Greptile
findings, but Superagent check
[123140675812](https://github.com/paperclipai/paperclip/pull/17983/checks?check_run_id=123140675812)
correctly flagged unbounded pending quality-card creation. Current head
fixes that under the existing task-row lock: equivalent requests with
fresh idempotency keys reuse the pending card; conflicting requests for
an unresolved deliverable return the existing interaction ID; pending
cards are capped at ten per task across all reviewers. Distinct outputs
remain independent, and already-answered items in a partially pending
batch can receive a fresh review. Added real-database concurrency,
cross-card duplicate, partial-answer, and hard-cap regressions. Quality
review 22/22 tests and final server typecheck passed; earlier
service/routes 163/163 tests passed before the final partial-answer
refinement. One added assertion initially expected a service HTTP error,
but duplicate keys are rejected earlier by the existing shared schema;
the assertion now verifies that validation. Fresh current-head
CI/reviews are pending; the action-required security result is not
treated as passed.
- `c9c575e5f` completed all 56 checks successfully with four conditional
skips, Greptile 5/5, and Superagent pass. Its two P2 review findings are
fixed in the current head: independently bound quality approvals now
each remain visible in attention; changing/clearing URL-backed
assignee/status filters updates the URL and survives task navigation.
Both review threads are resolved. Regression evidence: attention service
34/34 tests passed, CoordinatorTasks 20/20 passed, UI and server
typechecks and the full workspace build passed on `69c2c7543`. The first
new UI test run caught an assertion racing React Router's transition;
waiting for the navigation before asserting passes without weakening the
navigation/remount checks. These older-head green checks are not claimed
for the new fix commit.
- Preceding `0e6ef7c44` completed all 56 checks successfully with four
conditional skips, fresh Greptile 5/5 and no open findings, and passed
Superagent. A fifth migration-metadata collision arrived before the
final Runner job finished. Those green results are preserved as
prior-head evidence, not current acceptance.
- Previous fully verified migration head:
`0e6ef7c44696a377f35e69521b93587576374bd0`, integrating master
`f8226b051` after the fourth migration-number collision. Master added
terminal GitHub-response migration 0401 while the final native check
ran; upstream 0401 SQL/journal/snapshot is preserved unchanged, and
preferences are generated as idempotent `0402_yielding_blink.sql` on
top. Exactly the five newest snapshots remain. GitHub reports MERGEABLE
after the push. All 1,155 relevant
migration/review/interaction/native-execution/remote-assets tests,
workspace typecheck/build, migration guards and whitespace checks pass.
Fresh exact-head CI/Greptile/Superagent are pending.
- Immediately preceding head `36c67cf03` completed all 56 checks
successfully with four conditional skips, fresh Greptile 5/5 and no open
findings, plus passed Superagent security. No retry was needed for that
head's CI. Master advanced and introduced only a migration-metadata
conflict while its final native check ran, so that green result does not
establish acceptance of the current integration. Four consecutive
collisions (0398, 0399, 0400, 0401) during verification are retained as
concrete integration churn; a brief pause of competing migration merges
was requested, without assuming it happened or changing any repo
setting. The PR has not been merged.
- Prior fully verified head: `36c67cf03`, on the clean `30059c0ed`
integration of master `efd65c112`. The last Greptile P2 is fixed: Needs
attention retains the participant-agent scope through authoritative
server membership queries for each pending task, including historical
participation when another agent currently owns the task. It does not
approximate participation with current assignment or enumerate every
company task. The actual view-switch regression and all 31 focused
task/routing/collection tests, UI typecheck/build, token gates and
whitespace checks pass. Greptile completed a fresh 5/5 review on this
exact head (review 19) with zero new comments and no open review
threads. CI and Superagent remain in progress; no current-head CI
failure has been reported.
- Head `30059c0ed` received Greptile 5/5 with that one nonblocking
participant finding, now fixed. Superagent passed that head.
Current-base integration restored the ephemeral RunsOn fleet after a
superseded workflow retained queued aggregate jobs: normal cancellation
was insufficient; the single force-cancel request was interrupted but
readback confirmed that obsolete run cancelled and current CI began on
the trusted fleet. No cancellation retry or runner/security/workflow
changes were made. Its partial CI was superseded by the necessary
participant fix and is not current acceptance.
- Previous compatibility/base-sync head:
`30059c0ededc0eab4e04e8299a884f36db8b292f`, integrating master
`efd65c112` and the Inbox/workspace compatibility fixes. GitHub reports
MERGEABLE after the push. Coordinator keeps Inbox standalone under More
without rewriting the instance's Combined Inbox preference; opting out
restores that preference. Saved merged-Inbox URLs resolve to their
original owner, task status presets remain usable, and canonical
repeated `workspace` parameters retain scoped, deduplicated pagination
(including Needs attention). All 192 broader
routing/Inbox/sidebar/privacy/review tests and the final 16 task-page
tests pass, as do workspace typecheck/build, token gates and whitespace
checks. The two review threads are resolved. Fresh exact-head CI,
Greptile and Superagent results are pending.
- The preceding `d5b9be5bd` remained mergeable but its CI routing gate
intentionally fell back to GitHub-hosted runners: “stacked base merge
commit does not contain the current base branch.” All 45 downstream jobs
stayed queued. Current master was merged cleanly to refresh the pinned
base; no runner/security settings or workflow logic were changed.
Greptile scored that preceding head 4/5 with the two compatibility
findings fixed here. Its automatic Superagent scan was inconclusive at
checkout; the documented retry was still pending when superseded. Those
results do not establish acceptance of this current head.
- Previous approval/migration head:
`d5b9be5bd3b8d6b0437e42bf48138377f34fa67d`, integrating master
`ba5bba86d` and the stale-output approval correction. GitHub reports
MERGEABLE after the push. The fresh P1 finding is fixed: every submitted
item now validates and locks its bound output inside the resolution
transaction, whether or not it carries a required-quality-review
binding. Real database regressions verify that an advanced document
revision or deleted attachment refuses the entire batch without
recording approvals, and current ordinary output reviews still resolve.
All 272 combined migration/review/interaction tests pass; workspace
typecheck/build passed. Fresh exact-head Greptile and CI are pending.
The automatic Superagent scan ended inconclusive at checkout; one
documented on-demand retry is pending. These are explicit verification
limits, not passed security results. The P1 thread is resolved.
- Master consumed the next migration slot three times during this
verification pass: confirmation recovery took 0398, continuation
recovery took 0399, and GitHub acknowledgement recovery took 0400. Each
upstream SQL/journal/snapshot is preserved unchanged. Preferences are
now generated as idempotent `0401_white_lenny_balinger.sql` from
upstream 0400; exactly five snapshots remain, and replay coverage
locates this migration by table content. This is recorded concurrent
integration churn, not a claim that older green results apply to the
latest base.
- Head `ed3b68da9` fixed the two history/URL findings with 26 focused
regression tests, server/UI typechecks, workspace build and token gates
passing. Greptile then scored that head 4/5 with the stale-output P1
corrected in the current head. Its partial CI is superseded, not counted
as current acceptance.
- Previous filter-fix head: `ed3b68da9`, based on the `8458d39d9` merge
of master `063cfd438`. The two fresh Greptile findings are fixed:
history outcome filters now match recorded per-item verdicts in SQL
before pagination (mixed reviews remain in both applicable outcomes),
and same-page URL assignee changes/back/forward navigation update that
filter without clearing independent filters. All 26 focused
database/navigation/collection tests, server/UI typechecks, workspace
build, token gates and whitespace checks pass. The two review threads
are resolved. Fresh exact-head CI, Greptile and Superagent results are
pending.
- The `8458d39d9` migration integration also passed all 328 targeted
migration/interaction/confirmation tests, workspace typecheck/build and
Superagent security scan. Greptile scored that head 4/5 with the two
functional gaps fixed in the current head; those prior-head checks are
not current acceptance.
- Migration integration head:
`8458d39d9721f4cb312c2390070a0609f8cddd1a`, integrating master
`063cfd43813cabf18417605fb9eefb9aacf95c8d`. GitHub reports MERGEABLE
after the push. Master advanced twice during this conflict-resolution
pass: first its confirmation-recovery migration took 0398, then its
continuation-recovery migration took 0399. Both upstream migrations and
journal entries remain unchanged; Coordinator preferences are now
generated as idempotent `0400_sad_guardian.sql` from upstream's latest
snapshot. Exactly the five newest snapshots remain. The replay
regression now locates the table migration by content instead of
hardcoding a renumbered filename.
- All 328 targeted question/review/confirmation/migration tests passed
again after the second merge. Workspace typecheck/build and fresh
exact-head CI/reviews are in progress. The preceding `0c46f46d6` passed
workspace typecheck/build and Superagent security scan, but was
superseded because master consumed migration 0399 while those checks
ran. That prior-head result is not acceptance of the current head. No
production settings or runner/security permissions were changed, and the
PR has not been merged.
- Previous integration head: `0c46f46d6f2b23417ab872ce3cb6ff2673647287`,
integrating master `287b04d72f1b9fca1412e05435c75b8302ba0710`. GitHub
reports MERGEABLE after the push. The renewed conflicts were
`0398_snapshot.json`, `_journal.json`, and the top imports in
`issue-thread-interactions.ts`. Upstream's `0398` confirmation-recovery
index and journal history are preserved unchanged; Coordinator
preferences were regenerated as idempotent `0399_bouncy_miek.sql`, with
replay coverage updated and exactly the five newest snapshots retained.
Both terminal confirmation notifications and Coordinator task
assignment/required review behavior are preserved.
- All 328 targeted interaction/review/confirmation/migration tests pass,
as do workspace typecheck, map validation and whitespace checks. The
workspace build and fresh exact-head CI/Greptile/Superagent checks are
pending. The first migration-generation attempt hit the sandbox's local
IPC restriction before generating files; the unchanged authorized local
generation completed successfully. Prior-head green checks below do not
establish acceptance of this merge.
- Previous acceptance head: `8b7dcf739ed15afc51351fdfa0e0e5fbc75ab788`,
with master `1aa3a21ac` integrated and GitHub reporting MERGEABLE.
Greptile completed a fresh 5/5 review on this exact head with zero new
actionable findings and no open review threads. The [fresh CI
workflow](https://github.com/paperclipai/paperclip/actions/runs/40752864319)
completed SUCCESS on attempt 2 at 19:40:08 UTC, including all eight E2E
shards. Final completed check set: 55 succeeded, four conditional checks
skipped, zero pending/queued/running checks, and one
neutral/inconclusive Superagent scan. The auxiliary commitperclip review
and isolated native Runner compilation/cache-reuse check both passed.
This is not a claim that Superagent produced a passed security verdict.
GitHub still reports MERGEABLE against current master
`60b8089a44b4eaa37e627adbfdf2f130bda13335`.
- Current-head E2E: all eight shards and the aggregate passed, including
the previously failing YAML browser journey. Serialized server shard 9/9
failed: the protected YAML projection test exceeded its original
15-second timeout; its late update request then reached the next test's
reset mock (the captured payload is the prior test's model/label
update). All 88 tests in that exact unchanged file passed locally in
38.03 seconds, with no timeout or assertion changes. The original
slow-request cause remains unproven. CI failure log:
`/tmp/pr17983-8b7-serialized9.log`; local recovery:
`/tmp/pr17983-adapter-yaml-repro.log`. The single bounded unchanged
shard rerun passed, and the workflow completed SUCCESS. Rerun log:
`/tmp/pr17983-8b7-serialized9-rerun.log`. The initial failure is
retained; a passing retry does not establish its original slow-request
cause.
- Greptile scored preceding head `4873704be` 5/5 with one valid P2:
opened task decision records missed company-scoped live invalidation.
The current head uses the existing company decision prefix for
resolution and effect-completion events, and resets private record
payloads on access changes. Its thread is resolved. All 107 focused
record/live-update tests, UI typecheck/build, token checks and
whitespace checks pass.
- CI on `4873704be` failed E2E shard 7/8 in the Advanced YAML
lost-creation-response journey: its clipboard helper selected page text
starting with “Skip to Main Content” instead of YAML. The exact
unchanged journey passed in a disposable local browser instance (1 test,
17.1 seconds). No assertion, timeout or production behavior was
weakened; the original failure cause remains unproven. Failure log:
`/tmp/pr17983-487-e2e7.log`; local check:
`/tmp/pr17983-agent-yaml-repro.log`. The full unchanged Advanced YAML
browser suite also passed locally (6 tests, 37.8 seconds). Fresh
current-head CI subsequently passed this journey and all other E2E
shards.
- Both the automatic and one supported on-demand Superagent scan on
`4873704be` ended neutral/inconclusive: “Pinned PR scan merge-base
checkout failed or timed out.” These do not count as a passed security
verdict. The current head's automatic scan and one documented on-demand
retry also returned the identical neutral checkout failure, with zero
annotations or further diagnostics. This is an external scanner blocker,
not a passed security verdict. No security settings or permissions were
changed.
- Recorded decision links now render and focus the full source-task
record in both Classic and Coordinator, including recorded choice,
submitted inputs, and the existing effect-result resolver. Fresh
terminal records take precedence over older open-decision cache entries.
Context and account checks keep mismatched or inaccessible records out
of the DOM; no decision-history tab was added to tasks or chat. The
shared company live-run feed now drives live-only filtering, including
ended runs and terminal tasks with stale run entries. All 213 focused
tests, UI typecheck/build, token and whitespace checks pass; the final
focus follow-up passed all 188 task-detail tests and UI typecheck. The
first new navigation test failed because its test host omitted company
context; the host was corrected before the passing run.
- Previous integration head: `375c5e89516705050d94bab99336212841b2e6e1`
merges master `1aa3a21ac` after four additional upstream commits. The
sole conflict was competing imports in `server/src/services/issues.ts`;
both quality-review policy and inbound wake-notice notifications are
preserved. The PR-specific review import now sits beside
execution-policy imports instead of the frequently changing first line.
GitHub mergeability is rechecked after the push.
- On the combined master tree, workspace typecheck/build, all 153
affected UI tests, map validation, and whitespace checks pass. Four
server suites passed 77 tests; the fifth suite's module-import hook
timed out while broad verification was running. Its unchanged isolated
run passed all 41 tests in 7.2 seconds with the original timeout. This
records recovery without claiming the original import-timeout cause is
proven. CI on `375c5e895` passed every substantive job, including all
eight E2E shards and Superagent; Greptile found the two functional gaps
fixed in the current head. A short-lived `669d90876` commit added the
main fixes before the focused navigation follow-up.
- Immediately preceding head `9d9737b49` completed all 56 checks
successfully with four conditional skips, Greptile 5/5 and no open
findings, plus a successful Superagent scan. The signoff E2E shard
passed on its single accepted rerun; its initial cancellation/timing
failure is retained below. Master moved again while those checks ran,
requiring this final integration rather than treating the prior head's
green result as current acceptance.
- Previous head `9d9737b496911a6054d0ea22d1b42b28b115e9ab` includes
master `d30c8f42b842327ee1c18c41a2efd6ba623da5cd`; that head was
subsequently conflicted by moving master. The master merge preserved
durable account-bound writes and Coordinator UX. Workspace
typecheck/build, 416 focused UI tests, and 142 affected comment-route
tests passed. A stable full UI run on preceding head `938ad1665` passed
all 9,833 tests across 836 files; its final full workspace build also
passed.
- Greptile found nested proposal project inheritance and Classic
bound-revision links on `91be74952`. Both were fixed with 142
interaction-route tests, 113 focused UI tests, and UI/server typechecks.
Its next review identified a valid draft-preservation bug in the new
Classic loading UI. Head `9d9737b49` keeps loading/error notices outside
editors and annotations while preserving dirty drafts; 115 focused
review UI tests pass, including pending/failed revision loads and
continued draft editing. All related threads are resolved. Greptile
completed a fresh 5/5 review of
`9d9737b496911a6054d0ea22d1b42b28b115e9ab` with no open findings.
- CI on `938ad1665` exposed an integration regression with the newly
merged durable startup saves: the personal preference gate blocked the
task page before its first session lookup. The guarded title editor now
mounts while that lookup is pending, with presentation-specific tools
still gated. All 216 affected component tests pass. The unchanged
five-test `disconnect-write-recovery.spec.ts` browser suite passes
against a newly launched disposable local-trusted PostgreSQL instance on
port 33219, including the exact failed startup-save journey. No live
provider, hosted authentication or production proof is claimed. The
helper-owned test server exited and the port has no listener. UI
typecheck, built-browser assets, token and whitespace checks pass.
- Initial durable-write merge tests found duplicate imports and unscoped
draft fixtures, fixed before 416 focused tests passed. A sandbox
typecheck could not create its IPC socket; the supported rerun passed.
The first revision-link test used a wrong Return to latest button
assertion, corrected before the 113-test pass. The startup E2E
reproduction initially still failed because an outer shell gate also
blocked the page; the subsequent fix passed all five cases without
changing the test or its timeouts. A focused loading-header assertion
initially used an incorrect fixture title; correcting it preceded the
216-test pass. These failures remain recorded.
- Earlier routing gates fell back to GitHub-hosted runners while master
was moving or conflicted. Superseded queued runs were cancelled, then
the `938ad1665` routing gate explicitly selected the ephemeral RunsOn
fleet. Its CI actively executed and completed most tests; only the
diagnosed startup E2E shard and aggregate failed, alongside the valid
Greptile finding. Auxiliary GitHub-hosted workflows also completed
successfully on earlier heads, so queueing alone is not an
administrative blocker. Fresh [CI on
`9d9737b49`](https://github.com/paperclipai/paperclip/actions/runs/40744012678)
is the acceptance target; the previously failing startup E2E shard now
passes. A different signoff E2E shard failed during executor
resubmission when its fixture run was cancelled as
`issue_continuation_waiting_on_review`. The exact unchanged journey
passed locally (1 test, 46 seconds), and the preceding head with
identical server/signoff code passed that CI shard. This supports a
bounded rerun but does not establish the timing failure's root cause.
After the workflow finished, GitHub accepted one rerun of that failed
shard and its dependent aggregate; both passed, completing all checks on
that head. The failure log is retained at `/tmp/pr17983-9d9737-e2e7.log`
and the local reproduction at `/tmp/pr17983-signoff-repro.log`. No
assertion or timeout was weakened.
- On the first merge, full workspace typecheck/build, all 9,622 UI
tests, 267 tests across seven affected server suites, two migration
checks, map validation, token gates, and the PR diff whitespace check
passed. Greptile then found duplicate local task-search filtering and
lost completed item-review detail. Both are fixed, with 42 passing
focused UI tests and passing UI typecheck/build.
- A subsequent Greptile review found attachment confirmations without
working links and mobile history without a visible host. Confirmation
layouts now derive the authenticated immutable-content endpoint from the
attachment ID, and Needs You uses the existing full-screen mobile sheet.
All 119 focused tests pass, including missing/stale display URLs, both
review layouts, and both mobile history entry buttons. UI
typecheck/build and token checks pass. Full workspace typecheck/build
also pass after the second master merge.
- Greptile gave head 22f69c304 a 5/5 score with one non-blocking
desktop-history reopening finding. Head 6dd52b6d3 fixed it, passed all
nine history tests, UI typecheck/build, token gates, and the full
9,679-test UI suite, then received a fresh 5/5 review with zero open
findings. These are prior-head results; review on the master-sync commit
is pending.
- The chat and workspace CI jobs on head 22f69c304 were interrupted by
runner shutdown signals and cancellation before completing their tests.
Their logs do not report failing assertions. Those interrupted jobs are
not claimed as passes. The new head starts fresh runs.
- The first merge CI had a Slack session-sync idle assertion fail after
an unexpected database read. Its exact isolated reproduction passes, and
the chat CI shard passed on head 618c5a2a3. The original failure's cause
remains undetermined. The broader local reproduction, run concurrently
with full verification, instead encountered 21 timeout failures across
its two test chunks; it is not claimed as a passing full local server
run. A concurrent local UI run had eight failures (seven timeouts and
one delayed autosave assertion). The complete UI run on the final head
passed all 9,679 tests across 830 files with two workers; no test
timeout or assertion was weakened. This establishes recovery without
claiming that every earlier timeout's cause has been proved. An earlier
intermediate UI run also overlapped the second master merge and failed
the newly added Advanced-sidebar expectation, so it is not treated as
stable-tree evidence. The newly merged UI dependencies initially
required refreshing the local install from the upstream package
manifest; the generated local lockfile update is not committed, per
repository policy.
- Superagent returned neutral/inconclusive scans on the preceding heads
because its pinned merge-base checkout failed or timed out. The
available retry endpoint returned 404. These are not successful security
verdicts. The fresh scan on `91be74952` passed (PR scan passed; no
suspicious PR changes detected). The `938ad1665` scan again returned
neutral/inconclusive with the same pinned merge-base checkout error; the
check-suite rerun endpoint returned 404. The fresh `9d9737b49` scan
completed successfully at 18:22 UTC with no suspicious changes detected.
Earlier neutral scans are not counted as successful security verdicts.
- Prior head `57902152ac3218096fca669d33ff18400a2a86ae` passed 9,618 UI
tests across 826 files, received Greptile 5/5 with no open findings, and
completed CI with 56 passes and four conditional skips. These are
historical results, not acceptance of the latest merge commit.
- The first full build found generated capability-contract drift. The
generated outputs were refreshed. Initial sandbox runs could not open
local IPC sockets; verification was rerun with local test access.
- Current master was merged. The workspace preference migration was
regenerated after the existing migration history.
- The UI run first found two outdated expectations: early custom-answer
validation and the document access error copy. Both were corrected, and
the full UI suite then passed.
- The local server run found three failures in unchanged tests. The Muse
test passes with Python 3.13 instead of the host's Python 3.9. The two
workspace tests pass when their test process uses the expected master
default branch. These environment settings do not change application
behavior or global machine settings. The unsharded server run was
stopped after those reproductions; CI supplies the full sharded server
result. No successful full local server run is claimed.
- Skill inventory generation needs an external eval checkout, which is
absent locally. The existing generator functions refreshed only the live
skill inventory and its derived files. The checked-in eval inventory was
preserved. The inventory validation gate passes.
- Greptile found a dropped MCP review requirement, missing per-item
output links, generic item-review summaries, and a history-refresh
failure. The fixes have 32 passing database-backed server tests and
focused rendered-card tests. A follow-up partial-review finding was
corrected by forwarding the canonical mutation status before settling
the card. Attachments open through the authenticated immutable-content
route in both card layouts. The final focused UI set has 117 passing
tests, including these regressions.
- Both browser shards that first failed expected a disabled-chat
message. The copy was restored, and those shards passed in CI on the
next commit. The two journeys also passed locally. One local attempt
first timed out before feature disable while waiting for the provider's
initial message; its isolated reproduction passed. That earlier timing
failure remains recorded and is not presented as an explained
infrastructure failure.
- Serialized server shard 9 first failed during pnpm setup with
ECONNRESET, before dependencies or tests ran. Its single rerun passed
setup and all tests. The build and production runtime boot passed on the
first attempt, but that run's public-install step timed out during Pi
setup. The single build-job rerun passed compilation, runtime boot, and
clean public-install verification. Those setup scripts are unchanged by
this PR. The successful retry establishes recovery; the earlier Pi
timeout's underlying cause remains undetermined. The aggregate CI gate
is green: [workflow
run](https://github.com/paperclipai/paperclip/actions/runs/40637789695).

</details>

## Risks

- This touches shared task, interaction, and completion paths.
Regression tests must cover classic and experimental behavior,
authorization, duplicate answers, and stale review targets.
- The additive preference table must migrate before the setting is used.
The setting defaults off.
- The experiment changes navigation and message presentation. Canonical
task and document records remain the source of truth.
- The initial task brief and saved plan can repeat information. This
change fixes chronology; a broader redundancy policy remains a design
decision.

## Model Used

OpenAI GPT-6 Codex with reasoning and tool-assisted code editing, tests,
and browser verification. Earlier iterations used Codex models in this
task; their exact model IDs are not available in the current context.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used
- [x] I have checked ROADMAP.md
- [x] I have searched GitHub for duplicate or related PRs
- [x] I have described the issue in-PR following the relevant issue
template
- [x] I have not referenced internal/instance-local Paperclip issues or
links
- [x] My branch name describes the change
- [x] I have run relevant tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation
- [x] I have documented risks
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open recommendations or follow-ups
- [x] I will address review comments before requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 17:20:01 -07:00
d30c8f42b8 feat(ui): keep writes durable through temporary disconnects (#17960)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/123/changes/paperclip/123
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People save tasks, write documents, make decisions and send board
messages.
> - A disconnect can hide a response after the server accepts a write.
> - Recovery must keep the original account, task and request key.
> - The merged connection foundation in #15754 handles reads and shared
outage state.
> - This change adds bounded write recovery and explicit actions when
recovery stops.

## Linked Issues or Issue Description

**What happened?**

Temporary failures could lose edits, report accepted writes as failures,
or require people to copy and send input again. A retry could target a
newly selected task or account. Restoring attachments could create a
second task.

**Expected behavior**

Keep the draft, its owner and its target. Retry only operations with a
server contract that prevents duplicate writes. Verify uncertain
results. Show conflicts and permanent failures, with an explicit resend
or cancel action.

**Steps to reproduce**

1. Save a task title during an outage, then open another task before
recovery.
2. Restore a task creation that needs files, selecting those files in
another order.
3. Lose a document or decision response, then interrupt the verification
read.
4. Switch accounts while a create, upload or connected-channel
publication is pending.
5. Type and erase a new-task draft before the first account lookup
completes, then reopen it.

This PR carries the write layer from #15769 and its review fixes. It
targets master after #15754 merged. Related test cleanup #16952 already
covers the unchanged copy-link toast test; this PR does not duplicate
that work.

## What Changed

- Add bounded autosave and submit jobs for supported writes, with
pending, conflict and manual retry states. Retain admitted autosaves
after navigation and preserve newer task revisions.
- Keep each job with its original account, task and operation. First
account resolution adopts admitted startup work; a later account change
cancels old work. Remount inline and document editors when their owner
or document subject changes.
- Preserve task-creation keys and immutable request snapshots through
file reattachment. Restore generated document keys before comparing
reselected files. Reject changed requests instead of creating a second
task.
- Check the original account scope before creates and each upload. Save
successful upload receipts before stopping on an account change.
Identify attachments by content digest and metadata.
- Verify uncertain document and decision results. Replay only plain,
keyed comments automatically; combined reassignment, reopen and
run-setting changes require receipt reconciliation or cancel. Settle
each request once when a receipt races its retry.
- Scope drafts and connected-channel publication reads to their owner.
Keep unowned older records unread and unreplayed, with an explicit
confirmed discard action after Activity inspection. Preserve typing
through the first session lookup, keep erased text erased, and report
browser persistence only when storage succeeds.
- Wait for the first account lookup before sending startup status
changes or decisions. Retry failed required lookups with a fixed limit
and surface exhaustion to the original action. Preserve uncertain
comment keys on account cancellation. Check the account generation
before a comment retry calls its sender and again immediately before
POST after asynchronous preparation. Retire only that request’s
optimistic echo on completion.
- Return an ordinary comment’s accepted same-company, same-task,
same-user receipt before workspace reopening, task status changes or
wakeups. Reused keys with changed text still conflict. Complete
reference and activity records through the same finalizer for initial
sends and accepted retries. It locks the task before its comment,
matching task and company deletion, comment removal and tombstoning,
rejects removed or tombstoned comments, repairs references and inserts a
missing activity record in one transaction, and publishes after commit.
- Remove reader-only record and comment-body size caps so accepted
browser writes remain readable, including JSON-escaped comment requests
in local and session storage. Update four existing Storybook fixtures to
use owned draft keys.
- Document the write contracts and add regression and real browser
recovery coverage.

- Add the exact reviewed-save recovery regression for both composer
implementations and reloads. Align receipt completion, both comment
deletion methods and company deletion with task deletion by locking
tasks first. Cover real task and company deletion races.

## Verification

- The exact reviewed-unknown-save regression fails in all four cases on
original commit `1ed0af4186`. It passes with this PR for both composers,
before and after reload. Cancel keeps the text and uploaded receipt. The
retained draft sends, and the next message also sends. Run `pnpm exec
vitest run --project @paperclipai/ui
ui/src/components/composer-recovery.test.tsx`.
- The new real PostgreSQL task-deletion race fails with SQLSTATE `40P01`
on parent commit `f3253a00c4`. The company-deletion race also fails with
`40P01` on `e8cf0e02dd`. All six receipt tests pass after the final
lock-order fixes. They cover company deletion, task deletion, comment
removal, tombstoning, concurrent cross-task references and interrupted
reference repair. Run `pnpm exec vitest run --project
@paperclipai/server
server/src/__tests__/issue-comment-receipt-postgres.test.ts`.
- The full UI run passed 9,656 of 9,659 tests across 816 files. Three
cases failed under that run: two large-tree timeouts and one
plugin-panel assertion. All 67 tests in those two files passed in an
isolated rerun. These failures remain recorded; this does not claim a
clean full UI run.
- `pnpm -r typecheck`, `pnpm build`, token gates and map checks pass on
the final change. The local full repository test command was started,
then stopped when the delivery moved to this existing PR. Fresh PR CI
must provide the full-suite gate.
- A local Storybook walkthrough used the real rich editor. Cancel kept
the restored text, Send cleared it after the simulated save, and a new
draft enabled Send again. Storybook simulates submission; it is not
staging acceptance.
- Earlier verification on `f3253a00c4` recorded five browser journeys
for title saves, cached-task offline recovery, startup recovery,
accepted comment replay and session lookup failure. Those results remain
prior-head evidence. No new staging deployment is claimed.

- On `e8cf0e02dd`, all CI checks passed after one browser-shard rerun.
Its first failure copied page text instead of YAML in an unrelated
agent-configuration test. On final commit `35131d4380`, Greptile is 5/5
with no unresolved review threads. The first CI attempt has two failures
outside this diff: runner close-attachment suspension and
scheduled-retry teardown. The scheduled-retry file passes all 14 tests
in isolation; the isolated runner test still fails locally. The single
standard CI rerun passed both jobs, and the aggregate verification gate
passed. All CI checks are green on `35131d4380`; Apex is 5/5 on that
same commit with no unresolved findings.

## Risks

- Automatic replay requires server duplicate prevention or result
verification. Uncertain combined mutations require receipt observation
or cancel and a fresh intentional send.
- Old unowned form drafts remain stored but are not assigned to an
account. Unowned channel records can be retired after Activity
inspection; this never cancels an accepted remote update.
- Browser storage and hashing can be unavailable. Storage failure is
reported honestly. Without a digest, replay can duplicate an upload
rather than silently drop a selected file.
- Detached autosaves remain bounded and check account ownership on each
attempt. Conflicts or exhaustion retain the draft for explicit recovery.
- No schema, credential or agent permission change is included. This PR
does not claim staging deployment or original-task acceptance.

## Model Used

Anthropic Claude Opus 5.5 (`claude-opus-5-5`) produced the original
implementation with tool use. OpenAI Codex, GPT-6 family, assisted with
restoration, integration, verification and review fixes. This Codex
session does not expose its exact serving model ID or context window
size.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Amy (Opus) <claude@users.noreply.github.com>
Co-authored-by: Dotta <bippadotta@protonmail.com>
2026-10-28 10:52:06 -07:00
DottaandPaperclip 143d20e466 fix(server): retain native Codex Plan write boundaries (#18034)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native Codex task chat keeps a saved Plan inside the turn that wrote
it.
> - The compact conversation API omits ordinary tool history.
> - That omission also removes the write receipt needed to place the
Plan.
> - This pull request retains a small successful write receipt in
conversation reads.
> - The UI can then keep the saved Plan at its write boundary after
readback.

## Linked Issues or Issue Description

**What happened?**

A real native Codex Product E2E attempt saved its Plan and displayed it
inside a settled turn. The Plan used the fallback position. The
browser's final conversation-only API response contained no
`write_document` receipt. The full event snapshot retained the
successful write. The native placement assertion failed and remains
failed in the original report.

**Expected behavior**

Conversation readback must retain enough evidence to place the saved
Plan at its successful write boundary. It must keep arbitrary tool
bodies and ordinary tool history out of the compact response.

**Steps to reproduce**

1. Save a canonical Plan through a native `write_document` call.
2. Read the run with `view=conversation`.
3. Before this fix, the response omits the write receipt and the UI
places the Plan at the end-of-turn fallback.

Related eval evidence repair: Refs #18026. This is a separate product
readback fix. It does not resolve the failed human-input call or the
Claude tool-availability failure from those attempts.

## What Changed

- Include only successful canonical `plan` document results, matched to
a native `write_document` call in the same run, turn, session and source
instance. Ordinary document writes stay excluded.
- Build the small receipt inside PostgreSQL before its body crosses the
database connection. Preserve only fixed event metadata, tool identity,
the `plan` key and mutation disposition. Keep the existing payload
decoder for ordinary conversation events.
- Keep cursor paging, run scope, ordinary-tool exclusion, and full event
reads unchanged.
- Document the compact read contract in OpenAPI.
- Scope this fix to the canonical native dynamic-tool call/result pair
used by Codex. The retained Claude sample proves compatibility with that
captured shape. It does not qualify every current ACPX Claude producer.
Provider-activity-only paths and OpenCode keep the explicit fallback.

## Verification

- Real PostgreSQL red: the new boundary test fails because the first
selected event is assistant text rather than the saved write. The six
existing tests pass.
- Real PostgreSQL/API green: 36 tests pass across task cold-open and
OpenAPI routes on an isolated Linux current-master checkout.
- UI: 104 transcript tests pass, including completed native placement
from the body-free receipt.
- Review regression red: a later notes write incorrectly enters
conversation readback (one failure, six passes). After the fix, the
PostgreSQL/API suite passes all 36 tests.
- Fixed the new UI fixture's string-to-Date type mismatch found by
hosted CI. Original failed CI remains visible; fresh exact-head checks
are pending.
- Existing token/style gates pass.
- Retained native Codex and Claude fixture shapes both pass. Each
fixture includes the canonical item pair and parallel provider
`tool.execution.*` activity. All identifiers and document bodies in the
fixtures are synthetic. This captured-shape test is historical readback
compatibility, not fresh current-source Claude acceptance. The Codex
canonical pair is emitted by
`packages/paperclip-runner/src/drivers/codex/codex-session-server-requests.ts`
in the admitted dynamic-tool handler.
- Projection-collision regression red: a non-Plan result selected by
conversation identity was relabeled as a Plan. The SQL projection now
uses the same full Plan predicate as selection. The regression and both
native fixtures pass.
- The database test checks cursor paging, a Plan followed by notes,
failed/read/control-plane/unrelated-turn exclusion, schema and ID
bounds, omission of a large tool body, unchanged full-history reads, and
ordinary conversation payloads containing NUL.
- Local server typecheck fails on 80 installed workspace export
mismatches outside changed paths. No changed-path type error or local
full build pass is claimed. Clean hosted checks must pass before merge.
- Current-head hosted CI and legacy status pass. One failed-check retry
followed recorded runner shutdowns and an unrelated native-distribution
timeout; that test passed all 33 cases locally. Original failed logs
remain retained.
- Zero provider calls or paid attempt retries. Original failures and
accounting journals remain unchanged. This is not a new live
qualification result.

## Risks

- Conversation pages include matching Plan results within the existing
1,000-row page limit. The query adds a run-scoped match against
canonical tool calls and projects results inside SQL. PostgreSQL still
reads the stored JSON to select receipts; private bodies are not
transferred to the application. It adds no separate database round trip
or background work.
- Matching requires the existing canonical call/result identities.
Missing or malformed historical receipts keep the explicit fallback.
This fixes compact conversation readback; it does not redesign placement
in an unrelated full-history multi-document UI flow.
- This restores the existing UI write-boundary mechanism. It does not
change Plan acceptance, permissions, or completion rules.

## Model Used

- OpenAI Codex, GPT-6, with reasoning and code execution tools. The
exact serving variant and context window are not exposed in this
session.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-28 11:06:05 -05:00
Devin FoleyandPaperclip c9213d1be4 fix: send saved queued messages after Stop (#17959)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People can save follow-up messages while an agent runs.
> - Stop preserves those messages and stops the active execution.
> - The queue removed its delivery controls when that execution ended.
> - Native admission also refused an explicit resend of older queued
input.
> - This change adds Send for a stopped queue and records fresh board
intent.
> - The saved message can continue through normal cleanup and admission
checks.

## Linked Issues or Issue Description

**What happened?**

A person queued a message with a screenshot while an agent was starting.
Steering was not yet available. They stopped the run. The message
remained visible, but no control could send it. Native queue delivery
also rejected this transition.

**Expected behavior**

A stopped queue offers Send. The click preserves message IDs, content,
attachments and original authors. It starts at most one eligible
continuation. Stop remains effective until the person gives new
direction.

**Steps to reproduce**

1. Start a native task and queue a second message.
2. Stop the active run before it consumes that message.
3. Open the task after cleanup. Observe the saved message with no send
control.

Refs #16965 for the queue-control change and #15015 for stopped
conversation recovery. No open repair for this exact transition was
found.

## What Changed

- Show Send for a saved deferred queue with no active run.
- Accept the existing board queue action for a stopped native target.
Keep live native interruption restricted.
- Use the server-recorded click time to authorize older native messages.
Reject stale, malformed and wrong-actor intents.
- Reuse normal queue dispatch, revision checks, cleanup proofs and
execution admission, including a failed native predecessor after a
verified Send.
- Ignore a fully committed, successful recovered export when admitting a
fresh message, while retaining the wait for results still committing.
- Honor an applied `/new` conversation boundary while retaining native
execution holds until the existing stop and cleanup checks verify them.
Workspace holds also survive reset. Check the newest failed or cancelled
native execution even when older recovery actions exist.
- Keep native automatic delivery separate from the explicit Send action.
Update execution and access documentation.

## Verification

- Meaningful regressions failed before the fixes: stopped queues lacked
Send, native admission refused fresh intent, cleanup and dispatch
receipts were missing, deferred rows disappeared, live plan Interrupt
rejected its own receipt, and Agent Chat `/new` inherited an old
non-workspace execution hold.
- Six assembled-wakeup cases fail before the reset cleanup fix. All 11
reset/history cases pass after it: live processes, missing identity,
quarantined cleanup, remote leases and live controllers remain held;
verified cleanup proceeds and retires the hold. Two more cases fail
before the fallback fix and pass after it: Send verifies a stopped or
live native predecessor despite a later reset receipt and no recovery
record.
- **525 server tests pass** across seven queue admission, route,
dispatch, envelope, provenance, blocker and conversation files. **343
queue/thread UI tests** also pass. Server/UI TypeScript, token and map
guards pass. The final scoped server typecheck also builds native Runner
successfully.
- The latest regressions prove that completed recovered exports permit
fresh input, and clearing conversation history still requires old native
stop and cleanup verification; an unsafe workspace still blocks after
`/new`; failed native Send reaches actual continuation dispatch with the
original queued comment. A result still being committed remains
deferred. History plus a newer Stop cannot hide a missing
process/controller/lease receipt.
- The real Chromium Stop/Send journey passes on current head
`75fa5e7222c59f43ff7ac326e81093bc9da28330`: queue a follow-up, Stop,
reload, explicitly Send, then verify exactly one useful response and no
live run. Earlier browser journeys cover legacy Interrupt, interruption
during a write and Stop followed by a new direction. These use an
isolated app/database and controlled ACP fixture, not an external AI
account or a staging deployment.
- Negative cases retain actor, company, issue, assignee, queue and
cancellation-receipt bindings; cleanup/process/workspace/controller
holds; approvals; pause and budget gates. Typed responses keep their
original resolver and immutable result.
- Full local recursive typecheck stopped in unchanged Rust Runner
compilation with ENOSPC, so the chained full tests/build did not run.
All hosted CI gates pass on final commit
`75fa5e7222c59f43ff7ac326e81093bc9da28330`, including typecheck, tests,
build and E2E. Apex review on that commit is 5/5, with no unresolved
findings. Earlier unrelated CI failures involved PostgreSQL
fixture-cleanup deadlock and an unchanged decision-expiry deadline
assertion; the latter's 20 cases pass locally without source changes. No
assertions or limits were weakened. Local resource cleanup was limited
to this task's verified completed test processes and rebuildable npm
caches.

## Risks

- Send can authorize a new turn for a saved message after Stop. A Send
click must be newer than the stopped execution; a live plan Interrupt is
bound to the cancellation receipt produced by that same click. It does
not imply that cleanup finished or that an external action is safe to
replay.
- The existing endpoint and intent format are reused. No schema or
credential change is required. Live native steering and legacy
interruption keep their existing paths.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository inspection, tool
use and code execution. The session does not expose the exact serving
model ID or context window size.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 20:34:14 -07:00
DottaandPaperclip f52da40f08 fix: resume queued turns after maintenance (#17967)
Keep an accepted turn's starting input in task history, show its admission wait, and resume existing queued runs promptly when maintenance ends or expires.

Verified with behavioral red/green regressions, real PostgreSQL and process execution, browser/native Runner acceptance with a deterministic provider, workspace typecheck, production build, and current-head CI/review.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-27 22:20:03 -05:00
DottaandPaperclip f60ac29cf1 fix(runner): migrate Grok Build with native reasoning effort (#17922)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Harness selection maps supported agents to Paperclip Runner.
> - The native Runner already supports Grok Build, but its migration
mapping excludes Grok.
> - Grok agents also have a thinking-effort setting that the native
execution contract does not carry.
> - This pull request adds the migration path and preserves explicit
Grok effort through startup and resume.
> - Operators can upgrade an existing Grok agent without silently losing
its model, account, or effort.

## Linked Issues or Issue Description

**What happened?**

Existing Grok Build agents have no Runner selector or upgrade action.
Adding only the mapping would route conversion through the Codex
fallback and lose Grok execution semantics. Native execution also
ignores the legacy reasoning-effort field.

**Expected behavior**

A qualified Grok agent can explicitly upgrade. The saved model, account,
instructions, history, and supported effort remain intact. Unsupported
legacy settings fail before saving. The provider must acknowledge the
selected effort before inference.

**Steps to reproduce**

1. Open the runtime page of an existing Grok Build agent on a qualified
Linux x64 or macOS ARM64 computer.
2. Observe that the Runner selector and upgrade action are absent.
3. Compare the native execution input with the saved legacy
reasoning-effort setting.

Related work: #13882 introduced native Grok Build. #15422 covers the
earlier default-runner work. This change extends the current shared
selection contract.

## What Changed

- Add the Grok harness mapping, qualified platform limits, upgrade
action, and company-scoped computer qualification.
- Translate Grok settings to ACPX without changing the selected account
or explicit model. Resolve the legacy default model to the native
default. Preserve the effective legacy search policy. Reject
incompatible command, argument, permission, and turn-limit settings.
- Add native execution input v10 for explicit Grok effort and search
policy. Preserve historical schemas. Enforce disabled search through
Grok requirements and bind it across startup and recovery.
- Apply and verify ACP `reasoning_effort` before prompting. Bind the
value to provider descriptors, checkpoints, runtime identity, and resume
checks.
- Use the Grok catalog and effort choices in the task composer. Apply
task model and effort overrides while retaining the agent account and
search policy. Update runtime controls, portability/default handling,
documentation, and capability maps.
- Advance Pi and Copilot source attestations for changed shared
transport and recovery code. Keep historical identities intact and
update all Rust integration fixtures.

## Verification

- Migration and review regressions were reproduced before the fixes.
Coverage includes the Grok mapping, default model, explicit effort,
implicit search policy, task overrides, and incompatible legacy
settings. The broad migration, route, immutable-input, and composer
check passed 478 tests. The final catalog and task-input check passed
135 tests.
- Runner startup, recovery, search policy, and profile checks passed 361
tests, with one platform skip. The final source-identity,
search-admission, and transport event-pump check passed 89 tests.
- All 757 Rust workspace tests passed for the broad implementation.
After the final source attestation update, all 55 ACPX profile/session
tests passed.
- `pnpm -r typecheck` and `pnpm build` passed for the implementation.
Server and Runner typecheck passed after the final production change.
Server `tsc --noEmit` passed after the final test-fixture change. Docker
context integrity, token gates, maps, generated protocol data, and
replay goldens passed.
- The v10 startup fixture initially used an ambient local Grok login and
failed on CI. An explicitly empty credential home reproduced all four
failures. The fixture now supplies a synthetic key and a private empty
home. A separate case checks that missing credentials fail closed. All
seven selected Grok v10 and Claude v9 startup cases pass without host
credentials.
- The full local suite could not complete because embedded PostgreSQL
failed before database-backed fixture setup. The broad executor-suite
attempt hit the same limit and was stopped. Neither attempt is counted
as passing. Current-head CI must verify those paths before merge.
- Earlier CI found missing Rust input fields, stale source attestations
and exact fixture pins, a missing Docker context entry, and an outdated
import expectation. Those failures were fixed and checked locally. The
CI logs retain the original failures.
- Different earlier CI runs also failed unchanged cleanup pagination,
device-login timeout, and chat lost-response recovery cases. Later
attempts passed the cleanup and login cases without changes to those
implementations. Their causes remain unproven. The original evidence
remains in [the first
run](https://github.com/paperclipai/paperclip/actions/runs/40563402840),
[the login
run](https://github.com/paperclipai/paperclip/actions/runs/40571128328),
and [the chat
run](https://github.com/paperclipai/paperclip/actions/runs/40573072163).
A passing retry does not establish a root-cause fix.
- Both reviews rate current head
`16fba9b4cdf12bc7945e6628912e79da42959f35` 5/5. All current-head CI
gates pass in [run
40576580699](https://github.com/paperclipai/paperclip/actions/runs/40576580699).
All 60 check runs completed cleanly, including the four intentional
skips and the neutral 5/5 Paperclip review. The legacy security status
is successful. No review threads remain unresolved.
- Staging migration and a real shell task are pending deployment. This
PR does not claim full Grok provider qualification. Reviewers can verify
the operator path by upgrading a qualified Grok agent, checking its
saved model and effort, and running a shell task through native
execution.

## Risks

- Explicit effort and search policy require the matching Runner and
sidecar build. Older immutable execution inputs keep their existing
schemas.
- Providers that omit or reject the selected effort fail before a
prompt. Unsupported effort does not fall back silently.
- Existing agents retain their saved runner until an explicit change.
New Grok agents use native execution only on qualified platforms.
- Grok token and cost reporting remain unverified, as before.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving model ID and
context-window capacity are not exposed in this session. Used reasoning,
source editing, shell execution, and browser inspection.

## 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 and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run tests locally and the focused suites pass; the full
local suite has the environment limitation recorded above
- [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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 15:28:42 -05:00
DottaandPaperclip e71a23c01c fix(ui): animate late task sidebar loading (#17880)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/61/changes/paperclip/61
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task pages load the conversation and related sidebar data
separately.
> - The sidebar host did not exist until its content arrived.
> - Its first appearance skipped the width transition and moved the
thread at once.
> - This pull request keeps an empty host at zero width until content is
available.
> - The sidebar and thread now move together, with immediate changes for
reduced motion.

## Linked Issues or Issue Description

**What happened?**
A cold task load showed a wide skeleton. The right sidebar then appeared
at full width and shifted the thread at once.

**Expected behavior**
The sidebar should enter smoothly. The task thread should move with it.
Unknown or hidden sidebars should take no space.

**Steps to reproduce**
1. Open a populated task in a fresh browser context.
2. Delay the task metadata response.
3. Watch the skeleton and thread as the right sidebar becomes available.

Related work: [task cold-open
reads](https://github.com/paperclipai/paperclip/pull/17756).

## What Changed

- Keep the shared sidebar host mounted at zero width while its content
is unknown. Make hidden hosts inert and hide them from assistive
technology.
- Use shared motion tokens for width and opacity. Disable motion for
reduced-motion preferences and keep pointer resizing immediate.
- Clamp late content to the current viewport without overwriting the
saved width. Keep the motion catalog aligned with the reveal tokens.
- Clip the panel body during reveal. Keep the resize handle inside the
viewport during the first frame.
- Clear empty panes immediately when content is removed. Release
maximized geometry on that render. Remove the unused width/opacity
token.
- Add four replayable Storybook scenarios using the production skeleton
and panel components. Add browser checks for both arrival orders, absent
and hidden sidebars, reduced motion, resizing, and maximize/restore.
- Document the shared sidebar loading behavior in DESIGN.md.
- Load the comment-route test modules in suite setup. This prevents a
slow module load from timing out the first test and affecting the next
test. This test-only change fixes a reproducible CI failure; route
behavior and assertions stay the same.

## Verification

- 201 focused task-detail, properties-panel, and motion-catalog tests
passed. New host-continuity regressions failed against the original
component in both task interfaces.
- Eight focused Storybook browser checks passed without retries after
the review fix. They measure intermediate widths and matching thread
widths, check overflow, exercise resize and maximize controls, and
confirm immediate removal of docked and maximized content.
- The first removal checks sampled before replay cleanup committed.
Sampling now starts after the host becomes inert. All three removal
checks fail against the prior commit. Restoring the source during that
comparison left a stale Storybook module in the preview. After a preview
restart, all eight cases passed without retries on the fixed source.
- Verified a real populated local task in a fresh browser context with
delayed real API responses. Recorded a screencast for visual review. The
captured reveal had 20 intermediate widths, no horizontal overflow, and
no browser errors.
- Repository typecheck, full build, Storybook build, token gates, map
checks, and 30 catalog/map tests passed. Full typecheck, full build,
focused UI tests, and UI typecheck were repeated after the upstream
rebase.
- Full `pnpm test:run` was attempted and stopped after repeated embedded
PostgreSQL initialization failures. The host has exhausted its semaphore
pool. The local app test used a disposable container database instead.
- Replay `tasks-sidebar-loading--sidebar-during-skeleton` in Storybook.
Run the focused browser suite with `STORYBOOK_TEST_BASE_URL` set to that
Storybook server.

- CI serialized shard 6/9 failed when the first comment-route test hit
its 15-second timeout. Its work then affected the next test's mock
count. Both failures reproduced locally on Node 24. After moving module
loading to suite setup, all 103 tests and server typecheck passed with
the same test timeout. A first local attempt could not bind the
Supertest listener inside the sandbox; it was repeated with local
network access.

## Risks

- The shared host also serves other properties panels. Hidden
preferences, default widths, pointer resizing, maximize/restore, and
both task interfaces have focused coverage.
- Width animation can reflow text while the panel enters. Reduced motion
removes the transition. Navigation removes empty panes immediately.
- Visual approval is complete. The full CI suite must pass before merge.
No schema or API contracts change.

## Model Used

- OpenAI GPT-6 through Codex, with reasoning, code execution, and
browser tools. The exact deployed model ID and context-window size are
not exposed in this session.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-27 10:10:45 -05:00
Clément df5a78cf91 fix(ui): keep iPhone task chat stable while typing and streaming (#17232)
## Thinking Path

> - Paperclip keeps human-agent conversations attached to tasks.
> - People need to read and reply comfortably from a phone.
> - The mobile task page scrolled the document and positioned its
composer with a sticky navigation offset.
> - Safari's keyboard resize and later focus pan could move that
document again, causing overlap, gaps, and jumps while editing.
> - This change gives mobile and desktop the same message scroller and a
normal flex footer.
> - CSS owns the layout. A small VisualViewport adapter handles the
visible height and Safari's stale document focus scroll.
> - Streaming no longer measures every historical row while following
the bottom.

## Linked Issues or Issue Description

Fixes https://github.com/paperclipai/paperclip/issues/16497

Related: https://github.com/paperclipai/paperclip/pull/15245 also
addresses keyboard positioning. This change additionally removes mobile
document auto-follow and reduces historical-row measurement work.

## What Changed

### One scroll owner and a natural-flow composer

Before:

```text
Document scroll + mobile auto-follow
  └─ Conversation + sticky composer + animated navigation offset
```

After:

```text
Height-constrained conversation shell
  ├─ Header
  ├─ Message scroller — owns follow/reading position
  └─ Composer — normal flex footer
Navigation stays at the layout viewport bottom, behind the keyboard
```

- Reuse TaskMessageScroller on mobile. Delete the separate 136-line
useWindowAutoFollow implementation and its superseded tests.
- Keep the composer in normal flex flow. Remove its sticky bottom
positioning and navigation-offset animation.
- Constrain the mobile conversation with CSS. Classic tasks and other
pages retain their existing layout.
- Add a 47-line useMobileVisualViewport hook. It changes shell height on
resize, not on typing or incoming messages. It never translates the
shell or hides navigation.
- Reject Safari's stale document focus pan only for an unzoomed,
keyboard-open conversation. Inner message and editor scrolling stay
native.
- Keep a saved reading anchor when reading older messages. Skip
historical-row measurements while following the bottom.
- Update tests and the existing mobile streaming fixture. Keep only two
layout-contract sentences in DESIGN.md.

**Scope:** 19 files, +367 / -482 lines: 115 fewer lines overall.
Production UI/CSS alone is +158 / -190 lines. No API, database, or
dependency changes.

## Verification

Bottom-follow is also saved explicitly for Back navigation. A new
regression covers returning after rotation changes message wrapping,
without restoring historical-row scans.

### Physical iPhone acceptance

Tested on an iPhone 15 Pro running iOS 26.7.1. The reporter confirmed:

- Opening the keyboard positions the composer correctly immediately,
before any typing.
- The installed web app works.
- Long drafts, insertion, deletion, and sending are acceptable. The
reporter described long drafts as not perfect but good enough.
- Reading older messages during incoming output preserves position;
returning to the bottom resumes following.
- Rotation, keyboard close/reopen, and attachment/picker transitions
work.

Remote inspection corroborated the corrected open-keyboard state:
visible height 358px, composer bottom 358px, document scrollY 0.
Navigation remained display:block at y=631px, behind the keyboard.

Earlier candidates failed device testing. The decisive trace showed a
correct viewport resize followed about one frame later by a stale 337px
native document focus pan. Typing caused Safari to correct it. Tests now
cover that event ordering, the reverse ordering, and zoom panning.

### Performance evidence

The existing TaskChatPerfHarness supplied 200 historical responses,
4,000 collapsed tools, and 30 updates at 100ms intervals.

| Measurement | Before | After |
| --- | ---: | ---: |
| Historical row geometry reads | 6,000 | 0 |
| Renderer main-thread work | 331.2ms | 273.5ms |
| Largest task | 27.1ms | 12.3ms |

This is one instrumented Chromium development run on the Mac, not a
phone benchmark or a statistical speedup claim. The zero-row-measurement
result also has a regression test that failed with 6,000 reads before
the change.

To reproduce, serve ui/tests/task-chat-perf.html with the UI Vite
server. Record 30 streaming updates at the bottom. Inspect
TaskMessageScroller and row getBoundingClientRect calls. Existing
historical-render tests also confirm that unchanged Markdown does not
reparse on live-tail updates.

### Automated and full-app checks

- [Current-head
CI](https://github.com/paperclipai/paperclip/actions/runs/39862524031)
is green: 54 successful checks and 2 skipped checks. Greptile rates the
current head 5/5, confirms the Back-navigation fix, and has no
unresolved findings.

- **601 focused tests pass** across the task page, layout, composer,
scroller, viewport adapter, and historical-render coverage.
- UI typecheck and production build pass.
- Token gates, Storybook catalog checks, and catalog/map structural
tests pass.
- Independent review of the final source tree passed with no findings.
- The full source app ran on macOS with an isolated database and saved
conversation history. A reply sent through the real UI persisted after
reload. Provider execution was not part of this layout test.
- **Full local repository checks did not pass.** Build/typecheck stop at
missing Rust cargo. The full test run reported 142 failed server tests
and 3 failed suites; missing cargo is confirmed in those three suites.
The other server failures were not diagnosed in this UI task.
Current-head CI now supplies the repository-wide evidence; these local
failures remain disclosed.

## Risks

- Mobile conversations now share the desktop scroll owner. Navigation,
loading, history restoration, and reading-position tests cover that
change.
- The keyboard-state threshold is a 120px viewport reduction.
Accessory-only keyboards retain the normal navigation spacing.
- The document-scroll fallback is scoped to rendered conversations with
an open keyboard at scale 1. It does not handle inner scrolling or
prevent zoom panning.
- Long-draft behavior is accepted, with minor polish still possible.
- The UI change is reversible and requires no data migration.

## Model Used

OpenAI GPT-6 Astra, exact model ID gpt-6-astra, through OpenCode.
Capabilities used: reasoning, code editing, tests, Chromium performance
tracing, and Safari remote inspection. The harness does not expose the
context-window size. An independent general-purpose subagent reviewed
the final tree; its serving model ID was not exposed.

## 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
- [x] My branch name describes the change and contains no internal
Paperclip ticket id or instance-derived details
- [x] I have run focused tests locally and they pass; repository-wide
failures are disclosed above
- [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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-10-26 08:44:39 -07:00
Dotta 46760cc588 fix(chat): honor dismissal for all composer requests (#17218)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task conversations show requests in the feed and above the message
composer.
> - Earlier fixes kept dismissed questions in history, but excluded
completion reviews and other request kinds.
> - Closing those forms left a pending badge, and the server could still
demand a response.
> - This pull request saves human dismissal and removes the request from
composer reminders and ordinary completion gates.
> - People can continue the conversation and reopen the request from
history.

## Linked Issues or Issue Description

Related work: #15229 and #15392.

**What happened?**

Dismissing a completion review closed its form but left it counted as
pending. It could return after reload, block a retry, or cause the agent
to demand another response. Raw runtime requests could also lose their
only usable control when dismissed.

**Expected behavior**

Dismissal leaves an accessible request in the feed and clears the
composer form and pending count. It persists after reload. It does not
submit an answer, approve an action, or wake the agent.

**Steps to reproduce**

1. Open a task with a pending completion review or another composer
request.
2. Dismiss the request, then reload the task.
3. Check that the composer stays clear and the feed entry can reopen the
request.

## What Changed

- Add nullable dismissal fields and a human-only dismissal endpoint with
company, private-task access, resolver, and locked review-policy checks.
- Persist saved-request dismissal on the server. Keep browser
persistence for raw runtime requests and existing question dismissals.
- Keep confirmations, choices, item verdicts, suggested tasks, and
runtime requests accessible in the feed.
- Exclude dismissed ordinary requests from completion and retry gates.
Tell agents not to repeat deferred requests.
- Preserve tool, secret, connection, plan, company-policy, and
configured review authorization gates. Expire deferred non-question
requests when their task completes.
- Preserve the selected form when another dismissal finishes saving.
Keep reopened reviews visible through delayed comment refreshes.
- Add a completion-review Storybook test drive and update design, API,
database, and capability documentation.

## Verification

- `pnpm -r typecheck`: passed. The final UI changes also passed the UI
typecheck.
- `pnpm build`: passed. The final UI changes also passed the UI
production build.
- Focused UI and transcript tests: 550 passed across nine files after
merging the current base branch.
- Focused database, completion, and prompt tests: 105 passed across
three files, including two review-policy regressions that failed before
the fix. The tests reject a review requester excluded by current policy,
preserve the pending gate on denial, and permit an independent reviewer
to defer the request.
- Route regression suite: 81 passed, including denial before reading or
mutating a private-task request.
- `pnpm check:token-gates`: passed.
- Map and Storybook structural checks: passed; 30 map/catalog script
tests passed.
- Browser: used the production task-thread components in the
completion-review fixture. Dismissed, reloaded, reopened from the feed,
and dismissed again. No pending badge or composer takeover remained.
Story callbacks simulate API saves; separate server tests cover
persistence and permissions.
- `pnpm test:run`: stopped after the general-server group reported one
failure in `workspace-runtime.test.ts`: "returns a bounded structured
conflict and exposes only same-company workspace references". The same
test passed in isolation (1 passed, 178 skipped). The cause of the
full-suite failure is not established. The full PR CI suite subsequently
passed on e243cbb001; its two authorization review findings are fixed in
9e1b4478b3. Fresh [full
CI](https://github.com/paperclipai/paperclip/actions/runs/39871944846)
passes on 9e1b4478b3, including the previously failing server and
browser shards. All 54 executed checks passed; two optional Storybook
deployment/visual jobs were skipped. The legacy security status also
passed. Fresh Greptile review is 5/5, the security scan passes, and no
review threads remain open. This full CI run settles the merge gate; the
earlier local workspace-suite failure remains recorded above because its
cause was not established.
- Additional verification: the original failing browser journey passed
locally after the delayed-refresh fix. The expanded page-reload case
also passes on 9e1b4478b3 (52.7s): dismiss, reload, reopen, approve, and
receive the actual tool failure in the continuing task. It exposed a
fixture reading an accepted request before tool execution finished; the
fixture now waits for a stored execution result. The first reload
attempt stopped on a still-loading page at the default five-second
assertion; the reload now uses the suite’s navigation allowance. A
controlled server-restart run timed out waiting for server health before
the UI assertions. Local route-suite runs timed out during concurrent
module loading; sequential imports passed all 81 tests, including the
privacy regression.
- Initial verification failures: a missing SDK build and a story fixture
type error were fixed. PostgreSQL bootstrap then failed because the host
had exhausted its semaphore allowance. After explicit operator approval,
64 verified abandoned PostgreSQL semaphore sets were reclaimed; no live
process was stopped. The database regressions then passed. The
raw-runtime regression exposed a missing feed control; the
implementation now preserves that entry and the regression passes.

## Risks

- Apply the additive database migration before the new server code. It
adds two nullable columns and does not change existing decisions.
- A dismissal is shared task attention state. Only a human with task
read access and current resolver/review authority can persist it. Review
policy is checked under the task lock. The operation is idempotent and
records the dismissing user.
- Raw runtime dismissal remains specific to a browser. Saved interaction
dismissal persists across browsers.
- A deferred review is not an approval. Tests retain protected-action
and configured review gates.
- The browser walkthrough uses a fixture. This branch has not been
deployed to a live instance.

## Model Used

OpenAI Codex, GPT-6, with code execution and browser tools. The exact
backend model ID and context-window size are not exposed in this
session.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-10-22 18:37:36 -05:00
TonioandClaude Fable 5.1 341b622604 feat(ui): Artifacts V1 behind an experimental setting — Artifacts page, panel tab and task thread (#17228)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agents produce artifacts: documents, files, pictures, video and
links. The app shows them on the Artifacts page, in the right panel's
Artifacts tab and in the task thread
> - The artifact directions lab (#17213) settled a presentation for
those surfaces, MVP V1, drawn from the PCLP-Core mocks. It is a
reference, not product code
> - Shipping it means product components on product data, token-only,
behind a switch, one surface at a time, so the current presentation
stays the default until the new one has been used
> - This pull request adds the switch (Settings > Experimental >
Artifacts V1), the `--artifact-*` tokens, the V1 primitives as product
components, and the V1 presentation on all three surfaces behind the
switch: the Artifacts page, the panel's Artifacts tab and the task
thread
> - The benefit is the redesign in the product, reversible by one
setting, with every existing behaviour of those surfaces kept

## Linked Issues or Issue Description

No public issue exists. This section follows the feature request
template; the plan is `doc/plans/2026-10-22-artifacts-mvp-v1.md`.

**Subsystem affected**

The web UI (`ui/`): the Artifacts page, the right panel's Artifacts tab
and the task thread. The experimental settings contract in
`packages/shared` and `server` gains one boolean.

**Problem or motivation**

The three artifact surfaces grew separately and their artifact
presentation is dated and inconsistent. The lab produced a measured
direction; nothing in the product uses it yet.

**Proposed solution**

An experimental setting, `enableArtifactsV1`, default off, with the same
plumbing as the other experimental settings. Product primitives under
`ui/src/components/artifacts/v1` (kind helpers and adapters, the sheet
and print artwork, the stack, the page tiles with the Paper Mono pill,
the row the panel and thread will share), driven by `--artifact-*`
tokens in `index.css` with light and dark values. With the setting on:
the Artifacts page shows one row of views (Tasks, All files, Images,
Videos, Documents, Text, Files) and the V1 tiles, a task with several
artifacts as a stack whose newest artifact is the first page, everything
else as single tiles; the panel's Artifacts tab is one flat list of V1
rows, newest first, with the expandable rows (Markdown review surface,
document annotations, deep links) keeping their behaviour behind the row
as their face; the thread shows a message's files as rows under its
footer and registered deliverables and documents as one row each. The
hover movement respects reduced motion.

**Alternatives considered**

Replacing the current cards outright: no fallback and three surfaces to
land at once. Mounting the lab's components: they are typed on lab
fixtures and keep lab-local tokens, which the token gates reject. The
primitives were ported instead and the lab stays a reference.

**Roadmap alignment**

Supports the "Artifacts & Work Products" theme in `ROADMAP.md`.
Presentation only; no data model change.

**Additional context**

No new API fields: the tiles show title, identifier, count and "Updated
…"; rows take sizes from the work-product and attachment payloads; a
picture's aspect ratio comes from the loaded image, 4:3 until it loads.
The plan records what each surface keeps and what it drops (run sections
in the panel; the "Images · N / Files · N" labels and the four-up grid
in the thread).

## What Changed

- Add the `enableArtifactsV1` experimental setting: shared type,
validator and feature catalog, server defaults and managed keys, the
`useArtifactsV1Enabled` hook, and the Settings > Experimental toggle (in
its alphabetical place).
- Add the `--artifact-*` tokens and the Artifacts V1 component rules to
`ui/src/index.css`: light values on `:root`, dark overrides, and the
hover movement under `prefers-reduced-motion: no-preference`.
- Add `ui/src/components/artifacts/v1/`: `kinds.ts` (kind treatment,
labels, glyphs, the server's media-kind rule, adapters from
`CompanyArtifact`), `geometry.ts` (the measured constants), `when.ts`,
`ArtifactSheet`, `ArtifactPrint`, `ArtifactStack`, `ArtifactFront`,
`ArtifactTile` (stack and single tiles, caption, grid), `ArtifactRow`
(the row and its inline group), `ArtifactsV1Filters`, with the mock's
SVG assets.
- Wire the Artifacts page: with the setting on, the toolbar's filter row
becomes the V1 views and the grid renders V1 tiles; the toolbar takes an
optional `filters` row for this. The old cards and kind filters stay the
default.
- Wire the panel's Artifacts tab (`IssuePropertiesArtifactsTab`): with
the setting on, one flat list of V1 rows, newest first; `DocumentRow`
and `MarkdownWorkProductRow` take a `face` render prop so the V1 row
fronts their unchanged expansion, review and deep-link behaviour;
`PanelFileRow` opens attachments and attachment-backed work products the
way the shipped card does (gallery, text tab, new tab) with open and
download beside the name; other work products are a link row with their
status.
- Wire the task thread: `TaskChatBubble` hangs a message's files under
its footer as V1 rows inline (pictures and video to the gallery, text to
a text tab, files to a new tab) in place of the media grid and file
chips; `TaskChatProtocolCard`'s resource rows render deliverables,
documents and attachments as one V1 row each, opening where the card
did.
- `ArtifactRow` keeps trailing controls beside its own control (no
nested interactive elements) and can be a link, an in-app anchor, a
new-tab anchor or a button; adapters read work products, documents,
attachments and message references.
- Add a catalogued Storybook story, `Components/Artifact V1 primitives`,
under `documents-artifacts`, on fixtures.
- Add tests: the primitives (kinds, dates, print fitting, tiles, rows),
the hook, the Artifacts page, the panel's Artifacts tab, the task-chat
bubble and the protocol card, each with the setting on and off; the
settings page and server tests list the new key.
- Add `doc/plans/2026-10-22-artifacts-mvp-v1.md`.

## Verification

- Run `cd ui && pnpm typecheck`: the Storybook catalog accepts the new
story, and `tsc -b` is clean apart from the five pre-existing
`PluginOrganizationSwitcher` errors.
- Run `pnpm check:token-gates` and `node scripts/check-maps.mjs`: clean.
- Run `cd ui && npx vitest run src/components/artifacts
src/components/issue-properties
src/components/task-chat/TaskChatBubble.test.tsx
src/components/task-chat/TaskChatBubble.artifactsV1.test.tsx
src/components/task-chat/TaskChatProtocolCard.test.tsx
src/components/task-chat/TaskChatProtocolCard.artifactsV1.test.tsx
src/pages/Artifacts.test.tsx src/hooks/useArtifactsV1Enabled.test.ts
src/pages/InstanceExperimentalSettings.test.tsx`: the suites pass (151
tests in the last run).
- Run `cd packages/shared && npx vitest run src/feature-catalog.test.ts`
and `cd server && npx vitest run
src/__tests__/instance-settings-service.test.ts`: pass.
- Manual: open Settings > Experimental, turn on Artifacts V1. On the
Artifacts page the view row reads Tasks, All files, Images, Videos,
Documents, Text, Files; tasks with several artifacts show as stacks,
hovering fans the pages and lifts the artwork (not under reduced
motion); Images shows single tiles with bordered prints. Open a task's
Artifacts tab: one list of rows, newest first; a Markdown work product
still expands into its review surface, a document still opens in its
tab. In the thread, a message's files sit under its footer as rows. Turn
the setting off: everything returns to the current presentation.
- Storybook: `Tasks and conversations / Documents, attachments, and work
products / Components / Artifact V1 primitives`.
- Not run: the full `pnpm test:run` and `pnpm build` (CI runs them), and
a browser pass against a dev instance with real artifacts on the three
surfaces; that pass is the remaining step before this leaves draft.

## Risks

- Off by default; with the setting off, the only changes on a product
path are an optional `filters` prop on the toolbar, an optional `face`
prop on two panel rows, a read of the setting in the bubble and the
protocol card, and the new token declarations.
- With the setting on, the Artifacts page's view tabs set two URL
parameters (`groupBy`, `kind`) at once; the group-by menu and search are
unchanged.
- A picture with unknown dimensions renders at 4:3 until it loads, then
the print refits once; the frame's height is fixed so nothing below it
moves.
- About thirty new `--artifact-*` tokens, namespaced and documented in
place.

## Model Used

- Claude Fable 5.1 by Anthropic, model ID `claude-fable-5-1`, used
through Claude Code in the desktop app. Extended reasoning was on.
Capabilities used: tool use (shell, file edits, a headless Playwright
browser for the lab's measurements, the Figma MCP server for the mocks
during the lab work) and image input. The context window is the Claude
Code session's; its exact size is not surfaced to the session.

## 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 (#17213 is the lab this builds on)
- [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 (the suites listed above;
CI runs the full set)
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes (the
plan document; no command or product behaviour changes outside the
setting)
- [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
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-22 15:14:58 -07:00
DottaandPaperclip d33b40a5c3 fix: recover saved work and provide reliable task Retry (#16965)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The control plane must retain work when an execution or workspace
export fails.
> - Retained-workspace holds can leave saved input waiting with no
usable Retry action.
> - Users cannot verify process ownership or repair provider
allocations.
> - This pull request gives system recovery a durable budget and gives
each deliberate Retry a durable intent.
> - Safe recovery can preserve files, settle an accepted result, or
prepare an independent workspace.
> - One task state keeps infrastructure diagnostics out of the ordinary
conversation while preserving real permission and approval gates.

## Linked Issues or Issue Description

**What happened?**

A task with a retained workspace can show recovery, failed-run and
saved-message warnings at the same time. Historical runs without native
workspace descriptors cannot use the native restore path. Old recovery
metadata can prevent a new attempt even when an independent workspace
would be safe.

**Expected behavior**

Paperclip owns bounded infrastructure retries and file preservation. A
user can request another attempt with ordinary Retry. Thinking appears
immediately. The service preserves completed effects and current user
controls. It does not claim that starting fresh recovered the old files.

**Steps to reproduce**

1. Retain a failed run and its workspace after export or process-stop
failure.
2. Save a follow-up while the recovery hold is active.
3. Open the task and try to continue without infrastructure credentials
or operator certification.

Refs #16906, #16835, #16883. This extends their recovery and receipt
contracts. Related work: #16962 and #16963.

## What Changed

- Add task-level Retry with company-scoped authorization, all-status
idempotency and durable admission before physical work. Keep exact-run
Retry compatible.
- Add typed recovery phases, finite persisted backoff, historical
adoption and durable local failure diagnostics.
- Preserve native workspaces or verified historical snapshots. Admit an
independent fresh workspace only after execution containment. Keep
old-source preservation and cleanup obligations separate.
- Carry completed publication and API receipts forward. Fence uncertain
mutation retries across replacement runs. Preserve connected-chat
identity and authorization.
- Re-enter normal dispatch for saved input. Reuse accepted results
through the existing finalizer.
- Use one task interruption projection across the thread, composer and
task list. Show optimistic Thinking, ordinary Retry and genuine user
gates.
- Add PostgreSQL, filesystem, API, browser-fixture and controlled
provider coverage. Document the behavior and update the feature/access
maps.

## Verification

- All GitHub Actions CI jobs pass on
`6d8c6d27d50586d8548b31d03b47f6d73a0ee11d`: typecheck, all
server/chat/workspace and serialized suites, Runner checks, eight
browser shards, canary and build. The required merge gate passes.
- Greptile reviewed the final commit at 5/5, with no actionable findings
or unresolved review threads. Its two earlier P1 findings are fixed.
- Full recursive typecheck and build pass locally on the final commit.
All 16 task Retry cases pass against isolated real PostgreSQL. The
unrelated-success case and both stale Retry cases fail on the previous
code and pass after the fix.
- The corrected gateway fixture passes its uncertain-mutation and
independent-read case. Four real HTTP API cases pass for definite
403/422 rejection, completed-effect reuse, and uncertain-effect fences
across deliberate and automatic retries. These focused gateway/API
checks used a temporary database lifecycle harness on an existing
healthy local PostgreSQL process. The standard repository helper is
unchanged.
- Earlier qualification covers 291 task UI cases, saved-file copyback
and ancestry, current Agent Chat ownership races, nine chat Retry API
browser cases, and six assembled browser recovery fixtures. A real
API/PostgreSQL/native-runner journey showed Thinking in 25 ms despite a
delayed response, admitted one successor in a separate workspace,
retained original files, and survived reload.
- The controlled Daytona test interrupts export, joins the controller,
restarts it in a separate process, and verifies one agent start, one
external sentinel operation, retained file contents and no premature
cleanup. It does not establish abrupt-kill or live LLM/GitHub
acceptance.
- The full local `pnpm test:run` was attempted and was not green: an
OAuth row-lock timing assertion failed, and a later suite exhausted
macOS PostgreSQL semaphores. The ten OAuth timing cases passed on rerun
against a separate database. Later embedded database initialization
failures remain recorded; the final CI matrix passes.
- Security scanning passed on production-code commit
`63953edf069b111c6becc3144dffa6deb52f68b5`. Its only successor changes
one test-fixture identity line. The final scan is neutral/inconclusive
because its pinned merge-base checkout failed or timed out. Both rerun
API requests returned 404, so no fresh successful scan is claimed.
Socket and Snyk checks pass on the final head.
- The optional Paperclip Review remains queued behind an earlier run in
workspace finalization. Its prior completed assessment was incomplete
because a comparison tool was blocked by the platform filter. It is not
counted as a completed code review. GitHub does not require this check
for merge.
- Hosted acceptance remains pending deployment. Local and CI results do
not establish recovery of a hosted task or its retained files.

## Risks

- Recovery changes span admission, physical ownership and dispatch.
Incorrect evidence could permit overlapping work. Existing physical
locks and authoritative stop requirements remain in place.
- The migration adds concurrent indexes. It requires the existing
top-level migration runner and retries incomplete index creation safely.
- A fresh attempt can complete while old-source preservation remains
unresolved. The service retains that obligation and does not report
those files as recovered.
- Unknown tool mutations remain blocked until their authoritative
receipt owner resolves them. Generic upstream tools have no universal
result-query protocol.
- Recovery and diagnostics stay inside the stack. No Cloud incident
endpoint, notification worker or new outbound reporting channel is
included.

## Model Used

OpenAI Codex, GPT-6 family. The runtime does not expose a more specific
model version or context-window size. The model used reasoning, shell
execution, source editing and browser tools. No model subagents were
used for this implementation.

## 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 (focused suites; the full
local run limitation is documented above)
- [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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 19:58:53 -05:00
DottaandPaperclip b11010b0d4 Simplify failure banners and show only the latest error (#16982)
Remove dashed failure dividers and show only the latest adjacent run or recovery error. Preserve permitted retries, pending state and unrelated notice boundaries. Add production-component Storybook examples and browser regression coverage.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-20 14:29:39 -05:00
DottaandPaperclip 8ee851a0d8 fix(ui): keep runner turns stable through startup and completion (#16989)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Task chat shows each agent turn from message submission through
completion.
> - Run admission can publish adapter metadata before native runtime
metadata.
> - The UI changed layouts during that gap and removed the agent
identity.
> - Completion reports can also arrive before the provider writes its
final reply.
> - The event reader treated those reports as final replies and then
replaced them.
> - This pull request keeps the runner layout stable and delays report
fallbacks until the final history fetch completes.
> - Readers see one provider reply, while report-only runs keep a useful
answer.

## Linked Issues or Issue Description

**What happened?**

Sending a task message briefly replaced the runner avatar, name, and
Thinking row with a generic Working row. At completion, a full report
summary appeared as the answer. A shorter provider reply then replaced
it while streaming.

**Expected behavior**

Keep the runner identity and header spacing stable during admission.
Stream the provider's final reply once. Use a report summary as a
fallback only after the run ends and its final history fetch completes
without a provider reply.

**Steps to reproduce**

1. Send a message to a native Paperclip Runner agent.
2. Observe the initial run record before native runtime metadata
arrives.
3. Let the agent call its completion tool before writing its final
response.
4. Observe the report summary, final response stream, and saved reply
handoff.

**Paperclip version or commit**

Reproduced from source at `6b804bfeba`. The event-reader behavior was
also present in earlier revisions.

**Deployment mode**

Self-hosted server. Local component tests and browser fixtures reproduce
the UI transitions.

Related work: Refs #12617, which added native runner turns to task chat.
The duplicate search found no open PR for this specific defect.

## What Changed

- Keep Paperclip Runner turns in the runner layout while runtime
metadata resolves. Use the same header spacing for queued and running
states.
- Keep structured reports as report entries. Do not create synthetic
provider final messages from them.
- Track successful event fetches for each run status. Permit a terminal
report fallback after the final fetch, or when the transcript contains
its terminal receipt.
- Preserve report-only answers and saved reply deduplication.
- Add desktop and mobile regressions for streamed replies, late final
events, report-only runs, pagination, and fetch failures. Delay
missing-answer notices until terminal history is ready. Document the
presentation rules in `DESIGN.md`.

## Verification

- Passed all 8,750 UI tests across 769 files. This includes 456 focused
tests for the thread, runner turn, native projection, native transcript
hook, transcript adapter, and boundary fixtures.
- The six completion regressions fail against the old native event
reader and pass with the fix. Three empty-history regressions fail
before the review fix and pass afterward. The startup regressions also
fail against the old layout condition.
- Passed UI TypeScript checking with `node
node_modules/typescript/bin/tsc -b ui/tsconfig.json`.
- Passed the UI production build with `cd ui && node
node_modules/vite/bin/vite.js build`.
- Passed `pnpm check:token-gates`, `git diff --check`, and the Storybook
catalog generator.
- Browser check: mounted the production turn with native event snapshots
at desktop and 390-pixel mobile widths. The report stayed hidden while
running. The actual reply stayed unchanged at completion. The
report-only fallback appeared after completion. The identity row kept
the same position and size. No browser errors or horizontal overflow
occurred. The temporary fixture was removed.
- Passed `pnpm -r typecheck` and `pnpm build`. Initial attempts failed
with `COPILOT_INSTALLATION_INVALID`. Reinstalling the generated Copilot
assets resolved that local packaging failure without source changes.
- The full repository test run was attempted locally and stopped after
repeated embedded PostgreSQL bootstrap failures in server suites. The
complete UI suite passes independently. In CI, serialized shard 5/9 had
one 15-second timeout in the unchanged `agent-live-run-routes.test.ts`
history-limit case; its other 387 tests passed. All five history-limit
variants pass locally. The single CI job retry passed. The original
timeout cause is not established.

## Risks

- Report-only answers appear later because the UI waits for terminal
history. Failed event fetches keep that fallback pending until a retry
succeeds; provider replies remain visible.
- Historical replies and accepted response-wake behavior retain their
existing resolution rules. The focused tests cover these paths.
- The change does not alter provider execution, completion authority,
database schema, or run timing.

## Model Used

OpenAI GPT-6 through Codex. The exact serving model ID and context
window are not exposed in this session. Used reasoning, code execution,
and browser inspection.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 12:45:47 -05:00
DottaandPaperclip 92b238137b Connect and configure GitHub Copilot through Apps (#15705)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Apps and AI Connections store credentials and govern access to agent
runtimes.
> - Users need a supported saved-token connection and config values that
survive save and reopen.
> - The release must preserve saved-token access and task lifecycle
guarantees.
> - This pull request will connect Copilot through the normal Apps and
AI Connections path.
> - The benefit is a reviewable part of the Copilot production release.

## Linked Issues or Issue Description

Refs #15701 and #15703. Supersedes setup work in #15562. Base: #15703.
Next: #15706.

## What Changed

- Require configuration update authority before Copilot
credential-bearing model discovery; default to the saved environment and
preserve explicit selection for editors.

- Keep Copilot discovery passive during reconnect reconciliation;
refresh on explicit opening, account/environment changes and reconnect.

- Add GitHub AI token connections with encrypted storage, ownership,
grants and audit logging.
- Keep repository access separate from Copilot runtime authentication.
- Probe the selected environment without sending a model prompt and
preserve authenticated model selection through save/reopen.
- Keep fresh execution admission consistent with normal Copilot setup;
persist task model choices without changing provider or permission
policy.
- Refresh authenticated models after reconnecting the same saved Copilot
account, including recovery from a previous authentication error.
- Apply the additive provider-default constraint migration through the
normal generated migration workflow.

## Verification

Runtime #15701 is merged at `d855e550ad8d2a267312983f26457aabf5393c3a`.
History #15703 is merged at `df80616d98119cbf5abd40549794d9980a5fabf6`.
Remaining source
[`42bcbd61299655f7e37aabe6bb5f19bba770ad1d`](https://github.com/paperclipai/paperclip/commit/42bcbd61299655f7e37aabe6bb5f19bba770ad1d)
contains the four-file authorization repair. The remaining PR trees
preserve six nonoverlapping files from the newer public mainline
managed-settings fix and the CI-owned lockfile. No unrelated provider is
enabled.

The security finding is repaired: existing-agent discovery requires
`agent_config:update` before connection selection or token resolution.
The saved environment is the default. Authorized editors can select a
prospective environment. Both denied board-viewer and agent-reader
regressions fail on the original source. All49 route tests and server
typecheck pass with the fix. Denied requests perform no connection
selection, credential resolution or probe. Current-head security scans
pass on both remaining PRs; the repaired thread is resolved.

Copilot CLI1.0.88 and profile47 retain digest
`sha256:55044aa235e88b3fe36ec8a556ee1e3382590870aab907e4462ef7d64af49cea`.
The [qualification
record](https://github.com/paperclipai/paperclip/blob/42bcbd61299655f7e37aabe6bb5f19bba770ad1d/doc/plans/2026-10-20-copilot-qualification-v47.json)
reports20/20 Product cells,154 assertions and7/7 protocol cases,46
assertions against frozen normal installed source
`c2616370800f5f6df45246b0890ba35a7cd2faab`. The exact qualification
model is `gpt-5.6-luna`. Every passing Product case confirms cleanup.
Original failures remain recorded; automatic behavior retries are
disabled. The route-only authorization repair changes no bound
runtime/profile bytes and does not relabel the frozen campaign.

The ordinary installed remote journey passed saved-token selection,
model discovery, normal UI save/reopen, metadata-only Test, completed
task, accepted receipt and exact19-byte browser download. An open model
catalog caused no additional discovery requests during117seconds. Actual
installed runtime smokes passed on macOS ARM64, macOS x64 under Rosetta
and native Linux x64 on Daytona. Raw token browser entry was not
exercised; encrypted connection creation used the normal API.

The first Daytona file attempt timed out during delayed semantic
dispatch; its precise stalled layer remains unresolved. Independent
ordinary remote delivery and the other19 Product cells passed before one
instrumented recheck passed8/8 with unchanged source,prompt,assertions
and deadlines. No causal latency repair is claimed.

Before the authorization repair, all four final PR heads passed required
verify/E2E and fresh Greptile5/5 reviews with zero unresolved threads.
Current-head CI/review is running for the two repaired heads. Local
focused checks retain129 connection,59 runner,72 shared-eval and88
recovery/workspace passes, plus migration safety and token gates. The
additive Copilot migration is361; released master history is preserved.

[Cloud normal-package
run39414239704](https://github.com/paperclipai/paperclip/actions/runs/39414239704)
builds the pre-security source4f3f. All four native producers and Linux
package assembly pass; the final clean installed consumers are
finishing. All18 retained archives match their hashes;37,863 regular
files contain zero selected credentials. That package does not contain
the later route repair. The actual final published package must include
it and pass the local/Daytona live canaries. The frozen Daytona image
remains published and independently verified. No separate full-image
scan is claimed. Docker builds run in the cloud.

**Remaining:** current-head CI/review, setup and qualification merges,
final publication, and ordinary local/Daytona canaries against the
actual shipped package. The user explicitly authorizes the maintainer
review override; CI remains a merge gate. No production deployment is
claimed. Provider USD remains unknown and GitHub-attributed.

## Risks

Bad credentials, missing entitlement, runtime installation and
unavailable models must remain distinct failures. A connection must not
adopt ambient credentials. The constraint migration changes accepted
provider values, with no credential-storage migration.

Current-master NewAgent fixture extraction is retained. Copilot cases
use that shared support and test both passive discovery and explicit
reconnect under the same setup lifecycle.

The onboarding retry regression shares the component suite’s
saved-connection, authenticated-model, draft, agent-list, hire and
render lifecycle fixtures. Keeping it beside the existing onboarding
failures makes adoption versus duplicate hire observable under the same
lifecycle; this is the concrete cohesion reason for the existing large
test file.

## Model Used

OpenAI Codex, based on GPT-6. The exact serving model ID and context
window are not exposed in this task. Used for code changes, review and
tool-assisted verification.

## 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
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-20 07:02:22 -05:00
DottaandPaperclip 16689de291 fix: add one-click retry for restricted workspace setup (#16909)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Tasks need a clear way to resume after a setup failure.
> - A shared repository can contain another task that the assigned agent
cannot read.
> - Paperclip correctly stops before the agent starts, but the user must
then understand workspace settings to recover.
> - This pull request gives that failure a single Retry button and
selects a clean copy of the configured repository through normal
admission.
> - The task keeps its assigned agent and execution settings, while
access checks and existing work remain protected.

## Linked Issues or Issue Description

Related: #16895 classifies the restricted source failure. This change
adds the user recovery action. #16906 handles retained files after
execution; this change handles a setup failure before execution starts.

**What existing behavior does this improve?**

Recovery of a task whose shared repository includes a task workspace the
assigned agent cannot read.

**Current behavior**

The task stops before provider work and asks the user to understand
workspace choices or access grants.

**Proposed behavior**

Show Retry above the task message box, independent of loaded
conversation history. One click requests one attempt using a clean
checkout of the configured remote. Show Retrying while the request is
pending. Show an error only if the request fails.

**Reason and benefit**

The user can resume work without understanding repository isolation or
changing access to another task.

**Breaking changes**

None. The recovery source value is server-owned. The public workspace
selection request does not accept it. No migration is required.

## What Changed

- Add one Retry control above the composer in both task conversation
views. It stays available when an older notice is outside the loaded
comment pages.
- Bind recovery to the latest failed run, current assignee, and recorded
proof that provider work did not start.
- Use the existing atomic recovery route and pending workspace
selection. Normal admission clears the old session and creates the
isolated checkout.
- Choose a fresh task-owned branch for recovery, including fixed project
branches, existing task branches, and adapter branch overrides. Preserve
the model, environment, setup commands, pending user workspace choices,
previous files, and all execution gates.
- Update execution documentation and both workspace maps.

## Verification

- Passed all 461 tests in the eight affected database, Git, HTTP,
workspace binding, and conversation suites after the review fixes. An
additional 292 tests passed after the final compatibility fixes,
including IssueDetail and recovery action routing.
- Concurrent HTTP retries produce one wakeup. Paused projects and runs
that started provider work reject recovery without changing the
workspace.
- Real Git tests exclude private files, private commits, and unpublished
original files from the clean checkout, preserve the original, and
exercise reuse, cleanup, and reopen.
- Verified in a running local app: a task failed twice, displayed only
Retry, and reached Done after one click. A second browser test put the
failure notice behind 501 newer comments and used a fixed project
branch. Retry stayed visible and the task reached Done. The
credential-free process worker used the selected checkout and wrote its
result there. This does not claim a live model-provider run.
- The first manual fixture lacked a responsible-user membership and
failed after successful workspace recovery. Corrected the fixture,
retained that failure evidence, and verified the full flow with ordinary
authorization.
- Full typecheck, build, token gates, and map checks passed. The full
local suite was stopped after review changed its source during
execution; current-head CI provides the complete suite result.
- An earlier unrelated peer-comment read test hit a socket hangup. The
next complete affected-suite run passed; the first failure is retained
in local evidence.
- Current-head CI hit an unchanged runner credential-concurrency test
failure. That lane passed on the preceding commit, and all 42 credential
tests passed locally. The original failed job is retained; the one-time
rerun passed. All latest-head CI checks are green (55 success, 2
skipped, 1 neutral), and Greptile is 5/5 with both review threads
resolved.

## Risks

- A remote repository outage can still prevent the next attempt. Retry
does not grant access or copy unpublished files from the old checkout.
- Recovery accepts only the latest recorded pre-provider failure and
preserves normal execution gates. This limits duplicate work and stale
recovery requests.
- No database migration, dependency, or lockfile change.
- The first review found fixed-branch retry loops and dependence on
paginated notice history. Both had failing regressions before the fixes
and now pass targeted tests and the combined browser journey.
- Full CI then caught assumptions about missing run evidence and
unrelated recovery actions. The final changes tolerate absent evidence
and scope the new lookup to board-owned actions with valid run IDs. The
previously failing suites now pass locally.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and browser verification. The exact serving model ID and
context window are not exposed in this session.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 21:49:44 -05:00
7b9334cd10 Draft: Build agent-ready design proposal system (#16875)
## Thinking Path

> - Paperclip helps people manage AI agents and their work.
> - People need consistent UI patterns to review and control that work.
> - The current board uses related layouts and controls with different
spacing, type, and behavior.
> - That drift makes it hard for a designer or an agent to build a new
page from a reliable reference.
> - Storybook can show the shared patterns and the states they need to
support.
> - This pull request adds design proposals, a local sandbox, and
reusable UI controls so people can compare the patterns in context.
> - The benefit is a clearer design system that agents can use to build
consistent UI.

## Linked Issues or Issue Description

**Subsystem affected**

`ui/` — React board UI and Storybook.

**Problem or motivation**

Board pages repeat visual and interaction decisions. Storybook did not
provide a complete reference for task views, conversation states,
typography, toolbars, tabs, and light/dark colors. People could not
compare a proposed pattern with the running board in one place.

**Proposed solution**

Add a staged Design Proposals catalog with foundations, components,
layouts, and page specimens. Add an opt-in sandbox. Reuse production
components where possible. Include synthetic conversation states and
shared controls so reviewers can compare and refine them.

**Alternatives considered**

Separate static mockups would not show keyboard behavior, responsive
layout, or real component states. Rebuilding each page only in Storybook
would allow the reference to drift from the board.

**Roadmap alignment**

This improves existing board UI and Skills Manager surfaces. It does not
add a new control-plane capability.

## What Changed

- Added dark and light color references, typography and conversation
specimens, and component stories for buttons, tabs, toolbars, sidebar,
popovers, activity, and task lists.
- Added a local design sandbox with synthetic task conversation playback
and representative states.
- Shared collection toolbars and navigation patterns across task, agent,
project, routine, skill, connector, and artifact pages.
- Added the streamlined Skills tabs and a My Skills collection that uses
the shared skill cards.
- Restored saved-thread access during synthetic playback, kept connector
searchbox semantics, and updated reproduction checks after moving trial
stories.
- Documented the proposed patterns and added focused UI, catalog, and
browser checks.

## Verification

- `pnpm check:token-gates`, `node scripts/check-maps.mjs`, and `node
scripts/storybook-catalog.mjs --check` passed.
- Full workspace `pnpm -r typecheck` and `pnpm build` passed after
merging master. After the review fixes, focused UI typecheck, `pnpm
build-storybook`, 23 Skills Sources tests, and all 15 Storybook
typography browser tests passed.
- Focused task-thread and system-notice suites passed: 251 tests.
Connector Browse passed 84 tests; the connector, attachment, recovery,
and Storybook flyout browser journeys passed locally.
- A local full Vitest run hit one intermittent chat-channels integration
failure; that test passed in isolation. GitHub CI
[39347996059](https://github.com/paperclipai/paperclip/actions/runs/39347996059)
passed on the exact latest commit: 55 successful checks and two skipped
draft-only Storybook jobs.
- Greptile reviewed the exact latest commit at 5/5 with no new comments
or open review threads. GitHub reports the branch as cleanly mergeable.

## Risks

- This PR changes 206 files and exceeds the repository's 100-file review
target. Review by commit and consider a scoped split before merge.
- Design Proposals are staged references. Fixture interactions do not
prove API behavior, permissions, or provider execution.
- UI changes to shared controls may affect pages outside the proposal
sandbox. Focused browser checks and the full CI matrix passed.

## Model Used

- OpenAI Codex, GPT-6 family. The exact runtime model ID and context
window are not exposed in this session. The model used reasoning, code
execution, browser inspection, and local tests. Earlier branch commits
were also AI-assisted in this Codex conversation.

## 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 available in this session)
- [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 where applicable
- [x] I have either linked existing issues or described the issue in-PR
following the relevant issue template
- [x] I have not referenced internal or instance-local Paperclip issues
or links
- [x] My branch name describes the change and contains no internal
ticket id
- [x] I have run focused 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 risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Scott Tong <scott@scotts-mbp-m5-max.local>
Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 17:45:26 -07:00
DottaandPaperclip 45b67f1d93 feat: default new Apple Silicon Claude agents to Paperclip Runner (#15993)
## Thinking Path

> - Paperclip lets users choose an agent harness and account.
> - The server resolves the runner for new agents.
> - Claude still needs the same ordinary native-default journey as
Codex.
> - Existing agents must retain their runner, model and account.
> - This PR defaults new Apple Silicon Claude agents to Paperclip Runner
with Opus 5.5.
> - Users can connect and work without a runner override.

## Linked Issues or Issue Description

Refs #15683. This PR depends on #15994 and precedes #15997. Related
scope: #15422, #13978 and #15224.

## What Changed

- Resolve new Apple Silicon Claude agents to `paperclip_runner`,
`provider: acpx`, `acpxAgent: claude`. Keep explicit Legacy, models,
provider routing and saved execution.
- Use `claude-opus-5-5` for ordinary Claude defaults and retain explicit
overrides.
- Reuse existing API-key/subscription connections, credential storage
and checks. Generalize the shared Advanced runner control with Claude
branding.
- Carry configured effort into the shared v9 contract. Preserve
compatible permissions, instructions, skills, timeouts and session
behavior. Require Legacy for unsupported settings.
- Qualify a new immutable managed Claude target at explicit Connect
through the existing permission-gated probe. Use fresh scoped discovery
for test and hire. Discard stale results and require an explicit Connect
after settings change.
- Retain merged Codex onboarding recovery, auth preparation,
import/effort corrections and Grok Bot gates.
- Check the Claude first-task wizard's saved default directly. Update
configuration/runtime documentation and exact Opus 5.5 accounting.

- Align hire fixtures with the merged host-environment restriction.
Native agent-authenticated hires cannot inject host env settings; both
creation endpoints verify that no extra agent is saved.

## Verification

- Updated onto master `9179d8dcc3e908c217fde4f63c9d08ccf8132eeb` through
#15994. Native input v9 carries effort while preserving v7 home modes
and v8 Muse. Codex defaults remain unchanged.
- Focused local verification passed 285 server tests, 323 UI tests, 124
setup/registry tests, and two v9 permission-pin transport cases. Direct
server/UI TypeScript checks passed. An initial 30-second hook timeout
was resolved by serial verification with a longer hook budget: all 122
credential/permission cases and 232 snapshot/environment cases pass.
Direct server TypeScript checking also passes.
- Ordinary web creation with the experiment disabled saved native
Claude, Opus 5.5 and High effort without runner/model overrides. The
actual product task and follow-up both succeeded on integrated source
`b2c9fe43f9cd3bc5dd9d22552da0148845ba71a4` with the cloud-built daemon
from `04e0202ca81387b17cbe7fd094a8338648356fe9`. The final master
reconciliation also changes shared runtime source. Historical proof
retains its source identity; a final-source cloud qualification is
running before refreshing the preview daemon.
- Both actual browser downloads were checked: v1 has three sections/six
checkboxes (451 bytes); v2 preserves the original body and adds two
Rollback checks (612 bytes). The original attachment stayed
byte-identical. The follow-up records session resume and the same
provider session. Total estimated API usage: $0.518432800, with no
pending/unpriced usage in the successful fixture.
- Fixed the live-discovered setup incompatibility: native API-key
validation no longer depends on the global Legacy Claude CLI. The
existing provider endpoint verifies the key without a paid prompt;
subscription/custom routing probes remain intact.
- Fixed security review's native-hire credential redirection:
agent-supplied URLs, proxy/launch settings and other host environment
controls are rejected before inheritance. Native credential references
remain supported and partial edits use the saved harness. Added
create/hire/update regression coverage.
- Current-head cloud CI is green. All three stack PRs have fresh
Greptile 5/5 reviews and zero unresolved review threads. Required
typecheck, test and build gates ran in cloud CI; Docker work stayed
remote. Earlier failed checks remain in their original runs.
- Docker and native release builds ran in cloud infrastructure. An
inadvertent local Rust prerequisite was stopped; no local Docker build
was run.

- The final master merge preserves task-loading, permission,
skill-retention and OpenRouter changes. Pi uses a fresh combined profile
27, preserving both historical profile-24 declarations; Copilot remains
profile 22. Focused protocol checks passed 155 cases (one skipped), the
updated Pi attestation check passed 18 (one skipped), and 91
evaluation/catalog checks passed.

- Latest-application manual continuation passed in 37.942 seconds on
`695e5c005a85bddc8711d3fcddcaf6b7e1fb64d0`, with High effort, native
Opus 5.5, Anthropic API attribution, the same resumed Claude session, an
independently checked 635-byte file and persisted Done status. It uses
the earlier verified Mac daemon; the preceding-source package
qualification passed at `dca62c7aeb4b45f0dd91a8e18d386a16a2658ef8`. That
package run predates the small TypeScript startup fix and is not
relabeled as qualification for it.
- Upgrade limitation: changed compiled sidecar identity rejected old
durable launch state and recovery hit session-open bounds before
eventually resuming. That attempt was operator-cancelled and retained;
the successful manual continuation does not qualify seamless upgrades.

- Local latency profile, Opus 5.5/High unchanged: three alternating
real-ACP loopback samples per variant reduce median provider-ready time
from 5.081s to 4.034s. The matched real API task startup improves from
5.533s to 4.348s, but total reply time changes from 17.933s to 20.221s
because agent work varies. This establishes a startup saving of about
one second, not a consistent total-reply speedup. A real candidate
follow-up passed in 20.146s and resumed the same saved session. The
loopback fixture makes no external model requests; failed initial probes
remain retained.
- The startup change passes 107 focused runtime/effort/lease tests, 53
profile checks (one skipped), TypeScript checking and the
TypeScript-only runtime build. Native hire fixture checks pass 70 tests;
their first local run retained a socket-hangup failure and stale
OpenCode expectation, both accounted for before the passing rerun.
Broader required checks run in cloud CI.

## Risks

- Missing packages, authentication rejection, unsupported settings and
unavailable models must fail explicitly. Existing agents retain saved
execution; explicit runner changes use existing revision/session
invalidation.
- Subscription follow-up remains unverified; remaining live acceptance
uses API keys per human steering. Historical accounting holds and the
separate $50 ceiling remain intact.
- The subscription acceptance limit remains explicit for review. No
Claude database migration is introduced.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution and browser testing. The exact serving model ID and
context-window size are not exposed in this session.

## 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
- [ ] Focused local tests and final cloud verification 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 13:58:52 -05:00
DottaandPaperclip fa50cab568 perf(ui): speed task loading without shifting the conversation (#16849)
## Thinking Path

> - Paperclip's board should open a task quickly while keeping its
conversation and composer stable.
> - The browser currently downloads unrelated screens and unopened
dialog implementations before task content appears.
> - Splitting routes alone creates many shared requests and did not
improve measured cold loading.
> - This change groups the startup and task dependency trees, preloads
the task chunk, and defers optional routes and dialogs.
> - Existing coordinated history reveal stays intact so late data does
not insert content above the reader.
> - Hidden routes must not overwrite saved scroll positions with
zero-height geometry.
> - Repeated browser measurements and delayed-response tests establish
the result independently of bundle-file size.

## Linked Issues or Issue Description

Refs #14758. Related prior work: #10463 and #14727.

**What existing behavior does this improve?**

Cold task-page opening downloads and evaluates code for other screens
and globally mounted, unopened dialogs. A direct task link should reach
its saved conversation sooner without moving already-visible messages or
the composer.

**Subsystem affected**

Board UI startup, route boundaries, dialog loading, task scroll
restoration, and the issue-detail performance harness.

**Proposed behavior**

Load optional screens and dialogs when needed, keep startup requests
bounded, and preload the task route. Preserve the current history reveal
policy. Keep the shell mounted during route loading and preserve the
reader's position when a route is temporarily hidden.

**Additional context**

The older bundle-splitting attempt in #10463 is still open from August.
This implementation targets current master and deliberately preserves
today's editor, composer, and transcript reveal behavior. It does not
implement the alternative transcript-row design discussed in #14758.
ROADMAP.md does not describe overlapping startup-bundle work.

## What Changed

- Lazy-load board routes, standalone screens, the legacy layout,
onboarding, and unopened create dialogs.
- Keep activated dialogs mounted across close/reopen to retain their
existing draft lifecycle.
- Group startup and issue dependencies and preload the emitted issue
chunk from the production HTML.
- Contain route loading within the shell and retain existing chunk-error
recovery.
- Contain dialog import failures locally, support cancellation, and keep
setup dismissed after a late download. Warm the task module from task
lists and keep the small chat redirect eager.
- Wait for task-creation dialog fields in the browser fixture before
filling an explicit title.
- Ignore zero-height scroll geometry while a route is hidden.
- Reuse the same persisted performance fixture between builds, record
actual network spans, and distinguish concealed loading content from the
ready thread in browser assertions.

## Verification

- Production UI build and UI TypeScript check passed.
- Recovery follow-up: 74 focused UI tests passed; the cancellation
change passed 23 focused tests plus all 131 onboarding tests (the latter
with a 15-second per-test timeout on the contended local host).
- Setup cancellation was reproduced against the prior production build
and verified fixed after releasing the held real wizard download.
- 91 focused UI tests passed; the final route registrations were checked
again after making standalone screens lazy (33 routing tests passed).
- All eight real-browser layout scenarios passed: delayed comments, late
media, properties changes, growing drafts, older history, Back
navigation, deep links, desktop/mobile same-task links, request
failure/retry, and stalled native/log reads.
- Browser walkthrough: read a populated task, submit one reply, refresh,
navigate to Projects, and return. The reply persisted once and the
normal composer remained usable.
- Token design gates passed. The separate repository-wide publish-token
scan fails on pre-existing references to the local maintainer username
in unchanged files; this change adds none.
- Production-build measurements use the same persisted task, local
API/database, fresh browser contexts for cold opens, and five samples
per scenario/profile. These measurements do not establish deployed
staging latency.
- Final head `076466816a`, consecutive before/after production builds:
five samples per scenario/profile, same saved task and server. Cold Fast
4G/4x CPU content paint: **5,775 → 4,248 ms (26%)**; issue API server
timing was 23 ms in both sets. Warm Fast 4G: 989 → 971 ms. JavaScript
transferred before content: **2,596 → 1,722 KiB (34%)**.
- Unthrottled cold content paint: 1,306 → 676 ms; warm: 269 → 224 ms.
These local timings vary with host load. Earlier measurements showed
about 20% cold improvement, and a contended intermediate run had
substantially higher API latency; those runs are retained in the local
evidence. The final matched pair meets the proposed 25% target, but it
does not establish a guaranteed 25% improvement across environments.
- All four browser scenarios that failed on the first CI run passed
locally after the readiness fixes; the subsequent CI run passed all
eight browser shards.
- Fault-injection browser checks: delayed route loading preserves shell
geometry; a failed route recovers through Back; cancelled or failed
dialog loading preserves an unsent reply; Back dismisses pending setup
and contains its late failure.

- Final head `076466816a`: all CI gates green (55 successful checks, no
pending or failed checks); Greptile 5/5 with no actionable findings and
all review threads resolved.

## Risks

- Dynamic chunks add a loading state on first entry to optional screens
and dialogs. Route failures use the existing error boundary. Optional
dialog failures are dismissible without unmounting the board; retrying a
rejected import requires a reload.
- The task preload prioritizes the primary board journey, including when
another screen is opened first.
- Chunk grouping should be revisited when the dependency graph changes;
bundle size alone does not establish a speedup.
- No API, authorization, migration, editor semantics, or
transcript-reveal policy changes.

## Model Used

OpenAI Codex, GPT-6, with reasoning, repository tools, code execution,
and browser verification. The runtime does not expose a more precise
model identifier or context-window size.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-19 10:16:23 -05:00
DottaandPaperclip 896f3c7f3b Add personal Muse operator setup and composer controls (#16450)
Add Muse invitation, connection readiness and scoped operator controls.

Keep connection state tied to the current company, person, agent and binding. Surface failed reads and invalidate stale cleanup observations; require current authority and exact readback. Preserve Dot/Grok setup, source-trust limits and existing design tokens.

Carry actual merged backend e6dcc6b095 through a normal forward merge. Preserve its project-write authority fix, existing migration bytes and upstream idle-serving behavior; no new UI behavior is authored by this source carry. Current-head CI and substantive review remain merge gates; final canonical and deployed-provider qualification remain separate.

Refs #16450.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-17 23:01:42 -05:00
Nicky LeachandPaperclip ec3eb1968b feat(runner): expose credential updates through PRP (#16463)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The Runner uses PRP to send harness events to the host.
> - A harness can replace its stored OAuth tokens during a run.
> - The host has no PRP signal that tells it to read the updated
credential.
> - This pull request adds a durable credential update event and
observers for supported stores.
> - The host can react before it acknowledges the event. Token values
stay outside PRP.

## Linked Issues or Issue Description

**Subsystem affected**

`packages/paperclip-runner`: native provider execution, PRP schemas, and
host event delivery.

**Problem or motivation**

A Paperclip host that consumes PRP needs to react when a harness changes
its refresh-token credential. Existing credential copy-back paths do not
provide a common event during a warm session.

**Proposed solution**

Add `auth.credentials.updated` as a P0 runner event. Include only the
provider, binding ID, revision, and detection method. Observe native
Codex and Codex/Grok ACPX credential files. Retain each pending event
across runner restart until the durable outbox accepts it. Raw PRP
consumers opt in with `observeCredentials: true` before session open.
The bundled transport opts in for fresh sessions.

**Alternatives considered**

`harness.diagnostic` would mix a runner observation with harness
diagnostics. Sending token values through PRP would expose credentials
to event logs. Both approaches are unnecessary.

**Roadmap alignment**

I checked `ROADMAP.md`. This change extends the existing Runner protocol
and does not duplicate a planned core feature.

**Additional context**

Refs: #11094, #14056, #12696. These describe credential copy-back and
staging work. This PR adds the notification contract. It does not
replace those private credential channels or claim to fix their full
scope.

## What Changed

- Add strict credential update payload validation to PRP v1, v2, and v3.
Regenerate validators, the manifest, and the event catalog.
- Watch supported credential directories with `notify`. Add a periodic
read as a fallback and check at terminal and close boundaries.
- Persist a private baseline and pending event together. Notify on
account identity changes and retain the new baseline for later
refreshes. Ignore incomplete files, unsafe files, and metadata changes.
- Forward the event through the host transport. Test commit-before-ACK
delivery and replay.
- Commit pending runner observations before suspend and shutdown
commands complete. Preserve the provider event backlog.
- Create the private ACPX runtime directory before configuring
observation. Cover fresh session startup with observation enabled.
- Fence asynchronous PRP commits to the current authenticated connection
and run authority. Ignore replaced callbacks while preserving the
maintenance drain of admitted work.
- Deliver observations found during final provider cleanup before
clearing terminal recovery state. Retain the outbox and recovery state
when the host ACK is lost.
- Advance the pending Copilot candidate profile to v19 for the changed
shared PRP source hashes. Preserve its v18 history and pending
qualification status. Include the current fixture in the Docker build
context.
- Commit credential updates through an awaited host callback before PRP
ACK, including during idle and close. Persist them in a separate run-log
source namespace with company, agent, session, and runner checks.
- Preserve public event metadata through server redaction. Register the
event in task run details.
- Document opt-in behavior, supported stores, event semantics, and the
local run-log path.

## Verification

- All 45 durable runner control tests and 24 native executor integration
tests pass.
- Ten Rust credential observer tests pass. They cover atomic
replacement, polling, recovery, account-only changes and later refreshes
for Codex and Grok, unsafe files, fresh runtime creation, and the Grok
close handoff. Account identity stays private.
- The full Runner TypeScript suite passes: 3,565 tests in 221 files. An
additional 12 tests are skipped by the suite.
- All 214 focused tests pass for the contract, Codex event routing,
catalog, and durable host delivery.
- All 13 Node protocol contract tests pass.
- The exact Docker context integrity command passes: `docker buildx
build --file .github/docker-context-checks.Dockerfile .`.
- Rust formatting and generated protocol checks pass.
- `pnpm -r typecheck` and `pnpm build` pass. The full local `pnpm
test:run` was attempted with CI-compatible `init.defaultBranch=master`,
then stopped after a reproducible failure outside this change:
`git-workspace-expiration.test.ts` expects one re-expired workspace but
gets zero. The same case fails in isolation on this macOS checkout. Full
repository validation is provided by CI; the focused Runner and host
tests pass locally.
- All 253 native transport and restart tests pass against the final
release binary.
- All 3 durable recovery tests and 139 candidate profile and native
admission tests pass.
- All 41 host redaction and task protocol surface tests pass. `pnpm
check:token-gates` passes.
- All 467 CI policy tests pass, including the 15 CI profiling tests. The
upstream secret-reference test fix is retained from master. No workflow
changes are included.

- The Apex host-delivery fix passes 381 targeted Runner tests, six host
database tests, repository typecheck, and the production build. The
Runner tests cover commit-before-ACK, retry after a rejected host
commit, warm attachment, and close after the turn queue ends.
- Prior head `2f125cfcb` passed CI, standard Greptile 5/5, and Apex 5/5.
One CI shard was interrupted by GitHub runner shutdown; its single rerun
passed. Both Apex findings are addressed: idle/cleanup host delivery and
late callback reconnect fencing. Current head `5db78f082` passes CI (56
successful statuses and four optional skips) and standard Greptile 5/5.
Apex review of the account-change update is 5/5 on this exact head, with
no actionable issues.
- All 121 durable control-plane and credential callback tests pass,
including account-only change delivery, subsequent refresh on the new
account during close, host commit retry, late success/failure races,
forward cursor delivery on a replacement connection, and the existing
maintenance retirement contract. All 27 native provider and durable
recovery integration tests pass after the account-change update.

## Risks

- File changes signal a stored credential update. They do not prove that
an OAuth refresh succeeded. Changes between reads can be combined.
- Unix Codex and Codex/Grok ACPX stores are supported. Other harnesses
and credentials held only in memory need their own integration.
- Hosts must update their event schemas before opting in. Older hosts
omit the flag and receive no new event. Older runners ignore the flag.
- The host must use its existing private credential channel and account
checks to read or copy the token. Account switches trigger notification
but do not authorize accepting the new account. The event grants no
credential access.
- Tests use synthetic credentials. No live OAuth refresh has been
forced.

## Model Used

OpenAI Codex, exact model ID `gpt-6.1-sol`, with high reasoning effort,
repository inspection, tool use, and code execution. The session does
not expose its context window size.

## 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
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-15 14:49:00 -07:00