mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-30 05:16:50 +01:00
## Thinking Path > - Paperclip manages AI agents and their work. > - Product E2E evals check real server, browser, runner, and provider behavior. > - Feedback persistence already checks saved complaints and suggestions with exact bodies and run attribution. > - Its catalog registers only local cells, so a Daytona campaign cannot select the same workflow. > - This PR registers the existing workflow for the two native Daytona profiles and tests their gateway bindings. > - Remote cells stay explicit-only and unqualified until a bounded live run passes. ## Linked Issues or Issue Description Refs #17980 and #17975. No duplicate open PR or issue was found in the Daytona feedback search. **What existing behavior does this improve?** The `feedback-persistence` Product E2E suite and its explicit execution selectors. **Current behavior** At master `d54f776ca0`, the suite has only local Claude and Codex cells. Selecting the matching Daytona ID fails before admission. The gateway manifest already supports these native remote profiles. **Proposed behavior** Register four cells: local and Daytona for each native profile. Reuse the existing saved-body and completed-tool oracle. Require an immutable image and Daytona credentials. Keep one attempt, one expected work run, five-minute local and inherited 15-minute remote case timeouts, and the existing 60-minute provider creation TTL. **Reason and benefit** A bounded remote qualification can check both a simple task and real feedback persistence. Local evidence remains separate from remote acceptance. **Breaking changes** Explicit `--suite feedback-persistence` now lists four cells instead of two. `--all` still excludes the suite. Daily and weekly manifests still select their existing exact local IDs. ## What Changed - Register the two native Daytona feedback cells and increment the suite definition version. - Address the remote cold-start review: inherit the base task's 15-minute Daytona deadline and retain the five-minute local limit. The regression failed before the fix and now passes. - Check immutable-image requirements, credentials, lifetime, and shared gateway connections in existing contract tests. - Fix the config type in the TTL catalog test added by #17980. Keep its runtime lifetime assertions. - Document remote selection and its unqualified status in the existing eval guides. ## Verification - Before the catalog change, the registration regression failed: one failed and 16 passed. - Focused catalog, feedback, operations, ledger, manifest, and summary tests: 114 passed across six files. - Read-only discovery lists exactly the two Daytona feedback IDs. - The Node test phase passes separately: 137 tests. The retained Vitest database failure prevents the unit launcher from reaching that phase. - Full Product support suite: 4,523 passed, three skipped, and one embedded PostgreSQL bootstrap failure. The same database failure was reproduced on a clean baseline before this PR. - Fresh Linux Product typecheck passed at the review-fix commit: `GOMEMLIMIT=2GiB GOGC=50 GOMAXPROCS=2 node node_modules/typescript/bin/tsc -p tests/runner-e2e/tsconfig.json`. The default run and the ineffective JavaScript-heap attempt exited 137 and remain retained. The compiler launches a native child process; its memory controls let the unchanged semantic check complete. Host typecheck still has 15 stale installed DB/Runner export errors; the two TTL test typing errors are fixed. All 58 latest-head checks are acceptable (success, neutral, or skipped). Both fresh reviews are 5/5, with no unresolved review threads. - The updated credential-free Linux controller discovers both planned remote IDs and launches Chromium 151.0.7922.34. Runtime build inputs are unchanged from the prior controller. The Daytona image content ID is still `b55f03dc9c633db300b70206a691ff45a8e779e56a3c546f9358e3282d3597c9`. - No model requests, sandbox allocation, or paid schedule changes. ## Risks - Selecting the whole explicit suite now includes remote cells and requires Daytona configuration. Use exact IDs for a bounded paid campaign. - Registration and contract tests do not prove live remote behavior or token accounting. Remote qualification remains pending. - The shared dependency checkout limits the local host typecheck. The fresh Linux semantic check passed. Earlier compiler OOM failures and the database bootstrap failure remain retained. ## Model Used - OpenAI GPT-6 through Codex, with tool use and code execution. The exact serving model ID and context window are not exposed in this session. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
253 lines
16 KiB
Markdown
253 lines
16 KiB
Markdown
# Eval coverage and operating costs
|
|
|
|
Use this with [OPERATIONS.md](OPERATIONS.md). The bounded daily and weekly
|
|
selections cover Product E2E only. They do not authorize or cap the separate
|
|
Runner protocol workflow, manual matrix runs, or other live probes.
|
|
|
|
## Initial cadence
|
|
|
|
The runner E2E maintainers own these selections and their failure triage.
|
|
Both profiles use the exact model and limits in the reviewed pricecard.
|
|
|
|
| Journey | Failure detected | Feature-map association | Cadence |
|
|
| --- | --- | --- | --- |
|
|
| Native Claude message marker | A real task cannot complete and persist its expected answer through the metered route | `runs-adapters/runs` | Daily and weekly |
|
|
| Native Claude complaint and suggestion | Completed tools fail to save attributed feedback or collection loses it | `activity/agent-commentary` | Daily and weekly |
|
|
| Native Codex message marker | The corresponding Codex task/connection path fails | `runs-adapters/runs` | Weekly |
|
|
| Native Codex complaint and suggestion | The corresponding Codex feedback/tool path fails | `activity/agent-commentary` | Weekly |
|
|
|
|
These associations identify partial coverage. They do not qualify every run
|
|
lifecycle, the Commentary browser page, continuation, or remote execution.
|
|
The October 27 qualifications measured one successful attempt per selected cell:
|
|
$0.428650100 and 107.286 summed attempt seconds for the daily selection,
|
|
$0.793676500 and 158.093 seconds for the weekly selection. Claude ran on
|
|
GitHub-hosted Ubuntu; Codex ran in a local Linux ARM64 container. These are
|
|
historical gateway estimates from 19 final model request receipts. They include
|
|
setup, background and disconnected-client requests with terminal usage. Attempt
|
|
time includes setup and teardown, but omits workflow queue/build time and
|
|
non-model charges. Provider exports match usage and charges (Claude at one-cent
|
|
export precision); final monthly invoices remain pending. The hosted workflow
|
|
failed during report dependency setup after both cases passed. Its original
|
|
failure, and all earlier failed or interrupted attempts, remain retained.
|
|
|
|
`scheduled-measurements.json` retains each attempt, source revision, definition,
|
|
model, price version, measurement host, final request count, result hash and
|
|
journal hashes. `forecast.json` includes that evidence and a snapshot hash.
|
|
Historical totals remain separate from samples matching the current definition,
|
|
model, environment, runtime, route and pricing. Hosts form separate cohorts;
|
|
measurements from different hosts are not pooled into one cell distribution.
|
|
The feedback definition's source fingerprint changed after these samples, so
|
|
current compatible selection totals remain unknown. No historical hash is
|
|
rewritten to match the new definition.
|
|
|
|
`historicalHostedSelection` records the measured hosted subset only when every
|
|
selected cell has hosted evidence. Current `hostedModelUsd` and
|
|
`hostedAttemptMs` additionally require matching definitions. The four-case
|
|
weekly selection has no complete hosted measurement yet. Summed attempt time
|
|
is neither campaign wall time nor billed infrastructure time.
|
|
|
|
Per-cell mean and median are descriptive. P95 stays unknown below 20 samples
|
|
and then uses nearest rank; this is not a statistical confidence guarantee.
|
|
Do not sum per-cell percentiles into a campaign percentile. A passing sample
|
|
does not predict failure frequency or account for infrastructure, storage,
|
|
observability or subscriptions. Forecasts never reduce reservations, approved
|
|
budget limits, or qualification gates.
|
|
|
|
At the October 21, 2026 catalog audit, 47 suites declared 738 cells. `--all`
|
|
included 179; the other 559 required explicit selection. The bounded weekly
|
|
selection included four cells, and daily two. These are dated inventory counts,
|
|
not live acceptance results or an enduring catalog-size contract. Inspect the
|
|
current `pnpm test:e2e:runner -- --list` before choosing work. In particular,
|
|
Everyday Workflows, provider connections, feedback persistence, interruption,
|
|
and case handoffs must not be inferred from a passing `--all` campaign.
|
|
|
|
The explicit feedback suite also registers native Claude/Codex cells on Daytona.
|
|
Their model usage, duration, feedback persistence and cleanup remain unqualified
|
|
until retained live attempts prove them. These cells do not enter the daily or
|
|
weekly selections, and `--all` continues to exclude the suite.
|
|
|
|
Keep the broader rotating lane disabled until its exact cells have a metered
|
|
route, complete retained attempts, a measured cost/time distribution, and a
|
|
budget that includes failures. Prefer targeted continuation, approval, and
|
|
cleanup cases that detect different failures over another model running the
|
|
same marker. A release lane may broaden coverage only with its own reviewed
|
|
manifest; the daily/weekly allowance does not authorize it.
|
|
|
|
## Adding an eval or changing its cadence
|
|
|
|
The change's fixture documentation and PR must declare:
|
|
|
|
- A responsible maintainer/team and the concrete failure the case detects.
|
|
- Feature-map capability IDs, or an explicit unmapped gap. State what the
|
|
journey does not exercise within a broader capability.
|
|
- Exact suite, case, profiles, models, environment, and intended cadence.
|
|
State whether it is explicit-only and how it differs from existing coverage.
|
|
- A deterministic alternative considered, and why paid behavior is necessary.
|
|
- Attempt, request, output-token, concurrency, retry, and wall-time limits.
|
|
Include setup, judges, child/background work, and cleanup in the route audit.
|
|
- Estimated cost/time before the first run, then all-attempt measurements with
|
|
sample count, retained failures, source/definition IDs, and uncertainty.
|
|
An unmeasured field is unknown, never zero.
|
|
- Feedback collection/review, trace verification, missing-receipt handling,
|
|
and a failure/cleanup owner. Novel complaints are reviewed independently
|
|
of the product grade.
|
|
|
|
Use the existing [Product E2E authoring skill](../../.agents/skills/add-product-e2e-eval/SKILL.md)
|
|
or the separate [Runner authoring skill](../../.agents/skills/add-runner-eval/SKILL.md).
|
|
Update the existing scheduled selection and forecast only after qualification;
|
|
adding a catalog entry alone must not enable recurring spending.
|
|
|
|
## Reading campaign time
|
|
|
|
The report's summed attempt time uses every retained accounting receipt,
|
|
including failed retries. A missing attempt makes the total unknown; the report
|
|
keeps the observed subtotal and missing count. The observed attempt window runs
|
|
from the earliest retained start to the latest retained finish. Parallel attempts
|
|
overlap in that window, while their individual durations add to the sum. Gaps
|
|
between attempts remain in the window. Carried-forward evidence can span older
|
|
runs, so this window is not the current workflow's duration.
|
|
|
|
Agent execution and Daytona lease time remain separate measurements. Attempt
|
|
durations include the setup and cleanup inside their recorded boundaries.
|
|
New browser-worker results retain a separate phase receipt for fixture setup,
|
|
execution, feedback capture, cleanup and worker finalization. Repeated cleanup
|
|
segments add together. Atomic checkpoints preserve completed phases if the
|
|
worker is interrupted; the active phase has no inferred end time. Parent
|
|
recovery checks identity, interval bounds and file size before retaining that
|
|
partial receipt. Missing, malformed or unavailable receipts keep phase totals
|
|
unknown, while closed segments remain visible as observed subtotals.
|
|
|
|
These phases start inside the test callback, after browser/server startup, and
|
|
end before result publication. Parent teardown/finalization, CI queue/build time
|
|
and provider-billed runtime need their own receipts. Historical results and
|
|
non-browser launchers without a worker receipt remain explicitly unmeasured.
|
|
Test details show each selected attempt's receipt status and raw timing metadata.
|
|
Do not infer missing measurements by subtracting summed agent time from the
|
|
observed window. Refreshing a report computes these views from retained
|
|
results without making provider calls or changing the original measurements.
|
|
|
|
## Costs outside the model journal
|
|
|
|
Keep a separate cost component for each resource, with its currency, service,
|
|
resource/request identity, source window, allocation basis, and status. Join
|
|
components to campaign/attempt IDs where evidence permits. Do not sum a model
|
|
estimate with the invoice that later reconciles that same usage.
|
|
|
|
| Component | Evidence and allocation | When evidence is missing |
|
|
| --- | --- | --- |
|
|
| Provider models and paid tools | Dedicated project/key usage and billing exports; match provider request IDs or the narrowest available billing window | Preserve estimates, unknown requests, held reservations and the reconciliation difference |
|
|
| Daytona | Owned sandbox ID, actual resources, billable lifecycle and provider receipt; include failed creates, retries, stopped storage and delayed deletion | Retain the reservation or an explicitly partial estimate; a requested TTL does not prove deletion |
|
|
| CI compute | Workflow/job IDs, runner type, actual billed runtime and invoice rates; include setup, builds and failed jobs | Mark CI cost unknown; a short agent turn does not imply a cheap CI job |
|
|
| Storage and transfer | Artifact size, retention window and billed storage/egress | Report the unpriced component, including retained failure evidence |
|
|
| Braintrust/gateway usage | Project usage export and its window; distinguish included allowance from incremental overage | Do not treat free-looking trace metrics as proof of zero provider charges |
|
|
| Shared subscriptions | Show the existing Braintrust Pro $249/month separately under the October 21 operator policy; allocate newly incurred subscription/capacity charges from invoices with an explicit denominator | Keep new shared charges unallocated rather than assign an invented exact per-test cost |
|
|
|
|
Retain both the service total and the allocation denominator so allocated
|
|
amounts can be reproduced. A zero incremental usage charge can coexist with a
|
|
nonzero shared subscription. Never add the entire subscription to every test.
|
|
The approved daily/weekly budgets cover additional run costs, so they exclude
|
|
the existing $249/month fee while including new usage and capacity charges.
|
|
Scheduled admission now reserves the declared CI, storage, observability and
|
|
subscription allowances inside the same $20/$100 journal limit. Missing or stale
|
|
allowances stop scheduling before the AWS test runner starts. Missing receipts
|
|
keep their reservations held. Explicit reviewed full-lifecycle bounds may allow
|
|
provisional completion while billing remains pending; missing bounds, conflicts
|
|
and overspending still fail. Legacy reservations gain no qualification from the
|
|
policy change. This is a local admission
|
|
control, not a provider billing cap. Actual resource bounds, cost collection and
|
|
reviewed allowances still need qualification before recurrence is enabled; see
|
|
[the allowance contract](OPERATIONS.md#recurring-campaigns).
|
|
|
|
Recurring evidence and reports use private S3 archives with file/byte/request
|
|
boundaries, retained transfer receipts and verified access/expiration rules;
|
|
see [private recurring history](OPERATIONS.md#private-recurring-history). The
|
|
public workflow retains only a content-free availability marker for monitoring.
|
|
Public history is a separate explicit publication step. Private retention still
|
|
needs hosted OIDC qualification and actual storage/transfer billing evidence;
|
|
local archive tests and an infrastructure template do not establish those facts.
|
|
|
|
## Separate Runner Eval audit
|
|
|
|
The October 21 audit inspected Paperclip source on master `8b873e0112` plus the
|
|
eval operations stack, and the available `paperclip-evals` checkout at
|
|
`0bae4e0947dc7959cae25b73d27533c096f23a14`. This is a source audit, not a
|
|
new live run or proof of the workflow's configured private-repository revision.
|
|
|
|
Runner reports already retain immutable attempts, retry-inclusive estimated
|
|
cost and provider list cost as separate views, compatible-cohort comparisons,
|
|
and missing-usage coverage. Its mock control plane is a different authority
|
|
from the Product E2E server/database; Product feedback persistence cannot be
|
|
claimed from a Runner tool assertion.
|
|
|
|
The private `run_live_campaign.py` requires an explicit authorization envelope.
|
|
The hosted `runner-protocol-live-evals.yml` instead fans out individual
|
|
`run_live_roster.py` cells, supplies their direct provider credentials, and uses
|
|
configured per-attempt limits. It does not use the Product E2E shared gateway
|
|
journal, Braintrust attempt parent, indexing verifier, or feedback finalizer.
|
|
The private campaign wrapper's aggregate authorization must not be assumed to
|
|
protect that different hosted path.
|
|
|
|
Before adding Runner recurrence, its owners must establish an aggregate
|
|
allowance across fanout and retries, meter setup/provider bypasses, and qualify
|
|
native tracing through its actual packaged runner. Preserve direct-provider
|
|
qualification as its own route. Implement definition/roster changes in the
|
|
maintained private repository, pin that reviewed revision in the existing
|
|
workflow, and retain Runner's existing Evalbook renderer and scores. These
|
|
gaps remain open; Product E2E qualification does not close them.
|
|
|
|
## Missing campaign detection
|
|
|
|
Workflow failure notifications cover runs that start. The independent observer
|
|
is `scripts/eval-schedule-monitor.mjs`. Run it through a separate host with an
|
|
authenticated GitHub CLI and one private state file:
|
|
|
|
```sh
|
|
node scripts/eval-schedule-monitor.mjs "$HOME/.config/paperclip-evals/schedule-monitor.json"
|
|
```
|
|
|
|
The observer uses only GitHub GET requests. It never starts or retries paid
|
|
work and does not need provider credentials. It reads the two existing enable
|
|
gates plus `RUNNER_FULL_STACK_E2E_OPERATIONS_ENABLED_AT`, an ISO timestamp set
|
|
when recurrence is enabled. Missing activation time fails visibly; occurrences
|
|
before activation are not treated as missed. Workflow run titles carry the
|
|
literal cron expression to distinguish daily and weekly runs, including Sunday.
|
|
|
|
Only the legacy `RUNNER_FULL_STACK_E2E_NIGHTLY_ENABLED` gate being off establishes
|
|
disabled recurrence. If that gate is on while the operations gate is absent or
|
|
off, the observer reports `configuration_incomplete` and retains one incident
|
|
notification. Older deployed workflows use only the legacy gate, so a missing
|
|
new gate must not imply that those paid schedules are disabled. Verify the
|
|
deployed default-branch workflow and both variables before enabling recurrence.
|
|
|
|
The observer allows 90 minutes for schedule delay. It checks the most recent due
|
|
occurrence per cadence, marks a run overdue after four hours, and requires a
|
|
successful terminal run plus a nonempty, unexpired merged-report artifact.
|
|
The workflow's finalizer remains responsible for checking report content and
|
|
accounting. Metadata inspection does not repeat that validation. Unexpected
|
|
reruns, ambiguous matching runs, incomplete API lists and API failures remain
|
|
visible. The observer reads at most 100 rows per collection and fails closed
|
|
if a response is truncated.
|
|
|
|
Retained state includes the last successful inspection and inspected run IDs.
|
|
`notifications` is a durable outbox of problems and recovery transitions. Each
|
|
entry has an ID. After confirmed delivery, the host acknowledges those IDs:
|
|
|
|
```sh
|
|
node scripts/eval-schedule-monitor.mjs "$HOME/.config/paperclip-evals/schedule-monitor.json" --ack <notification-id> ...
|
|
```
|
|
|
|
Until acknowledgment, later inspections return the same pending entries even
|
|
if the problem has recovered. The host uses IDs to deduplicate delivery. This
|
|
survives a process exit between saving state and printing output; it does not
|
|
claim exactly-once delivery across an external notification service. After
|
|
acknowledgment, an unchanged problem stays quiet. A new missed occurrence is a
|
|
new incident. Disabled recurrence and unchanged healthy runs create no new
|
|
alerts. Use one writer for both checks and acknowledgments; do not reset the
|
|
state file to clear an incident. Malformed history fails before a query or
|
|
write. The external host owns notification delivery and its own liveness.
|
|
|
|
Schedule this observer outside the paid workflow after source and recurrence
|
|
are ready. It should inspect at least daily, after both scheduled start times
|
|
and their grace windows. Until that external trigger and notification delivery
|
|
are configured and exercised, missed-run detection remains an activation gap.
|