docs: keep the feature map focused on substantial features (#18767)

## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The feature map describes product capabilities and user journeys.
> - Small fixes and test changes have added long notes to that map.
> - These notes make substantial features harder to find.
> - This pull request removes those additions from the last week's
changes and sets a clear rule for future additions.
> - The benefit is a smaller map with stable capability IDs and accurate
entry points.

## Linked Issues or Issue Description

**Issue type**

Unclear or confusing documentation.

**Where is the issue?**

`maps/feature-map/`, the map maintenance instructions, and repository
rules.

**What's wrong?**

Between October 27 and November 3, 2026, 115 commits changed the feature
map. Many additions describe bug fixes, performance details, small UI
changes, or new tests. They do not introduce substantial product
features. The old synchronization instructions also encouraged a map
edit for every behavior change.

**Suggested fix**

Add a rule that requires a substantial new feature before expanding the
map. Remove minor-update notes. Keep genuine feature additions and
minimal corrections to existing instructions. The review covers master
through `b22ef22d56`; it does not revert application code. Conflict
resolution preserves later map changes from master outside that audit
snapshot.

Searched open GitHub PRs and issues for related feature-map work. No
duplicate cleanup was found. Substantial feature additions retained here
include Coordinator (#17983), the agent YAML editor (#18036), document
image galleries (#18157), remote workspace storage (#18403), native Kimi
(#18391), proactive chat messages (#18374), and the Sentry receiver
added in #18714.

## What Changed

- Add `rules/feature-map-scope.mdc` and register its `maps/**` scope
with Greptile.
- Align `AGENTS.md` and the shared map contract with that rule. Routine
fixes and test changes no longer require incidental map edits.
- Remove 755 net lines from 23 feature recipes. Preserve all 35 areas
and 192 capability IDs.
- Keep substantial features and the corrections needed for current
navigation, provider availability, and access boundaries.

Examples from the reviewed changes:

| Removed or shortened addition | Why it does not need a feature-map
expansion |
| --- | --- |
| Rounded composer image thumbnails (#18689) | Small UI change within
existing task creation. |
| Connection profile reads and review-count queries (#18687, #18688) |
Performance details within existing app permissions. |
| Warm-session, Retry, export-capacity, and tool-wait cases | Regression
details for existing execution and recovery. |
| New task-search, project-context, document-persistence, and routine
test journeys | Test additions for existing capabilities. The tests
remain in place. |
| New task button placement (#18703) | Another entry to an existing task
form. |
| Local browser verification notes | Run evidence belongs in the PR or
test report. |

## Verification

- `node scripts/check-maps.mjs` passes: 35 areas, 192 capability IDs,
valid references and contract fields.
- `node scripts/storybook-catalog.mjs` passes: 328 files and 3,068
stories. Generated indexes remain ignored.
- Compared capability keys and navigation metadata in every edited
recipe with the original source. All are unchanged.
- Checked rule frontmatter, Greptile registration, representative scope
matches, and `git diff --check`.
- `pnpm -r typecheck` and `pnpm build` pass on
`9a60eef8eb8da9bc7c3a02203c79bec12e8c8b6b`. The final
`a0801e8a939494ecde3739097a80258917428e94` commit only corrects two
lines in the plugin-panel recipe; map and catalog checks pass again.
- Greptile reviewed the final `a0801e8a939494ecde3739097a80258917428e94`
head at 5/5 with no findings. The earlier review found one inaccurate
phrase about unavailable plugin panels. The hook confirms that readiness
gates automatic opening, while declared panels remain selectable. The
final documentation commit corrects that phrase and the thread is
resolved. Paperclip's refreshed review is advisory and remains queued.
- The earlier CI run failed two assertions: [server
4/12](https://github.com/paperclipai/paperclip/actions/runs/41634761842/job/125914173960)
counted three Anthropic identity calls instead of two in
`connection-management.integration.test.ts`; [chat
1/3](https://github.com/paperclipai/paperclip/actions/runs/41634761842/job/125914174257)
observed zero publications instead of one in the same-principal
endpoint-settlement case. Both exact tests pass locally on the rebased
head. This PR changes neither their source nor their expectations. These
failed results remain historical evidence.
- Final-head CI passed server 4/12 and all other suites except the first
[chat 1/3
attempt](https://github.com/paperclipai/paperclip/actions/runs/41637834618/job/125925926131),
which repeated the same zero-publication assertion. The browser gate
passed. The single failed-job retry was accepted for this unchanged head
in [workflow attempt
2](https://github.com/paperclipai/paperclip/actions/runs/41637834618/attempts/2).
[Chat 1/3 passed on that
retry](https://github.com/paperclipai/paperclip/actions/runs/41637834618/job/125933199635),
and the aggregate verification gate passed. Both required gates, `ci /
verify` and `ci / e2e`, are green on
`a0801e8a939494ecde3739097a80258917428e94`. The one retry allowance is
consumed.
- The first full local `pnpm test:run` attempt was interrupted before
completion so master could be rebased without changing source under
running tests. It is not a passing test result. Full current-head CI
remains required.
- No application code, tests, schemas, or lockfiles changed.

## Risks

- Low runtime risk. This change only edits documentation and review
guidance.
- Detailed regression instructions become less visible in the feature
map. Their tests and technical documentation remain available.
- Some additions mix a new feature with a small fix. Those blocks retain
the feature and shorten the incidental detail.

## Model Used

- OpenAI Codex, GPT-6 family, with reasoning, Git history inspection,
repository tools, and code execution. The session does not expose a more
specific model deployment ID or context-window size.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass — map, catalog,
capability-ID, and rule-scope checks; full Vitest limits are stated
above
- [x] I have added or updated tests where applicable — no new runtime
tests apply to this documentation change
- [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>
This commit is contained in:
DottaandPaperclip authored and GitHub committed 2026-11-03 07:16:37 -06:00
1 parent 17e8bd7735
commit a61cf38106
27 files changed
+119 -817

No files matched your search

+7
View File
@@ -20,6 +20,13 @@
"path": "rules/module-boundaries.mdc",
"description": "Module ownership, justification of shared contract changes, delivery scope, and verification across affected consumers."
},
{
"path": "rules/feature-map-scope.mdc",
"description": "Limit feature-map additions to substantial new user capabilities; avoid minor-update churn and keep factual corrections minimal.",
"scope": [
"maps/**"
]
},
{
"path": "rules/runtime-dependency-boundaries.mdc",
"description": "Dependency cost, responsiveness, and verification requirements for changed server, adapter, and runner execution paths.",
+5 -2
View File
@@ -183,8 +183,11 @@ scope, not proof that a live journey passed.
The sibling [agent access map](maps/agent-access-map/README.md) records APIs,
agent entry points and permission boundaries using the same capability IDs.
Follow [the map contract](maps/README.md): update affected entries when mapped
behavior or access changes, and run `node scripts/check-maps.mjs` after map edits.
Follow [the feature-map scope rule](rules/feature-map-scope.mdc): additions require
substantial new features. Routine fixes, polish, refactors, and test changes do
not require map updates. Follow [the map contract](maps/README.md) for minimal
corrections when existing entries become materially inaccurate, and run
`node scripts/check-maps.mjs` after map edits.
Its structural checks do not prove live behavior or authorization.
Storybook has a downstream [feature catalog](maps/storybook-map/README.md).
+6 -3
View File
@@ -136,9 +136,12 @@ context; source presence alone does not qualify this operation.
## Keeping the maps synchronized
When a change adds/removes a capability or changes its behavior, API, permission,
tool binding, CLI support, or work mode, update the affected companion and product
recipe as appropriate in the same change. Preserve IDs across renames where the
Add entries only for substantial new features under the
[feature-map scope rule](../rules/feature-map-scope.mdc). Routine fixes, polish,
refactors, performance work, and test changes do not require map updates. Correct
or remove existing text only when behavior or access changes make it materially
inaccurate; keep the correction local to the affected recipe or companion.
Preserve IDs across renames where the
capability is unchanged; update the affected cross-links together. Indexes discover recipes automatically. An API-only
change may update the companion without rewriting unchanged user instructions.
Update the corresponding chat scenarios when their request, assumptions or
-11
View File
@@ -47,17 +47,6 @@ Automated: [activity service](../../server/src/__tests__/activity-service.test.t
Manual: Find a known mutation by actor/resource and a known run by status. Change filters, load more, and follow the source links. Reload the chosen view and verify no company leakage or duplicate events. Inspect a routine run from its audit entry.
On a native workspace export failure's run page, choose **Inspect recovery**,
then **Inspect current source** on the matching action. Compare the recorded
failure with the current recorded-source identity. Inspection is read-only and
does not confirm provider termination or file preservation. Resolved retained
actions remain inspectable. The control makes no inspection request until used.
[Source/HTTP regressions](../../server/src/services/workspace-recovery-source.test.ts)
cover current identity, rejected policy, foreign/reused allocation, bounded
lookup, redaction and unchanged recovery state; [component regressions](../../ui/src/components/RunWorkspaceRecoverySurface.test.tsx)
cover explicit selection, loading, failure and identity-only success. These
checks do not establish recovery of a deployed task.
Case detail's **View in Audit** opens `/activity?entityType=case&entityId=<case UUID>`.
The Activity filters include **Cases** actions and **Case** entities; the Case
search accepts a UUID or human identifier such as `CAS-C1` (Enter or blur applies
-18
View File
@@ -33,10 +33,6 @@ Open `/chats`, choose an agent, or use `/chats/:agentRef` and its conversation s
With Coordinator enabled, the composer exposes the shared model/thinking-level picker for supported agents. The agent stays fixed in this control; switching agents remains in the chat header. Choices save as conversation overrides on send, preserving the agent's configuration. A first message creates the conversation before saving settings and submitting through the ordered comments endpoint.
Standing chats open with the latest 20 contiguous messages. Scroll upward to fetch earlier messages, answer receipts, and created tasks. The loading indicator stays in the thread; history failures offer an inline Retry while preserving the draft and reading position. Opening a chat does not fetch its lifetime comment, activity, or run history. Already observed messages survive live refresh and Back within the query-cache session.
Click an agent's name or avatar above a message or active turn to open that agent's overview in the current company. The identity keeps its existing appearance, with no underline on hover. Identities without an agent ID remain plain text.
Coordinator answer receipts from this conversation jump to the answer bubble without leaving chat. Answer updates from an execution task link to that source task and its decision context. Compact document links read “Open [document title] in the sidebar”.
### `project-handoff`
@@ -53,8 +49,6 @@ Preconditions: follow the [baseline](./README.md#before-driving-a-journey). Enab
### `agent-conversation`
Local browser recipe: [long-chat startup and scrolling](../../tests/perf/agent-chat/agent-chat-startup.spec.ts), with fixture and command details in the [performance README](../../tests/perf/agent-chat/README.md). It covers recent-only reveal, delayed and failed pages, Back, older comment links, and live refresh. Synthetic local data is not deployed acceptance evidence.
Automated: [chat landing](../../ui/src/pages/AgentChats.test.tsx) checks recent-chat routing; [conversation service](../../server/src/__tests__/agent-conversations.test.ts) covers persisted conversation behavior.
Automated: [proactive delivery](../../server/src/__tests__/agent-chat-messages.test.ts)
@@ -67,15 +61,6 @@ qualify live PR retrieval or a model's editorial choices.
Automated: [composer picker](../../ui/src/components/task-chat/ComposerRunSettingsPicker.test.tsx) covers fixed-agent model/effort selection on desktop and mobile; [composer](../../ui/src/components/task-chat/TaskChatComposer.test.tsx) covers Coordinator gating and settings submission without reassignment. [Task detail](../../ui/src/pages/IssueDetail.test.tsx) verifies canonical first/existing-chat IDs, settings-before-comment ordering, and no comment submission when settings fail to save. These tests mock the API and do not prove provider execution with the chosen model.
Automated: [conversation delivery](../../server/src/__tests__/agent-conversation-delivery.test.ts)
checks that paused or otherwise non-invokable agents leave comments pending
without aborting startup recovery, and that a later unpause allows one delivery.
The test persists queue admissions only; it does not start agents or providers.
Automated: [historical chat](../../ui/src/pages/AgentChat.test.tsx) keeps an older
conversation reachable after a cached roster refresh ends in HTTP 429. It checks
lookup Retry and preserves permission and company boundaries. This is component
evidence with real query state, not live provider proof.
Automated: [thread and composer](../../ui/src/components/TaskChatThread.test.tsx)
keeps an in-flight attachment through first-chat creation on desktop and mobile,
while initial history for an existing conversation stays deferred. The
@@ -88,7 +73,6 @@ send. Confirm the same file stays in the composer after the chat is created.
Send it once, reload, and confirm the file and message remain.
Manual: Start a conversation, send a recognizable request, and inspect its reply.
Click the responding agent's name, return with Back, then click its avatar; both should open that agent's overview without changing companies. Check that the identity looks unchanged at rest and on hover on desktop and mobile.
Navigate away and reopen the same history. Use `/new` for a fresh session within
the same standing conversation. Test an unavailable historical agent and an
inaccessible saved conversation; verify no cross-user or cross-company history appears.
@@ -136,8 +120,6 @@ Manual: Check disabled access first, enable in the disposable instance, then sen
## Gotchas
- Coordinator Markdown references to a standing agent conversation display “Chat with [agent]” and route to that chat, preserving anchors. Labels resolve once from the existing current-person/current-company chat list and agent roster; no task status glyph or task quicklook is shown for these references. Ordinary task links retain their existing treatment.
- Idle chat is not failed execution.
- See [steering](./steering.md) for in-flight messages and [questions](./questions-and-approvals.md) for interactions.
- An API tool test does not prove that every harness will choose the same handoff tool.
+7 -35
View File
@@ -34,15 +34,8 @@ Use New agent from the roster or `/agents/new`.
Submitting the name creates an inactive record before adapter selection or account setup.
A name-only draft returns to adapter selection when reopened.
Save & exit keeps its configuration; Finish setup on the agent returns to the
same record. Open an unfinished agent from the roster to reach its header.
The header shows Finish setup instead of Run or Resume, including during computer
preparation and verification. Terminating agents cannot reopen setup. Final
submission requests approval when required, then follows the existing preparation
and verification lifecycle.
The confirmation shows **Finishing agent setup** until the foreground detail
query observes actual readiness. **Assign a Task** then hands that current
record to the composer, so its status does not come from an older paused draft.
Manual/import pauses and required hire approval remain blocking states.
same record. Final submission requests approval when required, then follows the
existing preparation and verification lifecycle.
When the native Runner adapter is available, **Google Antigravity** appears in the ordinary
adapter picker. Before runtime acceptance, its card says **Not available yet**.
@@ -64,16 +57,6 @@ Test verifies native account/model admission and cleanup without a model turn.
Other companies, remote targets, expired authority and other models stay blocked.
Verify this scoped path separately from production qualification and real task acceptance.
The explicit-only [Antigravity agent journey](../../tests/runner-e2e/ANTIGRAVITY-AGENT-JOURNEY.md)
protects the ordinary roster/picker path, saved personal Google subscription,
native Test, actual ready handoff, Instructions-only file marker, task and
same-task follow-up. Its fixed driver starts from the dashboard and creates the
new agent through visible controls. The current runnable cell attaches to a
self-hosted target with the admitted local macOS ARM64 candidate and exact low
model. Saved-account reuse does not qualify fresh OAuth, other platforms or
global provider release; registration and synthetic controls are separate from
the retained exploratory and fresh fixed-driver results.
Agent-owned plugin environments prepare the saved draft in the background when
their driver declares `requiresAgent`. The draft waits in `verifying` with its
setup hold until hiring finishes. Changing environments keeps the selected
@@ -151,9 +134,8 @@ replacement confirmation. The Chat agent picker opens a conversation; it does
not set the person's primary preference. This guidance grants no agent write
authority.
Open an agent profile and choose the outlined crown beside its name (**Set as my
primary**). Inspect the filled crown on the profile, the crown on the roster and
its position in the Agents sidebar, then open a new task or Chat.
Open an agent profile and choose **Set as my primary**. Inspect its crown on the
profile/roster and its position in the Agents sidebar, then open a new task or Chat.
### `agent-api-keys`
@@ -175,9 +157,6 @@ For an agent-owned plugin environment, verify preparation before connecting,
same-agent probes, account preservation after an environment change, failed
selection-save retry, and switching back while the computer stops. Confirm the
setup hold still blocks ordinary work and API key creation before finishing.
Start through the name/adapter dialog with a managed-only or forced Kubernetes
policy and a draft that inherits its environment. Once preparation completes,
confirm the auth choices, Advanced gateway, and saved subscription remain usable.
The [setup lifecycle tests](../../server/src/modules/agent-lifecycle/__tests__/setup.test.ts)
exercise durable transitions with synthetic plugin resources; they do not prove
live VM provisioning.
@@ -235,9 +214,7 @@ Manual: Save a harmless instruction edit, reload, and verify its revision and ef
For failed setup, use an unavailable model or invalid command on a disposable agent.
Confirm the profile names the failed verification step and gives a relevant action.
Check that a failed configuration test explains that automatic verification is paused
and offers **Retry now**. Repeated refreshes must not start another test. Timeouts
and temporary test-environment failures still retry automatically. Fix the configuration,
Check that it explains that verification is paused and offers **Retry now**. Fix the configuration,
retry, and reload; the failure must disappear only after readiness commits.
Provider output and credentials must not appear in the lifecycle message.
@@ -254,10 +231,6 @@ pending edits and an environment-variable draft. An unsaved change to a differen
effective computer must disable the action and explain that the computer change
must be saved first; restoring the saved target must re-enable it. Reopen the page and compare the
saved harness, model, account bindings, instructions, and run policy. Check a
Grok upgrade with an unset or `grok-build` model: it must use `grok-4.7`.
Compare effective search policy before and after, including the implicit disabled
default and explicit enabled search. Verify task model and effort changes use the
Grok catalog and reach execution while retaining the account and search policy. Check a
saved `maxTurnsPerRun: 1000`: upgrade must warn and remove it. Test an initially
unqualified Daytona Paperclip Computer: click must probe, record qualification,
refresh availability, and only then save. A failed probe or changed selection must
@@ -294,10 +267,9 @@ Manual: Inspect a manager and report, change the relationship through the offere
### `personal-primary-agent`
Automated: [primary-agent context](../../ui/src/context/PrimaryAgentProvider.test.tsx),
[the profile crown](../../ui/src/components/primary-agent/PrimaryAgentPresentation.test.tsx)
Automated: [primary-agent context](../../ui/src/context/PrimaryAgentProvider.test.tsx)
and [primary-agent routes](../../server/src/__tests__/primary-agent.test.ts)
cover selection, replacement confirmation, company/user scope, and request contracts.
cover selection, company/user scope, and request contracts.
Manual: Select an available agent, reload, and inspect the retained personal choice.
Replace it and verify confirmation is required. Leave or terminate the selected
-36
View File
@@ -27,12 +27,6 @@ that new approval before execution. Retries of the declined intent and its
rejection continuation remain declined. Missing or untrusted human provenance
does not open another review.
Changing the connection's agent list preserves profile assignments for agents
that remain installed. Saving the list must not restore a removed app-profile
assignment. New installations retain the current app-profile defaults.
Non-empty saves also remove legacy connection-wide include rules, including
unchanged lists and removals with no new targets.
## How to get to it (user POV)
### `permissions`
@@ -56,18 +50,8 @@ Preconditions: follow the [baseline](./README.md#before-driving-a-journey). Prep
### `permissions`
The page loads saved profiles for the displayed connection through the configuration read. It preserves complete app bindings for saves and the install fallback when bindings are empty. It does not request profile summaries or pending-review counts.
Automated: [app detail](../../ui/src/pages/apps/AppDetail.test.tsx) covers agent/action controls, quarantined actions, and navigation using mocked requests.
[Installation permission regressions](../../server/src/__tests__/tool-connection-installs.test.ts)
exercise the real install API with a local operator and PostgreSQL. They check
that adding, removing, or retaining agents preserves removed app-profile grants
and denies write tools for agents with read-only profiles. They also check
company installations, new-agent defaults, legacy connection-wide include
cleanup, and access-extension audit records.
These fixtures do not qualify an agent-authenticated request or a live provider.
[Runtime assignment tests](../../server/src/__tests__/agent-runtime-assignments.test.ts)
use PostgreSQL to verify committed assignment notifications, bounded snapshots,
rollback, and concurrent AI adoption. The owning lifecycle plugin can read
@@ -106,20 +90,6 @@ still need live account qualification.
Automated: [app detail tests](../../ui/src/pages/apps/AppDetail.test.tsx) cover test-dialog/UI contracts. Real provider execution and revocation require the selected provider’s live check.
AI account details share the Permissions page's grants query. Account and grants
reads have a 15-second deadline. The AI panel retries a transient failure once,
then shows an error with Retry. A background failure keeps loaded controls visible.
[AI account loading tests](../../ui/src/components/ai-connections/ManagedAiConnectionDetails.test.tsx)
exercise stalled account/grants reads, cancellation, retry recovery and cached grants.
The account-details section shows the provider email and organization when
available, beside the sign-in method and Paperclip ownership. Anthropic profile
permission denial shows an explicit unavailable message without changing the
connection's connected state. Account identity loads independently of maintenance
controls, has a bounded wait and a separate retry for temporary failures, and
is refreshed after a credential grant changes. [Account-details tests](../../ui/src/components/ai-connections/AiConnectionAccountDetails.test.tsx)
cover these states and prevent one grant's email from appearing for another.
Manual: Run a read-only action with explicit inputs and inspect returned data and activity. Refresh discovery and review new actions. Revoke or disconnect only the disposable credential, then verify subsequent use fails with an actionable reconnect state.
For Daytona, opening an older saved catalog discovers the current native
@@ -169,9 +139,3 @@ Sources: Source: [PermissionsPanel.tsx](../../ui/src/pages/apps/app-detail/Permi
### `delegated-configuration`
See the canonical [delegated configuration guidance and acceptance evidence](connection-setup.md#delegated-configuration).
The contextual connection sidebar reads only the selected connection's pending
signed action request and quarantined action counts. Its Review badge is the
pending request count plus one when any action is quarantined. It refreshes every
30 seconds and after existing attention invalidations. Archived connections show
no badge. The full Apps attention view keeps its existing company-wide read.
+7 -55
View File
@@ -29,14 +29,12 @@ Message the configured bot/address from its external provider and follow the cor
### `endpoint-management`
Delegated setup can save ordinary bot tokens and API keys. Provider verification keys require the addressed human credential-entry step or verified provider provisioning. Generic setup returns the saved handoff without changing those keys, and generic connection updates cannot replace channel credential references. A replacement card waits for an actual protected-value change and restored verification; old health, unchanged entry and unrelated bot-token repair do not complete it. Fresh GitHub handoffs open the import form; configured endpoints retain reconnect. Credential-entry field sets and completion modes stay distinct while matching retries reuse their saved baseline. Complete human replacements can repair disabled, deleted or unreadable old vault values. Saved links name the requested fields and completion mode; configured GitHub forms support targeted replacements while keeping other saved credentials. Provisioned Slack challenge proof survives runtime storage only for the same signing key and callback URL. The actual-auth Slack/GitHub fixtures cover these boundaries, retries, revocation and permitted bot-token repair; live provider repair remains separately qualified.
Delegated setup can save ordinary bot tokens and API keys. Provider verification
keys require the addressed human credential-entry step or verified provider
provisioning. Open the saved setup link as that person to complete the request.
Open `/apps/chat/:endpointId/settings` and the endpoint’s other available tabs; identity confirmation uses `/chat-identity/confirm`.
For GitHub external contributors, open the connection's Access tab and look up a username. The lookup uses that endpoint's active GitHub App installation with a metadata-only token. Verify that a person or bot resolves to its numeric identity and that unavailable accounts, rate limits, and installation failures show distinct errors. [Lookup regressions](../../server/src/services/chat-github-management.test.ts) use provider fixtures; live installation lookup remains separate evidence.
For delegated Slack test messages and identity invitations, apply a Block or Ask first rule to the calling agent while allowing the endpoint's assigned agent. Verify no message is sent. Exercise caller, target and shared rate limits: one shared quota admits one send and the next distinct request is denied. For a saved GitHub identity handoff on an otherwise healthy endpoint, verify the card stays pending before identity confirmation and after an OAuth callback alone. Confirm the addressed user's identity through their human session, then verify continuation becomes available. Revoked, expired, wrong-user and wrong-installation links must keep the handoff blocked. These cases pass through the assembled API with real key/JWT/session middleware and deterministic providers; live Slack/GitHub consent remains separate evidence.
### `outbound-agentmail`
Use `paperclipai email inboxes --company-id <company-id>`, then `email send --company-id <company-id> --file <new-email.json>` or `email reply --company-id <company-id> --file <reply.json>`. Inspect `email thread <email-task-id> --company-id <company-id>` and `email delivery <publication-id> --company-id <company-id>`. Agent mutations must provide --run-id or the active PAPERCLIP_RUN_ID.
@@ -49,17 +47,6 @@ AgentMail bypasses the chat-connectors UI gate, GitHub uses
`enableGitHubReviewBots`, and other chat providers use `enableChatConnectors`.
Setup is covered in [connection setup](./connection-setup.md).
For managed Slack setup, resume a saved draft with an authorized workspace and
choose Continue. Verify it creates and installs the bot once. The HTTP route
must resolve the selected Slack manager grant, reject malformed or missing IDs,
and deny another company's or person's grant before provider calls. The channel
integration suite exercises this route with a board fixture and provider fixtures;
live Slack setup remains a separate acceptance check.
After welcome delivery completes setup automatically, verify **Open Slack**
remains on Success and on the saved connection page. Follow that visible link,
send a real DM and thread follow-up, then reload the catalog to confirm setup
stays complete. A welcome message alone is not an agent response.
### `external-thread`
Automated: [channel integration](../../server/src/__tests__/chat-channels.integration.test.ts) uses provider fixtures; it does not prove a live Slack, Discord, Teams, Telegram, GitHub, email, or Photon delivery.
@@ -195,23 +182,14 @@ provider responses. Verify actual credential validity and restored delivery
separately against GitHub; a Storybook success does not establish live recovery.
For an agent-requested GitHub credential handoff, open the saved link as the
addressed human and verify it asks for exactly the requested fields and all/any
completion mode. A fresh App opens import; a configured App opens replacement
through reconnect and retains credentials omitted from the request. Interrupt
the response after a successful rotation, reload, and verify the saved rotation
resumes without replacing the key again. Wrong-user access, unchanged credentials
and missing verification must not complete the request. After OAuth, confirm the
addressed user's exact endpoint identity before expecting task continuation.
addressed human. A fresh App opens import; a configured App opens replacement
through reconnect and retains credentials omitted from the request. Complete
the requested credential entry and confirm the endpoint identity before
expecting task continuation.
For GitHub, submit a disposable PR and verify the summary heading uses the bot's
display name and the check remains **Paperclip Review**. For two separate bots on one PR, verify
their App-scoped checks and comments remain independent.
For a newly configured bot, verify `submit_review` describes body-only summary
and rationale fields. Submit a summary with repeated current-bot or legacy
score headings, including an old score; verify publication keeps one heading
with the structured score, preserves findings and rationale, and retains the
original assessment. The PostgreSQL-backed publication fixture covers this with
simulated GitHub responses; live model compliance remains separate evidence.
For GitHub publication recovery, interrupt a response after GitHub accepts a
write and verify one summary, finding, and App-scoped check. Retry the same tool
@@ -289,32 +267,6 @@ After successful admission, reload and verify that the prior skipped receipt doe
not strand a later real provider reply or tree resume. Provider fixtures support
this behavior; live fixed-source runtime and destination proof remain separate.
Also complete an older review successfully while a newer authorized PR event
remains deferred. Use Retry and verify that the existing saved-input receipt
starts exactly one new turn, repeated clicks share that turn, and the older
accepted result remains unchanged. Revoke the connection or change the source
binding before dispatch and verify no run starts. Keep prior cleanup pending,
then settle it and verify the same receipt resumes once. These database-backed
provider fixtures do not establish live GitHub publication at the fixed revision.
Also defer Retry behind cleanup, queue an independent board message, then
complete cleanup. Verify one run receives the exact GitHub batch and the board
message enters its own turn. For an older mixed batch rejected before provider
startup, ordinary task Retry must recover only certified undelivered receipts.
Changed input, active ownership, allocations and prior delivery must keep the
refusal effective. Check the restoration audit and unchanged failed-run history.
### `delegated-configuration`
Endpoint activity hides private-task events while retaining a next-page cursor across private-only windows, so older readable history stays reachable. Actual-JWT fixtures verify this separately from live provider delivery.
See the canonical [delegated configuration guidance and acceptance evidence](connection-setup.md#delegated-configuration).
GitHub finding category contract (2026-10-31): manual and automatic review
instructions list the repository policy categories. `begin_review` returns the
assessment snapshot's `findingCategories`; later settings do not change that
snapshot. Submit an unknown category and confirm rejection before publication,
then submit a listed custom category and inspect the saved assessment and
processed publication. The channel integration fixture covers real PostgreSQL
and the service path with simulated GitHub HTTP; live model behavior remains
unverified.
-12
View File
@@ -253,18 +253,6 @@ remain. Complete the step, verify the exact task continues, and confirm that
revoked authority or cancelled work prevents continuation. An ordinary bot-token
repair or an unchanged credential must not complete a signing-key request.
For Google, request a specific service set, leave and reopen setup, and inspect
the addressed user's pending choices. Another user's or organization grant must
not supply those choices. A newer actual consent supersedes the saved request;
a token refresh does not. A failed grant read must not broaden the selection.
For Vercel personal setup, verify the selected credential belongs to the
responsible person and new bindings record the configuring human as creator.
Agent-initiated API changes retain the acting agent in audit; the human callback
retains its actual human actor.
Use the [chat endpoint recipe](chat-channels.md#endpoint-management) for GitHub
field-specific credential entry and saved rotation recovery, and the
[model-account recipe](runs-adapters.md#managed-account-setup) for AI sign-in.
## Gotchas
- For connecting an assistant to Paperclip itself, use [Assistant connections (MCP)](./assistant-connections.md). This recipe's MCP-link journey connects Paperclip to an external app server.
+2 -29
View File
@@ -28,12 +28,8 @@ Open a document from the task thread or document side panel.
To create or edit a general task document, open **Open a new tab → Artifacts**
in the task side panel, then **New document** or **Document actions → Edit
document**. Edits use the shared versioned editor and autosave. Classic mode
keeps that editor in the task body. Plans retain their conversation and approval
flow and cannot be created through the general document editor.
Unfinished new documents, including a body typed before its key, survive a tab
switch or reload within the same account and task. Cancel removes the backup;
a confirmed creation clears it.
document**. Classic mode keeps the editor in the task body. Plans retain their
conversation and approval flow.
Select an inline image to open the document's image gallery. Use the left and
right arrow keys or the Previous and Next buttons to move through images in
@@ -63,15 +59,6 @@ Open `/artifacts` and its grouping, search, and media controls.
## Driving it with Playwright and the Paperclip CLI
The explicit `build-revise` [Product journey](../../tests/runner-e2e/PRODUCT-JOURNEYS.md) covers `documents-artifacts/attachments`: browser downloads of two ZIP versions, an independent content oracle, and preservation of the original. Its shared source is not proof of a pass on any deployed target.
The explicit `task-document-persistence` journey covers `documents-artifacts/documents`:
browser creation and editing, task reopen/reload, exact saved title/body and
independent original/latest revision reads, board-user authorship and zero agent
runs. The setup owns a backlog task but does not seed a document. Calibration
rejects stale content, lost history and foreign ownership. A target needs a fresh
live pass before adding this journey to its scheduled checks.
Preconditions: follow the [baseline](./README.md#before-driving-a-journey). Use a task with a text document, a small attachment, and a generated work product. Use nonsensitive fixture files.
### `task-document`
@@ -94,18 +81,6 @@ Manual: Edit a paragraph, save, reload, and compare revisions. Add an annotation
Automated: [attachment routes](../../server/src/__tests__/issue-attachment-routes.test.ts) and [work products](../../server/src/__tests__/work-products.test.ts) cover data/access behavior; [artifact arrival browser suite](../../tests/e2e/artifact-tab-arrival.spec.ts) targets arrival. [Artifact uploads](../../tests/e2e/artifact-uploads.spec.ts) drives file selection/drop, filename collisions, retry, and preservation of paused/unassigned tasks.
The deployment-targeted [uploaded-input journey](../../tests/runner-e2e/product-journeys/input-file-flow.ts)
adds composer upload, real agent consumption, independent calculation, attributed
saved output and reload checks. Registration and oracle controls do not establish
a live pass on a deployment.
[Native completion feedback](../../server/src/services/native-runtime/native-completion-feedback.test.ts)
checks a real saved-document link alongside a verified CSV attachment, including
attachment download query and fragment links. It rejects foreign task/company
links, missing documents, unproven current revisions, and workspace files. The
document alone cannot satisfy the requested file. These local tool/Postgres
checks do not establish hosted delivery or browser rendering.
Manual: Upload a small Markdown file and CSV through Artifacts. Markdown becomes
a versioned task document; other files become attachments. Read the document,
download the CSV and compare bytes, then reload. Upload the same Markdown filename
@@ -122,8 +97,6 @@ Manual: Find the task’s output through search and grouping, open its stack, pa
## Gotchas
- In Coordinator, saved plan cards use document chronology, so a plan written before its output appears first even when both writes share one native run. Authored issue-document links use the same compact sidebar-link surface and retain revision/annotation targets. Classic run embedding is unchanged. The UI does not remove or deduplicate canonical plan content.
- A local path is not automatically an uploaded artifact accessible to another user.
- A preview screenshot is not proof that download bytes or revision references are correct.
- Version conflicts and stale annotations must stay visible rather than silently targeting different content.
+6 -30
View File
@@ -53,14 +53,9 @@ and its diagnostic in the probe result: connection success alone does not mean
the image has native runtime qualification.
Paperclip-managed Cloud images use the current platform-selected image without
a saved qualification prerequisite. A missing, stale or revoked qualification
does not block execution or pin an older snapshot. Runtime startup and the
handshake detect real incompatibility. This exception excludes custom
environments and active captured custom images.
The active Cloud configuration must provision the sandbox provider. A stale
managed marker alone keeps the normal qualification rules.
An outdated captured image that execution ignores must not block discovery of
the current managed image. A matching custom capture keeps qualification.
a saved qualification prerequisite when the active Cloud configuration provisions
the sandbox provider. Custom environments and active captured custom images
retain qualification requirements.
For other images, the measured record is server-owned, company-bound and tied to the effective
configuration and active custom-image identity. Mutable tags, provider defaults
@@ -81,11 +76,6 @@ qualification is not reused. A mutable-image connection can succeed while
qualification remains absent. Assert ordinary agent and non-admin board probe
requests are denied, and environment create/PATCH payloads cannot supply
qualification metadata.
For a managed Cloud image, replace the platform-selected snapshot while an old
qualification remains. Discovery must still offer Paperclip Runner, and Test
must check the runtime directly. Verify execution selects the replacement image
and still reports a real provider startup failure. Keep a custom-image control
that requires its existing qualification.
This recipe and its [probe controls](../../server/src/__tests__/environment-probe.test.ts)
are not claims that a live provider or agent-access journey ran for this map update.
@@ -105,11 +95,9 @@ data transfer is outside task execution. See the
The [fake-provider integration](../../server/src/__tests__/plugin-runner-task.integration.test.ts)
checks acquisition, SDK dispatch, scope denial, stop proof and deletion recovery.
Its WebSocket is mocked; it does not qualify a live provider or a real Runner handshake.
Controller replacement reuses a surviving plugin task's active lease and exact
Runner identity. The integration checks reconnect without prepare, submit, or
stop. The [continuity recipe](../../doc/testing-native-remote-continuity.md#replacing-the-main-server)
also covers real-process recovery after controller files are removed; deployed
plugin and Daytona acceptance require their own evidence.
Controller replacement reuses a surviving plugin task's active lease and Runner
identity. Follow the [remote continuity recipe](../../doc/testing-native-remote-continuity.md#replacing-the-main-server)
to verify recovery across main-server replacement.
For a same-run retry on a replacement plugin task, verify that the retained
checkpoint loads before provider startup. The prior execution must have a stop
@@ -142,10 +130,6 @@ uses the real Runner and a synthetic Codex provider through loopback PRP; TLS
termination is replaced by the fixture. It does not qualify a live plugin provider.
The plugin prepares execution-host resources and the provider descriptor. Core validates the result, then supplies task identity and PRP launch limits.
For managed GitHub commands, verify the qualified executable remains canonical,
controller-staged helper discovery survives task entry, and a task-supplied shell
selector is rejected. A launch description or a healthy Runner alone is not proof
of authenticated git/gh execution.
### Storybook verification
@@ -189,11 +173,3 @@ Managed account transfer requires `projectAuthCheckVersion: 1` and a successful
`check_project_auth` result for the exact prepared configuration, provider, and
project set. New preparation removes old validation. Core checks the saved
validation again in the dispatch update.
Plugin task providers can advertise `githubCredentialBrokerVersion: 1` and receive
a live-run capability during preparation. This adds no agent management API.
Core resolves accepted identity, grants, company scope and trust at command time.
The plugin owns the command implementation; no particular script is required.
[Broker handoff coverage](../../server/src/services/native-runtime/plugin-runner-task.test.ts)
checks capability changes across warm turns. This is contract coverage, not live
authenticated push acceptance.
+1 -25
View File
@@ -67,13 +67,6 @@ Preconditions: follow the [baseline](./README.md#before-driving-a-journey). Seed
Automated: [archive routes](../../server/src/__tests__/inbox-archive-routes.test.ts) cover server mutations. [Task-list helpers](../../ui/src/pages/Issues.test.tsx) cover search URLs, pagination, and presentation constants; they do not render the combined Inbox/Tasks page. Reading, archiving, and navigating that page remain manual checks.
The deployment-targeted [personal-triage journey](../../tests/runner-e2e/product-journeys/inbox-triage-flow.ts)
drives Mark as read and Archive, reloads Unread and Mine, independently verifies
unchanged task status, and observes a later Blocked transition resurface the item.
It uses one owned self-assigned task and no agent work; its registration is
separate from a measured Cloud pass. Other actors and company boundaries remain
separate verification cases.
Automated: [Issue service regressions](../../server/src/__tests__/issues-service.test.ts)
cover exclusion of historical automatic read cleanup from user participation,
unread counts, and activity timestamps while retaining explicit user decisions
@@ -98,22 +91,7 @@ Cold-open verification: load Mine with the task-index response delayed while
approvals/runs resolve. Only the stable list placeholder should appear until the
initial sources settle; a failed-run row must not jump when tasks arrive. Release
visible-row details separately and compare row/title bounds. Mine reads its own
100-row index. Missing parents use the same index projection for their captions;
parents already in the index are reused. Failed-run tasks still load rich row
context by ID, including when they are also parents or already indexed, so resolved
interruptions stay hidden. The initial reveal waits for both context sources.
Sidebar badges use the count endpoint.
Coordinator desktop and mobile navigation share `/attention/summary` for the
outstanding count. Needs You owns its complete feed; Tasks → Needs attention
owns a compact complete task-ID index. Navigation reuses either page response. Coordinator keeps the optimized Inbox even when
the instance Streamlined UI setting is off. The loopback browser checks in
[collection startup](../../tests/perf/collections/startup.spec.ts) exercise these
reads and the initial task row budget. They do not establish deployed latency.
Collection startup selects the addressed active organization before starting
company reads. Shared controls load separately from task detail. A painted
collection or task-link intent starts a low-priority code fetch; direct task URLs keep
early module preload. The collection
browser cases cover a remembered different organization and failed speculation.
100-row index, with parent/run context by ID; sidebar badges use the count endpoint.
The [Inbox component checks](../../ui/src/pages/Inbox.test.tsx) cover the source
barrier and selected-source query; [badge tests](../../server/src/__tests__/inbox-dismissals.test.ts)
cover unread counts. Browser timing and layout proof remain separate from these tests.
@@ -210,5 +188,3 @@ Scope: ui
Storybook: Eligible live task toast, explicit mention, quiet unrelated event, own-action/visible-task suppression, dedupe and company/account switch.
Production: Persisted participation and mentions determine per-viewer socket eligibility; quiet events still refresh caches; reload retains eligibility, unauthorized resources remain denied.
Sources: Source: [ToastViewport.tsx](../../ui/src/components/ToastViewport.tsx), [ToastContext.tsx](../../ui/src/context/ToastContext.tsx), [LiveUpdatesProvider.tsx](../../ui/src/context/LiveUpdatesProvider.tsx), [task-toast-eligibility.ts](../../server/src/realtime/task-toast-eligibility.ts). Tests: [ToastContext.test.tsx](../../ui/src/context/ToastContext.test.tsx), [ToastViewport.test.tsx](../../ui/src/components/ToastViewport.test.tsx), [LiveUpdatesProvider.hook.test.tsx](../../ui/src/context/LiveUpdatesProvider.hook.test.tsx), [task-toast-eligibility.test.ts](../../server/src/__tests__/task-toast-eligibility.test.ts), [live-events-toast.test.ts](../../server/src/__tests__/live-events-toast.test.ts), [multi-user-authenticated.spec.ts](../../tests/e2e/multi-user-authenticated.spec.ts)
Coordinator navigation counts all outstanding canonical attention items on desktop and phone, using the same complete feed as Needs You. Classic keeps its existing today-oriented badge. Task questions resolve through their original interaction; pending chat projections, counts and recorded receipts invalidate together.
+1 -30
View File
@@ -67,27 +67,8 @@ served by the admitted application before it finishes. Repeat with a disconnect
before headers arrive. Confirm that neither leaves a permanent request hold. An
unfinished application write must still prevent sleep after its client leaves.
Automated: [historical cleanup](../../server/src/__tests__/historical-cleanup-verification.test.ts)
exercises the runtime inspection path for failed Cloud sandbox leases, including
verification leases without a run. A signed cleanup-only absence observation
can remove this blocker without changing failed outcomes or granting run
continuation. An unresolved provider resource still prevents idle sleep.
Manual: on an owned Cloud staging workspace, confirm the exact published build,
reconcile failed test allocations, then verify actual provider suspension and
normal hosted entry after wake. Local tests do not prove that hosted journey.
### `settings-backup`
Cloud startup reads nonsecret application choices from a private, versioned
PostgreSQL singleton after a bounded one-time legacy config seed. A fresh
process and different home restore the saved choices without consulting a stale
`.env` file. Invalid saved data or an unavailable database prevents startup;
saved telemetry opt-out applies before client creation. The
[database controls](../../server/src/__tests__/cloud-runtime-config.test.ts) and
[startup-order controls](../../server/src/__tests__/server-startup-feedback-export.test.ts)
cover these local boundaries. See [field ownership](../../doc/cloud-runtime-configuration.md).
These controls do not qualify a deployed Cloud rollout or durable file storage.
Automated: [experimental settings](../../ui/src/pages/InstanceExperimentalSettings.test.tsx) and [database backup routes](../../server/src/__tests__/instance-database-backups-routes.test.ts) cover their UI/API contracts.
Cloud migration: in one maintenance window, stop legacy file writers and run the
@@ -100,16 +81,6 @@ configuration/packages and does not qualify whole-server zero downtime, secret
bytes, or volume removal. [Local PostgreSQL evidence path](../../server/src/__tests__/cloud-configuration-migration-postgres.test.ts)
includes a real fixture worker; it does not establish a hosted replacement.
Managed adapters: change a visible adapter preference as an instance admin,
then use a second application process against the same disposable database to
confirm catalog and new-agent selection reflect it. Verify saved agents remain
usable. Restart with an operator adapter declaration, confirm its effective
list, and reject conflicting toggles. Remove the declaration and confirm saved
preferences return. [Database tests](../../server/src/services/adapter-settings-postgres.test.ts)
cover local persistence, concurrent writers, audit rollback, and failure responses;
[local compatibility tests](../../server/src/services/adapter-settings-local.test.ts)
cover the legacy file. No deployed walkthrough is claimed.
Manual: Change a harmless experimental setting, reload, and confirm the affected route honors it. Back up a disposable instance, inspect the reported file and metadata, and restore using the documented procedure into a second isolated target. Verify a known record after restoration.
Cloud staging: On a managed `*.staging.paperclip.app` instance, verify experiments
@@ -181,5 +152,5 @@ Capability ID: `instance-operations/diagnostics`.
Scope: cli
Storybook: No authored story required for doctor/health command results.
Production: Run doctor against an owned data directory; check readiness and nonzero failures. Instance operators can inspect `GET /api/instance/task-drain?upgradeReadiness=1` before a compatible app replacement. Verify that unknown or unsupported executions prevent readiness and that the read does not hold admission; separately prove same-run continuity through an actual upgrade. A listening port alone does not prove readiness; repair requires observing the repaired result.
Production: Run doctor against an owned data directory; check readiness and nonzero failures. A listening port alone does not prove readiness; repair requires observing the repaired result.
Sources: Source: [doctor.ts](../../cli/src/commands/doctor.ts). Tests: [doctor.test.ts](../../cli/src/__tests__/doctor.test.ts)
+2 -12
View File
@@ -112,9 +112,6 @@ to the existing Agent Chat control. Hidden or Cloud-managed controls are not
presented as editable. Disabled Chat routes link back to Experimental settings.
Enabling the personal workspace never changes the instance capability.
The Coordinator sidebar has a visible **New task** button above **Chat**. It opens
the existing task form and retains the shortcut beside **Tasks**.
Automated: [preference hook](../../ui/src/hooks/useCoordinatorWorkspaceEnabled.test.tsx),
[prerequisite settings card](../../ui/src/components/CoordinatorWorkspaceSetting.test.tsx),
[authorization](../../server/src/__tests__/workspace-preferences-routes.test.ts), and
@@ -125,15 +122,8 @@ choice. The [Settings card story](../../ui/storybook/stories/navigation-preferen
uses the production component with simulated API responses; it does not establish
real persistence or permission behavior.
Local browser verification (2026-10-26, isolated Coordinator worktree): initially
off, enabled and persisted across reload, disabled back to classic navigation,
then enabled back to Chat / Tasks / Needs You. This used `local_trusted`; signed-in
two-person browser isolation remains unverified.
Coordinator More exposes a pin/unpin button beside every destination. Each flyout
row highlights as one surface; its pin appears on row hover or keyboard focus.
Opening the flyout focuses its container so Search is not highlighted before
interaction. Pinned pages appear beneath More in pinning order and retain the
Coordinator More exposes a pin/unpin button beside every destination.
Pinned pages appear beneath More in pinning order and retain the
existing company-aware routes.
Unpin from either the flyout or the pinned row. The list is personal to the current
user in this browser, shared across companies; it does not sync across devices.
+2 -59
View File
@@ -37,18 +37,8 @@ the unprefixed route starts at organization naming on self-hosted instances.
Cloud-managed instances reuse their existing company for agent setup.
First-agent onboarding offers only Claude and Codex, subject to instance adapter
availability. GitHub Copilot and other providers remain available through Add
agent after onboarding. A saved draft for another provider requires a new choice.
Old Copilot drafts discard the retired selection and model, including when both
onboarding providers are disabled. The wizard no longer contains Copilot setup
UI, connection state, or model discovery; later Add agent retains that support.
Changing an unavailable saved provider clears its model. If both first-onboarding
providers are unavailable, the wizard explains how to enable one or use New Agent
from the Agents page for another provider.
Claude and Codex are harness choices, not a forced legacy runtime. Automatic
runner selection uses the execution environment's qualified native runner and
falls back to legacy on native Windows without changing the onboarding UI.
Windows should default to native when its runner platform support is qualified.
availability. Other providers remain available through Add agent after onboarding.
A saved draft for another provider requires a new choice.
### `cli-setup`
@@ -62,19 +52,6 @@ Preconditions: follow the [baseline](./README.md#before-driving-a-journey). Use
Automated: [wizard tests](../../ui/src/components/OnboardingWizard.test.tsx) cover mocked wizard behavior; [onboarding browser suite](../../tests/e2e/onboarding.spec.ts) supplies its own test environment. Live model execution is a separate check.
The [published canary smoke](../../tests/canary-onboarding/canary-onboarding.spec.ts)
checks the exact installed version through Connect a model. Submitting the agent
name must save one paused setup record with disabled heartbeats and no task or
run. The [authenticated release smoke](../../tests/release-smoke/docker-auth-onboarding.spec.ts)
checks the same held state, then completes that record through Connect without
creating a second agent. Its Docker harness mocks credential verification; live
provider authentication remains separate evidence.
Name-only setup defers the runner field while the provisional adapter remains
held in setup. Choosing a provider updates that same setup record with its
selected runner. The wizard regression covers a saved native choice followed by
OpenAI Subscription selection; it does not prove provider authentication.
- **Create company and resume.** Start a fresh empty instance and run doctor using
the [verification skill](../../.agents/skills/verify-paperclip/SKILL.md). Run
`node .agents/skills/verify-paperclip/scripts/onboarding-smoke.mjs --evidence-dir "$VERIFY_EVIDENCE_DIR"`.
@@ -159,40 +136,6 @@ parent, and recovery stopped the completion callback before a provider turn.
The failed report remains evidence; the revised source still needs live proof.
Local cases and automatic selection remain unchanged.
First-task task creation enforces proposal acceptance at the shared server
boundary. Verify that native `create_task` and both REST creation endpoints reject
an authenticated onboarding run before its latest proposal has a saved human
acceptance, including an explicit standalone parent. Then accept a confirmation
or the current plan revision and verify creation succeeds. Opening answers,
agent-only acceptance, stale plans and newer pending/rejected proposals must not
admit new work. [Admission controls](../../server/src/__tests__/onboarding-first-task-admission.test.ts)
exercise native and REST calls against disposable PostgreSQL; live model and
Cloud onboarding remain separate evidence.
For a native proposal, reject root-level `version` or `supersedeOnUserComment`
without creating a card. Correct them inside `payload`, preserve the confirmation
or checkbox approval kind, and verify one pending card after idempotent replay.
An answered question form still cannot authorize the proposed child task.
After acceptance, reject a new task whose blockers include its onboarding source.
The rejected command must leave no task, dependency, wake or creation receipt;
a corrected retry must still create the ready child. Preserve valid blockers for
other work. Check equivalent UUID spellings and a later child PATCH as well as
native dependency edits, including the child's own run with a waiting parent and
no first-class dependency yet. Preserve normal API attempt auditing and allow blocker
corrections without a new proposal acceptance. The shipped handoff recipe copies the actual approved inputs and
constraints into the child, then makes the parent depend on the child. Its
schema and persistence controls do not prove that a live model follows it.
Native completion also requires a saved human proposal decision. An opening
answer alone must leave the first task in review. Verify that premature native
completion is refused, including a result already saved before finalization.
Accepted proposals and acknowledged human rejections can close the first task;
rejection still does not authorize new tasks. The
[native completion controls](../../server/src/services/native-runtime/paperclip-control-plane-port.test.ts)
exercise these boundaries against disposable PostgreSQL. These controls do not
identify a historical Cloud failure or establish live onboarding success.
For accepted file-producing work, verify exactly one self-assigned child with a
self-contained description. The onboarding run must yield through the existing
dependency/block disposition so the child's own execution can publish its file.
-8
View File
@@ -44,14 +44,6 @@ Preconditions: follow the [baseline](./README.md#before-driving-a-journey). Use
Automated: [projects UI](../../ui/src/pages/Projects.test.tsx) and [project detail](../../ui/src/pages/ProjectDetail.test.tsx) are component tests.
Automated: the explicit [`project-task-context` deployment journey](../../tests/runner-e2e/product-journeys/project-context-flow.ts)
creates a project and a self-assigned task through the production dialogs. It
reopens both, verifies the project task list and task properties after reload,
and independently checks the saved company, project, prompt, assignment and
standard work mode with zero agent runs. [Oracle tests](../../tests/runner-e2e/product-journeys/project-context-evidence.test.ts)
reject lost links and mismatched records. This describes coverage; each target
still needs its own live pass before daily promotion.
Manual: Create a project, add a task from its view, and reload. Verify the task belongs to that project, list counts are plausible, and links preserve company scope. Archive only the disposable project and inspect list/task behavior.
### `repository-settings`
@@ -79,8 +79,6 @@ Channel-specific forms and identity linking require separate provider evidence.
## Driving it
The explicit `plan-revise-accept` and `protected-actions` [Product journeys](../../tests/runner-e2e/PRODUCT-JOURNEYS.md) cover `questions-and-approvals/plan-review` and `questions-and-approvals/tool-review`. They share the classic browser actions and saved-state checks. Cloud qualification remains separate; source registration is not a passing result.
Preconditions: follow the [baseline](./README.md#before-driving-a-journey).
Use separate disposable requests for accept, decline, and revision paths. Record
the actor and request revision. Prepare a waiting question through a test agent;
@@ -218,8 +216,6 @@ unless its actual provider journey was driven.
## Gotchas
- Canonical question forms show field validation only after Next/Submit (including the keyboard submit shortcut) is attempted. Invalid answers remain unsent and the form stays on the relevant question; correction clears the field warning. Pagination arrows still browse without validation, drafts remain preserved, and uploads/requests in flight still disable submission.
- Dismissing a question does not answer it. Dismissing an app review neither
grants permission nor resumes the agent. Ordinary comments cannot approve it.
- A resolved request and a successful tool execution are separate facts.
+11 -114
View File
@@ -25,28 +25,9 @@ Agent access: [companion](../agent-access-map/recovery.md).
Restart recovery respects live heartbeat preparation before workspace
synchronization finishes. PostgreSQL regressions cover unchanged ownership,
no duplicate dispatch, and later recovery after preparation leaves the registry.
An interrupted run with an audited pending Stop can reattach its exact remote
session only for cleanup. It reuses the original held reservation during a
budget pause and cannot start another provider turn. Local PostgreSQL
[Stop accounting](../../server/src/services/native-runtime/native-stop-accounting.integration.test.ts)
and [restart selection](../../server/src/services/native-runtime/native-runner-restart-recovery.integration.test.ts)
tests cover cleanup acknowledgement, fenced alternatives, and receipt debt.
Cleanup does not stage new attachments, retire another warm owner, or replay
pending semantic work. Authenticated Core intake retains that input unanswered.
Close still requires confirmed provider exit, durable event drain, and exact
runner suspension; the cleanup purpose alone cannot certify termination.
Hosted provider settlement remains separate acceptance.
An authorized fresh native retry publishes its own session for the next
ordinary comment or monitor. The [heartbeat regression](../../server/src/__tests__/native-session-resumption.test.ts)
covers fresh admission, saved session selection, and one subsequent resume.
Unfinished goals and unverified prior outcomes retain their recovery gates.
- `source-action`: `recovery/source-action` — source-scoped recovery actions remain attached to the task;
independent repair work may have its own issue and return owner.
- `exhaustion`: `recovery/exhaustion` — an exhausted infrastructure attempt offers ordinary Retry.
The failed-attempt notice has padding, a tinted background and an error icon;
its message and Retry remain readable on narrow screens in both themes. Verify
with [the browser layout checks](../../tests/e2e/execution-recovery/failed-attempt-notice.spec.ts)
against an owned Storybook server using `RECOVERY_STORYBOOK_URL`.
Internal repair stays system-owned; genuine user decisions retain their
specific action.
- `workspace`: `recovery/workspace` — workspace divergence/export failures show the applicable repair,
@@ -58,27 +39,10 @@ Agent access: [companion](../agent-access-map/recovery.md).
workspace link when the destination is disabled. Local PostgreSQL and real
filesystem regressions cover native and legacy recovery and one-time delivery;
hosted provider recovery remains separate acceptance.
Daytona directory export can stream its archive when the sandbox cannot store
a temporary tar. The transfer remains bounded and validates archive completion
and paths before import. The [capacity regression](../../packages/plugins/sandbox-providers/daytona/src/file-sync-capacity.test.ts)
exercises a real local PTY and file-size limit. The credential-gated
[provider test](../../packages/plugins/sandbox-providers/daytona/src/file-sync-capacity.live.test.ts)
covers stop/start, an ENOSPC archive sink, safe-link filtering, and a second
export. Neither test proves the original task's continuation or repairs lost
provider session state.
Native finalization deadline failures also retain the exact prepared source
for the same stop-and-save workflow before Retry admits another executor.
A blocked native restart records that preservation obligation atomically with
its failure. PostgreSQL regressions cover exact source binding, live ownership,
rollback, and no replacement run or wake from file preservation.
Retry reconstructs missing preservation for historical failures only from an
exact prepared source without a live finalization owner.
New messages and orphan cleanup can register missing preservation automatically
and wake the existing worker. Saved input still waits for verified stop and file
persistence, then enters ordinary admission once.
A completed explicit Retry also retires its failed, unowned sandbox predecessor's
stale retry and registers preservation atomically. Current task state and live or
mismatched owners remain protected; workspace switching still waits for cleanup.
- `unknown-outcome`: `recovery/unknown-outcome` — uncertain external side effects require inspection and
an explicit decision, not automatic replay.
- `user-continuation`: `recovery/user-continuation` — saved user messages after a stop are reconsidered once
@@ -90,44 +54,13 @@ Agent access: [companion](../agent-access-map/recovery.md).
the agent itself restarted or that a failed run succeeded.
## How to get to it (user POV)
For `recovery/reconnect`, interrupt a write response after the server accepts it.
Verify that task, document, and decision drafts survive reload and that retrying
the saved request does not create a duplicate. After the bounded retry budget
ends, use **Resend now** to continue. Check that drafts remain private to their
original account and task. See [durable autosave tests](../../ui/src/hooks/useDurableAutosave.test.tsx)
and the [disconnect recovery journey](../../tests/e2e/disconnect-write-recovery.spec.ts).
For `recovery/reconnect`, also interrupt a write response after the server accepts
it. Keep a title draft bound to its original task while navigating. Restore a
new-task draft with its files selected in another order and require the same
creation key and one task. Verify lost document-create and decision responses,
including an interrupted verification read. Once the bounded retry budget ends,
require a visible **Resend now** action. Use
[durable autosave tests](../../ui/src/hooks/useDurableAutosave.test.tsx) and
[task creation tests](../../ui/src/components/NewIssueDialog.test.tsx) for the
controlled source cases; repeat the real browser journey for acceptance.
Switch accounts while an inline edit is open or a channel send waits to retry:
the next account must see neither private text nor a retry from the first account.
Returning to the original account restores its retained channel request with the
same key for explicit retry. Unowned legacy receipts stay held for Activity
inspection until a person explicitly discards their browser record; discard does
not replay the text or cancel an accepted update. Typing before the first session
lookup survives that initial lookup and is backed up under the resolved owner. Component evidence lives in the
[inline editor tests](../../ui/src/components/InlineEditor.test.tsx) and
[connected-channel tests](../../ui/src/components/chat/ExternallyConnectedTaskBanner.test.tsx);
these controlled session changes do not establish hosted authentication acceptance.
Also switch accounts during a restored task create and while its files are
uploading: later uploads stop, the next account sees a fresh form, and the
original request key remains owned by the first account. Reselect colliding
text-document filenames in reverse order and verify their original keys and
contents. Switch between cached document subjects without copying either draft.
A receipt arriving before an in-flight resend must preserve the next message.
The startup browser journey in
[disconnect recovery](../../tests/e2e/disconnect-write-recovery.spec.ts) holds the
first session response while a title save waits, simulates an offline event with
API failures while keeping static assets reachable, then verifies the real saved
server title after account resolution and reload. The accepted-comment journey
then completes and assigns a task before repeating its saved comment request;
the original receipt must return once, its activity must appear once, and the task must stay Done. Reusing that
key with different text must return a conflict without changing the task. This
uses a disposable process agent and makes no provider call. A separate healthy-API
startup journey fails the session endpoint with JSON 500 responses, then restores
it while an edit waits; the same edit must save and survive reload without a
network reconnect or another user action.
### `source-task`
@@ -158,10 +91,7 @@ Open the agent's run (`/agents/:agentId/runs/:runId`) from activity or the task'
run link. The run page hosts workspace repair controls only for a failed run
with error code `workspace_validation_failed` and a linked source task that still
has a live `workspace_validation` recovery action. Use the source task for other
stopped-run recovery checks. Native workspace export failures also offer the
read-only **Inspect recovery** control described in the
[run diagnostic recipe](activity.md#activity-audit-1). It observes one selected
source's recorded identity and does not retry, repair, or authorize execution.
stopped-run recovery checks.
### `operator-retry`
@@ -253,7 +183,7 @@ Use these checks alongside the entry-point recipes below and the operation recor
| --- | --- | --- |
| `recovery/diagnosis` | Open the source task and exact run; compare cause, source action, original owner, recovery owner, attempt bounds and next action after reload. | Test an unrelated/private task and a stale run notice. Read-side retirement of a stale action must not create a new attempt, participant, or permission to replay. After workspace recovery, compare task and run instructions; recovered files must not leave instructions to repair a retained sandbox. The stopped run keeps its replay hold until continuation admission. An obsolete exact-session notice retires only after terminal coordinator proof and a separate exact-run workspace hold; no new execution or file cleanup follows. |
| `recovery/bounded-continuation` | Use a deterministic recoverable interruption and inspect the original run/session, attempt receipts, saved result and eventual useful output. | Repeat restart/receipt delivery, race Stop or a new owner, and retain unknown external outcomes. Accepted completion/finalization recovery must not start a new provider turn or repeat its side effect. |
| `recovery/source-action` | Inspect active and retained actions, follow the repair owner, and resolve one eligible source-bound action with its exact ID. | Retry the settled resolution and reject a stale/foreign action. Recovery ownership alone cannot mutate the source task; inspect source status, audit and wake independently. A running native owner must receive a conflict when resolution would change its own task status; its task tools must remain usable so it can report through semantic completion. Unchanged-status, Board and legacy recovery retain their normal permissions. |
| `recovery/source-action` | Inspect active and retained actions, follow the repair owner, and resolve one eligible source-bound action with its exact ID. | Retry the settled resolution and reject a stale/foreign action. Recovery ownership alone cannot mutate the source task; inspect source status, audit and wake independently. |
| `recovery/exhaustion` | Exhaust or age a bounded fixture; use the currently offered retry once, then inspect its durable acknowledgement and actual continuation. | Reassign, pause, stop, close, add an unresolved dependency, or impose a budget hold before retry. The old notice must not reopen terminal work or run the wrong owner. |
| `recovery/workspace` | Exercise retained-file recovery, export retry, reconstruction, branch repair/reconciliation and exact-owner finalization as distinct authorized operator paths. | Use exact source/action/run/receipt bindings and preserve existing files. Reject stale source, live/uncertain writers, unsafe archives and insufficient authority. Verify actual files and accepted result separately from queued acknowledgement. |
| `recovery/unknown-outcome` | Inspect the provider and saved intent before recording a source-specific chat, email or governed-provider outcome. | Use performed, not-performed and unresolved cases. Wrong company/request, stale state and unauthorized resolution must fail. Unknown effects must not replay automatically. An explicit retry must record the operator’s duplicate-risk acceptance and dispatch only the authorized attempt. |
@@ -291,15 +221,6 @@ provider restart. For that journey, interrupt a disposable deployment after
workspace preparation and before its first executor claim, then confirm one
provider turn starts on the original run through the normal admission gates.
The same suite's `diskless` and `diskless-per-turn` cases exercise three native
controller processes with both native projections removed between completed
turns. They check history and invocation counts through the real executor and
admission snapshot rebinder. The workspace and sandbox remain available, and
the processes use the same source revision. Separate Postgres tests cover
metadata import, bounded discovery, ownership holds and incomplete-publication
retention. These cases do not qualify full webserver disk loss, distinct releases,
HTTP traffic continuity, or the live Daytona provider path.
The [Runner transport regressions](../../packages/paperclip-runner/runner/crates/runner-core/src/durable/transport.rs)
exercise a real WebSocket welcome delayed beyond two seconds. Authentication
uses the ten-second connection setup budget, clipped by the current lifecycle
@@ -315,10 +236,8 @@ historical provider outage or successful hosted task recovery.
Active remote process supervision distinguishes a failed health read from a
confirmed exit. The [executor tests](../../server/src/services/native-runtime/native-session-executor.test.ts)
exercise timeout and repeated gateway-failure recovery with a real listening
process, unchanged ownership, and rejected identity evidence. Read-only probes
use their shared deadline with bounded backoff; fast failures do not exhaust a
three-attempt limit. Signal requests remain single-attempt. The Runner restart tests require positive exit
exercise timeout recovery with a real listening process, unchanged ownership,
and rejected identity evidence. The Runner restart tests require positive exit
evidence before replacement. The executor regressions also retire a real child
during its metadata read, keep unknown adopted-process ownership held, and reject
launch before detachment when Node is unavailable. The diagnostic tests cover
@@ -429,32 +348,10 @@ For a source with a retained-file protection marker, exercise recovery through
the assembled environment runtime. Its exact preservation owner may reopen the
stopped allocation to read saved files; ordinary resume stays blocked. Reject a
changed claim, missing stop intent, wrong lease or wrong environment before a
provider call. Repeat accepted-native-result copyback for both reusable lease policies. Require
the exact accepted result and completion contract; reject a rejected or unselected
result, another allocation owner, and an active host writer. Verify no provider
turn or wake is created, then finalize the original result once. Reject malformed
or oversized Git metadata through native finalization: the run must fail and
retain its file-recovery barrier, rather than successfully omitting the export.
Exercise both an oversized sender file and an oversized transfer report. Verify
one rejected export, no payload read after rejection, and unchanged host files.
Reload a large-result run and its activity: the failure code and task recovery
notice remain visible, and metadata repair offers no new provider turn. These database
and filesystem controls do not qualify a deployed provider.
Verify saved and newer local files, one preservation receipt, and
provider call. Verify saved and newer local files, one preservation receipt, and
no additional agent turn. The PostgreSQL regression covers this boundary; the
opt-in provider probe also uses this runtime path with the protection marker.
Repeat Task Retry with a completed native result whose unfinished export uses
the remote-workspace descriptor. Before preservation, require the original run
to remain the only task run. After preservation, verify restored file bytes and
Git HEAD, commitment of that same result, and an unanswered human review keeping
the task In Review. For an action superseded by a newer failure, request exact
historical file recovery through the board API: verify a committed snapshot,
unchanged newer workspace binding and attention owner, no old-result commitment,
and no provider turn. An active current writer or no explicit request keeps the
historical source waiting. The PostgreSQL/HTTP regression is in
[workspace recovery](../../server/src/services/workspace-recovery.test.ts).
For a missing managed allocation, verify a fresh Cloud-signed absence observation
under the exact physical recovery owner. The existing Retry may then select an
independent workspace through normal admission. Verify that the original run
+6 -14
View File
@@ -29,9 +29,7 @@ Open `/routines`, create one, and inspect `/routines/:routineId` and its edit se
### `trigger-history`
Use the routine's trigger controls and Runs/Recent Runs/Audit links; lists also
offer Run now. **View all tasks** opens the Tasks list with **Routine tasks**
selected, using `/issues?view=all&originKind=routine_execution&sortField=created&sortDir=desc`. Uncheck the
filter to return to other tasks. **History** records configuration versions, not executions.
offer Run now. **History** records configuration versions, not executions.
## Driving it with Playwright and the Paperclip CLI
@@ -54,15 +52,11 @@ Automated: [trigger wizard](../../ui/src/components/routine-triggers/TriggerWiza
Manual: Set a near-term disposable schedule or authorized test webhook, verify one eligible execution and its source trigger, then disable it and confirm further invocations stop. Inspect a failed execution without losing its history. Remove the temporary trigger after testing.
Sentry run-failure alerts can use the bearer-authenticated
`/api/routine-triggers/public/:publicId/sentry-run-failures` receiver. It validates
the source run against this company's task, admits one repair per failed run,
and ignores tasks originating from the repair routine, including children and
standalone creation descendants. Private or unreadable sources are ignored rather
than copied into company-readable routine history. The routine's instructions
should reuse existing repair cases/PRs for the same root cause. Service and HTTP
regressions in the routine suites cover recursion, concurrent delivery, and access;
these checks do not prove a live Sentry integration is configured.
A webhook-triggered routine can receive Sentry run-failure alerts through
`/api/routine-triggers/public/:publicId/sentry-run-failures`. Configure bearer
authentication, send an alert for an accessible task in the same company, and
verify one repair task for the failed run. Failures from the repair routine
and its descendants must not trigger another repair. See the [routine API](../../docs/api/routines.md).
## Gotchas
@@ -96,5 +90,3 @@ Sources: Source: [RoutineRunVariablesDialog.tsx](../../ui/src/components/Routine
### Documentation scope: Routines, cases, and status cards
All three capabilities have recipes. Trigger/provider/timezone combinations, custom case schemas and summarizer quality need deeper cases.
The target-independent Product E2E journey `routine-scheduled-run` covers browser creation, an actual scheduled invocation, run-attributed saved output, history after reload, and no new invocation across the next minute boundary after pause. Source: `tests/runner-e2e/product-journeys/routine-schedule-flow.ts`. Registration is not evidence of a passing deployed run.
+3 -135
View File
@@ -40,25 +40,6 @@ The agent header has one Run now action. Administrators can enable
Capture raw provider traces under the agent configuration’s Debugging section
for future runs. The header shows Raw tracing on while that setting is enabled.
Managed Git launchers let agents save local commits without a GitHub connection
or manual author setup. Verify a fresh checkout and a second shell in the same
workspace: both commits should use `Paperclip <noreply@paperclip.ing>` when no
identity is configured. Repository and command settings override this default;
an eligible managed identity still takes precedence. Inspect stored commit
metadata and confirm the default did not change repository or host configuration.
Repeat with unavailable GitHub access; authenticated operations must still obey
the existing credential checks. The [launcher controls](../../packages/adapter-utils/src/github-launcher.test.ts)
and [real-shell staging controls](../../packages/adapter-utils/src/github-launcher-environment.test.ts)
cover this local behavior, separately from live cloud execution and GitHub writes.
Native Runner agents wait for task-bound work. A generic heartbeat interval does
not create a taskless run or put an otherwise ready agent into an error state.
Assigned tasks, task monitors, routines and task-bound timer wakes keep their
existing admission paths; Legacy adapter intervals remain supported. The
[scheduler](../../server/src/services/heartbeat/scheduling.test.ts) and
[queue](../../server/src/services/heartbeat/queue.test.ts) regressions exercise
this boundary with PostgreSQL and synthetic execution, separately from live task acceptance.
For latency diagnosis with an operator OTLP endpoint, search the hashed run ID
without restricting the root span name. Compare workspace preparation with its
`workspace_<step>` intervals. Measure controller readiness separately through
@@ -93,84 +74,6 @@ mutations. Qualify a useful model task separately from saving the account.
### `session`
Recover an in-flight remote runner after controller restart, then let it finish
with slow instruction collection. Send two follow-ups without resetting its
session. Verify that completion does not detach the retained runner and that
provider history survives with one turn per wake. Preparation must retain its
lease until execution owns renewal; a genuine ownership loss must still detach.
The [remote continuity regression](../../doc/testing-native-remote-continuity.md)
uses a real Linux runner and deterministic provider. Live provider acceptance is
a separate check.
Repeat with a full prior-run controller projection that predates its committed
database checkpoint under the same run ID. Admission must refresh that projection
before reuse. A pending canonical command must still hold execution; current-run
state and a retained warm owner must keep their existing authority.
In a fresh sandbox workspace, fetch a different published branch with depth one,
then save a local result and finish. Verify export imports the shallow history,
retains host-only edits, and completes finalization without another provider turn.
Repeat when the host already has that branch history; its ancestry must remain
available. The filesystem sandbox regression covers transfer and merge behavior,
not live provider acceptance.
For a plugin computer, complete a task, let its warm session suspend, then send
two follow-ups within the next warm window. Verify the first resumes the saved
session and the second keeps the same provider history without an identity
mismatch. After a fresh recovery into a repository-free directory, send another
ordinary follow-up. Verify it retains that directory without Core Git worktree
preparation. Explicit repository strategies and changed provider owners must
remain denied. Executor and workspace-preparation regressions cover control
behavior; they do not establish live provider acceptance.
For a remote OpenCode agent configured with `per_turn`, complete a task, then
send two follow-ups without resetting its session. Verify that each continuation
restores its external controller checkpoint, retains provider context and saved
files, and finishes with no stranded task lock. A missing checkpoint, an active
prior owner or a mismatched session must still stop admission. The
rejected active-owner attempt must not prevent a later continuation from reading
the owner's newer completed checkpoint. The
[executor controls](../../server/src/services/native-runtime/native-session-executor.test.ts)
cover checkpoint restoration and its guards; real-provider acceptance remains
separate evidence.
For native OpenCode, hold an assigned tool result for more than 30 seconds.
Verify that the provider receives the saved result once and the next run can
attach with no pending tool call. Stop and bridge teardown must still end an
unanswered wait without claiming the action failed or repeating it. The
[native proxy regression](../../packages/paperclip-runner/src/live/runnerd-opencode-streaming-tools.test.ts)
uses the real Rust Runner and proxy with a deterministic provider; live provider
and deployed sandbox acceptance remain separate evidence.
After a completed warm turn, change an agent setting that invalidates its
instruction copy, then send a follow-up. Verify the old runner suspends during
preparation, saved files remain available, and the follow-up completes once.
Repeat with an expired or foreign preparation owner and verify that execution
stays held. The checkpoint integration regression covers the ownership boundary;
a real provider run remains separate acceptance evidence.
For a repository project that inherits storage-plugin defaults, run a task and
send two follow-ups. Start with unset task workspace settings, then repeat with
an explicit isolated mode or strategy. Binding must save `reuse_existing` and
the resolved mode without changing the effective policy,
session fingerprint, and workspace identity. An actual project-policy change
must still reset the session and preserve the stored workspace owner. The
[session admission regression](../../server/src/__tests__/heartbeat-session-preparation.test.ts)
checks this with PostgreSQL and synthetic provider execution; it is not live
warm-process or latency evidence.
After an isolated remote Retry, send a follow-up with unchanged workspace policy.
Verify the same workspace remains bound and no strategy-replacement operation is
recorded. Change the strategy or base ref and confirm that the normal replacement
guard still applies. The
[remote preparation regression](../../server/src/services/heartbeat/workspace-preparation.test.ts)
checks persisted configuration across both admissions; it does not prove a live
provider conversation resumed.
For a workspace carrying an older temporary fingerprint, verify that ordinary
reuse retains the strategy warning. Use the normal fresh recovery flow after
preserving its work, then repeat the unchanged follow-up check on the new workspace.
For `runs-adapters/session`, complete a task in a disposable warm sandbox and
retain its saved workspace file. Let the warm session close normally and verify
that the retained lease has a complete, lease-bound harness backup before
@@ -182,11 +85,6 @@ reads the retained file and appends one new line. Verify a replacement sandbox,
a new provider session, the exact file contents, successful finalization and no
stranded task lock. Send another follow-up and verify ordinary session reuse.
With external controller checkpoints enabled, also admit a fresh session on a
reused sandbox lease. Verify startup from canonical controller evidence and
reject a marker without a registered controller, changed identity or prior turn
activity. An existing remote session directory must retain its recovery gate.
Repeat without resetting the session: its replacement must restore verified
history or remain blocked. Missing backup state must not silently start an
existing session again. The [executor controls](../../server/src/services/native-runtime/native-session-executor.test.ts)
@@ -194,15 +92,9 @@ cover the bootstrap identity, activity and atomic directory claim; those
controls do not establish live provider acceptance.
### `adapter-setup`
Cloud-managed instances load adapters from the release image. Installing,
removing, or overriding adapters remains platform-managed.
Cloud-managed instances load adapters from the release image. Saved external
registrations cannot replace built-ins or supply UI parser code. Install,
reinstall, reload, remove, and override operations remain platform-managed.
The [fixture loader controls](../../server/src/adapters/cloud-external-adapters.test.ts)
exercise real packages, import side effects, both managed-instance signals and
self-hosted compatibility. The [route authorization controls](../../server/src/__tests__/adapter-routes-authz.test.ts)
check managed denials before package or registration access. These are local
controls, not live Cloud provider qualification.
Automated: [adapter validation routes](../../server/src/__tests__/agent-adapter-validation-routes.test.ts) and [model refresh](../../server/src/__tests__/adapter-model-refresh-routes.test.ts) cover server behavior.
@@ -219,16 +111,6 @@ Cloud onboarding must not offer shell commands the customer cannot run.
Manual: Select the intended adapter and account, refresh model choices, and run its environment test. Save, reload, then execute a small task. Repeat with a deliberately unavailable account and verify the failure remains visible.
The explicit-only [Antigravity agent journey](../../tests/runner-e2e/ANTIGRAVITY-AGENT-JOURNEY.md)
checks a saved personal subscription, prompt-free native Test and exact low model,
then independently correlates two actual downloaded outputs, accepted/committed
Done lineage, native conversation continuity and owned runtime retirement. Its
first settlement is captured before follow-up reopening; a later coordinator
assessment cannot erase that historical Done decision. A failed finish must not
mark prior completed file operations failed. The current local macOS ARM64
candidate scope leaves fresh authorization, remote targets and release
qualification unproven.
For Legacy Codex, assign a service secret such as `SLACK_BOT_TOKEN` through agent
configuration and run a task that checks its presence without printing its value.
Check both ACP and CLI execution. Remove the binding and repeat on the next run.
@@ -296,13 +178,7 @@ cover ordering, failure drain and credential projection; they do not qualify a
live response-time target.
For native OpenCode with assigned connections, inspect the provider tool surface
on both local and sandbox execution. It should contain bounded assigned-tool
search/call schemas. Confirm the search description states the 1–20 page limit
and default of 5. Follow `nextOffset` to inspect later pages.
Repeat discovery with empty and whitespace-only `schemaTool` values, including
`schemaOffset: 0`, and confirm it still returns searchable tools. An unknown
schema reference or a positive schema offset without a reference must explain
how to correct the call.
Discover an allowed tool, call its returned alias, revoke
search/call schemas. Discover an allowed tool, call its returned alias, revoke
its grant, and confirm discovery and execution enforce that revocation. Repeat
in planning/ask mode with a write tool and confirm denial. The controller must
retain the assigned gateway URL and token. An older direct-catalog OpenCode
@@ -344,14 +220,6 @@ a separate acceptance requirement.
Automated: [live run routes](../../server/src/__tests__/agent-live-run-routes.test.ts) and [run event sequencing](../../server/src/__tests__/heartbeat-run-event-sequencing.test.ts) cover run data contracts.
For `runs-adapters/runs`, verify a provider rejection during startup and during a
turn. The task interruption and run detail must show the same sanitized provider
explanation after reload. Unknown provider categories keep their message. A newer
attempt or a completed task hides the stale task notice, while historical run
details retain it. Check that existing retry and access gates remain effective.
The transport restart regression and PostgreSQL finalization integration cover
the persisted cause; component tests cover plain-text rendering and read-only use.
Manual: Start a disposable task, open its running transcript, and follow it to a terminal outcome. Reload and compare task/run IDs, status, output, and cost. Verify a failed run remains distinguishable from a completed run with useful output.
For Legacy OpenCode on a disposable Linux sandbox, run a Bash tool that reads
-6
View File
@@ -26,12 +26,6 @@ Agent access: [companion](../agent-access-map/secrets.md).
Open company Settings → Secrets and the company/personal secret views.
An agent's **Secrets** page also shows its environment variables, including
masked inline values, company secret references, and user secret references.
Environment bindings remain available from **Harness / Runtime** as well.
Save an added variable and reload to confirm that the existing masked bindings
and their secret references remain present.
### `proposal-import`
Use the Proposals tab or Import from vault where available.
-30
View File
@@ -45,8 +45,6 @@ Use skill policy/agent selection in the library or an agent’s Skills tab.
## Driving it with Playwright and the Paperclip CLI
The explicit `create-skill-studio` [Product journey](../../tests/runner-e2e/PRODUCT-JOURNEYS.md) covers `skills/authoring`: native creation of an owned company skill, its task activity card, a Studio edit, reload, and task-card readback. It does not establish policy, source-update, or Studio-test coverage. A deployed target requires its own live result.
Preconditions: follow the [baseline](./README.md#before-driving-a-journey). Use a harmless skill fixture and test agent with skill support. Record whether the source is local, bundled, project, or remote.
### `library-sources`
@@ -61,20 +59,6 @@ Automated: [Studio](../../ui/src/pages/SkillStudio.test.tsx) covers UI behavior;
Manual: Create or fork a disposable skill, edit instructions, save, and reload. Run a bounded test, respond to any question, and inspect the output. Verify the saved version matches what was tested and failed saves retain the draft.
For managed skills, open the same file in two Studio sessions. Save through one,
then save the other's stale draft. It must receive a conflict, retain its text,
and offer **Load latest saved file** with discard confirmation. File reads and
mutation results identify the committed version. Managed content has no server
source-directory repair flow. The [domain regression](../../server/src/__tests__/managed-skill-content.test.ts)
and [process qualification](../../server/src/__tests__/ephemeral-skills-process.test.ts)
cover fresh-home recovery; remote Runner staging remains a separate live proof.
Version history lists file metadata without downloading archives. Opening a diff
fetches only its selected versions; restoring fetches the chosen version. The
[library UI regression](../../ui/src/pages/CompanySkills.test.tsx) checks deferred
loads; the [package regression](../../server/src/__tests__/skill-package-store.test.ts)
checks that slow archive verification cannot hold up a warm agent preparation.
### `agent-enablement`
Automated: [policy service](../../server/src/__tests__/company-skill-policy-service.test.ts) and [agent skills state](../../ui/src/pages/agent-skills/AgentSkillsTab.test.ts) cover policy/state contracts.
@@ -103,14 +87,6 @@ version pins. The [concurrency regression](../../server/src/__tests__/company-sk
checks shared work and separate actor access; the cache tests check that cleanup
cannot remove a snapshot before the run stores its pins.
The [package storage regression](../../server/src/__tests__/skill-package-store.test.ts)
covers external snapshots, automatic legacy conversion and exact-commit recovery. A warm selected-repository
check must perform no object reads or repository-content SQL. Source/library
reconciliation remains available for discovery and mutable sources. The native context
regression checks that warm asset packaging reuses verified files, repairs missing/corrupt copies,
and notices source edits. Verify both writer-switch states during rollout; see
[package storage](../../doc/skill-package-storage.md).
## Gotchas
- The release picker requires `enableBetaSkills`. Do not invent an Instructions
@@ -166,12 +142,6 @@ Capability ID: `skills/testing`.
Scope: ui
Storybook: Studio test inputs/configuration, running, question/approval, result and failed test states.
Production: Run bounded test of actual saved version with correct selected account/environment; inspect persisted test detail and eligible interaction response.
Remote Runner selection accepts the Studio test work mode and preserves its
restricted scope; live qualification must cover the saved version delivered to
the selected Computer, including a skill with no permanent agent assignment.
The [execution configuration regression](../../server/src/__tests__/heartbeat-execution-configuration.test.ts)
checks that Studio's historical version replaces ordinary assignments without
changing the agent's configuration. Use an isolated Runner home for this journey.
Sources: Source: [SkillStudio.tsx](../../ui/src/pages/SkillStudio.tsx), [companySkills.ts](../../ui/src/api/companySkills.ts). Tests: [SkillStudio.test.tsx](../../ui/src/pages/SkillStudio.test.tsx), [company-skill-test-runs-service.test.ts](../../server/src/__tests__/company-skill-test-runs-service.test.ts)
### Documentation scope: Skills, Skill Studio, and teams
+1 -14
View File
@@ -35,7 +35,7 @@ Agent access: [companion](../agent-access-map/steering.md).
Open an assigned task (`/issues/:issueId`). Start work, then send follow-ups while
the agent runs. Use the queued-message controls to edit, reorder, discard,
steer, or interrupt when offered. After Stop, choose **Send** on a saved queue to explicitly continue it without recreating the messages or attachments. Native steering still requires an active turn; Send after Stop is a separate user decision. Use the composer stop/pause control separately.
steer, or interrupt when offered. Use the composer stop/pause control separately.
Both task presentations need attention when changing their shared behavior.
### `agent-chat`
@@ -58,15 +58,6 @@ inspect the resulting task and run in Paperclip.
## Driving it
The explicit `stop-redirect` [Product journey](../../tests/runner-e2e/PRODUCT-JOURNEYS.md) covers `steering/stop-and-pause` only for Stop and one new direction. It requires active work, native cancellation acknowledgement, resource cleanup, and completion without later original-turn activity. It does not qualify pause, interrupt, or all queued-message behavior. Source registration is not a live Cloud pass.
The explicit `followup-while-running` [Product journey](../../tests/runner-e2e/PRODUCT-JOURNEYS.md#active-follow-up)
covers `steering/queue`: one follow-up is saved while a bound native command is
active, its late requirement appears in one attributed final reply, the queue
empties, and the result survives reload. One steered turn or one normal successor
is allowed. Unit calibration and source registration are not live acceptance.
Preconditions: follow the [baseline](./README.md#before-driving-a-journey).
Use an agent that stays busy long enough to inspect the queue. Record the adapter,
native/legacy mode, and advertised steering capability. Test supported and
@@ -86,10 +77,6 @@ consumed message whose send response and queue snapshot arrive late. A started
run's input receipt removes that message from pending, while a separate unsent
message stays queued. Admission to a run that has not started is not delivery.
A later retry of the same message remains visible in its new authoritative queue.
A queued turn's own starting input stays in history before execution, including
board messages that reopen a task. Later inputs keep their queue controls and
full canonical order. A maintenance hold displays its current admission wait;
drain release and expiry prompt normal admission without a manual retry.
Receipts retain the primary wake and coalesced source queue IDs. They clear a late
snapshot even when its target names the preceding run or is null.
+4 -23
View File
@@ -25,11 +25,6 @@ Agent access: [companion](../agent-access-map/task-coordination.md).
Open the task’s parent/child and dependency links in task detail.
The task feed shows a linked card when an agent creates a direct subtask or a
follow-up task from that task. The card stays at its creation time beside
documents and artifacts. It shows the current task title, number, and status.
The Tasks tab retains the complete relationship list.
### `review-and-controls`
Inspect the task’s execution policy and available review, pause, resume, or stop controls.
@@ -46,11 +41,6 @@ creates a hold; it does not change task statuses to a paused status.
Automated: [dependency wakeups](../../server/src/__tests__/issue-dependency-wakeups-routes.test.ts) checks server behavior; visual relationship navigation remains a manual check.
The [created task card stories](../../ui/storybook/stories/task-coordination/task-created-inline.stories.tsx)
render the production feed with fixture task reads. The
[task feed tests](../../ui/src/components/TaskChatThread.task-creation-order.test.tsx)
check creation order, current status, links, and duplicate suppression.
Manual: Block one task on another, finish the prerequisite, and observe the dependent task’s eligible continuation. Follow parent/child links back to the source request. Verify no duplicate run or false parent completion occurs.
### `review-and-controls`
@@ -69,19 +59,10 @@ their execution, and uncertain prior executions must be reconciled before waking
### Plugin task panels
An installed plugin can offer an agent detail tab in the task side panel through
its optional `taskSidePanel` declaration. The launcher offers that view for the
running agent, or the task's assigned agent when idle. Manual selection mounts
the same authorized viewer used on the agent page and needs no activity event.
The view remains selectable after the run ends.
A declared activation pair controls automatic opening. The runtime captures
Runner context before use and records `runtime.activity.recorded` after success.
Core maps that namespace/activity key to the declaration and restores it from
the run log on reload or reconnect. After matching activity, readiness gets
three bounded attempts with no periodic availability poll. A ready view opens
the pane and selects its tab once per run, respecting dismissal during that run.
Declarations without a mapping support manual selection. Plugins own viewer
content, readiness, and authorization. Missing or disabled plugins add no view.
its optional `taskSidePanel` declaration. Open the view from the task side-panel
launcher for the running agent, or the assigned agent when idle. The plugin owns
its label, viewer, and access checks. Missing or disabled plugins add no view.
A closed panel can be reopened from the launcher.
Implementation: [panel discovery](../../ui/src/hooks/useTaskPluginPanels.ts) and
[task panel](../../ui/src/components/task-side-panel/TaskSidePanel.tsx).
+1 -59
View File
@@ -20,9 +20,6 @@ Agent access: [companion](../agent-access-map/tasks.md).
- `discussion`: `tasks/discussion` — persist comments, references, and files on the task.
- `completion`: `tasks/completion` — distinguish backlog, active work, review, blocked, done, and cancelled outcomes.
A board user closing an active native task must stop its run before the task
releases execution ownership, including providers without session goals.
Verify Done and Cancelled, an unconfirmed stop, and ordinary agent completion.
- `privacy`: `tasks/privacy` — create private tasks, share or revoke access, and inspect parent/project inheritance before changing visibility.
The [Product task-properties journey](../../tests/runner-e2e/PRODUCT-JOURNEYS.md)
@@ -30,12 +27,6 @@ checks only assignment to the signed-in user and persistence after reload. Its
source is reusable across self-hosted and Cloud; Cloud live qualification is
separate. It does not cover other property operations or agent authorization.
The [Product task-search-filter journey](../../tests/runner-e2e/PRODUCT-JOURNEYS.md)
checks `tasks/organize` with owned matching and nonmatching controls, exact task
identities, saved task content, and search/status persistence after reload and
detail/back navigation. It is model-free and reusable across deployment targets.
Live Cloud qualification is separate from the journey's assertion unit tests.
## How to get to it (user POV)
Cold collection loads use a lightweight index and batched hierarchy context,
@@ -44,56 +35,18 @@ visible-row details independently when verifying `tasks/organize`: row heights,
title bounds, and the first-row origin should remain stable. Test nested expansion,
scrolling to more rows, and detail/back navigation; a collection projection must
never suppress the full task instruction fetch.
Coordinator Tasks uses the same index and visible-row enrichment. Needs attention
resolves pending task IDs in batches of at most 100; it does not fetch enriched
task detail for every decision. Search and participant filters stay on the server.
Cold Coordinator detail must stay compact when Classic settings arrive before
the personal workspace preference. Verify explicit history expansion afterward.
### `new-task`
Use New task from the global launcher, task list, or project task view.
Images selected, pasted, or dropped into either the new-task or thread composer
appear as equal-size rounded thumbnails above the text. Check mixed image/file
selections, removal, thread upload failure/retry, and restored thread drafts.
New-task files persist in account- and company-scoped browser storage across
reloads and are cleared after creation. Verify that restored image bytes reach
the task and that older inline-image drafts keep the rich editor.
The Storybook new-task and add-menu suites have desktop and mobile image examples;
their upload and submit boundaries are fixtures.
### `task-list`
Scheduled ordinary monitor waits display **Monitoring** with a blue clock in
current task indicators, groups, board columns, and filters. Compare Monitoring
with In Progress, then start the check and verify the status returns to its
execution presentation. Retained monitors must not override blocked/review or
terminal states. Inspect due/overdue copy separately; no runner is implied.
Open `/issues` or a project’s Issues view; legacy `/tasks` links redirect.
Filters → **Routine tasks** selects tasks created by routine runs. The
`/issues?view=all&originKind=routine_execution&sortField=created&sortDir=desc` link opens that selection with newest-created tasks first. Sort controls update
`sortField` and `sortDir` in the URL. Reloads and task return links keep that order.
Shared sort links also retain their order when opened in another task interface.
### `task-detail`
During a cold open, task data prepares behind the shell loading view until the
personal presentation preference resolves. The temporary shell stays hidden.
The matching chat loading frame then owns the same viewport and
composer geometry as the resolved conversation. The real title and monitor
banner stay concealed until the initial reading position is prepared. The
[rich loading journey](../../tests/perf/issue-detail/loading-layout.spec.ts)
checks direct and list-based entry, delayed fonts and preferences, and desktop/mobile geometry
with a long saved thread, cards, a monitor, and a pending confirmation. This
synthetic local coverage does not establish a deployed staging pass. The normal
[browser CI journey](../../tests/e2e/task-loading-frame.spec.ts) also covers the
loading contract, Classic preference loading and typography, stable mobile chrome,
and a bounded wait for stalled fonts.
Open `/issues/:issueId` from a row, mention, or direct link. Cold opens show the instruction, recent exchange and saved cards together. Completed runs with saved replies defer their transcripts until the reader opens history. Live runs, failures, yielded runs and runs without a saved reply still hydrate; an already shown transcript stays available after completion. No URL fragment expands history; older-comment anchors fetch only their target, and document anchors open the pane. **More messages** appears only when earlier comments or runs are omitted and loads that history. Fresh tasks with no omitted history have no disclosure. A single run with deferred output or a truncated legacy log offers **More run output** instead. **More task actions → Show task activity** loads full activity even for a single native run; incoming messages remain visible while the task stays open.
For an ordinary native task, deferred workspace finalization must preserve the final reply for both completed work and work awaiting review. Reload must show that saved reply once. The pending review stays pending; publishing the reply does not approve it or start another run. The [database recovery suite](../../server/src/services/native-runtime/agent-chat-response-recovery.test.ts) covers deferred review publication, exact final-message selection and review preservation. Live acceptance is recorded in the pull request.
Open `/issues/:issueId` from a row, mention, or direct link. Cold opens show the instruction, recent exchange and saved cards together. **More messages** appears only when earlier comments or runs are omitted and loads that history. Fresh tasks with no omitted history have no disclosure. A run with deferred output or a truncated legacy log offers **More run output**. **More task actions → Show task activity** loads full activity even for a single native run; incoming messages remain visible while the task stays open.
### `task-sharing`
@@ -135,8 +88,6 @@ Use a human/unassigned task to verify persistence without invoking a model.
Automated: [task-list helpers](../../ui/src/pages/Issues.test.tsx) cover search URLs, pagination, deduplication, and presentation constants. The suite does not render the page or exercise filtering, grouping, opening a task, and returning; those interactions still need a running-browser check.
Task and inbox rows omit the system interruption labels **Thinking**, **Trying again soon**, and **Retry available**. [Shared row tests](../../ui/src/components/IssueRow.test.tsx) cover working, scheduled-retry, and failed interruptions in both row presentations, including suppression of replacement recovery chips. Task status and other relevant badges remain visible; retry controls remain inside the task conversation.
Manual: Seed human-created, agent-created, scheduled routine, human-initiated chat-channel, and creator-less tasks. Confirm automation is hidden by default, **Show agent-created tasks** reveals it, reload preserves the choice, and Clear filters hides it again. Verify list and board search with automation newer than the human results, and expand contextual ancestors/subtasks without promoting unrelated automated roots. Repeat in project task lists. Agent profiles and task-detail subtasks retain complete history.
Manual: Filter by status and assignee, change grouping/sort, open a task, and return. Verify the correct records and selected view survive navigation and reload. Include an empty result and a failed request.
@@ -147,8 +98,6 @@ Manual: Open a long task with slow historical requests. Read the instruction and
Automated: [cold-open reads](../../server/src/__tests__/task-cold-open.test.ts) cover bounded reads, event filtering and company denial. [Task detail](../../ui/src/pages/IssueDetail.test.tsx) covers component behavior, while [issue service](../../server/src/__tests__/issues-service.test.ts) covers server contracts.
The opt-in [saved-reply browser case](../../tests/perf/issue-detail/saved-reply-startup.spec.ts) uses 200 completed native runs and long saved replies in a disposable PostgreSQL instance. It holds transcript reads, checks desktop/mobile first-reveal geometry, then opens history while retaining the editor and draft. See its [setup](../../tests/perf/issue-detail/README.md).
Failure markers have no dashed divider rules. An adjacent run error and
no-live-execution-path notice show only the last error, with its details and
retry action, including a permitted legacy run retry carried onto a later
@@ -187,13 +136,6 @@ schema feedback supports a corrected call before a wait is claimed.
For a due monitor held by execution recovery, confirm that the schedule remains
and task activity explains the deferral. Repeated checks must not replay the held
work. Resolve the hold through its existing recovery action, then verify one wake.
On a blocked task with a retained monitor, verify that automatic checks show as
paused. Check now requests one check through normal admission without changing
the task status. Confirm that an unresolved dependency or recovery hold prevents
dispatch and does not produce a success message. Backlog and todo tasks must not
offer Check now. Blocked provider-quota recovery must offer no manual check and
retain its schedule until the task resumes. Agents and automatic ticks cannot
check a blocked task.
Hold native finalization after the provider has stopped, and verify that both
scheduled and manual checks retain the due monitor. After settlement, verify one
wake. If its timeout passes during workspace recovery, verify settlement followed
+3 -53
View File
@@ -43,15 +43,6 @@ Live staging acceptance remains separate from these regression tests.
Use the task’s workspace card or Files panel and follow its workspace link.
Native artifact-copy verification: in an admitted standard-mode task, save a
synthetic API response and call `download_artifact` with its saved identity and a
new workspace-relative filename. Independently inspect the file's complete byte
count and SHA-256 through the admitted filesystem. Retry the identical request;
reject a conflicting destination, symlink, revoked authority and foreign artifact.
The transfer does not change the content's untrusted status. See
[API tools](../../doc/runner-api-tools.md#verified-artifact-installation) for support
and limits. Provider-free regression evidence is not live remote qualification.
### `workspace-management`
Open `/workspaces`, a project workspace, or `/execution-workspaces/:workspaceId` and its Services/Configuration/Runtime logs views.
@@ -83,46 +74,9 @@ or original Git remote. Read-only cross-project referenced folders must fail
admission. Separate workspaces may run concurrently; shared concurrent writers
must be rejected.
Repeat remote capture with enough free space for the archive and normalized Git
metadata, but not another working-tree copy. Verify saved files and Git state
after restore. A concurrent file change must fail capture without publishing a
receipt or retaining a partial archive. The
[portable archive suite](../../server/src/services/remote-workspace-snapshot-archive.test.ts)
checks the space allowance and concurrent-change boundary; its filesystem quota
is controlled test input, not a live sandbox qualification.
For Daytona, also fail the guarded file-download copy after a workspace archive
exists. Verify export preserves the complete archive, removes partial copies,
and succeeds again after reconnect. A failed or oversized stream must preserve
newer host files. The [capacity suite](../../packages/plugins/sandbox-providers/daytona/src/file-sync-capacity.test.ts)
uses real local copies and terminals; the adjacent opt-in live suite checks
disposable Daytona allocations without filling their disks.
Create a child that inherits a saved isolated workspace or operator branch.
Verify it continues the same files after the prior writer saves, including on a
new allocation. Two bound children must not acquire concurrent writer authority.
Start the child while its parent is still writing. Verify it waits with one
scheduled retry and retains its workspace binding without acquiring an allocation.
Stop the waiting task and verify that the retry cannot execute. A stale writer
or a stopped writer with unfinished saves must remain fenced.
Reassign the child during preparation before reservation reports contention;
retry promotion must cancel the former assignee's run without starting it.
The [reservation regression](../../server/src/services/remote-workspace-reservation.test.ts)
and [saved-file lifecycle suite](../../server/src/services/remote-workspaces.integration.test.ts)
exercise inheritance, access checks, and file continuity with real PostgreSQL.
Their filesystem transport is local test execution, not live sandbox/provider proof.
The Files panel must label **Live workspace** or **Saved copy** with its save
time. Confirm browse, preview, and download agree. A missing allocation with
unsaved work must report unavailability rather than show an old save as current.
After a final save clears dirty state and writer authority, Files must read the
current committed saved version even while the old allocation is still recorded
or its read transport is unavailable. Confirm the original bytes and Saved copy
label; a new writer or dirty state must retain the live-read requirement.
Clear the recorded allocation while a saved preview is loading: the pinned copy
must remain readable. Epoch, snapshot, source, writer, dirty-state, and foreign
or reintroduced location changes must still reject the read. Live reads keep
their physical-location fence, and all private saved copies must be removed.
Close must retain dirty/unfinished work and reject custom cleanup/teardown
commands; a clean saved workspace can release compute while retaining files.
Manual runtime commands, jobs, repairs, and service starts must reject remote
@@ -235,12 +189,9 @@ Manual: Provision a disposable workspace, wait for readiness, start an available
encryption key. Edits after the last save still depend on the sandbox; there
is no periodic workspace backup. The experiment does not remove the instance
volume or establish zero-outage deployment for other data paths.
- Terminal workspace cleanup wakes after committed task/workspace/PR/finalization changes and
restores cooldown deadlines at startup. Empty lanes stop scanning. Metadata reads
do not inspect storage. Providers without ancestry inspection use finalized HEAD
and destination-aware GitHub proof before storage checks. Associated squash PRs
need not be recorded manually; wrong HEAD/base, unreachable integration commits,
or unavailable credentials retain the workspace. Compatible records share one advisory Git
- Terminal workspace cleanup wakes after committed task/workspace/PR changes and
restores cooldown deadlines at startup. Empty lanes stop scanning. Metadata
reads do not inspect storage. Compatible records share one advisory Git
inspection per bounded page, while each record keeps its own delivery check.
Destructive cleanup starts a separate Git scan even if an older scan is running.
The [worker tests](../../server/src/__tests__/terminal-workspace-work.test.ts)
@@ -262,5 +213,4 @@ Capability ID: `workspaces/closure`.
Scope: ui
Storybook: Close-readiness checks, pending changes/active runs, blocked/pending/error close, retry close and eligible reopening.
Production: Confirm owned workspace shutdown, preserved files/Git state and permitted lifecycle transition/reopening; Browser Use session closure is unrelated.
Workspace detail and operation-history reads do not inspect Git or remote storage. Delivery is unknown until explicit close readiness or lifecycle inspection. Verify that these reads work during an inspection outage, while destructive close still refuses unverified data.
Sources: Source: [ExecutionWorkspaceDetail.tsx](../../ui/src/pages/ExecutionWorkspaceDetail.tsx), [ExecutionWorkspaceCloseDialog.tsx](../../ui/src/components/ExecutionWorkspaceCloseDialog.tsx), [execution-workspaces.ts](../../server/src/routes/execution-workspaces.ts). Tests: [execution-workspaces-routes.test.ts](../../server/src/__tests__/execution-workspaces-routes.test.ts), [execution-workspaces-service.test.ts](../../server/src/__tests__/execution-workspaces-service.test.ts), [execution-workspace-reopen.test.ts](../../server/src/__tests__/execution-workspace-reopen.test.ts)
+44
View File
@@ -0,0 +1,44 @@
---
description: Reserve feature-map additions for substantial new features and avoid incidental map updates.
globs: "maps/**"
alwaysApply: false
---
# Feature maps require substantial new features
Applies to changes under `maps/`, especially `maps/feature-map/` and its
same-named agent-access companions.
## Requirements
- Add a feature recipe, capability ID, sub-feature, entry point, or descriptive
expansion only for a substantial new user-facing feature: a distinct,
meaningful task that users could not previously perform and that an existing
capability does not already cover. A new workflow such as reusable scheduled
routines qualifies; an extra sort option in an existing task list does not.
- Leave maps unchanged for routine bug fixes, small behavior adjustments, UI or
copy polish, additional filters or settings within an existing capability,
refactors, performance work, logging, and test changes. Code changes alone do
not require a map update, regardless of how many files they touch.
- Do not append implementation details, edge-case narratives, regression notes,
test results, or PR summaries to existing recipes to document small updates.
Keep those in the relevant tests, technical docs, PR, or issue.
- Keep additions focused on the new feature and reuse existing capability IDs
when they already cover the work. Do not expand unrelated recipes or companion
files. When the feature threshold is unclear, leave the maps unchanged.
## Existing-entry corrections
Instructions to keep maps synchronized require a minimal correction only when an
existing entry would become materially inaccurate, such as a removed entry
point, changed access requirement, or obsolete user journey. Correct or remove
the affected text in place and preserve stable IDs; this does not justify new
capabilities or incidental detail. Explicitly requested map maintenance may fix
existing entries but must apply the same threshold to additions.
## Review
For every addition, identify the substantial new user capability and why an
existing entry cannot cover it. Reject additions for minor updates and unrelated
map edits. For corrections, check that the edit fixes a concrete inaccuracy and
stays limited to the affected entry.