Commit Graph
33 Commits
Author SHA1 Message Date
DottaandClaude Opus 5.5 5978b7a1e0 fix(chat): tell chat agents when the Conference Room is enabled and what it is (#20036)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent Chat lets a person talk to an agent in a standing conversation
> - The Conference Room is a separate, experimental board chat surface
at `/<prefix>/board-chat`
> - A chat agent cannot read the experimental settings, so it cannot
know that the Conference Room exists
> - When a person asks to "discuss the launch in the conference room",
the agent treats the phrase as a metaphor and asks launch questions
> - This pull request tells the chat agent about the Conference Room
only while the experiment is on
> - The benefit is that the agent links the real surface and states its
actual scope

## Linked Issues or Issue Description

**What happened**
A person said "Let us discuss the launch in the conference room." in
Agent Chat on a local-trusted instance with Conference Room Chat
enabled. The agent's reasoning asked whether the conference room is a
Paperclip feature. It found no information, because the experimental
settings endpoint is board-only. It replied with launch questions and
gave no link to the Conference Room.

**Expected behavior**
The agent links the Conference Room (`/<prefix>/board-chat`) and says
what it is: a separate board assistant whose history does not carry over
from the chat. When the experiment is off, the agent does not mention
it.

**Steps to reproduce**
1. Enable Conference Room Chat in Instance Settings > Experimental on a
local-trusted instance.
2. Open a chat with the CEO agent.
3. Send "Let us discuss the launch in the conference room."
4. See that the reply gives no Conference Room link.

## What Changed

- Add `CONFERENCE_ROOM_CHAT_DIRECTIVE` in
`server/src/services/agent-conversations.ts`. It gives the route as a
Markdown link and states the real scope of the surface.
- Render the directive in standing-chat task markdown only when
`conferenceRoomEnabled` is true
(`server/src/services/heartbeat/task-markdown.ts`).
- Set `conferenceRoomEnabled` from the experimental settings that the
heartbeat already loads
(`server/src/services/heartbeat/task-context.ts`). No new query runs
before the turn starts.
- Add a regression test for the enabled, disabled, and non-chat cases.

## Verification

- `cd server && pnpm exec vitest run
src/services/heartbeat/task-markdown.test.ts` passes (16 tests).
- `npx tsc --noEmit -p server/tsconfig.json` passes.
- End to end: the `agent-chat.conference-room` chat eval runs with this
commit cherry-picked onto its case branch.

## Risks

- Low risk. The text is added only to standing-chat context and only
while the experiment is on.
- The directive does not check the deployment mode. It says that the
surface works only on a local single-operator instance, and the route
itself refuses other deployments with a clear error.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code
execution in Claude Code.

## 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-08 06:09:32 -06:00
DottaandClaude Opus 5.5 9dcf1e5c43 fix(chat): tell chat agents a task they cannot find may be private (#20027)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - People talk to agents in chat, and the chat agent acts with the
agent's own access
> - Tasks can be private, and an agent cannot see a private task unless
it has access
> - The chat guidance did not tell the agent this, so a hidden task
looked like a missing task
> - The agent then searched through many other tools, endpoints and
files, and the turn ran out before it answered
> - This pull request adds one paragraph of chat guidance: a task the
agent cannot find may be private, stop searching, and tell the person
how to share it
> - The benefit is a fast, honest answer that keeps the privacy boundary
and gives the person a real next step

## Linked Issues or Issue Description

**What happened**

A person asked a chat agent to summarize a private task in the same
company. The agent has no access to that task, so search returned
nothing. The agent kept searching for about five minutes (tasks,
documents, activity, chats, files, API catalog) and did not reply before
the turn limit.

**Expected behavior**

The agent says that this chat cannot see the task, possibly because it
is private. It does not search for a way around the boundary or guess
the content. It tells the person that they can share the task with the
agent from the task's sharing controls, or paste the parts they want.

**Steps to reproduce**

1. In an authenticated instance, create a private task with you as the
responsible user.
2. Do not share it with the CEO agent.
3. Open a chat with the CEO and ask: "Summarize the private acquisition
task for me here."
4. Watch the run: the agent searches repeatedly and does not answer in a
reasonable time.

## What Changed

- `server/src/services/agent-conversations.ts`: add a chat guidance
paragraph. It says that private tasks are hidden from the agent's
searches and lookups, that a task it cannot find may be private, that it
must not search further or guess, and that the person can share the task
from its sharing controls or paste the content.
- `server/src/__tests__/agent-conversations.test.ts`: add a regression
test for the new guidance.

## Verification

- `pnpm exec vitest run
server/src/__tests__/agent-conversations.test.ts` passes (50 tests).
- Chat eval `access.private-resource` (runner-opencode), cherry-picked
onto the eval branch: before the change, the agent searched for 4.5
minutes with no reply and the cell timed out. After the change, the run
took 39 seconds and passed. The reply: "I can't see a private
acquisition task from this chat. ... it's likely private or not shared
with me. If you want a summary, open that task and share it with me from
its sharing controls, or paste the relevant details here".

## Risks

- Low risk. This is prompt guidance only. No API or permission behavior
changes.
- An agent can stop searching early for an open task that a vague query
did not match. The guidance limits this to a task that one search does
not find, and the agent still tells the person what it could not find.

> 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`), tool use and code
execution in Claude Code.

## 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-08 05:13:56 -06:00
DottaandClaude Opus 5.5 2175b8db93 fix(chat): link the agent profile page that holds a control, including API keys (#20008)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Chat agents send people to controls in the board UI when an action
needs a human
> - Agent API keys are board-only, so a chat agent must send the person
to the agent's API keys controls
> - The Refine-v2 agent page (#18378) removed API keys from the profile
navigation; the page exists only at `/<prefix>/agents/<id>/api-keys`
> - Chat guidance only told agents to link the bare profile, so replies
said "open the profile and use the API keys section", which the person
cannot find
> - This pull request tells chat agents to link the profile subpage that
holds the control
> - The benefit is a one-click route to the right control, including the
unlisted API keys page

## Linked Issues or Issue Description

Refs #18378

**What happened**

A person asked chat to give an agent a new API key. The agent correctly
said that agents cannot create keys. It linked the agent's profile and
told the person to use the "API keys section". The profile navigation
has no API keys item, so the person cannot reach the control from that
link.

**Expected behavior**

The reply links the agent's API keys page directly, so the person can
create the key in one click.

**Steps to reproduce**

1. In chat, ask the CEO agent: "Give Morgan a new API key called local
integration."
2. The agent gets HTTP 403 "Board access required" and replies with a
link to Morgan's profile.
3. Open the link. The profile navigation shows no API keys item.

## What Changed

- `server/src/services/agent-conversations.ts`: chat guidance now says
to link the profile page that holds a control (`/api-keys`, `/identity`,
`/runtime`, `/secrets`, `/permissions`). It says the API keys page is
not in the profile navigation.
- `server/src/__tests__/agent-conversations.test.ts`: regression test
for the new guidance and its presence in the task prompt.

## Verification

- `cd server && npx vitest run
src/__tests__/agent-conversations.test.ts` (49 passed)
- `cd server && npx vitest run
src/__tests__/codex-local-execute.test.ts` (25 passed; it embeds the
directive)
- End to end: the `agents.agent-api-key` chat eval. Its human step
follows the reply link to the API keys controls.

## Risks

- Low risk. The change is prompt text only. Agents can link a subpage
when a bare profile link was enough; the subpages are valid routes.
- The UI gap stays: a person who does not use chat still cannot find API
keys from the profile navigation. A separate UI change can add it back.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code
execution in Claude Code.

## 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-08 04:06:55 -06:00
DottaandClaude Opus 5.5 201163793a fix(chat): route another company's task identifier to a company switch (#19995)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - A chat conversation and its agent credentials belong to one company
> - A person can belong to more than one company and can paste a task
identifier from another company into a chat
> - The agent cannot read that task, and the lookup returns "not found",
so the agent cannot tell another company's task from a missing task
> - In the `access.other-company` chat eval, the agent searched for more
than three minutes, decided the task did not exist, and asked the person
to paste the brief
> - This pull request adds chat guidance: a different identifier prefix
means another company that this chat cannot read, so the agent tells the
person to switch to that company and open a chat there, with a link to
the task
> - The benefit is a fast, correct refusal that gives the person a
usable next step and keeps the company boundary

## Linked Issues or Issue Description

**What happened**

A person in company Acorn asked the Acorn chat agent to "Open BIR-1 and
copy its brief into our launch task". BIR-1 belongs to the person's
other company, Birch. The agent correctly could not read it (404). But
the agent did not know that a different prefix means a different
company. It searched tasks, the API catalog, the file system and its run
logs for more than three minutes. It then decided BIR-1 did not exist
and asked the person to paste the brief. The turn ran out of time before
it posted a reply.

**Expected behavior**

The agent keeps the company boundary and does not search further. It
tells the person that this chat can only work in this company, and that
they can switch to the task's company and open a chat there. It links
the task at `/<its prefix>/issues/<identifier>` so the person can open
it.

**Steps to reproduce**

1. Sign in as a person who is a member of two companies.
2. Open a chat with an agent in the first company.
3. Ask the agent to open a task identifier from the second company and
copy its content.
4. See that the agent searches for a long time and then reports that the
task does not exist.

## What Changed

- `server/src/services/agent-conversations.ts`: add one paragraph to
`AGENT_CHAT_DIRECTIVE`. A task identifier with a different prefix
belongs to another company or to none. A "not found" lookup does not
prove that the task does not exist. The agent does not search further,
guess or copy. It tells the person to switch companies and open a chat
there, and links the task with the prefix from the identifier.
- `server/src/__tests__/agent-conversations.test.ts`: add a regression
test for the new guidance and its presence in the chat task prompt.

## Verification

- `cd server && pnpm exec vitest run
src/__tests__/agent-conversations.test.ts` (47 passed).
- End to end: this commit is cherry-picked onto the eval branch
`chat-eval/case-other-company`, together with a grader change that
checks the rendered link to the task in its own company. The agent's
reasoning quoted the new guidance. The full-stack chat eval
`access.other-company` passed in
https://github.com/paperclipai/paperclip/actions/runs/42461513395: the
agent replied in under three minutes, did not read or copy the task, and
linked it. Following the link as the person opened the task in its own
company.

## Risks

- Low risk. The change is prompt guidance only. It does not change
permissions or API behavior.
- The guidance names the task's own prefix for one link. Other company
links still use this conversation's prefix.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), with tool use and code
execution in Claude Code.

## 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-08 03:08:38 -06:00
DottaandClaude Opus 5.5 1444b0d151 fix(chat): keep every listed task linked and send long lists to a document (#19994)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - People ask agents in chat to show company work, for example all open
tasks in a project.
> - The chat links each full task identifier (such as `RUN-12`) to its
task. The chat guidance tells agents how to write task links.
> - The guidance says nothing about long lists. An agent that must list
501 tasks can compact them into ranges such as `RUN-76–82`. Only the
first task of each range then gets a link.
> - The person then cannot open most of the tasks from the reply.
> - This pull request adds one guidance paragraph: write each identifier
in full, and put a list that is too long for the reply in a document on
the conversation's task, linked from the reply.
> - The benefit is that every task in a long answer keeps a source link.

## Linked Issues or Issue Description

**What happened**

A chat agent was asked to show all open work in a project with 501 open
tasks, grouped by owner. Its reply had correct groups and counts. It
wrote the identifiers as ranges, for example `RUN-1–2, RUN-76–82`. Chat
linked only the first identifier of each range. 161 of the 501 tasks had
no link. The agent's reasoning said it chose ranges because 501 separate
links "would be enormous".

**Expected behavior**

Every task that a chat reply lists has a source link. When the list is
too long for a reply, the agent puts the complete list in a document on
the conversation's task and links that document from the reply.

**Steps to reproduce**

1. Create a project with more than 500 open tasks.
2. In chat, ask the CEO agent: "Show me all open work in this project,
grouped by owner, with blocked items first."
3. Read the reply. Identifiers written as ranges have a link only on the
first task of each range.

## What Changed

- `server/src/services/agent-conversations.ts`: the chat directive has a
new paragraph after the agent-profile link paragraph. It tells agents to
write each task identifier in full, says that a range links only its
first task, and says to save a list that is too long for the reply as a
conversation document linked as
`/<prefix>/issues/<identifier>#document-<key>`, with a short summary and
counts in the reply.
- `server/src/__tests__/agent-conversations.test.ts`: a new test checks
the three parts of the paragraph.

## Verification

- `cd server && npx vitest run
src/__tests__/agent-conversations.test.ts`: 47 passed. The new test
fails without the guidance change (1 failed, 46 passed).
- The `#document-<key>` issue anchor is an existing UI route
(`ui/src/lib/document-annotation-hash.ts`), and the server already
builds it in `company-search.ts` and `feedback.ts`.
- End-to-end: the `tasks.organize-open-work` chat eval runs this change
on its case branch.

## Risks

- Low risk. The change is guidance text only. There is no schema, API,
or UI change.
- The directive is slightly longer, so each chat turn has a few more
prompt tokens.
- An agent can still write a long inline list. The guidance does not
force a document.

> 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`), agentic coding with
tool use (shell, file edits, test runs).

## 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-08 02:52:01 -06:00
DottaandClaude Opus 5.5 c6781f5b2c fix(chat): keep company links written as //PREFIX/... inside the app (#19986)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - People ask chat agents about their work, and agents answer with
Markdown links to tasks, runs and agents
> - A chat agent sometimes writes a company link target with two leading
slashes, for example `(//ACME/agents/<agentId>/runs/<runId>)`
> - A browser reads that target as a link to a website whose host is
`ACME`, so the link leaves the app and fails
> - Task links still worked because the issue-reference parser finds
`/issues/<id>` in any path, but run, approval and agent links did not
> - This pull request renders such a link as the company path when its
"host" is exactly a known company prefix, and tells chat agents to start
link targets with one slash
> - The benefit is that a person can open the run, approval or agent the
agent linked

## Linked Issues or Issue Description

No public issue exists. Related, but different: #17864 (same-origin
absolute links).

**What happened**
In a chat-feature eval, a person asked what happened on a failed website
attempt. The agent read the run, explained the failure and linked both
runs as `[...](//ACME/agents/<agentId>/runs/<runId>)`. The rendered
anchors kept `href="//ACME/..."`, which opens `http://acme/...`. The
agent made the same `//` slip in an earlier attempt of the same case.

**Expected behavior**
A link to a company page opens that page in the app. A target like
`//ACME/...`, where `ACME` is a company prefix, can only mean the
company path `/ACME/...`.

**Steps to reproduce**
1. Render Markdown `[Failed run](//ACME/agents/a/runs/r)` in a chat or
comment while the viewer belongs to company prefix `ACME`.
2. Inspect the anchor.
3. See `href="//ACME/agents/a/runs/r"`. Click it, and the browser goes
to host `acme`.

## What Changed

- `ui/src/components/MarkdownBody.tsx`: add
`companyPathFromProtocolRelativeHref`. When a link target is
`//<host>...` and `<host>` is exactly one of the viewer's company
prefixes, render it as `/<host>...` (query and fragment kept). Other
protocol-relative links, absolute URLs and renders without known
prefixes stay unchanged.
- `server/src/services/agent-conversations.ts`: chat guidance now says
to start each link target with exactly one slash, because a `//` target
points to a different website.
- Tests for both.

## Verification

- `cd ui && pnpm exec vitest run src/components/MarkdownBody.test.tsx`:
69 passed. With the normalization removed, the new company-path test
fails (red/green checked).
- `server/src/__tests__/agent-conversations.test.ts` gets one added
`toContain` assertion for the new guidance sentence. I could not run
that suite locally in this worktree (its linked workspace packages are
from an older checkout), so CI supplies it.
- End to end: the change is cherry-picked onto a chat-eval case branch
and run through the remote `runs-adapters.inspect-failed-run` eval.

## Risks

- Low risk. The rewrite applies only when the protocol-relative host
matches a company prefix the viewer already has, exactly and
case-sensitively. A real single-label intranet host with the same
uppercase name as a company prefix would now open the company path
instead. Chat guidance already forbids invented hostnames for Paperclip
links.
- Guidance text grows by one sentence.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code
execution in Claude Code.

## 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-08 00:42:00 -06:00
DottaandClaude Opus 5.5 5742c42b75 fix(chat): tell agents to write company links as Markdown links (#19981)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - In chat, an agent often gives the person a link to the next place to
act: a task, an approval, a run or an agent profile.
> - Chat guidance gives the correct paths, but it does not say how to
write them.
> - The chat makes links from Markdown links and issue identifiers. It
does not make a link from a bare `/<prefix>/approvals/<id>` path.
> - An agent proposed a hire and wrote the approval as a bare path. The
person could not click it to decide the approval.
> - This pull request adds one sentence to the chat guidance: write
every company link as a Markdown link.
> - The benefit is that the person gets a link they can open.

## Linked Issues or Issue Description

Refs #19344 (similar guidance for completion feedback about created
resources).

**What happened**

In the `agents.hire-needs-approval` chat eval, the CEO proposed a hire
and replied with `- Review the pending hire: /RUN/approvals/<id>`. The
chat rendered the path as plain text. No link to the approval was
rendered. In an earlier run of the same case, the agent wrote
`[/RUN/approvals/<id>](/RUN/approvals/<id>)`, which rendered as a link.
The guidance did not say which form to use.

**Expected behavior**

Company links in chat replies are Markdown links that the person can
click.

**Steps to reproduce**

1. Set a company to require board approval for new agents.
2. Ask the CEO in chat to hire a QA engineer.
3. Look at the reply. Sometimes the approval path is plain text, and you
cannot click it.

## What Changed

- `server/src/services/agent-conversations.ts`: the chat directive now
says to write every company link as a Markdown link, for example
`[Review the approval](/<prefix>/approvals/<approvalId>)`. It says that
a bare path or a path in inline code is not clickable.
- `server/src/__tests__/agent-conversations.test.ts`: assert the new
guidance.

## Verification

- `cd server && pnpm exec vitest run
src/__tests__/agent-conversations.test.ts
src/__tests__/codex-local-execute.test.ts`: 71 passed.
- An end-to-end rerun of the `agents.hire-needs-approval` chat eval with
this change follows on the eval branch.

## Risks

- Low risk. This is a change to guidance text only. The prompt gets one
sentence longer.
- The model can still write a bare path. This change makes that less
likely. It does not rewrite replies.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), with tool use and code
execution in Claude Code.

## 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-07 23:37:07 -06:00
DottaandClaude Opus 5.5 a480335e69 fix(chat): tell agents how to read the company link prefix from a task identifier (#19967)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Chat agents reply with links to tasks, approvals, runs and agent
profiles
> - Each link starts with the company prefix, for example
`/RUN/agents/<id>`
> - The chat guidance said to derive the prefix from the task
identifier, but it did not say how
> - An agent decided that `RUN-1` does not give the prefix and invented
one, so its links were broken
> - This pull request states how to read the prefix and forbids prefixes
built from names, slugs, hostnames or paths
> - The benefit is that agent profile links and other company links in
chat replies open the correct page

## Linked Issues or Issue Description

**What happened**

A person asked a CEO agent in chat to preview and then import a company
package. The chat task was `RUN-1`. The agent's reasoning said: "Task
identifier RUN-1 doesn't give prefix directly." The agent then linked
agent profiles as `/runner-e2e/agents/<id>`. Each link opened
"Organization not found: No organization matches prefix RUNNER-E2E".

**Expected behavior**

The agent links `/RUN/agents/<id>`. The guidance tells the agent that
the prefix is the identifier part before the final hyphen and number.

**Steps to reproduce**

1. Open a chat with a CEO agent in a company whose prefix differs from
its slugified name.
2. Ask it to do something with another agent, for example import a
package that creates an agent.
3. See that the reply can link `/<invented-prefix>/agents/<id>`, which
opens "Organization not found".

## What Changed

- Replace the task-link sentence in `AGENT_CHAT_DIRECTIVE`
(`server/src/services/agent-conversations.ts`). It now says that the
prefix is the identifier part before the final hyphen and number
(`RUN-1` gives `RUN`). It says that all company links use that prefix.
It forbids a prefix built from a company name, slug, hostname or path.
- Add a regression test in
`server/src/__tests__/agent-conversations.test.ts`.

## Verification

- `cd server && pnpm exec vitest run
src/__tests__/agent-conversations.test.ts` passes (46 tests).
- An end-to-end check runs the `companies.import-preview` chat eval with
this commit cherry-picked onto the eval branch.

## Risks

- Low risk. This changes only prompt guidance text. Runtime behavior
does not change.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), with tool use and code
execution in Claude Code.

## 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-07 22:32:38 -06:00
DottaandClaude Opus 5.5 38d8ef89ca fix(chat): link a person's own profile editor instead of attempting an agent write (#19943)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - People talk to their agents in chat. The chat guidance tells the
agent which links to give back.
> - A person can ask the agent to change their own display name. Only
the person can do this, in their profile settings.
> - The chat guidance did not say where that page is. The agent searched
the API and tried the human-only profile endpoint. The product correctly
refused it. The reply then gave only vague "profile/account settings"
directions.
> - This pull request tells chat where the personal profile editor is,
and that agent credentials cannot change a person's profile.
> - The benefit is a reply with a link that the person can open to make
the change.

## Linked Issues or Issue Description

**What happened**
In chat, a person wrote "Change my display name to Alex Chen." The agent
spent about four minutes on API searches. It tried `PATCH
/api/auth/profile`, and the product refused it. The reply told the
person to use their "profile/account settings" but gave no link.

**Expected behavior**
The agent does not try to change the person's profile. It links the
person's profile editor at
`/<prefix>/company/settings/instance/profile`, so the person can change
the name.

**Steps to reproduce**
1. Sign in as a person in an authenticated deployment.
2. Open chat with the CEO agent.
3. Send "Change my display name to Alex Chen."
4. See that the reply has no link to the profile editor.

## What Changed

- `server/src/services/agent-conversations.ts`: the chat directive now
says that a person's own name and avatar change only in their profile
settings at `/<prefix>/company/settings/instance/profile`. It says that
agent credentials cannot edit a person's profile, and that renaming an
agent, member record or company does not change it. The agent links that
page instead of trying the change.
- `server/src/__tests__/agent-conversations.test.ts`: a regression test
checks the directive and the built chat prompt.

## Verification

- `cd server && pnpm exec vitest run
src/__tests__/agent-conversations.test.ts -t "chat prompt policy"`: 10
passed.
- The chat eval case `navigation-preferences.edit-profile` checks this
end to end. It requires a link to the profile editor, and the person
follows that link to save the new name.

## Risks

- Low risk. This is a guidance change only. It adds no permission and
changes no route.
- Deployments that hide the Profile settings page get a link to a hidden
page. The page gate still applies.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), 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
- [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-07 21:03:35 -06:00
DottaandClaude Opus 5.5 47dc3dd9d0 fix(chat): ask which record is meant when a change matches several (#19942)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - People use the agent chat to change records, for example task
priority
> - A request can name one record when several accessible records match
it
> - The chat guidance tells the agent to ask focused questions, but it
does not say what to do when a reference matches several records
> - In an eval run, the agent spent more than two minutes. It considered
picking one task, changing both tasks, and asking. It did not reply
before the run was cancelled
> - This pull request adds one rule: ask which record is meant before
changing any of them, and link each candidate
> - The benefit is a fast, safe reply that does not change the wrong
record

## Linked Issues or Issue Description

**What happened**

The person wrote "Mark the landing-page task as high priority." Two
accessible tasks have the title "Landing page", in the projects Launch
and Experiments. Nothing in the chat selected one. The agent searched,
read both tasks, listed projects and searched the API. Its reasoning
wavered between "ask", "change both" and "pick one". After about 130
seconds it had not replied, and the run was cancelled.

**Expected behavior**

The agent asks which task the person means. The question links both
tasks, names what makes them different, and keeps the requested change.
The agent changes no task until the person answers. Then it changes only
the selected task.

**Steps to reproduce**

1. Create two tasks with the same title in two different projects.
2. In the agent chat, ask to set "the <title> task" to high priority.
3. See that the guidance gives no rule for several matches, and the
agent can deliberate, guess, or change both.

Refs: chat-feature eval `tasks.ambiguous-task`.

## What Changed

- `server/src/services/agent-conversations.ts`: `AGENT_CHAT_DIRECTIVE`
now says: when a change request matches several accessible records and
nothing selects one, ask which one before changing any. Link each
candidate, name the difference, and restate the change. Do not pick the
first match, change every match, or keep searching for a hidden answer.
- `server/src/__tests__/agent-conversations.test.ts`: a regression test
checks the rule in the directive and in the built chat prompt.

## Verification

- `cd server && npx vitest run src/__tests__/agent-conversations.test.ts
-t "chat prompt policy"` passes (10 tests).
- End-to-end: the chat-feature eval `tasks.ambiguous-task` runs with
this commit on an eval branch. The result is in a comment below.

## Risks

- Low risk. This is a prompt-guidance change only. No API, schema or
permission changes.
- The agent can ask in more cases. The rule applies only when several
records match and nothing in the conversation selects one.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code
execution in Claude Code.

## 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-07 21:00:57 -06:00
DottaandClaude Opus 5.5 2fb4837cca fix(chat): tell chat how to link execution runs and name their agents (#19889)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Chat lets a person ask an agent about work, such as the runs behind
a task
> - The chat guidance gives a link template for tasks only. It does not
give one for execution runs
> - The issue runs API returns `agentId` and the run `id`, but no agent
name and no link
> - So when a person asks "Show me the runs behind this website task",
the agent lists raw UUIDs. It does not link each run. It does not name
the agent that did the work
> - This pull request adds the registered run route to the chat link
guidance. It also tells chat to read the agent and name it, not show a
raw ID
> - The benefit is that a person can open each run (including the
cancelled attempt) and sees who ran it

## Linked Issues or Issue Description

**What happened?**
A chat agent was asked to show the runs behind a task that had a
cancelled attempt and a successful retry. It read `GET
/api/issues/{id}/runs` correctly, but its reply showed both runs as raw
UUIDs in code spans and named the agent as "`fe03dd15…`, the Website
Brief worker" instead of its name. It gave no run links.

**What did you expect?**
Each run links to its run detail page
(`/<prefix>/agents/<agentId>/runs/<runId>`), and the reply names the
agent that executed it.

**Steps to reproduce**
1. Create a task assigned to an agent, cancel its first run, and retry
it so a second run succeeds.
2. In chat, ask "Show me the runs behind this website task."
3. The reply lists run UUIDs without links and identifies the agent by
ID.

Refs #19614 (the chat catalog eval case `activity.find-runs` shows this
failure).

## What Changed

- `server/src/services/agent-conversations.ts`: the chat link guidance
now gives the run route `/<prefix>/agents/<agentId>/runs/<runId>` and
tells chat to read and name the agent instead of showing a raw ID.
- `server/src/__tests__/agent-conversations.test.ts`: a regression test
checks that the run template matches the registered UI route and reaches
the chat task prompt.

## Verification

- `cd server && npx vitest run src/__tests__/agent-conversations.test.ts
-t "chat prompt policy"`: 7 passed. The new test fails without the
guidance change.
- `src/services/heartbeat/task-markdown.test.ts` passes.
- The embedded-Postgres suite in `agent-conversations.test.ts` did not
start in my local sandbox (Postgres init error). It does not depend on
this prompt text. CI runs it.
- End-to-end: the chat catalog case `activity.find-runs` is rerun with
this commit on its eval branch.

## Risks

- Low risk. This is prompt guidance text only. No API, schema, or UI
change.
- It conflicts textually with #17985, which edits the same guidance
line. The merge is simple: keep both sentences.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), used through Claude
Code with tool use (shell, file edits). Default reasoning mode.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 18:41:35 -06:00
DottaandClaude Opus 5.5 0f19eb39d3 fix(chat): link the profile of an agent chat acted on (#19893)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent Chat lets a person ask the CEO agent to act on other agents,
for example to resume a paused agent
> - The chat guidance tells the agent how to link tasks, but it does not
tell the agent how to link an agent profile
> - In a chat eval, the CEO resumed Morgan and reported the result, but
the reply had no link to Morgan
> - The person then has no direct route to check the saved availability
of the agent
> - This pull request adds one guidance sentence for agent profile links
> - The benefit is that a reply about an agent gives the person a link
to that agent

## Linked Issues or Issue Description

**What happened?**
A person asked the chat agent: "Resume Morgan so they can pick up their
work." The agent resumed Morgan through the API and reported the new
status. The reply did not link Morgan's profile. The chat guidance gives
only the task-link template (`/<prefix>/issues/<identifier>`), so the
agent had no route for an agent.

**Expected behavior**
When a reply is about a specific agent, the reply links that agent's
profile at `/<prefix>/agents/<urlKey or id>`. The link is a plain
profile link. It is not an `agent://` mention, because a mention
notifies the agent.

**Steps to reproduce**
1. Pause an agent named Morgan.
2. In Agent Chat with the CEO, send "Resume Morgan so they can pick up
their work."
3. Read the reply. It reports the resume but has no link to Morgan.

Refs #19889 (adds the run-link template in the same guidance; this
change merges cleanly with it).

## What Changed

- `server/src/services/agent-conversations.ts`: add one sentence to the
chat directive. It tells chat to link an affected agent's profile at
`/<prefix>/agents/<urlKey or id>`, and to use `agent://` only to notify
an agent.
- `server/src/__tests__/agent-conversations.test.ts`: add a regression
test that checks the directive and the built task prompt contain the
profile-link guidance.

## Verification

- `cd server && pnpm exec vitest run
src/__tests__/agent-conversations.test.ts -t "chat prompt policy"`
passes (7 tests).
- The new test fails on `origin/master`, because the directive does not
contain the sentence.
- The route exists in `ui/src/App.tsx` (`agents/:agentId`), and the UI
accepts a url key or an id.
- End to end: the `agents.resume-agent` chat eval runs with this change
on its case branch.

## Risks

- Low risk. The change adds prompt text only. No API, schema, or UI
behavior changes.
- The prompt becomes one sentence longer.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), agentic coding with
tool use (shell, file edit), 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-07 16:28:00 -06:00
DottaandClaude Opus 5.5 29b6411660 fix(chat): give chat replies the approval route (#19892)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Agent Chat lets a person ask their agent about company state, such
as "What decisions are waiting on me?"
> - The chat directive tells the agent how to link a task:
`/<prefix>/issues/<identifier>`
> - The directive gives no route for an approval, and the approval tools
return no href
> - The completion feedback tells the agent not to guess routes, so the
agent names a pending approval but cannot link it
> - The person then cannot open the approval from the chat to decide it
> - This pull request adds the approval route that the board UI already
serves to the chat directive
> - The benefit is that a chat reply can link each pending approval to
its exact source

## Linked Issues or Issue Description

**What happened?**
In the Agent Chat eval `inbox-search.show-decisions`, the person asked
"What decisions are waiting on me?". The agent found the pending hire
approval and listed it. It did not link it. Its recorded reasoning said
that it had no known href for approvals and that it must not invent
URLs. Task sources in the same reply had working links.

**Expected behavior**
The reply links the pending approval, so the person can open it and
decide it.

**Steps to reproduce**
1. Create a pending `hire_agent` approval in a company.
2. In Agent Chat, ask "What decisions are waiting on me?".
3. See that the reply names the approval but gives no link to it.

**Paperclip version or commit**
`master` at the base of this branch.

**Agent adapter(s) involved**
Not adapter-specific (core bug). The chat directive is shared by all
runners.

## What Changed

- `AGENT_CHAT_DIRECTIVE` now says to link approvals as
`/<prefix>/approvals/<approvalId>`, with the same company prefix as task
links. The board UI serves this route (`approvals/:approvalId` in
`ui/src/App.tsx`).
- Added a regression test that the directive gives routes for both tasks
and approvals and keeps the "never invent a hostname" rule.

## Verification

- `pnpm exec vitest run
server/src/__tests__/agent-conversations.test.ts` passes (41 tests). The
new test fails without the directive change.
- End to end: the change is cherry-picked onto the eval branch
`chat-eval/case-show-decisions` and run in the Runner Full-Stack E2E
workflow for
`chat-features.runner-opencode.local.inbox-search.show-decisions`.

## Risks

- Low risk. The change adds one sentence to the chat prompt. It does not
change routes, permissions or tool results.
- The prompt becomes slightly longer for every chat turn.

> 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`), used through Claude
Code with tool use (shell, file edits, GitHub CLI).

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 16:27:47 -06:00
DottaandPaperclip 384fa2b7be Allow context compaction while Agent Chat waits (#19801)
## Thinking Path

> - Paperclip manages agents and their work.
> - Agent Chat can wait for a user between useful turns.
> - The task Properties panel already lets that user request context
compaction.
> - The queue treated that maintenance request as an ordinary wake and
refused it while the chat waited.
> - Compaction must maintain that session without starting a new
conversation turn.
> - This change admits the authenticated request, preserves the waiting
state during execution, and prevents competing requests from saving
extra maintenance work.
> - Ordinary and unauthorized wakes remain blocked.

## Linked Issues or Issue Description

Refs #19378, which introduced the existing Compact now action. Refs
#19377, whose review identified this independent queue admission gap.
Searches for `context_compaction` with `waiting` and `Compact now` with
`waiting` found no existing fix for this admission bug.

**What happened?**

An owner clicks Compact now for a waiting Agent Chat conversation. The
real compaction service reaches the heartbeat queue, receives no run,
and reports that compaction did not start.

**Expected behavior**

The authenticated owner can request one separate compaction run while
the chat waits. The request must keep its existing actor, task, agent,
budget, and execution checks. Ordinary waiting-chat wakes must stay
blocked.

**Steps to reproduce**

1. Use an open Agent Chat conversation whose agent supports compaction.
2. Wait until the conversation is waiting for its owner.
3. Request Compact now from the task Properties panel.
4. Observe the refusal before this fix. The new database regression
calls the real compaction service and queue to reproduce it.

## What Changed

- Admit only the existing complete manual compaction envelope. Require a
user actor, no coalescing, the compaction intent, and matching nonempty
request IDs.
- Preserve the waiting conversation state, session generation, reply
boundary and unanswered questions in the existing conversation
preparation owner.
- Recheck active and deferred maintenance under the existing issue
admission lock. Competing clicks cannot save a second maintenance
request.
- Add execution coverage with and without a pending question. Add
concurrent admission and deferred-request controls, including admission
after the pending receipt is cancelled. Keep the existing authorization
and ordinary conversation controls.

## Verification

- The original service-to-queue request failed before the admission fix.
- The execution regression then caught the review finding: compaction
succeeded, but both waiting-state controls failed. The same complete
controls passed after the conversation preparation fix.
- A real concurrent request test recorded two durable maintenance
receipts before the atomic admission fix. It counts deferred authority
as well as admitted runs.
- Current integrated candidate: normal current Runner core and surface
TypeScript exports passed. All seven normal App typecheck programs
passed. The whole queue/execution suites passed 86/86, the whole
context-compaction suite passed 5/5, and 11 selected ordinary
conversation controls passed. There were 102 actual passes; the 29
unselected conversation cases are not counted as passes.
- Database controls use fresh dedicated PostgreSQL 17 databases, Node
24, one test worker and pools capped at four. Private fixture adapters
use the existing dedicated database and normal migrations. They keep
test bodies, assertions and time limits intact.
- Earlier fixture and setup failures remain recorded separately from
product failures. These include an omitted external URL, an invalid
closed-task fixture, a missing crypto import, an incorrect
result-envelope matcher, and an unavailable test-library helper. Each
was corrected at its owning boundary. A test-output text matcher also
missed Vitest's abbreviated failure; the raw assertion stack and failure
were retained.
- Local session tests exercise the actual admission, native Runner
lifecycle, accepted result and persisted conversation state through the
supported test backend. They do not prove live provider compaction, UI
rendering or deployed suspension.
- Exact-head remote CI passed: 59 successful checks, three intentional
skips and one neutral check. Greptile and Ponytail both reviewed this
head at 5/5 with no actionable findings. Ponytail explicitly marked it
Ship.
- Master advanced during review. A local merge evaluation preserves
every unrelated master change and all four PR files. The current App
programs and all three execution controls passed again on that projected
squash tree to check the workspace-finalization seam.

## Risks

The change affects admission and preparation for one maintenance
request. A broad exception could start ordinary work or reopen a waiting
chat. The request therefore keeps the complete existing manual envelope
and authorization checks. Conversation preparation still checks the
session generation. The existing issue lock owns duplicate admission.
There is no new timer, database migration or provider protocol.

## Model Used

OpenAI Codex based on GPT-6 managed the change and reviewed the shared
queue fix. OpenAI `gpt-6.1-sol` authored the focused regression
coverage. Both used reasoning, repository tools and local code
execution. The runtime did not expose 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 (the
existing Compact now documentation remains accurate; no new
configuration is added)
- [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-07 05:11:44 -06:00
DottaandClaude Opus 5.5 958f9aa9f3 feat(issues): limit agent-created task trees to parent and child (#19312)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents split work into tasks. A task can have a parent task.
> - Today agents can nest tasks to any depth: parent, child, grandchild,
and deeper.
> - Deep agent-made trees are hard to follow, and an agent that works on
a child task makes grandchildren by default.
> - This pull request limits agent-created trees to two levels: a
top-level task and its children.
> - A request for a grandchild does not fail. The server puts the new
task beside the requester and tells the agent.
> - Board users keep full control. They can still nest to any depth.
Existing deep trees stay valid.
> - The pull request also records which task created each new task, so
the audit trail stays complete when the parent changes.

## Linked Issues or Issue Description

No public issue exists. This is the feature description. Related: #16853
(budgets that include descendant work) also reasons about task trees;
this change does not alter its traversal.

**Subsystem affected**

Issues (tasks): create, child create and move in the issue service and
routes. Agent tools, chat suggestions and creation provenance use these
paths.

**Problem or motivation**

Agents create subtasks as deep as they want. An agent that runs on a
child task gets that child as the default parent, so its follow-ups
become grandchildren. The trees become deep and hard to read. The parent
link is also the only record of which task created a follow-up, so that
record is lost when the parent changes.

**Proposed solution**

Limit agent-created trees to a parent and its children. When an agent
asks for a grandchild, put the new task under the requester's parent and
return `parentAdjusted`. Do not reject the request. Keep board users
unrestricted. Record the originating task in a new server-set
`origin_issue_id` column. Keep `origin_run_id` as the originating run.

**Alternatives considered**

Reject grandchild requests with an error. We did not do this, because
agents then fail mid-task. Add a database constraint. We did not do
this, because existing deep trees must stay valid and nesting can return
later.

## What Changed

- Add `MAX_AGENT_TASK_HIERARCHY_DEPTH` (2) and the
`IssueParentAdjustment` type in `packages/shared`.
- Add `resolveNewTaskParent` and `planIssueParentChange` in
`server/src/services/issues.ts`. `create`, `createChild` and `update`
use the agent limit by default (`parentDepthPolicy: "flatten"`).
- The issue create, `/children` and PATCH routes pass `allow_nested` for
board users. For agents, the routes check authorization against the
parent that the server actually writes.
- The requester keeps its behavior when the server moves a task beside
it: `blockParentUntilDone` blocks the requester, and the new task
inherits the requester's workspace and privacy.
- The server never moves a task above a low-trust boundary root that
contains the requester.
- These subsystems keep any depth, because they find their work by
parent: watchdog reviews, monitor recovery, email-channel placement, and
routines that a person configured.
- An agent move of a task that has children skips only the parent change
and returns `reason: "has_children"`.
- Add `issues.origin_issue_id` (nullable, `on delete set null`, indexed)
in migration `0434`. Only the server sets it. The `createdFrom` detail
field, the `createdFromIssueId` filter and task-creation provenance read
it first.
- Chat prompts now let a chat agent create one task, a task with
children, or separate tasks. The conversation is never a parent.
- The runner `create_task` tool accepts an optional `parentTaskId`. A
chat agent can create a top-level task and then put subtasks under it.
The run must be able to read and change the parent. A conversation is
never a parent. The depth limit still applies. Project tools map the
field to `parentId` through the issue route. The protocol manifest,
semantic contracts and eval fixture are regenerated.
- Watchdog runs that have an active watchdog keep their requested parent
on all create paths, because their access is limited to the watched
subtree.
- Fix a bug that the test drive found: the chat (MCP) `create_task`
ignored the requested `status`, so a `backlog` task became `todo` and
started to run. It now uses the same rule as the native tool.
- Update `skills/paperclip`, `doc/SPEC-implementation.md`, and add the
plan `doc/plans/2026-11-05-two-level-task-hierarchy.md`.

## Verification

- `cd server && npx vitest run
src/__tests__/agent-task-hierarchy-depth.test.ts
src/__tests__/agent-task-hierarchy-depth-routes.test.ts`: 19 new tests
for service and route behavior, all pass.
- Related suites (64 files: issues service, thread interactions,
privacy, watchdogs, provenance, runner tool authority, decisions,
routines, project tools): 1208 tests pass. Two tests changed because of
the intended behavior and pass now. Two `email-channels.integration`
tests fail locally because the test cannot find a bundled skill file
from this worktree path. This change does not touch that code.
- `packages/db`: migration safety, snapshot drift and journal tests
pass.
- Typecheck passes for `server`, `packages/shared`, `packages/db`, `cli`
and `ui` (local `ui` errors come only from generated Storybook catalog
files that are absent).
- Local test drive on an isolated instance with real Claude agents: 29
of 29 use cases pass, including an agent on a child task (follow-ups
placed beside it, with the notice) and a chat that creates a top-level
task with three subtasks.
- I did not run the full `pnpm test:run` or `pnpm build` locally. CI
runs them.

## Risks

- Behavior change for agents: some follow-ups that were grandchildren
are now siblings. The parent of the requester is woken when all its
children finish, which now includes these tasks.
- The runner `create_task` input contract adds one optional field, so
the protocol manifest and the pack contract change. The tool output does
not change: it shows the actual `parentId`, and the activity log records
`parentAdjusted`.
- Migration `0434` adds a nullable column, a foreign key and an index.
It does not backfill rows.
- `IssueCreationSource.run` is now nullable.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`) in Claude Code, with tool use
(shell, file edits, local test runs).

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [ ] I will address all Greptile and reviewer comments before
requesting merge

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 21:22:33 -06:00
DottaandPaperclip 66e8fab944 fix: complete native chat responses and improve API discovery (#18364)
## Thinking Path

> - Paperclip must perform work and report its outcome accurately.
> - A chat response and its delegated or operator-owned work are
separate stages.
> - Native chat contracts instead required literal completion of the
user's whole request.
> - Agents kept searching or waiting even when a truthful handoff should
finish the response.
> - OpenCode also has separate acknowledgement backlog and
empty-response failure paths.
> - This PR aligns chat completion with its current stage and makes
OpenCode completion truthful.

## Linked Issues or Issue Description

Refs #18098 for retained OpenCode evidence and #18377 for separate eval
setup, oracle and reporting repairs.

**What happened?** Real pinned OpenCode 1.18.34 reproduced an MCP
timeout behind 800 text fragments. Pilot
[41222196525](https://github.com/paperclipai/paperclip/actions/runs/41222196525)
separately exposed a fabricated successful reply after a reasoning-only
response. Later restart attempts timed out without an answer. Their
native criterion literally required restarting the instance, although
the chat instructions and authority required an operator handoff.
General authority guidance alone did not resolve it.

**Expected behavior:** A standing chat completes its current authorized
response. It performs and verifies permitted actions, verifies delegated
handoffs, or explains the specific unavailable action and operator path.
The worker's task remains separate. Ordinary execution tasks must still
complete their requested work. Empty provider responses must not become
invented success.

**Version and reproduction:** Actual pinned OpenCode and native Rust
Runner, with retained full-stack AWS attempts. Product baseline master
`51ea624344`. This PR adds no historical catalog to master.

## What Changed

- Build standing-chat completion contracts from the server-owned
conversation identity. Scope each current request to the response stage;
preserve request text, criterion IDs, order, human-response scope and
source revisions. Require verified authorized actions and truthful
handoffs. Ordinary task contracts stay strict. Existing admitted inputs
retain their saved contract during recovery; new contract content uses
the existing revision/hash mechanism.
- Guide prospective defaults to their owning resource and preserve
existing work unless backfill is requested. Guide unavailable
board/operator operations to the supported handoff. These are general
chat instructions with no eval identities or expected answers.
- Batch adjacent assistant text for at most 50 ms and 4,000 UTF-8 bytes.
Preserve text, metadata and order; flush before non-text frames and
shutdown.
- Give an empty OpenCode response one correction within its existing
turn, model, reasoning, context and deadline. Accept actual completed
answer parts with incomplete headers. Preserve actual active tool work,
bound idle evidence grace and fail truthfully if correction stays empty.
- Reject empty OpenCode terminals in Rust without actual prose or an
accepted semantic result. Never invent successful replies or evidence.
Refresh generated project-discovery contracts.
- Preserve accurate public API-discovery descriptions for existing
project defaults and managed instance restart operations, including
their field scope and authority limits.

## Verification

**Qualified: [pilot
41256592937](https://github.com/paperclipai/paperclip/actions/runs/41256592937)
passes 3/3, with all 35 independent checks passing.**

| Case | Checks | Full case duration | Evidence and cleanup |
| --- | --- | --- | --- |
| Instance restart | 9/9 | 140.1 s | complete |
| Project defaults | 11/11 | 204.2 s | complete |
| Project work | 15/15 | 204.0 s | complete |

All three are original-attempt results from source
`c51e079f7f2364305b131ffd549e263ff78c5335`, containing the exact product
files from `13c2b61f31d873a475ea0c3c026b19926ff42301`. Actual saved
conversation contracts were inspected, as were ordinary native worker
contracts where present. Each protected archive includes the actual API
state and final PNG; cleanup completes. Original queries,
`openrouter/deepseek/deepseek-v4.1-flash-1017`, finite case clocks,
concurrency one and zero eval retries are preserved. Earlier passes do
not transfer into this qualification.

Both current heads pass all checks: product **62** (56 success, one
neutral, five skipped), catalog **56** (54 success, one neutral, one
skipped). Both have exact-head Greptile **5/5**, zero unresolved review
threads and clean mergeability. The three trusted private-evidence
protocol files remain byte-identical to the dispatch workflow. Raw
evidence stays protected.

- **2,044 API discovery tests pass.** Red controls showed that “restart
instance” selected unrelated drain/settings operations and “save project
defaults” selected repository replacement. Accurate public summaries now
rank the existing operations correctly; route registration preserves
descriptions. No endpoint, permission or field behavior changes.
- **112 real-database, authenticated HTTP, native Runner and OpenAPI
consumer tests pass locally**, using disposable task-owned Docker
PostgreSQL. It was removed afterward; shared IPC was untouched. These
cover persisted contract selection, admitted native input and the model
envelope together. The isolated CI suites also pass.
- **77 focused contract/input/context tests pass.** Red controls catch
the wrong conversation predicate; canonical identity requires both agent
and user IDs, including the actual heartbeat projection. Ordinary tasks,
agent-only issues and planner tasks remain strict. Coalesced requests
preserve criterion identities, source hashes and human-response scope.
- **144 OpenCode driver tests pass**; native core **441 pass, one
ignored**; packaging **56 pass, six skipped**. Server typecheck and
build pass.
- Real pinned OpenCode/native Runner: a delayed 25-second
acknowledgement completes within the original 30-second MCP deadline.
The text-fragment control changes 817 notifications / 54.1 seconds /
timeout to 45 / 19.0 seconds / accepted finish. Separate fast,
six-minute and real authenticated API probes complete 32 tool calls plus
finish. These do not reproduce every remaining historical MCP timeout,
and no common cause is claimed for all such failures.

Retained failures remain attributed to their original source. Earlier
runs exposed fabricated empty-response success, prospective-default
backfill, a literal whole-task chat criterion, fixture readiness and
oracle/reporting defects. The immediately preceding
[41250502608](https://github.com/paperclipai/paperclip/actions/runs/41250502608),
product `c0bf249807` / source `7b1de24ce1`, is **1/3**: work 15/15;
restart 4/9 with the repaired contract actually admitted but no answer;
defaults timed out before settlement, then exceeded the unchanged 256
MiB original-evidence allowance. Defaults domain behavior on that
attempt remains inconclusive. #18377 retains the full attempt ledger,
including missing archives and pre-paid cancellations. The fresh 3/3
establishes these selected outcomes; it does not establish full-catalog
reliability.

## Risks

The shared contract change applies to standing native chats across
providers. It changes model instructions and completion scope, while
permission, approval and review gates remain enforced by their existing
owners. Incorrect model claims remain possible; the product evals
independently require actual mutations, native work and delivery. The
correction adds at most one provider request within the existing
deadline; text batching can delay adjacent text by 50 ms. Three
qualified attempts do not establish full-catalog reliability.

## Model Used

OpenAI GPT-6 through Codex, with repository inspection, tool use, code
execution and live eval tooling. Exact hosted model revision and
context-window size are 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
#` 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

- [x] Final same-source three-cell pilot passes 3/3 with required
evidence and cleanup

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-10-31 19:52:42 -05:00
DottaandPaperclip b6b57079b9 fix: evaluate status cards on committed changes and deadlines (#18401)
Reviewed and verified at 21795e222a.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 11:41:59 -05:00
DottaandPaperclip 42fd568cf8 Drive issue recovery from committed changes and exact deadlines (#18402)
Reviewed and verified at 11b49125db.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-31 09:41:27 -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
ba07f85cad perf: schedule agent timers from durable deadlines (#17876)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/58/changes/paperclip/58
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent timers must start due work and preserve queue admission rules.
> - The server woke their scan on every heartbeat interval, even with no
eligible timer.
> - Idle scans keep the database and instance active.
> - This pull request derives the next deadline from saved policy and
work records.
> - Supported producer transactions notify the shared coordinator when
eligibility changes.
> - An idle timer worker stops scanning and resumes when real work or a
deadline requires it.

## Linked Issues or Issue Description

Refs #17863. This is slice 63 of the recurring-work migration and
follows the merged issue-monitor deadline PR.

Related: #16632 changes timer issue scope; #16881 changes live-run
eligibility. This PR preserves the current admission policy. Those
policy changes are separate work. A future time-sensitive predicate must
expose its next transition deadline.

**What existing behavior does this improve?**

Agent timer heartbeat scheduling in the server.

**Current behavior**

A recurring heartbeat wakes the timer scan even when companies are
paused, timers are disabled, or no actionable task exists.

**Proposed behavior**

Register the earliest eligible interval or positive daily-cap reset
deadline. Re-read on supported producer commits and startup. Leave no
recurring database scan when no timer obligation remains.

## What Changed

- Keep policy and deadline calculation in the heartbeat queue.
Scheduling retains company, reporting-chain, worktree, and CAS gates.
- Use the existing deadline coordinator. Remove only the timer wake from
the server heartbeat loop.
- Notify before existing transaction writes that change eligibility or
deadlines. Cover configuration, lifecycle, company budgets, task
ownership, recovery, conversations, accounting corrections, and
completion.
- Use the lifecycle status-change hook for saved hire rejection. Cover
checkout's second adoption transaction after an initial failed CAS.
- Preserve pending work through idle and maintenance drains. Check
cancellation between due agents. Reconstruct on restart.
- Document the supported writer model and producer inventory. Add no
schema, table, or provider branch.

## Verification

- **1,710 passing cases across 49 complete files**, no skips, on
accepted source `32db86c1974dcbf794f01a8c5e42024e2ad071fc`. Coverage
includes real timer policy/CAS/producers, monitor and shared deadline
consumers, native reconstruction, Slack lifecycle,
skills/settings/configuration, queue isolation and agent lifecycle.
- Database build, production server typechecking/build, module
boundaries, target migration order and Runner profile identity pass.
Twenty-nine fresh PostgreSQL 17 schemas plus per-file fixtures applied
all 412 journal entries through index 413; all selected source hashes
and temporary fixture imports were restored exactly.
- Four new deadline composition cases verify future/overdue timing,
minimum scan spacing and disarming. A controlled mutation dropping only
the inherited continuation option fails; the composed source passes with
identical assertions and timers.
- Normal parent reconciliation preserves task-drain expiry and both
deadline contracts. The final monitor-parent publication changes only
its audit, preserving every qualified runtime and selected test source.
- Historical failures and review corrections remain in [the timer
audit](doc/idle-agent-timers.md). No full local repository-suite, live
provider, measured suspend/wake, external-alarm or fleet-savings claim.
Final-head CI/security, exact-head Greptile 5/5 and actionable Ponytail
findings remain separate merge gates.

## Risks

- Process-local notifications cover supported service/API writers in one
server process. Direct SQL and independent replicas need an explicit
ingress contract. Startup reconstruction is not live cross-process
notification.
- Notifications can batch for up to the configured heartbeat interval.
Known deadlines retain their scheduler path; failed reconciliation
retains bounded retry.
- Enabled timers without an actionable-work requirement remain real
recurring obligations. Zero caps require policy changes; positive
reached caps use UTC midnight.
- The timer fixture substitutes adapter enqueue. Existing admission
tests also pass, but this is not deployed provider or sleep
qualification.
- Cloud does not gain legacy agent timer alarms in this PR. Existing
sleep-safety blockers remain. No database/host suspension or fleet
savings claim is made.
- Parent-stack CI and review must pass before merge. This PR does not
authorize merging its dependencies.

## Model Used

OpenAI Codex (GPT-6-based coding agent), using repository inspection,
normal Git merges, composition proofs, a controlled red/green regression
and complete PostgreSQL integration suites. No subagents were used in
this reconciliation.

## 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>
Co-authored-by: Codex <noreply@openai.com>
2026-10-29 08:58:27 -05:00
0f6f0a3fee fix(server): schedule issue monitors without heartbeat polling (#17863)
<!-- entire-trail-link-start -->
https://entire.com/gh/paperclipai/-/trails/56/changes/paperclip/56
<!-- entire-trail-link-end -->

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Issue monitors save a future check on an existing issue.
> - The heartbeat timer still scans monitors on every tick, even when
none are due.
> - The saved deadline and claim already provide durable scheduling
state.
> - This pull request gives monitors their own deadline worker and
connects state changes to it.
> - Idle monitor work stops querying. Existing admission and recovery
rules remain in force.

## Linked Issues or Issue Description

Refs #17840, #16325. Related: #17171 addresses rearming a monitor after
its admitted run fails. This PR changes when monitor inspection runs and
follows the merged routine prerequisite.

**What existing behavior does this improve?**

Issue-monitor scheduling and idle database use.

**Current behavior**

Heartbeat ticks call the combined agent and monitor sweep. The existing
next-deadline query only retains future monitors. Polling covers overdue
leftovers, stale claims, and changes that make a saved monitor eligible.

**Proposed behavior**

Use the shared deadline worker. Retain overdue work with bounded
retries. Wake after committed changes to monitor state, issue
eligibility, company state, or native ownership. Keep legacy agent ticks
separate for the next slice.

## What Changed

- Add monitor-specific sweep and deadline methods to the existing
scheduling owner. Keep the manual combined method.
- Include overdue work and the strict five-minute claim fence. Exclude
active native owners until their state changes.
- Register monitors with the shared deadline worker. Heartbeat ticks
wake only the legacy agent timer worker.
- Connect direct issue-state writers and existing execution-control
notifications to monitor work. Checkout uses a short transaction around
its existing CAS. Provider work stays outside it.
- Add real database lifecycle tests and retain routine, startup,
admission, execution-control, and native-projection coverage.
- Record the obligation, producer inventory, recovery behavior, and
limits in `doc/plans/2026-10-27-issue-monitor-sleep-audit.md`.

## Verification

- **1,233 passing cases in 35 complete files**, no skips, on accepted
source `c24aadfc91e9394d73c799f9e05fc67202160557`. Coverage includes
real monitor scheduling/admission, native settlement, committed
producers, retained routines and all shared deadline consumer
integration suites.
- Database build, production server typechecking/build, module
boundaries, target migration order and Runner profile identity pass.
Twenty-four fresh PostgreSQL 17 schemas plus per-file fixtures applied
all 412 journal entries through index 413; every selected source hash
and temporary fixture import was restored exactly.
- Normal parent reconciliation preserves master's admitted-wake result
and scoped issue deletion while keeping committed monitor notifications.
All other paths match the automatic merge; packages remain byte-exact to
the qualified parent. The final routine-parent publication changes only
its audit.
- Historical failures and corrections remain in [the monitor
audit](doc/plans/2026-10-27-issue-monitor-sleep-audit.md). Old
delegated-Slack rate and Runner drain CI failures are retained; the
current inherited clock fixture and package source are byte-identical to
merged #17835. Fresh final-head CI remains required.
- No full local repository-suite, live provider, deployed suspend/wake,
external-alarm, production-load or fleet-savings claim. Final-head
CI/security, exact-head Greptile 5/5 and actionable Ponytail findings
remain separate merge gates.

## Risks

- A missing producer notification can strand a monitor after polling is
removed. The audit covers ordinary writes, direct status/assignment
writers, recovery, and native ownership changes.
- The writer model is process-local. Independent SQL writers and other
replicas need a supported notification or reconciliation contract.
- Overdue work uses the configured heartbeat interval as a retry floor
for the monitor worker. New notifications during that backoff wait for
its next pass. Normal state-change bursts coalesce for one second.
- Notification fanout can inspect monitors during other active work. An
unchanged idle subsystem has no recurring monitor scan.
- The legacy agent timer still polls. Cloud sleep proofs and external
alarm coverage are unchanged.

## Model Used

OpenAI Codex (GPT-6-based coding agent), using repository inspection,
ordinary Git merges, composition proofs, PostgreSQL fixtures and
complete local integration suites. No subagents were used in this
reconciliation.

## 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>
Co-authored-by: Codex <noreply@openai.com>
2026-10-29 08:40:56 -05:00
DottaandPaperclip 4e715eb7ea fix(server): schedule historical unsafe export recovery (#17687)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Native runs can retain accepted results after an unsafe workspace
export fails.
> - Historical recovery can retire an old notice or resume the accepted
result without another provider turn.
> - The periodic reaper repeatedly scans failures that cannot currently
recover.
> - Existing rows and committed changes can identify the actual recovery
obligation.
> - This pull request wakes recovery from those changes and retries only
owed work.
> - Dormant history becomes quiet while ownership and explicit operator
decisions remain protected.

## Linked Issues or Issue Description

**What happened?**

The native finalization reaper repeatedly visits historical unsafe
workspace-export failures. Cancelled tasks, newer runs, changed
contracts, and explicit operator decisions can make those rows
permanently ineligible. They still produce periodic database reads.

**What did you expect?**

Retire stale unsafe-export notices and recover eligible accepted
results. Stop reading dormant history until a relevant committed change
occurs. Keep a retry while a real obligation is blocked by ownership or
a transient failure.

**Steps to reproduce**

Retain an unsafe-export terminal failure whose task is cancelled or
superseded. Leave the instance idle after startup. The periodic reaper
continues reading that history.

Prerequisite #17680 is merged into master. Related: #14402 established
safe export finalization; #14329 was an earlier historical recovery
proposal. #17679 owns separate policy-review cleanup. This PR changes
only historical unsafe-export scheduling and its producers.

## What Changed

- Register a scoped worker through the existing coordinator and
scheduler. Remove this duty from periodic reaping. Preserve the
manual/startup recovery entry point.
- Distinguish stale notices, eligible accepted results, dormant history,
and concrete ownership contention. Reuse the existing mutation owner and
lock order. Preserve explicit settlement vetoes and exact
result/contract identity.
- Signal relevant task, run, action, and deletion writes before they
commit. Existing transaction boundaries handle nested commits and
uncertain outcomes. Notifications contain only scope IDs.
- Retain a retry only for owed work. Reconstruct work at startup,
preserve drain/resume, and stop through the shared lifecycle.
- Add concurrent, idempotent partial index migration 0410 for unsafe
terminal failures. Keep the five newest generated schema snapshots.
- Document producer coverage, query plans, supported writer boundaries,
and test failures in the unsafe-export audit.

## Verification

- Source `2a13dd08a6cc52f0adab09e3df9ce31e97b746b9` passes all 2188
cases across 24 complete files, without skips. The main selection passes
2129 cases in 192.58 seconds; safe-replacement passes 59 in 26.04
seconds. Coverage includes all 968 native-session cases, real
export/action producers, explicit continuation, workspace
reconstruction, interaction routing, Stop, queue and Slack consumers.
The audit gives per-file counts.
- Twenty separate fresh PostgreSQL 17 databases migrate through 0410
before setup. Four embedded-only fixture imports temporarily use their
own external database on this IPC-exhausted host, then are restored byte
for byte. Assertions and timing limits stay unchanged. This is qualified
external-database acceptance, not an unmodified embedded CI run.
- Database build, server typecheck/build, module boundaries and
exact-head migration order pass. Normal integration preserves the
complete original runtime/schema patch and unrelated upstream blobs.
Original concurrent index SQL, all prior executable history, journal
entries and retained snapshot bytes are unchanged; five snapshots 0406
through 0410 remain. Added comment removal preserves the full
non-comment TypeScript token streams.
- A populated 0409-to0410 upgrade preserves all 408 prior migration
receipts and 38 companies. It appends exactly one receipt; replay adds
none. The index is valid and ready on fresh and upgraded databases.
- The owning audit retains earlier fixture failures, skipped checks and
notice-retirement regression history. Older combined stack checks retain
their original scope in their owning audits. Actual parent
`73d24aa5acfcf17b3f676b4da7cd05eb70b60b99` is reconciled through a
normal merge. Its tree equals the reviewed ancestor and the complete
accepted child tree is unchanged. Fresh published-head CI and Greptile
5/5 remain required. No deployed sleep, fleet-cost or live provider
qualification claim is made.

- Inherited prefix correction: current integration
`8f43c9f81fac23b50997e7f0e1d0d9cf383a8109` changes only two values in a
previously unselected corpus fixture. All production code, the complete
package tree and all 24 accepted test files remain byte-identical to the
2188-case source above. The additional complete 72-case corpus passes in
14.00 seconds and again on the same database in 13.08 seconds. Retained
PSC/OUT and sentinel rows remain unchanged. The repeat is not
double-counted. The parent audit retains the original collision and
rejected cleanup attempt.

- Latest parent context: integration
`4d51231abe8b68c21ce896d0d2ac16865978c8ab` carries only the parent's
one-argument GitHub observation correction and an independent master
cleanup assertion. All production code, packages, 24 accepted suite
files and the additional corpus are unchanged. The two focused
native-presentation cases pass in 15.14 seconds and the complete
cleanup-removal suite passes all six cases in 8.31 seconds on two fresh
0410 PostgreSQL fixtures. This does not claim the full parent workflow
was rerun here.

Current head `b28399babac72ba9db1c4a4ef882c5e87aded38c` has passing CI
and Greptile 5/5 with no actionable findings. The first CI attempt lost
runners: fourteen jobs explicitly received simultaneous shutdown
signals, two reported lost runner communication, and two aggregate gates
failed downstream. One failed-job retry on unchanged source passes. The
underlying host shutdown cause remains unconfirmed; no code fix or extra
retry is claimed. [CI run and
attempts](https://github.com/paperclipai/paperclip/actions/runs/40819408528).
No Ponytail verdict is present.

## Risks

- A missing future producer can delay dormant-history discovery until
restart. The audit names current producers. Independent SQL writers and
other server processes remain outside the process-local signal contract.
- Physical ownership and uncertain operations retain retries. Time alone
does not authorize taking workspace ownership. No provider turn or
unsafe archive retry is added.
- The recovery owner remains authoritative if state changes after
discovery. Terminal UI status does not authorize resource destruction or
accepted-result replay.
- The partial index adds matching-row write/storage cost. It builds
concurrently through the existing restart-safe migration runner.
- This proves the changed worker becomes quiet. It does not prove host
suspension, external wake coverage, or fleet cost savings. Other sleep
migrations remain. This slice still requires fresh current-head CI and
reviews.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning and code-execution tools.
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 00:13:22 -05: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
DottaandPaperclip 5f0da562db fix(server): wake chat lifecycle milestones from committed changes (#17606)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Connected chats show safe notices when a run starts, waits,
finishes, or fails.
> - A recurring scan projected these notices even when no eligible work
existed.
> - Eligibility depends on committed run state, conversation lineage,
and current authority.
> - Existing database rows can reconstruct that work after restart.
> - This PR wakes a scoped worker from those writes and removes
lifecycle polling.
> - Native progress events keep their separate existing owner until the
next migration.

## Linked Issues or Issue Description

**What happened?**

The chat maintenance timer repeatedly scanned run lifecycle state. Empty
and settled instances still queried the database. A run-status event
alone cannot replace the scan: prompt receipts, continuation receipts,
identity changes, and restored authority can make a run eligible later.

**What did you expect?**

Committed changes wake projection. Startup reconstructs eligible work. A
completed pass stops until another relevant change arrives. Failed work
retains recovery without scanning settled history forever.

**Steps to reproduce**

Configure an automatic chat endpoint. Finish its work, or leave it
unused. Observe recurring lifecycle projection queries from the chat
maintenance callback.

Stacked on #17592. Related foundation: #15625. This PR owns lifecycle
milestones only.

## What Changed

- Preserve upstream coalesced Cloud membership writes together with
locked membership restoration and its committed chat notification.

- Signal milestone eligibility from the real Slack account-link
transaction.

- Register the lifecycle worker with the existing delivery coordinator.
Remove lifecycle projection from the periodic chat callback. Keep native
progress in a separately named lane and preserve the explicit combined
API.
- Reconstruct company/issue scopes from the existing selector. Drain
bounded batches with company fairness. Retry failures, retain writes
through drain/resume, and disarm settled work.
- Signal from supported run, presentation, interaction, receipt,
lineage, conversation, recovery, and authority writers. Preserve their
transaction ownership, including nested savepoints and uncertain
settlement. No new table is added.
- Preserve provider authorization, authored-final suppression,
responsible-user continuity, deduplication, the 24-hour selection
window, and raw-output restrictions. Keep provider interpretation in its
owner.
- Preserve PostgreSQL timestamp precision in lifecycle pagination.
Rejected submillisecond candidates must not repeat the same page and
starve later notices.
- Document producer coverage and alternate-writer dispositions in
`doc/plans/2026-10-25-chat-run-milestone-sleep-audit.md`.

## Verification

Published head: `1d056f68c5b1005933b9e12de8745bf1c4cbeeca`, targeting
master after #17592 merged at
`7d75ae0569e41786640cf09647ae8849411d2f22`. A normal merge integrates
the actual landed parent. The entire 77-path milestone patch is
binary-identical to the locally verified preparation across that
ancestry reconciliation; both unrelated master paths are preserved. The
four earlier producer/test integration conflicts retain scoped milestone
and voice notices, current onboarding completion admission, and expanded
identity query/read-scope coverage.

- **330 distinct selected cases pass on the verified unchanged patch:**
305 across 14 complete suites (all five milestone worker suites, run
identity, board claim, Cloud provisioning, auth session routes, Cloud
actor authentication, stale-lock recovery, GitHub credentials, project
Git authorization, and app admission wiring), plus 25 selected real chat
producer cases. The remaining 1,590 chat integration cases were skipped,
not passed.
- The real producer cases cover saved milestone discovery, GitHub and
Slack identity changes, account-link rollback/reconfirmation, ordinary
ingress reactivation, post-close action/delivery receipt settlement, all
ten authority-restoration paths including Cloud synchronization, and
changed native review metadata.
- Worker coverage verifies outer commit, rollback, uncertain-write
recovery, restart, bounded batching/fairness, timestamp precision,
retries, drain/resume, and settled SQL quiet. Authorization and existing
publication deduplication remain with their owning services.
- Server production typechecking, build, and module-boundary checks
pass. The tests above were executed separately. Production typechecking
excludes `src/__tests__` and does not replace those runs. Each database
owner uses its own newly created and app-migrated PostgreSQL fixture.
- [Current-parent acceptance and preserved failure
ledger](https://github.com/paperclipai/paperclip/blob/1d056f68c5b1005933b9e12de8745bf1c4cbeeca/doc/plans/2026-10-25-chat-run-milestone-sleep-audit.md#current-parent-integration-and-acceptance-october-28)
records commands, counts, producer scope, conflict dispositions, and
limits. Earlier combined-stack counts and failures keep their original
revision scope; local acceptance does not erase old CI failures.
- No new migration, queue table, dependency, workflow, or shared
scheduler contract is introduced. Parent migration 0397, bounded consent
recovery, voice cleanup/retention repairs, and runner checkpoint
restoration remain present.
- **Exact-head Greptile is 5/5 and all 55 current checks are clean.** No
Ponytail review is present, which is an explicitly authorized
nonblocker; no failing review is waived. Older reviews and parent checks
are not current passes. Actual failing Ponytail findings must be fixed;
an absent/stopped/paused turn without a verdict is an authorized
nonblocker. Active unfinished Ponytail uses its original request/start
timer, with a 25-minute monitor cutoff respecting the user's 30-minute
maximum.
- No complete local repository matrix, live provider tenant, external
alarm, physical host/database suspension, or fleet savings claim is
made. Native progress remains a separate following slice.

## Risks

- A future eligibility writer must notify the existing projection
boundary. Independent SQL writers or another active server process are
outside this process-local signal contract.
- Authority and lineage remain sensitive. The worker uses the existing
selectors and publication policy; it does not grant execution or
disclosure authority.
- Native progress and other publication maintenance still have recurring
work. This PR removes one reason, not the entire chat maintenance timer.
- Worker quiet does not prove database suspension, host sleep, or
external alarm coverage. Cloud sleep blockers remain unchanged.
- Merge eligibility requires passing current-head CI and Greptile 5/5
after this actual-master reconciliation. Subsequent stack slices retain
their own gates.

## Model Used

OpenAI Codex, GPT-6 family. The exact serving model ID and
context-window size are not exposed. Used repository inspection,
reasoning, shell execution, PostgreSQL tests, browser E2Es and GitHub
tools.

## 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 `#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 documented 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 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:07:54 -05:00
DottaandPaperclip 2ee36a4c0a test: add chat feature scenarios and real task workflow evals (#17794)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat lets a person assign work through a conversation.
> - Feature and API maps do not prove that a natural request produces
the right saved result.
> - Product E2E already owns isolated fixtures, browser runs, evidence
and cleanup.
> - This pull request adds a chat scenario catalog and two real task
workflows in that framework.
> - Independent checks verify the task, its author, the saved output and
the reply in chat.
> - The benefit is a small executable foundation for broader chat
coverage.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

It adds real task creation and delegation coverage for Agent Chat.

**Current behavior**

Existing maps describe features and agent access. Existing chat evals
cover specific protocols and handoffs. They do not connect a broad
human-request catalog to independent saved-state checks.

**Proposed behavior**

Keep 244 planned scenarios across 35 feature areas. Promote two requests
into the explicit-only `chat-features` suite. One saves a backlog task
without starting work. The other delegates an announcement and returns
the saved result to the original chat.

**Reason and benefit**

A successful tool call or confident reply does not prove the requested
result exists. These evals check public API state, attribution and
browser access after a real model run.

**Breaking changes**

No API or data schema changes. Chat instructions now require actual
relative task links. The local E2E private-state scanner recognizes
Codex account ownership metadata while continuing to reject credentials
and model-visible identity leaks.

**Additional context**

Related prior work: #13969 and #13762. This improves verification of the
existing Agent Chat roadmap item. It does not add a new core product
feature.

## What Changed

- Add YAML scenarios with capability IDs, starting context, user
requests and expected outcomes. Validate all area files against their
schema, global ID uniqueness and exact feature-map capability coverage.
- Add two local native Codex subscription cells. Send the exact catalog
request once through Chromium.
- Seed only prerequisites through public APIs. Use shipped agent
instructions and explicit disposable budget policies for unpriced
subscription usage.
- Check task ownership, creation audit, no premature execution, current
worker-authored output, automatic completion delivery and usable links
after reload.
- Keep private Codex account ownership metadata distinct from bearer
credentials. Scan rollout message content, all tokens and published
evidence as before.
- Teach normal chat instructions to use relative task links instead of
invented hosts. Update tests, maps and the runbook.
- Repair existing E2E contract drift: include the active Copilot
identity in the image digest and update Pi profile expectations. Keep
global catalog cardinality in its owning catalog test.

Product E2E owns the new flow and grader. Its existing launch and report
paths remain in use. The shared scanner change is limited to
owner-private temporary Codex runtime metadata. Other callers retain the
full secret scan. No UI, endpoint, schema or permission behavior
changes.

## Verification

- `node scripts/check-maps.mjs` passed: 35 areas and 191 capability IDs.
- Product E2E typecheck and focused tests passed before rebase: 225
Vitest tests and 137 Node tests. Conversation service tests passed
40/40. Five existing runner turn-binding regressions passed.
- Historical live measurement used real Chromium, server, database and
native Codex with no automatic retries. The initial same-definition
batch passed 5/6 cells. Backlog passed 3/3; delegation passed 2/3. One
CEO startup failed because the runner did not receive a provider turn
identity. The cause is unresolved.
- An unchanged follow-up passed delegation three times and backlog
twice. Combined evidence is backlog 5/5 and delegation 5/6. Each attempt
passed cleanup. Later passes do not erase the earlier failure or prove a
runner repair.
- Earlier failed revisions exposed an invented task hostname, private
account metadata false positives and missing funding for unpriced
subscription usage. Those led to the specific changes above; the failed
records remain retained locally.
- The runbook records campaign identifiers and definition provenance.
Generated result artifacts are not committed. Historical live results
predate this branch rebase; fresh PR-source live evidence and final
validation are recorded below.
- Full workspace typecheck and production build passed on the rebased
branch. Product E2E typecheck passed.
- The full Product E2E support suite first reproduced four baseline
failures: two missing active Copilot image-identity inputs and two stale
Pi/catalog expectations. The narrow contract fixes above resolved them.
The full rerun passed 4,282 Vitest tests plus 137 Node tests, with two
skipped. Image checks verify mutation changes the hash, unchanged input
stays stable, and an input closure without Copilot is unaffected.
Original failed logs remain retained.
- The repo-wide local Vitest run has reported two failures in unchanged
service files. The Workspace connection test passed an isolated recheck
and its full file passed 469/469 unchanged. The recovery test hit a
15-second timeout; its full file passed 89/89 unchanged. The run later
hit explicit PostgreSQL `semget` resource exhaustion and was interrupted
after those observed failures; no final aggregate counts or full local
pass are claimed. Its complete available log is retained. No assertion
or timeout was weakened. Matching remote server CI passed on the same
source.
- On clean PR head `39ad80b523ce194c90aafafd077d48dd9a36b4c5`, backlog
passed in `local-2026-10-26T19-24-13-014Z`. The parallel delegation
fixture failed during PostgreSQL initdb, before browser or model
execution; its failed cleanup grade is retained. A disposable standalone
initdb probe then passed. No semaphore sets or kernel settings were
changed before that probe/recheck. After confirming no remaining fixture
process, its private temporary files were removed.
- One separate delegation recheck passed in
`local-2026-10-26T19-29-24-800Z`, with one attempt, zero automatic
retries and successful cleanup. Both passing current-source cells use
definition
`3f2c9ba2d03e3dcddde47ddab3b43bc52de977f25e256fceae0a24c9128e204b`. The
earlier bootstrap failure and the historical provider startup failure
remain distinct. These local results omit automatic source-SHA metadata;
the clean checkout SHA is recorded here from the execution session.
- The later broad local run reported `could not create semaphores: No
space left on device`. A bounded cleanup removed 32 current-user
PostgreSQL sets with 17 members, marker 537, a dead recorded creator and
zero waiters. No live process or kernel limit was changed by that
cleanup. The test process group was subsequently stopped; no broad rerun
is planned. This direct later resource failure does not prove the
precise cause of the earlier live initdb failure.
- Review follow-up adds only static catalog validation and documentation
of the existing five-minute journey bound. The executable definition is
unchanged. Focused catalog/oracle tests passed 28/28; no redundant live
run is claimed.
- Final head `30fcb36ac9ae1f0270a589dbfafcec91ca6a03f3` passed all
required and underlying CI checks in [run
40391402347](https://github.com/paperclipai/paperclip/actions/runs/40391402347),
including `ci / verify` and `ci / e2e`. Greptile and Paperclip Review
both scored this head 5/5, with all review threads resolved. The static
follow-up leaves every executable definition input byte-identical to the
live-tested source at `39ad80b`.

Normal squash auto-merge is enabled. Actual merge is pending eligible
code-owner approval for the owned dependency manifest; no protection is
bypassed.

## Risks

- Live model behavior can vary. One missing turn-start event remains
unexplained; this PR does not claim provider reliability or broad
catalog qualification.
- Subscription costs are unpriced. Explicit fixture funding admits that
usage. Run counts and deadlines remain bounded, but the dollar limit
cannot cap unknown cost.
- Account identity exceptions apply only to known private Codex runtime
files. Token reuse, unknown files and model-visible rollout content
remain blocking findings.
- Deterministic checks establish saved state, output structure, required
brief facts and access. They do not score all prose quality. Initial
samples also require human inspection.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, code execution, browser and
repository tools. The precise model revision and context window are not
exposed to this session. Live eval agents used `gpt-5.6-sol`; that is
the evaluated model, not a claim about the authoring model.

## 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 local tests; focused suites pass and the interrupted
full-run failures are 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-26 16:19:39 -05:00
Devin FoleyandPaperclip 9f3a5456ac perf(server): bound run reads in authentication and conversation recovery (#17663)
Read compact run identity during authentication and compact turn state during conversation recovery. Preserve fresh checks, durable steering and reply evidence, locking, and complete stored payloads.

Validate 184 targeted PostgreSQL and lifecycle tests, workspace typecheck, server build, full CI, and Apex 5/5.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 15:53:18 -07:00
DottaandPaperclip a7dd5284b5 feat: add company fast-response acknowledgements (#15748)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Human messages start agent work through task, chat, and
external-channel intake.
> - Agent startup can delay the first visible response.
> - A small direct model call can acknowledge the request while normal
work starts.
> - This response must remain separate from evidence that the agent
answered or completed work.
> - This pull request adds optional company-wide fast responses with
durable receipts, access checks, and cost accounting.
> - Users receive prompt acknowledgement without changing the agent
execution path.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: database, shared contracts, server orchestration,
connections, and UI.

**Problem or motivation**

Users can wait for an agent to start before they receive a contextual
response. Generic progress messages do not confirm what the user asked.
An acknowledgement must not falsely complete work or satisfy an
unanswered turn.

**Proposed solution**

Add a disabled-by-default experimental fast-response model using an
existing shared API connection. Generate one short acknowledgement for
each accepted human turn. Use the existing agent identity and external
publication outboxes. Retain platform provenance and account for the
inference independently.

**Alternatives considered**

Running the acknowledgement through the agent runtime adds startup
latency. Restricting implementation to OpenRouter leaves other existing
API connections unsupported. This change supports all existing API
connections and uses OpenRouter for live verification.

**Roadmap alignment**

This extends existing agent communication and connection settings.
ROADMAP.md and open pull requests were checked. No duplicate
fast-response implementation was found. The maintainer supplied the
feature plan directly.

## What Changed

- Add Experimental fast responses to instance settings. Keep the feature
off by default. Enforce the flag at intake, dispatch, and publication.
- Move Decision model and Fast response setup to company Settings →
Connections when the experiment is enabled. Place Connections below
Environments. Separate the model sections with clear headings and a
divider. Keep Decision model in General when the experiment is off.
Route Costs setup links to the available settings page.
- Make the acknowledgement prompt a multiline template string. Ask for a
brief, positive response in the user’s language.

- Add settings, connection/model selection, sponsorship, fixed-sample
testing, and Costs history.
- Add a Vercel AI SDK text service for existing native, routed, Bedrock,
and local API connections.
- Add durable per-turn requests, a bounded worker, a three-second
admission deadline, and one inference attempt.
- Integrate task creation, task and agent chat, steering, queued
follow-ups, experimental board chat, shared chat intake, and email.
- Preserve receipt provenance and exclude receipts from completion,
recovery, interaction resolution, and agent wakeups.
- Recheck authorization, source validity, real replies, budgets, and
destination binding before publication. Preserve accounting for
suppressed or uncertain outcomes.
- Add provider contracts, database race tests, channel outbox tests, UI
tests, Stories, and documentation. Keep decision-model execution
unchanged.

## Verification

- Local `pnpm -r typecheck`, `pnpm build`, and UI token gates pass after
rebase. The UI typecheck and build also pass after the final navigation
fixes. All 37 focused navigation tests pass. The first full local `pnpm
test:run` invocation reported seven chat failures. All seven passed in
isolated reruns after fixture updates and host cleanup. This invocation
was stopped after the full final-head CI suite passed.
- Initial local database tests hit macOS shared-memory exhaustion. A
diagnostic confirmed `shmget: No space left on device` with the system
limit of 32 IDs. Three abandoned, unattached PostgreSQL IPC headers were
reclaimed. The isolated rerun passed all 31 fast-response and channel
tests. The two additional Slack regression cases also passed in a
separate rerun. No active database was stopped.
- UI token gates pass. Provider contract tests cover all supported API
connection types. Fast-response tests cover uniqueness, authorization,
budgets, expiry, cancellation, restart, real-reply races, and the
experimental flag.
- The test drive verified that disabling the experiment hides
Connections and redirects its direct URL. Enabling it restores the saved
OpenRouter setup. After restart on the final commit, the OpenRouter
settings sample returned “Sure, I’ll take care of fixing the border
around the settings panel.” in 428 ms. It used 260 input and 31 output
tokens and recorded $0.0000576 in reported cost.
- Earlier live OpenRouter verification produced a receipt in 1.013
seconds for a new task. The real agent then supplied its substantive
answer. A separate settings test took 1.34 seconds, used 246 input and
23 output tokens, and recorded $0.0000361.
- Live Slack verification on final commit
`24016fa525961ebc7a4acffdc5019ce123970549` passed for a fresh initial
task and a follow-up in a disposable bot DM. The initial acknowledgement
appeared 2.405 seconds after the Slack message and 1.413 seconds after
durable acceptance; the follow-up appeared in 2.322 seconds and 1.160
seconds respectively. The recorded generation/settlement durations were
898 ms and 697 ms. The initial call used 291 input / 39 output tokens
and cost $0.00006705; the follow-up used 281 / 47 and cost $0.00007035.
- The Slack acknowledgements retained the assigned agent identity and
`origin: fast_response`, source-turn references, and no fabricated run
ID. A status snapshot after the initial receipt showed the task still
`in_progress` with its real execution run. The agent then read the CSV
fixture and correctly reported two ready items, two blockers, and their
owners. Both replies stayed in the originating DM, and no duplicate
generic working message followed the delivered contextual
acknowledgements. The `new` command started a fresh conversation session
without generating a fast response.
- An earlier eligible Slack turn generated a response but suppressed
publication. Its reported cost was retained, generic progress remained,
and the real agent completed the requested result. This is recorded
separately from the two delivered acknowledgements; the history did not
expose a precise suppression reason.
- Slack verification used real signed provider events, the existing
intake/publication paths, and a user-approved temporary webhook-only
HTTPS tunnel. Subscriptions were limited to direct-message events. The
test bot was paused and the tunnel stopped afterward. Live
channel/group-thread and GitHub journeys remain unverified; their mocked
tests cover intake, destination binding, publication, and continued
underlying work.
- Greptile reviewed final commit
`24016fa525961ebc7a4acffdc5019ce123970549` at 5/5. Both new review
findings are fixed and all threads are resolved. [Final-head CI
run](https://github.com/paperclipai/paperclip/actions/runs/38060015730)
passed. This includes grouped server/chat/workspace tests, serialized
suites, runner checks, browser journeys, typecheck, build, release
registry, policy, and the canary dry run.
- Manual check: enable Experimental fast responses. Open company
Settings → Connections. Select a shared API connection and model. Save
and use Test response. Submit a task message and confirm that its
receipt does not complete the task.

## Risks

- The migration adds receipt and configuration tables plus accounting
references. It uses idempotent statements and follows the current
migration sequence.
- A slow provider, authorization change, or real-agent reply can
suppress an acknowledgement. Existing progress feedback remains
available.
- Unknown provider billing retains a reservation until reconciliation.
External deliveries with uncertain outcomes must not be blindly
repeated.
- Live Slack initial-task and follow-up DM journeys pass. Live Slack
channel/group-thread and GitHub journeys remain unverified. The PR
remains a draft and records these gaps. Final-head repository CI and
automated review pass.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, repository tools, code
execution, and browser interaction. The runtime does not expose an exact
model snapshot ID or context-window size; these are not asserted.

## 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-10 13:09:17 -05:00
DottaandPaperclip 4039d4f06b fix(auth): allow scoped low-trust work and owner-chat instruction edits (#14870)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Low-trust agents must work within their assigned scope.
> - Task creation currently rejects these agents before checking
assignment permission or scope.
> - Persistent instruction saves also reject direct requests from
authorized chat owners.
> - This PR checks the requested action and its recorded authority
instead of denying all such work.
> - Agents can organize permitted work and follow their owner's
instruction-edit requests while outside work stays restricted.

## Linked Issues or Issue Description

**What happened?**

Low-trust agents cannot create self-assigned tasks or subtasks, even
within their allowed scope. An authorized user also cannot ask an agent
in their own Agent Chat to update its managed `AGENTS.md`. Agent-folder
collection can hide the permission rejection behind a generic save
failure.

**Expected behavior**

Allow task creation when assignment permissions and project or root-task
scope permit it. Allow instruction self-edits during authenticated
owner-chat execution, subject to the user's current edit permission.
Outside tasks, subtasks, connector messages, and peer agents do not
inherit that instruction authority. Explain the actual denial when a
save fails.

**Steps to reproduce**

1. Configure an active agent with `low_trust_review` and a project or
root-task boundary.
2. Ask it to create an in-scope task assigned to itself, or a subtask of
its own task.
3. As a user with permission to configure that agent, ask it in your
Agent Chat to update its managed `AGENTS.md`.
4. Observe blanket permission denials rather than action-specific
checks.

**Paperclip version or commit**

Rebased onto master at `8ec4b84e1`. This is a core authorization change,
independent of adapter choice.

**Deployment mode**

Authenticated server. Regression coverage uses the server services, HTTP
routes, native tool authority, and embedded PostgreSQL.

Related work: #14775 adds human-directed task execution. #13599 concerns
instruction-path configuration; this PR leaves that configuration
restricted. #11988 proposes separate active-review instruction
protection. #10693 reports unclear authorization denials on a different
API surface.

## What Changed

- Apply task-assignment checks to both HTTP creation routes and native
task creation, including unassigned work. Preserve low-trust policy and
source attribution on the created task and its initial plan.
- Allow self-assigned decomposition within the permitted project or
root-task tree. Resolve workspace-derived project scope before
authorization, and reauthorize existing tasks before duplicate detection
returns them. Keep cross-project and peer-assignment checks.
- Derive instruction self-edit authority from the accepted run identity
and authenticated owner-message wake. Recheck current permissions at
save time. Bind retries to the same request and chat session.
- Reject inherited instruction authority from outside tasks, subtasks,
plugins, connectors, stale sessions, cancelled runs, and peer edits.
- Surface permission errors in instruction and agent-folder save
receipts. Tell chat agents to explain the rejected action and the
specific restriction.
- Update the low-trust policy and implementation documentation.

## Verification

- All 297 tests in 11 focused server suites pass after the rebase. These
cover owner-chat saves, private copies, warm agent directories, reset
and retry boundaries, permission revocation, task creation routes, and
native tool authority.
- After review fixes, all 126 tests in the four affected
authorization/chat suites pass. Workspace scope regressions and 146
existing creation/ownership/workspace-route tests also pass.
- The final duplicate-task and CI fixes pass all 39 tests across
chat-project tools, duplicate creation, environment-selection guards,
and assignee-invokability routes. The duplicate-task test reproduced an
unauthorized response before the fix and verifies denial plus permitted
reuse afterward.
- `pnpm --filter @paperclipai/server typecheck` passes after rebasing;
`pnpm --filter @paperclipai/server exec tsc --noEmit` also passes after
the review fixes.
- `git diff --check origin/master...HEAD` passes.
- Final head `7e73270b86748792649e4ae6fbc6879f73b42b73`: all 54 checks
passed, with two expected skips and no pending or failed checks. This
includes builds, typechecking, the full test matrix, end-to-end tests,
runner verification, the canary dry run, and security scans.
- Greptile is 5/5 on that exact head, with no unresolved review threads.
This change has not been deployed to staging.

## Risks

This changes authorization behavior. The instruction exception must not
become an inherited task permission. The check uses server-owned
execution records, requires the agent's own chat and instructions, and
keeps normal protected-change and responsible-user checks. Saves fail
closed when current provenance or permission is missing. Owner chat
grants a turn-scoped capability; the server does not classify the
message intent or require approval of the exact new file bytes. Prompt
injection within an authorized owner-chat turn remains a model-level
risk. This is the requested owner-chat trust boundary, without a new
per-edit confirmation flow. No database migration or broad trust-preset
change is required.

## Model Used

OpenAI Codex, based on GPT-6, with reasoning, code editing, shell tools,
and test execution. The exact runtime 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-01 15:42:40 -05:00
DottaandPaperclip 3c561642b4 fix(chat): resolve approvals and preserve unanswered questions (#14613)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agents ask for decisions and optional details through cards in chat.
> - A clear approval in a message can leave the matching card pending.
> - An unanswered question can also block an unrelated later reply.
> - Decisions need a saved source message, while optional questions need
to remain answerable in history.
> - This pull request records conversational decisions and lets users
move on from questions and answer them later.

## Linked Issues or Issue Description

**What happened?**

Native Claude and Codex could act on approval in chat while the original
approval card stayed pending. Pending question forms stayed above the
composer, were absent from history, and could suppress later chat
replies. A late native question answer could wait for a finished run to
reconnect.

**Expected behavior**

The active agent records a clear approval or refusal against the exact
card and user message. Ambiguous replies do not grant consent. Users can
send another message without answering a question. The question remains
pending in history and can be reopened and answered later. The saved
answer reaches the agent.

**Steps to reproduce**

1. Ask an agent to propose work with a confirmation card, then approve
it in chat.
2. Check that the original card records that approval before work
starts.
3. Ask an interactive question, send an unrelated message, and reload.
4. Open the unanswered question from history and submit an answer.

Related work: #14408 added completion delivery. #14607 tests completion
reporting turns. Neither records conversational answers on approval
cards.

## What Changed

- Add a confirmation endpoint backed by a user comment, with schema
validation, OpenAPI discovery, and native Plan-mode access. Ask mode
remains read-only.
- Check company, active run, actor, current session, message provenance,
revision, and resolver policy. Save the decision and audit in one
transaction. Retries do not repeat effects. Emit resolution telemetry
after commit.
- Give fresh and resumed chat turns the actual pending confirmation
identities. Teach agents to save clear conversational decisions before
acting and to clarify ambiguity.
- Keep unanswered Agent Chat questions as compact history entries. A
newer user message closes the old form. Question cards never contribute
to composer pending counts or navigation, including after dismissing a
fresh form. The history card is the sole reminder; clicking it restores
that exact form and draft.
- Preserve Agent Chat questions when later messages or questions arrive.
Historical ordinary inputs no longer gate later chat replies.
Current-run requests, task execution, and governed approvals keep their
gates. Remove the special acknowledgement-publication proof helpers that
this rule replaces.
- Route answers to finished native runs through durable fresh-wake
delivery, with existing idempotency and source-question context. Settle
late replies against contiguous completed conversation turns and freeze
their history replay; failed, unhandled, and newly arriving messages
remain actionable.
- Add real-component Storybook scenarios, database and UI regressions,
and a three-turn native Claude/Codex E2E case. Capture distinct,
UI-ready screenshots and report the individual assertions.

## Verification

- Focused decision/publication/UI regressions after merging master: 288
passed; subsequent UI draft, failed-send, and conversation checks: 199
passed.
- Native question and durable delivery regressions: 106 passed,
including all four terminal run states and exactly-once late delivery.
Seven targeted regressions fail against the original implementation and
pass with the fix.
- Latest conversation/decision/native-delivery regressions after the
master merge: 121 passed. Covers completed progress, missing or failed
intervening turns, new messages during a late reply, stale sessions, and
frozen retry/replay boundaries. Four new assertions fail before the
ordering fix.
- E2E support suite after the master merge: 792 passed. Negative
controls reject expired cards, wrong questions/answers, stale or missing
replies, unrelated clarification forms, and unexpected tasks.
- The embedded-browser walkthrough caught one additional defect:
dismissing a fresh question still showed a composer badge. Both Cancel
and close-button regressions failed before the fix. The fix at
`65f2ade12` passes 170 chat-thread tests and 792 E2E support tests.
After merging master, 232 chat-thread/confirmation tests, server/UI
typechecks, and token gates pass. The preview and two-provider live E2E
pass at `e5512a206`; Greptile is 5/5 with zero unresolved threads at
that commit. All 55 checks are now successful at `e5512a206` (four
conditional checks skipped), including the aggregate verification gate
and clean-install canary test. The first attempt was interrupted by
simultaneous CI worker shutdowns; one failed-job rerun passed without
code changes.
- [Published
Storybook](https://d1p6rlowie26tp.cloudfront.net/storybook/branches/codex~2Fchat-approval-resolution/?path=/story/chat-comments-agent-chat-unanswered-questions--moved-on):
nine real-component scenarios. Manually exercised move on, reopen,
preserve draft, answer later, answer one of multiple questions, and a
custom mobile answer in the embedded browser. Retested fresh Cancel and
close-button dismissal in the updated build, then reopened and submitted
the preserved Green selection and inspected its answered receipt. Static
preview has no live model/backend; its callbacks are fixture responses.
- [First live
campaign](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36714504406-1/)
reproduced the late-answer completion-state defect on both providers
despite correct saved answers and acknowledgements. It also exposed a
valid imperative clarification rejected by the old oracle. Both issues
are fixed with regression controls; this failing run is retained as
evidence.
- [Four-cell
qualification](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36717804064-1/)
passed 4/4 at `2bf8a1009`: unanswered-question return and ambiguous
confirmation, each on native Claude and Codex. Inspected saved state,
source-message decisions, visible cards, and agent replies. Both
late-answer chats settled to waiting; no unrequested tasks were created.
[Final branch
rerun](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36719666238-1/)
passed 2/2 at `142630720`: the same unanswered-question journey after
merging master, plus an additional screenshot and browser assertion for
the actual late-answer acknowledgement.
- [Composer-reminder
E2E](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36727006818-1/)
passed 2/2 at `5b62c52d9`: native Claude and Codex, three turns each,
with explicit no-badge assertions before and after reload. Inspected
saved pending/answered state, both screenshots with a clear composer,
and actual Blue acknowledgements; all five behavioral matchers passed
per provider and neither created tasks. Cost coverage is partial; this
is bounded workflow qualification.
- [Fresh-dismissal
E2E](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36742773318-1/)
passed 2/2 at `e5512a206`: native Claude and Codex, including fresh
Cancel, clear composer, reopen, unrelated message, reload, late Blue
answer, and actual agent acknowledgement. All five behavioral matchers
pass per provider. Inspected the fresh-dismissal screenshots and saved
pending/answered identity; neither created tasks. Cost coverage is
partial (4/6 runs).
- Prior evidence remains available in [the earlier
campaign](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-36642252725-1/).
Its early loading screenshot and overwritten final capture prompted the
UI-ready, distinct screenshot fixes.

## Risks

- The model interprets intent. The server verifies permission and
provenance; it does not infer consent from text. Ambiguous and unrelated
replies are not approvals.
- Historical questions can accumulate. They remain visible, pending, and
answerable; no automatic answer or expiry is invented.
- The change to completion gates is scoped to Agent Chat and ordinary
historical inputs. Current-turn and governed approvals retain their
existing controls.
- Live qualification is limited to the selected stories. Broader native
onboarding finalization remains separate work.
- No database migration. Telemetry adds no fields or values; the
contract and README document the commit boundary. Privacy review was
requested on the PR.

## Model Used

OpenAI Codex, GPT-6 family, with reasoning, repository tools, code
execution, and browser-test orchestration. The exact model ID and
context-window size are not exposed to 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-09-30 11:46:46 -05:00
DottaandPaperclip 83076d7e7c feat: return completed handoffs to Agent Chat (#14408)
Return completed Agent Chat handoffs through a durable outbox and scope each generated update to its supplied tasks. Add recovery, browser delivery, result access, and calibrated quality coverage.

Validated with two consecutive ten-case Claude/Codex campaigns, all CI checks, and a 5/5 review.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-29 10:25:52 -05:00
DottaandPaperclip 36dbb7ed1c fix: harden agent chat runner tools and recovery (#13678)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Agent Chat turns discussion into plans, tasks, reviews, and hires.
> - These workflows need reliable tool results and task context on the
native runner.
> - Live Claude and Codex tests exposed lost retry requests, invalid
project inputs, and a child startup crash.
> - Recovery also exposed a misleading retry action and missing child
task context.
> - This pull request fixes those paths and adds regression coverage.
> - Agents can continue the original request and operators can inspect a
stopped run.

## Linked Issues or Issue Description

**What happened?**

A failed Agent Chat retry could lose the user's question. Project
creation accepted unsupported icons in its tool schema. Codex could stop
when a helper's MCP startup event arrived before its thread lineage. A
stopped task offered Retry even when the server required execution
reconciliation. Resumed agents could miss existing delegated tasks.
Hiring and review instructions did not describe the native runner's
available tools and source requirements.

**Expected behavior**

Retries retain the selected request. Tool schemas match the API. Child
startup information does not gain authority over the parent or stop it.
Recovery actions match the server's requirements. Task context exposes
existing child work. Handoffs contain the material the assignee needs.

**Steps to reproduce**

1. Enable experimental Agent Chat in an isolated development instance.
2. Configure native Codex and ACPX Claude agents on Paperclip Runner.
3. Ask for a plan, revise it, approve task creation, and request a hire
and status report.
4. Retry a failed chat turn and check that it answers the original
request.
5. Start a Codex helper before its thread lineage arrives.
6. Resume a delegated task and inspect its existing children and saved
output.

**Paperclip version or commit**

The live failures were found at `f2c5e54dc`. This branch is rebased onto
`86b7ee992`.

**Deployment mode**

Isolated local development instance with native Codex and ACPX Claude.
No database migration or default permission change.

Related work: Refs #13284 for Agent Chat. Refs #13438 for the
server-side API receipt fix, which this branch preserves. The transport
also accepts the earlier HTTP receipt format. Refs #13655 for the
current Codex continuation and helper lineage handling, which this
branch also preserves.

## What Changed

- Preserve failed Agent Chat wake-comment IDs and session generation
from the authorized source run. Reject pre-reset retries.
- Wrap API receipts with the correct semantic call identity. Test
current and earlier receipt formats through real HTTP and runnerd.
- Classify early child MCP startup notifications as information. Keep
foreign completion and result events rejected.
- Constrain project icons on both tool surfaces and regenerate the
protocol contracts.
- Include bounded, company-scoped visible direct child tasks in task
context. Filter hidden tasks before applying the limit.
- Replace the rejected Retry action with Inspect run for native
continuation reconciliation.
- Update hiring, review handoff, status reporting, and development
guidance.

## Verification

- Live tests covered Claude and Codex questions, plan revisions,
approval, task creation, hiring, status, chat reset, failures, and
recovery.
- The recovered task produced its saved checklist and example. A later
follow-up read the existing child tasks and document without creating
more work.
- Full build, repository type checks, token gates, 142 focused tests,
188 runner TypeScript tests, and the Rust notification/descendant
regressions passed after rebase. The separate local full-suite run was
stopped after the complete CI suite passed.
- Review fixes passed the updated route, tool-authority, and icon
regression tests plus server type checking.
- Required commands: `pnpm build`, `pnpm -r typecheck`,
`PAPERCLIP_IN_WORKTREE=false pnpm test:run`, and `pnpm
check:token-gates`.
- At `4ce8047b0`, all 55 applicable GitHub checks pass (two Storybook
checks are intentionally skipped), including the complete
general/serialized test matrix, runner tests, browser tests, build, type
checks, Docker checks, and canary dry run.
- Fresh Greptile review is 5/5 on `4ce8047b0`; all three findings were
fixed with regressions and there are no unresolved review threads.
- Two initial CI service-startup timeouts passed unchanged in local
reproductions and in the latest CI run.

## Risks

- The new event classification is limited to MCP startup information. It
does not authorize foreign task completion, results, or tool requests.
- Task context returns at most 100 direct child tasks and reports
truncation. It excludes hidden tasks and other companies. This improves
delegation context but does not enforce semantic duplicate detection.
- Native reconciliation still requires an operator to inspect and record
prior outcomes. The new link does not replace the recovery API.
- API tools remain opt-in. Claude permission choices remain explicit. No
default permission, schema, or workflow changes.

## Model Used

OpenAI GPT-6 in Codex, with reasoning, repository editing, code
execution, API tools, and browser testing. The exact deployment
identifier and context-window size are not exposed in this session. Live
acceptance agents used OpenAI `gpt-5.6-sol` and Anthropic
`claude-sonnet-4-6`.

## 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-09-19 09:11:04 -05:00
DottaandPaperclip 43acbcc398 fix(runner): preserve sessions and complete question and approval continuations (#13655)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The native runner connects task state to provider sessions.
> - Follow-up turns must retain provider memory and carry new user
direction.
> - Lost session IDs caused repeated context and extra input tokens.
> - Native question answers and approval races could leave valid work
blocked.
> - This pull request repairs those paths and adds regression coverage.
> - Agents can continue accepted work without repeating the conversation
or losing the user's answer.

## Linked Issues or Issue Description

Refs #13574. That merged PR shortened continuation prompts and moved
question instructions into tool documentation. This change preserves
sessions and fixes failures exposed by broader testing. Related runtime
work: #13408 and #13410.

**What happened?**

Native follow-up turns could lose the provider session ID. Completion
guidance could replace the original task with its latest comment. Claude
native questions could remain pending after the user answered. Approval
during a running tool call could suspend the run before the tool
response arrived. Onboarding and chat handoff instructions also caused
repeated planning or missing plan documents.

**Expected behavior**

Reuse a valid provider session. Send only new events when that session
already has the history. Preserve the task requirements and apply later
user direction. Store the question answer and deliver it to the waiting
run. Finish governed tool responses before suspending. Execute the
accepted plan without asking for the same approval again.

**Steps to reproduce**

Run the continuation, local-session-integrity, first-task, and
agent-chat suites with native Codex and Claude. Include
provider-question-bridge, accept-while-running, and plan-handoff.

**Paperclip version or commit**

This branch is based on master d54b75011. The active full catalog run
tests 4e75881db. Later review fixes have separate regression coverage.

**Deployment mode**

Isolated local instances and Daytona sandboxes in the existing Runner
full-stack E2E harness.

## What Changed

- Retain provider session identity across turns and late usage
snapshots. Send new continuation events on session reuse, with full
context available for a fresh session.
- Preserve task requirements and later direction in completion guidance.
Return the current contract revision after a stale completion
submission.
- Bridge native Claude questions to saved Paperclip cards. Submit
answers through the saved card and resume the same run.
- Delay governed suspension until tool results settle. Add a
deterministic test barrier for approval during an active run.
- Clarify free-text question examples, explicit onboarding plans, and
execution of accepted chat plans.
- Fix continuation readiness, verified output evidence, and declared
screenshot collection.
- Qualify the legacy Claude test CLI at 2.1.277. The old 2.1.19 CLI did
not discover mounted skills. Update the existing workflow pin and
isolated launcher together.
- Refresh the Daytona image lockfile integrity pin after reviewing
master patch updates.
- Carry continuation mode as runtime metadata instead of inferring it
from user-visible text. Install the test Claude CLI without lifecycle
scripts.

## Verification

- Targeted paid verification: 20/20 cases passed across
local-environment campaigns before the rebase.
[Report](https://pages.paperclip.ing/runner-e2e-seven-fixes-35397904249/).
- Harness checks: 379 unit tests passed; harness typecheck passed.
- Latest-head PR checks: 55 passed, two intentionally skipped. Greptile
is 5/5; the security scan passes.
- Review regressions: 350 executor tests and 204 session/driver tests
passed. A script-free Claude install was verified with the actual CLI.
- Full catalog, including the explicit-only everyday suite: [run
35417932353](https://github.com/paperclipai/paperclip/actions/runs/35417932353).
Completed: **164/205 passed; 41 failed**. [Full dashboard and failure
investigation](https://pages.paperclip.ing/runner-e2e-full-catalog-35417932353/).
Includes 204 case artifacts and one pre-case GitHub authorization
timeout; missing evidence is not scored as a pass. The full run tested
`4e75881db`; Final-head metadata/CLI smoke cases both passed. In the
separate [six infrastructure
retries](https://github.com/paperclipai/paperclip/actions/runs/35419769343),
the GitHub timeout case passed and all five Docker preflight failures
repeated. [Follow-up
dashboard](https://pages.paperclip.ing/runner-e2e-full-catalog-35417932353/follow-up/).
- Full local typecheck and build passed on the rebased branch. The full
local unit run completed with 657 passing files, two test timeouts and
one suite setup timeout. All three affected files passed when rerun in
isolation (84 tests). The first full local run was not clean.
- Focused regression coverage includes the live question bridge,
same-run response delivery, UI routing, stale revisions, approval
overlap, and session reuse.

## Full-catalog follow-ups

- Test infrastructure: 14 Claude everyday cells probe an absent host
CLI; six cells failed pre-task GitHub/Docker qualification (GitHub
passes on retry; all five Docker cases repeat; the workflow preflight
allowlist omits their case IDs); five ACPX Codex cells cannot create
sandbox namespaces.
- Runtime: four OpenCode completion-criteria mismatches masked by
shutdown errors, one service-approval suspension failure; three Daytona
recovery failures encounter existing skill files; one duplicate
completion wake.
- Confirmed test defects: question pagination and a noncanonical plan
document key.
- Product/behavior: mismatched visible/required question sets, an
attachment instead of the requested task document, one lone-option
onboarding question, early completion instead of review, and a Codex
Mini completion-schema failure.
- The report job itself fails on trusted master’s stale patch/lock
configuration. The linked report is rebuilt with the shared renderer
from original cell results and public fixture screenshots; it excludes
private snapshots, logs and traces.

These are investigated follow-ups, not silently regraded passes.
First-task passed 51/52. The PR checks are green independently of the
broader catalog’s behavioral/infrastructure failures.

## Risks

- Session reuse depends on a valid provider identity and context
coverage. Fresh-session fallback and reset tests cover this boundary.
- Native question delivery spans saved interaction state and a live
provider run. Tests cover duplicate events, closed runs, and same-run
answers.
- Provider behavior varies. The full paid catalog may expose failures
beyond these targeted fixes; those results will be reported without
relaxing valid approval or output checks.
- The legacy Claude version update is limited to test infrastructure. No
database migration is included.

## Model Used

OpenAI Codex, GPT-6 family, with repository inspection, code execution,
and browser/E2E tools. The exact runtime model identifier 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 (targeted checks and all
three timeout-file reruns pass; full-run timeout caveat 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-09-19 07:42:57 -05:00
DottaandPaperclip ab15aff390 feat: add experimental persistent agent chat (#13284)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Conversations must use the same tasks, controls, and execution
history.
> - Users need an ongoing chat with an agent without managing task
properties.
> - Agents should clarify and plan work, then hand execution to assigned
project tasks.
> - This pull request combines the reviewed Agent Chat stack for one
squash merge.
> - The benefit is persistent conversation with normal task governance
and shared UI.

## Linked Issues or Issue Description

**Subsystem affected**

Task lifecycle, agent runtime tools, shared task UI, and browser/paid
runner tests.

**Problem or motivation**

Users need one persistent conversation with each agent. A separate chat
store or renderer would duplicate task behavior and bypass existing
controls.

**Proposed solution**

Use a task-backed chat per company, user, and agent. Reuse the task
composer and transcript. Clarify and plan in chat, then create assigned
project tasks with the relevant plan. Keep Agent Chat behind its own
disabled-by-default experimental setting.

**Roadmap alignment**

This implements the task-backed direction in [CEO
Chat](https://github.com/paperclipai/paperclip/blob/master/ROADMAP.md#-ceo-chat).
Related proposals: #2504 and #9693. Related request: #7981. The
maintainer requested one squash merge of the complete stack.

Consolidates the reviewed runtime
[#13281](https://github.com/paperclipai/paperclip/pull/13281), backend
[#13282](https://github.com/paperclipai/paperclip/pull/13282), and UI
[#13283](https://github.com/paperclipai/paperclip/pull/13283) layers
with this PR's E2E coverage. All four layers passed CI and received
Greptile 5/5 before consolidation. This PR targets master and includes
the complete feature.

## What Changed

- Add personal canonical chat tasks with ordinary company visibility,
immutable identity, idempotent first sends, and an idle waiting state.
- Process `/new` in queue order. Preserve history, release a chat pause,
and fence old provider context and delayed writes.
- Keep chat lifecycle rules across recovery, finalization, assignment,
task lists, and rollups.
- Support research and plan revision in chat. Hand plans to ordinary
assigned project tasks before execution starts. Reject new chat
subtasks.
- Add repository-aware project creation and discovery tools, including
multiple repository IDs and GitHub URLs, authorization, idempotency, and
durable project-created cards.
- Reuse task UI components for chat, with starred/recent agent
navigation and a separate `enableAgentChat` experimental flag.
- Add deterministic browser tests and 24 paid chat cells across four
Codex/Claude profiles, with validated reports and screenshots.
- Integrate current master recovery, controller lease, queued-message,
and task UI changes. Gate chat interruption and deferred promotion on
ownership/feature policy. Guarantee lease renewal and active controls
are stopped even if teardown fails.
- Preserve master's migration 0273 and generate chat migration 0274 with
idempotent replay for development databases.

## Verification

- Prior exact heads of all four PRs passed Linux CI, including build,
typecheck, general/serialized tests, and browser E2E. Each had Greptile
5/5 and no unresolved findings.
- Integrated local verification passed: full repository typecheck and
production build, Storybook build, token gates, 340 focused UI tests,
all 20 deterministic chat browser tests, two migration replay tests, 88
focused chat/queue/native/controller tests, and provider/session
regressions including real lease expiry. These include the three
lifecycle regressions for the final admission/teardown fixes; server
typecheck also passes. Current head
`1268eda16cc2af892055917e7292f068820be135` has Greptile 5/5 with no
unresolved findings and passing security scans. All final-head CI gates
passed: build, full Runner verification, typecheck/release registry,
canary, all general/serialized test shards, and all browser E2E shards
([CI
run](https://github.com/paperclipai/paperclip/actions/runs/34696739927)).
Local PostgreSQL startup contention required serialized retries; skipped
fixtures do not count as passing coverage.
- The earlier paid campaign passed all 24 chat cells and retained 32
screenshots:
[report](https://d1p6rlowie26tp.cloudfront.net/runner-e2e/campaigns/gha-34648511170-1/index.html?report=agent-chat#suite-agent-chat).
It tested `abacbdfd2f660709ec37312cdb758284c8399d04`; it is prior
evidence, not a paid run of this integrated head.
- Manual check: enable Agent Chat in Experimental settings, open an
agent, clarify and revise a plan, then hand off to an assigned project
task. Stop a reply, send `/new`, and verify fresh context with retained
history. Disable the setting and verify agent shortcuts/new chat turns
are blocked.

## Risks

- Queue/session integration can affect retries and delayed writes. Tests
cover ownership, cancellation, reset boundaries, idle recovery, and
ordinary task behavior.
- Migration 0274 adds conversation fields and constraints. Replay is
idempotent and preserves existing development chat history.
- This combines the previously reviewed stack at the maintainer's
request. Agent Chat remains off by default and is separate from
Conference Room.

## Model Used

OpenAI Codex, GPT-6 Astra (`gpt-6-astra`), with reasoning, code
execution, browser tools, and parallel review. The exact context-window
size is not exposed in this session. Codex and Claude also ran as test
subjects in the linked paid campaign.

## 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-09-12 08:56:04 -05:00